20

I wanted to create a table of the fonts on my machine with short examples of each. So I got the function below and tried to modify to print the font in its typeface. (LuaLatex)

\documentclass[10pt,a4paper]{article}
\usepackage{fontspec}
\usepackage{luacode,luaotfload,luatextra}
\usepackage[margin=18mm]{geometry}

\begin{document}
\begin{luacode}
myfonts=dofile(fonts.names.path.localdir..'/otfl-names.lua')
--tex.print('\\begin{verbatim}\\par')
for i,v in ipairs(myfonts.mappings) do
  --tex.print('\\fontspec{' .. v.fontname .. '}')   % most recent attempt
  --tex.print('\\setmainfont{' .. v.fontname .. '}') % first attempt
tex.print(v.familyname..', '..v.fontname..'\\par')
end
--tex.print('\\end{verbatim}\\par')
\end{luacode}

\end{document}

Both of the commented lines does not work (fontspec or setmainfont).

How should go about doing this with lua?

Louis
  • 1,471

3 Answers3

21

This improves Caramdir's answer to make the table easier to read:

\documentclass{article}

\usepackage{fontspec}
\setmainfont{Latin Modern Mono Light}

\usepackage{luacode}

\usepackage[margin=18mm]{geometry}
\parindent=0pt

\usepackage{longtable,makecell}
\renewcommand\arraystretch{2}

\begin{document}
\begin{luacode}
myfonts=dofile(fonts.names.path.localdir..'/otfl-names.lua') -- TeX Live 2012 or earlier
-- myfonts=dofile(fonts.names.path.path) -- TeX Live 2013
teststring = "Sphinx of black quartz, judge my vow."

tex.print("\\begin{longtable}{ll}\\hline")

for i,v in ipairs(myfonts.mappings) do
  -- Stop early for testing purposes.
  if i > 20 then break end

  tex.print('\\makecell[l]{\\bfseries')
  tex.print(-2, v.familyname)
  tex.print('\\\\[-1ex] \\scriptsize')
  tex.print(-2, v.fontname)
  tex.print('} & \\LARGE\\fontspec{' .. v.fontname .. '}')
  tex.print(-2, teststring)
  tex.print('\\\\ \\hline')
end
tex.print("\\end{longtable}")
\end{luacode}

\end{document}

enter image description here

Leo Liu
  • 77,365
  • TNX. This is exactly what I intended. I will just add some numbers. Some fonts make 1,L and l nearly the same and that I don't like. – Louis Jul 21 '11 at 07:28
  • @Caramdir: I will maybe also only print one example per font family to same time and just get a view of the family. – Louis Jul 21 '11 at 07:29
  • @Leo Liu: I'd like to sort the mappings array for the fontname, but failed. I suppose that I had to write first the fontnames into an array and sort this one. Right? –  Jul 21 '11 at 09:42
  • 1
    I have a question about this solution. Say I want to produce such a table for the entire Adobe Font Folio 11 library. There are about 2000 fonts there (only counting western language fonts). And LuaTeX eventually run out of memory (in my case, it stops at about 1500 fonts, using more than 24GB memory, that's all I get). Is there anyway to free the memory used by fonts somewhere during the process. After all each fonts are used only for a short period. Let's say I don't really need them to be tables, just print then one fonts per page, like a specimen. – Yan Zhou Aug 25 '11 at 09:34
  • 1
    @Yan Zhou: You can write a script to produce many small separate test document. And then use pdftk or other tools to make a big one. – Leo Liu Aug 29 '11 at 08:00
  • 1
    In Tex Live 2013 the code doesn't work. Ulrike Fischer provides the solution here: http://tex.stackexchange.com/questions/14162/how-do-i-get-a-list-of-all-available-fonts-for-luaotfload – Marco Daniel Jun 03 '13 at 11:52
  • 1
    Can somebody adapt this to TeX Live 2015? – mlainz Jan 16 '16 at 05:23
10

This works for me—as long as there are no fonts with underscores or other offending characters. For the general case, use the optional first argument of tex.print to avoid any troubles: setting it to -2 assigns catcode 12 (other) to all characters except spaces (that way TeX doesn't see \, _, etc. as special characters). See the LuaTeX manual (texdoc luatex) for details.

\documentclass[10pt,a4paper]{article}
\usepackage{fontspec}
\usepackage{luacode,luaotfload,luatextra}
\usepackage[margin=18mm]{geometry}

\begin{document}
\begin{luacode}
myfonts=dofile(fonts.names.path.localdir..'/otfl-names.lua')

for i,v in ipairs(myfonts.mappings) do
  tex.print('\\setmainfont{' .. v.fontname .. '}') 
  tex.sprint(-2, v.familyname..', '..v.fontname) --Prints everything with catcode 12.
  tex.sprint('\\par')
  if i > 50 then break end --Stop early for testing purposes.
end
\end{luacode}    
\end{document}

the first few lines

Running this without the early breaking line will take rather long and some fonts might cause problems (e.g., in my case MnSymbol9.otf caused the pdf to be corrupt and ocrb5.otf caused fontspec to fail).

Caramdir
  • 89,023
  • 26
  • 255
  • 291
2

The following works with lualatex (LuaTeX) 0.95.0 (TeX Live 2016).

First, ensure that luaotfload-names.lua is in the same directory:

luaotfload-tool -u
cp ~/.texlive/texmf-var/luatex-cache/generic/names/luaotfload-names.lua.gz .
gzip -d ~/luaotfload-names.lua.gz

Then create allfonts.tex with the following content:

\RequirePackage{luatex85}
\documentclass[varwidth]{standalone}
\usepackage{fontspec}
\setmainfont{Latin Modern Mono Light}

\usepackage[tmargin=23mm,lmargin=25mm]{geometry}

\usepackage{luacode}

\usepackage{longtable,makecell}
\renewcommand\arraystretch{2}

\begin{document}
\begin{luacode}
myfonts=dofile('luaotfload-names.lua')
teststring = "Sphinx of black quartz, judge my vow."

tex.print("\\begin{longtable}{ll}\\hline")

for i,v in ipairs(myfonts.mappings) do
  -- Stop early for testing purposes.
  if i > 20 then break end

  tex.print('\\makecell[l]{\\bfseries')
  tex.print(-2, v.familyname)
  tex.print('\\\\[-1ex] \\scriptsize')
  tex.print(-2, v.fontname)
  tex.print('} & \\LARGE\\fontspec{' .. v.fontname .. '}')
  tex.print(-2, teststring)
  tex.print('\\\\ \\hline')
end
tex.print("\\end{longtable}")
\end{luacode}

\end{document}

Run lualatex allfonts.tex

output sample of rendered fonts

This is a slightly modified version of Leo Liu's answer. Took me a while to figure out that I ran into errors because of fonts.names.path.localdir and not knowing how to generate the list of fonts.

qubodup
  • 199