% !TEX TS-program = lualatex

\documentclass[10pt,a4paper]{article}

\textheight=268mm
\textwidth=140mm
\oddsidemargin=5mm
\evensidemargin=5mm
\topmargin=-25mm

\usepackage{cmgraded}
\usepackage{longtable}
\usepackage{color}
\usepackage{luacode}

\definecolor{darkred}{rgb}{0.8,0,0}

\newfontface\lmfont{Latin Modern Roman}
\newfontface\cmgfont{Computer Modern Graded Serif}

\newcommand{\gu}[1]{\texttt{\footnotesize U+#1}}  % Unicode code point
\newcommand{\gt}[1]{\texttt{\footnotesize #1}} % official Unicode name
\newcommand{\gl}[1]{{\lmfont\char"#1\relax}} % the glyph in Latin Modern
\newcommand{\gc}[1]{{\cmgfont\char"#1\relax}} % the glyph in CM Graded
\newcommand{\gn}{\textbf{\textsf{\color{darkred}\small (n/a)}}} % not in CM Graded

% Emit one longtable row per Latin Modern code point, in ascending order.
% For every glyph Latin Modern has, we look up whether Computer Modern Graded
% has a glyph for the same code point; if not, the cell shows "(n/a)".
% GLM / GCMG are the two font ids, captured at the start of the document.
\begin{luacode*}
function cmg_glyph_table()
  local lm  = font.getfont(GLM)
  local cmg = font.getfont(GCMG)

  -- Official Unicode names, read straight from the Unicode Character Database
  -- (unicode-data's UnicodeData.txt, shipped with TeX Live) -- so no names are
  -- listed in this file. Each line is "codepoint;NAME;...". Fall back to Latin
  -- Modern's own glyph name, then to uniXXXX, if a name is not found.
  local uniname = {}
  local udpath = kpse.find_file("UnicodeData.txt")
  if udpath then
    for line in io.lines(udpath) do
      local cp, nm = line:match("^(%x+);([^;]*)")
      if cp and nm and nm ~= "" and nm:sub(1, 1) ~= "<" then
        uniname[tonumber(cp, 16)] = nm
      end
    end
  end
  local res = lm.resources or (lm.shared and lm.shared.rawdata and lm.shared.rawdata.resources)
  local fontname = {}
  if res and res.unicodes then
    for name, uni in pairs(res.unicodes) do
      if type(uni) == "number" and not fontname[uni] then fontname[uni] = name end
    end
  end

  -- collect and sort Latin Modern's code points. Skip: the control range;
  -- any code point mapping to .notdef; and the Private Use Areas, where LM
  -- parks unencoded helper glyphs (extra ligatures, capital-height accents,
  -- accent-composition pieces) reachable only via font features -- these are
  -- not assigned Unicode characters and do not belong in this table.
  local function is_pua(cp)
    return (cp >= 0xE000   and cp <= 0xF8FF)    -- Private Use Area (BMP)
        or (cp >= 0xF0000  and cp <= 0xFFFFD)   -- Supplementary Private Use Area-A
        or (cp >= 0x100000 and cp <= 0x10FFFD)  -- Supplementary Private Use Area-B
  end
  local cps = {}
  for cp in pairs(lm.characters) do
    if type(cp) == "number" and cp >= 0x20
       and (lm.characters[cp].index or -1) ~= 0 and not is_pua(cp) then
      cps[#cps + 1] = cp
    end
  end
  table.sort(cps)

  -- escape the few TeX-special characters that could appear in a glyph name
  local function esc(s)
    return (s:gsub(".", function(ch)
      if ch == "\\" then return "\\textbackslash{}" end
      if ch == "^"  then return "\\^{}" end
      if ch == "~"  then return "\\~{}" end
      if ch:match("[{}$&#%%_]") then return "\\" .. ch end
      return ch
    end))
  end

  local cmgchars = cmg.characters
  for _, cp in ipairs(cps) do
    local hex     = string.format("%04X", cp)
    local name    = uniname[cp] or fontname[cp] or ("uni" .. hex)
    local cmgcell = cmgchars[cp] and ("\\gc{" .. hex .. "}") or "\\gn"
    tex.sprint(string.format(
      "\\gu{%s} & \\gl{%s} & %s & \\ \\gt{%s} \\\\ \\hline",
      hex, hex, cmgcell, esc(name)))
  end
end
\end{luacode*}

\pagestyle{empty}

\begin{document}

% Capture the two font ids for the Lua row generator (each inside a group so
% the surrounding font is left untouched).
{\lmfont\directlua{GLM = font.current()}}%
{\cmgfont\directlua{GCMG = font.current()}}%

\section*{\textsf{Computer Modern Graded – List Glyphs Example}}

\textsf{This example document lists all glyphs
of the current Lua\LaTeX\ default font \textbf{Latin Modern}
next to the same glyphs in \textbf{Computer Modern Graded};
more precisely, for Roman/Serif 10pt.
%
Where Computer Modern Graded has no glyph for a code point,
the last column displays \gn\ instead.
%
The rows are generated by a small Lua script embedded in the source
that reads both fonts and compares their glyph coverage.}

\textsf{Note that the exact set of glyphs differs slightly
between the different kinds and styles of these font families\,—\,%
you could edit the *.tex source of this document to list others.}

\textsf{Also note that if you want to use some of the non-existing glyphs,
you might want to consider using mechanisms similar to the
examples with German low quotes and French guillemets
of the \texttt{cmgraded-emulate-glyphs.tex} example.}

%\vspace{-2mm}
\begin{center}
\renewcommand{\arraystretch}{1.4}
\begin{longtable}{|l|c|c|p{90mm}|}
\hline
\textbf{\textsf{Unicode}} & \textbf{\textsf{LM}} & \textbf{\textsf{CMG}} & \textbf{\textsf{Name}} \\ \hline
\endfirsthead
\hline
\textbf{\textsf{Unicode}} & \textbf{\textsf{LM}} & \textbf{\textsf{CMG}} & \textbf{\textsf{Name}} \\ \hline
\endhead
\directlua{cmg_glyph_table()}
\end{longtable}
\end{center}

\end{document}
