Detect if all required glyphs are available

In XeTeX, a message is printed to the log file if a glyph is not available with the current font. The input

\documentclass{scrartcl}

\begin{document}
α
\end{document}


leads to the following entry in the log:

Missing character: There is no α in font cmr10!


Is there a way to check for a given input if all glyphs required to render it are available, without relying on the log file? Apparently, there is no Command to flush log file, and (in a scenario where I pipe into a running XeLaTeX process) I'd like to know before XeTeX is terminated.

• No, it's not possible; typesetting a character happens at a very deep stage in processing, when there's no user's control any more. I guess something can be done with LuaTeX, but not with XeTeX, that only provides \iffontchar\font<charcode> to check if the <charcode> corresponds to an existing glyph in the current font. – egreg Mar 15 '14 at 12:28
• @egreg: Thanks. Can XeTeX be told to treat this condition as an error, so that the process would abort when -halt-on-error is given on the command line? – krlmlr Mar 15 '14 at 13:15
• No, this is not possible; but you'd have to look at the log file anyway, wouldn't you? – egreg Mar 15 '14 at 14:17
• @egreg: It seems that I can only reliably parse the log file after XeTeX has terminated. Remember that I intend to keep XeTeX open and feed it via its stdin. See github.com/yihui/tikzDevice/issues/5 for some more detail, I'd be glad for any input. – krlmlr Mar 15 '14 at 14:37
• I think you're doomed, sorry. :( – egreg Mar 15 '14 at 14:41

Longer post

This task was a big issue for me many years ago when I was typesetting and generating preview books of fonts where I needed to know all kind information about the glyphs before actual typesetting. I divided the answer into three small parts each with compilable TeX file.

Part 1: xelatex and its tool

There is a way in xelatex, it is mentioned indirectly on page 8 in the reference manual. We can use the \XeTeXcharglyph command and check if the output is 0 (or .notdef if checking glyph name). Once any glyph is not defined the zero value is assigned to the character slot.

After that step we can use \ifnum...\else...\fi statement to decide what to typeset, if anything at all. In the example I am testing four letters, ? A \ a, two are defined, the remaining two are not. I have downloaded and installed RodgauApesInitials from Manfred Klein's collection, http://moorstation.org/typoasis/designers/klein04/deco/rodgau_apes.htm

We run xelatex mal-kanji1.tex and terminal says:

The glyph slot of 003F(hex) is: 0 (.notdef)
The glyph slot of 0041(hex) is: 3 (A)
The glyph slot of 005C(hex) is: 0 (.notdef)
The glyph slot of 0061(hex) is: 29 (a)


This is the code:

% run: xelatex mal-kanji1.tex
\documentclass[a4paper]{article}
\pagestyle{empty}
\usepackage{xltxtra}
\usepackage{fontspec}
\usepackage{pgffor}
\begin{document}
%\font\malfont=RodGauApes.ttf
\font\klein="RodGauApes Initials"
\font\cmr=cmr10%
\message{^^J}% One \n to the terminal...
% U+0041, A, dec 65
\def\checkme#1{%
\klein\message{The glyph slot of #1(hex) is: \the\XeTeXcharglyph"#1 \space
(\XeTeXglyphname\klein\XeTeXcharglyph"#1)^^J}%
%! Cannot use \XeTeXcharglyph with cmr10; not a native platform font.
\ifnum\XeTeXcharglyph"#1=0%
\cmr Undefined glyph!%
\else
\klein\char"#1%
\fi% End of \ifnum...
}% End of \checkme...
\foreach \malglyph in {003F,0041,005C,0061}% ? A \ a
{\checkme\malglyph\cmr\par%
}% End of \foreach...
\end{document}


I needed and I used this strategy when I typesetted a preview book of kanji. I was using many different font faces and I needed to know exactly how many glyphs were going to be typeset. If a glyph or more were missing it was up to me to decide if to typeset that rectangle, or not. I should say that it is normal that a font is missing some CJKV characters, there are so many of them. I enclose a snapshot from the book, it is a preview of a single Japanese character/kanji.

The big disadvantage is that we can use this strategy only with the xelatex format and we can check only newer fonts (TTF, OTF), it is not working with PFB. That's a serious limitation in work. Let me show you other approach.

Part 2: testfont.tex

One of tools in the TeX distribution is testfont.tex file. If we run, e.g.:

pdftex testfont.tex


We are asked about the name of the font, let's use dmjhira and hit Enter. There is a list of options when we use \help and hit Enter. The common option is to write \table\bye followed by Enter. We are getting the testfont.pdf file and this is a preview of it.

A problem is that we cannot customize it and we cannot enter TTF and OTF fonts without installing and setting up the fonts. It is worth checking another approach.

Part 3: Measuring a TeX box (Hiragana and Katakana as test cases)

The core of TeX is in measuring boxes. It is the approach we are going to use and test. We will test a single glyph, but we could easily measure almost anything. After defining a new box (\newbox), we virtually fulfill the box (\setbox) and we can measure width, height and depth of the box (\wd, \ht and \dp).

In the example below we typeset Hiragana, a Japanese syllabary, but we may spot several defects. There is an opening space, lines don't break ideally, spaces are shrinking and stretching, we have no idea how many glyphs were typesetted. But it is a starting point for further explorations.

Worth mentioning is that we can run any major latex engine and if we use e.g. fontspec package, we can test glyphs in the TTF, OTF and some dfont files when running lualatex or xelatex. I enclose the TeX code and a preview of the result.

% run: *latex mal-kanji2.tex
\documentclass[a4paper]{article}
\rightskip=6cm% And TeXie, :-), please narrow the text width somehow...
\begin{document}
\font\hira=dmjhira at 2ex% Setting up a new font face (Hiragana)...
\newcount\malcounter% Setting up a new counter...
\malcounter=-1% The initialization of the counter
\loop% The core of this example...
\advance\malcounter by 1% Move on to the next glyph...
{\hira\char\malcounter} % Show me the glyph, add space...
%\discretionary{}{}{}% Allow a page break after the glyph... (the first alternative)
\allowbreak% (the second alternative)
\ifnum\malcounter<255\repeat% Run all 256 characters in the font...
\end{document}


We typeset a glyph only when glyph width is a nonzero value. There are some exceptions in ornament fonts, but it is considered bad fontography. We add a counter (\newcount) taking care of a number of typesetted glyphs, we limit spaces to fixed dimension (\fontdimen 3, 4 and 7), we allow line breaks, simply said we are having full control over the output now.

I enclose an example and a preview of the PDF file with Katakana, a Japanase syllabary.

% run: *latex mal-kanji3.tex
\documentclass[a4paper]{article}
\pagestyle{empty}
\parindent=0pt
\begin{document}
\newbox\emptybox
\setbox\emptybox=\hbox{}
\newbox\malbox
\font\kata=dmjkata% A new font face to be used (Katakana)...
\newcount\counter
\counter=-1% The counter of glyphs...
\fontdimen3\font=0pt \fontdimen4\font=0pt \fontdimen7\font=0pt
% Eliminate the stretch in spaces, or, we could use \makebox...
\loop% Process all the glyphs...
\advance\counter by 1% Go to the next glyph...
\setbox\malbox=\hbox{\kata\char\counter}% Measure the glyph...
\ifnum\wd\malbox=\wd\emptybox\relax\else% Is width 0pt? Height is not tested (\ht, \dp)...
\texttt{\ifnum\counter<10 0\fi% Add zero in front of number <10...
\the\counter.\copy\malbox\ }% Show me the glyph...
\discretionary{}{}{}%Allow the line break, or, \allowbreak...
\fi% End of \ifnum condition...
\ifnum\counter<255\repeat% Show me all the glyphs in range 0-255...
\end{document}


Conclusions

There are some limitations of these methods. We cannot test if two glyphs are not just rotated, flipped or scaled, we are also not listing glyphs outside 0-255 region. In case you need something like that, use FontForge, it can be done there as it has own scripting language and a support for Python scripts.

In case you are wondering what was that splash in the very first example in the last letter under the letter: Oh, yes, that's an ape from the great Manfred Klein legendary font creator himself! I enclose a screenshot from FontForge and a preview of his font with 26+26 letters in it.

As an extension of Malipivo's excellent answer, I wanted to mention that you can also use \iffontchar as shown in the following example. Note that LuaLaTeX gives different results from XeLaTeX here -- it looks like XeLaTeX doesn't like glyphs in the very upper ranges of Unicode here (above U+F0000 perhaps).

The code should be fairly evident, but the idea is that you call

\fontrange {xits-math.otf} {1} {"FFFFF} { \texttt{\small #2}:\quad #3\par}


where the first argument is the fontspec font, the second is the starting glyph point, the second is the ending glyph point, and the fourth argument defines how the result is typeset (#2 is the hex code of the glyph and #3 is the character corresponding to the glyph itself).

\documentclass[a4paper]{article}
\usepackage{fontspec,multicol}
\usepackage[margin=2cm]{geometry}
\begin{document}

\ExplSyntaxOn
\DeclareDocumentCommand \fontrange { m m m +m }
{
\group_begin:
\cs_set:Npn \__typeset:nnn ##1 ##2 ##3 {#4}
\fontspec{#1}
\int_step_inline:nnnn {#2} {1} {#3}
{
\iffontchar\font ##1\relax
\__typeset:nnn {##1} { \int_to_Hex:n {##1} } { \char ##1 \relax }
\fi
}
\group_end:
}
\ExplSyntaxOff

\begin{multicols}{5}
\fontrange{xits-math.otf}{1}{"FFFFF}

• I'm not sure this fits into fontspec; it seems more like fonttable. – egreg May 27 '14 at 6:35
• @egreg I agree to some extent — but all I'd be providing in fontspec would be something like that \fontrange command and it'd be up to whomever to do something useful with it. Making it flexible would probably be difficult, though; so perhaps not. – Will Robertson May 28 '14 at 2:38