# Generating a table of glyphs with XeTeX

I am trying to get XeTeX to generate a table of all the possible glyphs of a given font, but can not figure out how to make XeTeX know how many glyphs the font has, so I have to specify an exact number.

This is what I have got so far:

\documentclass[border=0.5cm,10pt,landscape]{standalone}
\usepackage{geometry}
\usepackage{xunicode, xltxtra}
\usepackage{fontspec}
\usepackage{multicol}
\setmainfont[Mapping=tex-text, Ligatures={Historical}, Alternate=0]{Linux Libertine O}
\setlength{\columnsep}{0.3cm}
\setlength{\columnseprule}{1pt}
\begin{document}

\begin{multicols}{10}
\newcount\charcount
\charcount=0
\loop
\number\charcount \hspace{1ex} \XeTeXglyph\charcount
\par
\ifnum\charcount<2500
\repeat
\end{multicols}

\end{document}


Fig. 1: Example of the output.

How can it automatically know the exact number of accessible glyphs?

Bonus: Is anyone willing to waste his time by making it put everything inside a table with 10 columns? :-) It also reports an error probably caused by multicol which a I could not fix yet.

-
This might be easier to do with LuaTeX. –  Caramdir Jul 22 '11 at 22:59
@Caramdir: It won't be more difficult to do with XeTeX. –  Leo Liu Jul 23 '11 at 4:28

1. Use \iffontchar\font number ... \fi to test if a glyph is in the font.

2. multicol is OK for me. Set \parindent to 0pt to get proper result.

Here is a neat example:

...

\documentclass[landscape]{article}
\usepackage{geometry}
\usepackage{fontspec}
\setmainfont{Linux Libertine O}
\usepackage{multicol}
\setlength{\columnseprule}{0.4pt}
\usepackage{multido}
\setlength{\parindent}{0pt}
\begin{document}

\begin{multicols}{10}
\multido{\i=0+1}{"10000}{% from U+0000 to U+FFFF
\iffontchar\font\i
\makebox[3em][l]{\i}%
\symbol{\i}\endgraf
\fi
}
\end{multicols}

\end{document}


Note: I tried my best to keep the code simple. But there're still two unusual points: I use \iffontchar to test the font characters, and use \endgraf instead of \par to cheat \multido.

-
It works very well, but I had to reduce the number to 9999. Egreg mentioned that the last glyph of Linux Libertine O produces an error and this was probably the same case. Thank you! All three answers are very useful to me, but I am going to accept this one as it uses XeTeX and multicol. –  Harold Cavendish Jul 23 '11 at 10:03

I know that you are asking for a solution with XeTeX (and egreg already gave one), but here is a LuaTeX solution:

\documentclass[10pt,landscape]{article}
\usepackage{luacode}
\usepackage[margin=0.5cm]{geometry}
\usepackage{fontspec}
\usepackage{multicol}
\setlength{\columnsep}{0.3cm}
\setlength{\columnseprule}{1pt}

\newfontface\thefont{Linux Libertine O}

\begin{document}
\section*{Linux Libertine O}
\begin{multicols}{7}\noindent
\begin{luacode*}

local glyphs = {}
for i = 0, f.glyphmax - 1 do
local g = f.glyphs[i]
if g then
table.insert(glyphs, {name = g.name, unicode = g.unicode})
end
end

table.sort(glyphs, function (a,b) return (a.unicode < b.unicode) end)

for i = 1, #glyphs do
tex.sprint(glyphs[i].unicode .. ': ')
if (glyphs[i].unicode > 0) then
tex.sprint('{\\thefont\\char' .. glyphs[i].unicode .. '}');
end
tex.sprint(' {\\tiny (')
tex.sprint(-2, glyphs[i].name)
tex.sprint(')}\\\\')
end

\end{luacode*}
\end{multicols}
\end{document}


-
You can simplify your loops, instead of i=1 while i<foo do i = i+1 end use for i=1, foo do end –  Khaled Hosny Jul 23 '11 at 3:02
You also don't need to re-load the font in lua, you can access the table of the current font using fonts.identifiers[font.current()]. –  Khaled Hosny Jul 23 '11 at 3:09
@Khaled: True. I based that on some code in the LuaTeX manual, which had those loops. I'll change the code. That second comment looks useful. However, since the main font is LM (so that one can also list, e.g., dingbat fonts), this won't work. –  Caramdir Jul 23 '11 at 4:06
Thank you, it is a motivation to learn Lua. I do not understand some parts of it yet. –  Harold Cavendish Jul 23 '11 at 10:07
You can do something like \font\foo={name:Linux Libertine O} and in lua f = fonts.identifiers[font.id("foo")] so you don't need to locate the font manually. –  Khaled Hosny Jul 23 '11 at 18:08
\documentclass{article}
\usepackage[a4paper,landscape,textwidth=239mm,textheight=480pt]{geometry}
\usepackage{fontspec}
\setmainfont{Linux Libertine O}
\newcount\charcount
\parindent=0pt
\begin{document}

\chardef\highest=\XeTeXcountglyphs\font
\offinterlineskip
\loop
\makebox[15mm][l]{\strut\vrule\,\number\charcount\hfill \XeTeXglyph\charcount}\hskip1mm plus 1mm
\ifnum\charcount<\numexpr\highest-1\relax
\repeat

\end{document}


With Linux Libertine the last glyph produces an error, that's the reason of the strange limitation. This does not happen with other fonts.

If one wants a table with the actual codes for the characters, a slower routine must be used:

\documentclass{article}
\usepackage[a4paper,landscape,textwidth=239mm,textheight=480pt]{geometry}
\usepackage{fontspec}
\setmainfont{Old Standard}
\newcount\charcount
\parindent=0pt
\begin{document}

\offinterlineskip
\def\dochar{\iffontchar\font\charcount
\makebox[15mm][l]{\strut\vrule\,{\tiny\number\charcount}\hfill\char\charcount}\hskip1mm plus 1mm
\fi}
\loop\dochar
\ifnum\charcount<"10FFFF\relax

The range is wrong. \XeTeXcountglyphs\font returns the number of glyphs in current font, but not the highest glyph code in current font. In Linux Libertine, there are 2575 (\XeTeXcountglyphs\font) glyphs, but U+FFFD (\symbol{65533}) is the last symbol. –  Leo Liu Jul 23 '11 at 4:57
@LeoLiu, if you use \XeTeXcountglyphs\font together with \XeTeXglyph it works perfectly fine and prints all glyphs. based on your previously posted code: \begin{multicols}{10} \multido{\i=0+1}{\XeTeXcountglyphs\font}{% from U+0000 to U+FFFF \makebox[3em][l]{\i}% \XeTeXglyph\i\endgraf } –  Paul Feb 13 at 22:32