\documentclass{article}

\PassOptionsToPackage{log-declarations=false}{xparse}
\PassOptionsToPackage{no-math}{fontspec}
\PassOptionsToPackage{table}{xcolor}
\PassOptionsToPackage{titles}{tocloft}
%\PassOptionsToPackage{showframe}{geometry}
\usepackage{%
  expl3,xparse,
  ctexheading,geometry,fancyhdr,tocloft,fontspec,xcolor,hologo,
  array,longtable,multirow,hhline,
  hyperref,zref-totpages}

\makeatletter\ExplSyntaxOn

\seq_const_from_clist:Nn \c_@@_unicode_reserved_seq
  {
    % Greek and Coptic
      378,   379,   380,   381,   382,   383,   38B,   38D,  3A2,
    % General Punctuation
     2065,
    % Superscripts and Subscripts
     2072,  2073,  208F,  209D,  209E,  209F,
    % Currency Symbols
     20C0,  20C1,  20C2,  20C3,  20C4,  20C5,  20C6,  20C7,  20C8,  20C9,
     20CA,  20CB,  20CC,  20CD,  20CE,  20CF,
    % Combining Diacritical Marks for Symbols
     20F1,  20F2,  20F3,  20F4,  20F5,  20F6,  20F7,  20F8,  20F9,  20FA,
     20FB,  20FC,  20FD,  20FE,  20FF,
    % Number Forms
     218C,  218D,  218E,  218F,
    % Control Pictures
     2427,  2428,  2429,  242A,  242B,  242C,  242D,  242E,  242F,  2430,
     2431,  2432,  2433,  2434,  2435,  2436,  2437,  2438,  2439,  243A,
     243B,  243C,  243D,  243E,  243F,
    % Optical Character Recognition
     244B,  244C,  244D,  244E,  244F,  2450,  2451,  2452,  2453,  2454,
     2455,  2456,  2457,  2458,  2459,  245A,  245B,  245C,  245D,  245E,
     245F,
    % Miscellaneous Symbols and Arrows
     2B74,  2B75,  2B96,
    % Alphabetic Presentation Forms
     FB07,  FB08,  FB09,  FB0A,  FB0B,  FB0C,  FB0D,  FB0E,  FB0F,  FB10,
     FB11,  FB12,  FB18,  FB19,  FB1A,  FB1B,  FB1C,  FB37,  FB3D,  FB3F,
     FB42,  FB45,
    % Arabic Presentation Forms-B
     FE75,  FEFD,  FEFE,
    % Mathematical Alphanumeric Symbols
    1D455, 1D49D, 1D4A0, 1D4A1, 1D4A3, 1D4A4, 1D4A7, 1D4A8, 1D4AD, 1D4BA,
    1D4BC, 1D4C4, 1D506, 1D50B, 1D50C, 1D515, 1D51D, 1D53A, 1D53F, 1D545,
    1D547, 1D548, 1D549, 1D551, 1D6A6, 1D6A7, 1D7CC, 1D7CD,
    % Geometric Shapes Extended
    1F7D9, 1F7DA, 1F7DB, 1F7DC, 1F7DD, 1F7DE, 1F7DF, 1F7EC, 1F7ED, 1F7EE,
    1F7EF, 1F7F0, 1F7F1, 1F7F2, 1F7F3, 1F7F4, 1F7F5, 1F7F6, 1F7F7, 1F7F8,
    1F7F9, 1F7FA, 1F7FB, 1F7FC, 1F7FD, 1F7FE, 1F7FF,
  }

\seq_const_from_clist:Nn \c_@@_unicode_control_seq
  {
    % C0 Controls and Basic Latin
     0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  A,  B,  C,  D,  E,  F,
    10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1A, 1B, 1C, 1D, 1E, 1F,
    7F,
     % C1 Controls and Latin-1 Supplement
    80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 8A, 8B, 8C, 8D, 8E, 8F,
    90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 9A, 9B, 9C, 9D, 9E, 9F
  }

% Require `\c_@@_glyph_non_unicode_with_type_seq`
\file_input:n { firamath-glyph-list.tex }

% #1 = symbol index
\cs_new_protected:Npn \@@_symbol:n #1
  { \tex_char:D \int_eval:n {#1} \scan_stop: }
\prg_new_protected_conditional:Npnn \@@_if_char_exist:n #1 { T, F, TF }
  {
    \tex_iffontchar:D \tex_font:D \int_eval:n {#1} \scan_stop:
      \prg_return_true:
    \else:
      \prg_return_false:
    \fi:
  }
% #1 = glyph name
% See https://tex.stackexchange.com/q/420167
\cs_new_protected:Npn \@@_glyph_from_name:n #1
  { \tex_XeTeXglyph:D \tex_XeTeXglyphindex:D "#1" \scan_stop: }

% Centering with fixed width
\newcolumntype {C} [1] { > { \centering \arraybackslash } m {#1} }
% Empty array rule
\newcolumntype {E} { ! { \skip_horizontal:N \arrayrulewidth } }

\definecolor { encoding @ bg   } { HTML } { BDBDBD }
\definecolor { reserved @ bg   } { HTML } { EA4335 }
\definecolor { control  @ bg   } { HTML } { 4285F4 }
\definecolor { nochar   @ text } { HTML } { E0E0E0 }

\cs_set:Npn \NumberStyle      { \ttfamily   \footnotesize }
\cs_set:Npn \GlyphStyle       { \SymbolFont \Large        }
\cs_set:Npn \EncodingStyle
  { \ttfamily \fontsize { 4 } { 5 } \selectfont \cellcolor { encoding@bg } }

\cs_set:Npn \GlyphStrut               { \@@_set_arstrut:nn {  20 pt } { 10 pt } }
\cs_set:Npn \NonUnicodeGlyphStrut     { \@@_set_arstrut:nn {  32 pt } { 20 pt } }
\cs_set:Npn \NonUnicodeHighGlyphStrut { \@@_set_arstrut:nn {  64 pt } { 40 pt } }
\cs_set:Npn \EncodingStrut            { \@@_set_arstrut:nn { 4.5 pt } {  1 pt } }

\dim_const:Nn \c_@@_cell_wd_dim        { 30 pt }
\dim_const:Nn \c_@@_column_sep_dim     {  0 pt }
\dim_const:Nn \c_@@_row_number_ht_dim  { 20 pt }
\dim_const:Nn \c_@@_row_number_sep_dim {  6 pt }
\dim_const:Nn \c_@@_non_unicode_wd_dim        { 87 pt }

% The total number of glyphs.
\newcounter { glyph }
\setcounter { glyph } { -1 }

% The main function.
\NewDocumentCommand \fonttable { s m g }
  {
    \IfBooleanTF {#1}
      { \@@_non_unicode:nn {#2}      }
      { \@@_unicode:nn     {#2} {#3} }
    \clearpage
  }

% #1 = section name
% #2 = begin/end encoding
\cs_new_protected:Npn \@@_unicode:nn #1#2
  {
    \tl_set:Nn \l_@@_glyph_count_tl
      { \ref* { count: glyph @ #1 } / \ref* { count: codepoint @ #1 } }
    \section { #1 ~ (\tl_use:N \l_@@_glyph_count_tl) }
    \cs_set_eq:NN \@@_left_foot: \@@_left_foot_unicode:
    \@@_parse_encoding:n {#2}
    \int_gzero:N \g_@@_glyph_int
    \int_gzero:N \g_@@_code_point_int
    \@@_make_table:
    \newcounter     {     glyph     @ #1 }
    \newcounter     {     codepoint @ #1 }
    \int_set:cn     { c @ glyph     @ #1 } { \g_@@_glyph_int      - 1 }
    \int_set:cn     { c @ codepoint @ #1 } { \g_@@_code_point_int - 1 }
    \refstepcounter {     glyph     @ #1 } \label { count: glyph     @ #1 }
    \refstepcounter {     codepoint @ #1 } \label { count: codepoint @ #1 }
  }
\tl_new:N  \l_@@_glyph_count_tl
\int_new:N \g_@@_glyph_int
\int_new:N \g_@@_code_point_int

\cs_new_protected:Npn \@@_left_foot_unicode:
  {
    \mode_leave_vertical:
    \footnotesize
    \@@_color_box:nn { reserved @ bg } Reserved~ Code~ Points, \quad
    \@@_color_box:nn { control  @ bg } Control~ Codes.
  }
\cs_new_protected:Npn \@@_color_box:nn #1#2
  {
    \group_begin:
      \color {#1} \rule [ -2 pt ] { 10 pt } { 10 pt }
    \group_end:
    \ = \ #2
  }

% #1 = `begin` - `end`
\cs_new_protected:Npn \@@_parse_encoding:n #1
  {
    \seq_set_split:Nnn \l_tmpa_seq { - } {#1}
    \int_set:Nn \l_@@_begin_int { \seq_item:Nn \l_tmpa_seq { 1 } }
    \int_set:Nn \l_@@_end_int   { \seq_item:Nn \l_tmpa_seq { 2 } }
  }
\int_new:N \l_@@_begin_int
\int_new:N \l_@@_end_int

\cs_new_protected:Npn \@@_make_table:
  {
    \longtable { r | * { 16 } { C { \c_@@_cell_wd_dim } | } }
      \@@_long_table_head:
      \@@_multi_row:nn
        { \int_use:N \l_@@_begin_int }
        { \int_use:N \l_@@_end_int   }
    \endlongtable
  }
\dim_set_eq:NN \tabcolsep \c_@@_column_sep_dim

% These functions must be expandable:
%   \@@_long_table_head:, \@@_first_row:,
%   \@@_multi_row:nn, \@@_row:n, \@@_div_sixteen:n,
%   \@@_hline:, \@@_set_arstrut:nn, \@@_restore_arstrut:, etc.,
% so that `noalign` can work properly.
% Hence we use `\cs_new:Npn` and `\int_step_function:nnnN` here.

\cs_new:Npn \@@_long_table_head:
  {
    % It's very hackable here!
    % The dimension is measured by hand. Not universal at all.
    \@@_set_arstrut:nn { 0 pt } { 0 pt }
    \multicolumn { 17 } { c } { \rule { 0 pt } { 1.29 cm } } \\
    \@@_first_row:
    \endhead
    \@@_first_row:
    \endfirsthead
  }

\cs_new:Npn \@@_first_row:
  {
    \multicolumn { 17 } { r }
      {
        \tabular
            {
              % Skip row number
              r |
              * { 15 } { C { \c_@@_cell_wd_dim } E }
              C { \c_@@_cell_wd_dim } |
            }
          % I don't know why there are so many `#`.
          \int_step_inline:nnn { 0 } { 15 }
            { & \@@_first_row_cell:n {####1} }
        \endtabular
      }
    \\*
    \@@_hline:
  }
\cs_new_protected:Npn \@@_first_row_cell:n #1
  { \NumberStyle \int_to_Hex:n {#1} }

\cs_new:Npn \@@_multi_row:nn #1#2
  {
    \int_step_function:nnnN
      { \@@_div_sixteen:n {#1} * 16 }
      { 16 }
      { (\@@_div_sixteen:n {#2} + 1) * 16 - 1 }
      \@@_row:n
  }
\cs_new:Npn \@@_div_sixteen:n #1
  { \int_div_truncate:nn {#1} { 16 } }

\cs_new:Npn \@@_row:n #1
  {
    % Glyph row
    \GlyphStrut
    % Row number
    \multirow { 2 } * { \@@_row_nummber:n {#1} }
    \int_step_inline:nnn {#1} { #1 + 15 }
      { & \@@_glyph:n {##1} }
    \\*
    \@@_restore_arstrut:
    % Encoding row
    \@@_hline:
    \EncodingStrut
    \int_step_inline:nnn {#1} { #1 + 15 }
      { & \@@_encoding:n {##1} }
    \\
    \@@_hline:
  }

% To skip the first column (i.e. row index).
% LaTeX3 syntax makes `~` to equal space, so we need to change its catcode temporarily.
\group_begin:
  \char_set_catcode_active:N \~
  \cs_new:Npn \@@_hline:
    { \hhline { ~ | * { 16 } { - } } }
\group_end:

\cs_new:Npn \@@_set_arstrut:nn #1#2
  {
    \tex_noalign:D
      {
        \group_begin:
          % Store the old strutbox
          \box_gset_eq:NN \l_@@_old_arstrut_box \@arstrutbox
          % Change the dimensions of \@arstrutbox
          \hbox_set_to_wd:Nnn \l_tmpa_box { \c_zero_dim } { }
          \box_set_ht:Nn \l_tmpa_box {#1}
          \box_set_dp:Nn \l_tmpa_box {#2}
          \hbox_gset:Nn \@arstrutbox { \box_use:N \l_tmpa_box }
        \group_end:
      }
  }
\cs_new:Npn \@@_restore_arstrut:
  {
    \tex_noalign:D
      { \box_gset_eq:NN \@arstrutbox \l_@@_old_arstrut_box }
  }
\box_new:N \l_@@_old_arstrut_box

\cs_new_protected:Npn \@@_row_nummber:n #1
  {
    \raisebox { \dim_use:N \c_@@_row_number_ht_dim }
      {
        \NumberStyle
        \int_set:Nn \l_tmpa_int { #1 / 16 }
        \int_compare:nNnTF { \l_tmpa_int } < { "10 }
          { 00 }
          {
            \int_compare:nNnT { \l_tmpa_int } < { "100 }
              { 0 }
          }
        \int_to_Hex:n { \l_tmpa_int }
        \skip_horizontal:N \c_@@_row_number_sep_dim
      }
  }

\cs_new_protected:Npn \@@_glyph:n #1
  {
    \tl_set:Nx \l_tmpa_tl { \int_to_Hex:n {#1} }
    \seq_if_in:NVTF \c_@@_unicode_reserved_seq \l_tmpa_tl
      { \cellcolor { reserved@bg } }
      {
        \seq_if_in:NVTF \c_@@_unicode_control_seq \l_tmpa_tl
          { \cellcolor { control@bg } }
          {
            % It must be outside `\@@_if_char_exist`
            \GlyphStyle
            \@@_if_char_exist:nTF {#1}
              {
                \@@_symbol:n {#1}
                \refstepcounter { glyph }
                \int_gincr:N \g_@@_glyph_int
              }
              {
                \normalfont
                \int_compare:nNnTF {#1} < { "10000 }
                  { \BMPFallbackFont } { \SMPFallbackFont }
                \textcolor { nochar@text } { \@@_symbol:n {#1} }
              }
            \int_gincr:N \g_@@_code_point_int
          }
      }
  }

\cs_new_protected:Npn \@@_encoding:n #1
  {
    \group_begin:
      \EncodingStyle
      \int_compare:nNnTF {#1} < { "10 }
        { 000 }
        {
          \int_compare:nNnTF {#1} < { "100 }
            { 00 }
            {
              \int_compare:nNnT {#1} < { "1000 }
                { 0 }
            }
        }
      \int_to_Hex:n {#1}
    \group_end:
  }

% #1 = section name
% #2 = non-unicode data file
\cs_new_protected:Npn \@@_non_unicode:nn #1#2
  {
    \tl_set:Nn \l_@@_glyph_count_tl { \ref* { count: glyph @ non-unicode } }
    \section { #1 ~ (\tl_use:N \l_@@_glyph_count_tl) }
    \cs_set_eq:NN \@@_left_foot: \prg_do_nothing:
    \int_gzero:N \g_@@_non_unicode_glyph_int
    \@@_non_unicode_print:
    \newcounter     {     glyph @ non-unicode }
    \int_set:cn     { c @ glyph @ non-unicode } { \g_@@_non_unicode_glyph_int - 1 }
    \refstepcounter {     glyph @ non-unicode } \label { count: glyph @ non-unicode }
    \refstepcounter {     glyph               } \label { count: glyph               }
  }
\int_new:N \g_@@_non_unicode_glyph_int

\cs_new_protected:Npn \@@_non_unicode_print:
  {
    \seq_map_inline:Nn \c_@@_glyph_non_unicode_with_type_seq
      { \@@_non_unicode_print_class:nn ##1 }
  }

% #1 = class
% #2 = clist of glyph names
\cs_new_protected:Npn \@@_non_unicode_print_class:nn #1#2
  {
    \subsection { #1 ~ (\clist_count:n {#2}) }
    \clist_map_inline:nn {#2}
      {
        \@@_non_unicode_cell:n {##1}
        \refstepcounter { glyph }
        \int_gincr:N \g_@@_non_unicode_glyph_int
      }
  }

\cs_new_protected:Npn \@@_non_unicode_cell:n #1
  {
    \tabular { | C { \c_@@_non_unicode_wd_dim } | }
      % Glyph
      \hline
      \NonUnicodeGlyphStrut \GlyphStyle
      \@@_glyph_from_name:n {#1}
      \\
      \@@_restore_arstrut:
      % Encoding (glyph name)
      \hline
      \EncodingStrut \EncodingStyle
      #1
      \\
      \@@_restore_arstrut:
      \hline
    \endtabular
    % A space allowing line break
    \
  }

% Header and footer.
\fancyhf { }
\fancyhead [ R ] { \thepage }
\fancyfoot [ L ]
  {
    \footnotesize
    \int_compare:nNnTF { \int_use:c { c@page } } = { \ztotpages }
      { \@@_left_foot_last_page: } { \@@_left_foot: }
  }
\fancyfoot [ R ]
  {
    \footnotesize \itshape
    Copyright~ \copyright{}~ 2018--2020~ by~ Xiangdong~ Zeng
  }
% `\headrulewidth` is not a dim variable.
\cs_set:Npn \headrulewidth { 0 pt }
\cs_new_protected:Npn \@@_left_foot_last_page:
  {
    \itshape
    Other~ fonts~ used~ in~ this~ document:~
    FiraGO,~ Fira~ Code,~ GNU~ Unifont. \\
    Colors~ are~ inspired~ by~ Google~ Material~ Design.
  }

\ExplSyntaxOff\makeatother

\geometry{a4paper, hmargin=1cm, vmargin=2.5cm}
\ctexset{section/format=\Large\bfseries\centering}
\hypersetup{bookmarksnumbered=true, colorlinks=true,
  linkcolor=[HTML]34A853, urlcolor=[HTML]E91E63}

\setmainfont{FiraGO}[BoldFont=* SemiBold, Numbers=Monospaced]
\setmonofont{Fira Code}[UprightFont=* Light, BoldFont=* Regular]

\newfontface\BMPFallbackFont{Unifont}
\newfontface\SMPFallbackFont{Unifont Upper}
\newfontface\SymbolFont{Fira Math Regular}

\title{\bfseries\huge Fira Math\\
  \itshape\Large Sans-serif font with Unicode math support}
\author{Xiangdong Zeng}
\date{2020/10/15\quad v0.3.4}

\begin{document}

\newgeometry{hmargin=1.5in, vmargin=1.0in}

\maketitle

\begin{abstract}
  \href{https://github.com/firamath/firamath}{Fira Math} is a sans-serif font
  with Unicode math support. The design of this font is based on
  \href{https://github.com/mozilla/Fira}{Fira Sans} and
  \href{https://bboxtype.com/typefaces/FiraGO}{FiraGO}. Fira Math is distributed
  in OpenType format, and can be used with
  \href{https://www.ctan.org/pkg/unicode-math}{unicode-math} package under
  \hologo{XeTeX} or \hologo{LuaTeX}. There are \ref*{count:glyph} glyphs in
  Fira Math at present.

  Fira Math is licensed under the
  \href{http://scripts.sil.org/OFL}{SIL Open Font License}, Version 1.1.
\end{abstract}

\setlength\cftbeforesubsecskip{1ex}
\tableofcontents

\clearpage

\restoregeometry
\pagestyle{fancy}

\fonttable{C0 Controls and Basic Latin}{"0-"7F}
\fonttable{C1 Controls and Latin-1 Supplement}{"80-"FF}
\fonttable{Latin Extended-A}{"100-"17F}
\fonttable{Latin Extended-B}{"180-"24F}
\fonttable{Combining Diacritical Marks}{"300-"36F}
\fonttable{Greek and Coptic}{"370-"3FF}
\fonttable{Cyrillic}{"400-"4FF}
\fonttable{General Punctuation}{"2000-"206F}
\fonttable{Currency Symbols}{"20A0-"20CF}
\fonttable{Combining Diacritical Marks for Symbols}{"20D0-"20FF}
\fonttable{Letterlike Symbols}{"2100-"214F}
\fonttable{Number Forms}{"2150-"218F}
\fonttable{Arrows}{"2190-"21FF}
\fonttable{Mathematical Operators}{"2200-"22FF}
\fonttable{Miscellaneous Technical}{"2300-"23FF}
\fonttable{Block Elements}{"2580-"259F}
\fonttable{Geometric Shapes}{"25A0-"25FF}
\fonttable{Miscellaneous Symbols}{"2600-"26FF}
\fonttable{Miscellaneous Mathematical Symbols-A}{"27C0-"27EF}
\fonttable{Supplemental Arrows-A}{"27F0-"27FF}
\fonttable{Supplemental Arrows-B}{"2900-"297F}
\fonttable{Miscellaneous Mathematical Symbols-B}{"2980-"29FF}
\fonttable{Supplemental Mathematical Operators}{"2A00-"2AFF}
\fonttable{Miscellaneous Symbols and Arrows}{"2B00-"2BFF}
\fonttable{Alphabetic Presentation Forms}{"FB00-"FB4F}
\fonttable{Mathematical Alphanumeric Symbols}{"1D400-"1D7FF}
\fonttable{Geometric Shapes Extended}{"1F780-"1F7FF}
\fonttable*{Non-Unicode Glyphs}

\end{document}
