diff options
| -rw-r--r-- | luaotfload.dtx | 414 | ||||
| -rw-r--r-- | luaotfload.lua | 416 | ||||
| -rwxr-xr-x | mkluatexfontdb.lua | 184 | ||||
| -rw-r--r-- | otfl-font-nms.lua | 75 | 
4 files changed, 903 insertions, 186 deletions
| diff --git a/luaotfload.dtx b/luaotfload.dtx index 595a9fa..3685083 100644 --- a/luaotfload.dtx +++ b/luaotfload.dtx @@ -130,13 +130,14 @@ and the derived files  \setsansfont[Ligatures=TeX,Scale=MatchLowercase]{Iwona Medium}  %setmathfont{XITS Math} -\newcommand\TEX    {\TeX\xspace} -\newcommand\LUA    {Lua\xspace} -\newcommand\PDFTEX {pdf\TeX\xspace} -\newcommand\LUATEX {Lua\TeX\xspace} -\newcommand\XETEX  {\XeTeX\xspace} -\newcommand\LATEX  {\LaTeX\xspace} -\newcommand\CONTEXT{Con\TeX t\xspace} +\newcommand\TEX     {\TeX\xspace} +\newcommand\LUA     {Lua\xspace} +\newcommand\PDFTEX  {pdf\TeX\xspace} +\newcommand\LUATEX  {Lua\TeX\xspace} +\newcommand\XETEX   {\XeTeX\xspace} +\newcommand\LATEX   {\LaTeX\xspace} +\newcommand\CONTEXT {Con\TeX t\xspace} +\newcommand\OpenType{\identifier{Open\kern-.25ex Type}\xspace}  \def\definehighlight[#1][#2]%   {\ifcsname #1\endcsname\else @@ -192,24 +193,26 @@ and the derived files  % \maketitle  %  % \begin{abstract} -% This package is an adaptation of the \CONTEXT font loading system, providing -% the ability to load \identifier{OpenType} fonts with extended font loading syntax -% supporting a large selection of \identifier{OpenType} font features. +% This package is an adaptation of the \CONTEXT font loading system. +% It allows for loading \OpenType fonts with an extended syntax and adds +% support for a variety of font features.  % \end{abstract}  %  % \tableofcontents  % +% \part{Package Description} +%  % \section{Introduction}  %  % Font management and installation has always been painful with \TEX.  A lot of  % files are needed for one font (\abbrev{tfm}, \abbrev{pfb}, \abbrev{map}, -% \abbrev{fd}, \abbrev{vf}), and as \TEX is 8-bit each font is limited to 256 -% characters. +% \abbrev{fd}, \abbrev{vf}), and due to the 8-Bit encoding each font is limited +% to 256 characters.  % But the font world has evolved since the original  % \TEX, and new typographic systems have appeared, most notably the so -% called \emphasis{smart font} technologies like \identifier{OpenType} -% (\abbrev{otf}) fonts. -% These fonts can contain a lot of characters and additional +% called \emphasis{smart font} technologies like \OpenType +% fonts (\abbrev{otf}). +% These fonts can contain many more characters than \TEX fonts, as well as additional  % functionality like ligatures, old-style numbers, small capitals,  % etc., and support more complex writing systems like Arabic and  % Indic\footnote{% @@ -219,7 +222,7 @@ and the derived files  %   appreciated.  % }  % scripts. -% \identifier{OpenType} fonts are widely deployed and available for all +% \OpenType fonts are widely deployed and available for all  % modern operating systems.  % As of 2013 they have become the de facto standard for advanced text  % layout. @@ -227,12 +230,17 @@ and the derived files  % world was with the \XETEX engine.  %  % Unlike \XETEX, \LUATEX has no built-in support for -% \identifier{OpenType} or other technologies. -% Instead, it provides hooks for executing Lua during the \TEX run +% \OpenType or technologies other than the original \TEX fonts. +% Instead, it provides hooks for executing \LUA code during the \TEX run  % that allow implementing extensions for loading fonts and manipulating  % how input text is processed without modifying the underlying engine. +% This is where \identifier{luaotfload} comes into play: +% Based on code from \CONTEXT, it extends \LUATEX with functionality necessary +% for handling \OpenType fonts. +% Additionally, it provides means for accessing fonts known to the operating +% system conveniently by indexing the metadata.  % -% \section{Loading fonts} +% \section{Loading Fonts}  %  % \identifier{luaotfload} supports an extended font loading syntax:  % @@ -252,7 +260,7 @@ and the derived files  % \paragraph{Prefix}  %  % The \meta{prefix} is either |file:| or |name:|. -% It determines whether font loader should interpret the request as a +% It determines whether the font loader should interpret the request as a  % file name or font name, respectively, which again influences how it  % will attempt to locate the font.  % The prefix can be omitted, in which case |name:| is assumed. @@ -266,30 +274,89 @@ and the derived files  %% For compatibility with \XETEX, surrounding the \meta{font name} with  %% square brackets is synonymous to using the |file:| prefix.  % -% Accessing fonts by fontname allows loading system installed fonts as -% well as \fileent{texmf} ones, and requires a font names database; see -% Section~\ref{sec:fontdb} for more information. +% In order for fonts installed both in system locations and in your +% \fileent{texmf} to be accessible by font name, \identifier{luaotfload} must +% first collect the metadata included in the files. +% Please refer to section ~\ref{sec:fontdb} below for instructions on how to +% create the database.  %  % \paragraph{Font name}  %  % The \meta{font name} can be either a font filename or actual font  % name based on the \meta{prefix} as mentioned above.  % -% Fonts loaded by filename may either include their absolute path in -% the filesystem or consist of just the filename without a path.  If no -% path is specified, then \identifier{kpathsea} is used to locate the +% A filename request may optionally include the absolute path to the font file, +% allowing for fonts outside the standard locations to be loaded as well. +% If no path is specified, then \identifier{kpathsea} is used to locate the  % font (which will typically be in the \fileent{texmf} tree or the  % current directory).  % -% For example, +% \subparagraph{Examples for loading by file name} +% +% For example, conventional \abbrev{type1} font can be loaded with a \verb|file:| +% request like so: +%  % \begin{quote} -% \begin{verbatim} -% \font\1={file:ec-lmr10} at 10pt -% \font\2={/Users/Shared/Fonts/aldus.otf} at 11pt -% \font\3={name:TeX Gyre Pagella} at 9pt -% \end{verbatim} +%   \begin{verbatim} +%   \font\lmromanten={file:ec-lmr10} at 10pt +%   \end{verbatim}  % \end{quote}  % +% The \OpenType version of Janusz Nowacki’s font \emphasis{Antykwa +% Półtawskiego} (in \TEX Live) in its condensed variant can be loaded as +% follows: +% +% \begin{quote} +%   \begin{verbatim} +%   \font\apcregular=file:antpoltltcond-regular.otf at 42pt +%   \end{verbatim} +% \end{quote} +% +% The next example shows how to load the \emphasis{Porson} font digitized by +% the Greek Font Society using \XETEX-style syntax and an absolute path from a +% non-standard directory: +%  +% \begin{quote} +%   \begin{verbatim} +%   \font\gfsporson="[/tmp/GFSPorson.otf]" at 12pt +%   \end{verbatim} +% \end{quote} +% +% \subparagraph{Examples for loading by font name} +% +% The \verb|name:| lookup does not depend on cryptic filenames: +% +% \begin{quote} +%   \begin{verbatim} +%   \font\pagellaregular={name:TeX Gyre Pagella} at 9pt +%   \end{verbatim} +% \end{quote} +% +% A bit more specific but essentially the same lookup would be: +% +% \begin{quote} +%   \begin{verbatim} +%   \font\pagellaregular={name:TeX Gyre Pagella Regular} at 9pt +%   \end{verbatim} +% \end{quote} +% +% Which fits nicely with the whole set: +% +% \begin{quote} +%   \begin{verbatim} +%   \font\pagellaregular   ={name:TeX Gyre Pagella Regular}    at 9pt +%   \font\pagellaitalic    ={name:TeX Gyre Pagella Italic}     at 9pt +%   \font\pagellabold      ={name:TeX Gyre Pagella Bold}       at 9pt +%   \font\pagellabolditalic={name:TeX Gyre Pagella Bolditalic} at 9pt +% +%   {\pagellaregular     foo bar baz\endgraf} +%   {\pagellaitalic      foo bar baz\endgraf} +%   {\pagellabold        foo bar baz\endgraf} +%   {\pagellabolditalic  foo bar baz\endgraf} +% +%   ... +%   \end{verbatim} +% \end{quote}  %  % \paragraph{Font features}  % @@ -298,10 +365,14 @@ and the derived files  %   Cf. \url{http://www.microsoft.com/typography/otspec/featurelist.htm}.  % }  % and font options. -% Prepending a font feature with a |+|-sign enables it, while -% a |-| disables it. For instance, the request +% Prepending a font feature with a |+| (plus sign) enables it, whereas +% a |-| (minus) disables it. For instance, the request  % -% |\font\test=Latin Modern Roman:+clig;-kern| +% \begin{quote} +%   \begin{verbatim} +%   \font\test=LatinModernRoman:+clig;-kern +%   \end{verbatim} +% \end{quote}  %  % \noindent activates contextual ligatures (|clig|) and disables  % kerning (|kern|). @@ -309,35 +380,45 @@ and the derived files  % the feature in a key/value expression.  % The following request has the same meaning as the last one:  % -% |\font\test=Latin Modern Roman:clig=true;kern=false| +% \begin{quote} +%   \begin{verbatim} +%   \font\test=LatinModernRoman:clig=true;kern=false +%   \end{verbatim} +% \end{quote}  %  % \noindent -% Furthermore, this second syntax is required if a font feature -% accepts options besides its activation state. -% For example, \emphasis{stylistic alternates} (|salt|) provide a set -% of variants to given glyphs. -% These can be selected either explicitly by supplying the variant -% index (starting from 1), or randomly by setting the value to, -% obviously, |random|: -% -% |\font\test=Latin Modern Roman:salt=1| +% Furthermore, this second syntax is required should a font feature +% accept other options besides a true/false switch. +% For example, \emphasis{stylistic alternates} (|salt|) are variants of given +% glyphs. +% They can be selected either explicitly by supplying the variant +% index (starting from one), or randomly by setting the value to, +% obviously, |random|. +% +% \iffalse TODO verify that this actually works with a font that supports +%               the salt/random feature!\fi +% \begin{quote} +%   \begin{verbatim} +%   \font\librmsaltfirst=LatinModernRoman:salt=1 +%   \end{verbatim} +% \end{quote}  %  % \noindent Other font options include:  %  % \begin{description}  %  % \item [mode] \hfill \\ -%        \identifier{luaotfload} has two \identifier{OpenType} processing +%        \identifier{luaotfload} has two \OpenType processing  %        \emphasis{modes}:  %        \identifier{base} and \identifier{node}.  % -%        \identifier{base} mode works by mapping \identifier{OpenType} -%        features to traditional \TEX ligature and kerning mechanisms, -%        thus supporting only non-contextual substitutions and kerning -%        pairs, but is the slightly faster variant. -%        \identifier{node} mode works by processing \TEX’s internal +%        \identifier{base} mode works by mapping \OpenType +%        features to traditional \TEX ligature and kerning mechanisms. +%        Supporting only non-contextual substitutions and kerning +%        pairs, it is the slightly faster, albeit somewhat limited, variant. +%        \identifier{node} mode works by processing \TeX’s internal  %        node list directly at the \LUA end and supports -%        a wider range of \identifier{OpenType} features. +%        a wider range of \OpenType features.  %        The downside is that the intricate operations required for  %        \identifier{node} mode may slow down typesetting especially  %        with complex fonts and it does not work in math mode. @@ -346,19 +427,20 @@ and the derived files  %        mode, and \identifier{base} mode has to be requested where needed,  %        e.~g. for math fonts.  % -% \item [script] \ref{script-tag} \hfill \\ -%        An \identifier{OpenType} script tag;\footnote{% +% \item [script] \label{script-tag} \hfill \\ +%        An \OpenType script tag;\footnote{%  %          See \url{http://www.microsoft.com/typography/otspec/scripttags.htm}  %          for a list of valid values.  %          For scripts derived from the Latin alphabet the value  %          |latn| is good choice.  %        }  %        the default value is |dlft|. -%        Some fonts do not assign features to the |dflt| script, in +%        Some fonts, including very popular ones by foundries like Adobe, +%        do not assign features to the |dflt| script, in  %        which case the script needs to be set explicitly.  %  % \item [language] \hfill \\ -%        An \identifier{OpenType} language system identifier,\footnote{% +%        An \OpenType language system identifier,\footnote{%  %          Cf. \url{http://www.microsoft.com/typography/otspec/languagetags.htm}.  %        }  %        defaulting to |dflt|. @@ -367,13 +449,13 @@ and the derived files  %        A comma-separated list of feature files to be applied to the  %        font.  %        Feature files contain a textual representation of -%        \identifier{OpenType} tables and extend the features of a font +%        \OpenType tables and extend the features of a font  %        on fly.  %        After they are applied to a font, features defined in a  %        feature file can be enabled or disabled just like any  %        other font feature.  %        The syntax is documented in \identifier{Adobe}’s -%        \identifier{OpenType} Feature File Specification.\footnote{% +%        \OpenType Feature File Specification.\footnote{%  %          Cf. \url{http://www.adobe.com/devnet/opentype/afdko/topic_feature_file_syntax.html}.  %        }  % @@ -391,13 +473,17 @@ and the derived files  %  %        For example, in order to set text in semitransparent red:  % -%        |\font\test=Latin Modern Roman:color=FF0000BB| +%        \begin{quote} +%           \begin{verbatim} +%           \font\test={Latin Modern Roman}:color=FF0000BB +%           \end{verbatim} +%        \end{quote}  %  % \item [protrusion \& expansion] \hfill \\ -%        These keys both control microtypographic features of the font, +%        These keys control microtypographic features of the font,  %        namely \emphasis{character protrusion} and \emphasis{font  %        expansion}. -%        They accept names of predefined \LUA tables that contain +%        Their arguments are names of \LUA tables that contain  %        values for the respective features.\footnote{%  %           For examples of the table layout please refer to the  %           section of the file \fileent{otfl-fonts-ext.lua} where the @@ -423,12 +509,16 @@ and the derived files  %          for details.  %        }:  % -%        |\font\test=Latin Modern Roman:protrusion=default| +%        \begin{quote} +%           \begin{verbatim} +%           \font\test=LatinModernRoman:protrusion=default +%           \end{verbatim} +%        \end{quote}  % \end{description}  %  % \paragraph{Non-standard font features} -% \identifier{luaotfload} add a number of features that are not defined -% in the original \identifier{OpenType} specification, most of them +% \identifier{luaotfload} adds a number of features that are not defined +% in the original \OpenType specification, most of them  % aiming at emulating the behavior familiar from other \TEX engines.  % Currently (2013) there are three of them:  % @@ -441,7 +531,15 @@ and the derived files  %  %   \item [tlig]  %           Applies legacy \TEX ligatures: -%           |``|, |''|, |`|, |'|, |"|, |--|, |---|, |!`| and |?`|.% +% +%           \begin{tabular}{rlrl} +%              ``  &  \verb|``|  &  ''  &  \verb|''|  \\ +%              `   &  \verb|`|   &  '   &  \verb|'|   \\ +%              "   &  \verb|"|   &  --  &  \verb|--|  \\ +%              --- &  \verb|---| &  !`  &  \verb|!`|  \\ +%              ?`  &  \verb|?`|  &      &             \\ +%           \end{tabular} +%  %           \footnote{%  %             These contain the feature set \verb|trep| of earlier  %             versions of \identifier{luaotfload}. @@ -463,16 +561,16 @@ and the derived files  %  % As mentioned above, \identifier{luaotfload} keeps track of which  % fonts are available to \LUATEX by means of a \emphasis{database}. -% This allows loading not only by explicit filenames but also by the -% proper names contained in the metadata which is often more accessible -% to humans.\footnote{% +% This allows referring to fonts not only by explicit filenames but +% also by the proper names contained in the metadata which is often +% more accessible to humans.\footnote{%  %   The tool \href{http://www.lcdf.org/type/}{\fileent{otfinfo}} (comes -%   with \TEX Live), when invoked on a font file with the \verb|-o| +%   with \TEX Live), when invoked on a font file with the \verb|-i|  %   option, lists the variety of name fields defined for it.  % }  % -% When \identifier{luaotfload} is asked to load a font by font name, it -% will check if the database exists and load it or else generate a +% When \identifier{luaotfload} is asked to load a font by a font name, +% it will check if the database exists and load it, or else generate a  % fresh one.  % Should it then fail to locate the font, an update to the database is  % performed in case the font has been added to the system only @@ -482,16 +580,22 @@ and the derived files  % behave as unobtrusively as possible, while providing a convenient  % interface to the fonts installed on the system.  % -% \subsection[mkluatexfontdb.lua]% -%            {\fileent{mkluatexfontdb.lua}\footnote{% +% Generating the database for the first time may take a while since it +% inspects every font file on your computer. +% This is particularly noticeable if it occurs during a typesetting run. +% In any case, subsequent updates to the database will be quite fast. +% +% \subsection[fontdbutil / mkluatexfontdb.lua]% +%            {\fileent{fontdbutil} / +%             \fileent{mkluatexfontdb.lua}\footnote{%  %   The script may be named just \fileent{mkluatexfontdb} in your  %   distribution.  % }}  % -% However, it can be desirable at times to do some of these steps -% manually. +% It can still be desirable at times to do some of these steps +% manually, and without having to compile a document.  % To this end, \identifier{luaotfload} comes with the utility -% \fileent{mkluatexfontdb} that offers an interface to the database +% \fileent{fontdbutil} that offers an interface to the database  % functionality.  % Being a \LUA script, there are two ways to run it:  % either make it executable (\verb|chmod +x| on unixoid systems) or @@ -499,27 +603,39 @@ and the derived files  %   Tests by the maintainer show only marginal performance gain by  %   running with Luigi Scarso’s  %   \href{https://foundry.supelec.fr/projects/luajittex/}% -%        {\LUA jit\TEX}, +%        {\identifier{Luajit\kern-.25ex\TEX}},  %   which is probably due to the fact that most of the time is spent  %   on file system operations.  %  %   \emphasis{Note}:  %   On \abbrev{MS} \identifier{Windows} systems, the script can be run  %   either by calling the wrapper application -%   \fileent{mkluatexfontdb.exe} or as -%   \verb|texlua.exe mkluatexfontdb.lua|. +%   \fileent{fontdbutil.exe} or as +%   \verb|texlua.exe fontdbutil|.  % } -% Invoke it from the command line with the \verb|--force| switch to -% initiate a complete rebuild of the database. +% Invoked with the argument \verb|--update| it will perform a database +% update, scanning for fonts not indexed.  % -% \begin{verbatim} -%   mkluatexfontdb --force -% \end{verbatim} +% \begin{quote} +%   \begin{verbatim} +%     fontdbutil --update +%   \end{verbatim} +% \end{quote}  % -% Generating the database for the first time may take a while since it -% inspects every font file on your computer. -% This is particularly noticeable if it occurs during a typesetting run. -% In any case, subsequent updates to the database will be quite fast. +% Adding the \verb|--force| switch will initiate a complete +% rebuild of the database. +% +% \begin{quote} +%   \begin{verbatim} +%     fontdbutil --update --force +%   \end{verbatim} +% \end{quote} +% +% For sake of backwards compatibility, \fileent{fontdbutil} may be +% renamed or symlinked to \fileent{mkluatexfontdb}. +% Whenever it is run under this name, it will update the database +% first, mimicking the behavior of earlier versions of +% \identifier{luaotfload}.  %  % \subsection{Search Paths}  % @@ -548,9 +664,9 @@ and the derived files  %       Windows     & \verb|%WINDIR%\Fonts|  %       \\  %       Linux       & \fileent{/usr/local/etc/fonts/fonts.conf} and\hfill\break -%                     \fileent{/etc/fonts/fonts.conf"} +%                     \fileent{/etc/fonts/fonts.conf}  %       \\ -%       Mac         & \fileent{~/Library/Fonts},\break +%       Mac         & \fileent{\textasciitilde/Library/Fonts},\break  %                     \fileent{/Library/Fonts},\break  %                     \fileent{/System/Library/Fonts}, and\hfill\break  %                     \fileent{/Network/Library/Fonts} @@ -561,49 +677,70 @@ and the derived files  %   \hrule  % \end{table}  % -% \subsection{Querying from outside} +% \subsection{Querying from Outside}  % -% \fileent{mkluatexfontdb.lua} also provides rudimentary means of -% accessing the font database. -% If the option \verb|--find=name| is given, the script will try and search -% the fonts indexed by \identifier{luaotfload} for a matching name. +% \fileent{fontdbutil} also provides rudimentary means of +% accessing the information collected in the font database. +% If the option \verb|--find=|\emphasis{name} is given, the script will +% try and search the fonts indexed by \identifier{luaotfload} for a +% matching name.  % For instance, the invocation  % -% \begin{verbatim} -%   mkluatexfontdb.lua  --find="Iwona Regular" -% \end{verbatim} +% \begin{quote} +%   \begin{verbatim} +%     fontdbutil  --find="Iwona Regular" +%   \end{verbatim} +% \end{quote}  % +% \noindent  % will verify if “Iwona Regular” is found in the database and can be  % readily requested in a document.  % -% If you are unsure about the actual font name, then you can add the -% \verb|-F| switch to the command line to enable approximate matching. +% If you are unsure about the actual font name, then add the +% \verb|-F| (or \verb|--fuzzy|) switch to the command line to enable +% approximate matching.  % Suppose you cannot precisely remember if the variant of  % \identifier{Iwona} you are looking for was “Bright” or “Light”.  % The query   % -% \begin{verbatim} -%   mkluatexfontdb.lua  -F --find="Iwona Bright" -% \end{verbatim} +% \begin{quote} +%   \begin{verbatim} +%     fontdbutil  -F --find="Iwona Bright" +%   \end{verbatim} +% \end{quote}  % +% \noindent  % will tell you that indeed the latter name is correct.  % -% \verb|mkluatexfontdb.lua --help| will list the available command line -% switches, including some that will not be discussed in detail here. +% Basic information about fonts in the database can be displayed +% using the \verb|-i| option (\verb|--info|). +% \begin{quote} +%   \begin{verbatim} +%     fontdbutil  -F --find="Iwona Light Italic" +%   \end{verbatim} +% \end{quote} +% \noindent +% The meaning of the printed values is described in section 4.4 of the +% \LUATEX reference manual.\footnote{% +%   In \TEX Live: \fileent{texmf-dist/doc/luatex/base/luatexref-t.pdf}. +% } +%   +% \verb|fontdbutil --help| will list the available command line +% switches, including some not discussed in detail here.  % -% \subsection{Blacklisting fonts} +% \subsection{Blacklisting Fonts}  % \label{font-blacklist}  %  % Some fonts are problematic in general, or just in \LUATEX.  % If you find that compiling your document takes far too long or eats  % away all your system’s memory, you can track down the culprit by -% running \verb|mkluatexfontdb -v| to increase verbosity. +% running \verb|fontdbutil -v| to increase verbosity.  % Take a note of the \emphasis{filename} of the font that database  % creation fails with and append it to the file  % \fileent{otfl-blacklist.cnf}.  %  % A blacklist file is a list of font filenames, one per line. -% Specifying the full path where the file is located is optional, the +% Specifying the full path to where the file is located is optional, the  % plain filename should suffice.  % File extensions (\fileent{.otf}, \fileent{.ttf}, etc.) may be omitted.  % Anything after a percent (|%|) character until the end of the line @@ -634,13 +771,13 @@ and the derived files  %  % \section{Files from \CONTEXT and \LUATEX-Fonts}  % -% This package relies on code originally written by Hans +% \identifier{luaotfload} relies on code originally written by Hans  % Hagen\footnote{%  %   The creator of the \href{http://wiki.contextgarden.net}{\CONTEXT}  %   format.  % }  % for and tested with \CONTEXT. -% \identifier{luaotfload} integrates the font loader as distributed in +% It integrates the font loader as distributed in  % the \identifier{\LUATEX-Fonts} package.  % The original \LUA source files have been combined using the  % \fileent{mtx-package} script into a single, self-contained blob. @@ -653,7 +790,7 @@ and the derived files  % The guiding principle is to let \CONTEXT/\LUATEX-Fonts take care of  % the implementation, and update the imported code from time to time.  % As maintainers, we aim at importing files from upstream essentially -% \emphasis{unmodified}, except for renaming the files to prevent name +% \emphasis{unmodified}, except for renaming them to prevent name  % clashes.  % This job has been greatly alleviated since the advent of  % \LUATEX-Fonts, prior to which the individual dependencies had to be @@ -714,10 +851,10 @@ and the derived files  %                           \end{itemize}  %                         \end{multicols}  % -%             \normalitem The \emphasis{Font Loader} itself. +%             \normalitem The \emphasis{font loader} itself.  %                         These files have been written for -%                         \LUATEX-Fonts and are distributed along with -%                         \identifier{luaotfload}. +%                         \LUATEX-Fonts and they are distributed along +%                         with \identifier{luaotfload}.  %                         \begin{multicols}{2}  %                           \begin{itemize}  %                             \incitem{luatex-basics-gen.lua} @@ -748,6 +885,16 @@ and the derived files  %                         \end{multicols}  %           \end{itemize}  % +%           Note that if \identifier{luaotfload} cannot locate the +%           merged file, it will load the individual \LUA libraries +%           instead. +%           Their names remain the same as in \CONTEXT (without the +%           \verb|otfl|-prefix) since they are hard-coded in +%           \fileent{otfl-fonts.lua}. +%           Thus if you prefer running bleeding edge code from the +%           \CONTEXT beta, all you have to do is remove +%           \fileent{otfl-fonts-merged.lua} from the search path. +%  %   \end{itemize}  %  % In addition to these, \identifier{luaotfload} requires a number of @@ -766,9 +913,9 @@ and the derived files  %     \ouritem {otfl-lib-dir.lua}  \fileent{l-dir} from \CONTEXT;  %                                  contains functionality required  %                                  by \fileent{otfl-font-nms.lua}. -%     \ouritem {otfl-luat-ovr.lua} overrides for the \CONTEXT logging +%     \ouritem {otfl-luat-ovr.lua} overrides the \CONTEXT logging  %                                  functionality. -%     \ouritem {otfl-font-pfb.lua} registers the \identifier{OpenType} +%     \ouritem {otfl-font-pfb.lua} registers the \OpenType  %                                  font reader as handler for  %                                  Postscript fonts.  %     \ouritem {otfl-font-nms.lua} font database. @@ -790,11 +937,12 @@ and the derived files  % version of this package before reporting a bug, as  % \identifier{luaotfload} is under active development and still a  % moving target. +%  % Errors during database generation can be traced by increasing  % verbosity levels and redirecting log output to \fileent{stdout}:  %  % \begin{verbatim} -%   mkluatexfontdb.lua -F -vvv --log=stdout +%   fontdbutil -fuvvv --log=stdout  % \end{verbatim}  %  % If this fails, the font last printed to the terminal is likely to be @@ -803,20 +951,40 @@ and the derived files  % being (see above, page \pageref{font-blacklist}).  %  % A common problem is the lack of features for some -% \identifier{OpenType} fonts even when specified. +% \OpenType fonts even when specified.  % This can be related to the fact that some fonts do not provide -% features for the |dflt| script (see above on page +% features for the \verb|dflt| script (see above on page  % \pageref{script-tag}),  % which is the default one in this package. -% If this happens, assigning a script when the font is defined should +% If this happens, assigning a noth script when the font is defined should  % fix it. -% For example with the |latn| script: +% For example with \verb|latn|:  %  % \begin{verbatim}  %   \font\test=file:MyFont.otf:script=latn;+liga;  % \end{verbatim}  % -% \part{\fileent{luaotfload.lua}} +% \part{Implementation} +% +% \section{\fileent{luaotfload.lua}} +% +% This file initializes the system and loads the font loader. +% To minimize potential conflicts between other packages and the +% code imported from \CONTEXT, several precautions are in order. +% Some of the functionality that the font loader expects to be present, +% like raw access to callbacks, are assumed to have been disabled by +% \identifier{luatexbase} when this file is processed. +% In some cases it is possible to trick it by putting dummies into +% place and restoring the behavior from \identifier{luatexbase} after +% initilization. +% Other cases such as attribute allocation require that we hook the +% functionality from \identifier{luatexbase} into locations where they +% normally wouldn’t be. +% +% Anyways we can import the code base without modifications, which is +% due mostly to the extra effort by +% Hans Hagen to make \LUATEX-Fonts self-contained and encapsulate it, +% and especially due to his willingness to incorporate our suggestions.  %  % \iffalse  %<*lua> @@ -1322,7 +1490,7 @@ loadmodule"features.lua"  %</lua>  % \fi  % -% \part{\fileent{luaotfload.sty}} +% \section{\fileent{luaotfload.sty}}  %  % \iffalse  %<*package> diff --git a/luaotfload.lua b/luaotfload.lua new file mode 100644 index 0000000..c85041b --- /dev/null +++ b/luaotfload.lua @@ -0,0 +1,416 @@ +module("luaotfload", package.seeall) + +luaotfload.module = { +    name          = "luaotfload", +    version       = 2.2, +    date          = "2013/04/15", +    description   = "OpenType layout system.", +    author        = "Elie Roux & Hans Hagen", +    copyright     = "Elie Roux", +    license       = "CC0" +} + +local luatexbase = luatexbase + +local type, next       = type, next +local stringfind       = string.find +local stringsub        = string.sub +local stringmatch      = string.match +local find_file        = kpse.find_file + +local add_to_callback, create_callback = +      luatexbase.add_to_callback, luatexbase.create_callback +local reset_callback, call_callback = +      luatexbase.reset_callback, luatexbase.call_callback + +local dummy_function = function () end + +_G.luaotfload     = _G.luaotfload or { } +local luaotfload  = _G.luaotfload + +--[[doc-- +No final decision has been made on how to handle font definition.  At +the moment, there are three candidates: The \identifier{generic} +callback as hard-coded in the font loader, the \identifier{old} +wrapper, and a simplified version of the latter (\identifier{patch}) +that does nothing besides applying font patches. +--doc]]-- + +luaotfload.font_definer = "patch" --- | “generic” | “old” + +local error, warning, info, log = +    luatexbase.provides_module(luaotfload.module) + +--[[doc-- +This is a necessary initalization in order not to rebuild an existing +font. +Maybe 600 should be replaced by \texmacro{pdfpkresolution} %% (why?) +or \luafunction{texconfig.pk_dpi} (and it should be replaced +dynamically), but we don't have access (yet) to the +\identifier{texconfig} table, so we let it be 600. +Anyway, it does still work fine even if \texmacro{pdfpkresolution} is +changed. +--doc]]-- + +kpse.init_prog("", 600, "/") + +--[[doc-- +We set the minimum version requirement for \LUATEX to v0.74, as it was +the first version to include version 5.2 of the \LUA interpreter. +--doc]]-- + +local luatex_version = 74 + +if tex.luatexversion < luatex_version then +    warning("LuaTeX v%.2f is old, v%.2f is recommended.", +             tex.luatexversion/100, +             luatex_version   /100) +end + +--[[doc-- +\subsection{Module loading} + +We load the files imported from \CONTEXT with this function. +It automatically prepends the prefix \fileent{otfl-} to its argument, +so we can refer to the files with their actual \CONTEXT name. +--doc]]-- + +local fl_prefix = "otfl" -- “luatex” for luatex-plain +local loadmodule = function (name) +    local tofind = fl_prefix .."-"..name +    local found = find_file(tofind,"tex") +    if found then +        log("loading file %s.", found) +        dofile(found) +    else +        error("file %s not found.", tofind) +    end +end + +--[[doc-- +Virtual fonts are resolved via a callback. +\luafunction{find_vf_file} derives the name of the virtual font file +from the filename. +(NB: \CONTEXT handles this likewise in \fileent{font-vf.lua}.) +--doc]]-- +local Cs, P, lpegmatch = lpeg.Cs, lpeg.P, lpeg.match + +local p_dot, p_slash = P".",  P"/" +local p_suffix       = (p_dot * (1 - p_dot - p_slash)^1 * P(-1)) / "" +local p_removesuffix = Cs((p_suffix + 1)^1) + +local find_vf_file = function (name) +    local fullname = find_file(name, "ovf") +    if not fullname then +        --fullname = find_file(file.removesuffix(name), "ovf") +        fullname = find_file(lpegmatch(p_removesuffix, name), "ovf") +    end +    if fullname then +        log("loading virtual font file %s.", fullname) +    end +    return fullname +end + +--[[doc-- + +\subsection{Preparing the Font Loader} +We treat the fontloader as a black box so behavior is consistent +between formats. +The wrapper file is \fileent{otfl-fonts.lua} which we imported from +\href{http://standalone.contextgarden.net/current/context/experimental/tex/generic/context/luatex/}{\LUATEX-Plain}. +It has roughly two purposes: + +\begin{enumerate} + +   \item insert the functionality required for fontloader; and + +   \item put it in place via the respective callbacks. + +\end{enumerate} + +How the first step is executed depends on the presence on the +\emphasis{merged font loader code}. +In \identifier{luaotfload} this is contained in the file +\fileent{otfl-fonts-merged.lua}. +If this file cannot be found,  the original libraries from \CONTEXT of +which the merged code was composed are loaded instead. + +Hans provides two global tables to control the font loader: + +  \begin{itemize} +    \item  \luafunction{generic_context}: +           encapsulation mechanism, callback functions +    \item  \luafunction{non generic_context}: +           customized code insertion +  \end{itemize} + + +With \luafunction{non_generic_context} we can tailor the font loader +insertion to our file naming habits (key \luafunction{load_before}). +Additionally, \luafunction{skip_loading} can be unset to force loading +of the original libraries as though the merged code was absent. +Another key, \luafunction{load_after} is called at the time when the +font loader is actually inserted. +In combination with the option \luafunction{no_callbacks_yet} in +\luafunction{generic_context}, we can insert our own, +\identifier{luatexbase}-style callback handling here. +--doc]]-- +if not _G.    generic_context then _G.    generic_context = { } end +if not _G.non_generic_context then _G.non_generic_context = { } end + +local     generic_context =    generic_context +local non_generic_context =non_generic_context + +generic_context.no_callbacks_yet = true + +_G.non_generic_context = { luatex_fonts = { +        load_before     = "otfl-fonts-merged.lua", +        -- load_after      = nil, --- TODO, this is meant for callbacks +        skip_loading    = true, +}} + +--[[doc-- +The imported font loader will call \luafunction{callback.register} once +while reading \fileent{font-def.lua}. +This is unavoidable unless we modify the imported files, but harmless +if we make it call a dummy instead. +--doc]]-- + +local trapped_register = callback.register +callback.register      = dummy_function + +--[[doc-- +Now that things are sorted out we can finally load the fontloader. +--doc]]-- + +loadmodule"fonts.lua" + +--[[doc-- +By default, the fontloader requires a number of \emphasis{private +attributes} for internal use. +These must be kept consistent with the attribute handling methods as +provided by \identifier{luatexbase}. +Our strategy is to override the function that allocates new attributes +before we initialize the font loader, making it a wrapper around +\luafunction{luatexbase.new_attribute}.\footnote{% +    Many thanks, again, to Hans Hagen for making this part +    configurable! +} +The attribute identifiers are prefixed “\fileent{otfl@}” to +avoid name clashes. +--doc]]-- + +do +    local new_attribute = luatexbase.new_attribute +    local the_attributes = luatexbase.attributes + +    _G.attributes = _G.attributes or { } + +    _G.attributes.private = function (name) +        local attr   = "otfl@" .. name +        local number = the_attributes[attr] +        if not number then +            number = new_attribute(attr) +        end +        return number +    end +end + +--[[doc-- + +\subsection{Callbacks} + +After the fontloader is ready we can restore the callback trap from +\identifier{luatexbase}. +--doc]]-- + +callback.register = trapped_register + +--[[doc-- +We do our own callback handling with the means provided by luatexbase. + +Note: \luafunction{pre_linebreak_filter} and \luafunction{hpack_filter} +are coupled in \CONTEXT in the concept of \emphasis{node processor}. +--doc]]-- + +add_to_callback("pre_linebreak_filter", +                generic_context.callback_pre_linebreak_filter, +                "luaotfload.node_processor", +                1) +add_to_callback("hpack_filter", +                generic_context.callback_hpack_filter, +                "luaotfload.node_processor", +                1) +add_to_callback("find_vf_file", +                find_vf_file, "luaotfload.find_vf_file") + +loadmodule"font-otc.lua"   -- TODO check what we can drop from otfl-features +loadmodule"lib-dir.lua"    -- required by font-nms +loadmodule"luat-ovr.lua" + +if fonts and fonts.readers.tfm then +  -------------------------------------------------------------------- +  --- OFM; read this first +  -------------------------------------------------------------------- +  --- I can’t quite make out whether this is still relevant +  --- as those ofm fonts always fail, even in the 2011 version +  --- (mktexpk:  don't know how to create bitmap font for omarabb.ofm) +  --- the font loader appears to read ofm like tfm so if this +  --- hack was supposed achieve that, we should excise it anyways +  fonts.readers.ofm  = fonts.readers.tfm +  fonts.handlers.ofm = fonts.handlers.tfm --- empty anyways +  fonts.formats.ofm  = fonts.formats.tfm  --- “type1” +  --- fonts.readers.sequence[#fonts.readers.sequence+1] = "ofm" +  -------------------------------------------------------------------- +end + +--[[doc-- + +Now we load the modules written for \identifier{luaotfload}. + +--doc]]-- +loadmodule"font-pfb.lua"    --- new in 2.0, added 2011 +loadmodule"font-nms.lua" +loadmodule"font-clr.lua" +loadmodule"font-ltx.lua"    --- new in 2.0, added 2011 + +--[[doc-- + +We create a callback for patching fonts on the fly, to be used by other +packages. +It initially contains the empty function that we are going to override +below. + +--doc]]-- + +create_callback("luaotfload.patch_font", "simple", dummy_function) + +--[[doc-- + +This is a wrapper for the imported font loader. +As of 2013, everything it does appear to be redundand, so we won’t use +it unless somebody points out a cogent reason. +Nevertheless, it has been adapted to work with the current structure of +font data objects and will stay here for reference / until breakage is +reported. + +\emphasis{TODO} +This one also enables patching fonts. +The current fontloader apparently comes with a dedicated mechanism for +that already: enhancers. +How those work remains to be figured out. + +--doc]]-- +local define_font_wrapper = function (...) +    --- we use “tfmdata” (not “fontdata”) for consistency with the +    --- font loader +    local tfmdata = fonts.definers.read(...) +    if type(tfmdata) == "table" and tfmdata.shared then +        local metadata = tfmdata.shared.rawdata.metadata +        local mathdata = metadata.math --- do all fonts have this field? +        if mathdata then +            local mathconstants = { } --- why new hash, not modify in place? +            local units_per_em  = metadata.units_per_em +            local size          = tfmdata.size +            for k,v in next, mathdata do +                --- afaics this is alread taken care of by +                --- definers.read +                if stringfind(k, "Percent") then +                    -- keep percent values as is +                    print(k,v) +                    mathconstants[k] = v +                else +                    mathconstants[k] = v / units_per_em * size +                end +            end +            --- for \overwithdelims +            --- done by definers.read as well +            mathconstants.FractionDelimiterSize             = 1.01 * size +            --- fontloader has 2.4 × size +            mathconstants.FractionDelimiterDisplayStyleSize = 2.39 * size +            tfmdata.MathConstants = mathconstants +        end +        call_callback("luaotfload.patch_font", tfmdata) +    end +    return tfmdata +end + +--[[doc-- + +\subsection{\CONTEXT override} + +We provide a simplified version of the original font definition +callback. + +--doc]]-- + +local read_font_file = fonts.definers.read +local patch_defined_font = function (...) +    local tfmdata = read_font_file(...)-- spec -> size -> id -> tmfdata +    if type(tfmdata) == "table" then +        call_callback("luaotfload.patch_font", tfmdata) +    end +    -- inspect(table.keys(tfmdata))  +    return tfmdata +end + +caches.compilemethod = "both" + +reset_callback("define_font") + +--[[doc-- +Finally we register the callbacks +--doc]]-- + +if luaotfload.font_definer == "old"  then +  add_to_callback("define_font", +                  define_font_wrapper, +                  "luaotfload.define_font", +                  1) +elseif luaotfload.font_definer == "generic"  then +  add_to_callback("define_font", +                  generic_context.callback_define_font, +                  "luaotfload.define_font", +                  1) +elseif luaotfload.font_definer == "patch"  then +  add_to_callback("define_font", +                  patch_defined_font, +                  "luaotfload.define_font", +                  1) +end + +--[[todo-- +--- The manual promises coercion of the file: lookup if +--- the asked name is enclosed in brackets. +--- A couple things make me doubt that this is the case: +--- +---     1) there doesn’t appear to be code for these cases +---     2) the brackets remain part of the file name +---     3) we still get calls to names.resolve which +---        ignores the “lookup” field of the spec it gets +--- +--- For this reason here is some code that a) coerces +--- file: lookups in these cases and b) strips the brackets +--- from the file name. As we *still* get name: lookups even +--- though this code is active I’ll just leave it here +--- for reference, ineffective as it is. +do +    local getspecification, makespecification = +        fonts.definers.getspecification, fonts.definers.makespecification + +    local analyze = function (specification, size) +        local lookup, name, sub, method, detail = getspecification(specification or "") +        local filename = stringmatch(name, "^%[(.*)%]$") +        if filename then +            lookup   = "file"    --> coerce file: +            name     = filename  --> remove brackets +        end +        return makespecification(specification, lookup, name, sub, method, detail, size) +    end +    fonts.definers.analyze = analyze +end +--]]-- + +loadmodule"features.lua" + +-- vim:tw=71:sw=4:ts=4:expandtab diff --git a/mkluatexfontdb.lua b/mkluatexfontdb.lua index e7796db..776fbb3 100755 --- a/mkluatexfontdb.lua +++ b/mkluatexfontdb.lua @@ -11,6 +11,8 @@ kpse.set_program_name"luatex"  local stringformat  = string.format  local texiowrite_nl = texio.write_nl +local stringfind    = string.find +local stringlower   = string.lower  -- First we need to be able to load module (code copied from  -- luatexbase-loader.sty): @@ -21,11 +23,49 @@ local loader_path = assert(kpse.find_file(loader_file, "lua"),  --texiowrite_nl("("..loader_path..")")  dofile(loader_path) -- FIXME this pollutes stdout with filenames -_G.config      = _G.config or { } -local config   = _G.config +--[[doc-- +Depending on how the script is called we change its behavior. +For backwards compatibility, moving or symlinking the script to a +file name starting with \fileent{mkluatexfontdb} will cause it to +trigger a database update on every run. +Running as \fileent{fontdbutil} -- the new name -- will do this upon +request only. + +There are two naming conventions followed here: firstly that of +utilities such as \fileent{mktexpk}, \fileent{mktexlsr} and the likes, +and secondly that of \fileent{fmtutil}. +After support for querying the database was added, the latter appeared +to be the more appropriate. +--doc]]-- + +config              = config or { } +local config        = config +config.luaotfload   = config.luaotfload or { } + +do -- we don’t have file.basename and the likes yet, so inline parser ftw +    local C, P         = lpeg.C, lpeg.P +    local lpegmatch    = lpeg.match +    local slash        = P"/" +    local dot          = P"." +    local noslash      = 1 - slash +    local slashes      = slash^1 +    local path         =  slashes^-1 * (noslash^1 * slashes)^1 +    local thename      = (1 - slash - dot)^1 +    local extension    = dot * (1 - slash - dot)^1 +    local p_basename   = path^-1 * C(thename) * extension^-1 * P(-1) + +    -- if stringfind(stringlower(arg[0]), "^fontdbutil") then   +    local self = lpegmatch(p_basename, stringlower(arg[0])) +    if self == "fontdbutil" then +        config.luaotfload.self = "fontdbutil" +    else +        config.luaotfload.self = "mkluatexfontdb" +    end +end  config.lualibs                  = config.lualibs or { } -config.lualibs.prefer_merged    = false +config.lualibs.verbose          = false +config.lualibs.prefer_merged    = true  config.lualibs.load_extended    = false  require"lualibs" @@ -34,29 +74,42 @@ require"otfl-luat-ovr.lua"  --- this populates the logs.* namespace  require"otfl-font-nms"  require"alt_getopt" -local name    = "mkluatexfontdb"  local version = "2.2" -- same version number as luaotfload  local names    = fonts.names  local db_src_out = names.path.dir.."/"..names.path.basename  local db_bin_out = file.replacesuffix(db_src_out, "luc") -local function help_msg() -    texiowrite_nl(stringformat([[ + +local help_messages = { +    fontdbutil = [[  Usage: %s [OPTION]... -Rebuild the LuaTeX font database. +Operations on the LuaTeX font database. + +This tool is part of the luaotfload package. Valid options are: + +------------------------------------------------------------------------------- +                             VERBOSITY AND LOGGING -Valid options: -  -f --force                   force re-indexing all fonts    -q --quiet                   don't output anything    -v --verbose=LEVEL           be more verbose (print the searched directories)    -vv                          print the loaded fonts    -vvv                         print all steps of directory searching    -V --version                 print version and exit    -h --help                    print this message + +------------------------------------------------------------------------------- +                                   DATABASE + +  -u --update                  update the database +  -f --force                   force re-indexing all fonts +    --find="font name"           query the database for a font name    -F --fuzzy                   look for approximate matches if --find fails +  --limit=n                    limit display of fuzzy matches to <n> +                               (default: n = 1) +  -i --info                    display font metadata    --log=stdout                 redirect log output to stdout @@ -64,13 +117,70 @@ The font database will be saved to     %s     %s -]], name, db_src_out, db_bin_out)) +]], +    mkluatexfontdb = [[ + +Usage: %s [OPTION]... +     +Rebuild the LuaTeX font database. + +Valid options: +  -f --force                   force re-indexing all fonts +  -q --quiet                   don't output anything +  -v --verbose=LEVEL           be more verbose (print the searched directories) +  -vv                          print the loaded fonts +  -vvv                         print all steps of directory searching +  -V --version                 print version and exit +  -h --help                    print this message + +The font database will be saved to +   %s +   %s + +]], +} + +local help_msg = function ( ) +    local template = help_messages[config.luaotfload.self] +                  or help.messages.fontdbutil +    texiowrite_nl(stringformat(template, config.luaotfload.self, db_src_out, db_bin_out))  end -local function version_msg() +local version_msg = function ( )      texiowrite_nl(stringformat(          "%s version %s, database version %s.\n", -        name, version, names.version)) +        config.luaotfload.self, version, names.version)) +end + +local show_info_items = function (fontinfo) +    local items    = table.sortedkeys(fontinfo) +    for n = 1, #items do +        local item = items[n] +        texiowrite_nl(stringformat( +            [[  %11s:  %s]], item, fontinfo[item])) +    end +end + +local show_font_info = function (filename) +    local fullname = resolvers.findfile(filename) +    if fullname then +        local fontinfo = fontloader.info(fullname) +        local nfonts   = #fontinfo +        if nfonts > 0 then -- true type collection +            logs.names_report(true, 0, "resolve", +                [[%s is a font collection]], filename) +            for n = 1, nfonts do +                logs.names_report(true, 0, "resolve", +                    [[showing info for font no. %d]], n) +                show_info_items(fontinfo[n]) +            end +        else +            show_info_items(fontinfo) +        end +    else +        logs.names_report(true, 0, "resolve", +            "font %s not found", filename) +    end  end  --[[-- @@ -79,17 +189,19 @@ executed in the correct order. To avoid duplication we track them in a  set.  --]]-- -local action_sequence = { "loglevel", "help", "version", "generate", "query" } +local action_sequence = { +    "loglevel", "help", "version", "generate", "query" +}  local action_pending  = table.tohash(action_sequence, false) -action_pending.loglevel = true --- always set the loglevel -action_pending.generate = true --- this is the default action +action_pending.loglevel = true  --- always set the loglevel +action_pending.generate = false --- this is the default action  local actions = { } --- (jobspec -> (bool * bool)) list  actions.loglevel = function (job)      logs.set_loglevel(job.log_level) -    logs.names_report("log", 2, +    logs.names_report("log", 2, "util",                        "setting log level", "%d", job.log_level)      return true, true  end @@ -107,8 +219,8 @@ end  actions.generate = function (job)      local fontnames, savedname      fontnames = names.update(fontnames, job.force_reload) -    logs.names_report("log", 0, "fonts in the database", -                      "%i", #fontnames.mappings) +    logs.names_report("log", 0, "db", +        "fonts in the database", "%i", #fontnames.mappings)      savedname = names.save(fontnames)      if savedname then --- FIXME have names.save return bool          return true, true @@ -134,6 +246,9 @@ actions.query = function (job)              "resolve", "Font “%s” found!", query)          logs.names_report(false, 0,              "resolve", "Resolved file name “%s”:", foundname) +        if job.show_info then +            show_font_info(foundname) +        end      else          logs.names_report(false, 0,              "resolve", "Cannot find “%s”.", query) @@ -163,19 +278,25 @@ local process_cmdline = function ( ) -- unit -> jobspec          log_level    = 1,      } +    if config.luaotfload.self == "mkluatexfontdb" then +        action_pending["generate"] = true +    end +      local long_options = { +        find             = 1,          force            = "f", +        fuzzy            = "F",          help             = "h", +        info             = "i", +        limit            = 1,          log              = 1,          quiet            = "q", +        update           = "u",          verbose          = 1  ,          version          = "V", -        find             = 1, -        fuzzy            = "F", -        limit            = 1,      } -    local short_options = "fFqvVh" +    local short_options = "fFiquvVh"      local options, _, optarg =          alt_getopt.get_ordered_opts (arg, short_options, long_options) @@ -185,6 +306,8 @@ local process_cmdline = function ( ) -- unit -> jobspec          local v = options[n]          if     v == "q" then              result.log_level = 0 +        elseif v == "u" then +            action_pending["generate"] = true          elseif v == "v" then              if result.log_level > 0 then                  result.log_level = result.log_level + 1 @@ -196,6 +319,7 @@ local process_cmdline = function ( ) -- unit -> jobspec          elseif v == "h" then              action_pending["help"] = true          elseif v == "f" then +            result.update       = true              result.force_reload = 1          elseif v == "verbose" then              local lvl = optarg[n] @@ -217,6 +341,8 @@ local process_cmdline = function ( ) -- unit -> jobspec              if lim then                  result.fuzzy_limit = tonumber(lim)              end +        elseif v == "i" then +            result.show_info = true          end      end      return result @@ -233,24 +359,24 @@ local main = function ( ) -- unit -> int          local actionname = action_sequence[i]          local exit       = false          if action_pending[actionname] then -            logs.names_report("log", 3, "preparing for task", +            logs.names_report("log", 3, "util", "preparing for task",                                "%s", actionname)              local action             = actions[actionname]              local success, continue  = action(job)              if not success then -                logs.names_report(false, 0, "could not finish task", -                                  "%s", actionname) +                logs.names_report(false, 0, "util", +                    "could not finish task", "%s", actionname)                  retval = -1                  exit   = true              elseif not continue then -                logs.names_report(false, 3, "task completed, exiting", -                                  "%s", actionname) +                logs.names_report(false, 3, "util", +                    "task completed, exiting", "%s", actionname)                  exit   = true              else -                logs.names_report(false, 3, "task completed successfully", -                                  "%s", actionname) +                logs.names_report(false, 3, "util", +                    "task completed successfully", "%s", actionname)              end          end          if exit then break end diff --git a/otfl-font-nms.lua b/otfl-font-nms.lua index 2e54028..cec2a54 100644 --- a/otfl-font-nms.lua +++ b/otfl-font-nms.lua @@ -21,6 +21,9 @@ local tonumber                = tonumber  local iolines                 = io.lines  local ioopen                  = io.open  local kpseexpand_path         = kpse.expand_path +local kpseexpand_var          = kpse.expand_var +local kpselookup              = kpse.lookup +local kpsereadable_file       = kpse.readable_file  local mathabs                 = math.abs  local mathmin                 = math.min  local stringfind              = string.find @@ -40,10 +43,11 @@ local utf8lower               = unicode.utf8.lower  --- these come from Lualibs/Context  local dirglob                 = dir.glob -local dirmkdirs               = dir.mkdirds +local dirmkdirs               = dir.mkdirs  local filebasename            = file.basename  local filecollapsepath        = file.collapsepath  local fileextname             = file.extname +local fileiswritable          = file.iswritable  local filejoin                = file.join  local filereplacesuffix       = file.replacesuffix  local filesplitpath           = file.splitpath @@ -180,15 +184,15 @@ load_names = function ( )      local foundname, data = load_lua_file(names.path.path)      if data then -        report("info", 0, "Font names database loaded", "%s", foundname) +        report("info", 1, "db", +            "Font names database loaded", "%s", foundname)      else -        report("info", 0, +        report("info", 0, "db",              [[Font names database not found, generating new one.               This can take several minutes; please be patient.]])          data = update_names(fontnames_init())          save_names(data)      end -    texiowrite_nl""      return data  end @@ -251,7 +255,7 @@ font database created by the mkluatexfontdb script.  ---  --- the return value of “resolve” is the file name of the requested  --- font ----  +---  --- 'a -> 'a -> table -> (string * string | bool * bool)  ---  ---     note by phg: I added a third return value that indicates a @@ -358,8 +362,8 @@ resolve = function (_,_,specification) -- the 1st two parameters are used by Con                  end              end              if #found == 1 then -                if kpse.lookup(found[1].filename[1]) then -                    report("log", 0, "load font", +                if kpselookup(found[1].filename[1]) then +                    report("log", 0, "resolve",                          "font family='%s', subfamily='%s' found: %s",                          name, style, found[1].filename[1]                      ) @@ -379,8 +383,8 @@ resolve = function (_,_,specification) -- the 1st two parameters are used by Con                          least   = difference                      end                  end -                if kpse.lookup(closest.filename[1]) then -                    report("log", 0, "load font", +                if kpselookup(closest.filename[1]) then +                    report("log", 0, "resolve",                          "font family='%s', subfamily='%s' found: %s",                          name, style, closest.filename[1]                      ) @@ -396,7 +400,7 @@ resolve = function (_,_,specification) -- the 1st two parameters are used by Con              else                  --- else, fallback to requested name                  --- specification.name is empty with absolute paths, looks -                --- like a bug in the specification parser << is it still +                --- like a bug in the specification parser <TODO< is it still                  --- relevant? looks not...                  return specification.name, false, false              end @@ -569,7 +573,7 @@ font_fullinfo = function (filename, subfont, texmf)          end      else          -- no names table, propably a broken font -        report("log", 1, "broken font rejected", "%s", basefile) +        report("log", 1, "db", "broken font rejected", "%s", basefile)          return      end      tfmdata.fontname    = metadata.fontname @@ -601,7 +605,7 @@ local load_font = function (filename, fontnames, newfontnames, texmf)      if filename then          if names.blacklist[filename] or             names.blacklist[basename] then -            report("log", 2, "ignoring font", "%s", filename) +            report("log", 2, "db", "ignoring font", "%s", filename)              return          end          local timestamp, db_timestamp @@ -624,7 +628,7 @@ local load_font = function (filename, fontnames, newfontnames, texmf)                  newmappings[#newmappings+1]        = mappings[v]                  newstatus[basefile].index[index+1] = #newmappings              end -            report("log", 1, "font already indexed", "%s", basefile) +            report("log", 1, "db", "font already indexed", "%s", basefile)              return          end          local info = fontloader.info(filename) @@ -659,7 +663,7 @@ local load_font = function (filename, fontnames, newfontnames, texmf)                  newstatus[basefile].index[1] = index              end          else -            report("log", 1, "failed to load", "%s", basefile) +            report("log", 1, "db", "failed to load", "%s", basefile)          end      end  end @@ -681,9 +685,9 @@ local function path_normalize(path)      if os.type ~= "windows" and os.type ~= "msdos" then          local dest = lfs.readlink(path)          if dest then -            if kpse.readable_file(dest) then +            if kpsereadable_file(dest) then                  path = dest -            elseif kpse.readable_file(filejoin(file.dirname(path), dest)) then +            elseif kpsereadable_file(filejoin(file.dirname(path), dest)) then                  path = filejoin(file.dirname(path), dest)              else                  -- broken symlink? @@ -700,7 +704,7 @@ names.blacklist = { }  local function read_blacklist()      local files = { -        kpse.lookup("otfl-blacklist.cnf", {all=true, format="tex"}) +        kpselookup("otfl-blacklist.cnf", {all=true, format="tex"})      }      local blacklist = names.blacklist      local whitelist = { } @@ -719,7 +723,7 @@ local function read_blacklist()                      if stringsub(line, 1, 1) == "-" then                          whitelist[stringsub(line, 2, -1)] = true                      else -                        report("log", 2, "blacklisted file", "%s", line) +                        report("log", 2, "db", "blacklisted file", "%s", line)                          blacklist[line] = true                      end                  end @@ -776,22 +780,25 @@ local function scan_dir(dirname, fontnames, newfontnames, texmf)      ]]      local list, found = { }, { }      local nbfound = 0 -    report("log", 2, "scanning", "%s", dirname) +    report("log", 2, "db", "scanning", "%s", dirname)      for _,i in next, font_extensions do          for _,ext in next, { i, stringupper(i) } do              found = dirglob(stringformat("%s/**.%s$", dirname, ext))              -- note that glob fails silently on broken symlinks, which happens              -- sometimes in TeX Live. -            report("log", 2, "fonts found", "%s '%s' fonts found", #found, ext) +            report("log", 2, "db", +                "fonts found", "%s '%s' fonts found", #found, ext)              nbfound = nbfound + #found              tableappend(list, found)          end      end -    report("log", 2, "fonts found", "%d fonts found in '%s'", nbfound, dirname) +    report("log", 2, "db", +        "fonts found", "%d fonts found in '%s'", nbfound, dirname)      for _,file in next, list do          file = path_normalize(file) -        report("log", 1, "loading font", "%s", file) +        report("log", 1, "db", +            "loading font", "%s", file)          load_font(file, fontnames, newfontnames, texmf)      end  end @@ -802,9 +809,9 @@ local function scan_texmf_fonts(fontnames, newfontnames)      variables OPENTYPEFONTS and TTFONTS of texmf.cnf      ]]      if stringis_empty(kpseexpand_path("$OSFONTDIR")) then -        report("info", 0, "Scanning TEXMF fonts...") +        report("info", 1, "db", "Scanning TEXMF fonts...")      else -        report("info", 0, "Scanning TEXMF and OS fonts...") +        report("info", 1, "db", "Scanning TEXMF and OS fonts...")      end      local fontdirs = stringgsub(kpseexpand_path("$OPENTYPEFONTS"), "^%.", "")      fontdirs       = fontdirs .. stringgsub(kpseexpand_path("$TTFONTS"), "^%.", "") @@ -844,7 +851,7 @@ read_fonts_conf = function (path, results, passed_paths)      passed_paths[#passed_paths+1] = path      passed_paths_set = tabletohash(passed_paths, true)      if not fh then -        report("log", 2, "cannot open file", "%s", path) +        report("log", 2, "db", "cannot open file", "%s", path)          return results      end      local incomments = false @@ -895,7 +902,7 @@ read_fonts_conf = function (path, results, passed_paths)                          include = filejoin(file.dirname(path), include)                      end                      if      lfs.isfile(include) -                    and     kpse.readable_file(include) +                    and     kpsereadable_file(include)                      and not passed_paths_set[include]                      then                          -- maybe we should prevent loops here? @@ -953,8 +960,8 @@ local function scan_os_fonts(fontnames, newfontnames)        - fontcache for Unix (reads the fonts.conf file and scans the directories)        - a static set of directories for Windows and MacOSX      ]] -    report("info", 0, "Scanning OS fonts...") -    report("info", 2, "Searching in static system directories...") +    report("info", 1, "db", "Scanning OS fonts...") +    report("info", 2, "db", "Searching in static system directories...")      for _,d in next, get_os_dirs() do          scan_dir(d, fontnames, newfontnames, false)      end @@ -966,7 +973,7 @@ update_names = function (fontnames, force)      - fontnames is the final table to return      - force is whether we rebuild it from scratch or not      ]] -    report("info", 0, "Updating the font names database") +    report("info", 1, "db", "Updating the font names database")      if force then          fontnames = fontnames_init() @@ -976,8 +983,8 @@ update_names = function (fontnames, force)          end          if fontnames.version ~= names.version then              fontnames = fontnames_init() -            report("log", 0, "No font names database or old one found; " -                           .."generating new one") +            report("log", 1, "db", "No font names database or old " +                                .. "one found; generating new one")          end      end      local newfontnames = fontnames_init() @@ -1000,14 +1007,14 @@ save_names = function (fontnames)          dirmkdirs(path)      end      path = filejoin(path, names.path.basename) -    if file.iswritable(path) then +    if fileiswritable(path) then          local luaname, lucname = make_name(path)          tabletofile(luaname, fontnames, true)          caches.compile(fontnames,luaname,lucname) -        report("info", 0, "Font names database saved") +        report("info", 0, "db", "Font names database saved")          return path      else -        report("info", 0, "Failed to save names database") +        report("info", 0, "db", "Failed to save names database")          return nil      end  end | 
