diff options
Diffstat (limited to 'macros/luatex/generic')
46 files changed, 6883 insertions, 3819 deletions
diff --git a/macros/luatex/generic/luamplib/Makefile b/macros/luatex/generic/luamplib/Makefile index f4d638764e..a0a2282675 100644 --- a/macros/luatex/generic/luamplib/Makefile +++ b/macros/luatex/generic/luamplib/Makefile @@ -26,6 +26,8 @@ CTAN_ZIP = $(NAME).zip TDS_ZIP = $(NAME).tds.zip ZIPS = $(CTAN_ZIP) $(TDS_ZIP) +DOLATEX = texfot --quiet --tee=/dev/null --ignore "hypdoc" --ignore "^Overfull" --ignore "^Underfull" lualatex -recorder $(DTX) + all: $(GENERATED) doc: $(DOC) unpack: $(UNPACKED) @@ -36,7 +38,9 @@ world: all ctan .PHONY: all doc unpack ctan tds check world %.pdf: %.dtx - latexmk -lualatex -recorder- -silent $< >/dev/null + @$(DOLATEX) + @if( grep rerunfilecheck $(NAME).log |grep 'has changed' > /dev/null ); then $(DOLATEX); fi + @if( grep 'Rerun to get' $(NAME).log > /dev/null ); then $(DOLATEX); fi $(UNPACKED): $(DTX) luatex -interaction=batchmode $< >/dev/null diff --git a/macros/luatex/generic/luamplib/NEWS b/macros/luatex/generic/luamplib/NEWS index f0dd1cf2f4..1e4fcf9520 100644 --- a/macros/luatex/generic/luamplib/NEWS +++ b/macros/luatex/generic/luamplib/NEWS @@ -1,5 +1,161 @@ History of the luamplib package +2024/07/27 2.34.3 + * in DVI mode, use LaTeX's shipout hooks to generate new XObjects + or to put resources to pageresources. (in plain, load atbegshi.sty) + + * fix shading to allow the even-odd rule + +2024/07/24 2.34.2 + * With the newly introduced macros, \mplibgroup ... \endmplibgroup, users + can define a transparency group or a normal form XObject from TeX side. + The LaTeX environment 'mplibgroup' is identical to this pair of macros. + See the document for details. + + * document: be more precise about the color effect of a transparency group + + * remove trailing zeros from numeric objects to get smaller PDF + +2024/07/19 2.34.1 + * transparency group is available with plain format as well. + * transparency group once used is reusable in the TeX code or + in other MetaPost code chunks. see the document for details. + +2024/07/17 2.34.0 + * support transparency group with metafun format + * fix regarding default value in circular fading mode + * fix regarging the scope of graphics state + +2024/07/14 2.33.1 + * refactor the manual, including some minor items undocumented so far + * improve fading routine to get possibly smaller pdf file + +2024/07/08 2.33.0 + * provide a new metapost operator 'withfademethod' and related macros, + which make the color of an object gradiently transparent. see luamplib + document for details. + + * fix spot-color shading routine to support user-defined colorspace + +2024/07/03 2.32.4 + * make the variable 'patterns' local + * 'math.randomseed' on plain TeX + * remove redundant code 'fullcircle scaled 0' + +2024/06/21 2.32.3 + * 'coloured' is a synonym of the option 'colored' in pattern definition. + + * fix a bug related to pdf page resources in dvi mode + + * users can access the lua table containing mplib instances 'luamplib.instances', + through which metapost variables are also easily accessible as documented in + LuaTeX manual 11.2.8.4. + +2024/06/14 2.32.2 + * fix matrix conversion between MP and PDF + +2024/06/13 2.32.1 + * for the sake of convenience, width and height values of tiling patterns + will be written down into the log file. + + * table type is allowed as well as string type for 'matrix' and 'bbox' + options in pattern definition. + + * metapost code such as 'rotated 30 slanted .2' is allowed as well as the + string or table of numbers for the 'matrix' option in pattern definition. + + * as for the 'resources' option in pattern definition, luamplib + automatically includes the resources of the current page. + + * luamplib does not log info even if there's no beginfig ... endfig. + +2024/06/10 2.32.0 + * \mppattern{<name>} ... \endmppattern defines a tiling pattern which can be + used with 'withpattern' operator to fill a closed path by replicating the tile + horizontally and vertically. \begin{mppattern} ... \end{mppattern} is exactly + the same as \mppattern ... \endmppattern. See luamplib manual for details. + +2024/05/30 2.31.2 + * support vertical writing mode in mpliboutlinetext (presently luatexko + package only, and except horizontal mode inside vertical mode) + + * after the process of mpliboutlinetext, mpliboutlinepic[1] ... + mpliboutlinepic[mpliboutlinenum] will be preserved as an array of images + each of which containing a glyph or a rule. N.B. Unicode grapheme cluster + is not considered here. + +2024/05/24 2.31.1 + * fix bugs in outlinetext routine + * improve rule treatment in graphictext + +2024/05/21 2.31.0 + * provide a new metapost operator 'mpliboutlinetext', which mimicks + metafun's 'outlinetext'. The syntax is the same as metafun's. (#133) + +2024/05/10 2.30.0 + * provide a new metapost operator 'mplibglyph', which returns a metapost + picture containing outline paths of a glyph in opentype, truetype or type1 + fonts. When a type1 font is specified, metapost primitive 'glyph' will be + called. In the syntax as follows, subfont number is zero based. + + mplibglyph 50 of \fontid\font % slot 50 of current font + mplibglyph 50 of "cmr10" % type1 font + mplibglyph "Q" of "TU/TeXGyrePagella(0)/m/n/10" % font csname + mplibglyph "똠" of "NotoSansCJKkr-Regular.otf" % raw filename + mplibglyph "Q" of "Times.ttc(2)" % subfont number + mplibglyph "똠" of "SourceHanSansK-VF.otf[Regular]" % instance name + + * provide a new metapost command 'mplibdrawglyph'. In contrast to metapost's + 'draw' command, this one fills paths of a picture according to the Nonzero + Winding Number Rule. + + * in 'mplibgraphictext', option 'scale' is deprecated and now a synonym of + 'scaled'. In DVI mode, unicode-math package is needed for math formula + graphictext. + +2024/05/01 2.29.0 + + * provide new TeX macros to reduce typing toil. + + \mpfig ... \endmpfig is roughly the abbreviation of + \begin{mplibcode}[@mpfig] + beginfig(0) + token list declared by \everymplib[@mpfig] + ... + token list declared by \everyendmplib[@mpfig] + endfig; + \end{mplibcode} + + \mpfig* ... \endmpfig is roughly the abbreviation of + \begin{mplibcode}[@mpfig] + ... + \end{mplibcode} + + These macros are protected and unexpandable. + In these macros \mpliblegacybehavior{false} is forcibly declared. + As both share the same instance name, MetaPost codes are inherited among them. + The instance name (default: @mpfig) can be changed by redefining `\mpfiginstancename'. + + * instance names are allowed in plain TeX as well. The syntax is: + + \mplibcode[name] ... \endmplibcode + \everymplib[name]{ ... } + \everyendmplib[name]{ ... } + + These macros are now protected and unexpandable. + + * provide new MetaPost operators `mplibtexcolor' and `mplibrgbtexcolor' + which convert TeX color expressions to MetaPost color expressions. + The latter one forces rgb model results (#112). For instance, + + mplibtexcolor "olive" % => (0, 0, 1, 0.5) + mplibrgbtexcolor "olive" % => (0.5, 0.5, 0) + + As spot colors are always forced to cmyk or rgb model, it is not + recommended to use these operators for them. + + * write down MetaPost messages into the log file + 2024/04/25 2.28.2 * direction of figure box is explicitly declared as TLT (#129) * figure box materials are emitted in one go at the end of the figure @@ -72,11 +228,11 @@ 2024/03/01 2.26.0 * when \mplibcachedir{<dir>} is not set, default cache directory will be in the following order: - $TEXMFVAR/luamplib_cache - $TEXMF_OUTPUT_DIRECTORY/luamplib_cache - ./luamplib_cache - $TEXMFOUTPUT/luamplib_cache - . + $TEXMFVAR/luamplib_cache + $TEXMF_OUTPUT_DIRECTORY/luamplib_cache + ./luamplib_cache + $TEXMFOUTPUT/luamplib_cache + . 2024/01/25 2.25.3 * protect "..." even if textextlabel is disabled (revert part of v2.25.0) diff --git a/macros/luatex/generic/luamplib/luamplib.dtx b/macros/luatex/generic/luamplib/luamplib.dtx index 283120c622..440558a64e 100644 --- a/macros/luatex/generic/luamplib/luamplib.dtx +++ b/macros/luatex/generic/luamplib/luamplib.dtx @@ -2,8 +2,8 @@ % % Copyright (C) 2008-2024 by Hans Hagen, Taco Hoekwater, Elie Roux, % Manuel Pégourié-Gonnard, Philipp Gesang and Kim Dohyun. -% Currently maintained by the LuaLaTeX development team. -% Support: <lualatex-dev@tug.org> +% Currently maintained by Kim Dohyun. +% Support: <https://github.com/lualatex/luamplib> % % This work is under the GPL v2.0 license. % @@ -85,9 +85,9 @@ See source file '\inFileName' for licencing and contact information. %<*driver> \NeedsTeXFormat{LaTeX2e} \ProvidesFile{luamplib.drv}% - [2024/04/25 v2.28.2 Interface for using the mplib library]% + [2024/07/27 v2.34.3 Interface for using the mplib library]% \documentclass{ltxdoc} -\usepackage{metalogo,multicol,mdwlist,fancyvrb,xspace} +\usepackage{metalogo,multicol,xspace} \usepackage[x11names]{xcolor} % \def\primarycolor{DodgerBlue4} %%-> rgb 16 78 139 | #104e8b @@ -112,7 +112,7 @@ See source file '\inFileName' for licencing and contact information. ItalicFont = {Linux Libertine O Italic}, SlantedFont = {Linux Libertine O Italic}, ]{Linux Libertine O} -\setmonofont[Ligatures=TeX,Scale=MatchLowercase]{InconsolataN} +\setmonofont[Scale=MatchLowercase]{InconsolataN} %setsansfont[Ligatures=TeX]{Linux Biolinum O} \setsansfont[Ligatures=TeX,Scale=MatchLowercase]{Iwona Medium} %setmathfont{XITS Math} @@ -123,7 +123,9 @@ See source file '\inFileName' for licencing and contact information. \newcommand*\email [1] {<\href{mailto:#1}{#1}>} \newcommand \file {\nolinkurl} -\newcommand \pk {\textsf} + +\newcommand*\metapost {\textsc{metapost}\xspace} +\newcommand*\mplib {\pkg{mplib}\xspace} \begin{document} \DocInput{luamplib.dtx}% @@ -149,90 +151,164 @@ See source file '\inFileName' for licencing and contact information. % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % -% \title{The \textsf{luamplib} package} +% \title{The \pkg{luamplib} package} % \author{Hans Hagen, Taco Hoekwater, Elie Roux, Philipp Gesang and Kim Dohyun\\ -% Maintainer: LuaLaTeX Maintainers --- -% Support: \email{lualatex-dev@tug.org}} -% \date{2024/04/25 v2.28.2} +% Current Maintainer: Kim Dohyun\\ +% Support: \url{https://github.com/lualatex/luamplib}} +% \date{2024/07/27 v2.34.3} % % \maketitle % % \begin{abstract} -% Package to have metapost code typeset directly in a document with \LuaTeX. +% Package to have \metapost code typeset directly in a document with \LuaTeX. % \end{abstract} % % \section{Documentation} % -% This packages aims at providing a simple way to typeset directly metapost -% code in a document with \LuaTeX. \LuaTeX\ is built with the lua -% \texttt{mplib} library, that runs metapost code. This package is basically a -% wrapper (in Lua) for the Lua \texttt{mplib} functions and some \TeX\ -% functions to have the output of the \texttt{mplib} functions in the pdf. -% -% In the past, -% the package required PDF mode in order to output something. -% Starting with version 2.7 it works in DVI mode as well, though -% DVIPDFMx is the only DVI tool currently supported. +% This package aims at providing a simple way to typeset directly \metapost +% code in a document with \LuaTeX. \LuaTeX\ is built with the Lua +% \mplib library, that runs \metapost code. This package is basically a +% wrapper for the Lua \mplib functions and some \TeX\ +% functions to have the output of the \mplib functions in the pdf. % -% The metapost figures are put in a \TeX\ \texttt{hbox} with dimensions -% adjusted to the metapost code. -% -% Using this package is easy: in Plain, type your metapost code between the +% Using this package is easy: in Plain, type your \metapost code between the % macros \cs{mplibcode} and \cs{endmplibcode}, and in \LaTeX\ in the -% \texttt{mplibcode} environment. +% |mplibcode| environment. +% +% The resulting \metapost figures are put in a \TeX\ |hbox| with dimensions +% adjusted to the \metapost code. % -% The code is from the \texttt{luatex-mplib.lua} and \texttt{luatex-mplib.tex} files -% from \ConTeXt, they have been adapted to \LaTeX\ and Plain by Elie Roux and -% Philipp Gesang, new functionalities have been added by Kim Dohyun. -% The changes are: +% The code of luamplib is basically from the |luatex-mplib.lua| and |luatex-mplib.tex| files +% from \ConTeXt. They have been adapted to \LaTeX\ and Plain by Elie Roux and +% Philipp Gesang and new functionalities have been added by Kim Dohyun. +% The most notable changes are: % % \begin{itemize} -% \item a \LaTeX\ environment -% \item all \TeX\ macros start by |mplib| -% \item use of our own function for errors, warnings and informations % \item possibility to use |btex ... etex| to typeset \TeX\ code. -% |textext()| is a more versatile macro equivalent to |TEX()| from TEX.mp. -% |TEX()| is also allowed and is a synomym of |textext()|.\par\smallskip -% \textsc{n.b.} Since v2.5, |btex ... etex| input from external |mp| files -% will also be processed by \textsf{luamplib}.\par\smallskip -% \textsc{n.b.} Since v2.20, |verbatimtex ... etex| from external |mp| files -% will be also processed by \textsf{luamplib}. Warning: This is a change -% from previous version. +% |textext()| is a more versatile macro equivalent to |TEX()| from \pkg{TEX.mp}. +% |TEX()| is also allowed and is a synonym of |textext()|. +% The argument of +% \mplib's primitive |maketext| will also be processed by the same routine. +% +% \item possibility to use |verbatimtex ... etex|, though it's behavior cannot +% be the same as the stand-alone \pkg{mpost}. +% Of course you cannot include \cs{documentclass}, \cs{usepackage} etc. +% When these \TeX\ commands are found in |verbatimtex ... etex|, the entire code will be +% ignored. +% The treatment of |verbatimtex| command has changed a lot since v2.20: +% see \hyperlink{mpliblegacybehavior}{below \S\,1.1}. +% +% \item in the past, +% the package required PDF mode in order to have some output. +% Starting with version 2.7 it works in DVI mode as well, though +% DVIPDFMx is the only DVI tool currently supported. % \end{itemize} % -% Some more changes and cautions are: +% It seems to be convenient to divide the explanations of some more changes and cautions +% into three parts: \TeX, \textsc{MetaPost}, and Lua interfaces. +% +% \subsection{\TeX} % % \paragraph{\cs{mplibforcehmode}} -% When this macro is declared, every mplibcode figure box will be +% When this macro is declared, every \metapost figure box will be % typeset in horizontal mode, so \cs{centering}, \cs{raggedleft} etc -% will have effects. |\mplibnoforcehmode|, being default, reverts this -% setting. (Actually these commands redefine |\prependtomplibbox|. You -% can define this command with anything suitable before a box.) -% -% \paragraph{\cs{mpliblegacybehavior\{enable\}}} -% By default, |\mpliblegacybehavior{enable}| is already declared, -% in which case -% a |verbatimtex ... etex| that comes just before |beginfig()| -% is not ignored, but the \TeX\ code will be inserted before the -% following mplib hbox. Using this command, -% each mplib box can be freely moved horizontally and/or vertically. -% Also, a box number might be assigned to mplib box, allowing it to be -% reused later (see test files). -% \begin{verbatim} +% will have effects. \cs{mplibnoforcehmode}, being default, reverts this +% setting. (Actually these commands redefine \cs{prependtomplibbox}; you +% can redefine this command with anything suitable before a box.) +% +% \paragraph{\cs{everymplib\{...\}}, \cs{everyendmplib\{...\}}} +% \cs{everymplib} and \cs{everyendmplib} redefine +% the lua table containing \metapost code +% which will +% be automatically inserted at the beginning and ending of each \metapost code chunk. +%\begin{verbatim} +% \everymplib{ beginfig(0); } +% \everyendmplib{ endfig; } +% \begin{mplibcode} +% % beginfig/endfig not needed +% draw fullcircle scaled 1cm; +% \end{mplibcode} +%\end{verbatim} +% +% \paragraph{\cs{mplibsetformat\{plain\textbar metafun\}}} +% There are (basically) two formats for \metapost: \emph{plain} and +% \emph{metafun}. By default, the \emph{plain} format is used, but you can set +% the format to be used by future figures at any time using +% \cs{mplibsetformat\{<format name>\}}. +% +% \textsc{n.b.} As \emph{metafun} is such a complicated format, +% we cannot support all the functionalities producing special effects provided by \emph{metafun}. +% At least, however, transparency (actually opacity), transparency group, and shading (gradient colors) +% are fully supported, +% and outlinetext is supported by our own alternative |mpliboutlinetext| +% (see \hyperlink{mpliboutlinetext}{below \S\,1.2}). +% +% \leavevmode\llap{\textcolor{red}{☞}\kern1.2\parindent}\relax +% Among these, transparency is so simple that you can apply it to an object, +% even with the \emph{plain} format, +% just by appending |withprescript| |"tr_transparency=<number>"| to the sentence. +% ($0 \le \hbox{\emph{<number>}} \le 1$) +% +% \hypertarget{metafunformat}{}\relax +% As for transparency group, the current \emph{metafun} document \S\,8.8 is not correct. +% The true syntax is: +%\begin{verbatim} +% draw <picture>|<path> asgroup <string> +%\end{verbatim} +% where \emph{<string>} should be |""| (empty), |"isolated"|, |"knockout"|, or |"isolated,knockout"|. +% Beware that currently many of the PDF rendering applications, except Adobe Acrobat Reader, +% cannot properly render the isolated or knockout effect. +% Transparency group is available with \emph{plain} format as well, with extended functionality. +% See \hyperlink{transparencygroup}{below \S\,1.2}. +% +% One thing worth mentioning about shading is: +% when a color expression is given in string type, +% it is regarded by luamplib as +% a color expression of \TeX\ side. +% For instance, when |withshadecolors("orange", 2/3red)| is given, the first color |"orange"| will be +% interpreted as a \pkg{color}, \pkg{xcolor} or \pkg{l3color}'s expression. +% +% \paragraph{\cs{mplibnumbersystem\{scaled\textbar double\textbar decimal\}}} +% Users can choose |numbersystem| option. +% The default value is |scaled|, which can be changed +% by declaring \cs{mplibnumbersystem\{double\}} or +% \cs{mplibnumbersystem\{decimal\}}. +% +% \paragraph{\cs{mplibshowlog\{enable\textbar disable\}}} +% Default: |disable|. +% When \cs{mplibshowlog\{enable\}}\footnote{As for user's setting, +% |enable|, |true| and |yes| are identical; +% |disable|, |false| and |no| are identical.} is declared, log messages returned by +% the \metapost process will be printed to the |.log| file. +% This is the \TeX{} side interface for |luamplib.showlog|. +% +% \paragraph{\cs{mpliblegacybehavior\{enable\textbar disable\}}} +% \hypertarget{mpliblegacybehavior}{}\relax +% By default, \cs{mpliblegacybehavior\{enable\}} +% is already declared for backward compatibility, +% in which case \TeX\ code in +% |verbatimtex| |...| |etex| that comes just before |beginfig()| +% will be inserted before the +% following \metapost figure box. In this way, +% each figure box can be freely moved horizontally or vertically. +% Also, a box number can be assigned to a figure box, allowing it to be +% reused later. +%\begin{verbatim} % \mplibcode % verbatimtex \moveright 3cm etex; beginfig(0); ... endfig; % verbatimtex \leavevmode etex; beginfig(1); ... endfig; % verbatimtex \leavevmode\lower 1ex etex; beginfig(2); ... endfig; % verbatimtex \endgraf\moveright 1cm etex; beginfig(3); ... endfig; % \endmplibcode -% \end{verbatim} +%\end{verbatim} % \textsc{n.b.} \cs{endgraf} should be used instead of \cs{par} inside % |verbatimtex ... etex|. % -% By contrast, \TeX\ code in |VerbatimTeX(...)| or |verbatimtex ... etex| +% On the other hand, \TeX\ code in |verbatimtex ... etex| % between |beginfig()| and |endfig| will be inserted -% after flushing out the mplib figure. -% \begin{verbatim} +% after flushing out the \metapost figure. +% As shown in the example below, |VerbatimTeX()| is a synonym of |verbatimtex| |...| |etex|. +%\begin{verbatim} % \mplibcode % D := sqrt(2)**7; % beginfig(0); @@ -241,15 +317,15 @@ See source file '\inFileName' for licencing and contact information. % endfig; % \endmplibcode % diameter: \Dia bp. -% \end{verbatim} +%\end{verbatim} % -% \paragraph{\cs{mpliblegacybehavior\{disable\}}} -% If |\mpliblegacybehavior{disabled}| is declared by user, any -% |verbatimtex ... etex| will be executed, along with |btex ... etex|, +% By contrast, +% when \cs{mpliblegacybehavior\{disable\}} is declared, any +% |verbatimtex| |...| |etex| will be executed, along with |btex| |...| |etex|, % sequentially one by one. % So, some \TeX\ code in |verbatimtex ... etex| will have effects on -% |btex ... etex| codes that follows. -% \begin{verbatim} +% following |btex| |...| |etex| codes. +%\begin{verbatim} % \begin{mplibcode} % beginfig(0); % draw btex ABC etex; @@ -258,113 +334,72 @@ See source file '\inFileName' for licencing and contact information. % draw btex GHI etex shifted (2cm,0); % bold face % endfig; % \end{mplibcode} -% \end{verbatim} +%\end{verbatim} % -% \paragraph{\cs{everymplib}, \cs{everyendmplib}} -% Since v2.3, new macros \cs{everymplib} and \cs{everyendmplib} redefine -% the lua table containing MetaPost code -% which will -% be automatically inserted at the beginning and ending of each |mplibcode|. -% \begin{verbatim} -% \everymplib{ beginfig(0); } -% \everyendmplib{ endfig; } -% \mplibcode % beginfig/endfig not needed -% draw fullcircle scaled 1cm; -% \endmplibcode -% \end{verbatim} -% -% \paragraph{\cs{mpdim}} -% Since v2.3, \cs{mpdim} and other raw \TeX\ commands are allowed -% inside mplib code. This feature is inpired by gmp.sty authored by -% Enrico Gregorio. Please refer the manual of gmp package for details. -% \begin{verbatim} -% \begin{mplibcode} -% draw origin--(.6\mpdim{\linewidth},0) withpen pencircle scaled 4 -% dashed evenly scaled 4 withcolor \mpcolor{orange}; -% \end{mplibcode} -% \end{verbatim} -% \textsc{n.b.} Users should not use the protected variant of -% |btex ... etex| as provided by gmp package. As \textsf{luamplib} -% automatically protects \TeX\ code inbetween, \cs{btex} is not supported -% here. -% -% \paragraph{\cs{mpcolor}} -% With \cs{mpcolor} command, color names or expressions of -% \textsf{color}/\textsf{xcolor} packages can be used inside mplibcode -% enviroment (after |withcolor| operator), -% though \textsf{luamplib} does not automatically load these -% packages. See the example code above. For spot colors, -% \textsf{colorspace}, \textsf{spotcolor} -% (in PDF mode) and \textsf{xespotcolor} (in DVI mode) packages are supported -% as well. -% -% From v2.26.1, \textsf{l3color} is also supported by the command -% \cs{mpcolor\{color expression\}}, including spot colors. -% -% \paragraph{\cs{mplibnumbersystem}} -% Users can choose |numbersystem| option since v2.4. -% The default value |scaled| can be changed to |double| or |decimal| -% by declaring |\mplibnumbersystem{double}| or |\mplibnumbersystem{decimal}|. -% For details see -% \url{http://github.com/lualatex/luamplib/issues/21}. -% -% \paragraph{\cs{mplibtextextlabel}} -% Starting with v2.6, |\mplibtextextlabel{enable}| enables -% string labels typeset via |textext()| instead of |infont| operator. +% \paragraph{\cs{mplibtextextlabel\{enable\textbar disable\}}} +% Default: |disable|. +% \cs{mplibtextextlabel\{enable\}} enables +% the labels typeset via |textext| instead of |infont| operator. % So, |label("my text",origin)| thereafter is exactly the same as -% |label(textext("my text"),origin)|. \textsc{n.b.} In the background, -% \textsf{luamplib} redefines |infont| operator so that the right side -% argument (the font part) is totally ignored. Every string label -% therefore will be typeset with current \TeX\ font. +% |label(textext("my text"),origin)|. +% +% \textsc{n.b.} In the background, +% luamplib redefines |infont| operator so that the right side +% argument (the font part) is totally ignored. Therefore the left side arguemnt +% will be typeset with the current \TeX\ font. % Also take care of |char| operator in the left side argument, % as this might bring unpermitted characters into \TeX. % -% \paragraph{\cs{mplibcodeinherit}} -% Starting with v2.9, |\mplibcodeinherit{enable}| enables the inheritance -% of variables, constants, and macros defined by previous |mplibcode| chunks. -% On the contrary, the default value |\mplibcodeinherit{disable}| will make -% each code chunks being treated as an independent instance, and never +% \paragraph{\cs{mplibcodeinherit\{enable\textbar disable\}}} +% Default: |disable|. +% \cs{mplibcodeinherit\{enable\}} enables the inheritance +% of variables, constants, and macros defined by previous \metapost code chunks. +% On the contrary, \cs{mplibcodeinherit\{disable\}} will make +% each code chunk being treated as an independent instance, never % affected by previous code chunks. % -% \paragraph{Separate instances for \LaTeX{} environment} -% v2.22 has added the support for several named MetaPost instances +% \paragraph{Separate \metapost instances} +% luamplib v2.22 has added the support for several named \metapost instances % in \LaTeX{} |mplibcode| environment. -% Syntax is like so: -% \begin{verbatim} +% Plain \TeX\ users also can use this functionality. +% The syntax for \LaTeX\ is: +%\begin{verbatim} % \begin{mplibcode}[instanceName] % % some mp code % \end{mplibcode} -% \end{verbatim} -% Behaviour is as follows. +%\end{verbatim} +% The behavior is as follows. % \begin{itemize} % \item All the variables and functions are shared % only among all the environments belonging to the same instance. -% \item |\mplibcodeinherit| only affects environments +% \item \cs{mplibcodeinherit} only affects environments % with no instance name set (since if a name is set, % the code is intended to be reused at some point). -% \item From v2.27, |btex ... etex| boxes are also shared and do not -% require |\mplibglobaltextext|. +% \item |btex ... etex| boxes are also shared and do not +% require \cs{mplibglobaltextext}. % \item When an instance names is set, -% respective |\currentmpinstancename| is set. +% respective \cs{currentmpinstancename} is set as well. % \end{itemize} -% In parellel with this functionality, v2.23 and after supports +% In parellel with this functionality, we support % optional argument of instance name for \cs{everymplib} and % \cs{everyendmplib}, affecting only those |mplibcode| environments % of the same name. % Unnamed \cs{everymplib} affects not only those instances with no name, % but also those with name but with no corresponding \cs{everymplib}. -% Syntax is: -% \begin{verbatim} +% The syntax is: +%\begin{verbatim} % \everymplib[instanceName]{...} % \everyendmplib[instanceName]{...} -% \end{verbatim} +%\end{verbatim} % -% \paragraph{\cs{mplibglobaltextext}} -% Formerly, to inherit |btex ... etex| boxes as well as metapost variables, +% \paragraph{\cs{mplibglobaltextext\{enable\textbar disable\}}} +% Default: |disable|. +% Formerly, to inherit |btex| |...| |etex| boxes as well as other \metapost macros, variables and constants, % it was necessary to declare \cs{mplibglobaltextext\{enable\}} in advance. % But from v2.27, this is implicitly enabled when \cs{mplibcodeinherit} -% is |true|. -% \begin{verbatim} +% is enabled. +% This optional command still remains mostly for backward compatibility. +%\begin{verbatim} % \mplibcodeinherit{enable} % %\mplibglobaltextext{enable} % \everymplib{ beginfig(0);} \everyendmplib{ endfig;} @@ -376,37 +411,92 @@ See source file '\inFileName' for licencing and contact information. % \mplibcode % currentpicture := pic scaled 2; % \endmplibcode -% \end{verbatim} -% Generally speaking, it is recommended to turn |mplibglobaltextext| -% always on, because it has the advantage of more efficient processing. -% But everything has its downside: it will waste more memory resources. +%\end{verbatim} % -% \paragraph{\cs{mplibverbatim}} -% Starting with v2.11, users can issue |\mplibverbatim{enable}|, after which +% \paragraph{\cs{mplibverbatim\{enable\textbar disable\}}} +% Default: |disable|. +% Users can issue \cs{mplibverbatim\{enable\}}, after which % the contents of mplibcode environment will be read verbatim. As a result, -% except for |\mpdim| and |\mpcolor|, all other \TeX\ commands outside -% |btex ... etex| or |verbatimtex ... etex| are not expanded and will be fed -% literally into the mplib process. -% -% \paragraph{\cs{mplibshowlog}} -% When |\mplibshowlog{enable}| is declared, log messages returned by -% |mplib| instance will be printed into the |.log| file. -% |\mplibshowlog{disable}| will revert this functionality. -% This is a \TeX{} side interface for |luamplib.showlog|. (v2.20.8) -% -% \paragraph{Settings regarding cache files} -% To support |btex ... etex| in external |.mp| files, \textsf{luamplib} -% inspects the content of each and every |.mp| input files and makes caches -% if nececcsary, before returning their paths to \LuaTeX's mplib library. -% This would make the compilation time longer wastefully, as most |.mp| files -% do not contain |btex ... etex| command. So \textsf{luamplib} provides -% macros as follows, so that users can give instruction about files +% except for \cs{mpdim} and \cs{mpcolor} (see \hyperlink{mpdim}{below}), +% all other \TeX\ commands outside of the +% |btex| or |verbatimtex| |...| |etex| are not expanded and will be fed +% literally to the \mplib library. +% +% \paragraph{\cs{mpdim\{...\}}} +% \hypertarget{mpdim}{}\relax +% Besides other \TeX\ commands, \cs{mpdim} is specially allowed +% in the mplibcode environment. This feature is inpired by \pkg{gmp} package authored by +% Enrico Gregorio. Please refer to the manual of \pkg{gmp} package for details. +%\begin{verbatim} +% \begin{mplibcode} +% beginfig(1) +% draw origin--(.6\mpdim{\linewidth},0) withpen pencircle scaled 4 +% dashed evenly scaled 4 withcolor \mpcolor{orange}; +% endfig; +% \end{mplibcode} +%\end{verbatim} +% +% \paragraph{\cs{mpcolor[...]\{...\}}} +% With \cs{mpcolor} command, color names or expressions of +% \pkg{color}, \pkg{xcolor} and \pkg{l3color} module/packages can be used in the mplibcode +% environment (after |withcolor| operator). +% See the example \hyperlink{mpdim}{above}. +% The optional |[...]| denotes the option of \pkg{xcolor}'s \cs{color} command. +% For spot colors, \pkg{l3color} (in PDF/DVI mode), +% \pkg{colorspace}, \pkg{spotcolor} +% (in PDF mode) and \pkg{xespotcolor} (in DVI mode) packages are supported +% as well. +% +% \paragraph{\cs{mpfig} \ldots\ \cs{endmpfig}} +% Besides the |mplibcode| environment (for \LaTeX) and +% \cs{mplibcode ...} \cs{endmplibcode} (for Plain), +% we also provide unexpandable \TeX\ macros \cs{mpfig} |...| \cs{endmpfig} and its starred version +% \cs{mpfig*} |...| \cs{endmpfig} to save typing toil. +% The former is roughly the same as follows: +%\begin{verbatim} +% \begin{mplibcode}[@mpfig] +% beginfig(0) +% token list declared by \everymplib[@mpfig] +% ... +% token list declared by \everyendmplib[@mpfig] +% endfig; +% \end{mplibcode} +%\end{verbatim} +% and the starred version is roughly the same as follows: +%\begin{verbatim} +% \begin{mplibcode}[@mpfig] +% ... +% \end{mplibcode} +%\end{verbatim} +% In these macros \cs{mpliblegacybehavior\{disable\}} +% is forcibly declared. +% Again, as both share the same instance name, \metapost codes are inherited among them. +% A simple example: +%\begin{verbatim} +% \everymplib[@mpfig]{ drawoptions(withcolor .5[red,white]); } +% \mpfig* input boxes \endmpfig +% \mpfig +% circleit.a(btex Box 1 etex); drawboxed(a); +% \endmpfig +%\end{verbatim} +% The instance name (default: |@mpfig|) can be changed by redefining +% \cs{mpfiginstancename}, after which a new \mplib instance will start and +% code inheritance too will begin anew. \cs{let}\cs{mpfiginstancename}\cs{empty} will +% prevent code inheritance if \cs{mplibcodeinherit\{true\}} is not declared. +% +% \paragraph{About cache files} +% To support |btex ... etex| in external |.mp| files, luamplib +% inspects the content of each and every |.mp| file and makes caches +% if nececcsary, before returning their paths to \LuaTeX's \mplib library. +% This could waste the compilation time, as most |.mp| files +% do not contain |btex ... etex| commands. So luamplib provides +% macros as follows, so that users can give instructions about files % that do not require this functionality. % \begin{itemize} -% \item |\mplibmakenocache{<filename>[,<filename>,...]}| -% \item |\mplibcancelnocache{<filename>[,<filename>,...]}| +% \item \cs{mplibmakenocache\{<filename>[,<filename>,...]\}} +% \item \cs{mplibcancelnocache\{<filename>[,<filename>,...]\}} % \end{itemize} -% where |<filename>| is a file name excluding |.mp| extension. +% where |<filename>| is a filename excluding |.mp| extension. % Note that |.mp| files under |$TEXMFMAIN/metapost/base| and % |$TEXMFMAIN/metapost/context/base| are already registered by default. % @@ -414,55 +504,477 @@ See source file '\inFileName' for licencing and contact information. % if it's not available (mostly not writable), % in the directory where output files are saved: % to be specific, |$TEXMF_OUTPUT_DIRECTORY/luamplib_cache|, -% |./luamplib_cache|, |$TEXMFOUTPUT/luamplib_cache|, and |.| in this order. -% (|$TEXMF_OUTPUT_DIRECTORY| is normally the value of |--output-directory| -% command-line option.) -% This behavior however can be changed by the command -% |\mplibcachedir{<directory path>}|, where tilde (|~|) is interpreted +% |./luamplib_cache|, |$TEXMFOUTPUT/luamplib_cache|, and |.|, in this order. +% |$TEXMF_OUTPUT_DIRECTORY| is normally the value of |--output-directory| +% command-line option. +% +% Users can change this behavior by the command +% \cs{mplibcachedir\{<directory path>\}}, where tilde (|~|) is interpreted % as the user's home directory (on a windows machine as well). -% As backslashes (|\|) should be escaped by users, it would be easier to use +% As backslashes (\cs{}) should be escaped by users, it would be easier to use % slashes (|/|) instead. % -% \paragraph{\texttt{mplibgraphictext}} -% For some amusement, luamplib provides its own metapost operator -% |mplibgraphictext|, the effect of which is similar to that of -% \ConTeXt's |graphictext|. However syntax is somewhat different. -% \begin{verbatim} -% mplibgraphictext "Funny" -% fakebold 2.3 scale 3 % fontspec options -% drawcolor .7blue fillcolor "red!50" % color expressions -% \end{verbatim} -% |fakebold|, |scale|, |drawcolor| and |fillcolor| are optional; -% default values are |2|, |1|, |"black"| and |"white"| respectively. -% When color expressions are given as string, they are regarded as -% xcolor's or l3color's expressions (this is the same with shading colors). -% All from |mplibgraphictext| to the end of sentence will compose an -% anonymous |picture|, which can be drawn or assigned to a variable. -% Incidentally, |withdrawcolor| and |withfillcolor| are synonyms of -% |drawcolor| and |fillcolor|, hopefully to be compatible with |graphictext|. -% \textsc{n.b.} Because luamplib's current implementation is quite different -% from the \ConTeXt's, there are some limitations such that you can't -% apply shading (gradient colors) to the text. -% -% \paragraph{About figure box metrics} -% Notice that, after each figure is processed, macro \cs{MPwidth} stores -% the width value of latest figure; \cs{MPheight}, the height value. +% \paragraph{About figure box metric} +% Notice that, after each figure is processed, the macro \cs{MPwidth} stores +% the width value of the latest figure; \cs{MPheight}, the height value. % Incidentally, also note that \cs{MPllx}, \cs{MPlly}, \cs{MPurx}, and -% \cs{MPury} store the bounding box information of latest figure +% \cs{MPury} store the bounding box information of the latest figure % without the unit |bp|. % % \paragraph{luamplib.cfg} -% At the end of package loading, \textsf{luamplib} searches +% At the end of package loading, luamplib searches % |luamplib.cfg| and, if found, reads the file in automatically. % Frequently used settings such as \cs{everymplib}, \cs{mplibforcehmode} % or \cs{mplibcodeinherit} are suitable for going into this file. % -% \bigskip +% \subsection{\textsc{MetaPost}} +% +% \paragraph{\texttt{mplibdimen(...)}, \texttt{mplibcolor(...)}} +% These are \metapost interfaces for the \TeX\ commands +% \cs{mpdim} and \cs{mpcolor} (see \hyperlink{mpdim}{above}). For example, +% |mplibdimen("\linewidth")| is basically the same as \cs{mpdim\{\cs{linewidth}\}}, and +% |mplibcolor("red!50")| is basically the same as \cs{mpcolor\{red!50\}}. +% The difference is that these \metapost operators can also be used in external |.mp| files, +% which cannot have \TeX\ commands outside of the |btex| or |verbatimtex| |...| |etex|. +% +% \paragraph{\texttt{mplibtexcolor ...}, \texttt{mplibrgbtexcolor ...}} +% |mplibtexcolor|, which accepts a string argument, is a \metapost operator that converts a \TeX\ color expression +% to a \metapost color expression, that can be used anywhere color expression is expected +% as well as after the |withcolor| operator. +% For instance: +%\begin{verbatim} +% color col; +% col := mplibtexcolor "olive!50"; +%\end{verbatim} +% But the result may vary in its color model (gray/rgb/cmyk) +% according to the given \TeX\ color. (Spot colors are forced to +% cmyk model, so this operator is not recommended for spot colors.) +% Therefore the example shown above would raise a \metapost error: +% |cmykcolor col;| should have been declared. +% By contrast, |mplibrgbtexcolor| \emph{<string>} always returns rgb model expressions. +% +% \paragraph{\texttt{mplibgraphictext ...}} +% |mplibgraphictext| is a \metapost operator, the effect of which is similar to that of +% \ConTeXt's |graphictext| or our own |mpliboutlinetext| +% (see \hyperlink{mpliboutlinetext}{below}). +% However the syntax is somewhat different. +%\begin{verbatim} +% mplibgraphictext "Funny" +% fakebold 2.3 % fontspec option +% drawcolor .7blue fillcolor "red!50" % color expressions +%\end{verbatim} +% |fakebold|, |drawcolor| and |fillcolor| are optional; +% default values are |2|, |"black"| and |"white"| respectively. +% When the color expressions are given in string type, they are regarded as +% \pkg{color}, \pkg{xcolor} or \pkg{l3color}'s expressions. +% All from |mplibgraphictext| to the end of sentence will compose an +% anonymous |picture|, which can be drawn or assigned to a variable. +% Incidentally, |withdrawcolor| and |withfillcolor| are synonyms of +% |drawcolor| and |fillcolor|, hopefully to be compatible with |graphictext|. +% +% \textsc{n.b.} +% In some cases, |mplibgraphictext| will produce better results than \ConTeXt\ +% or even than our own |mpliboutlinetext|, +% especially when processing complicated \TeX\ code +% such as the vertical writing in Chinese or Japanese. +% However, because the implementation is quite different from others, +% there are some limitations such that you can't +% apply shading (gradient colors) to the text. Again, +% in DVI mode, \pkg{unicode-math} package is needed for math formula, +% as we cannot embolden type1 fonts in DVI mode. +% +% \paragraph{\texttt{mplibglyph ... of ...}} +% From v2.30, we provide a new \metapost operator |mplibglyph|, which returns a \metapost picture +% containing outline paths of a glyph in opentype, truetype or type1 fonts. +% When a type1 font is specified, \metapost primitive |glyph| will be called. +%\begin{verbatim} +% mplibglyph 50 of \fontid\font % slot 50 of current font +% mplibglyph "Q" of "TU/TeXGyrePagella(0)/m/n/10" % font csname +% mplibglyph "Q" of "texgyrepagella-regular.otf" % raw filename +% mplibglyph "Q" of "Times.ttc(2)" % subfont number +% mplibglyph "Q" of "SourceHanSansK-VF.otf[Regular]" % instance name +%\end{verbatim} +% Both arguments before and after of ``|of|'' can be either a number or a string. +% Number arguments are regarded as a glyph slot (GID) and a font id number, repectively. +% String argument at the left side is regarded as a glyph name in the font or a unicode character. +% String argument at the right side is regarded as a \TeX\ font csname (without backslash) or +% the raw filename of a font. When it is a font filename, a number within parentheses +% after the filename denotes a +% subfont number (starting from zero) of a TTC font; a string within brackets denotes +% an instance name of a variable font. +% +% \paragraph{\texttt{mplibdrawglyph ...}} +% The picture returned by |mplibglyph| will be quite similar to the result of |glyph| primitive in its structure. +% So, \metapost's |draw| command will fill the inner path of the picture with the background color. +% In contrast, |mplibdrawglyph| \emph{<picture>} command fills the paths according to the nonzero winding +% number rule. As a result, for instance, the area surrounded by inner path of ``O'' +% will remain transparent. +% +% \leavevmode\llap{\textcolor{red}{☞}\kern1.2\parindent}\relax +% To apply the nonzero winding number rule to a picture containing paths, +% luamplib appends |withpostscript| |"collect"| +% to the paths except the last one in the picture. +% If you want the even-odd rule instead, you can, with \emph{plain} format as well, +% additionally declare |withpostscript| |"evenodd"| to the last path in the picture. +% +% \paragraph{\texttt{mpliboutlinetext (...)}} +% \hypertarget{mpliboutlinetext}{}\relax +% From v2.31, a new \metapost operator |mpliboutlinetext| is available, which mimicks +% \emph{metafun}'s |outlinetext|. So the syntax is the same: see the \emph{metafun} +% manual \S\,8.7 (|texdoc metafun|). A simple example: +%\begin{verbatim} +% draw mpliboutlinetext.b ("$\sqrt{2+\alpha}$") +% (withcolor \mpcolor{red!50}) +% (withpen pencircle scaled .2 withcolor red) +% scaled 2 ; +%\end{verbatim} +% After the process, |mpliboutlinepic[]| +% and |mpliboutlinenum| will be preserved as global variables; +% |mpliboutlinepic[1]| \ldots{} |mpliboutlinepic[mpliboutlinenum]| +% will be an array of images each of which containing a glyph or a rule. +% +% \textsc{n.b.} As Unicode grapheme cluster is not considered in the array, a unit that must be +% a single cluster might be separated apart. +% +% \paragraph{\cs{mppattern\{...\} ...} \cs{endmppattern}, \texttt{... withpattern ...}} +% \hypertarget{mppattern}{}\relax +% \TeX\ macros +% \cs{mppattern\{<name>\}} |...| \cs{endmppattern} define a tiling pattern +% associated with the |<name>|. +% \metapost operator |withpattern|, the syntax being +% \emph{<path>} |withpattern| \emph{<string>}, will return a \metapost picture which fills +% the given path with a tiling pattern of the |<name>| +% by replicating it horizontally and vertically. +% An example: +%\begin{verbatim} +% \mppattern{mypatt} % or \begin{mppattern}{mypatt} +% [ % options: see below +% xstep = 10, ystep = 12, +% matrix = {0, 1, -1, 0}, % or "0 1 -1 0" +% ] +% \mpfig % or any other TeX code, +% draw (llcorner unitsquare--urcorner unitsquare) +% scaled 10 +% withcolor 1/3[blue,white] +% ; +% draw (ulcorner unitsquare--lrcorner unitsquare) +% scaled 10 +% withcolor 1/3[red,white] +% ; +% \endmpfig +% \endmppattern % or \end{mppattern} +% +% \mpfig +% draw fullcircle scaled 90 +% withpostscript "collect" +% ; +% draw fullcircle scaled 200 +% withpattern "mypatt" +% withpen pencircle scaled 1 +% withcolor \mpcolor{red!50!blue!50} +% withpostscript "evenodd" +% ; +% \endmpfig +%\end{verbatim} +% +% The available options are listed in Table~\ref{tab:mppatternoptions}. +% \begin{table} +% \centering +% \caption{options for \cs{mppattern}}\label{tab:mppatternoptions} +% \begin{tabular}{lll}\hline +% Key & Value Type & Explanation\\\hline +% |xstep| &\emph{number} & horizontal spacing between pattern cells\\ +% |ystep| &\emph{number} & vertical spacing between pattern cells\\ +% |xshift| &\emph{number} & horizontal shifting of pattern cells\\ +% |yshift| &\emph{number} & vertical shifting of pattern cells\\ +% |matrix| &\emph{table} or \emph{string} & |xx|, |yx|, |xy|, |yy| values\kern1pt* or MP transform code\\ +% |bbox| &\emph{table} or \emph{string} & |llx|, |lly|, |urx|, |ury| values\kern1pt*\\ +% |resources|&\emph{string} & PDF resources if needed\\ +% |colored| or |coloured| &\emph{boolean}& |false| for uncolored pattern. default: |true|\\\hline +% & & \small *\,in string type, numbers are separated by spaces\\ +% \end{tabular} +% \end{table} +% +% For the sake of convenience, the width and height values of tiling patterns will be written down +% into the log file. (depth is always zero.) Users can refer to them for option setting. +% +% As for |matrix| option, \metapost code such as `|rotated 30 slanted .2|' is allowed as well +% as string or table of four numbers. You can also set |xshift| and |yshift| +% values by using `|shifted|' operator. But when |xshift| or |yshift| option is explicitly +% given, they have precedence over the effect of `|shifted|' operator. +% +% When you use special effects such as transparency in a pattern, +% |resources| option is needed: for instance, |resources="/ExtGState 1 0 R"|. +% However, as luamplib automatically includes the resources of the current page, this option +% is not needed in most cases. +% +% Option |colored=false| (|coloured| is a synonym of |colored|) will generate an uncolored pattern which shall have no color at all. +% Uncolored pattern will be painted later by the color of a \metapost object. +% An example: +%\begin{verbatim} +% \begin{mppattern}{pattnocolor} +% [ +% colored = false, +% matrix = "slanted .3 rotated 30", +% ] +% \tiny\TeX +% \end{mppattern} +% +% \begin{mplibcode} +% beginfig(1) +% picture tex; +% tex = mpliboutlinetext.p ("\bfseries \TeX"); +% for i=1 upto mpliboutlinenum: +% j:=0; +% for item within mpliboutlinepic[i]: +% j:=j+1; +% draw pathpart item scaled 10 +% if j < length mpliboutlinepic[i]: +% withpostscript "collect" +% else: +% withpattern "pattnocolor" +% withpen pencircle scaled 1/2 +% withcolor (i/4)[red,blue] % paints the pattern +% fi; +% endfor +% endfor +% endfig; +% \end{mplibcode} +%\end{verbatim} +% +% \paragraph{\texttt{... withfademethod ...}} +% This is a \metapost operator which makes the color of an object gradiently transparent. +% The syntax is \emph{<path>}\texttt{\textbar}\emph{<picture>} |withfademethod| \emph{<string>}, +% the latter being either |"linear"| or |"circular"|. +% Though it is similar to the |withshademethod| from \emph{metafun}, +% the differences are: (1) the operand of |withfademethod| can be a picture as well as a path; +% (2) you cannot make gradient colors, but can only make gradient opacity. +% +% Related macros to control optional values are: +% \begin{description} +% \let\bfseries\relax +% \item [|withfadeopacity (|\emph{number, number}|)|] +% sets the starting opacity and the ending opacity, default value being |(1,0)|. +% `|1|' denotes full color; `|0|' full transparency. +% \item [|withfadevector (|\emph{pair, pair}|)|] +% sets the starting and ending points. Default value in the linear mode is +% |(llcorner p, lrcorner p)|, where |p| is the operand, +% meaning that fading starts from the left edge and ends at the right edge. +% Default value in the circular mode is |(center p, center p)|, which means +% centers of both starting and ending circles are the center of the bounding box. +% \item [|withfadecenter|] is a synonym of |withfadevector|. +% \item [|withfaderadius (|\emph{number, number}|)|] +% sets the radii of starting and ending circles. This is no-op in the linear mode. +% Default value is |(0, abs(center p - urcorner p))|, meaning that fading starts from the +% center and ends at the four corners of the bounding box. +% \item [|withfadebbox (|\emph{pair, pair}|)|] +% sets the bounding box of the fading area, default value being |(llcorner p, urcorner p)|. +% Though this option is not needed in most cases, there could be cases when users want to +% explicitly control the bounding box. +% \end{description} +% An example: +%\begin{verbatim} +% \mpfig +% picture mill; +% mill = btex \includegraphics[width=100bp]{mill} etex; +% draw mill +% withfademethod "circular" +% withfadecenter (center mill, center mill) +% withfaderadius (20, 50) +% withfadeopacity (1, 0) +% ; +% \endmpfig +%\end{verbatim} +% +% \paragraph{\texttt{... asgroup ...}} +% \hypertarget{transparencygroup}{}\relax +% As said \hyperlink{metafunformat}{before}, +% transparency group is available with \emph{plain} as well as \emph{metafun} format. +% The syntax is exactly the same: +% \emph{<picture>} \textbar\ \emph{<path>} |asgroup| +% |""| \textbar\ |"isolated"| \textbar\ |"knockout"| \textbar\ |"isolated,knockout"|, +% which will return a \metapost picture. +% It is called \emph{Transparency Group} because the objects contained in the group are composited +% to produce a single object, so that outer transparency effect, if any, +% will be applied to the group as a whole, not to the individual objects cumulatively. +% +% The additional feature provided by luamplib is that +% you can reuse the group as many times as you want +% in the \TeX{} code or in other \metapost code chunks, +% with infinitesimal increase in the size of PDF file. +% For this functionality we provide \TeX{} and \metapost macros as follows: +% \begin{description} +% \let\bfseries\relax +% \item[|withgroupname| \emph{<string>}] associates a transparency group with the given name. +% When this is not appended to the sentense with |asgroup| operator, +% the default group name `|lastmplibgroup|' will be used. +% +% \item[\cs{usemplibgroup\{...\}}] +% \hypertarget{usemplibgroup}{}\relax +% is a \TeX\ command to reuse a transparency group of the name +% once used. +% Note that the position of the group will be origin-based: +% in other words, lower-left corner of the group will be shifted to the origin. +% +% \item[|usemplibgroup| \emph{<string>}] is a \metapost command which will add +% a transparency group of the name to the |currentpicture|. +% Contrary to the \TeX\ command just mentioned, +% the position of the group is the same as the original transparency group. +% \end{description} +% An example showing the difference between the \TeX\ and \metapost commands: +%\begin{verbatim} +% \mpfig +% draw image( +% fill fullcircle scaled 100 shifted 25right withcolor .5[blue,white]; +% fill fullcircle scaled 100 withcolor .5[red,white] ; +% ) asgroup "" withgroupname "mygroup"; +% draw (left--right) scaled 10; +% draw (up--down) scaled 10; +% \endmpfig +% +% \noindent +% \clap{\vrule width 20pt height .25pt depth .25pt}% +% \clap{\vrule width .5pt height 10pt depth 10pt}% +% \usemplibgroup{mygroup} +% +% \mpfig +% usemplibgroup "mygroup" rotated 15; +% draw (left--right) scaled 10; +% draw (up--down) scaled 10; +% \endmpfig +%\end{verbatim} +% +% Also note that normally the reused transparency groups are not affected by outer color commands. +% However, if you have made the original transparency group using |withoutcolor| command, +% colors will have effects on the uncolored objects in the group. +% +% \paragraph{\cs{mplibgroup\{...\} ...} \cs{endmplibgroup}} +% These \TeX\ macros are described here in this subsection, as they are +% deeply related to the |asgroup| operator. +% Users can define a transparency group or a normal \emph{form XObject} +% with these macros from \TeX\ side. +% The syntax is similar to the \cs{mppattern} command (see \hyperlink{mppattern}{above}). +% An example: +%\begin{verbatim} +% \mplibgroup{mygrx} % or \begin{mplibgroup}{mygrx} +% [ % options: see below +% asgroup="", +% ] +% \mpfig % or any other TeX code +% draw (left--right) scaled 30 rotated 45 withpen pencircle scaled 10; +% draw (left--right) scaled 30 rotated -45 withpen pencircle scaled 10; +% \endmpfig +% \endmplibgroup % or \end{mplibgroup} +% +% \usemplibgroup{mygrx} +% +% \mpfig +% usemplibgroup "mygrx" scaled 1.5 withprescript "tr_transparency=0.5"; +% \endmpfig +%\end{verbatim} +% Availabe options, much fewer than those for \cs{mppattern}, +% are listed in Table~\ref{tab:mplibgroupoptions}. +% \begin{table} +% \centering +% \caption{options for \cs{mplibgroup}}\label{tab:mplibgroupoptions} +% \begin{tabular}{lll} +% \hline +% Key & Value Type & Explanation\\ +% \hline +% |asgroup| &\emph{string} & |""|, |"isolated"|, |"knockout"|, or |"isolated,knockout"|\\ +% |bbox| &\emph{table} or \emph{string} & |llx|, |lly|, |urx|, |ury| values\kern1pt*\\ +% |matrix| &\emph{table} or \emph{string} & |xx|, |yx|, |xy|, |yy| values\kern1pt* +% or MP transform code\\ +% |resources| &\emph{string} & PDF resources if needed\\ +% \hline +% & & \small *\,in string type, numbers are separated by spaces\\ +% \end{tabular} +% \end{table} +% +% When |asgroup| option, including empty string, is not given, +% a normal form XObject will be generated rather than a transparency group. +% So, the individual objects, not the XObject as a whole, will be affected +% by outer transparency command. +% +% As shown in the example, you can reuse the transparency group or the normal form XObject +% once defined +% using the \TeX\ command \cs{usemplibgroup} or +% the \metapost command |usemplibgroup|. +% The behavior of these commands is the same as that described \hyperlink{usemplibgroup}{above}. +% +% +% \subsection{Lua} +% +% \paragraph{\texttt{runscript ...}} +% Using the primitive |runscript| \emph{<string>}, you can run a Lua code chunk from \metapost side +% and get some \metapost code returned by Lua if you want. +% As the functionality is provided by the \mplib library itself, +% luamplib does not have much to say about it. +% +% One thing is worth mentioning, however: +% if you return a Lua \emph{table} to the \metapost process, +% it is automatically converted to a relevant \metapost value type +% such as pair, color, cmykcolor or transform. +% So users can save some extra toil of converting a table to a string, though it's not a big deal. +% For instance, |runscript "return {1,0,0}"| will give you the \metapost color expression |(1,0,0)| +% automatically. +% +% \paragraph{Lua table \texttt{luamplib.instances}} +% Users can access the Lua table containing \mplib instances, |luamplib.instances|, +% through which \metapost variables are also easily accessible from Lua side, +% as documented in Lua\TeX{} manual \S\,11.2.8.4 (|texdoc luatex|). +% The following will print |false|, |3.0|, |MetaPost| and +% the knots and the cyclicity of the path |unitsquare|, consecutively. +%\begin{verbatim} +% \begin{mplibcode}[instance1] +% boolean b; b = 1 > 2; +% numeric n; n = 3; +% string s; s = "MetaPost"; +% path p; p = unitsquare; +% \end{mplibcode} +% +% \directlua{ +% local instance1 = luamplib.instances.instance1 +% print( instance1:get_boolean "b" ) +% print( instance1:get_number "n" ) +% print( instance1:get_string "s" ) +% local t = instance1:get_path "p" +% for k,v in pairs(t) do +% print(k, type(v)=='table' and table.concat(v,' ') or v) +% end +% } +%\end{verbatim} +% +% \paragraph{Lua function \texttt{luamplib.process\_mplibcode}} +% Users can execute a \metapost code chunk from Lua side by using this function: +%\begin{verbatim} +% luamplib.process_mplibcode (<string> metapost code, <string> instance name) +%\end{verbatim} +% The second argument cannot be absent, but can be an empty string (|""|) which +% means that it has no instance name. +% +% Some other elements in the |luamplib| namespace, listed in Table~\ref{tab:elementsinluamplib}, +% can have effects on the process of |process_mplibcode|. +% \begin{table} +% \centering +% \caption{elements in \texttt{luamplib} table (partial)}\label{tab:elementsinluamplib} +% \begin{tabular}{lll}\hline +% Key & Type & Related \TeX\ macro \\\hline +% |codeinherit| & \emph{boolean} & \cs{mplibcodeinherit}\\ +% |everyendmplib| & \emph{table} & \cs{everyendmplib}\\ +% |everymplib| & \emph{table} & \cs{everymplib}\\ +% |getcachedir| & \emph{function} (\emph{<string>}) & \cs{mplibcachedir}\\ +% |globaltextext| & \emph{boolean} & \cs{mplibglobaltextext}\\ +% |legacyverbatimtex| & \emph{boolean} & \cs{mpliblegacybehavior}\\ +% |noneedtoreplace| & \emph{table} & \cs{mplibmakenocache}\\ +% |numbersystem| & \emph{string} & \cs{mplibnumbersystem}\\ +% |setformat| & \emph{function} (\emph{<string>}) & \cs{mplibsetformat}\\ +% |showlog| & \emph{boolean} & \cs{mplibshowlog}\\ +% |textextlabel| & \emph{boolean} & \cs{mplibtextextlabel}\\ +% |verbatiminput| & \emph{boolean} & \cs{mplibverbatim}\\\hline +% \end{tabular} +% \end{table} % -% There are (basically) two formats for metapost: \emph{plain} and -% \emph{metafun}. By default, the \emph{plain} format is used, but you can set -% the format to be used by future figures at any time using -% \cs{mplibsetformat}\marg{format name}. % % \section{Implementation} % @@ -476,14 +988,14 @@ See source file '\inFileName' for licencing and contact information. luatexbase.provides_module { name = "luamplib", - version = "2.28.2", - date = "2024/04/25", + version = "2.34.3", + date = "2024/07/27", description = "Lua package to typeset Metapost with LuaTeX's MPLib.", } % \end{macrocode} % -% Use the |luamplib| namespace, since |mplib| is for the metapost library +% Use the |luamplib| namespace, since |mplib| is for the \metapost library % itself. \ConTeXt{} uses |metapost|. % \begin{macrocode} luamplib = luamplib or { } @@ -519,7 +1031,6 @@ local function termorlog (target, text, kind) if kind == "Error" then error() end end end - local function warn (...) -- beware '%' symbol termorlog("term and log", select("#",...) > 1 and format(...) or ...) end @@ -535,32 +1046,23 @@ luamplib.showlog = luamplib.showlog or false % \end{macrocode} % % This module is a stripped down version of libraries that are used by -% \ConTeXt. Provide a few ``shortcuts'' expected by the imported code. +% \ConTeXt. Provide a few ``shortcuts'' expected by the code. % \begin{macrocode} local tableconcat = table.concat +local tableinsert = table.insert +local tableunpack = table.unpack local texsprint = tex.sprint local texgettoks = tex.gettoks local texgetbox = tex.getbox local texruntoks = tex.runtoks -% \end{macrocode} -% -% We don't use |tex.scantoks| anymore. See below reagrding |tex.runtoks|. -% \begin{verbatim} -% local texscantoks = tex.scantoks -% \end{verbatim} -% \begin{macrocode} - if not texruntoks then err("Your LuaTeX version is too old. Please upgrade it to the latest") end - local is_defined = token.is_defined local get_macro = token.get_macro - local mplib = require ('mplib') local kpse = require ('kpse') local lfs = require ('lfs') - local lfsattributes = lfs.attributes local lfsisdir = lfs.isdir local lfsmkdir = lfs.mkdir @@ -576,7 +1078,6 @@ local file = file or { } local replacesuffix = file.replacesuffix or function(filename, suffix) return (filename:gsub("%.[%a%d]+$","")) .. "." .. suffix end - local is_writable = file.is_writable or function(name) if lfsisdir(name) then name = name .. "/_luam_plib_temp_file_" @@ -598,15 +1099,12 @@ end % \end{macrocode} % % |btex ... etex| in input |.mp| files will be replaced in finder. -% Because of the limitation of MPLib regarding |make_text|, +% Because of the limitation of \mplib regarding |make_text|, % we might have to make cache files modified from input files. % \begin{macrocode} -local luamplibtime = kpse.find_file("luamplib.lua") -luamplibtime = luamplibtime and lfsattributes(luamplibtime,"modification") - +local luamplibtime = lfsattributes(kpse.find_file"luamplib.lua", "modification") local currenttime = os.time() - -local outputdir +local outputdir, cachedir if lfstouch then for i,v in ipairs{'TEXMFVAR','TEXMF_OUTPUT_DIRECTORY','.','TEXMFOUTPUT'} do local var = i == 3 and v or kpse.var_value(v) @@ -626,7 +1124,6 @@ if lfstouch then end end outputdir = outputdir or '.' - function luamplib.getcachedir(dir) dir = dir:gsub("##","#") dir = dir:gsub("^~", @@ -634,7 +1131,7 @@ function luamplib.getcachedir(dir) if lfstouch and dir then if lfsisdir(dir) then if is_writable(dir) then - luamplib.cachedir = dir + cachedir = dir else warn("Directory '%s' is not writable!", dir) end @@ -643,10 +1140,9 @@ function luamplib.getcachedir(dir) end end end - % \end{macrocode} % -% Some basic MetaPost files not necessary to make cache files. +% Some basic \metapost files not necessary to make cache files. % \begin{macrocode} local noneedtoreplace = { ["boxes.mp"] = true, -- ["format.mp"] = true, @@ -665,7 +1161,6 @@ local noneedtoreplace = { ["mp-tool.mpiv"] = true, ["mp-cont.mpiv"] = true, } luamplib.noneedtoreplace = noneedtoreplace - % \end{macrocode} % % |format.mp| is much complicated, so specially treated. @@ -687,7 +1182,6 @@ local function replaceformatmp(file,newfile,ofmodify) lfstouch(newfile,currenttime,ofmodify) return newfile end - % \end{macrocode} % % Replace |btex ... etex| and |verbatimtex ... etex| in input files, @@ -697,13 +1191,11 @@ local name_b = "%f[%a_]" local name_e = "%f[^%a_]" local btex_etex = name_b.."btex"..name_e.."%s*(.-)%s*"..name_b.."etex"..name_e local verbatimtex_etex = name_b.."verbatimtex"..name_e.."%s*(.-)%s*"..name_b.."etex"..name_e - local function replaceinputmpfile (name,file) local ofmodify = lfsattributes(file,"modification") if not ofmodify then return file end - local cachedir = luamplib.cachedir or outputdir local newfile = name:gsub("%W","_") - newfile = cachedir .."/luamplib_input_"..newfile + newfile = format("%s/luamplib_input_%s", cachedir or outputdir, newfile) if newfile and luamplibtime then local nf = lfsattributes(newfile) if nf and nf.mode == "file" and @@ -711,24 +1203,19 @@ local function replaceinputmpfile (name,file) return nf.size == 0 and file or newfile end end - if name == "format.mp" then return replaceformatmp(file,newfile,ofmodify) end - local fh = ioopen(file,"r") if not fh then return file end local data = fh:read("*all"); fh:close() - % \end{macrocode} -% -% ``|etex|'' must be followed by a space or semicolon as specified in -% \LuaTeX\ manual, which is not the case of standalone MetaPost though. +% ``|etex|'' must be preceded by a space and followed by a space or semicolon as specified in +% \LuaTeX\ manual, which is not the case of standalone \metapost though. % \begin{macrocode} local count,cnt = 0,0 data, cnt = data:gsub(btex_etex, "btex %1 etex ") -- space count = count + cnt data, cnt = data:gsub(verbatimtex_etex, "verbatimtex %1 etex;") -- semicolon count = count + cnt - if count == 0 then noneedtoreplace[name] = true fh = ioopen(newfile,"w"); @@ -738,7 +1225,6 @@ local function replaceinputmpfile (name,file) end return file end - fh = ioopen(newfile,"w") if not fh then return file end fh:write(data); fh:close() @@ -748,8 +1234,8 @@ end % \end{macrocode} % -% As the finder function for MPLib, use the |kpse| library and -% make it behave like as if MetaPost was used. And replace it with +% As the finder function for \mplib, use the |kpse| library and +% make it behave like as if \metapost was used. And replace |.mp| files with % cache files if needed. % See also \#74, \#97. % \begin{macrocode} @@ -761,13 +1247,11 @@ do end mpkpse = kpse.new(arg[exe], "mpost") end - local special_ftype = { pfb = "type1 fonts", enc = "enc files", } - -local function finder(name, mode, ftype) +function luamplib.finder (name, mode, ftype) if mode == "w" then if name and name ~= "mpout.log" then kpse.record_output_file(name) -- recorder @@ -789,13 +1273,12 @@ local function finder(name, mode, ftype) return file end end -luamplib.finder = finder % \end{macrocode} % -% Create and load MPLib instances. -% We do not support ancient version of MPLib any more. -% (Don't know which version of MPLib started to support +% Create and load \mplib instances. +% We do not support ancient version of \mplib any more. +% (Don't know which version of \mplib started to support % |make_text| and |run_script|; let the users find it.) % \begin{macrocode} local preamble = [[ @@ -804,34 +1287,29 @@ local preamble = [[ let normalfontsize = fontsize; input %s ; ]] - % \end{macrocode} % -% |plain| or |metafun|, -% though we cannot support |metafun| format fully. +% \emph{plain} or \emph{metafun}, +% though we cannot support \emph{metafun} format fully. % \begin{macrocode} local currentformat = "plain" -local function setformat (name) +function luamplib.setformat (name) currentformat = name end -luamplib.setformat = setformat - % \end{macrocode} % % v2.9 has introduced the concept of ``code inherit'' % \begin{macrocode} luamplib.codeinherit = false - local mplibinstances = {} -local instancename - +luamplib.instances = mplibinstances +local has_instancename = false local function reporterror (result, prevlog) if not result then err("no result object returned") else local t, e, l = result.term, result.error, result.log % \end{macrocode} -% % log has more information than term, so log first (2021/08/02) % \begin{macrocode} local log = l or t or "no-term" @@ -850,10 +1328,9 @@ local function reporterror (result, prevlog) elseif prevlog then log = prevlog..log % \end{macrocode} -% % v2.6.1: now luamplib does not disregard |show| command, % even when |luamplib.showlog| is false. Incidentally, -% it does not raise error but just prints an info, +% it does not raise error nor prints an info, % even if output has no figure. % \begin{macrocode} local show = log:match"\n>>? .+" @@ -867,18 +1344,20 @@ local function reporterror (result, prevlog) return log end end - +% \end{macrocode} +% +% |lualibs-os.lua| installs a randomseed. When this file is not loaded, +% we should explicitly seed a unique integer to get random randomseed for each run. +% \begin{macrocode} +if not math.initialseed then math.randomseed(currenttime) end local function luamplibload (name) local mpx = mplib.new { ini_version = true, find_file = luamplib.finder, % \end{macrocode} -% % Make use of |make_text| and |run_script|, which will co-operate -% with \LuaTeX's |tex.runtoks|. And we -% provide |numbersystem| option since v2.4. Default value ``|scaled|'' -% can be changed by declaring |\mplibnumbersystem{double}| -% or |\mplibnumbersystem{decimal}|. +% with \LuaTeX's |tex.runtoks| or other Lua functions. And we +% provide |numbersystem| option since v2.4. % See \url{https://github.com/lualatex/luamplib/issues/21}. % \begin{macrocode} make_text = luamplib.maketext, @@ -889,14 +1368,13 @@ local function luamplibload (name) extensions = 1, } % \end{macrocode} -% -% Append our own MetaPost preamble to the preamble above. +% Append our own \metapost preamble to the preamble above. % \begin{macrocode} local preamble = tableconcat{ format(preamble, replacesuffix(name,"mp")), - luamplib.mplibcodepreamble, - luamplib.legacy_verbatimtex and luamplib.legacyverbatimtexpreamble or "", - luamplib.textextlabel and luamplib.textextlabelpreamble or "", + luamplib.preambles.mplibcode, + luamplib.legacyverbatimtex and luamplib.preambles.legacyverbatimtex or "", + luamplib.textextlabel and luamplib.preambles.textextlabel or "", } local result, log if not mpx then @@ -907,39 +1385,27 @@ local function luamplibload (name) log = reporterror(result) return mpx, result, log end - % \end{macrocode} % % Here, excute each |mplibcode| data, % ie |\begin{mplibcode} ... \end{mplibcode}|. % \begin{macrocode} -local function process (data) -% \end{macrocode} -% -% The workaround of issue \#70 seems to be unnecessary, as we use -% |make_text| now. -% \begin{verbatim} -% if not data:find(name_b.."beginfig%s*%([%+%-%s]*%d[%.%d%s]*%)") then -% data = data .. "beginfig(-1);endfig;" -% end -% \end{verbatim} -% \begin{macrocode} +local function process (data, instancename) local currfmt if instancename and instancename ~= "" then currfmt = instancename + has_instancename = true else currfmt = tableconcat{ currentformat, luamplib.numbersystem or "scaled", tostring(luamplib.textextlabel), - tostring(luamplib.legacy_verbatimtex), + tostring(luamplib.legacyverbatimtex), } + has_instancename = false end local mpx = mplibinstances[currfmt] - local standalone = false - if currfmt ~= instancename then - standalone = not luamplib.codeinherit - end + local standalone = not (has_instancename or luamplib.codeinherit) if mpx and standalone then mpx:finish() end @@ -955,8 +1421,6 @@ local function process (data) if log then if result.fig then converted = luamplib.convert(result) - else - info"No figure output. Maybe no beginfig/endfig" end end else @@ -970,83 +1434,56 @@ end % |dvipdfmx| is supported, though nobody seems to use it. % \begin{macrocode} local pdfmode = tex.outputmode > 0 + % \end{macrocode} % -% |make_text| and some |run_script| uses \LuaTeX's |tex.runtoks|, -% which made possible running \TeX\ code snippets inside |\directlua|. +% |make_text| and some |run_script| uses \LuaTeX's |tex.runtoks|. % \begin{macrocode} local catlatex = luatexbase.registernumber("catcodetable@latex") local catat11 = luatexbase.registernumber("catcodetable@atletter") - % \end{macrocode} % % |tex.scantoks| sometimes fail to read catcode properly, especially % |\#|, |\&|, or |\%|. After some experiment, we dropped using it. -% Instead, a function containing |tex.script| seems to work nicely. -% \begin{verbatim} -% local function run_tex_code_no_use (str, cat) -% cat = cat or catlatex -% texscantoks("mplibtmptoks", cat, str) -% texruntoks("mplibtmptoks") -% end -% \end{verbatim} +% Instead, a function containing |tex.sprint| seems to work nicely. % \begin{macrocode} local function run_tex_code (str, cat) texruntoks(function() texsprint(cat or catlatex, str) end) end - % \end{macrocode} % -% Prepare textext box number containers, -% locals, globals and possibly instances. +% Prepare textext box number containers, locals and globals. % |localid| can be any number. They are local anyway. % The number will be reset at the start of a new code chunk. % Global boxes will use |\newbox| command in |tex.runtoks| process. -% This is the same when |codeinherit| is declared as true. -% Boxes of an instance will also be global, so that +% This is the same when |codeinherit| is true. +% Boxes in instances with name will also be global, so that % their tex boxes can be shared among instances of the same name. % \begin{macrocode} -local texboxes = { - locals = {}, localid = 4096, - globals = {}, globalid = 0, -} +local texboxes = { globalid = 0, localid = 4096 } % \end{macrocode} % For conversion of |sp| to |bp|. % \begin{macrocode} local factor = 65536*(7227/7200) - local textext_fmt = 'image(addto currentpicture doublepath unitsquare \z -xscaled %f yscaled %f shifted (0,-%f) \z -withprescript "mplibtexboxid=%i:%f:%f")' - + xscaled %f yscaled %f shifted (0,-%f) \z + withprescript "mplibtexboxid=%i:%f:%f")' local function process_tex_text (str) if str then - local boxtable, global - if instancename and instancename ~= "" - or luamplib.globaltextext or luamplib.codeinherit then - boxtable, global = texboxes.globals, "\\global" + local global = (has_instancename or luamplib.globaltextext or luamplib.codeinherit) + and "\\global" or "" + local tex_box_id + if global == "" then + tex_box_id = texboxes.localid + 1 + texboxes.localid = tex_box_id else - boxtable, global = texboxes.locals, "" - end - local tex_box_id = boxtable[str] - local box = tex_box_id and texgetbox(tex_box_id) - if not box then - if global == "" then - tex_box_id = texboxes.localid + 1 - texboxes.localid = tex_box_id - else - local boxid = texboxes.globalid + 1 - texboxes.globalid = boxid - run_tex_code(format( - [[\expandafter\newbox\csname luamplib.box.%s\endcsname]], boxid)) - tex_box_id = tex.getcount'allocationnumber' - end - if str:find"^[%s%w%{%}%$%^%_]*$" then -- the same cs may expand differently - boxtable[str] = tex_box_id - end - run_tex_code(format("%s\\setbox%i\\hbox{%s}", global, tex_box_id, str)) - box = texgetbox(tex_box_id) + local boxid = texboxes.globalid + 1 + texboxes.globalid = boxid + run_tex_code(format([[\expandafter\newbox\csname luamplib.box.%s\endcsname]], boxid)) + tex_box_id = tex.getcount'allocationnumber' end + run_tex_code(format("%s\\setbox%i\\hbox{%s}", global, tex_box_id, str)) + local box = texgetbox(tex_box_id) local wd = box.width / factor local ht = box.height / factor local dp = box.depth / factor @@ -1060,7 +1497,6 @@ end % Make |color| or |xcolor|'s color expressions usable, % with \cs{mpcolor} or |mplibcolor|. These commands should be used % with graphical objects. -% % Attempt to support l3color as well. % \begin{macrocode} local mplibcolorfmt = { @@ -1076,7 +1512,6 @@ local mplibcolorfmt = { [[\color_select:n%s\endgroup]], }, } - local colfmt = is_defined'color_select:n' and "l3color" or "xcolor" if colfmt == "l3color" then run_tex_code{ @@ -1090,8 +1525,7 @@ if colfmt == "l3color" then } end local ccexplat = luatexbase.registernumber"luamplibcctabexplat" - -local function process_color (str, kind) +local function process_color (str) if str then if not str:find("%b{}") then str = format("{%s}",str) @@ -1112,117 +1546,16 @@ local function process_color (str, kind) end end end - if myfmt == mplibcolorfmt.l3color and (kind == "fill" or kind == "draw") then return str end run_tex_code(myfmt:format(str), ccexplat or catat11) local t = texgettoks"mplibtmptoks" if not pdfmode and not t:find"^pdf" then t = t:gsub("%a+ (.+)","pdf:bc [%1]") end - if kind then return t end - return format('1 withprescript "MPlibOverrideColor=%s"', t) + return format('1 withprescript "mpliboverridecolor=%s"', t) end return "" end -local function colorsplit (res) - local t, tt = { }, res:gsub("[%[%]]",""):explode() - local be = tt[1]:find"^%d" and 1 or 2 - for i=be, #tt do - if tt[i]:find"^%a" then break end - t[#t+1] = tt[i] - end - return t -end - -luamplib.outlinecolor = function (str, filldraw) - local nn = filldraw == "fill" and 'fn:=' or 'dn:=' - local cc = filldraw == "fill" and 'fc:=' or 'dc:=' - local res = process_color(str, filldraw) - if res:match"{(.+)}" == str then - return format('%s"n"; %s"%s";', nn,cc,str) - end - local t = colorsplit(res) - local md = #t == 1 and 'gray' or #t == 3 and 'rgb' or #t == 4 and 'cmyk' - return format('%s"nn"; %s"%s}{%s";', nn, cc, md, tableconcat(t,',')) -end - -luamplib.shadecolor = function (str) - local res = process_color(str, "shade") - if res:find" cs " or res:find"@pdf.obj" then -- spot color shade: l3 only -% \end{macrocode} -% An example of spot color shading: -% \begin{verbatim} -% \documentclass{article} -% \usepackage{luamplib} -% \mplibsetformat{metafun} -% \ExplSyntaxOn -% \color_model_new:nnn { pantone3005 } -% { Separation } -% { name = PANTONE~3005~U , -% alternative-model = cmyk , -% alternative-values = {1, 0.56, 0, 0} -% } -% \color_set:nnn{spotA}{pantone3005}{1} -% \color_set:nnn{spotB}{pantone3005}{0.6} -% \color_model_new:nnn { pantone1215 } -% { Separation } -% { name = PANTONE~1215~U , -% alternative-model = cmyk , -% alternative-values = {0, 0.15, 0.51, 0} -% } -% \color_set:nnn{spotC}{pantone1215}{1} -% \color_model_new:nnn { pantone2040 } -% { Separation } -% { name = PANTONE~2040~U , -% alternative-model = cmyk , -% alternative-values = {0, 0.28, 0.21, 0.04} -% } -% \color_set:nnn{spotD}{pantone2040}{1} -% \ExplSyntaxOff -% \begin{document} -% \begin{mplibcode} -% beginfig(1) -% fill unitsquare xyscaled (\mpdim\textwidth,1cm) -% withshademethod "linear" -% withshadevector (0,1) -% withshadestep ( -% withshadefraction .5 -% withshadecolors ("spotB","spotC") -% ) -% withshadestep ( -% withshadefraction 1 -% withshadecolors ("spotC","spotD") -% ) -% ; -% endfig; -% \end{mplibcode} -% \end{document} -% \end{verbatim} -% \begin{macrocode} - run_tex_code({ - [[\color_export:nnN{]], str, [[}{backend}\mplib_@tempa]], - },ccexplat) - local name = get_macro'mplib_@tempa':match'{(.-)}{.+}' - local t, obj = res:explode() - if pdfmode then - obj = t[1]:match"^/(.+)" - if ltx.pdf and ltx.pdf.object_id then - obj = format("%s 0 R", ltx.pdf.object_id(obj)) - else - run_tex_code({ - [[\edef\mplib_@tempa{\pdf_object_ref:n{]], obj, "}}", - },ccexplat) - obj = get_macro'mplib_@tempa' - end - else - obj = t[2] - end - local value = t[3]:match"%[(.-)%]" or t[3] - return format('(%s) withprescript"mplib_spotcolor=%s:%s"', value,obj,name) - end - return colorsplit(res) -end - % \end{macrocode} % % for \cs{mpdim} or |mplibdimen| @@ -1252,25 +1585,18 @@ end % % For legacy verbatimtex process. % |verbatimtex ... etex| before |beginfig()| is not ignored, -% but the \TeX\ code is inserted just before the mplib box. And -% \TeX\ code inside |beginfig() ... endfig| is inserted after the mplib box. +% but the \TeX\ code is inserted just before the \mplib box. And +% \TeX\ code inside |beginfig() ... endfig| is inserted after the \mplib box. % \begin{macrocode} local tex_code_pre_mplib = {} luamplib.figid = 1 luamplib.in_the_fig = false - -local function legacy_mplibcode_reset () - tex_code_pre_mplib = {} - luamplib.figid = 1 -end - local function process_verbatimtex_prefig (str) if str then tex_code_pre_mplib[luamplib.figid] = str end return "" end - local function process_verbatimtex_infig (str) if str then return format('special "postmplibverbtex=%s";', str) @@ -1289,18 +1615,16 @@ local runscript_funcs = { % \end{macrocode} % -% For |metafun| format. see issue \#79. +% For \emph{metafun} format. see issue \#79. % \begin{macrocode} mp = mp or {} local mp = mp mp.mf_path_reset = mp.mf_path_reset or function() end mp.mf_finish_saving_data = mp.mf_finish_saving_data or function() end mp.report = mp.report or info - - % \end{macrocode} % -% metafun 2021-03-09 changes crashes luamplib. +% \emph{metafun} 2021-03-09 changes crashes luamplib. % \begin{macrocode} catcodes = catcodes or {} local catcodes = catcodes @@ -1334,7 +1658,6 @@ local function mpprint(buffer,...) end end end - function luamplib.runscript (code) local id, str = code:match("(.-){(.*)}") if id and str then @@ -1356,7 +1679,7 @@ function luamplib.runscript (code) return buffer end buffer = {} - mpprint(buffer, table.unpack(res)) + mpprint(buffer, tableunpack(res)) return tableconcat(buffer) end return "" @@ -1373,9 +1696,7 @@ local function protecttexcontents (str) :gsub("%zPerCent%z", "\\%%") :gsub("%s+", " ") end - -luamplib.legacy_verbatimtex = true - +luamplib.legacyverbatimtex = true function luamplib.maketext (str, what) if str and str ~= "" then str = protecttexcontents(str) @@ -1384,7 +1705,7 @@ function luamplib.maketext (str, what) not str:find("\\begin%s*{document}") and not str:find("\\documentstyle"..name_e) and not str:find("\\usepackage"..name_e) then - if luamplib.legacy_verbatimtex then + if luamplib.legacyverbatimtex then if luamplib.in_the_fig then return process_verbatimtex_infig(str) else @@ -1403,9 +1724,710 @@ end % \end{macrocode} % -% Our MetaPost preambles +% luamplib's \metapost color operators % \begin{macrocode} -local mplibcodepreamble = [[ +local function colorsplit (res) + local t, tt = { }, res:gsub("[%[%]]",""):explode() + local be = tt[1]:find"^%d" and 1 or 2 + for i=be, #tt do + if tt[i]:find"^%a" then break end + t[#t+1] = tt[i] + end + return t +end + +luamplib.gettexcolor = function (str, rgb) + local res = process_color(str):match'"mpliboverridecolor=(.+)"' + if res:find" cs " or res:find"@pdf.obj" then + if not rgb then + warn("%s is a spot color. Forced to CMYK", str) + end + run_tex_code({ + "\\color_export:nnN{", + str, + "}{", + rgb and "space-sep-rgb" or "space-sep-cmyk", + "}\\mplib_@tempa", + },ccexplat) + return get_macro"mplib_@tempa":explode() + end + local t = colorsplit(res) + if #t == 3 or not rgb then return t end + if #t == 4 then + return { 1 - math.min(1,t[1]+t[4]), 1 - math.min(1,t[2]+t[4]), 1 - math.min(1,t[3]+t[4]) } + end + return { t[1], t[1], t[1] } +end + +luamplib.shadecolor = function (str) + local res = process_color(str):match'"mpliboverridecolor=(.+)"' + if res:find" cs " or res:find"@pdf.obj" then -- spot color shade: l3 only +% \end{macrocode} +% An example of spot color shading: +%\begin{verbatim} +% \documentclass{article} +% \usepackage{luamplib} +% \mplibsetformat{metafun} +% \ExplSyntaxOn +% \color_model_new:nnn { pantone3005 } +% { Separation } +% { name = PANTONE~3005~U , +% alternative-model = cmyk , +% alternative-values = {1, 0.56, 0, 0} +% } +% \color_set:nnn{spotA}{pantone3005}{1} +% \color_set:nnn{spotB}{pantone3005}{0.6} +% \color_model_new:nnn { pantone1215 } +% { Separation } +% { name = PANTONE~1215~U , +% alternative-model = cmyk , +% alternative-values = {0, 0.15, 0.51, 0} +% } +% \color_set:nnn{spotC}{pantone1215}{1} +% \color_model_new:nnn { pantone2040 } +% { Separation } +% { name = PANTONE~2040~U , +% alternative-model = cmyk , +% alternative-values = {0, 0.28, 0.21, 0.04} +% } +% \color_set:nnn{spotD}{pantone2040}{1} +% \ExplSyntaxOff +% \begin{document} +% \begin{mplibcode} +% beginfig(1) +% fill unitsquare xyscaled (\mpdim\textwidth,1cm) +% withshademethod "linear" +% withshadevector (0,1) +% withshadestep ( +% withshadefraction .5 +% withshadecolors ("spotB","spotC") +% ) +% withshadestep ( +% withshadefraction 1 +% withshadecolors ("spotC","spotD") +% ) +% ; +% endfig; +% \end{mplibcode} +% \end{document} +%\end{verbatim} +% another one: user-defined DeviceN colorspace +%\begin{verbatim} +% \DocumentMetadata{ } +% \documentclass{article} +% \usepackage{luamplib} +% \mplibsetformat{metafun} +% \ExplSyntaxOn +% \color_model_new:nnn { pantone1215 } +% { Separation } +% { name = PANTONE~1215~U , +% alternative-model = cmyk , +% alternative-values = {0, 0.15, 0.51, 0} +% } +% \color_model_new:nnn { pantone+black } +% { DeviceN } +% { +% names = {pantone1215,black} +% } +% \color_set:nnn{purepantone}{pantone+black}{1,0} +% \color_set:nnn{pureblack} {pantone+black}{0,1} +% \ExplSyntaxOff +% \begin{document} +% \mpfig +% fill unitsquare xscaled \mpdim{\textwidth} yscaled 30 +% withshademethod "linear" +% withshadecolors ("purepantone","pureblack") +% ; +% \endmpfig +% \end{document} +%\end{verbatim} +% \begin{macrocode} + run_tex_code({ + [[\color_export:nnN{]], str, [[}{backend}\mplib_@tempa]], + },ccexplat) + local name, value = get_macro'mplib_@tempa':match'{(.-)}{(.-)}' + local t, obj = res:explode() + if pdfmode then + obj = format("%s 0 R", ltx.pdf.object_id( t[1]:sub(2,-1) )) + else + obj = t[2] + end + return format('(1) withprescript"mplib_spotcolor=%s:%s:%s"', value,obj,name) + end + return colorsplit(res) +end + +% \end{macrocode} +% +% Remove trailing zeros for smaller PDF +% \begin{macrocode} +local function rmzeros(str) return str:gsub("%.?0+$","") end + +% \end{macrocode} +% +% luamplib's mplibgraphictext operator +% \begin{macrocode} +local emboldenfonts = { } +local function getemboldenwidth (curr, fakebold) + local width = emboldenfonts.width + if not width then + local f + local function getglyph(n) + while n do + if n.head then + getglyph(n.head) + elseif n.font and n.font > 0 then + f = n.font; break + end + n = node.getnext(n) + end + end + getglyph(curr) + width = font.getcopy(f or font.current()).size * fakebold / factor * 10 + emboldenfonts.width = width + end + return width +end +local function getrulewhatsit (line, wd, ht, dp) + line, wd, ht, dp = line/1000, wd/factor, ht/factor, dp/factor + local pl + local fmt = "%f w %f %f %f %f re %s" + if pdfmode then + pl = node.new("whatsit","pdf_literal") + pl.mode = 0 + else + fmt = "pdf:content "..fmt + pl = node.new("whatsit","special") + end + pl.data = fmt:format(line, 0, -dp, wd, ht+dp, "B") :gsub("%.%d+", rmzeros) + local ss = node.new"glue" + node.setglue(ss, 0, 65536, 65536, 2, 2) + pl.next = ss + return pl +end +local function getrulemetric (box, curr, bp) + local running = -1073741824 + local wd,ht,dp = curr.width, curr.height, curr.depth + wd = wd == running and box.width or wd + ht = ht == running and box.height or ht + dp = dp == running and box.depth or dp + if bp then + return wd/factor, ht/factor, dp/factor + end + return wd, ht, dp +end +local function embolden (box, curr, fakebold) + local head = curr + while curr do + if curr.head then + curr.head = embolden(curr, curr.head, fakebold) + elseif curr.replace then + curr.replace = embolden(box, curr.replace, fakebold) + elseif curr.leader then + if curr.leader.head then + curr.leader.head = embolden(curr.leader, curr.leader.head, fakebold) + elseif curr.leader.id == node.id"rule" then + local glue = node.effective_glue(curr, box) + local line = getemboldenwidth(curr, fakebold) + local wd,ht,dp = getrulemetric(box, curr.leader) + if box.id == node.id"hlist" then + wd = glue + else + ht, dp = 0, glue + end + local pl = getrulewhatsit(line, wd, ht, dp) + local pack = box.id == node.id"hlist" and node.hpack or node.vpack + local list = pack(pl, glue, "exactly") + head = node.insert_after(head, curr, list) + head, curr = node.remove(head, curr) + end + elseif curr.id == node.id"rule" and curr.subtype == 0 then + local line = getemboldenwidth(curr, fakebold) + local wd,ht,dp = getrulemetric(box, curr) + if box.id == node.id"vlist" then + ht, dp = 0, ht+dp + end + local pl = getrulewhatsit(line, wd, ht, dp) + local list + if box.id == node.id"hlist" then + list = node.hpack(pl, wd, "exactly") + else + list = node.vpack(pl, ht+dp, "exactly") + end + head = node.insert_after(head, curr, list) + head, curr = node.remove(head, curr) + elseif curr.id == node.id"glyph" and curr.font > 0 then + local f = curr.font + local i = emboldenfonts[f] + if not i then + local ft = font.getfont(f) or font.getcopy(f) + if pdfmode then + width = ft.size * fakebold / factor * 10 + emboldenfonts.width = width + ft.mode, ft.width = 2, width + i = font.define(ft) + else + if ft.format ~= "opentype" and ft.format ~= "truetype" then + goto skip_type1 + end + local name = ft.name:gsub('"',''):gsub(';$','') + name = format('%s;embolden=%s;',name,fakebold) + _, i = fonts.constructors.readanddefine(name,ft.size) + end + emboldenfonts[f] = i + end + curr.font = i + end + ::skip_type1:: + curr = node.getnext(curr) + end + return head +end +local function graphictextcolor (col, filldraw) + if col:find"^[%d%.:]+$" then + col = col:explode":" + if pdfmode then + local op = #col == 4 and "k" or #col == 3 and "rg" or "g" + col[#col+1] = filldraw == "fill" and op or op:upper() + return tableconcat(col," ") + end + return format("[%s]", tableconcat(col," ")) + end + col = process_color(col):match'"mpliboverridecolor=(.+)"' + if pdfmode then + local t, tt = col:explode(), { } + local b = filldraw == "fill" and 1 or #t/2+1 + local e = b == 1 and #t/2 or #t + for i=b,e do + tt[#tt+1] = t[i] + end + return tableconcat(tt," ") + end + return col:gsub("^.- ","") +end +luamplib.graphictext = function (text, fakebold, fc, dc) + local fmt = process_tex_text(text):sub(1,-2) + local id = tonumber(fmt:match"mplibtexboxid=(%d+):") + emboldenfonts.width = nil + local box = texgetbox(id) + box.head = embolden(box, box.head, fakebold) + local fill = graphictextcolor(fc,"fill") + local draw = graphictextcolor(dc,"draw") + local bc = pdfmode and "" or "pdf:bc " + return format('%s withprescript "mpliboverridecolor=%s%s %s")', fmt, bc, fill, draw) +end + +% \end{macrocode} +% +% luamplib's mplibglyph operator +% \begin{macrocode} +local function mperr (str) + return format("hide(errmessage %q)", str) +end +local function getangle (a,b,c) + local r = math.deg(math.atan(c.y-b.y, c.x-b.x) - math.atan(b.y-a.y, b.x-a.x)) + if r > 180 then + r = r - 360 + elseif r < -180 then + r = r + 360 + end + return r +end +local function turning (t) + local r, n = 0, #t + for i=1,2 do + tableinsert(t, t[i]) + end + for i=1,n do + r = r + getangle(t[i], t[i+1], t[i+2]) + end + return r/360 +end +local function glyphimage(t, fmt) + local q,p,r = {{},{}} + for i,v in ipairs(t) do + local cmd = v[#v] + if cmd == "m" then + p = {format('(%s,%s)',v[1],v[2])} + r = {{x=v[1],y=v[2]}} + else + local nt = t[i+1] + local last = not nt or nt[#nt] == "m" + if cmd == "l" then + local pt = t[i-1] + local seco = pt[#pt] == "m" + if (last or seco) and r[1].x == v[1] and r[1].y == v[2] then + else + tableinsert(p, format('--(%s,%s)',v[1],v[2])) + tableinsert(r, {x=v[1],y=v[2]}) + end + if last then + tableinsert(p, '--cycle') + end + elseif cmd == "c" then + tableinsert(p, format('..controls(%s,%s)and(%s,%s)',v[1],v[2],v[3],v[4])) + if last and r[1].x == v[5] and r[1].y == v[6] then + tableinsert(p, '..cycle') + else + tableinsert(p, format('..(%s,%s)',v[5],v[6])) + if last then + tableinsert(p, '--cycle') + end + tableinsert(r, {x=v[5],y=v[6]}) + end + else + return mperr"unknown operator" + end + if last then + tableinsert(q[ turning(r) > 0 and 1 or 2 ], tableconcat(p)) + end + end + end + r = { } + if fmt == "opentype" then + for _,v in ipairs(q[1]) do + tableinsert(r, format('addto currentpicture contour %s;',v)) + end + for _,v in ipairs(q[2]) do + tableinsert(r, format('addto currentpicture contour %s withcolor background;',v)) + end + else + for _,v in ipairs(q[2]) do + tableinsert(r, format('addto currentpicture contour %s;',v)) + end + for _,v in ipairs(q[1]) do + tableinsert(r, format('addto currentpicture contour %s withcolor background;',v)) + end + end + return format('image(%s)', tableconcat(r)) +end +if not table.tofile then require"lualibs-lpeg"; require"lualibs-table"; end +function luamplib.glyph (f, c) + local filename, subfont, instance, kind, shapedata + local fid = tonumber(f) or font.id(f) + if fid > 0 then + local fontdata = font.getfont(fid) or font.getcopy(fid) + filename, subfont, kind = fontdata.filename, fontdata.subfont, fontdata.format + instance = fontdata.specification and fontdata.specification.instance + filename = filename and filename:gsub("^harfloaded:","") + else + local name + f = f:match"^%s*(.+)%s*$" + name, subfont, instance = f:match"(.+)%((%d+)%)%[(.-)%]$" + if not name then + name, instance = f:match"(.+)%[(.-)%]$" -- SourceHanSansK-VF.otf[Heavy] + end + if not name then + name, subfont = f:match"(.+)%((%d+)%)$" -- Times.ttc(2) + end + name = name or f + subfont = (subfont or 0)+1 + instance = instance and instance:lower() + for _,ftype in ipairs{"opentype", "truetype"} do + filename = kpse.find_file(name, ftype.." fonts") + if filename then + kind = ftype; break + end + end + end + if kind ~= "opentype" and kind ~= "truetype" then + f = fid and fid > 0 and tex.fontname(fid) or f + if kpse.find_file(f, "tfm") then + return format("glyph %s of %q", tonumber(c) or format("%q",c), f) + else + return mperr"font not found" + end + end + local time = lfsattributes(filename,"modification") + local k = format("shapes_%s(%s)[%s]", filename, subfont or "", instance or "") + local h = format(string.rep('%02x', 256/8), string.byte(sha2.digest256(k), 1, -1)) + local newname = format("%s/%s.lua", cachedir or outputdir, h) + local newtime = lfsattributes(newname,"modification") or 0 + if time == newtime then + shapedata = require(newname) + end + if not shapedata then + shapedata = fonts and fonts.handlers.otf.readers.loadshapes(filename,subfont,instance) + if not shapedata then return mperr"loadshapes() failed. luaotfload not loaded?" end + table.tofile(newname, shapedata, "return") + lfstouch(newname, time, time) + end + local gid = tonumber(c) + if not gid then + local uni = utf8.codepoint(c) + for i,v in pairs(shapedata.glyphs) do + if c == v.name or uni == v.unicode then + gid = i; break + end + end + end + if not gid then return mperr"cannot get GID (glyph id)" end + local fac = 1000 / (shapedata.units or 1000) + local t = shapedata.glyphs[gid].segments + if not t then return "image()" end + for i,v in ipairs(t) do + if type(v) == "table" then + for ii,vv in ipairs(v) do + if type(vv) == "number" then + t[i][ii] = format("%.0f", vv * fac) + end + end + end + end + kind = shapedata.format or kind + return glyphimage(t, kind) +end + +% \end{macrocode} +% +% mpliboutlinetext : based on mkiv's font-mps.lua +% \begin{macrocode} +local rulefmt = "mpliboutlinepic[%i]:=image(addto currentpicture contour \z + unitsquare shifted - center unitsquare;) xscaled %f yscaled %f shifted (%f,%f);" +local outline_horz, outline_vert +function outline_vert (res, box, curr, xshift, yshift) + local b2u = box.dir == "LTL" + local dy = (b2u and -box.depth or box.height)/factor + local ody = dy + while curr do + if curr.id == node.id"rule" then + local wd, ht, dp = getrulemetric(box, curr, true) + local hd = ht + dp + if hd ~= 0 then + dy = dy + (b2u and dp or -ht) + if wd ~= 0 and curr.subtype == 0 then + res[#res+1] = rulefmt:format(#res+1, wd, hd, xshift+wd/2, yshift+dy+(ht-dp)/2) + end + dy = dy + (b2u and ht or -dp) + end + elseif curr.id == node.id"glue" then + local vwidth = node.effective_glue(curr,box)/factor + if curr.leader then + local curr, kind = curr.leader, curr.subtype + if curr.id == node.id"rule" then + local wd = getrulemetric(box, curr, true) + if wd ~= 0 then + local hd = vwidth + local dy = dy + (b2u and 0 or -hd) + if hd ~= 0 and curr.subtype == 0 then + res[#res+1] = rulefmt:format(#res+1, wd, hd, xshift+wd/2, yshift+dy+hd/2) + end + end + elseif curr.head then + local hd = (curr.height + curr.depth)/factor + if hd <= vwidth then + local dy, n, iy = dy, 0, 0 + if kind == 100 or kind == 103 then -- todo: gleaders + local ady = abs(ody - dy) + local ndy = math.ceil(ady / hd) * hd + local diff = ndy - ady + n = (vwidth-diff) // hd + dy = dy + (b2u and diff or -diff) + else + n = vwidth // hd + if kind == 101 then + local side = vwidth % hd / 2 + dy = dy + (b2u and side or -side) + elseif kind == 102 then + iy = vwidth % hd / (n+1) + dy = dy + (b2u and iy or -iy) + end + end + dy = dy + (b2u and curr.depth or -curr.height)/factor + hd = b2u and hd or -hd + iy = b2u and iy or -iy + local func = curr.id == node.id"hlist" and outline_horz or outline_vert + for i=1,n do + res = func(res, curr, curr.head, xshift+curr.shift/factor, yshift+dy) + dy = dy + hd + iy + end + end + end + end + dy = dy + (b2u and vwidth or -vwidth) + elseif curr.id == node.id"kern" then + dy = dy + curr.kern/factor * (b2u and 1 or -1) + elseif curr.id == node.id"vlist" then + dy = dy + (b2u and curr.depth or -curr.height)/factor + res = outline_vert(res, curr, curr.head, xshift+curr.shift/factor, yshift+dy) + dy = dy + (b2u and curr.height or -curr.depth)/factor + elseif curr.id == node.id"hlist" then + dy = dy + (b2u and curr.depth or -curr.height)/factor + res = outline_horz(res, curr, curr.head, xshift+curr.shift/factor, yshift+dy) + dy = dy + (b2u and curr.height or -curr.depth)/factor + end + curr = node.getnext(curr) + end + return res +end +function outline_horz (res, box, curr, xshift, yshift, discwd) + local r2l = box.dir == "TRT" + local dx = r2l and (discwd or box.width/factor) or 0 + local dirs = { { dir = r2l, dx = dx } } + while curr do + if curr.id == node.id"dir" then + local sign, dir = curr.dir:match"(.)(...)" + local level, newdir = curr.level, r2l + if sign == "+" then + newdir = dir == "TRT" + if r2l ~= newdir then + local n = node.getnext(curr) + while n do + if n.id == node.id"dir" and n.level+1 == level then break end + n = node.getnext(n) + end + n = n or node.tail(curr) + dx = dx + node.rangedimensions(box, curr, n)/factor * (newdir and 1 or -1) + end + dirs[level] = { dir = r2l, dx = dx } + else + local level = level + 1 + newdir = dirs[level].dir + if r2l ~= newdir then + dx = dirs[level].dx + end + end + r2l = newdir + elseif curr.char and curr.font and curr.font > 0 then + local ft = font.getfont(curr.font) or font.getcopy(curr.font) + local gid = ft.characters[curr.char].index or curr.char + local scale = ft.size / factor / 1000 + local slant = (ft.slant or 0)/1000 + local extend = (ft.extend or 1000)/1000 + local squeeze = (ft.squeeze or 1000)/1000 + local expand = 1 + (curr.expansion_factor or 0)/1000000 + local xscale = scale * extend * expand + local yscale = scale * squeeze + dx = dx - (r2l and curr.width/factor*expand or 0) + local xpos = dx + xshift + (curr.xoffset or 0)/factor + local ypos = yshift + (curr.yoffset or 0)/factor + local vertical = ft.shared and ft.shared.features.vertical and "rotated 90" or "" + if vertical ~= "" then -- luatexko + for _,v in ipairs(ft.characters[curr.char].commands or { }) do + if v[1] == "down" then + ypos = ypos - v[2] / factor + elseif v[1] == "right" then + xpos = xpos + v[2] / factor + else + break + end + end + end + local image + if ft.format == "opentype" or ft.format == "truetype" then + image = luamplib.glyph(curr.font, gid) + else + local name, scale = ft.name, 1 + local vf = font.read_vf(name, ft.size) + if vf and vf.characters[gid] then + local cmds = vf.characters[gid].commands or {} + for _,v in ipairs(cmds) do + if v[1] == "char" then + gid = v[2] + elseif v[1] == "font" and vf.fonts[v[2]] then + name = vf.fonts[v[2]].name + scale = vf.fonts[v[2]].size / ft.size + end + end + end + image = format("glyph %s of %q scaled %f", gid, name, scale) + end + res[#res+1] = format("mpliboutlinepic[%i]:=%s xscaled %f yscaled %f slanted %f %s shifted (%f,%f);", + #res+1, image, xscale, yscale, slant, vertical, xpos, ypos) + dx = dx + (r2l and 0 or curr.width/factor*expand) + elseif curr.replace then + local width = node.dimensions(curr.replace)/factor + dx = dx - (r2l and width or 0) + res = outline_horz(res, box, curr.replace, xshift+dx, yshift, width) + dx = dx + (r2l and 0 or width) + elseif curr.id == node.id"rule" then + local wd, ht, dp = getrulemetric(box, curr, true) + if wd ~= 0 then + local hd = ht + dp + dx = dx - (r2l and wd or 0) + if hd ~= 0 and curr.subtype == 0 then + res[#res+1] = rulefmt:format(#res+1, wd, hd, xshift+dx+wd/2, yshift+(ht-dp)/2) + end + dx = dx + (r2l and 0 or wd) + end + elseif curr.id == node.id"glue" then + local width = node.effective_glue(curr, box)/factor + dx = dx - (r2l and width or 0) + if curr.leader then + local curr, kind = curr.leader, curr.subtype + if curr.id == node.id"rule" then + local wd, ht, dp = getrulemetric(box, curr, true) + local hd = ht + dp + if hd ~= 0 then + wd = width + if wd ~= 0 and curr.subtype == 0 then + res[#res+1] = rulefmt:format(#res+1, wd, hd, xshift+dx+wd/2, yshift+(ht-dp)/2) + end + end + elseif curr.head then + local wd = curr.width/factor + if wd <= width then + local dx = r2l and dx+width or dx + local n, ix = 0, 0 + if kind == 100 or kind == 103 then -- todo: gleaders + local adx = abs(dx-dirs[1].dx) + local ndx = math.ceil(adx / wd) * wd + local diff = ndx - adx + n = (width-diff) // wd + dx = dx + (r2l and -diff-wd or diff) + else + n = width // wd + if kind == 101 then + local side = width % wd /2 + dx = dx + (r2l and -side-wd or side) + elseif kind == 102 then + ix = width % wd / (n+1) + dx = dx + (r2l and -ix-wd or ix) + end + end + wd = r2l and -wd or wd + ix = r2l and -ix or ix + local func = curr.id == node.id"hlist" and outline_horz or outline_vert + for i=1,n do + res = func(res, curr, curr.head, xshift+dx, yshift-curr.shift/factor) + dx = dx + wd + ix + end + end + end + end + dx = dx + (r2l and 0 or width) + elseif curr.id == node.id"kern" then + dx = dx + curr.kern/factor * (r2l and -1 or 1) + elseif curr.id == node.id"math" then + dx = dx + curr.surround/factor * (r2l and -1 or 1) + elseif curr.id == node.id"vlist" then + dx = dx - (r2l and curr.width/factor or 0) + res = outline_vert(res, curr, curr.head, xshift+dx, yshift-curr.shift/factor) + dx = dx + (r2l and 0 or curr.width/factor) + elseif curr.id == node.id"hlist" then + dx = dx - (r2l and curr.width/factor or 0) + res = outline_horz(res, curr, curr.head, xshift+dx, yshift-curr.shift/factor) + dx = dx + (r2l and 0 or curr.width/factor) + end + curr = node.getnext(curr) + end + return res +end +function luamplib.outlinetext (text) + local fmt = process_tex_text(text) + local id = tonumber(fmt:match"mplibtexboxid=(%d+):") + local box = texgetbox(id) + local res = outline_horz({ }, box, box.head, 0, 0) + if #res == 0 then res = { "mpliboutlinepic[1]:=image();" } end + return tableconcat(res) .. format("mpliboutlinenum:=%i;", #res) +end + +% \end{macrocode} +% +% Our \metapost preambles +% \begin{macrocode} +luamplib.preambles = { + mplibcode = [[ texscriptmode := 2; def rawtextext (expr t) = runscript("luamplibtext{"&t&"}") enddef; def mplibcolor (expr t) = runscript("luamplibcolor{"&t&"}") enddef; @@ -1424,82 +2446,242 @@ if known context_mlib: (1-mfun_labxf@#-mfun_labyf@#)*llcorner p)) fi enddef; - def colordecimals primary c = - if cmykcolor c: - decimal cyanpart c & ":" & decimal magentapart c & ":" & decimal yellowpart c & ":" & decimal blackpart c - elseif rgbcolor c: - decimal redpart c & ":" & decimal greenpart c & ":" & decimal bluepart c - elseif string c: - colordecimals resolvedcolor(c) - else: - decimal c - fi - enddef; - def resolvedcolor(expr s) = - runscript("return luamplib.shadecolor('"& s &"')") - enddef; else: vardef textext@# (text t) = rawtextext (t) enddef; + def message expr t = + if string t: runscript("mp.report[=["&t&"]=]") else: errmessage "Not a string" fi + enddef; fi +def resolvedcolor(expr s) = + runscript("return luamplib.shadecolor('"& s &"')") +enddef; +def colordecimals primary c = + if cmykcolor c: + decimal cyanpart c & ":" & decimal magentapart c & ":" & + decimal yellowpart c & ":" & decimal blackpart c + elseif rgbcolor c: + decimal redpart c & ":" & decimal greenpart c & ":" & decimal bluepart c + elseif string c: + if known graphictextpic: c else: colordecimals resolvedcolor(c) fi + else: + decimal c + fi +enddef; def externalfigure primary filename = draw rawtextext("\includegraphics{"& filename &"}") enddef; def TEX = textext enddef; +def mplibtexcolor primary c = + runscript("return luamplib.gettexcolor('"& c &"')") +enddef; +def mplibrgbtexcolor primary c = + runscript("return luamplib.gettexcolor('"& c &"','rgb')") +enddef; def mplibgraphictext primary t = begingroup; mplibgraphictext_ (t) enddef; def mplibgraphictext_ (expr t) text rest = save fakebold, scale, fillcolor, drawcolor, withfillcolor, withdrawcolor, - fb, sc, fc, dc, fn, dn, tpic; - picture tpic; tpic := nullpicture; - numeric fb, sc; string fc, dc, fn, dn; - fb:=2; sc:=1; fc:="white"; dc:="black"; fn:=dn:="n"; + fb, fc, dc, graphictextpic; + picture graphictextpic; graphictextpic := nullpicture; + numeric fb; string fc, dc; fb:=2; fc:="white"; dc:="black"; + let scale = scaled; def fakebold primary c = hide(fb:=c;) enddef; - def scale primary c = hide(sc:=c;) enddef; - def fillcolor primary c = hide( - if string c: - runscript("return luamplib.outlinecolor('"& c &"','fill')") - else: - fn:="nn"; fc:=mpliboutlinecolor_(c); - fi - ) enddef; - def drawcolor primary c = hide( - if string c: - runscript("return luamplib.outlinecolor('"& c &"','draw')") - else: - dn:="nn"; dc:=mpliboutlinecolor_(c); - fi - ) enddef; + def fillcolor primary c = hide(fc:=colordecimals c;) enddef; + def drawcolor primary c = hide(dc:=colordecimals c;) enddef; let withfillcolor = fillcolor; let withdrawcolor = drawcolor; - addto tpic doublepath origin rest; tpic:=nullpicture; + addto graphictextpic doublepath origin rest; graphictextpic:=nullpicture; def fakebold primary c = enddef; - def scale primary c = enddef; - def fillcolor primary c = enddef; - def drawcolor primary c = enddef; + let fillcolor = fakebold; let drawcolor = fakebold; let withfillcolor = fillcolor; let withdrawcolor = drawcolor; - image(draw rawtextext( - "{\addfontfeature{FakeBold="& decimal fb &",Scale="& decimal sc & - "}\csname color_fill:"& fn &"\endcsname{"& fc & - "}\csname color_stroke:"& dn &"\endcsname{"& dc & - "}"& t &"}") rest;) + image(draw runscript("return luamplib.graphictext([===["&t&"]===]," + & decimal fb &",'"& fc &"','"& dc &"')") rest;) endgroup; enddef; -def mpliboutlinecolor_ (expr c) = - if color c: - "rgb}{" & decimal redpart c & "," & decimal greenpart c - & "," & decimal bluepart c - elseif cmykcolor c: - "cmyk}{" & decimal cyanpart c & "," & decimal magentapart c - & "," & decimal yellowpart c & "," & decimal blackpart c +def mplibglyph expr c of f = + runscript ( + "return luamplib.glyph('" + & if numeric f: decimal fi f + & "','" + & if numeric c: decimal fi c + & "')" + ) +enddef; +def mplibdrawglyph expr g = + draw image( + save i; numeric i; i:=0; + for item within g: + i := i+1; + fill pathpart item + if i < length g: withpostscript "collect" fi; + endfor + ) +enddef; +def mplib_do_outline_text_set_b (text f) (text d) text r = + def mplib_do_outline_options_f = f enddef; + def mplib_do_outline_options_d = d enddef; + def mplib_do_outline_options_r = r enddef; +enddef; +def mplib_do_outline_text_set_f (text f) text r = + def mplib_do_outline_options_f = f enddef; + def mplib_do_outline_options_r = r enddef; +enddef; +def mplib_do_outline_text_set_u (text f) text r = + def mplib_do_outline_options_f = f enddef; +enddef; +def mplib_do_outline_text_set_d (text d) text r = + def mplib_do_outline_options_d = d enddef; + def mplib_do_outline_options_r = r enddef; +enddef; +def mplib_do_outline_text_set_r (text d) (text f) text r = + def mplib_do_outline_options_d = d enddef; + def mplib_do_outline_options_f = f enddef; + def mplib_do_outline_options_r = r enddef; +enddef; +def mplib_do_outline_text_set_n text r = + def mplib_do_outline_options_r = r enddef; +enddef; +def mplib_do_outline_text_set_p = enddef; +def mplib_fill_outline_text = + for n=1 upto mpliboutlinenum: + i:=0; + for item within mpliboutlinepic[n]: + i:=i+1; + fill pathpart item mplib_do_outline_options_f withpen pencircle scaled 0 + if (n<mpliboutlinenum) or (i<length mpliboutlinepic[n]): withpostscript "collect"; fi + endfor + endfor +enddef; +def mplib_draw_outline_text = + for n=1 upto mpliboutlinenum: + for item within mpliboutlinepic[n]: + draw pathpart item mplib_do_outline_options_d; + endfor + endfor +enddef; +def mplib_filldraw_outline_text = + for n=1 upto mpliboutlinenum: + i:=0; + for item within mpliboutlinepic[n]: + i:=i+1; + if (n<mpliboutlinenum) or (i<length mpliboutlinepic[n]): + fill pathpart item mplib_do_outline_options_f withpostscript "collect"; + else: + draw pathpart item mplib_do_outline_options_f withpostscript "both"; + fi + endfor + endfor +enddef; +vardef mpliboutlinetext@# (expr t) text rest = + save kind; string kind; kind := str @#; + save i; numeric i; + picture mpliboutlinepic[]; numeric mpliboutlinenum; + def mplib_do_outline_options_d = enddef; + def mplib_do_outline_options_f = enddef; + def mplib_do_outline_options_r = enddef; + runscript("return luamplib.outlinetext[===["&t&"]===]"); + image ( addto currentpicture also image ( + if kind = "f": + mplib_do_outline_text_set_f rest; + mplib_fill_outline_text; + elseif kind = "d": + mplib_do_outline_text_set_d rest; + mplib_draw_outline_text; + elseif kind = "b": + mplib_do_outline_text_set_b rest; + mplib_fill_outline_text; + mplib_draw_outline_text; + elseif kind = "u": + mplib_do_outline_text_set_u rest; + mplib_filldraw_outline_text; + elseif kind = "r": + mplib_do_outline_text_set_r rest; + mplib_draw_outline_text; + mplib_fill_outline_text; + elseif kind = "p": + mplib_do_outline_text_set_p; + mplib_draw_outline_text; + else: + mplib_do_outline_text_set_n rest; + mplib_fill_outline_text; + fi; + ) mplib_do_outline_options_r; ) +enddef ; +primarydef t withpattern p = + image( fill t withprescript "mplibpattern=" & if numeric p: decimal fi p; ) +enddef; +vardef mplibtransformmatrix (text e) = + save t; transform t; + t = identity e; + runscript("luamplib.transformmatrix = {" + & decimal xxpart t & "," + & decimal yxpart t & "," + & decimal xypart t & "," + & decimal yypart t & "," + & decimal xpart t & "," + & decimal ypart t & "," + & "}"); +enddef; +primarydef p withfademethod s = + if picture p: + image( + draw p; + draw center p withprescript "mplibfadestate=stop"; + ) else: - "gray}{" & decimal c + p withprescript "mplibfadestate=stop" fi + withprescript "mplibfadetype=" & s + withprescript "mplibfadebbox=" & + decimal xpart llcorner p & ":" & + decimal ypart llcorner p & ":" & + decimal xpart urcorner p & ":" & + decimal ypart urcorner p enddef; -]] -luamplib.mplibcodepreamble = mplibcodepreamble - -local legacyverbatimtexpreamble = [[ +def withfadeopacity (expr a,b) = + withprescript "mplibfadeopacity=" & + decimal a & ":" & + decimal b +enddef; +def withfadevector (expr a,b) = + withprescript "mplibfadevector=" & + decimal xpart a & ":" & + decimal ypart a & ":" & + decimal xpart b & ":" & + decimal ypart b +enddef; +let withfadecenter = withfadevector; +def withfaderadius (expr a,b) = + withprescript "mplibfaderadius=" & + decimal a & ":" & + decimal b +enddef; +def withfadebbox (expr a,b) = + withprescript "mplibfadebbox=" & + decimal xpart a & ":" & + decimal ypart a & ":" & + decimal xpart b & ":" & + decimal ypart b +enddef; +primarydef p asgroup s = + image( + fill llcorner p--lrcorner p--urcorner p--ulcorner p--cycle + withprescript "gr_state=start" + withprescript "gr_type=" & s; + draw p; + draw center p withprescript "gr_state=stop"; + ) +enddef; +def withgroupname expr s = + withprescript "mplibgroupname=" & s +enddef; +def usemplibgroup primary s = + draw maketext("\usemplibgroup{" & s & "}") + shifted runscript("return luamplib.trgroupshifts['" & s & "']") +enddef; +]], + legacyverbatimtex = [[ def specialVerbatimTeX (text t) = runscript("luamplibprefig{"&t&"}") enddef; def normalVerbatimTeX (text t) = runscript("luamplibinfig{"&t&"}") enddef; let VerbatimTeX = specialVerbatimTeX; @@ -1509,10 +2691,8 @@ extra_endfig := extra_endfig & " let VerbatimTeX = specialVerbatimTeX;"& "runscript(" &ditto& "if luamplib.in_the_fig then luamplib.figid=luamplib.figid+1 end "& "luamplib.in_the_fig=false" &ditto& ");"; -]] -luamplib.legacyverbatimtexpreamble = legacyverbatimtexpreamble - -local textextlabelpreamble = [[ +]], + textextlabel = [[ primarydef s infont f = rawtextext(s) enddef; def fontsize expr f = begingroup @@ -1521,15 +2701,14 @@ def fontsize expr f = if size = 0: 10pt else: size fi endgroup enddef; -]] -luamplib.textextlabelpreamble = textextlabelpreamble +]], +} % \end{macrocode} % % When \cs{mplibverbatim} is enabled, do not expand |mplibcode| data. % \begin{macrocode} luamplib.verbatiminput = false - % \end{macrocode} % % Do not expand |btex ... etex|, |verbatimtex ... etex|, and @@ -1545,7 +2724,6 @@ local function protect_expansion (str) return format("\\unexpanded{%s}",str) end end - local function unprotect_expansion (str) if str then return str:gsub("!!!Control!!!", "\\") @@ -1555,27 +2733,20 @@ local function unprotect_expansion (str) :gsub("!!!RBrace!!!", "}") end end - -luamplib.everymplib = { [""] = "" } -luamplib.everyendmplib = { [""] = "" } - -local function process_mplibcode (data, instance) - instancename = instance - texboxes.locals, texboxes.localid = {}, 4096 - +luamplib.everymplib = setmetatable({ [""] = "" },{ __index = function(t) return t[""] end }) +luamplib.everyendmplib = setmetatable({ [""] = "" },{ __index = function(t) return t[""] end }) +function luamplib.process_mplibcode (data, instancename) + texboxes.localid = 4096 % \end{macrocode} -% -% This is needed for legacy behavior regarding |verbatimtex| +% This is needed for legacy behavior % \begin{macrocode} - legacy_mplibcode_reset() - - local everymplib = luamplib.everymplib[instancename] or - luamplib.everymplib[""] - local everyendmplib = luamplib.everyendmplib[instancename] or - luamplib.everyendmplib[""] + if luamplib.legacyverbatimtex then + luamplib.figid, tex_code_pre_mplib = 1, {} + end + local everymplib = luamplib.everymplib[instancename] + local everyendmplib = luamplib.everyendmplib[instancename] data = format("\n%s\n%s\n%s\n",everymplib, data, everyendmplib) :gsub("\r","\n") - % \end{macrocode} % These five lines are needed for |mplibverbatim| mode. % \begin{macrocode} @@ -1586,7 +2757,6 @@ local function process_mplibcode (data, instance) :gsub(btex_etex, "btex %1 etex ") :gsub(verbatimtex_etex, "verbatimtex %1 etex;") % \end{macrocode} -% % If not |mplibverbatim|, expand |mplibcode| data, % so that users can use \TeX\ codes in it. % It has turned out that no comment sign is allowed. @@ -1605,7 +2775,6 @@ local function process_mplibcode (data, instance) run_tex_code(format("\\mplibtmptoks\\expandafter{\\expanded{%s}}",data)) data = texgettoks"mplibtmptoks" % \end{macrocode} -% % Next line to address issue \#55 % \begin{macrocode} :gsub("##", "#") @@ -1617,10 +2786,8 @@ local function process_mplibcode (data, instance) return format("verbatimtex %s etex", unprotect_expansion(str)) end) end - - process(data) + process(data, instancename) end -luamplib.process_mplibcode = process_mplibcode % \end{macrocode} % @@ -1648,145 +2815,34 @@ end % \end{macrocode} % -% Codes below for inserting PDF lieterals are mostly from ConTeXt general, -% with small changes when needed. +% pdfliterals will be stored in |figcontents| table, and written to pdf in one go +% at the end of the flushing figure. +% Subtable |post| is for the legacy behavior. % \begin{macrocode} -local function getobjects(result,figure,f) - return figure:objects() -end - -local function convert(result, flusher) - luamplib.flush(result, flusher) - return true -- done -end -luamplib.convert = convert - local figcontents = { post = { } } local function put2output(a,...) figcontents[#figcontents+1] = type(a) == "string" and format(a,...) or a end - local function pdf_startfigure(n,llx,lly,urx,ury) put2output("\\mplibstarttoPDF{%f}{%f}{%f}{%f}",llx,lly,urx,ury) end - local function pdf_stopfigure() put2output("\\mplibstoptoPDF") end - % \end{macrocode} % % |tex.sprint| with catcode regime -2, as sometimes |#| gets doubled % in the argument of pdfliteral. % \begin{macrocode} -local function pdf_literalcode (fmt,...) - put2output{-2, format(fmt,...)} -end - -local function pdf_textfigure(font,size,text,width,height,depth) - text = text:gsub(".",function(c) - return format("\\hbox{\\char%i}",string.byte(c)) -- kerning happens in metapost : false - end) - put2output("\\mplibtextext{%s}{%f}{%s}{%s}{%s}",font,size,text,0,0) -end - -local bend_tolerance = 131/65536 - -local rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1 - -local function pen_characteristics(object) - local t = mplib.pen_info(object) - rx, ry, sx, sy, tx, ty = t.rx, t.ry, t.sx, t.sy, t.tx, t.ty - divider = sx*sy - rx*ry - return not (sx==1 and rx==0 and ry==0 and sy==1 and tx==0 and ty==0), t.width -end - -local function concat(px, py) -- no tx, ty here - return (sy*px-ry*py)/divider,(sx*py-rx*px)/divider -end - -local function curved(ith,pth) - local d = pth.left_x - ith.right_x - if abs(ith.right_x - ith.x_coord - d) <= bend_tolerance and abs(pth.x_coord - pth.left_x - d) <= bend_tolerance then - d = pth.left_y - ith.right_y - if abs(ith.right_y - ith.y_coord - d) <= bend_tolerance and abs(pth.y_coord - pth.left_y - d) <= bend_tolerance then - return false - end - end - return true -end - -local function flushnormalpath(path,open) - local pth, ith - for i=1,#path do - pth = path[i] - if not ith then - pdf_literalcode("%f %f m",pth.x_coord,pth.y_coord) - elseif curved(ith,pth) then - pdf_literalcode("%f %f %f %f %f %f c",ith.right_x,ith.right_y,pth.left_x,pth.left_y,pth.x_coord,pth.y_coord) - else - pdf_literalcode("%f %f l",pth.x_coord,pth.y_coord) - end - ith = pth - end - if not open then - local one = path[1] - if curved(pth,one) then - pdf_literalcode("%f %f %f %f %f %f c",pth.right_x,pth.right_y,one.left_x,one.left_y,one.x_coord,one.y_coord ) - else - pdf_literalcode("%f %f l",one.x_coord,one.y_coord) - end - elseif #path == 1 then -- special case .. draw point - local one = path[1] - pdf_literalcode("%f %f l",one.x_coord,one.y_coord) - end -end - -local function flushconcatpath(path,open) - pdf_literalcode("%f %f %f %f %f %f cm", sx, rx, ry, sy, tx ,ty) - local pth, ith - for i=1,#path do - pth = path[i] - if not ith then - pdf_literalcode("%f %f m",concat(pth.x_coord,pth.y_coord)) - elseif curved(ith,pth) then - local a, b = concat(ith.right_x,ith.right_y) - local c, d = concat(pth.left_x,pth.left_y) - pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concat(pth.x_coord, pth.y_coord)) - else - pdf_literalcode("%f %f l",concat(pth.x_coord, pth.y_coord)) - end - ith = pth - end - if not open then - local one = path[1] - if curved(pth,one) then - local a, b = concat(pth.right_x,pth.right_y) - local c, d = concat(one.left_x,one.left_y) - pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concat(one.x_coord, one.y_coord)) - else - pdf_literalcode("%f %f l",concat(one.x_coord,one.y_coord)) - end - elseif #path == 1 then -- special case .. draw point - local one = path[1] - pdf_literalcode("%f %f l",concat(one.x_coord,one.y_coord)) - end -end - -local function start_pdf_code() - if pdfmode then - pdf_literalcode("q") - else - put2output"\\special{pdf:bcontent}" - end -end -local function stop_pdf_code() - if pdfmode then - pdf_literalcode("Q") - else - put2output"\\special{pdf:econtent}" - end +local function pdf_literalcode (...) + put2output{ -2, format(...) :gsub("%.%d+", rmzeros) } end +local start_pdf_code = pdfmode + and function() pdf_literalcode"q" end + or function() put2output"\\special{pdf:bcontent}" end +local stop_pdf_code = pdfmode + and function() pdf_literalcode"Q" end + or function() put2output"\\special{pdf:econtent}" end % \end{macrocode} % @@ -1820,38 +2876,124 @@ end % \end{macrocode} % -% Colors and Transparency +% Colors +% \begin{macrocode} +local prev_override_color +local function do_preobj_CR(object,prescript) + if object.postscript == "collect" then return end + local override = prescript and prescript.mpliboverridecolor + if override then + if pdfmode then + pdf_literalcode(override) + override = nil + else + put2output("\\special{%s}",override) + prev_override_color = override + end + else + local cs = object.color + if cs and #cs > 0 then + pdf_literalcode(luamplib.colorconverter(cs)) + prev_override_color = nil + elseif not pdfmode then + override = prev_override_color + if override then + put2output("\\special{%s}",override) + end + end + end + return override +end + +% \end{macrocode} +% +% For transparency and shading % \begin{macrocode} local pdfmanagement = is_defined'pdfmanagement_add:nnn' local pdfobjs, pdfetcs = {}, {} pdfetcs.pgfextgs = "pgf@sys@addpdfresource@extgs@plain" - -if pdfmode then - pdfetcs.getpageres = pdf.getpageresources or function() return pdf.pageresources end - pdfetcs.setpageres = pdf.setpageresources or function(s) pdf.pageresources = s end -else - texsprint("\\special{pdf:obj @MPlibTr<<>>}","\\special{pdf:obj @MPlibSh<<>>}") -end - -local function update_pdfobjs (os) - local on = pdfobjs[os] +pdfetcs.pgfpattern = "pgf@sys@addpdfresource@patterns@plain" +pdfetcs.pgfcolorspace = "pgf@sys@addpdfresource@colorspaces@plain" +local function update_pdfobjs (os, stream) + local key = os + if stream then key = key..stream end + local on = pdfobjs[key] if on then return on,false end if pdfmode then - on = pdf.immediateobj(os) + if stream then + on = pdf.immediateobj("stream",stream,os) + else + on = pdf.immediateobj(os) + end else on = pdfetcs.cnt or 1 - texsprint(format("\\special{pdf:obj @mplibpdfobj%s %s}",on,os)) + if stream then + texsprint(format("\\special{pdf:stream @mplibpdfobj%s (%s) <<%s>>}",on,stream,os)) + else + texsprint(format("\\special{pdf:obj @mplibpdfobj%s %s}",on,os)) + end pdfetcs.cnt = on + 1 end - pdfobjs[os] = on + pdfobjs[key] = on return on,true end +pdfetcs.resfmt = pdfmode and "%s 0 R" or "@mplibpdfobj%s" +if pdfmode then + pdfetcs.getpageres = pdf.getpageresources or function() return pdf.pageresources end + local getpageres = pdfetcs.getpageres + local setpageres = pdf.setpageresources or function(s) pdf.pageresources = s end + local initialize_resources = function (name) + local tabname = format("%s_res",name) + pdfetcs[tabname] = { } + if luatexbase.callbacktypes.finish_pdffile then -- ltluatex + local obj = pdf.reserveobj() + setpageres(format("%s/%s %i 0 R", getpageres() or "", name, obj)) + luatexbase.add_to_callback("finish_pdffile", function() + pdf.immediateobj(obj, format("<<%s>>", tableconcat(pdfetcs[tabname]))) + end, + format("luamplib.%s.finish_pdffile",name)) + end + end + pdfetcs.fallback_update_resources = function (name, res) + local tabname = format("%s_res",name) + if not pdfetcs[tabname] then + initialize_resources(name) + end + if luatexbase.callbacktypes.finish_pdffile then + local t = pdfetcs[tabname] + t[#t+1] = res + else + local tpr, n = getpageres() or "", 0 + tpr, n = tpr:gsub(format("/%s<<",name), "%1"..res) + if n == 0 then + tpr = format("%s/%s<<%s>>", tpr, name, res) + end + setpageres(tpr) + end + end +else + texsprint { + "\\luamplibatfirstshipout{", + "\\special{pdf:obj @MPlibTr<<>>}", + "\\special{pdf:obj @MPlibSh<<>>}", + "\\special{pdf:obj @MPlibCS<<>>}", + "\\special{pdf:obj @MPlibPt<<>>}}", + } + pdfetcs.resadded = { } + pdfetcs.fallback_update_resources = function (name,obj,res) + texsprint{"\\special{pdf:put ", obj, " <<", res, ">>}"} + if not pdfetcs.resadded[name] then + texsprint{"\\luamplibateveryshipout{\\special{pdf:put @resources <</", name, " ", obj, ">>}}"} + pdfetcs.resadded[name] = obj + end + end +end % \end{macrocode} % -% transparency +% Transparency % \begin{macrocode} local transparancy_modes = { [0] = "Normal", "Normal", "Multiply", "Screen", "Overlay", @@ -1860,39 +3002,20 @@ local transparancy_modes = { [0] = "Normal", "Hue", "Saturation", "Color", "Luminosity", "Compatible", } - -local function opacity_initialize () - pdfetcs.opacity_res = {} - if pdfmode and luatexbase.callbacktypes.finish_pdffile then -- ltluatex - local extgstate_obj = pdf.reserveobj() - pdfetcs.setpageres(format("%s/ExtGState %i 0 R",pdfetcs.getpageres() or "",extgstate_obj)) - luatexbase.add_to_callback("finish_pdffile", function() - pdf.immediateobj(extgstate_obj, format("<<%s>>",tableconcat(pdfetcs.opacity_res))) - end, "luamplib.opacity.finish_pdffile") - end -end - -local function update_tr_res(mode,opaq) - if pdfetcs.pgfloaded == nil then - pdfetcs.pgfloaded = is_defined(pdfetcs.pgfextgs) - if not pdfmanagement and not pdfetcs.pgfloaded and not is_defined"TRP@list" then - opacity_initialize() - end - end - local os = format("<</BM /%s/ca %.3f/CA %.3f/AIS false>>",mode,opaq,opaq) - local on, new = update_pdfobjs(os) +local function add_extgs_resources (on, new) + local key = format("MPlibTr%s", on) if new then - if pdfmode then - if pdfmanagement then - texsprint(ccexplat,{ - [[\pdfmanagement_add:nnn{Page/Resources/ExtGState}]], - format("{MPlibTr%s}{%s 0 R}", on, on), - }) - else - local tr = format("/MPlibTr%s %s 0 R",on,on) - if pdfetcs.pgfloaded then - texsprint(format("\\csname %s\\endcsname{%s}", pdfetcs.pgfextgs,tr)) - elseif is_defined"TRP@list" then + local val = format(pdfetcs.resfmt, on) + if pdfmanagement then + texsprint { + "\\csname pdfmanagement_add:nnn\\endcsname{Page/Resources/ExtGState}{", key, "}{", val, "}" + } + else + local tr = format("/%s %s", key, val) + if is_defined(pdfetcs.pgfextgs) then + texsprint { "\\csname ", pdfetcs.pgfextgs, "\\endcsname{", tr, "}" } + elseif pdfmode then + if is_defined"TRP@list" then texsprint(catat11,{ [[\if@filesw\immediate\write\@auxout{]], [[\string\g@addto@macro\string\TRP@list{]], @@ -1903,101 +3026,42 @@ local function update_tr_res(mode,opaq) texsprint(catat11,[[\global\TRP@reruntrue]]) end else - if luatexbase.callbacktypes.finish_pdffile then - pdfetcs.opacity_res[#pdfetcs.opacity_res+1] = tr - else - local tpr, n = pdfetcs.getpageres() or "", 0 - tpr, n = tpr:gsub("/ExtGState<<", "%1"..tr) - if n == 0 then - tpr = format("%s/ExtGState<<%s>>", tpr, tr) - end - pdfetcs.setpageres(tpr) - end + pdfetcs.fallback_update_resources("ExtGState", tr) end - end - else - if pdfmanagement then - texsprint(ccexplat,{ - [[\pdfmanagement_add:nnn{Page/Resources/ExtGState}]], - format("{MPlibTr%s}{@mplibpdfobj%s}", on, on), - }) else - local tr = format("/MPlibTr%s @mplibpdfobj%s",on,on) - if pdfetcs.pgfloaded then - texsprint(format("\\csname %s\\endcsname{%s}", pdfetcs.pgfextgs,tr)) - else - texsprint(format("\\special{pdf:put @MPlibTr<<%s>>}",tr)) - texsprint"\\special{pdf:put @resources<</ExtGState @MPlibTr>>}" - end + pdfetcs.fallback_update_resources("ExtGState","@MPlibTr",tr) end end end - return on + return key end - -local function do_preobj_TR(prescript) +local function do_preobj_TR(object,prescript) + if object.postscript == "collect" then return end local opaq = prescript and prescript.tr_transparency - local tron_no, troff_no if opaq then + local key, on, os, new local mode = prescript.tr_alternative or 1 - mode = transparancy_modes[tonumber(mode)] - troff_no = update_tr_res("Normal", 1) - tron_no = update_tr_res(mode, opaq) - pdf_literalcode("/MPlibTr%i gs",tron_no) - end - return troff_no -end - -% \end{macrocode} -% -% color -% \begin{macrocode} -local prev_override_color -local function do_preobj_CR(object,prescript) - local override = prescript and prescript.MPlibOverrideColor - if override then - if pdfmode then - pdf_literalcode(override) - override = nil - else - put2output("\\special{%s}",override) - prev_override_color = override - end - else - local cs = object.color - if cs and #cs > 0 then - pdf_literalcode(luamplib.colorconverter(cs)) - prev_override_color = nil - elseif not pdfmode then - override = prev_override_color - if override then - put2output("\\special{%s}",override) + mode = transparancy_modes[tonumber(mode)] or mode + for i,v in ipairs{ {mode,opaq},{"Normal",1} } do + mode, opaq = v[1], v[2] + os = format("<</BM/%s/ca %s/CA %s/AIS false>>",mode,opaq,opaq) + on, new = update_pdfobjs(os) + key = add_extgs_resources(on,new) + if i == 1 then + pdf_literalcode("/%s gs",key) + else + return format("/%s gs",key) end end end - return override end % \end{macrocode} % -% Shading with |metafun| format. +% Shading with \emph{metafun} format. % \begin{macrocode} -local function shading_initialize () - pdfetcs.shading_res = {} - if pdfmode and luatexbase.callbacktypes.finish_pdffile then -- ltluatex - local shading_obj = pdf.reserveobj() - pdfetcs.setpageres(format("%s/Shading %i 0 R",pdfetcs.getpageres() or "",shading_obj)) - luatexbase.add_to_callback("finish_pdffile", function() - pdf.immediateobj(shading_obj,format("<<%s>>",tableconcat(pdfetcs.shading_res))) - end, "luamplib.shading.finish_pdffile") - end -end - local function sh_pdfpageresources(shtype,domain,colorspace,ca,cb,coordinates,steps,fractions) - if not pdfmanagement and not pdfetcs.shading_res then - shading_initialize() - end - local fun2fmt,os = "<</FunctionType 2/Domain [%s]/C0 [%s]/C1 [%s]/N 1>>" + local fun2fmt,os = "<</FunctionType 2/Domain[%s]/C0[%s]/C1[%s]/N 1>>" if steps > 1 then local list,bounds,encode = { },{ },{ } for i=1,steps do @@ -2007,69 +3071,44 @@ local function sh_pdfpageresources(shtype,domain,colorspace,ca,cb,coordinates,st encode[2*i-1] = 0 encode[2*i] = 1 os = fun2fmt:format(domain,tableconcat(ca[i],' '),tableconcat(cb[i],' ')) - list[i] = format(pdfmode and "%s 0 R" or "@mplibpdfobj%s",update_pdfobjs(os)) + list[i] = format(pdfetcs.resfmt, update_pdfobjs(os)) end os = tableconcat { "<</FunctionType 3", - format("/Bounds [%s]", tableconcat(bounds,' ')), - format("/Encode [%s]", tableconcat(encode,' ')), - format("/Functions [%s]", tableconcat(list, ' ')), - format("/Domain [%s]>>", domain), + format("/Bounds[%s]", tableconcat(bounds,' ')), + format("/Encode[%s]", tableconcat(encode,' ')), + format("/Functions[%s]", tableconcat(list, ' ')), + format("/Domain[%s]>>", domain), } else os = fun2fmt:format(domain,tableconcat(ca[1],' '),tableconcat(cb[1],' ')) end - local objref = format(pdfmode and "%s 0 R" or "@mplibpdfobj%s",update_pdfobjs(os)) + local objref = format(pdfetcs.resfmt, update_pdfobjs(os)) os = tableconcat { format("<</ShadingType %i", shtype), format("/ColorSpace %s", colorspace), format("/Function %s", objref), - format("/Coords [%s]", coordinates), - "/Extend [true true]/AntiAlias true>>", + format("/Coords[%s]", coordinates :gsub("%.%d+", rmzeros)), + "/Extend[true true]/AntiAlias true>>", } local on, new = update_pdfobjs(os) - if pdfmode then - if new then - if pdfmanagement then - texsprint(ccexplat,{ - [[\pdfmanagement_add:nnn{Page/Resources/Shading}]], - format("{MPlibSh%s}{%s 0 R}", on, on), - }) - else - local res = format("/MPlibSh%s %s 0 R", on, on) - if luatexbase.callbacktypes.finish_pdffile then - pdfetcs.shading_res[#pdfetcs.shading_res+1] = res - else - local pageres = pdfetcs.getpageres() or "" - if not pageres:find("/Shading<<.*>>") then - pageres = pageres.."/Shading<<>>" - end - pageres = pageres:gsub("/Shading<<","%1"..res) - pdfetcs.setpageres(pageres) - end - end - end - else + if new then + local key, val = format("MPlibSh%s", on), format(pdfetcs.resfmt, on) if pdfmanagement then - if new then - texsprint(ccexplat,{ - [[\pdfmanagement_add:nnn{Page/Resources/Shading}]], - format("{MPlibSh%s}{@mplibpdfobj%s}", on, on), - }) - end + texsprint { + "\\csname pdfmanagement_add:nnn\\endcsname{Page/Resources/Shading}{", key, "}{", val, "}" + } else - if new then - texsprint{ - "\\special{pdf:put @MPlibSh", - format("<</MPlibSh%s @mplibpdfobj%s>>}",on, on), - } + local res = format("/%s %s", key, val) + if pdfmode then + pdfetcs.fallback_update_resources("Shading", res) + else + pdfetcs.fallback_update_resources("Shading","@MPlibSh",res) end - texsprint"\\special{pdf:put @resources<</Shading @MPlibSh>>}" end end return on end - local function color_normalize(ca,cb) if #cb == 1 then if #ca == 4 then @@ -2081,12 +3120,23 @@ local function color_normalize(ca,cb) cb[1], cb[2], cb[3], cb[4] = 1-cb[1], 1-cb[2], 1-cb[3], 0 end end - -pdfetcs.clrspcs = { } +pdfetcs.clrspcs = setmetatable({ }, { __index = function(t,names) + run_tex_code({ + [[\color_model_new:nnn]], + format("{mplibcolorspace_%s}", names:gsub(",","_")), + format("{DeviceN}{names={%s}}", names), + [[\edef\mplib_@tempa{\pdf_object_ref_last:}]], + }, ccexplat) + local colorspace = get_macro'mplib_@tempa' + t[names] = colorspace + return colorspace +end }) local function do_preobj_SH(object,prescript) local shade_no local sh_type = prescript and prescript.sh_type - if sh_type then + if not sh_type then + return + else local domain = prescript.sh_domain or "0 1" local centera = prescript.sh_center_a or "0 0"; centera = centera:explode() local centerb = prescript.sh_center_b or "0 0"; centerb = centerb:explode() @@ -2134,18 +3184,17 @@ local function do_preobj_SH(object,prescript) local script = object.prescript:explode"\13+" for i=#script,1,-1 do if script[i]:find"mplib_spotcolor" then - local name, value - objref, name = script[i]:match"=(.-):(.+)" - value = script[i+1]:match"=(.+)" + local t, name, value = script[i]:explode"="[2]:explode":" + value, objref, name = t[1], t[2], t[3] if not names[name] then pos = pos+1 names[name] = pos names[#names+1] = name end - local t = { } + t = { } for j=1,names[name] do t[#t+1] = 0 end t[#t+1] = value - table.insert(#ca == #cb and ca or cb, t) + tableinsert(#ca == #cb and ca or cb, t) end end for _,t in ipairs{ca,cb} do @@ -2156,20 +3205,7 @@ local function do_preobj_SH(object,prescript) if #names == 1 then colorspace = objref else - local name = tableconcat(names,"-") - local obj = pdfetcs.clrspcs[name] - if obj then - colorspace = obj - else - run_tex_code({ - [[\color_model_new:nnn]], - format("{mplibcolorspace_%s}", name), - format("{DeviceN}{names={%s}}", tableconcat(names,",")), - [[\edef\mplib_@tempa{\pdf_object_ref_last:}]], - }, ccexplat) - colorspace = get_macro'mplib_@tempa' - pdfetcs.clrspcs[name] = colorspace - end + colorspace = pdfetcs.clrspcs[ tableconcat(names,",") ] end else local model = 0 @@ -2213,17 +3249,500 @@ end % \end{macrocode} % -% color stuffs at the end of object +% Patterns % \begin{macrocode} -local function do_postobj_color(tr,over,sh) - if sh then - pdf_literalcode("W n /MPlibSh%s sh Q",sh) +pdfetcs.patterns = { } +local function gather_resources (optres) + local t, do_pattern = { }, not optres + local names = {"ExtGState","ColorSpace","Shading"} + if do_pattern then + names[#names+1] = "Pattern" + end + if pdfmode then + if pdfmanagement then + for _,v in ipairs(names) do + local pp = get_macro(format("g__pdfdict_/g__pdf_Core/Page/Resources/%s_prop",v)) + if pp and pp:find"__prop_pair" then + t[#t+1] = format("/%s %s 0 R", v, ltx.pdf.object_id("__pdf/Page/Resources/"..v)) + end + end + else + local res = pdfetcs.getpageres() or "" + run_tex_code[[\mplibtmptoks\expandafter{\the\pdfvariable pageresources}]] + res = res .. texgettoks'mplibtmptoks' + if do_pattern then return res end + res = res:explode"/+" + for _,v in ipairs(res) do + v = v:match"^%s*(.-)%s*$" + if not v:find"Pattern" and not optres:find(v) then + t[#t+1] = "/" .. v + end + end + end + else + if pdfmanagement then + for _,v in ipairs(names) do + local pp = get_macro(format("g__pdfdict_/g__pdf_Core/Page/Resources/%s_prop",v)) + if pp and pp:find"__prop_pair" then + run_tex_code { + "\\mplibtmptoks\\expanded{{", + format("/%s \\csname pdf_object_ref:n\\endcsname{__pdf/Page/Resources/%s}",v,v), + "}}", + } + t[#t+1] = texgettoks'mplibtmptoks' + end + end + elseif is_defined(pdfetcs.pgfextgs) then + run_tex_code ({ + "\\mplibtmptoks\\expanded{{", + "\\ifpgf@sys@pdf@extgs@exists /ExtGState @pgfextgs\\fi", + "\\ifpgf@sys@pdf@colorspaces@exists /ColorSpace @pgfcolorspaces\\fi", + do_pattern and "\\ifpgf@sys@pdf@patterns@exists /Pattern @pgfpatterns \\fi" or "", + "}}", + }, catat11) + t[#t+1] = texgettoks'mplibtmptoks' + else + for _,v in ipairs(names) do + local vv = pdfetcs.resadded[v] + if vv then + t[#t+1] = format("/%s %s", v, vv) + end + end + end + end + return tableconcat(t) +end +function luamplib.registerpattern ( boxid, name, opts ) + local box = texgetbox(boxid) + local wd = format("%.3f",box.width/factor) :gsub("%.%d+", rmzeros) + local hd = format("%.3f",(box.height+box.depth)/factor) :gsub("%.%d+", rmzeros) + info("w/h/d of '%s': %s %s 0", name, wd, hd) + if opts.xstep == 0 then opts.xstep = nil end + if opts.ystep == 0 then opts.ystep = nil end + if opts.colored == nil then + opts.colored = opts.coloured + if opts.colored == nil then + opts.colored = true + end + end + if type(opts.matrix) == "table" then opts.matrix = tableconcat(opts.matrix," ") end + if type(opts.bbox) == "table" then opts.bbox = tableconcat(opts.bbox," ") end + if opts.matrix and opts.matrix:find"%a" then + local data = format("mplibtransformmatrix(%s);",opts.matrix) + process(data,"@mplibtransformmatrix") + local t = luamplib.transformmatrix + opts.matrix = format("%s %s %s %s", t[1], t[2], t[3], t[4]) + opts.xshift = opts.xshift or t[5] + opts.yshift = opts.yshift or t[6] + end + local attr = { + "/Type/Pattern", + "/PatternType 1", + format("/PaintType %i", opts.colored and 1 or 2), + "/TilingType 2", + format("/XStep %s", opts.xstep or wd), + format("/YStep %s", opts.ystep or hd), + format("/Matrix[%s %s %s]", opts.matrix or "1 0 0 1", opts.xshift or 0, opts.yshift or 0), + } + local optres = opts.resources or "" + optres = optres .. gather_resources(optres) + local patterns = pdfetcs.patterns + if pdfmode then + if opts.bbox then + attr[#attr+1] = format("/BBox[%s]", opts.bbox) + end + local index = tex.saveboxresource(boxid, tableconcat(attr), optres, true, opts.bbox and 4 or 1) + patterns[name] = { id = index, colored = opts.colored } + else + local cnt = #patterns + 1 + local objname = "@mplibpattern" .. cnt + local metric = format("bbox %s", opts.bbox or format("0 0 %s %s",wd,hd)) + texsprint { + "\\expandafter\\newbox\\csname luamplib.patternbox.", cnt, "\\endcsname", + "\\global\\setbox\\csname luamplib.patternbox.", cnt, "\\endcsname", + "\\hbox{\\unhbox ", boxid, "}\\luamplibatnextshipout{", + "\\special{pdf:bcontent}", + "\\special{pdf:bxobj ", objname, " ", metric, "}", + "\\raise\\dp\\csname luamplib.patternbox.", cnt, "\\endcsname", + "\\box\\csname luamplib.patternbox.", cnt, "\\endcsname", + "\\special{pdf:put @resources <<", optres, ">>}", + "\\special{pdf:exobj <<", tableconcat(attr), ">>}", + "\\special{pdf:econtent}}", + } + patterns[cnt] = objname + patterns[name] = { id = cnt, colored = opts.colored } + end +end +local function pattern_colorspace (cs) + local on, new = update_pdfobjs(format("[/Pattern %s]", cs)) + if new then + local key, val = format("MPlibCS%i",on), format(pdfetcs.resfmt,on) + if pdfmanagement then + texsprint { + "\\csname pdfmanagement_add:nnn\\endcsname{Page/Resources/ColorSpace}{", key, "}{", val, "}" + } + else + local res = format("/%s %s", key, val) + if is_defined(pdfetcs.pgfcolorspace) then + texsprint { "\\csname ", pdfetcs.pgfcolorspace, "\\endcsname{", res, "}" } + elseif pdfmode then + pdfetcs.fallback_update_resources("ColorSpace", res) + else + pdfetcs.fallback_update_resources("ColorSpace","@MPlibCS",res) + end + end + end + return on +end +local function do_preobj_PAT(object, prescript) + local name = prescript and prescript.mplibpattern + if not name then return end + local patterns = pdfetcs.patterns + local patt = patterns[name] + local index = patt and patt.id or err("cannot get pattern object '%s'", name) + local key = format("MPlibPt%s",index) + if patt.colored then + pdf_literalcode("/Pattern cs /%s scn", key) + else + local color = prescript.mpliboverridecolor + if not color then + local t = object.color + color = t and #t>0 and luamplib.colorconverter(t) + end + if not color then return end + local cs + if color:find" cs " or color:find"@pdf.obj" then + local t = color:explode() + if pdfmode then + cs = format("%s 0 R", ltx.pdf.object_id( t[1]:sub(2,-1) )) + color = t[3] + else + cs = t[2] + color = t[3]:match"%[(.+)%]" + end + else + local t = colorsplit(color) + cs = #t == 4 and "/DeviceCMYK" or #t == 3 and "/DeviceRGB" or "/DeviceGray" + color = tableconcat(t," ") + end + pdf_literalcode("/MPlibCS%i cs %s /%s scn", pattern_colorspace(cs), color, key) end - if over then + if not patt.done then + local val = pdfmode and format("%s 0 R",index) or patterns[index] + if pdfmanagement then + texsprint { + "\\csname pdfmanagement_add:nnn\\endcsname{Page/Resources/Pattern}{", key, "}{", val, "}" + } + else + local res = format("/%s %s", key, val) + if is_defined(pdfetcs.pgfpattern) then + texsprint { "\\csname ", pdfetcs.pgfpattern, "\\endcsname{", res, "}" } + elseif pdfmode then + pdfetcs.fallback_update_resources("Pattern", res) + else + pdfetcs.fallback_update_resources("Pattern","@MPlibPt",res) + end + end + end + patt.done = true +end + +% \end{macrocode} +% +% Fading +% \begin{macrocode} +pdfetcs.fading = { } +local function do_preobj_FADE (object, prescript) + local fd_type = prescript and prescript.mplibfadetype + local fd_stop = prescript and prescript.mplibfadestate + if not fd_type then + return fd_stop -- returns "stop" (if picture) or nil + end + local bbox = prescript.mplibfadebbox:explode":" + local dx, dy = -bbox[1], -bbox[2] + local vec = prescript.mplibfadevector; vec = vec and vec:explode":" + if not vec then + if fd_type == "linear" then + vec = {bbox[1], bbox[2], bbox[3], bbox[2]} -- left to right + else + local centerx, centery = (bbox[1]+bbox[3])/2, (bbox[2]+bbox[4])/2 + vec = {centerx, centery, centerx, centery} -- center for both circles + end + end + local coords = { vec[1]+dx, vec[2]+dy, vec[3]+dx, vec[4]+dy } + if fd_type == "linear" then + coords = format("%f %f %f %f", tableunpack(coords)) + elseif fd_type == "circular" then + local width, height = bbox[3]-bbox[1], bbox[4]-bbox[2] + local radius = (prescript.mplibfaderadius or "0:"..math.sqrt(width^2+height^2)/2):explode":" + tableinsert(coords, 3, radius[1]) + tableinsert(coords, radius[2]) + coords = format("%f %f %f %f %f %f", tableunpack(coords)) + else + err("unknown fading method '%s'", fd_type) + end + fd_type = fd_type == "linear" and 2 or 3 + local opaq = (prescript.mplibfadeopacity or "1:0"):explode":" + local on, os, new + on = sh_pdfpageresources(fd_type, "0 1", "/DeviceGray", {{opaq[1]}}, {{opaq[2]}}, coords, 1) + os = format("<</PatternType 2/Shading %s>>", format(pdfetcs.resfmt, on)) + on = update_pdfobjs(os) + bbox = format("0 0 %f %f", bbox[3]+dx, bbox[4]+dy) :gsub("%.%d+", rmzeros) + local streamtext = format("q /Pattern cs/MPlibFd%s scn %s re f Q", on, bbox) + os = format("<</Pattern<</MPlibFd%s %s>>>>", on, format(pdfetcs.resfmt, on)) + on = update_pdfobjs(os) + local resources = format(pdfetcs.resfmt, on) + on = update_pdfobjs"<</S/Transparency/CS/DeviceGray>>" + local attr = tableconcat{ + "/Subtype/Form", + format("/BBox[%s]", bbox), + format("/Matrix[1 0 0 1 %s]", format("%f %f", -dx,-dy) :gsub("%.%d+", rmzeros)), + format("/Resources %s", resources), + "/Group ", format(pdfetcs.resfmt, on), + } + on = update_pdfobjs(attr, streamtext) + os = "<</SMask<</S/Luminosity/G " .. format(pdfetcs.resfmt, on) .. ">>>>" + on, new = update_pdfobjs(os) + local key = add_extgs_resources(on,new) + start_pdf_code() + pdf_literalcode("/%s gs", key) + if fd_stop then return "standalone" end + return "start" +end + +% \end{macrocode} +% +% Transparency Group +% \begin{macrocode} +pdfetcs.tr_group = { shifts = { } } +luamplib.trgroupshifts = pdfetcs.tr_group.shifts +local function do_preobj_GRP (object, prescript) + local grstate = prescript and prescript.gr_state + if not grstate then return end + local trgroup = pdfetcs.tr_group + if grstate == "start" then + trgroup.name = prescript.mplibgroupname or "lastmplibgroup" + trgroup.isolated, trgroup.knockout = false, false + for _,v in ipairs(prescript.gr_type:explode",+") do + trgroup[v] = true + end + local p = object.path + trgroup.bbox = { + math.min(p[1].x_coord, p[2].x_coord, p[3].x_coord, p[4].x_coord), + math.min(p[1].y_coord, p[2].y_coord, p[3].y_coord, p[4].y_coord), + math.max(p[1].x_coord, p[2].x_coord, p[3].x_coord, p[4].x_coord), + math.max(p[1].y_coord, p[2].y_coord, p[3].y_coord, p[4].y_coord), + } + put2output[[\begingroup\setbox\mplibscratchbox\hbox\bgroup]] + elseif grstate == "stop" then + local llx,lly,urx,ury = tableunpack(trgroup.bbox) + put2output(tableconcat{ + "\\egroup", + format("\\wd\\mplibscratchbox %fbp", urx-llx), + format("\\ht\\mplibscratchbox %fbp", ury-lly), + "\\dp\\mplibscratchbox 0pt", + }) + local grattr = format("/Group<</S/Transparency/I %s/K %s>>",trgroup.isolated,trgroup.knockout) + local res = gather_resources() + local bbox = format("%f %f %f %f", llx,lly,urx,ury) :gsub("%.%d+", rmzeros) + if pdfmode then + put2output(tableconcat{ + "\\saveboxresource type 2 attr{/Type/XObject/Subtype/Form/FormType 1", + "/BBox[", bbox, "]", grattr, "} resources{", res, "}\\mplibscratchbox", + [[\setbox\mplibscratchbox\hbox{\useboxresource\lastsavedboxresourceindex}]], + [[\wd\mplibscratchbox 0pt\ht\mplibscratchbox 0pt\dp\mplibscratchbox 0pt]], + [[\box\mplibscratchbox\endgroup]], + "\\expandafter\\xdef\\csname luamplib.group.", trgroup.name, "\\endcsname{", + "\\noexpand\\mplibstarttoPDF{",llx,"}{",lly,"}{",urx,"}{",ury,"}", + "\\useboxresource \\the\\lastsavedboxresourceindex\\noexpand\\mplibstoptoPDF}", + }) + else + trgroup.cnt = (trgroup.cnt or 0) + 1 + local objname = format("@mplibtrgr%s", trgroup.cnt) + put2output(tableconcat{ + "\\special{pdf:bxobj ", objname, " bbox ", bbox, "}", + "\\unhbox\\mplibscratchbox", + "\\special{pdf:put @resources <<", res, ">>}", + "\\special{pdf:exobj <<", grattr, ">>}", + "\\special{pdf:uxobj ", objname, "}\\endgroup", + }) + token.set_macro("luamplib.group."..trgroup.name, tableconcat{ + "\\mplibstarttoPDF{",llx,"}{",lly,"}{",urx,"}{",ury,"}", + "\\special{pdf:uxobj ", objname, "}\\mplibstoptoPDF", + }, "global") + end + trgroup.shifts[trgroup.name] = { llx, lly } + end + return grstate +end +function luamplib.registergroup (boxid, name, opts) + local box = texgetbox(boxid) + local res = (opts.resources or "") .. gather_resources() + local attr = { "/Type/XObject/Subtype/Form/FormType 1" } + if type(opts.matrix) == "table" then opts.matrix = tableconcat(opts.matrix," ") end + if type(opts.bbox) == "table" then opts.bbox = tableconcat(opts.bbox," ") end + if opts.matrix and opts.matrix:find"%a" then + local data = format("mplibtransformmatrix(%s);",opts.matrix) + process(data,"@mplibtransformmatrix") + opts.matrix = tableconcat(luamplib.transformmatrix, ' ') + end + local grtype = 3 + if opts.bbox then + attr[#attr+1] = format("/BBox[%s]", opts.bbox :gsub("%.%d+", rmzeros)) + grtype = 2 + end + if opts.matrix then + attr[#attr+1] = format("/Matrix[%s]", opts.matrix :gsub("%.%d+", rmzeros)) + grtype = opts.bbox and 4 or 1 + end + if opts.asgroup then + local t = { isolated = false, knockout = false } + for _,v in ipairs(opts.asgroup:explode",+") do t[v] = true end + attr[#attr+1] = format("/Group<</S/Transparency/I %s/K %s>>", t.isolated, t.knockout) + end + local trgroup = pdfetcs.tr_group + trgroup.shifts[name] = { get_macro'MPllx', get_macro'MPlly' } + if pdfmode then + local index = tex.saveboxresource(boxid, tableconcat(attr), res, true, grtype) + token.set_macro("luamplib.group."..name, "\\useboxresource "..index, "global") + else + trgroup.cnt = (trgroup.cnt or 0) + 1 + local objname = format("@mplibtrgr%s", trgroup.cnt) + local wd, ht, dp = node.getwhd(box) + texsprint { + "\\expandafter\\newbox\\csname luamplib.groupbox.", trgroup.cnt, "\\endcsname", + "\\global\\setbox\\csname luamplib.groupbox.", trgroup.cnt, "\\endcsname", + "\\hbox{\\unhbox ", boxid, "}\\luamplibatnextshipout{", + "\\special{pdf:bcontent}", + "\\special{pdf:bxobj ", objname, " width ", wd, "sp height ", ht, "sp depth ", dp, "sp}", + "\\unhbox\\csname luamplib.groupbox.", trgroup.cnt, "\\endcsname", + "\\special{pdf:put @resources <<", res, ">>}", + "\\special{pdf:exobj <<", tableconcat(attr), ">>}", + "\\special{pdf:econtent}}", + } + token.set_macro("luamplib.group."..name, tableconcat{ + "\\begingroup\\setbox\\mplibscratchbox\\hbox{\\special{pdf:uxobj ", objname, "}}", + "\\wd\\mplibscratchbox ", wd, "sp", + "\\ht\\mplibscratchbox ", ht, "sp", + "\\dp\\mplibscratchbox ", dp, "sp", + "\\box\\mplibscratchbox\\endgroup", + }, "global") + end +end + +local function stop_special_effects(fade,opaq,over) + if fade then -- fading + stop_pdf_code() + end + if opaq then -- opacity + pdf_literalcode(opaq) + end + if over then -- color put2output"\\special{pdf:ec}" end - if tr then - pdf_literalcode("/MPlibTr%i gs",tr) +end + +% \end{macrocode} +% +% Codes below for inserting PDF lieterals are mostly from ConTeXt general, +% with small changes when needed. +% \begin{macrocode} +local function getobjects(result,figure,f) + return figure:objects() +end + +function luamplib.convert (result, flusher) + luamplib.flush(result, flusher) + return true -- done +end + +local function pdf_textfigure(font,size,text,width,height,depth) + text = text:gsub(".",function(c) + return format("\\hbox{\\char%i}",string.byte(c)) -- kerning happens in metapost : false + end) + put2output("\\mplibtextext{%s}{%f}{%s}{%s}{%s}",font,size,text,0,0) +end + +local bend_tolerance = 131/65536 + +local rx, sx, sy, ry, tx, ty, divider = 1, 0, 0, 1, 0, 0, 1 + +local function pen_characteristics(object) + local t = mplib.pen_info(object) + rx, ry, sx, sy, tx, ty = t.rx, t.ry, t.sx, t.sy, t.tx, t.ty + divider = sx*sy - rx*ry + return not (sx==1 and rx==0 and ry==0 and sy==1 and tx==0 and ty==0), t.width +end + +local function concat(px, py) -- no tx, ty here + return (sy*px-ry*py)/divider,(sx*py-rx*px)/divider +end + +local function curved(ith,pth) + local d = pth.left_x - ith.right_x + if abs(ith.right_x - ith.x_coord - d) <= bend_tolerance and abs(pth.x_coord - pth.left_x - d) <= bend_tolerance then + d = pth.left_y - ith.right_y + if abs(ith.right_y - ith.y_coord - d) <= bend_tolerance and abs(pth.y_coord - pth.left_y - d) <= bend_tolerance then + return false + end + end + return true +end + +local function flushnormalpath(path,open) + local pth, ith + for i=1,#path do + pth = path[i] + if not ith then + pdf_literalcode("%f %f m",pth.x_coord,pth.y_coord) + elseif curved(ith,pth) then + pdf_literalcode("%f %f %f %f %f %f c",ith.right_x,ith.right_y,pth.left_x,pth.left_y,pth.x_coord,pth.y_coord) + else + pdf_literalcode("%f %f l",pth.x_coord,pth.y_coord) + end + ith = pth + end + if not open then + local one = path[1] + if curved(pth,one) then + pdf_literalcode("%f %f %f %f %f %f c",pth.right_x,pth.right_y,one.left_x,one.left_y,one.x_coord,one.y_coord ) + else + pdf_literalcode("%f %f l",one.x_coord,one.y_coord) + end + elseif #path == 1 then -- special case .. draw point + local one = path[1] + pdf_literalcode("%f %f l",one.x_coord,one.y_coord) + end +end + +local function flushconcatpath(path,open) + pdf_literalcode("%f %f %f %f %f %f cm", sx, rx, ry, sy, tx ,ty) + local pth, ith + for i=1,#path do + pth = path[i] + if not ith then + pdf_literalcode("%f %f m",concat(pth.x_coord,pth.y_coord)) + elseif curved(ith,pth) then + local a, b = concat(ith.right_x,ith.right_y) + local c, d = concat(pth.left_x,pth.left_y) + pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concat(pth.x_coord, pth.y_coord)) + else + pdf_literalcode("%f %f l",concat(pth.x_coord, pth.y_coord)) + end + ith = pth + end + if not open then + local one = path[1] + if curved(pth,one) then + local a, b = concat(pth.right_x,pth.right_y) + local c, d = concat(one.left_x,one.left_y) + pdf_literalcode("%f %f %f %f %f %f c",a,b,c,d,concat(one.x_coord, one.y_coord)) + else + pdf_literalcode("%f %f l",concat(one.x_coord,one.y_coord)) + end + elseif #path == 1 then -- special case .. draw point + local one = path[1] + pdf_literalcode("%f %f l",concat(one.x_coord,one.y_coord)) end end @@ -2231,7 +3750,7 @@ end % % Finally, flush figures by inserting PDF literals. % \begin{macrocode} -local function flush(result,flusher) +function luamplib.flush (result,flusher) if result then local figures = result.fig if figures then @@ -2245,21 +3764,18 @@ local function flush(result,flusher) local llx, lly, urx, ury = bbox[1], bbox[2], bbox[3], bbox[4] -- faster than unpack if urx < llx then % \end{macrocode} -% % luamplib silently ignores this invalid figure for those % that do not contain |beginfig ... endfig|. (issue \#70) % Original code of ConTeXt general was: -% \begin{verbatim} +%\begin{verbatim} % -- invalid % pdf_startfigure(fignum,0,0,0,0) % pdf_stopfigure() -% \end{verbatim} +%\end{verbatim} % \begin{macrocode} else % \end{macrocode} -% For collecting pdf materials and -% for legacy behavior. Insert `pre-fig' \TeX\ code here, and -% prepare a table for `in-fig' codes. +% For legacy behavior, insert `pre-fig' \TeX\ code here. % \begin{macrocode} if tex_code_pre_mplib[f] then put2output(tex_code_pre_mplib[f]) @@ -2273,15 +3789,15 @@ local function flush(result,flusher) local object = objects[o] local objecttype = object.type % \end{macrocode} -% -% The following 7 lines are part of |btex...etex| patch. +% The following 8 lines are part of |btex...etex| patch. % Again, colors are processed at this stage. % \begin{macrocode} local prescript = object.prescript prescript = prescript and script2table(prescript) -- prescript is now a table - local tr_opaq = do_preobj_TR(prescript) - local cr_over = do_preobj_CR(object,prescript) - local shade_no = do_preobj_SH(object,prescript) + local cr_over = do_preobj_CR(object,prescript) -- color + local tr_opaq = do_preobj_TR(object,prescript) -- opacity + local fading_ = do_preobj_FADE(object,prescript) -- fading + local trgroup = do_preobj_GRP(object,prescript) -- transparency group if prescript and prescript.mplibtexboxid then put_tex_boxes(object,prescript) elseif objecttype == "start_bounds" or objecttype == "stop_bounds" then --skip @@ -2295,7 +3811,6 @@ local function flush(result,flusher) miterlimit, linecap, linejoin, dashed = -1, -1, -1, false elseif objecttype == "special" then % \end{macrocode} -% % Collect \TeX\ codes that will be executed after flushing. % Legacy behavior. % \begin{macrocode} @@ -2308,7 +3823,7 @@ local function flush(result,flusher) pdf_literalcode("%f %f %f %f %f %f cm",ot[3],ot[4],ot[5],ot[6],ot[1],ot[2]) pdf_textfigure(object.font,object.dsize,object.text,object.width,object.height,object.depth) stop_pdf_code() - else + elseif not trgroup and fading_ ~= "stop" then local evenodd, collect, both = false, false, false local postscript = object.postscript if not object.istext then @@ -2332,6 +3847,9 @@ local function flush(result,flusher) savedhtap[#savedhtap+1] = object.htap or false end else +% \end{macrocode} +% Removed from ConTeXt general: color stuff. +% \begin{macrocode} local ml = object.miterlimit if ml and ml ~= miterlimit then miterlimit = ml @@ -2358,6 +3876,11 @@ local function flush(result,flusher) pdf_literalcode("[] 0 d") dashed = false end +% \end{macrocode} +% Added : shading and pattern +% \begin{macrocode} + local shade_no = do_preobj_SH(object,prescript) -- shading + local pattern_ = do_preobj_PAT(object,prescript) -- pattern local path = object.path local transformed, penwidth = false, 1 local open = path and path[1].left_type and path[#path].right_type @@ -2394,8 +3917,7 @@ local function flush(result,flusher) flushnormalpath(path,open) end % \end{macrocode} -% -% Change from ConTeXt general: there was color stuffs. +% Shading seems to conflict with these ops % \begin{macrocode} if not shade_no then -- conflict with shading if objecttype == "fill" then @@ -2415,6 +3937,9 @@ local function flush(result,flusher) stop_pdf_code() end local path = object.htap +% \end{macrocode} +% How can we generate an |htap| object? Please let us know if you have succeeded. +% \begin{macrocode} if path then if transformed then start_pdf_code() @@ -2447,18 +3972,38 @@ local function flush(result,flusher) stop_pdf_code() end end - end - end % \end{macrocode} -% -% Added to ConTeXt general: color stuff. -% And execute legacy |verbatimtex| code. +% Added to ConTeXt general: post-object colors and shading stuff. +% We should beware the |q ... Q| scope. % \begin{macrocode} - do_postobj_color(tr_opaq,cr_over,shade_no) + if shade_no then -- shading + pdf_literalcode("W%s n /MPlibSh%s sh Q",evenodd and "*" or "",shade_no) + end + end + end + if fading_ == "start" then + pdfetcs.fading.specialeffects = {fading_, tr_opaq, cr_over} + elseif trgroup == "start" then + pdfetcs.tr_group.specialeffects = {fading_, tr_opaq, cr_over} + elseif fading_ == "stop" then + local se = pdfetcs.fading.specialeffects + if se then stop_special_effects(se[1], se[2], se[3]) end + elseif trgroup == "stop" then + local se = pdfetcs.tr_group.specialeffects + if se then stop_special_effects(se[1], se[2], se[3]) end + else + stop_special_effects(fading_, tr_opaq, cr_over) + end + if fading_ or trgroup then -- extgs resetted + miterlimit, linecap, linejoin, dashed = -1, -1, -1, false + end end end stop_pdf_code() pdf_stopfigure() +% \end{macrocode} +% output collected materials to PDF, plus legacy |verbatimtex| code. +% \begin{macrocode} for _,v in ipairs(figcontents) do if type(v) == "table" then texsprint"\\mplibtoPDF{"; texsprint(v[1], v[2]); texsprint"}" @@ -2473,9 +4018,8 @@ local function flush(result,flusher) end end end -luamplib.flush = flush -local function colorconverter(cr) +function luamplib.colorconverter (cr) local n = #cr if n == 4 then local c, m, y, k = cr[1], cr[2], cr[3], cr[4] @@ -2488,7 +4032,6 @@ local function colorconverter(cr) return format("%.3f g %.3f G",s,s), "0 g 0 G" end end -luamplib.colorconverter = colorconverter % \end{macrocode} % % \iffalse @@ -2505,15 +4048,34 @@ luamplib.colorconverter = colorconverter % First we need to load some packages. % % \begin{macrocode} -\bgroup\expandafter\expandafter\expandafter\egroup -\expandafter\ifx\csname selectfont\endcsname\relax - \input ltluatex -\else +\ifcsname ProvidesPackage\endcsname +% \end{macrocode} +% We need \LaTeX\ 2024-06-01 as we use |ltx.pdf.object_id| when pdfmanagement is loaded. +% But as \pkg{fp} package does not accept an option, we do not append the date option. +% \begin{macrocode} \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{luamplib} - [2024/04/25 v2.28.2 mplib package for LuaTeX] - \ifx\newluafunction\@undefined + [2024/07/27 v2.34.3 mplib package for LuaTeX] +\fi +\ifdefined\newluafunction\else \input ltluatex +\fi +% \end{macrocode} +% +% In DVI mode, a new XObject (mppattern, mplibgroup) must be encapsulated in an \cs{hbox}. +% But this should not affect typesetting. So we use Hook mechanism provided by \LaTeX\ kernel. +% In Plain, \pkg{atbegshi.sty} is loaded. +% \begin{macrocode} +\ifnum\outputmode=0 + \ifdefined\AddToHookNext + \def\luamplibatnextshipout{\AddToHookNext{shipout/background}} + \def\luamplibatfirstshipout{\AddToHook{shipout/firstpage}} + \def\luamplibateveryshipout{\AddToHook{shipout/background}} + \else + \input atbegshi.sty + \def\luamplibatnextshipout#1{\AtBeginShipoutNext{\AtBeginShipoutAddToBox{#1}}} + \let\luamplibatfirstshipout\AtBeginShipoutFirst + \def\luamplibateveryshipout#1{\AtBeginShipout{\AtBeginShipoutAddToBox{#1}}} \fi \fi % \end{macrocode} @@ -2533,7 +4095,7 @@ luamplib.colorconverter = colorconverter \fi % \end{macrocode} % -% Set the format for metapost. +% Set the format for \metapost. % \begin{macrocode} \def\mplibsetformat#1{\directlua{luamplib.setformat("#1")}} % \end{macrocode} @@ -2549,12 +4111,12 @@ luamplib.colorconverter = colorconverter \ifcsname PackageInfo\endcsname \PackageInfo{luamplib}{only dvipdfmx is supported currently} \else - \write128{luamplib Info: only dvipdfmx is supported currently} + \immediate\write-1{luamplib Info: only dvipdfmx is supported currently} \fi \fi % \end{macrocode} % -% Make |mplibcode| typesetted always in horizontal mode. +% To make |mplibcode| typeset always in horizontal mode. % \begin{macrocode} \def\mplibforcehmode{\let\prependtomplibbox\leavevmode} \def\mplibnoforcehmode{\let\prependtomplibbox\relax} @@ -2575,47 +4137,193 @@ luamplib.colorconverter = colorconverter \def\mplibputtextbox#1{\vbox to 0pt{\vss\hbox to 0pt{\raise\dp#1\copy#1\hss}}} % \end{macrocode} % -% The Plain-specific stuff. +% use Transparency Group % \begin{macrocode} -\unless\ifcsname ver@luamplib.sty\endcsname -\def\mplibcode{% - \begingroup +\protected\def\usemplibgroup#1{\csname luamplib.group.#1\endcsname} +\protected\def\mplibgroup#1{% \begingroup - \mplibsetupcatcodes - \mplibdocode + \def\MPllx{0}\def\MPlly{0}% + \def\mplibgroupname{#1}% + \mplibgroupgetnexttok } -\long\def\mplibdocode#1\endmplibcode{% - \endgroup - \directlua{luamplib.process_mplibcode([===[\unexpanded{#1}]===],"")}% +\def\mplibgroupgetnexttok{\futurelet\nexttok\mplibgroupbranch} +\def\mplibgroupskipspace{\afterassignment\mplibgroupgetnexttok\let\nexttok= } +\def\mplibgroupbranch{% + \ifx [\nexttok + \expandafter\mplibgroupopts + \else + \ifx\mplibsptoken\nexttok + \expandafter\expandafter\expandafter\mplibgroupskipspace + \else + \let\mplibgroupoptions\empty + \expandafter\expandafter\expandafter\mplibgroupmain + \fi + \fi +} +\def\mplibgroupopts[#1]{\def\mplibgroupoptions{#1}\mplibgroupmain} +\def\mplibgroupmain{\setbox\mplibscratchbox\hbox\bgroup\ignorespaces} +\protected\def\endmplibgroup{\egroup + \directlua{ luamplib.registergroup( + \the\mplibscratchbox, '\mplibgroupname', {\mplibgroupoptions} + )}% \endgroup } -\else % \end{macrocode} % -% The \LaTeX-specific part: a new environment. +% Patterns % \begin{macrocode} -\newenvironment{mplibcode}[1][]{% - \global\def\currentmpinstancename{#1}% - \mplibtmptoks{}\ltxdomplibcode -}{} -\def\ltxdomplibcode{% +{\def\:{\global\let\mplibsptoken= } \: } +\protected\def\mppattern#1{% \begingroup - \mplibsetupcatcodes - \ltxdomplibcodeindeed + \def\mplibpatternname{#1}% + \mplibpatterngetnexttok +} +\def\mplibpatterngetnexttok{\futurelet\nexttok\mplibpatternbranch} +\def\mplibpatternskipspace{\afterassignment\mplibpatterngetnexttok\let\nexttok= } +\def\mplibpatternbranch{% + \ifx [\nexttok + \expandafter\mplibpatternopts + \else + \ifx\mplibsptoken\nexttok + \expandafter\expandafter\expandafter\mplibpatternskipspace + \else + \let\mplibpatternoptions\empty + \expandafter\expandafter\expandafter\mplibpatternmain + \fi + \fi } -\def\mplib@mplibcode{mplibcode} -\long\def\ltxdomplibcodeindeed#1\end#2{% +\def\mplibpatternopts[#1]{% + \def\mplibpatternoptions{#1}% + \mplibpatternmain +} +\def\mplibpatternmain{% + \setbox\mplibscratchbox\hbox\bgroup\ignorespaces +} +\protected\def\endmppattern{% + \egroup + \directlua{ luamplib.registerpattern( + \the\mplibscratchbox, '\mplibpatternname', {\mplibpatternoptions} + )}% \endgroup - \mplibtmptoks\expandafter{\the\mplibtmptoks#1}% - \def\mplibtemp@a{#2}% - \ifx\mplib@mplibcode\mplibtemp@a - \directlua{luamplib.process_mplibcode([===[\the\mplibtmptoks]===],"\currentmpinstancename")}% - \end{mplibcode}% +} +% \end{macrocode} +% +% simple way to use \mplib: +% |\mpfig draw fullcircle scaled 10; \endmpfig| +% \begin{macrocode} +\def\mpfiginstancename{@mpfig} +\protected\def\mpfig{% + \begingroup + \futurelet\nexttok\mplibmpfigbranch +} +\def\mplibmpfigbranch{% + \ifx *\nexttok + \expandafter\mplibprempfig \else - \mplibtmptoks\expandafter{\the\mplibtmptoks\end{#2}}% - \expandafter\ltxdomplibcode + \expandafter\mplibmainmpfig \fi } +\def\mplibmainmpfig{% + \begingroup + \mplibsetupcatcodes + \mplibdomainmpfig +} +\long\def\mplibdomainmpfig#1\endmpfig{% + \endgroup + \directlua{ + local legacy = luamplib.legacyverbatimtex + local everympfig = luamplib.everymplib["\mpfiginstancename"] or "" + local everyendmpfig = luamplib.everyendmplib["\mpfiginstancename"] or "" + luamplib.legacyverbatimtex = false + luamplib.everymplib["\mpfiginstancename"] = "" + luamplib.everyendmplib["\mpfiginstancename"] = "" + luamplib.process_mplibcode( + "beginfig(0) "..everympfig.." "..[===[\unexpanded{#1}]===].." "..everyendmpfig.." endfig;", + "\mpfiginstancename") + luamplib.legacyverbatimtex = legacy + luamplib.everymplib["\mpfiginstancename"] = everympfig + luamplib.everyendmplib["\mpfiginstancename"] = everyendmpfig + }% + \endgroup +} +\def\mplibprempfig#1{% + \begingroup + \mplibsetupcatcodes + \mplibdoprempfig +} +\long\def\mplibdoprempfig#1\endmpfig{% + \endgroup + \directlua{ + local legacy = luamplib.legacyverbatimtex + local everympfig = luamplib.everymplib["\mpfiginstancename"] + local everyendmpfig = luamplib.everyendmplib["\mpfiginstancename"] + luamplib.legacyverbatimtex = false + luamplib.everymplib["\mpfiginstancename"] = "" + luamplib.everyendmplib["\mpfiginstancename"] = "" + luamplib.process_mplibcode([===[\unexpanded{#1}]===],"\mpfiginstancename") + luamplib.legacyverbatimtex = legacy + luamplib.everymplib["\mpfiginstancename"] = everympfig + luamplib.everyendmplib["\mpfiginstancename"] = everyendmpfig + }% + \endgroup +} +\protected\def\endmpfig{endmpfig} +% \end{macrocode} +% +% The Plain-specific stuff. +% \begin{macrocode} +\unless\ifcsname ver@luamplib.sty\endcsname + \def\mplibcodegetinstancename[#1]{\gdef\currentmpinstancename{#1}\mplibcodeindeed} + \protected\def\mplibcode{% + \begingroup + \futurelet\nexttok\mplibcodebranch + } + \def\mplibcodebranch{% + \ifx [\nexttok + \expandafter\mplibcodegetinstancename + \else + \global\let\currentmpinstancename\empty + \expandafter\mplibcodeindeed + \fi + } + \def\mplibcodeindeed{% + \begingroup + \mplibsetupcatcodes + \mplibdocode + } + \long\def\mplibdocode#1\endmplibcode{% + \endgroup + \directlua{luamplib.process_mplibcode([===[\unexpanded{#1}]===],"\currentmpinstancename")}% + \endgroup + } + \protected\def\endmplibcode{endmplibcode} +\else +% \end{macrocode} +% +% The \LaTeX-specific part: a new environment. +% \begin{macrocode} + \newenvironment{mplibcode}[1][]{% + \global\def\currentmpinstancename{#1}% + \mplibtmptoks{}\ltxdomplibcode + }{} + \def\ltxdomplibcode{% + \begingroup + \mplibsetupcatcodes + \ltxdomplibcodeindeed + } + \def\mplib@mplibcode{mplibcode} + \long\def\ltxdomplibcodeindeed#1\end#2{% + \endgroup + \mplibtmptoks\expandafter{\the\mplibtmptoks#1}% + \def\mplibtemp@a{#2}% + \ifx\mplib@mplibcode\mplibtemp@a + \directlua{luamplib.process_mplibcode([===[\the\mplibtmptoks]===],"\currentmpinstancename")}% + \end{mplibcode}% + \else + \mplibtmptoks\expandafter{\the\mplibtmptoks\end{#2}}% + \expandafter\ltxdomplibcode + \fi + } \fi % \end{macrocode} % @@ -2632,9 +4340,9 @@ luamplib.colorconverter = colorconverter \def\mpliblegacybehavior#1{\directlua{ local s = string.lower("#1") if s == "enable" or s == "true" or s == "yes" then - luamplib.legacy_verbatimtex = true + luamplib.legacyverbatimtex = true else - luamplib.legacy_verbatimtex = false + luamplib.legacyverbatimtex = false end }} \def\mplibverbatim#1{\directlua{ @@ -2652,17 +4360,17 @@ luamplib.colorconverter = colorconverter % |luamplib.every(end)mplib| tables % % \begin{macrocode} -\protected\def\everymplib{% - \begingroup - \mplibsetupcatcodes - \mplibdoeverymplib -} -\protected\def\everyendmplib{% - \begingroup - \mplibsetupcatcodes - \mplibdoeveryendmplib -} \ifcsname ver@luamplib.sty\endcsname + \protected\def\everymplib{% + \begingroup + \mplibsetupcatcodes + \mplibdoeverymplib + } + \protected\def\everyendmplib{% + \begingroup + \mplibsetupcatcodes + \mplibdoeveryendmplib + } \newcommand\mplibdoeverymplib[2][]{% \endgroup \directlua{ @@ -2676,16 +4384,29 @@ luamplib.colorconverter = colorconverter }% } \else + \def\mplibgetinstancename[#1]{\def\currentmpinstancename{#1}} + \protected\def\everymplib#1#{% + \ifx\empty#1\empty \mplibgetinstancename[]\else \mplibgetinstancename#1\fi + \begingroup + \mplibsetupcatcodes + \mplibdoeverymplib + } \long\def\mplibdoeverymplib#1{% \endgroup \directlua{ - luamplib.everymplib[""] = [===[\unexpanded{#1}]===] + luamplib.everymplib["\currentmpinstancename"] = [===[\unexpanded{#1}]===] }% } + \protected\def\everyendmplib#1#{% + \ifx\empty#1\empty \mplibgetinstancename[]\else \mplibgetinstancename#1\fi + \begingroup + \mplibsetupcatcodes + \mplibdoeveryendmplib + } \long\def\mplibdoeveryendmplib#1{% \endgroup \directlua{ - luamplib.everyendmplib[""] = [===[\unexpanded{#1}]===] + luamplib.everyendmplib["\currentmpinstancename"] = [===[\unexpanded{#1}]===] }% } \fi @@ -2693,14 +4414,13 @@ luamplib.colorconverter = colorconverter % % Allow \TeX\ dimen/color macros. Now |runscript| does the job, % so the following lines are not needed for most cases. -% But the macros will be expanded when they are used in another macro. % \begin{macrocode} \def\mpdim#1{ runscript("luamplibdimen{#1}") } \def\mpcolor#1#{\domplibcolor{#1}} \def\domplibcolor#1#2{ runscript("luamplibcolor{#1{#2}}") } % \end{macrocode} % -% MPLib's number system. Now |binary| has gone away. +% \mplib's number system. Now |binary| has gone away. % \begin{macrocode} \def\mplibnumbersystem#1{\directlua{ local t = "#1" @@ -2765,12 +4485,13 @@ luamplib.colorconverter = colorconverter % \end{macrocode} % % The followings are from ConTeXt general, mostly. -% % We use a dedicated scratchbox. +% +% We use a dedicated scratchbox. % \begin{macrocode} \ifx\mplibscratchbox\undefined \newbox\mplibscratchbox \fi % \end{macrocode} % -% We encapsulate the litterals. +% We encapsulate the literals. % \begin{macrocode} \def\mplibstarttoPDF#1#2#3#4{% \prependtomplibbox diff --git a/macros/luatex/generic/luamplib/luamplib.pdf b/macros/luatex/generic/luamplib/luamplib.pdf Binary files differindex 6d410a4c26..448c237835 100644 --- a/macros/luatex/generic/luamplib/luamplib.pdf +++ b/macros/luatex/generic/luamplib/luamplib.pdf diff --git a/macros/luatex/generic/luamplib/test-luamplib-latex.tex b/macros/luatex/generic/luamplib/test-luamplib-latex.tex index a077f67736..22b30b0760 100644 --- a/macros/luatex/generic/luamplib/test-luamplib-latex.tex +++ b/macros/luatex/generic/luamplib/test-luamplib-latex.tex @@ -1,9 +1,13 @@ %\DocumentMetadata{ uncompress } -\documentclass{article} +\ifnum\outputmode > 0 + \documentclass{article} +\else + \documentclass[dvipdfmx]{article} +\fi \usepackage{fontspec} \setmainfont{latin modern roman} \usepackage{luamplib} -\usepackage{xcolor} +\usepackage{graphicx,xcolor} \everymplib{ beginfig(0); } \everyendmplib{ endfig; } \mpliblegacybehavior{true}% @@ -171,15 +175,16 @@ diameter:\Dia bp.% \par \begin{mplibcode} beginfig(1) -draw mplibgraphictext "\bfseries Funny" - fakebold 2 scale 2 % fontspec options - drawcolor "blue" fillcolor "red!50" % l3color expressions - scaled 2 rotated 30 ; + draw mplibgraphictext "\bfseries Funny$\sqrt{2}$" + fakebold 2 % fontspec option + drawcolor blue fillcolor "red!50" % l3color expression + scaled 3 rotated 30 ; picture p; p:=mplibgraphictext "\bfseries\itshape xyz"; draw p scaled 3 shifted (40,0); endfig; \end{mplibcode}% +\par \mplibsetformat{metafun}% \begin{mplibcode} beginfig(1) @@ -197,6 +202,141 @@ fill unitsquare xyscaled (\mpdim\textwidth,1cm) ; endfig; \end{mplibcode}% +\leavevmode +\mpfig +picture Q, u, e; +Q := mplibglyph "Q" of "texgyrepagella-bolditalic.otf" scaled .1; +u := mplibglyph "u" of "texgyrepagella-bolditalic.otf" scaled .1 shifted lrcorner Q; +e := mplibglyph "e" of "texgyrepagella-bolditalic.otf" scaled .1 shifted lrcorner u; +i:=0; +totallen := length Q + length u + length e; +for pic=Q, u, e: + for item within pic: + i:=i+1; + fill pathpart item + if i < totallen: withpostscript "collect"; fi + endfor +endfor + withshademethod "linear" + withshadedirection (0.5,2.5) + withshadecolors (.7red,.7yellow) + ; +\endmpfig +\everymplib[@mpfig]{ drawoptions(withcolor mplibrgbtexcolor "olive"); }% +\mpfig* input boxes \endmpfig +\mpfig circleit.a(btex\tracingcommands0 Box 1 etex); drawboxed(a); \endmpfig +\def\mpfiginstancename{mympfig}% +\mpfig +draw mpliboutlinetext.b ("$\displaystyle\frac{1}{1-x^2}$") + (withcolor .6[red,white]) + (withpen pencircle scaled .2 withcolor red) + scaled 4 ; +\endmpfig +\par +\mpfig + draw mpliboutlinetext.r + ("Question") + ( withpen pencircle scaled .3 ) + ( + withshademethod "linear" + withshadedirection (2.5, 0.5) + withshadecolors(red, blue) + ) + scaled 4; +\endmpfig +\par\leavevmode +\mppattern{mypatt} +[ + xstep = 5, ystep = 6, +% matrix = "rotated 30", +] +\mpfig +draw (llcorner unitsquare--urcorner unitsquare) scaled 5 withcolor 1/3[blue,white] ; +draw (ulcorner unitsquare--lrcorner unitsquare) scaled 5 withcolor 1/3[red,white] ; +\endmpfig +\endmppattern +\mpfig +draw unitsquare shifted -center unitsquare scaled 45 withpostscript "collect" ; +draw fullcircle scaled 100 withpattern "mypatt" withpen pencircle scaled 1 + withcolor \mpcolor{red!50!blue!50} withpostscript "evenodd" ; +\endmpfig +\begin{mppattern}{pattuncolored} + [ + colored = false, + matrix = "slanted .3 rotated 30", + ] + \tiny\TeX +\end{mppattern}\relax +\mpfig + picture tex; + tex = mpliboutlinetext.p ("\bfseries \TeX"); + for i=1 upto mpliboutlinenum: + draw image( + j:=0; + for item within mpliboutlinepic[i]: + j:=j+1; + draw pathpart item scaled 10 + if j < length mpliboutlinepic[i]: + withpostscript "collect" + else: + withpattern "pattuncolored" + withpen pencircle scaled 1/2 + withcolor (i/4)[red,blue] + fi; + endfor + ) + withfademethod "linear" + ; + endfor +\endmpfig +\par\leavevmode +\mpfig + picture mill; mill = btex \includegraphics[width=100bp]{mill} etex; + draw mill; + mill := mill shifted 125right; + draw mill + withfademethod "circular" + withfadecenter (center mill, center mill) + withfaderadius (30, abs(lrcorner mill - llcorner mill)/2) + withfadeopacity (1, 0) + ; +\endmpfig +\par +\def\test#1{% + \mpfig + fill unitsquare shifted -center unitsquare scaled 200 + withshademethod "linear" + withshadecolors (.3[red,white], .3[blue,white]) + ; + label( btex MetaPost etex scaled 3, origin) ; + draw image( + fill fullcircle scaled 100 shifted 25left + withcolor .8white + withtransparency (2,1) + ; + fill fullcircle scaled 100 shifted 25right + withcolor .8white + withtransparency (2,1) + ; + ) + asgroup "#1" + withgroupname "test:#1" + withtransparency (1,.5) + ; + currentpicture := currentpicture scaled 2/3; + \endmpfig +}% +\hbox{\test{isolated,knockout}\,\test{isolated}\vbox to\MPheight{\vss\hbox{~isolated}\vss}}% +\hbox{\test{knockout}\,\test{}}% +\hbox to\MPwidth{\hss knockout\hss}% +\leavevmode +\mpfig usemplibgroup "test:isolated,knockout" scaled 2/3 rotated 15 ; \endmpfig +\usemplibgroup{test:isolated,knockout}% +\begin{mplibgroup}{mytex}[matrix="rotated 15"] \TeX \end{mplibgroup}% +\hbox to0pt{\hss\vrule width.5pt height5pt depth5pt\hss}% +\hbox to0pt{\hss\vrule width10pt height.25pt depth.25pt\hss}% +\usemplibgroup{mytex}% +\mpfig usemplibgroup "mytex"; draw (left--right) scaled 5; draw (up--down) scaled 5; \endmpfig \tracingcommands0 \vskip 2\baselineskip diff --git a/macros/luatex/generic/luamplib/test-luamplib-plain.tex b/macros/luatex/generic/luamplib/test-luamplib-plain.tex index 20773b280f..0804ca5a9b 100644 --- a/macros/luatex/generic/luamplib/test-luamplib-plain.tex +++ b/macros/luatex/generic/luamplib/test-luamplib-plain.tex @@ -1,6 +1,7 @@ +\input luaotfload.sty \input miniltx \input color -\definecolor{orange}{rgb}{1,0.5,0} +\definecolor{orange}{cmyk}{0,.5,1,0} \input luamplib.sty \mpliblegacybehavior{true}% \everymplib{ beginfig(0); }\everyendmplib{ endfig; } @@ -163,4 +164,210 @@ diameter:\Dia bp.% rotatedlabel.top(textext("Rotated!"), origin, 45); endfig; \endmplibcode +\par +\mplibcode +beginfig(1) % in dvi mode, not work for type1 font +draw mplibgraphictext "\bf Funny$\sqrt{2}$" + fakebold 2 % fontspec option + drawcolor blue fillcolor .5[red,white] + scaled 3 rotated 30 ; +picture p; +p:=mplibgraphictext "\it xyz" + fillcolor .7white; +draw p scaled 3 shifted (40,0); +endfig; +\endmplibcode +\par +\mplibsetformat{metafun}% +\mplibcode +beginfig(1) +fill unitsquare xyscaled (\mpdim\hsize, 1cm) + withshademethod "linear" + withshadevector (0,1) + withshadestep ( + withshadefraction .5 + withshadecolors (red,blue) + ) + withshadestep ( + withshadefraction 1 + withshadecolors (blue,green) + ) + ; +endfig; +\endmplibcode +\leavevmode +\mpfig +picture Q, u, e; +Q := mplibglyph "Q" of "texgyrepagella-bolditalic.otf" scaled .1; +u := mplibglyph "u" of "texgyrepagella-bolditalic.otf" scaled .1 shifted lrcorner Q; +e := mplibglyph "e" of "texgyrepagella-bolditalic.otf" scaled .1 shifted lrcorner u; +i:=0; +totallen := length Q + length u + length e; +for pic=Q, u, e: + for item within pic: + i:=i+1; + fill pathpart item + if i < totallen: withpostscript "collect"; fi + endfor +endfor + withshademethod "linear" + withshadedirection (0.5,2.5) + withshadecolors (.7red,.7yellow) + ; +\endmpfig +\everymplib[@mpfig]{ drawoptions(withcolor mplibrgbtexcolor"orange"); }% +\mpfig* input boxes \endmpfig +\mpfig circleit.a(btex\tracingcommands0 Box 1 etex); drawboxed(a); \endmpfig +\def\mpfiginstancename{mympfig}% +\mpfig +draw mpliboutlinetext.b ("$\overbrace{x+\cdots+x}^k$") + (withcolor .6[red,white]) + (withpen pencircle scaled .2 withcolor red) + scaled 3 ; +\endmpfig +\par +\mpfig + draw mpliboutlinetext.r + ("Question") + ( withpen pencircle scaled .3 ) + ( + withshademethod "linear" + withshadedirection (2.5, 0.5) + withshadecolors(red, blue) + ) + scaled 4; +\endmpfig +\par\leavevmode +\mppattern{mypatt} + \mpfig + picture q; + q := btex Q etex; + fill bbox q withcolor .8[red,white]; + draw q withcolor .8red; + \endmpfig +\endmppattern +\mpfig + fill fullcircle scaled 100 withpostscript "collect"; + draw unitsquare shifted - center unitsquare scaled 45 + withpattern "mypatt" + withpostscript "evenodd" + ; +\endmpfig +\mppattern{pattuncolored} + [ + colored = false, + matrix = "slanted .3 rotated 30", + ] + \fiverm\TeX +\endmppattern +\mpfig + picture tex; + tex = mpliboutlinetext.p ("\bf \TeX"); + draw image( + for i=1 upto mpliboutlinenum: + j:=0; + for item within mpliboutlinepic[i]: + j:=j+1; + draw pathpart item scaled 10 + if j < length mpliboutlinepic[i]: + withpostscript "collect" + else: + withpattern "pattuncolored" + withpen pencircle scaled 1/2 + withcolor (i/4)[red,blue] + fi; + endfor + endfor + ) + withfademethod "linear" + ; +\endmpfig +\par\leavevmode +\mpfig +fill fullcircle scaled 125 withcolor 2/3[blue,white]; +fill fullcircle scaled 80 withcolor 2/3[red,white]; +draw image( + draw (left--right) rotated 45 scaled 50 + withpen pencircle scaled 20 + ; + draw (left--right) rotated -45 scaled 50 + withpen pencircle scaled 20 + ; + ) + asgroup "" + withgroupname "testTRgroup" + withprescript "tr_transparency=.3" + ; +\endmpfig +\mpfig +fill fullcircle scaled 125 withcolor 2/3[red,white]; +fill fullcircle scaled 80 withcolor 2/3[blue,white]; +usemplibgroup "testTRgroup" + withfademethod "circular" + withfaderadius (0,60) + ; +\endmpfig +\mplibgroup{mytex}[matrix="rotated 15"] \TeX \endmplibgroup +\hbox to0pt{\hss\vrule width.5pt height5pt depth5pt\hss}% +\hbox to0pt{\hss\vrule width10pt height.25pt depth.25pt\hss}% +\usemplibgroup{mytex}% +\mpfig usemplibgroup "mytex"; draw (left--right) scaled 5; draw (up--down) scaled 5; \endmpfig +\tracingcommands0 + +\vskip 2\baselineskip +\mplibcodeinherit{disable} +\everymplib[instanceOne]{beginfig(1);} +\everyendmplib[instanceOne]{endfig;} + +\mplibcode[instanceOne] + picture TeX; + TeX := btex \TeX etex; +a := 1cm; +draw fullcircle scaled a; +draw btex a circle with $d=a$ etex shifted (a,0); +draw TeX; +\endmplibcode +Current instance name is: \currentmpinstancename \vskip 2\baselineskip + +\mplibcode[instanceTwo] +beginfig(1); +if not known a: + draw btex code is not inherited from an instance with a different name etex; +else: + errmessage("Variable was inherited from a different instance"); +fi; +endfig; +\endmplibcode +Current instance name is: \currentmpinstancename \vskip 2\baselineskip + +\mplibcode +beginfig(1); +if not known a: + draw btex code is not inherited if instance name is not listed etex; +else: + errmessage("Variable was inherited from a different instance"); +fi; +a := 1cm; +endfig; +\endmplibcode +Current instance name is: \currentmpinstancename (should be empty) \vskip 2\baselineskip + +\mplibcode +beginfig(1); +if not known a: + draw btex code is not inherited if mplibcodeinherit is disabled and instance name is not explicitly set etex; +else: + errmessage("Variable was inherited when code inheritance is turned off and instance name is not set"); +fi; +endfig; +\endmplibcode +Current instance name is: \currentmpinstancename (should be empty) \vskip 2\baselineskip + +\mplibcode[instanceOne] +draw unitsquare scaled a; +draw btex a square with side $=a$, inherited from the same instance etex shifted (3/2a, 1/2a); + draw TeX; +\endmplibcode +Current instance name is: \currentmpinstancename \vskip 2\baselineskip + \bye diff --git a/macros/luatex/generic/luatexja/COPYING b/macros/luatex/generic/luatexja/COPYING index 610a7b62b2..b82ffc50fe 100644 --- a/macros/luatex/generic/luatexja/COPYING +++ b/macros/luatex/generic/luatexja/COPYING @@ -1,4 +1,4 @@ -Copyright (c) 2011--2023 The LuaTeX-ja project, All rights reserved. +Copyright (c) 2011--2024 The LuaTeX-ja project, All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/macros/luatex/generic/luatexja/README b/macros/luatex/generic/luatexja/README index 4e48f6c82f..0bc40ac643 100644 --- a/macros/luatex/generic/luatexja/README +++ b/macros/luatex/generic/luatexja/README @@ -1,6 +1,6 @@ -The LuaTeX-ja Package 20240219.0 +The LuaTeX-ja Package 20240714.0 -------------------------------- -Copyright (c) 2011--2023 The LuaTeX-ja project +Copyright (c) 2011--2024 The LuaTeX-ja project License: modified BSD (see COPYING) LuaTeX-ja is a macro package for typesetting Japanese documents with LuaTeX. @@ -24,7 +24,8 @@ Installation - LuaTeX 1.10.0 (or later) - luaotfload (v3.1 or later recommended) - adobemapping (Adobe CMap files) - - LaTeX2e 2020-02-02 patch level 5 or later (if you want to use with LaTeX) + - LaTeX2e 2021-06-01 or later (if you want to use with LaTeX) + - l3kernel about 2023-10-10 or later - etoolbox package - ltxcmds package, pdftexcmds package - filehook package, atbegshi package (for LaTeX2e 2020-02-02) @@ -32,7 +33,7 @@ Installation - Harano Aji fonts (https://github.com/trueroad/HaranoAjiFonts) more specifically, HaranoAjiMincho-Regular and HaranoAjiGothic-Medium - Using LuaTeX-ja with LuaHBTeX is not well tested. + Using LuaTeX-ja with Harfbuzz is not well tested. One might be able to typeset documents without an error, but with some unwanted results. @@ -41,7 +42,7 @@ Installation 2. If you must/want to install manually: a. Download the source archive from CTAN, - or tagged as 20240219.0 in the Git repository by + or tagged as 20240714.0 in the Git repository by <https://github.com/luatexja/luatexja/archive/refs/tags/$VER.zip> b. Extract the archive and process following three files by LuaLaTeX @@ -91,4 +92,4 @@ Notes This file and ltj-kinsoku.lua are not used anymore. (Do not remove ltj-kinsoku.tex.) -Last commit date: Mon Feb 19 19:11:46 2024 +0900 +Last commit date: Sun Jul 14 08:56:04 2024 +0900 diff --git a/macros/luatex/generic/luatexja/doc/luatexja-en.pdf b/macros/luatex/generic/luatexja/doc/luatexja-en.pdf Binary files differindex 547c5f9b46..eac7af315d 100644 --- a/macros/luatex/generic/luatexja/doc/luatexja-en.pdf +++ b/macros/luatex/generic/luatexja/doc/luatexja-en.pdf diff --git a/macros/luatex/generic/luatexja/doc/luatexja-ja.pdf b/macros/luatex/generic/luatexja/doc/luatexja-ja.pdf Binary files differindex 3dc1d9a8d7..ee55789a60 100644 --- a/macros/luatex/generic/luatexja/doc/luatexja-ja.pdf +++ b/macros/luatex/generic/luatexja/doc/luatexja-ja.pdf diff --git a/macros/luatex/generic/luatexja/doc/luatexja.dtx b/macros/luatex/generic/luatexja/doc/luatexja.dtx index dace65c689..9ad5209465 100644 --- a/macros/luatex/generic/luatexja/doc/luatexja.dtx +++ b/macros/luatex/generic/luatexja/doc/luatexja.dtx @@ -648,14 +648,9 @@ and \emph{Japanese fonts} for fonts used in \textbf{JAchar}. %<ja> (DVI出力(\cs{outputmode=0})は対応していない.) \item recent \href{https://github.com/latex3/luaotfload}{\Pkg{luaotfload}} (v3.1 or later recommended) \item \Pkg{adobemapping} (Adobe cmap and pdfmapping files) -\item \LaTeXe\ 2020-02-02 patch level 5 or later -%<en> (if you want to use \LuaTeX-ja with \LaTeXe) -%<ja> (\LaTeXe 下で\LuaTeX-jaを使う場合) \item \href{https://github.com/josephwright/etoolbox/}{\Pkg{etoolbox}} %<en> (if you want to use \LuaTeX-ja with \LaTeXe) %<ja> (\LaTeXe 下で\LuaTeX-jaを使う場合) -\item \Pkg{everysel} (only for \LaTeXe\ 2020-02-02~and~2020-10-01) -\item \Pkg{filehook}, \Pkg{atbegshi} (only for \LaTeXe\ 2020-02-02) \item \Pkg{ltxcmds}, \Pkg{pdftexcmds} \item \href{https://github.com/wspr/fontspec/}{\Pkg{fontspec}} v2.7c (or later) %<*en> @@ -1472,14 +1467,19 @@ Alphabetic fonts &\cs{fontspec}&\cs{setmainfont}&\cs{setsansfont}&\cs{setmonofont}\\ \midrule Japanese fonts -&\cs{newjfontfamily}&\cs{renewjfontfamily}&\cs{setjfontfamily}\\ +&\cs{newjfontfamily}&\cs{renewjfontfamily}&\cs{setjfontfamily}&\cs{providejfontfamily}\\ +Alphabetic fonts +&\cs{newfontfamily}&\cs{renewfontfamily}&\cs{setfontfamily}&\cs{providefontfamily}\\ +\midrule +Japanese fonts +&\cs{newjfontface}&\cs{renewjfontface}&\cs{setjfontface}&\cs{providejfontface}\\ Alphabetic fonts -&\cs{newfontfamily}&\cs{renewfontfamily}&\cs{setfontfamily}\\ +&\cs{newfontface}&\cs{renewfontface}&\cs{setfontface}&\cs{providefontface}\\ \midrule Japanese fonts -&\cs{newjfontface}&\cs{defaultjfontfeatures}&\cs{addjfontfeatures}\\ +&\cs{defaultjfontfeatures}&\cs{addjfontfeatures}\\ Alphabetic fonts -&\cs{newfontface}&\cs{defaultfontfeatures}&\cs{addfontfeatures}\\ +&\cs{defaultfontfeatures}&\cs{addfontfeatures}\\ \bottomrule \end{tabular}\par} \end{table} @@ -1497,14 +1497,19 @@ Alphabetic fonts &\cs{fontspec}&\cs{setmainfont}&\cs{setsansfont}&\cs{setmonofont}\\ \midrule \emph{和文} -&\cs{newjfontfamily}&\cs{renewjfontfamily}&\cs{setjfontfamily}\\ +&\cs{newjfontfamily}&\cs{renewjfontfamily}&\cs{setjfontfamily}&\cs{providejfontfamily}\\ +\emph{欧文} +&\cs{newfontfamily}&\cs{renewfontfamily}&\cs{setfontfamily}&\cs{providefontfamily}\\ +\midrule +\emph{和文} +&\cs{newjfontface}&\cs{renewjfontface}&\cs{setjfontface}&\cs{providejfontface}\\ \emph{欧文} -&\cs{newfontfamily}&\cs{renewfontfamily}&\cs{setfontfamily}\\ +&\cs{newfontface}&\cs{renewfontface}&\cs{setfontface}&\cs{providefontface}\\ \midrule \emph{和文} -&\cs{newjfontface}&\cs{defaultjfontfeatures}&\cs{addjfontfeatures}\\ +&\cs{defaultjfontfeatures}&\cs{addjfontfeatures}\\ \emph{欧文} -&\cs{newfontface}&\cs{defaultfontfeatures}&\cs{addfontfeatures}\\ +&\cs{defaultfontfeatures}&\cs{addfontfeatures}\\ \bottomrule \end{tabular}\par} \end{table} @@ -7838,7 +7843,7 @@ stretch_priority={kanjiskip=-35,xkanjiskip=-25,others=50} さらに,バージョン20220211.0以降では次の命令が提供される. \begin{cslist} - \item[\cs{ltjghostbeginjachar}] + \item[\cs{ltjghostbeforejachar}] \LuaTeX-ja本体が提供している\cs{ltjfakeparbegin}, \cs{ltjfakeboxbdd}と類似の命令である. 実行された箇所が(限定・非限定を問わず)水平モードであった場合に,実行された箇所は 「文字クラス0の\textbf{JAchar}」の直前であると, @@ -7855,7 +7860,7 @@ A\LG 字 \par% ==> ALchar--(xkanjiskip)--\LG \end{LTXexample} \item[\cs{ltjghostafterjachar}] - \cs{ltjghostbeginjachar}と対を成す命令で,実行された箇所は + \cs{ltjghostbeforejachar}と対を成す命令で,実行された箇所は 「文字クラス0の\textbf{JAchar}」の直後であると, \LuaTeX-jaの和文処理グルー挿入処理に認識させる.以下の実行例を参照. diff --git a/macros/luatex/generic/luatexja/src/addons/luatexja-fontspec-27c.sty b/macros/luatex/generic/luatexja/src/addons/luatexja-fontspec-27c.sty index 76ebf8716c..6ef3ff1751 100644 --- a/macros/luatex/generic/luatexja/src/addons/luatexja-fontspec-27c.sty +++ b/macros/luatex/generic/luatexja/src/addons/luatexja-fontspec-27c.sty @@ -3,7 +3,7 @@ % \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{luatexja-fontspec-27c}[2024-02-19 fontspec support of LuaTeX-ja] +\ProvidesPackage{luatexja-fontspec-27c}[2024-05-27 fontspec support of LuaTeX-ja] \RequirePackage{l3keys2e} \ExplSyntaxOn @@ -359,10 +359,24 @@ \setfontfamily #1 [#2,#4] {#3} \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_orig_fontspec_set_family:Nnn } +\DeclareDocumentCommand \providejfontfamily { m O{} m O{} } { + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_fontspec_set_family:Nnn + \providefontfamily #1 [#2,#4] {#3} + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_orig_fontspec_set_family:Nnn +} \DeclareDocumentCommand \newjfontface { m O{} m O{} } { \newjfontfamily #1 [ BoldFont={},ItalicFont={},SmallCapsFont={},#2,#4 ] {#3} } +\DeclareDocumentCommand \renewjfontface { m O{} m O{} } { + \renewjfontfamily #1 [ BoldFont={},ItalicFont={},SmallCapsFont={},#2,#4 ] {#3} +} +\DeclareDocumentCommand \setjfontface { m O{} m O{} } { + \setjfontfamily #1 [ BoldFont={},ItalicFont={},SmallCapsFont={},#2,#4 ] {#3} +} +\DeclareDocumentCommand \providejfontface { m O{} m O{} } { + \providejfontfamily #1 [ BoldFont={},ItalicFont={},SmallCapsFont={},#2,#4 ] {#3} +} \prop_new:N \l__ltj_fontspec_tmp_prop \prop_new:N \g__ltj_fontspec_fontopts_prop diff --git a/macros/luatex/generic/luatexja/src/addons/luatexja-fontspec-29c.sty b/macros/luatex/generic/luatexja/src/addons/luatexja-fontspec-29c.sty new file mode 100644 index 0000000000..51af33447c --- /dev/null +++ b/macros/luatex/generic/luatexja/src/addons/luatexja-fontspec-29c.sty @@ -0,0 +1,429 @@ +% +% luatexja-fontspec-29c.sty +% + +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{luatexja-fontspec-29c}[2024-05-27 fontspec support of LuaTeX-ja] +\RequirePackage{l3keys2e} +\ExplSyntaxOn + +%%%%%%%% Change Japanese font family by \rmfamily or not +\bool_if:NT \__ltj_fontspec_match_bool { + \renewcommand\jttdefault{\gtdefault} + \@ltj@match@familytrue +} +%%%%%%%% Messages +\msg_new:nnn {luatexja-fontspec} {addjfontfeatures-ignored} +{ + \string\addjfontfeature (s)~ ignored;\\ + it~ cannot~ be~ used~ with~ a~ font~ that~ wasn't~ selected~ by~ luatexja-fontspec. +} + +\msg_new:nnn {luatexja-fontspec} {altfont-ignored-by-norange} +{ + ignored~ sublist~ `#1'~ in~ AltFont~ (no~ range~ is~ specified). +} + +\msg_new:nnn {luatexja-fontspec} {altfont-ignored-by-rangeonly} +{ + ignored~ sublist~ `#1'~ in~ AltFont~ (only~ range~ is~ specified). +} + +\cs_generate_variant:Nn \prg_new_conditional:Nnn {Nnx} + +%%%%%%%% Internal control sequences +%% Each CS is ltj_fontspec version that corresponds to original CS of fontspec. +\cs_new:Nn \__ltj_fontspec_define_option:nn { + \__fontspec_keys_define_code:nnn {fontspec} {#1} {#2} +} +\cs_new:Nn \__ltj_fontspec_define_preparse_external:nn { + \__fontspec_keys_define_code:nnn {fontspec-preparse-external} {#1} {#2} +} +\cs_new:Nn \__ltj_fontspec_define_altfont_option:nn { + \__fontspec_keys_define_code:nnn {fontspec-ltjaltfont} {#1} {#2} +} + +%% Alternate Fonts +%% Spec: AltFont = { +%% ... +%% { Range = <range>, <font features> }, +%% { Range = <range>, Font = <font name>, <font features> }, +%% { Range = <range>, Font = <font name> }, +%% ... +%% } +\tl_new:N \l__ltj_fontspec_altname_tl +\tl_new:N \l__ltj_fontspec_altrange_tl +\clist_new:N \l__ltj_fontspec_altfont_clist +\clist_new:N \l__ltj_fontspec_altfont_leftover_clist +\int_new:N \g__ltj_fontspec_altnumber_int + +\__ltj_fontspec_define_altfont_option:nn {Range} { + \tl_set:Nn \l__ltj_fontspec_altrange_tl {#1} +} +\__ltj_fontspec_define_altfont_option:nn {Font} { + \fontspec_complete_fontname:Nn \l__ltj_fontspec_altname_tl {#1} +} +\__fontspec_keys_define_code:nnn {fontspec-ltjaltfont-reparse} {AltFont} { + \clist_put_right:Nn \l__ltj_fontspec_altfont_clist { #1 } +} +\__fontspec_keys_define_code:nnn {fontspec-ltjaltfont-reparse} {YokoFeatures} { + \clist_put_right:Nn \l__ltj_fontspec_fontfeat_yoko_clist { #1 } +} +\__fontspec_keys_define_code:nnn {fontspec-ltjaltfont-reparse} {TateFeatures} { + \clist_put_right:Nn \l__ltj_fontspec_fontfeat_tate_clist { #1 } +} +\__fontspec_keys_define_code:nnn {fontspec-ltjaltfont-reparse} {TateFont} { + \tl_if_empty:nF {#1} { + \fontspec_complete_fontname:Nn \l__ltj_fontspec_fontname_tate_tl {#1} + } +} +%% +\clist_new:N \l__ltj_fontspec_fontfeat_yoko_clist +\clist_new:N \l__ltj_fontspec_fontfeat_tate_clist +\tl_new:N \l__ltj_fontspec_fontname_tate_tl + +\cs_new:Npn \__ltj_fontspec_DeclareFontFamily #1 #2 #3 { + \DeclareKanjiFamily {JY3} {#2} {#3} + \DeclareKanjiFamily {JT3} {#2} {#3} +} + +%% save and restore global variable +\tl_new:N \g__ltj_fontspec_kanji_nfss_family_tl +\tl_new:N \g__ltj_fontspec_orig_nfss_family_tl +\seq_new:N \l__ltj_fontspec_kanji_bf_series_seq +\seq_new:N \l__ltj_fontspec_orig_bf_series_seq +\clist_new:N \g__ltj_fontspec_kanji_default_fontopts_clist +\clist_new:N \g__ltj_fontspec_orig_default_fontopts_clist + +\cs_new:Nn \__ltj_set_global_variable_for_kanji: { + \tl_gset_eq:NN \g__ltj_fontspec_orig_nfss_family_tl \g__fontspec_nfss_family_tl + \tl_gset_eq:NN \g__fontspec_nfss_family_tl \g__ltj_fontspec_kanji_nfss_family_tl + \seq_set_eq:NN \l__ltj_fontspec_orig_bf_series_seq \l__fontspec_bf_series_seq + \seq_set_eq:NN \l__fontspec_bf_series_seq \l__ltj_fontspec_kanji_bf_series_seq + %\seq_gclear:N \g__fontspec_bf_series_seq + \clist_set_eq:NN \g__ltj_fontspec_orig_default_fontopts_clist \g__fontspec_default_fontopts_clist + \clist_set_eq:NN \g__fontspec_default_fontopts_clist \g__ltj_fontspec_kanji_default_fontopts_clist +} + +\cs_new:Nn \__ltj_restore_global_variable: { + \tl_gset_eq:NN \g__ltj_fontspec_kanji_nfss_family_tl \g__fontspec_nfss_family_tl + \tl_gset_eq:NN \g__fontspec_nfss_family_tl \g__ltj_fontspec_orig_nfss_family_tl + \seq_set_eq:NN \l__ltj_fontspec_kanji_bf_series_seq \l__fontspec_bf_series_seq + \seq_set_eq:NN \l__fontspec_bf_series_seq \l__ltj_fontspec_orig_bf_series_seq + \clist_set_eq:NN \g__ltj_fontspec_kanji_default_fontopts_clist \g__fontspec_default_fontopts_clist + \clist_set_eq:NN \g__fontspec_default_fontopts_clist \g__ltj_fontspec_orig_default_fontopts_clist +} + +\cs_set_eq:NN \__ltj_orig_fontspec_select_font_family:nn \__fontspec_select_font_family:nn +\cs_new_protected:Nn \__ltj_fontspec_select_font_family:nn { + \group_begin: + \__ltj_fontspec_define_option:nn {NoEmbed} {} + \__ltj_fontspec_define_option:nn {AltFont} { + \clist_put_right:Nn \l__ltj_fontspec_altfont_clist { ##1 } + } + \__ltj_fontspec_define_option:nn {CID} { + \__fontspec_update_featstr:n {cid=##1} + } + \__ltj_fontspec_define_option:nn {Kanjiskip} { + \str_if_eq:eeTF {false} { \str_lower_case:n { ##1 } }{ + \__fontspec_update_featstr:n {-ltjksp} + } { + \__fontspec_update_featstr:n {+ltjksp} + } + } + \__ltj_fontspec_define_option:nn {JFM} { + \__fontspec_update_featstr:n {jfm=##1} + } + % vary by shape + \__ltj_fontspec_define_option:nn {YokoFeatures} { + \clist_put_right:Nn \l__ltj_fontspec_fontfeat_yoko_clist { ##1 } + } + \__ltj_fontspec_define_option:nn {TateFeatures} { + \clist_put_right:Nn \l__ltj_fontspec_fontfeat_tate_clist { ##1 } + } + \__ltj_fontspec_define_option:nn {TateFont} + { + \tl_if_empty:nF {##1} { + \fontspec_complete_fontname:Nn \l__ltj_fontspec_fontname_tate_tl {##1} + } + } + \__ltj_fontspec_define_option:nn {JFM-var} { + \__fontspec_update_featstr:n {jfmvar=##1} + } + \__ltj_fontspec_define_preparse_external:nn {NoEmbed} { + \cs_set:Npn \__fontspec_fontname_wrap:n ##1 {psft:##1} + } + + %% Omit the warning message + %% "OpenType feature 'Kerning=Off' (-kern) not available ..." + \keys_define:nn {fontspec-opentype} { + Kerning/Off.code:n=\__fontspec_update_featstr:n {-kern} + } + \clist_set:Ne \g__fontspec_default_fontopts_clist { + YokoFeatures = { JFM=\ltj@stdyokojfm }, TateFeatures = { JFM=\ltj@stdtatejfm }, + Scale=\Cjascale, Kerning=Off, Script=CJK, + \g__ltj_fontspec_kanji_default_fontopts_clist + } + \prop_set_eq:NN \g__fontspec_fontopts_prop \g__ltj_fontspec_fontopts_prop + \cs_set_eq:NN \__fontspec_make_font_shapes:Nnnnn \__ltj_fontspec_make_font_shapes:Nnnnn + \cs_set_eq:NN \DeclareFontFamily \__ltj_fontspec_DeclareFontFamily + \tl_set:Nn \g_fontspec_encoding_tl {JY3} + \__ltj_orig_fontspec_select_font_family:nn{#1}{#2} + + \cs_gset:Npx \__ltj_fontspec_aftergroup { + \exp_not:N \tl_set:Nn \exp_not:N \l_fontspec_family_tl { \l_fontspec_family_tl } + } + \aftergroup \__ltj_fontspec_aftergroup + \group_end: +} + +%% declare_shape + +\cs_new:Nn \__ltj_fontspec_declare_shape_yoko:nnnn { + \__ltj_fontspec_declare_shape_aux:nnnnnn {#1} {#2} {#3} {#4} { JY3 } { \l__ltj_fontspec_fontfeat_yoko_clist } +} +\cs_new:Nn \__ltj_fontspec_declare_shape_tate:nnnn { + \__ltj_fontspec_declare_shape_aux:nnnnnn {#1} {#2} {#3} {#4} { JT3 } { \l__ltj_fontspec_fontfeat_tate_clist } +} +\cs_new:Nn \__ltj_fontspec_declare_shape:nnnn { + \__ltj_fontspec_declare_shape_yoko:nnnn {#1} {#2} {#3} {#4} + \__ltj_fontspec_declare_shape_tate:nnnn {#1} {#2} {#3} {#4} +} +\cs_generate_variant:Nn \__ltj_fontspec_declare_shape:nnnn {nnxx} +\cs_generate_variant:Nn \__ltj_fontspec_declare_shape_yoko:nnnn {nnxx} +\cs_generate_variant:Nn \__ltj_fontspec_declare_shape_tate:nnnn {nnxx} + +\cs_new:Nn \__ltj_fontspec_declare_shape_aux:nnnnnn +{ + \tl_build_begin:N \l__fontspec_nfss_tl + \tl_build_begin:N \l__fontspec_nfss_sc_tl + \tl_set_eq:NN \l__fontspec_saved_fontname_tl \l_fontspec_fontname_tl + + \tl_set:Nn \g_fontspec_encoding_tl {#5} + \tl_set:Nn \g__fontspec_nfss_enc_tl {#5} + \exp_args:Ne \clist_map_inline:nn {#4} + { \__ltj_fontspec_setup_single_size:nnn {#3} {#6} {##1} } + \tl_build_end:N \l__fontspec_nfss_tl + \tl_build_end:N \l__fontspec_nfss_sc_tl + + \bool_set_true:N \l__fontspec_nosc_bool + \__fontspec_declare_shapes_normal:nn {#1} {#2} + \__fontspec_declare_shape_slanted:nn {#1} {#2} +} + +\cs_new:Nn \__ltj_fontspec_setup_single_size:nnn +{ + \tl_clear:N \l__fontspec_size_tl + \tl_set_eq:NN \l__fontspec_sizedfont_tl \l__fontspec_saved_fontname_tl % in case not spec'ed + + \keys_set_known:neN {fontspec-sizing} { \exp_after:wN \use:n #3 } + \l__fontspec_sizing_leftover_clist + \tl_if_empty:NT \l__fontspec_size_tl { \__fontspec_error:n {no-size-info} } + + \str_if_eq:eeTF { \g__fontspec_nfss_enc_tl } { JY3 } { + % "normal" + \__fontspec_load_fontname:Nn \l_fontspec_fontname_tl {\l__fontspec_sizedfont_tl} + } { + \tl_if_empty:NTF \l__ltj_fontspec_fontname_tate_tl + { \__fontspec_load_fontname:Nn \l_fontspec_fontname_tl {\l__fontspec_sizedfont_tl} } + { \__fontspec_load_fontname:Nn \l_fontspec_fontname_tl {\l__ltj_fontspec_fontname_tate_tl} } + } + \__fontspec_setup_nfss:Nnnn \l__fontspec_nfss_tl {#1} {#2} {} +} + +\cs_new:Nn \__ltj_fontspec_set_family:Nnn { + \__ltj_set_global_variable_for_kanji: + \cs_set_eq:NN \__fontspec_select_font_family:nn \__ltj_fontspec_select_font_family:nn + \__ltj_orig_fontspec_set_family:Nnn #1 {#2} {#3} + \cs_set_eq:NN \__fontspec_select_font_family:nn \__ltj_orig_fontspec_select_font_family:nn + \__ltj_restore_global_variable: +} +\cs_set_eq:NN \__ltj_orig_fontspec_set_family:Nnn \fontspec_set_family:Nnn +\cs_set_eq:NN \__ltj_orig_fontspec_make_font_shapes:Nnnnn \__fontspec_make_font_shapes:Nnnnn +\cs_set_eq:NN \__ltj_fontspec_orig_DeclareFontShape \DeclareFontShape + +\cs_new:Nn \__ltj_fontspec_make_font_shapes:Nnnnn { + \group_begin: + %% 基底フォント + \cs_set_eq:NN \__fontspec_font_set:Nnn \use_none:nnn + \cs_set_eq:NN \__fontspec_font_if_null:NT \use_none:nn + \cs_set_eq:NN \__fontspec_declare_shape:nnxx \__ltj_fontspec_declare_shape:nnxx + \__ltj_orig_fontspec_make_font_shapes:Nnnnn {#1} {#2} {#3} {#4} {#5} + %% + \__ltj_fontspec_make_font_shapes_alt:Nnnnnn {#1}{#2}{#3} + {#4, \l__ltj_fontspec_fontfeat_yoko_clist}{#5} {JY3 } + \__ltj_fontspec_make_font_shapes_alt:Nnnnnn {#1}{#2}{#3} + {#4, \l__ltj_fontspec_fontfeat_tate_clist}{#5} {JT3} + \group_end: + } + +%%% Altfont 内部処理部 +\cs_new:Nn \__ltj_fontspec_make_font_shapes_alt:Nnnnnn { + \group_begin: + \str_if_eq:eeTF { #6 } { JY3 } { + \cs_set_eq:NN \__fontspec_declare_shape:nnxx \__ltj_fontspec_declare_shape_yoko:nnxx + }{ + \cs_set_eq:NN \__fontspec_declare_shape:nnxx \__ltj_fontspec_declare_shape_tate:nnxx + } + \keys_set_known:nn {fontspec-ltjaltfont-reparse} { #4 } + \clist_if_empty:NF \l__ltj_fontspec_altfont_clist { + \int_gzero:N \g__ltj_fontspec_altnumber_int + \clist_map_inline:Nn \l__ltj_fontspec_altfont_clist { + \tl_clear:N \l__ltj_fontspec_altrange_tl + \tl_set:Nn \l__ltj_fontspec_altname_tl { #1 } + \tl_set:Nn \l_tmpa_tl { #1 } + + \keys_set_known:neN {fontspec-ltjaltfont} { \exp_after:wN \use:n ##1 } + \l__ltj_fontspec_altfont_leftover_clist + \keys_set_known:nn {fontspec-ltjaltfont-reparse} { \exp_after:wN \use:n ##1 } + + \tl_if_empty:NT \l__ltj_fontspec_altrange_tl { + \msg_warning:nnn {luatexja-fontspec} {altfont-ignored-by-norange} { ##1 } + } { + \bool_if:nTF { + \tl_if_eq_p:NN \l__ltj_fontspec_altname_tl \l_tmpa_tl + && + \tl_if_empty_p:N \l__ltj_fontspec_altfont_leftover_clist + } { + \msg_warning:nnn {luatexja-fontspec} {altfont-ignored-by-rangeonly} { ##1 } + } { + \__ltj_orig_fontspec_make_font_shapes:Nnnnn + { \l__ltj_fontspec_altname_tl } {#2} + {#3 _ alt \int_use:N \g__ltj_fontspec_altnumber_int } + {#4, \l__ltj_fontspec_altfont_leftover_clist } + {#5} + \DeclareAlternateKanjiFont + { #6 }{ \g__fontspec_nfss_family_tl }{#2}{#3}% + { #6 }{ \g__fontspec_nfss_family_tl }{#2} + { #3 _alt \int_use:N \g__ltj_fontspec_altnumber_int } + { \l__ltj_fontspec_altrange_tl } + \int_gincr:N \g__ltj_fontspec_altnumber_int + } + } + } + } + \group_end: +} + + +%%%%%%%% User commands +\DeclareDocumentCommand \jfontspec { O{} m O{} } { + \__ltj_fontspec_set_family:Nnn \k@family {#1,#3}{#2} + \selectfont + \ignorespaces +} + +\DeclareDocumentCommand \setmainjfont { O{} m O{} } { + \ifdefined\DeclareFontSeriesDefault + \DeclareFontSeriesDefault[mc]{bf}{\bfdefault} + \fi + \__ltj_fontspec_set_family:Nnn \mcdefault {#1,#3}{#2} + \unless\ifltj@disablejfam + \DeclareSymbolFont{mincho}{JY3}{\mcdefault}{\mddefault}{n} + \SetSymbolFont{mincho}{bold}{JY3}{\mcdefault}{\bfdefault}{n} + \fi + \normalfont +} + +\DeclareDocumentCommand \setsansjfont { O{} m O{} } { + \ifdefined\DeclareFontSeriesDefault + \DeclareFontSeriesDefault[gt]{bf}{\bfdefault} + \fi + \__ltj_fontspec_set_family:Nnn \gtdefault {#1,#3}{#2} + \unless\ifltj@disablejfam + \DeclareMathAlphabet{\mathgt}{JY3}{\gtdefault}{\mddefault}{n} + \fi + \normalfont +} + +\DeclareDocumentCommand \setmonojfont { O{} m O{} } { + \ifdefined\DeclareFontSeriesDefault + \DeclareFontSeriesDefault[jtt]{bf}{\bfdefault} + \fi + \__ltj_fontspec_set_family:Nnn \jttdefault {#1,#3}{#2} + \normalfont +} + +\DeclareDocumentCommand \newjfontfamily { m O{} m O{} } { + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_fontspec_set_family:Nnn + \newfontfamily #1 [#2,#4] {#3} + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_orig_fontspec_set_family:Nnn +} +\DeclareDocumentCommand \renewjfontfamily { m O{} m O{} } { + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_fontspec_set_family:Nnn + \renewfontfamily #1 [#2,#4] {#3} + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_orig_fontspec_set_family:Nnn +} +\DeclareDocumentCommand \setjfontfamily { m O{} m O{} } { + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_fontspec_set_family:Nnn + \setfontfamily #1 [#2,#4] {#3} + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_orig_fontspec_set_family:Nnn +} +\DeclareDocumentCommand \providejfontfamily { m O{} m O{} } { + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_fontspec_set_family:Nnn + \providefontfamily #1 [#2,#4] {#3} + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_orig_fontspec_set_family:Nnn +} + +\DeclareDocumentCommand \newjfontface { m O{} m O{} } { + \newjfontfamily #1 [ BoldFont={},ItalicFont={},SmallCapsFont={},#2,#4 ] {#3} +} +\DeclareDocumentCommand \renewjfontface { m O{} m O{} } { + \renewjfontfamily #1 [ BoldFont={},ItalicFont={},SmallCapsFont={},#2,#4 ] {#3} +} +\DeclareDocumentCommand \setjfontface { m O{} m O{} } { + \setjfontfamily #1 [ BoldFont={},ItalicFont={},SmallCapsFont={},#2,#4 ] {#3} +} +\DeclareDocumentCommand \providejfontface { m O{} m O{} } { + \providejfontfamily #1 [ BoldFont={},ItalicFont={},SmallCapsFont={},#2,#4 ] {#3} +} + +\prop_new:N \l__ltj_fontspec_tmp_prop +\prop_new:N \g__ltj_fontspec_fontopts_prop +\DeclareDocumentCommand \defaultjfontfeatures { t+ o m } + { + \IfNoValueTF {#2} + { \__ltj_fontspec_set_default_features:nn {#1} {#3} } + { \__ltj_fontspec_set_font_default_features:nnn {#1} {#2} {#3} } + \ignorespaces + } +\cs_new:Nn \__ltj_fontspec_set_default_features:nn + { + \__ltj_set_global_variable_for_kanji: + \__fontspec_set_default_features:nn {#1} {#2} + \__ltj_restore_global_variable: + } +\cs_new:Nn \__ltj_fontspec_set_font_default_features:nnn + { + \prop_set_eq:NN \l__ltj_fontspec_tmp_prop \g__fontspec_fontopts_prop + \prop_set_eq:NN \g__fontspec_fontopts_prop \g__ltj_fontspec_fontopts_prop + \__fontspec_set_font_default_features:nnn {#1} {#2} {#3} + \prop_set_eq:NN \g__ltj_fontspec_fontopts_prop \g__fontspec_fontopts_prop + \prop_set_eq:NN \g__fontspec_fontopts_prop \l__ltj_fontspec_tmp_prop + } + +\DeclareDocumentCommand \addjfontfeatures {m} { + \__ltj_fontspec_if_fontspec_font:TF + { + \__ltj_set_global_variable_for_kanji: + \group_begin: + \tl_set_eq:NN \f@family \k@family + \cs_set_eq:NN \__fontspec_select_font_family:nn \__ltj_fontspec_select_font_family:nn + \addfontfeatures {#1} + \group_end: + \kanjifamily\g__fontspec_nfss_family_tl\selectfont + \__ltj_restore_global_variable: + }{ + \msg_warning:nn {luatexja-fontspec} {addjfontfeatures-ignored} + } + \ignorespaces +} + +\cs_set_eq:NN \addjfontfeature \addjfontfeatures + +\prg_new_conditional:Nnn \__ltj_fontspec_if_fontspec_font: {TF,T,F} +{ + \cs_if_exist:cTF {g__fontspec_fontinfo_ \k@family _prop} \prg_return_true: \prg_return_false: +} + +\endinput diff --git a/macros/luatex/generic/luatexja/src/addons/luatexja-fontspec-29e.sty b/macros/luatex/generic/luatexja/src/addons/luatexja-fontspec-29e.sty new file mode 100644 index 0000000000..02a79ad6ca --- /dev/null +++ b/macros/luatex/generic/luatexja/src/addons/luatexja-fontspec-29e.sty @@ -0,0 +1,429 @@ +% +% luatexja-fontspec-29e.sty +% + +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{luatexja-fontspec-29e}[2024-05-27 fontspec support of LuaTeX-ja] +\RequirePackage{l3keys2e} +\ExplSyntaxOn + +%%%%%%%% Change Japanese font family by \rmfamily or not +\bool_if:NT \__ltj_fontspec_match_bool { + \renewcommand\jttdefault{\gtdefault} + \@ltj@match@familytrue +} +%%%%%%%% Messages +\msg_new:nnn {luatexja-fontspec} {addjfontfeatures-ignored} +{ + \string\addjfontfeature (s)~ ignored;\\ + it~ cannot~ be~ used~ with~ a~ font~ that~ wasn't~ selected~ by~ luatexja-fontspec. +} + +\msg_new:nnn {luatexja-fontspec} {altfont-ignored-by-norange} +{ + ignored~ sublist~ `#1'~ in~ AltFont~ (no~ range~ is~ specified). +} + +\msg_new:nnn {luatexja-fontspec} {altfont-ignored-by-rangeonly} +{ + ignored~ sublist~ `#1'~ in~ AltFont~ (only~ range~ is~ specified). +} + +\cs_generate_variant:Nn \prg_new_conditional:Nnn {Nnx} + +%%%%%%%% Internal control sequences +%% Each CS is ltj_fontspec version that corresponds to original CS of fontspec. +\cs_new:Nn \__ltj_fontspec_define_option:nn { + \__fontspec_keys_define_code:nnn {fontspec} {#1} {#2} +} +\cs_new:Nn \__ltj_fontspec_define_preparse_external:nn { + \__fontspec_keys_define_code:nnn {fontspec-preparse-external} {#1} {#2} +} +\cs_new:Nn \__ltj_fontspec_define_altfont_option:nn { + \__fontspec_keys_define_code:nnn {fontspec-ltjaltfont} {#1} {#2} +} + +%% Alternate Fonts +%% Spec: AltFont = { +%% ... +%% { Range = <range>, <font features> }, +%% { Range = <range>, Font = <font name>, <font features> }, +%% { Range = <range>, Font = <font name> }, +%% ... +%% } +\tl_new:N \l__ltj_fontspec_altname_tl +\tl_new:N \l__ltj_fontspec_altrange_tl +\clist_new:N \l__ltj_fontspec_altfont_clist +\clist_new:N \l__ltj_fontspec_altfont_leftover_clist +\int_new:N \g__ltj_fontspec_altnumber_int + +\__ltj_fontspec_define_altfont_option:nn {Range} { + \tl_set:Nn \l__ltj_fontspec_altrange_tl {#1} +} +\__ltj_fontspec_define_altfont_option:nn {Font} { + \fontspec_complete_fontname:Nn \l__ltj_fontspec_altname_tl {#1} +} +\__fontspec_keys_define_code:nnn {fontspec-ltjaltfont-reparse} {AltFont} { + \clist_put_right:Nn \l__ltj_fontspec_altfont_clist { #1 } +} +\__fontspec_keys_define_code:nnn {fontspec-ltjaltfont-reparse} {YokoFeatures} { + \clist_put_right:Nn \l__ltj_fontspec_fontfeat_yoko_clist { #1 } +} +\__fontspec_keys_define_code:nnn {fontspec-ltjaltfont-reparse} {TateFeatures} { + \clist_put_right:Nn \l__ltj_fontspec_fontfeat_tate_clist { #1 } +} +\__fontspec_keys_define_code:nnn {fontspec-ltjaltfont-reparse} {TateFont} { + \tl_if_empty:nF {#1} { + \fontspec_complete_fontname:Nn \l__ltj_fontspec_fontname_tate_tl {#1} + } +} +%% +\clist_new:N \l__ltj_fontspec_fontfeat_yoko_clist +\clist_new:N \l__ltj_fontspec_fontfeat_tate_clist +\tl_new:N \l__ltj_fontspec_fontname_tate_tl + +\cs_new:Npn \__ltj_fontspec_DeclareFontFamily #1 #2 #3 { + \DeclareKanjiFamily {JY3} {#2} {#3} + \DeclareKanjiFamily {JT3} {#2} {#3} +} + +%% save and restore global variable +\tl_new:N \g__ltj_fontspec_kanji_nfss_family_tl +\tl_new:N \g__ltj_fontspec_orig_nfss_family_tl +\seq_new:N \l__ltj_fontspec_kanji_bf_series_seq +\seq_new:N \l__ltj_fontspec_orig_bf_series_seq +\clist_new:N \g__ltj_fontspec_kanji_default_fontopts_clist +\clist_new:N \g__ltj_fontspec_orig_default_fontopts_clist + +\cs_new:Nn \__ltj_set_global_variable_for_kanji: { + \tl_gset_eq:NN \g__ltj_fontspec_orig_nfss_family_tl \g__fontspec_nfss_family_tl + \tl_gset_eq:NN \g__fontspec_nfss_family_tl \g__ltj_fontspec_kanji_nfss_family_tl + \seq_set_eq:NN \l__ltj_fontspec_orig_bf_series_seq \l__fontspec_bf_series_seq + \seq_set_eq:NN \l__fontspec_bf_series_seq \l__ltj_fontspec_kanji_bf_series_seq + %\seq_gclear:N \g__fontspec_bf_series_seq + \clist_set_eq:NN \g__ltj_fontspec_orig_default_fontopts_clist \g__fontspec_default_fontopts_clist + \clist_set_eq:NN \g__fontspec_default_fontopts_clist \g__ltj_fontspec_kanji_default_fontopts_clist +} + +\cs_new:Nn \__ltj_restore_global_variable: { + \tl_gset_eq:NN \g__ltj_fontspec_kanji_nfss_family_tl \g__fontspec_nfss_family_tl + \tl_gset_eq:NN \g__fontspec_nfss_family_tl \g__ltj_fontspec_orig_nfss_family_tl + \seq_set_eq:NN \l__ltj_fontspec_kanji_bf_series_seq \l__fontspec_bf_series_seq + \seq_set_eq:NN \l__fontspec_bf_series_seq \l__ltj_fontspec_orig_bf_series_seq + \clist_set_eq:NN \g__ltj_fontspec_kanji_default_fontopts_clist \g__fontspec_default_fontopts_clist + \clist_set_eq:NN \g__fontspec_default_fontopts_clist \g__ltj_fontspec_orig_default_fontopts_clist +} + +\cs_set_eq:NN \__ltj_orig_fontspec_select_font_family:nn \__fontspec_select_font_family:nn +\cs_new_protected:Nn \__ltj_fontspec_select_font_family:nn { + \group_begin: + \__ltj_fontspec_define_option:nn {NoEmbed} {} + \__ltj_fontspec_define_option:nn {AltFont} { + \clist_put_right:Nn \l__ltj_fontspec_altfont_clist { ##1 } + } + \__ltj_fontspec_define_option:nn {CID} { + \__fontspec_update_featstr:n {cid=##1} + } + \__ltj_fontspec_define_option:nn {Kanjiskip} { + \str_if_eq:eeTF {false} { \str_lower_case:n { ##1 } }{ + \__fontspec_update_featstr:n {-ltjksp} + } { + \__fontspec_update_featstr:n {+ltjksp} + } + } + \__ltj_fontspec_define_option:nn {JFM} { + \__fontspec_update_featstr:n {jfm=##1} + } + % vary by shape + \__ltj_fontspec_define_option:nn {YokoFeatures} { + \clist_put_right:Nn \l__ltj_fontspec_fontfeat_yoko_clist { ##1 } + } + \__ltj_fontspec_define_option:nn {TateFeatures} { + \clist_put_right:Nn \l__ltj_fontspec_fontfeat_tate_clist { ##1 } + } + \__ltj_fontspec_define_option:nn {TateFont} + { + \tl_if_empty:nF {##1} { + \fontspec_complete_fontname:Nn \l__ltj_fontspec_fontname_tate_tl {##1} + } + } + \__ltj_fontspec_define_option:nn {JFM-var} { + \__fontspec_update_featstr:n {jfmvar=##1} + } + \__ltj_fontspec_define_preparse_external:nn {NoEmbed} { + \cs_set:Npn \__fontspec_fontname_wrap:n ##1 {psft:##1} + } + + %% Omit the warning message + %% "OpenType feature 'Kerning=Off' (-kern) not available ..." + \keys_define:nn {fontspec-opentype} { + Kerning/Off.code:n=\__fontspec_update_featstr:n {-kern} + } + \clist_set:Ne \g__fontspec_default_fontopts_clist { + YokoFeatures = { JFM=\ltj@stdyokojfm }, TateFeatures = { JFM=\ltj@stdtatejfm }, + Scale=\Cjascale, Kerning=Off, Script=CJK, + \g__ltj_fontspec_kanji_default_fontopts_clist + } + \prop_set_eq:NN \g__fontspec_fontopts_prop \g__ltj_fontspec_fontopts_prop + \cs_set_eq:NN \__fontspec_make_font_shapes:Nnnnn \__ltj_fontspec_make_font_shapes:Nnnnn + \cs_set_eq:NN \DeclareFontFamily \__ltj_fontspec_DeclareFontFamily + \tl_set:Nn \g_fontspec_encoding_tl {JY3} + \__ltj_orig_fontspec_select_font_family:nn{#1}{#2} + + \cs_gset:Npx \__ltj_fontspec_aftergroup { + \exp_not:N \tl_set:Nn \exp_not:N \l_fontspec_family_tl { \l_fontspec_family_tl } + } + \aftergroup \__ltj_fontspec_aftergroup + \group_end: +} + +%% declare_shape + +\cs_new:Nn \__ltj_fontspec_declare_shape_yoko:nnnn { + \__ltj_fontspec_declare_shape_aux:nnnnnn {#1} {#2} {#3} {#4} { JY3 } { \l__ltj_fontspec_fontfeat_yoko_clist } +} +\cs_new:Nn \__ltj_fontspec_declare_shape_tate:nnnn { + \__ltj_fontspec_declare_shape_aux:nnnnnn {#1} {#2} {#3} {#4} { JT3 } { \l__ltj_fontspec_fontfeat_tate_clist } +} +\cs_new:Nn \__ltj_fontspec_declare_shape:nnnn { + \__ltj_fontspec_declare_shape_yoko:nnnn {#1} {#2} {#3} {#4} + \__ltj_fontspec_declare_shape_tate:nnnn {#1} {#2} {#3} {#4} +} +\cs_generate_variant:Nn \__ltj_fontspec_declare_shape:nnnn {nnxx} +\cs_generate_variant:Nn \__ltj_fontspec_declare_shape_yoko:nnnn {nnxx} +\cs_generate_variant:Nn \__ltj_fontspec_declare_shape_tate:nnnn {nnxx} + +\cs_new:Nn \__ltj_fontspec_declare_shape_aux:nnnnnn +{ + \tl_build_begin:N \l__fontspec_nfss_tl + \tl_build_begin:N \l__fontspec_nfss_sc_tl + \tl_set_eq:NN \l__fontspec_saved_fontname_tl \l_fontspec_fontname_tl + + \tl_set:Nn \g_fontspec_encoding_tl {#5} + \tl_set:Nn \g__fontspec_nfss_enc_tl {#5} + \exp_args:Ne \clist_map_inline:nn {#4} + { \__ltj_fontspec_setup_single_size:nn {#3, #6} {##1} } + \tl_build_end:N \l__fontspec_nfss_tl + \tl_build_end:N \l__fontspec_nfss_sc_tl + + \bool_set_true:N \l__fontspec_nosc_bool + \__fontspec_declare_shapes_normal:nn {#1} {#2} + \__fontspec_declare_shape_slanted:nn {#1} {#2} +} + +\cs_new:Nn \__ltj_fontspec_setup_single_size:nn +{ + \tl_clear:N \l__fontspec_size_tl + \tl_set_eq:NN \l__fontspec_sizedfont_tl \l__fontspec_saved_fontname_tl % in case not spec'ed + + \keys_set_known:neN {fontspec-sizing} { \exp_after:wN \use:n #2 } + \l__fontspec_sizing_leftover_clist + \tl_if_empty:NT \l__fontspec_size_tl { \__fontspec_error:n {no-size-info} } + + \str_if_eq:eeTF { \g__fontspec_nfss_enc_tl } { JY3 } { + % "normal" + \__fontspec_load_fontname:Nn \l_fontspec_fontname_tl {\l__fontspec_sizedfont_tl} + } { + \tl_if_empty:NTF \l__ltj_fontspec_fontname_tate_tl + { \__fontspec_load_fontname:Nn \l_fontspec_fontname_tl {\l__fontspec_sizedfont_tl} } + { \__fontspec_load_fontname:Nn \l_fontspec_fontname_tl {\l__ltj_fontspec_fontname_tate_tl} } + } + \__fontspec_setup_nfss:Nn \l__fontspec_nfss_tl {#1} +} + +\cs_new:Nn \__ltj_fontspec_set_family:Nnn { + \__ltj_set_global_variable_for_kanji: + \cs_set_eq:NN \__fontspec_select_font_family:nn \__ltj_fontspec_select_font_family:nn + \__ltj_orig_fontspec_set_family:Nnn #1 {#2} {#3} + \cs_set_eq:NN \__fontspec_select_font_family:nn \__ltj_orig_fontspec_select_font_family:nn + \__ltj_restore_global_variable: +} +\cs_set_eq:NN \__ltj_orig_fontspec_set_family:Nnn \fontspec_set_family:Nnn +\cs_set_eq:NN \__ltj_orig_fontspec_make_font_shapes:Nnnnn \__fontspec_make_font_shapes:Nnnnn +\cs_set_eq:NN \__ltj_fontspec_orig_DeclareFontShape \DeclareFontShape + +\cs_new:Nn \__ltj_fontspec_make_font_shapes:Nnnnn { + \group_begin: + %% 基底フォント + \cs_set_eq:NN \__fontspec_font_set:Nnn \use_none:nnn + \cs_set_eq:NN \__fontspec_font_if_null:NT \use_none:nn + \cs_set_eq:NN \__fontspec_declare_shape:nnxx \__ltj_fontspec_declare_shape:nnxx + \__ltj_orig_fontspec_make_font_shapes:Nnnnn {#1} {#2} {#3} {#4} {#5} + %% + \__ltj_fontspec_make_font_shapes_alt:Nnnnnn {#1}{#2}{#3} + {#4, \l__ltj_fontspec_fontfeat_yoko_clist}{#5} {JY3 } + \__ltj_fontspec_make_font_shapes_alt:Nnnnnn {#1}{#2}{#3} + {#4, \l__ltj_fontspec_fontfeat_tate_clist}{#5} {JT3} + \group_end: + } + +%%% Altfont 内部処理部 +\cs_new:Nn \__ltj_fontspec_make_font_shapes_alt:Nnnnnn { + \group_begin: + \str_if_eq:eeTF { #6 } { JY3 } { + \cs_set_eq:NN \__fontspec_declare_shape:nnxx \__ltj_fontspec_declare_shape_yoko:nnxx + }{ + \cs_set_eq:NN \__fontspec_declare_shape:nnxx \__ltj_fontspec_declare_shape_tate:nnxx + } + \keys_set_known:nn {fontspec-ltjaltfont-reparse} { #4 } + \clist_if_empty:NF \l__ltj_fontspec_altfont_clist { + \int_gzero:N \g__ltj_fontspec_altnumber_int + \clist_map_inline:Nn \l__ltj_fontspec_altfont_clist { + \tl_clear:N \l__ltj_fontspec_altrange_tl + \tl_set:Nn \l__ltj_fontspec_altname_tl { #1 } + \tl_set:Nn \l_tmpa_tl { #1 } + + \keys_set_known:neN {fontspec-ltjaltfont} { \exp_after:wN \use:n ##1 } + \l__ltj_fontspec_altfont_leftover_clist + \keys_set_known:nn {fontspec-ltjaltfont-reparse} { \exp_after:wN \use:n ##1 } + + \tl_if_empty:NT \l__ltj_fontspec_altrange_tl { + \msg_warning:nnn {luatexja-fontspec} {altfont-ignored-by-norange} { ##1 } + } { + \bool_if:nTF { + \tl_if_eq_p:NN \l__ltj_fontspec_altname_tl \l_tmpa_tl + && + \tl_if_empty_p:N \l__ltj_fontspec_altfont_leftover_clist + } { + \msg_warning:nnn {luatexja-fontspec} {altfont-ignored-by-rangeonly} { ##1 } + } { + \__ltj_orig_fontspec_make_font_shapes:Nnnnn + { \l__ltj_fontspec_altname_tl } {#2} + {#3 _ alt \int_use:N \g__ltj_fontspec_altnumber_int } + {#4, \l__ltj_fontspec_altfont_leftover_clist } + {#5} + \DeclareAlternateKanjiFont + { #6 }{ \g__fontspec_nfss_family_tl }{#2}{#3}% + { #6 }{ \g__fontspec_nfss_family_tl }{#2} + { #3 _alt \int_use:N \g__ltj_fontspec_altnumber_int } + { \l__ltj_fontspec_altrange_tl } + \int_gincr:N \g__ltj_fontspec_altnumber_int + } + } + } + } + \group_end: +} + + +%%%%%%%% User commands +\DeclareDocumentCommand \jfontspec { O{} m O{} } { + \__ltj_fontspec_set_family:Nnn \k@family {#1,#3}{#2} + \selectfont + \ignorespaces +} + +\DeclareDocumentCommand \setmainjfont { O{} m O{} } { + \ifdefined\DeclareFontSeriesDefault + \DeclareFontSeriesDefault[mc]{bf}{\bfdefault} + \fi + \__ltj_fontspec_set_family:Nnn \mcdefault {#1,#3}{#2} + \unless\ifltj@disablejfam + \DeclareSymbolFont{mincho}{JY3}{\mcdefault}{\mddefault}{n} + \SetSymbolFont{mincho}{bold}{JY3}{\mcdefault}{\bfdefault}{n} + \fi + \normalfont +} + +\DeclareDocumentCommand \setsansjfont { O{} m O{} } { + \ifdefined\DeclareFontSeriesDefault + \DeclareFontSeriesDefault[gt]{bf}{\bfdefault} + \fi + \__ltj_fontspec_set_family:Nnn \gtdefault {#1,#3}{#2} + \unless\ifltj@disablejfam + \DeclareMathAlphabet{\mathgt}{JY3}{\gtdefault}{\mddefault}{n} + \fi + \normalfont +} + +\DeclareDocumentCommand \setmonojfont { O{} m O{} } { + \ifdefined\DeclareFontSeriesDefault + \DeclareFontSeriesDefault[jtt]{bf}{\bfdefault} + \fi + \__ltj_fontspec_set_family:Nnn \jttdefault {#1,#3}{#2} + \normalfont +} + +\DeclareDocumentCommand \newjfontfamily { m O{} m O{} } { + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_fontspec_set_family:Nnn + \newfontfamily #1 [#2,#4] {#3} + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_orig_fontspec_set_family:Nnn +} +\DeclareDocumentCommand \renewjfontfamily { m O{} m O{} } { + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_fontspec_set_family:Nnn + \renewfontfamily #1 [#2,#4] {#3} + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_orig_fontspec_set_family:Nnn +} +\DeclareDocumentCommand \setjfontfamily { m O{} m O{} } { + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_fontspec_set_family:Nnn + \setfontfamily #1 [#2,#4] {#3} + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_orig_fontspec_set_family:Nnn +} +\DeclareDocumentCommand \providejfontfamily { m O{} m O{} } { + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_fontspec_set_family:Nnn + \providefontfamily #1 [#2,#4] {#3} + \cs_set_eq:NN \fontspec_set_family:Nnn \__ltj_orig_fontspec_set_family:Nnn +} + +\DeclareDocumentCommand \newjfontface { m O{} m O{} } { + \newjfontfamily #1 [ BoldFont={},ItalicFont={},SmallCapsFont={},#2,#4 ] {#3} +} +\DeclareDocumentCommand \renewjfontface { m O{} m O{} } { + \renewjfontfamily #1 [ BoldFont={},ItalicFont={},SmallCapsFont={},#2,#4 ] {#3} +} +\DeclareDocumentCommand \setjfontface { m O{} m O{} } { + \setjfontfamily #1 [ BoldFont={},ItalicFont={},SmallCapsFont={},#2,#4 ] {#3} +} +\DeclareDocumentCommand \providejfontface { m O{} m O{} } { + \providejfontfamily #1 [ BoldFont={},ItalicFont={},SmallCapsFont={},#2,#4 ] {#3} +} + +\prop_new:N \l__ltj_fontspec_tmp_prop +\prop_new:N \g__ltj_fontspec_fontopts_prop +\DeclareDocumentCommand \defaultjfontfeatures { t+ o m } + { + \IfNoValueTF {#2} + { \__ltj_fontspec_set_default_features:nn {#1} {#3} } + { \__ltj_fontspec_set_font_default_features:nnn {#1} {#2} {#3} } + \ignorespaces + } +\cs_new:Nn \__ltj_fontspec_set_default_features:nn + { + \__ltj_set_global_variable_for_kanji: + \__fontspec_set_default_features:nn {#1} {#2} + \__ltj_restore_global_variable: + } +\cs_new:Nn \__ltj_fontspec_set_font_default_features:nnn + { + \prop_set_eq:NN \l__ltj_fontspec_tmp_prop \g__fontspec_fontopts_prop + \prop_set_eq:NN \g__fontspec_fontopts_prop \g__ltj_fontspec_fontopts_prop + \__fontspec_set_font_default_features:nnn {#1} {#2} {#3} + \prop_set_eq:NN \g__ltj_fontspec_fontopts_prop \g__fontspec_fontopts_prop + \prop_set_eq:NN \g__fontspec_fontopts_prop \l__ltj_fontspec_tmp_prop + } + +\DeclareDocumentCommand \addjfontfeatures {m} { + \__ltj_fontspec_if_fontspec_font:TF + { + \__ltj_set_global_variable_for_kanji: + \group_begin: + \tl_set_eq:NN \f@family \k@family + \cs_set_eq:NN \__fontspec_select_font_family:nn \__ltj_fontspec_select_font_family:nn + \addfontfeatures {#1} + \group_end: + \kanjifamily\g__fontspec_nfss_family_tl\selectfont + \__ltj_restore_global_variable: + }{ + \msg_warning:nn {luatexja-fontspec} {addjfontfeatures-ignored} + } + \ignorespaces +} + +\cs_set_eq:NN \addjfontfeature \addjfontfeatures + +\prg_new_conditional:Nnn \__ltj_fontspec_if_fontspec_font: {TF,T,F} +{ + \cs_if_exist:cTF {g__fontspec_fontinfo_ \k@family _prop} \prg_return_true: \prg_return_false: +} + +\endinput diff --git a/macros/luatex/generic/luatexja/src/addons/luatexja-fontspec.sty b/macros/luatex/generic/luatexja/src/addons/luatexja-fontspec.sty index 19d9952fef..abb2ca986e 100644 --- a/macros/luatex/generic/luatexja/src/addons/luatexja-fontspec.sty +++ b/macros/luatex/generic/luatexja/src/addons/luatexja-fontspec.sty @@ -3,7 +3,7 @@ % \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{luatexja-fontspec}[2020-09-14 fontspec support of LuaTeX-ja] +\ProvidesPackage{luatexja-fontspec}[2024-05-14 fontspec support of LuaTeX-ja] \RequirePackage{l3keys2e,luatexja} \ExplSyntaxOn @@ -28,7 +28,15 @@ \ProcessKeysOptions{ luatexja-fontspec } \RequirePackage{fontspec}[2019/03/15]% v2.7c -\RequirePackage{luatexja-fontspec-27c} % v2.7c +\@ifpackagelater{fontspec}{2024-05-03}{% + \@ifpackagelater{fontspec}{2024-05-10}{% + \RequirePackage{luatexja-fontspec-29e} % v2.9e + }{ + \RequirePackage{luatexja-fontspec-29c} % v2.9c + } +}{ + \RequirePackage{luatexja-fontspec-27c} % v2.7c +} \ExplSyntaxOff %%%%%%%% Now we completely ignore kanjifont definition file. diff --git a/macros/luatex/generic/luatexja/src/addons/luatexja-preset.sty b/macros/luatex/generic/luatexja/src/addons/luatexja-preset.sty index ed2a9084e6..e83a50a615 100644 --- a/macros/luatex/generic/luatexja/src/addons/luatexja-preset.sty +++ b/macros/luatex/generic/luatexja/src/addons/luatexja-preset.sty @@ -1,5 +1,5 @@ % luatexja-preset.sty -\ProvidesPackage{luatexja-preset}[2022-06-19 Japanese font presets] +\ProvidesPackage{luatexja-preset}[2024-03-30 Japanese font presets] \RequirePackage{expl3,l3keys2e} \RequirePackage{luatexja} @@ -57,7 +57,7 @@ } \seq_put_right:Nn \g__ltjpreset_presets_seq { #1 } } -\cs_generate_variant:Nn \ltjpreset_declare_preset:nn {nx} +\cs_generate_variant:Nn \ltjpreset_declare_preset:nn {ne} \cs_new:Nn \__ltjpreset_declare_bool_option:nn { \bool_new:c { g__ltjpreset_#1_bool } \bool_set_false:c { g__ltjpreset_#1_bool } @@ -100,6 +100,7 @@ mc .groups:n = { preset }, mc .value_required:n = true, mc-bx .code:n = \prop_put:Nnn \g__ltjpreset_font_prop { mc-b } {#1}, + mc-bx .groups:n = { preset }, mc-bx .value_required:n = true, gt .code:n = \prop_put:Nnn \g__ltjpreset_font_prop { gt-u } {#1} \prop_put:Nnn \g__ltjpreset_font_prop { gt-d } {#1} @@ -112,6 +113,7 @@ \prop_put:Nnn \g__ltjpreset_font_prop { gt-d } {#1}, gt .groups:n = { preset }, gt .value_required:n = true, gt-m .groups:n = { preset }, gt-m .value_required:n = true, + gt-bx .groups:n = { preset }, gt-bx .value_required:n = true, } \cs_set:Nn \ltjpreset_define_preset_prop:n { \keys_define:nn { luatexja-preset } { @@ -152,7 +154,7 @@ % 小塚 (Adobe) %% Pro -\ltjpreset_declare_preset:nx{kozuka-pro}{ +\ltjpreset_declare_preset:ne{kozuka-pro}{ mc-m = KozMinPro-Regular, mc-b = KozMinPro-Bold, gt-d = KozGoPro-Regular, gt-b = KozGoPro-Bold, gt-u = KozGoPro-Medium, gt-eb = KozGoPro-Heavy, @@ -160,7 +162,7 @@ __custom = false, __office = false, __noembed = false, } %% Pr6 -\ltjpreset_declare_preset:nx{kozuka-pr6}{ +\ltjpreset_declare_preset:ne{kozuka-pr6}{ mc-m = KozMinProVI-Regular, mc-b = KozMinProVI-Bold, gt-d = KozGoProVI-Regular, gt-b = KozGoProVI-Bold, gt-u = KozGoProVI-Medium, gt-eb = KozGoProVI-Heavy, @@ -168,7 +170,7 @@ __custom = false, __office = false, __noembed = false, } %% Pr6N -\ltjpreset_declare_preset:nx{kozuka-pr6n}{ +\ltjpreset_declare_preset:ne{kozuka-pr6n}{ mc-m = KozMinPr6N-Regular, mc-b = KozMinPr6N-Bold, gt-d = KozGoPr6N-Regular, gt-b = KozGoPr6N-Bold, gt-u = KozGoPr6N-Medium, gt-eb = KozGoPr6N-Heavy, @@ -177,14 +179,14 @@ } % ヒラギノ (OSX) -\ltjpreset_declare_preset:nx{hiragino-pro}{ +\ltjpreset_declare_preset:ne{hiragino-pro}{ mc-m = HiraMinPro-W3, mc-b = HiraMinPro-W6, gt-d = HiraKakuPro-W3, gt-b = HiraKakuPro-W6, gt-u = HiraKakuPro-W6, gt-eb = HiraKakuStd-W8, mg-m = HiraMaruPro-W4, mc-l = HiraMinPro-W2, __custom = false, __office = false, __noembed = false, } -\ltjpreset_declare_preset:nx{hiragino-pron}{ +\ltjpreset_declare_preset:ne{hiragino-pron}{ mc-m = HiraMinProN-W3, mc-b = HiraMinProN-W6, gt-d = HiraKakuProN-W3, gt-b = HiraKakuProN-W6, gt-u = HiraKakuProN-W6, gt-eb = HiraKakuStdN-W8, @@ -193,21 +195,21 @@ } % モリサワ -\ltjpreset_declare_preset:nx{bizud}{ +\ltjpreset_declare_preset:ne{bizud}{ mc = BIZ-UDMinchoM.ttc, gt-d = BIZ-UDGothicR.ttc, gt-b = BIZ-UDGothicB.ttc, gt-u = BIZ-UDGothicR.ttc, gt-eb = BIZ-UDGothicB.ttc, mg-m = BIZ-UDGothicB.ttc, __custom = false, __office = false, __noembed = false, } -\ltjpreset_declare_preset:nx{morisawa-pro}{ +\ltjpreset_declare_preset:ne{morisawa-pro}{ mc = A-OTF-RyuminPro-Light.otf, mc-b = A-OTF-FutoMinA101Pro-Bold.otf, gt-d = A-OTF-GothicBBBPro-Medium.otf , gt-b = A-OTF-FutoGoB101Pro-Bold.otf, gt-u = A-OTF-GothicBBBPro-Medium.otf , gt-eb = A-OTF-MidashiGoPro-MB31.otf, mg-m = A-OTF-Jun101Pro-Light.otf, __custom = false, __office = false, __noembed = false, } -\ltjpreset_declare_preset:nx{morisawa-pr6n}{ +\ltjpreset_declare_preset:ne{morisawa-pr6n}{ mc = A-OTF-RyuminPr6N-Light.otf, mc-b = A-OTF-FutoMinA101Pr6N-Bold.otf, gt-d = A-OTF-GothicBBBPr6N-Medium.otf , gt-b = A-OTF-FutoGoB101Pr6N-Bold.otf, gt-u = A-OTF-GothicBBBPr6N-Medium.otf , gt-eb = A-OTF-MidashiGoPr6N-MB31.otf, @@ -216,7 +218,7 @@ } % 游明朝/游ゴシック (Win8.1) -\ltjpreset_declare_preset:nx{yu-win}{ +\ltjpreset_declare_preset:ne{yu-win}{ mc-m = YuMincho-Regular, mc-b = YuMincho-Demibold, gt-d = YuGothic-Regular, gt-b = YuGothic-Bold, gt-u = YuGothic-Regular, gt-eb = YuGothic-Bold, @@ -224,7 +226,7 @@ __custom = false, __office = false, __noembed = false, } % Win10 -\ltjpreset_declare_preset:nx{yu-win10}{ +\ltjpreset_declare_preset:ne{yu-win10}{ mc-m = YuMincho-Regular, mc-b = YuMincho-Demibold, gt-d = YuGothic-Regular, gt-b = YuGothic-Bold, gt-u = YuGothic-Medium, gt-eb = YuGothic-Bold, @@ -234,7 +236,7 @@ % Yu fonts in OSX % according to http://support.apple.com/kb/HT5944 -\ltjpreset_declare_preset:nx{yu-osx}{ +\ltjpreset_declare_preset:ne{yu-osx}{ mc = YuMincho~Medium, mc-b = YuMincho~Demibold, gt-d = YuGothic~Medium, gt-u = YuGothic~Medium, gt-b = YuGothic~Bold, gt-eb = YuGothic~Bold, @@ -243,14 +245,14 @@ } % moga-mobo -\ltjpreset_declare_preset:nx{moga-mobo}{ +\ltjpreset_declare_preset:ne{moga-mobo}{ mc = Moga90Mincho, mc-b = Moga90Mincho~Bold, gt-d = Moga90Gothic, gt-b = Moga90Gothic~Bold, gt-u = Moga90Gothic, gt-eb = Moga90Gothic~Bold, mg-m = Mobo90Gothic, __custom = false, __office = false, __noembed = false, } -\ltjpreset_declare_preset:nx{moga-mobo-ex}{ +\ltjpreset_declare_preset:ne{moga-mobo-ex}{ mc = MogaEx90Mincho, mc-b = MogaEx90Mincho~Bold, gt-d = MogaEx90Gothic, gt-b = MogaEx90Gothic~Bold, gt-u = MogaEx90Gothic, gt-eb = MogaEx90Gothic~Bold, @@ -259,7 +261,7 @@ } % Ume fones -\ltjpreset_declare_preset:nx{ume}{ +\ltjpreset_declare_preset:ne{ume}{ mc = Ume~Mincho, gt-d = Ume~Gothic, gt-b = Ume~Gothic~O5, gt-u = Ume~Gothic~O5, gt-eb = Ume~Gothic~O5, @@ -268,7 +270,7 @@ } % Source Han {Serif,Sans} -\ltjpreset_declare_preset:nx{sourcehan}{ +\ltjpreset_declare_preset:ne{sourcehan}{ mc-m = Source~Han~Serif~Regular, mc-b = Source~Han~Serif~Bold, gt-d = Source~Han~Sans~Regular, @@ -279,7 +281,7 @@ mc-l = Source~Han~Serif~Light, __custom = false, __office = false, __noembed = false, } -\ltjpreset_declare_preset:nx{sourcehan-jp}{ +\ltjpreset_declare_preset:ne{sourcehan-jp}{ mc-m = Source~Han~Serif~JP~Regular, mc-b = Source~Han~Serif~JP~Bold, gt-d = Source~Han~Sans~JP~Regular, @@ -290,7 +292,7 @@ mc-l = Source~Han~Serif~JP~Light, __custom = false, __office = false, __noembed = false, } -\ltjpreset_declare_preset:nx{noto-otc}{ +\ltjpreset_declare_preset:ne{noto-otc}{ mc-m = Noto~Serif~CJK~Regular, mc-b = Noto~Serif~CJK~Bold, gt-d = Noto~Sans~CJK~Regular, @@ -301,7 +303,7 @@ mc-l = Noto~Serif~CJK~Light, __custom = false, __office = false, __noembed = false, } -\ltjpreset_declare_preset:nx{noto-otf}{ +\ltjpreset_declare_preset:ne{noto-otf}{ mc-m = Noto~Serif~CJK~JP~Regular, mc-b = Noto~Serif~CJK~JP~Bold, gt-d = Noto~Sans~CJK~JP~Regular, @@ -312,10 +314,10 @@ mc-l = Noto~Serif~CJK~JP~Light, __custom = false, __office = false, __noembed = false, } -\ltjpreset_declare_preset:nx{noto}{ +\ltjpreset_declare_preset:ne{noto}{ noto-otf, } -\ltjpreset_declare_preset:nx{noto-jp}{ +\ltjpreset_declare_preset:ne{noto-jp}{ mc-m = Noto~Serif~JP~Regular, mc-b = Noto~Serif~JP~Bold, gt-d = Noto~Sans~JP~Regular, @@ -328,7 +330,7 @@ } % HaranoAji {Mincho, Gothic} -\ltjpreset_declare_preset:nx{haranoaji}{ +\ltjpreset_declare_preset:ne{haranoaji}{ mc-m = HaranoAjiMincho-Regular.otf, mc-b = HaranoAjiMincho-Bold.otf, gt-d = HaranoAjiGothic-Regular.otf, @@ -342,30 +344,30 @@ % ipa, ipaex, ms -\ltjpreset_declare_preset:nx{ipa}{ +\ltjpreset_declare_preset:ne{ipa}{ \__ltjpreset_set_uni:nn { IPAMincho } { IPAGothic } } -\ltjpreset_declare_preset:nx{ipaex}{ +\ltjpreset_declare_preset:ne{ipaex}{ \__ltjpreset_set_uni:nn { IPAExMincho } { IPAExGothic } } -\ltjpreset_declare_preset:nx{ms}{ +\ltjpreset_declare_preset:ne{ms}{ \__ltjpreset_set_uni:nn { MS-Mincho } { MS-Gothic } } % {ipa,ipaex,ms}-dx % Office 付属フォントを利用 -\ltjpreset_declare_preset:nx{ipaex-hg}{ +\ltjpreset_declare_preset:ne{ipaex-hg}{ \__ltjpreset_set_office:nn { IPAExMincho } { IPAExGothic } } -\ltjpreset_declare_preset:nx{ipa-hg}{ +\ltjpreset_declare_preset:ne{ipa-hg}{ \__ltjpreset_set_office:nn { IPAMincho } { IPAGothic } } -\ltjpreset_declare_preset:nx{ms-hg}{ +\ltjpreset_declare_preset:ne{ms-hg}{ \__ltjpreset_set_office:nn { MS-Mincho } { MS-Gothic } } % 非埋込 -\ltjpreset_declare_preset:nx{noembed}{ +\ltjpreset_declare_preset:ne{noembed}{ \__ltjpreset_set_uni:nn { Ryumin-Light } { GothicBBB-Medium }, __custom = false, __office = false, __noembed = true, } @@ -385,12 +387,12 @@ \bool_if:NF \g__ltjpreset_custom_bool { \tl_set:Nn \l_tmpa_tl {, CJKShape=JIS2004 } \tl_if_eq:NNT \l__ltjpreset_kanji_shape_tl \l_tmpa_tl { - \tl_set:Nx \l_tmpb_tl { \prop_item:Nn \g__ltjpreset_font_prop { mc-m } } + \tl_set:Ne \l_tmpb_tl { \prop_item:Nn \g__ltjpreset_font_prop { mc-m } } \tl_if_in:NnT \l_tmpb_tl { Moga90Mincho } { \prop_clear:N \l_tmpa_prop \prop_map_inline:Nn \g__ltjpreset_font_prop { \tl_set:Nn \l_tmpb_tl { ##2 } \tl_remove_all:Nn \l_tmpb_tl {90} - \prop_put:Nnx \l_tmpa_prop { ##1 } { \tl_use:N \l_tmpb_tl } + \prop_put:Nne \l_tmpa_prop { ##1 } { \tl_use:N \l_tmpb_tl } } \prop_set_eq:NN \g__ltjpreset_font_prop \l_tmpa_prop } @@ -398,44 +400,44 @@ \prop_clear:N \l_tmpa_prop \prop_map_inline:Nn \g__ltjpreset_font_prop { \tl_set:Nn \l_tmpb_tl { ##2 } \tl_remove_all:Nn \l_tmpb_tl {90} - \prop_put:Nnx \l_tmpa_prop { ##1 } { \tl_use:N \l_tmpb_tl } + \prop_put:Nne \l_tmpa_prop { ##1 } { \tl_use:N \l_tmpb_tl } } \prop_set_eq:NN \g__ltjpreset_font_prop \l_tmpa_prop } } } %%%% リストからの展開 - \cs_set:Nx \__ltjpreset_font_mc_l: { \prop_item:Nn \g__ltjpreset_font_prop { mc-l } } - \cs_set:Nx \__ltjpreset_font_mc_m: { \prop_item:Nn \g__ltjpreset_font_prop { mc-m } } - \cs_set:Nx \__ltjpreset_font_mc_b: { \prop_item:Nn \g__ltjpreset_font_prop { mc-b } } - \cs_set:Nx \__ltjpreset_font_gt_m: { \prop_item:Nn \g__ltjpreset_font_prop { gt-d } } - \cs_set:Nx \__ltjpreset_font_gt_u: { \prop_item:Nn \g__ltjpreset_font_prop { gt-u } } - \cs_set:Nx \__ltjpreset_font_gt_b: { \prop_item:Nn \g__ltjpreset_font_prop { gt-b } } - \cs_set:Nx \__ltjpreset_font_gt_eb: { \prop_item:Nn \g__ltjpreset_font_prop { gt-eb } } - \cs_set:Nx \__ltjpreset_font_mg_m: { \prop_item:Nn \g__ltjpreset_font_prop { mg-m } } + \cs_set:Ne \__ltjpreset_font_mc_l: { \prop_item:Nn \g__ltjpreset_font_prop { mc-l } } + \cs_set:Ne \__ltjpreset_font_mc_m: { \prop_item:Nn \g__ltjpreset_font_prop { mc-m } } + \cs_set:Ne \__ltjpreset_font_mc_b: { \prop_item:Nn \g__ltjpreset_font_prop { mc-b } } + \cs_set:Ne \__ltjpreset_font_gt_m: { \prop_item:Nn \g__ltjpreset_font_prop { gt-d } } + \cs_set:Ne \__ltjpreset_font_gt_u: { \prop_item:Nn \g__ltjpreset_font_prop { gt-u } } + \cs_set:Ne \__ltjpreset_font_gt_b: { \prop_item:Nn \g__ltjpreset_font_prop { gt-b } } + \cs_set:Ne \__ltjpreset_font_gt_eb: { \prop_item:Nn \g__ltjpreset_font_prop { gt-eb } } + \cs_set:Ne \__ltjpreset_font_mg_m: { \prop_item:Nn \g__ltjpreset_font_prop { mg-m } } %% HG 系フォント + JIS2004/90JIS のときはフォント名を置換 \bool_if:nT { !\g__ltjpreset_custom_bool && \g__ltjpreset_office_bool } { \tl_set:Nn \l_tmpa_tl {, CJKShape=JIS2004 } \tl_if_eq:NNT \l__ltjpreset_kanji_shape_tl \l_tmpa_tl { - \cs_set:Nx \__ltjpreset_font_mc_b: { hgrme04.ttc } - \cs_set:Nx \__ltjpreset_font_gt_b: { hgrge04.ttc } - \cs_set:Nx \__ltjpreset_font_gt_eb: { hgrsgu04.ttc } - \cs_set:Nx \__ltjpreset_font_mg_m: { hgrsmp04.ttf } + \cs_set:Ne \__ltjpreset_font_mc_b: { hgrme04.ttc } + \cs_set:Ne \__ltjpreset_font_gt_b: { hgrge04.ttc } + \cs_set:Ne \__ltjpreset_font_gt_eb: { hgrsgu04.ttc } + \cs_set:Ne \__ltjpreset_font_mg_m: { hgrsmp04.ttf } \cs_set_eq:NN \__ltjpreset_font_gt_m: \__ltjpreset_font_gt_u: % HG ゴシックM のときはそうはいかないので 1 ウェイト時のゴシック体を使う } \tl_set:Nn \l_tmpa_tl {, CJKShape=JIS1990 } \tl_if_eq:NNT \l__ltjpreset_kanji_shape_tl \l_tmpa_tl { - \cs_set:Nx \__ltjpreset_font_mc_b: { hgrme.ttc } - \cs_set:Nx \__ltjpreset_font_gt_b: { hgrge.ttc } - \cs_set:Nx \__ltjpreset_font_gt_eb: { hgrsgu.ttc } - \cs_set:Nx \__ltjpreset_font_mg_m: { hgrsmp.ttf } + \cs_set:Ne \__ltjpreset_font_mc_b: { hgrme.ttc } + \cs_set:Ne \__ltjpreset_font_gt_b: { hgrge.ttc } + \cs_set:Ne \__ltjpreset_font_gt_eb: { hgrsgu.ttc } + \cs_set:Ne \__ltjpreset_font_mg_m: { hgrsmp.ttf } } } % mc/l - \tl_set:Nx \l_tmpa_tl { \__ltjpreset_font_mc_l: } + \tl_set:Ne \l_tmpa_tl { \__ltjpreset_font_mc_l: } \tl_if_empty:NT \l_tmpa_tl {\tl_set:Nn \l_tmpa_tl {~}} - \cs_set:Nx \__ltjpreset_font_mc_l: { + \cs_set:Ne \__ltjpreset_font_mc_l: { \tl_if_blank:nTF \l_tmpa_tl { \__ltjpreset_font_mc_m: } {\tl_use:N \l_tmpa_tl } } %% bold オプションの処理 @@ -479,7 +481,7 @@ \__ltjpreset_wrap_fontname:e { \cs:w __ltjpreset_font_#1_#2: \cs_end: } \font \g__ltjpreset_font_test: = \l__ltjpreset_font_name:\relax \ifx \g__ltjpreset_font_test: \nullfont - \msg_warning:nnxxxx { luatexja-preset }{ no-font } + \msg_warning:nneeee { luatexja-preset }{ no-font } { \cs:w __ltjpreset_font_#1_#2: \cs_end: }{ #1/#2 } { \cs:w __ltjpreset_font_#3_#4: \cs_end: }{ #3/#4 } \cs_gset_eq:cc { __ltjpreset_font_#1_#2: } { __ltjpreset_font_#3_#4: } @@ -520,7 +522,7 @@ } \fp_compare:nNnF \Cjascale = 1 - { \msg_warning:nnx { luatexja-preset }{ scale }{ \Cjascale } } + { \msg_warning:nne { luatexja-preset }{ scale }{ \Cjascale } } % {1: encoding}{2: family}{3: series}{4: shape}{5: fontname}{6: feature}{7: scale} \cs_new:Nn \__ltjpreset_declare_font_shape:nnnnnnn { @@ -589,7 +591,7 @@ } \tl_set:Nn \l_tmpa_tl {, CJKShape=JIS2004 } \tl_if_eq:NNT \l__ltjpreset_kanji_shape_tl \l_tmpa_tl { - \tl_set:Nx \l__ltjpreset_kanji_shape_tl { ;+jp04 } + \tl_set:Ne \l__ltjpreset_kanji_shape_tl { ;+jp04 } } \__ltjpreset_define_family:nnn {mc} {m} {\__ltjpreset_font_mc_m:} \__ltjpreset_define_family:nnn {mc} {bx} {\__ltjpreset_font_mc_b:} @@ -610,7 +612,7 @@ } { \RequirePackage{luatexja-fontspec} % scale - \msg_warning:nnx { luatexja-preset }{ scale }{ \Cjascale } + \msg_warning:nne { luatexja-preset }{ scale }{ \Cjascale } \tl_new:N \l__ltjpreset_add_features_tl \bool_if:NT \g__ltjpreset_expert_bool { @@ -621,7 +623,7 @@ \addjfontfeature{ Kerning=Off } % 実際の fontspec の呼びだし \cs_new:Nn \__ltjpreset_do_fontset: { \group_begin: - \tl_gset:Nx \l__ltjpreset_add_features_tl { + \tl_gset:Ne \l__ltjpreset_add_features_tl { \tl_use:N \l__ltjpreset_kanji_shape_tl, YokoFeatures = { JFM = \tl_use:N \__ltjpreset_use_jfm_yoko_tl }, TateFeatures = { JFM = \tl_use:N \__ltjpreset_use_jfm_tate_tl }, diff --git a/macros/luatex/generic/luatexja/src/lltjext.sty b/macros/luatex/generic/luatexja/src/lltjext.sty index a83c9305c9..69e709f02e 100644 --- a/macros/luatex/generic/luatexja/src/lltjext.sty +++ b/macros/luatex/generic/luatexja/src/lltjext.sty @@ -3,7 +3,7 @@ % \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{lltjext}[2022-08-24 v1.2k-ltj-14 Macros for vertical writing] +\ProvidesPackage{lltjext}[2024-05-16 v1.2k-ltj-15 Macros for vertical writing] \RequirePackage{luatexja} \newcount\ltj@ext@dir \let\ltj@lltjext@orig@tabular=\tabular @@ -541,17 +541,11 @@ \else \let\box@dir\utod \fi \fi -\ifltj@ltfilehook@avail % LaTeX2e >= 2020-10-01 \@defaultunitsset\@picht{#3}\unitlength \@defaultunitsset\@picwd{#2}\unitlength \setbox\@picbox\hbox to\@picwd\bgroup\box@dir \@defaultunitsset\@tempdimc{#4}\unitlength\hskip-\@tempdimc \@defaultunitsset\@tempdimc{#5}\unitlength\lower\@tempdimc\hbox\bgroup -\else % <= 2020-02-02 - \@picwd=#2\unitlength \@picht=#3\unitlength - \setbox\@picbox\hbox to\@picwd\bgroup\box@dir - \hskip-#4\unitlength\lower#5\unitlength\hbox\bgroup -\fi \ltj@@pic@reset@blshift \ignorespaces} \def\endpicture{% diff --git a/macros/luatex/generic/luatexja/src/ltj-base.lua b/macros/luatex/generic/luatexja/src/ltj-base.lua index 2af3908554..e112dfa374 100644 --- a/macros/luatex/generic/luatexja/src/ltj-base.lua +++ b/macros/luatex/generic/luatexja/src/ltj-base.lua @@ -398,6 +398,19 @@ function ltjb.add_to_callback(name,fun,description,priority) return end +--- fix \e@alloc@luafunction@count (gh:5) +do + local t = lua.get_functions_table() + local m = 0 + local n = tex.getcount('e@alloc@luafunction@count') + for i = 1,math.max(n, #t)+100 do-- I think 100 is sufficient + if t[i] then m = i end + end + if m>n then + tex.setcount('global', 'e@alloc@luafunction@count', m) + end +end + -------------------- mock of debug logger if not ltjb.out_debug then local function no_op() end diff --git a/macros/luatex/generic/luatexja/src/ltj-latex.sty b/macros/luatex/generic/luatexja/src/ltj-latex.sty index 7e091d161d..9f6e4d0a36 100644 --- a/macros/luatex/generic/luatexja/src/ltj-latex.sty +++ b/macros/luatex/generic/luatexja/src/ltj-latex.sty @@ -12,45 +12,14 @@ \def\luatexjalatexLoaded{\endinput} \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{ltj-latex}[2022-10-15 LaTeX support of LuaTeX-ja] +\ProvidesPackage{ltj-latex}[2024-05-16 LaTeX support of LuaTeX-ja] \endlinechar=13 %%% LaTeX version detection -\newif\ifltj@ltfilehook@avail -\@ifl@t@r\fmtversion{2020-10-01}{% - \@ifl@t@r\fmtversion{2020-10-02}% - {\ltj@ltfilehook@availtrue} - {% - \ifnum\patch@level<0\relax \ifnum\patch@level<-6 \ltj@ltfilehook@availtrue\fi - \else\ltj@ltfilehook@availtrue\fi - }% -}{} -\@ifl@t@r\fmtversion{2021-05-01}{\count@=1 }{\count@=0 } -\ifnum \count@<1 -%%%% \shipout - \newluafunction\ltj@@lua@shipout@inner - \directlua{ - local t = lua.get_functions_table() - local getbox, setbox = tex.getbox, tex.setbox - local shipout_lthook = luatexja.direction.shipout_lthook - t[\the\ltj@@lua@shipout@inner]=function () - local a = shipout_lthook(getbox(\the\ltj@afbox)) - if a then setbox(\the\ltj@afbox, a) end - end - } - \protected\luadef\ltj@@lua@shipout\ltj@@lua@shipout@inner - \def\ltj@shipout@{\ltj@@lua@shipout\primitive\shipout\box\ltj@afbox}% - \protected\def\ltj@shipout{\ltj@afterbox\ltj@shipout@} - \ifprimitive\shipout\let\shipout\ltj@shipout\fi - \ifcsname tex_shipout:D\endcsname - \expandafter\let\csname tex_shipout:D\endcsname\ltj@shipout - \fi -\else - \directlua{% - luatexbase.add_to_callback('pre_shipout_filter',luatexja.direction.shipout_lthook, 'ltj.direction', 1) - } -\fi +\directlua{% + luatexbase.add_to_callback('pre_shipout_filter',luatexja.direction.shipout_lthook, 'ltj.direction', 1) +} %%% patch for LaTeX \usepackage{lltjfont} @@ -59,36 +28,30 @@ \RequirePackage{lltjp-atbegshi} %%% patching commands -\ifltj@ltfilehook@avail - %% \ltj@ExecuteBeforePackage <package><code> and \ltj@ExecuteAfterPackage <package><code> - %% no-starred version: do nothing if the <package> is loaded - %% starred version: do <code> right away if the <package> is loaded - \def\ltj@ExecuteAfterPackage{\@ifstar\@@ltj@ExecuteAfterPackage@star\@@ltj@ExecuteAfterPackage} - \def\ltj@ExecuteBeforePackage{\@ifstar\@@ltj@ExecuteBeforePackage@star\@@ltj@ExecuteBeforePackage} - \@ifl@t@r\fmtversion{2021-11-15}{% 2021-11-15 - \def\@@ltj@ExecuteAfterPackage@star#1{\AddToHook{package/#1/after}} - \def\@@ltj@ExecuteBeforePackage@star#1{\AddToHook{package/#1/before}} - \long\def\@@ltj@ExecuteAfterPackage#1#2{% - \@ifpackageloaded{#1}{}{\AddToHook{package/#1/after}{#2}}% - } - \long\def\@@ltj@ExecuteBeforePackage#1#2{% - \@ifpackageloaded{#1}{}{\AddToHook{package/#1/before}{#2}}% - } - }{ - \def\@@ltj@ExecuteAfterPackage#1{\AddToHook{package/after/#1}} - \def\@@ltj@ExecuteBeforePackage#1{\AddToHook{package/before/#1}} - \long\def\@@ltj@ExecuteAfterPackage@star#1#2{% - \@ifpackageloaded{#1}{#2}{\@@ltj@ExecuteAfterPackage{#1}{#2}}% - } - \long\def\@@ltj@ExecuteBeforePackage@star#1#2{% - \@ifpackageloaded{#1}{#2}{\@@ltj@ExecuteBeforePackage{#1}{#2}}% - } +%% \ltj@ExecuteBeforePackage <package><code> and \ltj@ExecuteAfterPackage <package><code> +%% no-starred version: do nothing if the <package> is loaded +%% starred version: do <code> right away if the <package> is loaded +\def\ltj@ExecuteAfterPackage{\@ifstar\@@ltj@ExecuteAfterPackage@star\@@ltj@ExecuteAfterPackage} +\def\ltj@ExecuteBeforePackage{\@ifstar\@@ltj@ExecuteBeforePackage@star\@@ltj@ExecuteBeforePackage} +\@ifl@t@r\fmtversion{2021-11-15}{% 2021-11-15 + \def\@@ltj@ExecuteAfterPackage@star#1{\AddToHook{package/#1/after}} + \def\@@ltj@ExecuteBeforePackage@star#1{\AddToHook{package/#1/before}} + \long\def\@@ltj@ExecuteAfterPackage#1#2{% + \@ifpackageloaded{#1}{}{\AddToHook{package/#1/after}{#2}}% } -\else - \RequirePackage{filehook} - \let\ltj@ExecuteAfterPackage=\AtEndOfPackageFile - \let\ltj@ExecuteBeforePackage=\AtBeginOfPackageFile -\fi + \long\def\@@ltj@ExecuteBeforePackage#1#2{% + \@ifpackageloaded{#1}{}{\AddToHook{package/#1/before}{#2}}% + } +}{ + \def\@@ltj@ExecuteAfterPackage#1{\AddToHook{package/after/#1}} + \def\@@ltj@ExecuteBeforePackage#1{\AddToHook{package/before/#1}} + \long\def\@@ltj@ExecuteAfterPackage@star#1#2{% + \@ifpackageloaded{#1}{#2}{\@@ltj@ExecuteAfterPackage{#1}{#2}}% + } + \long\def\@@ltj@ExecuteBeforePackage@star#1#2{% + \@ifpackageloaded{#1}{#2}{\@@ltj@ExecuteBeforePackage{#1}{#2}}% + } +} \def\ltj@pkgpatch@im#1{\@ifnextchar[{\ltj@pkgpatch@im@{#1}}{\ltj@pkgpatch@im@{#1}[lltjp-#1]}}%] \def\ltj@pkgpatch@im@#1[#2]{\ltj@ExecuteAfterPackage*{#1}{\ltj@pkgpatch@im@@{#2}}} \def\ltj@pkgpatch@im@@#1{% @@ -101,11 +64,7 @@ } \def\ltj@pkgpatch#1{\@ifnextchar[{\ltj@pkgpatch@{#1}}{\ltj@pkgpatch@{#1}[lltjp-#1]}}%] -\ifltj@ltfilehook@avail - \def\ltj@pkgpatch@@{\AddToHook{begindocument/before}[luatexja.autopatch]} -\else - \def\ltj@pkgpatch@@{\gpreto\@begindocumenthook} -\fi +\def\ltj@pkgpatch@@{\AddToHook{begindocument/before}[luatexja.autopatch]} \def\ltj@pkgpatch@#1[#2]{% \ltj@pkgpatch@@{% \@ifpackageloaded{#1}{\@ifpackageloaded{#2}{}{\RequirePackage{#2}}}{}% @@ -121,18 +80,12 @@ \ltj@pkgpatch{tascmac} \ltj@pkgpatch{ascmac}[lltjp-tascmac] \ltj@pkgpatch@im{stfloats} -\ifltj@ltfilehook@avail\else - \ltj@pkgpatch{preview} %% at \begin{document} - % (preview package has delayed option) -\fi \ltj@pkgpatch{array} %% at \begin{document} \ltj@pkgpatch{collcell} %% at \begin{document} \ltj@pkgpatch@im{unicode-math} \ltj@pkgpatch@im{siunitx} \ltj@pkgpatch@im{microtype} -\ifltj@ltfilehook@avail\else\ltj@pkgpatch@im{everyshi}\fi - \RequirePackage{lltjp-geometry} \ltj@ExecuteBeforePackage{breqn}{% diff --git a/macros/luatex/generic/luatexja/src/ltj-pretreat.lua b/macros/luatex/generic/luatexja/src/ltj-pretreat.lua index 43ecac806c..8f5632be4e 100644 --- a/macros/luatex/generic/luatexja/src/ltj-pretreat.lua +++ b/macros/luatex/generic/luatexja/src/ltj-pretreat.lua @@ -156,16 +156,17 @@ function set_box_stack_level(head, mode) if ltjs.list_dir == dir_tate then for p in traverse_glyph(to_direct(head)) do if getlang(p)==lang_ja and has_attr(p, attr_icflag, 0) then - local pf = ltjf_replace_altfont(attr_curtfnt, getchar(p), p) + local pc = ltjs_orig_char_table[p] or getchar(p) + local pf = ltjf_replace_altfont(attr_curtfnt, pc, p) if ltjf_font_metric_table[pf].vert_activated then - local pc = ltjf_font_metric_table[pf].vform[pc]; if pc then setchar(p, pc) end + pc = ltjf_font_metric_table[pf].vform[pc]; if pc then setchar(p, pc) end end end end else for p in traverse_glyph(to_direct(head)) do if getlang(p)==lang_ja and has_attr(p, attr_icflag, 0) then - ltjf_replace_altfont(attr_curjfnt, getchar(p), p) + ltjf_replace_altfont(attr_curjfnt, ltjs_orig_char_table[p] or getchar(p), p) end end end diff --git a/macros/luatex/generic/luatexja/src/ltj-rmlgbm.lua b/macros/luatex/generic/luatexja/src/ltj-rmlgbm.lua index 88352dd5b2..2b65eb5e5c 100644 --- a/macros/luatex/generic/luatexja/src/ltj-rmlgbm.lua +++ b/macros/luatex/generic/luatexja/src/ltj-rmlgbm.lua @@ -15,7 +15,7 @@ do end local cidfont_data = {} local cache_chars = {} -local cache_ver = 13 +local cache_ver = 14 local identifiers = fonts.hashes.identifiers local cid_reg, cid_order, cid_supp, cid_name @@ -147,7 +147,7 @@ do descender = 655360*0.12, }, embedding = "no", cache = "yes", factor = 0, hfactor = 0, vfactor = 0, - tounicode = 1, + tounicode = 1, filename="", properties = { language = "dflt", script = "dflt" }, } cidfont_data[cid_name] = k diff --git a/macros/luatex/generic/luatexja/src/luatexja.sty b/macros/luatex/generic/luatexja/src/luatexja.sty index 164c02d8d3..f9ae793bb4 100644 --- a/macros/luatex/generic/luatexja/src/luatexja.sty +++ b/macros/luatex/generic/luatexja/src/luatexja.sty @@ -27,7 +27,7 @@ \newif\ifltj@disablejfam %%%% VERSION -\def\LuaTeXjaversion{20240219.0} +\def\LuaTeXjaversion{20240714.0} %% Check if LaTeX is used. \begingroup\expandafter\expandafter\expandafter\endgroup diff --git a/macros/luatex/generic/luatexja/src/patches/lltjdefs.sty b/macros/luatex/generic/luatexja/src/patches/lltjdefs.sty index bb63ac6877..00c858e349 100644 --- a/macros/luatex/generic/luatexja/src/patches/lltjdefs.sty +++ b/macros/luatex/generic/luatexja/src/patches/lltjdefs.sty @@ -3,7 +3,7 @@ % \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{lltjdefs}[2022-01-23 Default font settings of LuaTeX-ja] +\ProvidesPackage{lltjdefs}[2024-05-16 Default font settings of LuaTeX-ja] \ifdefined\ltj@stdmcfont\else\def\ltj@stdmcfont{file:HaranoAjiMincho-Regular.otf}\fi \ifdefined\ltj@stdgtfont\else\def\ltj@stdgtfont{file:HaranoAjiGothic-Medium.otf}\fi @@ -18,13 +18,8 @@ \DeclareKanjiEncodingDefaults{}{} \DeclareErrorKanjiFont{JY3}{mc}{m}{n}{10} \kanjifamily{mc} -\ifnum\ltj@@latex@plv<1500 % <=2020-10-01 - \kanjiseries{m} - \kanjishape{n} -\else % >=2021-06-01 - \def\k@series{m} - \def\k@shape{n} -\fi +\def\k@series{m} +\def\k@shape{n} \fontsize{10}{10} \DeclareYokoKanjiEncoding{JY3}{}{} \DeclareKanjiSubstitution{JY3}{mc}{m}{n} @@ -37,12 +32,7 @@ \newcommand\kanjiencodingdefault{JY3} \newcommand\kanjifamilydefault{\mcdefault} \newcommand\kanjiseriesdefault{\mddefault} -\ifnum 0\ifltj@ltfilehook@avail1\fi\ifdefined\@rmfamilyhook1\fi>0 - %% LaTeX 2020-02-02 - \newcommand\kanjishapedefault{\shapedefault} -\else%% LaTeX 2019-10-01 - \newcommand\kanjishapedefault{\updefault} -\fi +\newcommand\kanjishapedefault{\shapedefault} \DeclareKanjiFamily{JY3}{mc}{} \DeclareFontShape{JY3}{mc}{m}{n}{<-> s*[\ifdefined\Cjascale\Cjascale\else 0.962216\fi] @@ -90,57 +80,36 @@ \DeclareMathAlphabet{\mathgt}{JY3}{gt}{m}{n} \fi -\ifnum 0\ifltj@ltfilehook@avail1\fi\ifdefined\@rmfamilyhook1\fi>0 -%%%% LaTeX >= 2020-02-02 \edef\bfseries@mc{\bfdefault} \edef\bfseries@gt{\bfdefault} \def\bfseries@jtt{\bfseries@mc} \edef\mdseries@mc{\mddefault} \edef\mdseries@gt{\mddefault} \def\mdseries@jtt{\mdseries@mc} -\fi \newif\if@ltj@match@family \@ltj@match@familyfalse \def\verbatim@font{\normalfont\ttfamily\kanjifamily\jttdefault\selectfont} -\def\@ltj@hook@family#1#2{% #1: csname #2: contents - \ifltj@ltfilehook@avail % LaTeX 2020-10-01 - \AddToHook{#1}{#2}% - \else\ifcsname @#1hook\endcsname % LaTeX 2020-02-02 - \csappto{@#1hook}{#2}% - \else % LaTeX 2019-10-01 - \ifcsname #1 \endcsname - \expandafter\patchcmd\csname #1 \endcsname{\selectfont}{#2\selectfont}{}{}% - \else - \PackageWarningNoLine{luatexja}{% - Patching to \expandafter\string\csname #1\endcsname\space failed% - }% - \fi - \fi\fi -} -\@ltj@hook@family{rmfamily}{% +\AddToHook{rmfamily}{% \if@ltj@match@family \prepare@family@series@update@kanji{mc}\mcdefault \fi } -\@ltj@hook@family{sffamily}{% +\AddToHook{sffamily}{% \if@ltj@match@family \prepare@family@series@update@kanji{gt}\gtdefault \fi } -\@ltj@hook@family{ttfamily}{% +\AddToHook{ttfamily}{% \if@ltj@match@family \prepare@family@series@update@kanji{jtt}\jttdefault \fi } -\let\@ltj@hook@family\@undefined -\ifltj@ltfilehook@avail % 2020-10-01 - \expandafter\def\expandafter\kanjiseriesdefault - \expandafter{\kanjiseriesdefault\@empty} - \let\kanjiseriesdefault@kernel\kanjiseriesdefault -\fi +\expandafter\def\expandafter\kanjiseriesdefault + \expandafter{\kanjiseriesdefault\@empty} +\let\kanjiseriesdefault@kernel\kanjiseriesdefault %%% \eminnershape \expandafter\patchcmd\csname em \endcsname{\itshape}{\gtfamily\itshape}{}{} diff --git a/macros/luatex/generic/luatexja/src/patches/lltjfont.sty b/macros/luatex/generic/luatexja/src/patches/lltjfont.sty index 2efc9435ab..52ac44d5cc 100644 --- a/macros/luatex/generic/luatexja/src/patches/lltjfont.sty +++ b/macros/luatex/generic/luatexja/src/patches/lltjfont.sty @@ -3,31 +3,10 @@ % \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{lltjfont}[2023-04-13 Patch to NFSS2 for LuaTeX-ja] +\ProvidesPackage{lltjfont}[2023-05-16 Patch to NFSS2 for LuaTeX-ja] %%%%%%%% LaTeX2e version detection -\newcount\ltj@@latex@plv \ltj@@latex@plv=-1 -\ifltj@ltfilehook@avail -\ExplSyntaxOn - \cs_if_exist:NTF \__shipout_execute_main_cont:Nnnn - {\ltj@@latex@plv=1500}% 2021-06-01 - {\ifnum\patch@level>2\relax \ltj@@latex@plv=1300\else \ltj@@latex@plv=1000\fi}% 2020-10-01 -\ExplSyntaxOff -\else\ifdefined\@rmfamilyhook % 2020-02-02 - \ifx\@forced@seriestrue\@undefined % 2020-02-02 pl0--2 - \@latex@error - {Please update LaTeX2e!^^J\space\space - At least LaTeX2e 2020-02-02 patch level 3 is required}% - {LaTeX2e 2020-02-02 patch level 2 (and 4) has a bug.} - \else - \ltj@@latex@plv=300 - \unless\ifx\series@maybe@drop@one@m@x\@undefined % pl5 + develop - \ltj@@latex@plv=501 - \else\unless\ifx\series@maybe@drop@one@m\@undefined % patch level 5 - \ltj@@latex@plv=500 - \fi\fi - \fi -\fi\fi +\newcount\ltj@@latex@plv \ltj@@latex@plv=1500 %% patching \DeclareTextComposite \def\ltj@chardef@text@cmd#1{% @@ -400,59 +379,7 @@ \directlua{luatexja.jfont.pickup_alt_font_a('\f@size')}% }% \fi} -\ifnum\ltj@@latex@plv<1500 % <=2020-10-01 -\protected\def\ltj@selectfont@patch{% - \ltj@@start@time@measure{selectfont}% - \let\tmp@error@fontshape\error@fontshape - \let\error@fontshape\error@kfontshape - \ltj@@is@kyenc{\k@encoding}\ifin@% - \let\cy@encoding\k@encoding - \ensure@KanjiEncodingPair{t}% - \edef\ct@encoding{\csname t@enc@\k@encoding\endcsname}% - \else - \ltj@@is@ktenc{\k@encoding}\ifin@% - \let\ct@encoding\k@encoding - \ensure@KanjiEncodingPair{y}% - \edef\cy@encoding{\csname y@enc@\k@encoding\endcsname}% - \else - \@latex@error{KANJI Encoding scheme `\k@encoding' unknown}\@eha - \fi - \fi - \global\let\ltj@afont@name=\font@name - \ltj@selectfont@tate\ltj@selectfont@yoko -% - \edef\tmp@item{{\k@encoding}}\expandafter\def\expandafter\k@encoding\tmp@item - \kenc@update - \global\let\font@name=\ltj@afont@name - \let\error@fontshape\tmp@error@fontshape - \if@knjcmd \@knjcmdfalse - \expandafter\ifx - \csname rel@\k@encoding/\k@family/\k@series/\k@shape\endcsname\relax - \expandafter\ifx - \csname rel@\k@encoding/\k@family/\k@series/all\endcsname\relax - \else - \csname rel@\k@encoding/\k@family/\k@series/all\endcsname\selectfont - % 警告: 再び \selectfont を呼んでいる.無限ループの可能性あり - \fi - \else - \csname rel@\k@encoding/\k@family/\k@series/\k@shape\endcsname\selectfont - % 警告: 再び \selectfont を呼んでいる.無限ループの可能性あり - \fi - \fi - \global\let\font@name=\ltj@afont@name - \ltj@@stop@time@measure{selectfont}% -} -\RequirePackage{everysel} -\let\ltj@@EverySelectfont@Init=\@EverySelectfont@Init -\expandafter\expandafter\expandafter\let -\expandafter\expandafter\csname ltj@@orig@selectfont\endcsname\csname selectfont\space\endcsname -\@EverySelectfont@Init% for LaTeX2e <=2020-10-01 -\def\@EverySelectfont@Init{% - \expandafter\let\csname selectfont\space \endcsname \ltj@@orig@selectfont - \ltj@@EverySelectfont@Init -} -\EverySelectfont{\ltj@selectfont@patch} -\else % LaTeX2e >=2021-06-01 + \AddToHook{selectfont}[luatexja]{% \ltj@@start@time@measure{selectfont}% \ifx\delayed@k@adjustment\@empty @@ -514,7 +441,6 @@ \global\let\font@name=\ltj@afont@name \ltj@@stop@time@measure{selectfont}% } -\fi \bgroup \def\ltj@@dir@patch#1#2#3{% @@ -721,8 +647,6 @@ } %%%%%% -\ifnum\ltj@@latex@plv>0 -%%%% LaTeX >= 2020-02-02 \newif\if@shape@roman@kanji \def\merge@kanji@series#1{% @@ -740,76 +664,11 @@ \@nil } -\ifnum\ltj@@latex@plv>500 % !!! pl5 + develop \def\set@target@series@kanji#1{% \edef\k@series{#1}% \series@maybe@drop@one@m\k@series\k@series } -\else\ifnum\ltj@@latex@plv>300 % !!! pl5 - \def\set@target@series@kanji#1{% - \edef\k@series{#1}% - \expandafter\series@maybe@drop@one@m\expandafter{\k@series}\k@series - } -\else % !!! pl 3, 4 - \def\set@target@series@kanji#1{% - \edef\k@series{#1}% - \edef\k@series{\expandafter\series@drop@one@m\k@series mm\series@drop@one@m}% - } -\fi\fi -\ifnum\ltj@@latex@plv<1500% <=2020-10-01 -\def\merge@kanji@series@#1#2#3\@nil{% - \def\reserved@a{#3}% - \ifx\reserved@a\@empty - \set@target@series@kanji{#2}% - \else - \begingroup\let\f@encoding\k@encoding\let\f@family\k@family - \maybe@load@fontshape\endgroup - \edef\reserved@a{\k@encoding /\k@family /#1/\k@shape}% - \ifcsname \reserved@a \endcsname - \set@target@series@kanji{#1}% - \else - \ifcsname \k@encoding /\k@family /#2/\k@shape \endcsname - \set@target@series@kanji{#2}% - {\let\curr@fontshape\curr@kfontshape\@font@shape@subst@warning}% - \else - \set@target@series@kanji{#3}% - {\let\curr@fontshape\curr@kfontshape\@font@shape@subst@warning}% - \fi - \fi - \fi -} -\def\merge@kanji@shape@#1#2#3\@nil{% - \def\reserved@a{#3}% - \ifx\reserved@a\@empty - \if@shape@roman@kanji - \set@safe@kanji@shape{#2}{}% - \else - \edef\k@shape{#2}% - \fi - \else - \begingroup\let\f@encoding\k@encoding\let\f@family\k@family - \maybe@load@fontshape\endgroup - \edef\reserved@a{\k@encoding /\k@family /\k@series/#1}% - \ifcsname \reserved@a\endcsname - \edef\k@shape{#1}% - \else - \ifcsname \k@encoding /\k@family /\k@series/#2\endcsname - \edef\k@shape{#2}% - {\let\curr@fontshape\curr@kfontshape\@font@shape@subst@warning}% - \else - \if@shape@roman@kanji - \set@safe@kanji@shape{#3}% - {{\let\curr@fontshape\curr@kfontshape\@font@shape@subst@warning}}% - \else - \edef\k@shape{#3}% - {\let\curr@fontshape\curr@kfontshape\@font@shape@subst@warning}% - \fi - \fi - \fi - \fi -} -\else % >=2021-06-01 \def\merge@kanji@series@#1#2#3\@nil{% \def\reserved@a{#3}% \ifx\reserved@a\@empty @@ -892,20 +751,8 @@ \fi } \let\delayed@merge@kanji@shape\merge@kanji@shape@without@substitution -\fi \newif\if@forced@series@kanji -\ifnum\ltj@@latex@plv=300 % 2020-02-02 pl3, 4 - \DeclareRobustCommand\romanseries[1]{\merge@font@series{#1}} - \DeclareRobustCommand\kanjiseries[1]{\merge@kanji@series{#1}} - \DeclareRobustCommand\romanseriesforce[1]{\edef\f@series{#1}} - \DeclareRobustCommand\kanjiseriesforce[1]{\edef\k@series{#1}} -\else\ifnum\ltj@@latex@plv<1500% >=2020-02-02 pl5 and <=2020-10-01 - \DeclareRobustCommand\romanseries[1]{\@forced@seriesfalse\merge@font@series{#1}} - \DeclareRobustCommand\kanjiseries[1]{\@forced@series@kanjifalse\merge@kanji@series{#1}} - \DeclareRobustCommand\romanseriesforce[1]{\@forced@seriestrue\edef\f@series{#1}} - \DeclareRobustCommand\kanjiseriesforce[1]{\@forced@series@kanjitrue\edef\k@series{#1}} -\else% >=2021-06-01 \DeclareRobustCommand\romanseries[1]{\@forced@seriesfalse \expandafter\def\expandafter\delayed@f@adjustment\expandafter {\delayed@f@adjustment\delayed@merge@font@series{#1}}} @@ -919,22 +766,9 @@ \expandafter\def\expandafter\delayed@k@adjustment\expandafter {\delayed@k@adjustment\edef\k@series{#1}}} \let\delayed@k@adjustment\@empty -\fi\fi \DeclareRobustCommand\fontseries[1]{\kanjiseries{#1}\romanseries{#1}}% \DeclareRobustCommand\fontseriesforce[1]{\kanjiseriesforce{#1}\romanseriesforce{#1}}% -\ifnum\ltj@@latex@plv<1500% <=2020-10-01 - \DeclareRobustCommand\romanshape[1]{\merge@font@shape{#1}} - \DeclareRobustCommand\kanjishape[1]{\merge@kanji@shape{#1}} - \DeclareRobustCommand\fontshape[1]{% - \@shape@roman@kanjitrue - \merge@font@shape{#1}\merge@kanji@shape{#1}% - \@shape@roman@kanjifalse - } - \DeclareRobustCommand\romanshapeforce[1]{\edef\f@shape{#1}} - \DeclareRobustCommand\kanjishapeforce[1]{\edef\k@shape{#1}} - \DeclareRobustCommand\fontshapeforce[1]{\set@safe@kanji@shape{#1}{}\romanshapeforce{#1}} -\else% >=2021-06-01 \DeclareRobustCommand\romanshape[1]{% \expandafter\def\expandafter\delayed@f@adjustment\expandafter {\delayed@f@adjustment\delayed@merge@font@shape{#1}}} @@ -956,9 +790,6 @@ \romanshapeforce{#1}% \expandafter\def\expandafter\delayed@k@adjustment\expandafter {\delayed@k@adjustment\set@safe@kanji@shape{#1}{}}} -\fi -\ifnum\ltj@@latex@plv>1499 -%%%% LaTeX >= 2021-06-01 \DeclareRobustCommand\usekanji[4]{% \kanjiencoding{#1}\edef\k@family{#2}% \set@target@series@kanji{#3}\edef\k@shape{#4}% @@ -969,42 +800,6 @@ \set@target@series{#3}\edef\f@shape{#4}% \let\delayed@f@adjustment\@empty \selectfont\ignorespaces} -\else\ifnum\ltj@@latex@plv>1000 -%%%% 2021-10-01 PL3 <= LaTeX < 2021-06-01 -\DeclareRobustCommand\usekanji[4]{% - \kanjiencoding{#1}\edef\k@family{#2}% - \set@target@series@kanji{#3}\edef\k@shape{#4}% - \selectfont\ignorespaces} -\DeclareRobustCommand\useroman[4]{% - \romanencoding{#1}\edef\f@family{#2}% - \set@target@series{#3}\edef\f@shape{#4}% - \selectfont\ignorespaces} -\else -%%%% 2020-10-01 <= LaTeX < 2020-10-01 PL3 -\DeclareRobustCommand\usekanji[4]{% - \kanjiencoding{#1}\edef\k@family{#2}\edef\k@series{#3}\edef\k@shape{#4}% - \selectfont\ignorespaces} -\DeclareRobustCommand\useroman[4]{% - \romanencoding{#1}\edef\f@family{#2}\edef\f@series{#3}\edef\f@shape{#4}% - \selectfont\ignorespaces} -\fi\fi -%%%% LaTeX >= 2020-02-02 END -\else -%%%% LaTeX 2019-10-01 -\DeclareRobustCommand\romanseries[1]{\edef\f@series{#1}} -\DeclareRobustCommand\kanjiseries[1]{\edef\k@series{#1}} -\DeclareRobustCommand\fontseries[1]{\kanjiseries{#1}\romanseries{#1}} -\DeclareRobustCommand\romanshape[1]{\edef\f@shape{#1}} -\DeclareRobustCommand\kanjishape[1]{\edef\k@shape{#1}} -\DeclareRobustCommand\fontshape[1]{\set@safe@kanji@shape{#1}{}\romanshape{#1}} -\DeclareRobustCommand\usekanji[4]{% - \kanjiencoding{#1}\kanjifamily{#2}\kanjiseries{#3}\kanjishape{#4}% - \selectfont\ignorespaces} -\DeclareRobustCommand\useroman[4]{% - \romanencoding{#1}\romanfamily{#2}\romanseries{#3}\romanshape{#4}% - \selectfont\ignorespaces} -%%%% LaTeX 2019-10-01 END -\fi %%%% \def\set@safe@kanji@shape#1#2{% @@ -1026,8 +821,6 @@ \else\useroman{#1}{#2}{#3}{#4}% \fi} -\ifnum 0\ifltj@ltfilehook@avail1\fi\ifdefined\@rmfamilyhook1\fi>0 -%%%% LaTeX >= 2020-02-02 \let\prepare@family@series@update@kanji=\prepare@family@series@update \patchcmd\prepare@family@series@update{\fontfamily}{\romanfamily}{}{} \patchcmd\prepare@family@series@update@kanji{\if@forced@series}{\if@forced@series@kanji}{}{} @@ -1049,34 +842,16 @@ \patchcmd\update@series@target@value@kanji{\f@series}{\k@series}{}{} \def\@meta@family@list@kanji{\@elt{mc}\@elt{gt}\@elt{jtt}} -\def\@ltj@hook@series@default#1#2#3{% - \ifltj@ltfilehook@avail % 2020-10-01 - \AddToHook{#1/defaults}{#2}% - \else\ifcsname @set#1defaultshook\endcsname %after 2020-04-07 - \expandafter\g@addto@macro\csname @set#1defaultshook\endcsname{#2}% - \else % 2020-02-02 - \expandafter\patchcmd\csname #1 \endcsname{#3}{#3#2}{}{}% - \fi\fi -} -\@ltj@hook@series@default{bfseries}{% +\AddToHook{bfseries/defaults}{% \let\bfseries@mc\bfdef@ult \let\bfseries@gt\bfdef@ult \let\bfseries@jtt\bfdef@ult -}{% - \let\bfseries@rm\bfdef@ult - \let\bfseries@sf\bfdef@ult - \let\bfseries@tt\bfdef@ult } -\@ltj@hook@series@default{mdseries}{% +\AddToHook{mdseries/defaults}{% \let\mdseries@mc\mddef@ult \let\mdseries@gt\mddef@ult \let\mdseries@jtt\mddef@ult -}{% - \let\mdseries@rm\mddef@ult - \let\mdseries@sf\mddef@ult - \let\mdseries@tt\mddef@ult } -\let\@ltj@hook@series@default\@undefined \expandafter\patchcmd\csname bfseries \endcsname{% \ifx\f@family\rmdef@ult \fontseries\bfseries@rm @@ -1105,105 +880,41 @@ \fi\fi\fi }{}{} -\def\@ltj@hook@series#1#2{% - \ifltj@ltfilehook@avail % 2020-10-01 - \AddToHook{#1}{#2}% - \else % 2020-02-02 - \expandafter\patchcmd\csname #1 \endcsname{\selectfont}{#2\selectfont}{}{}% - \fi -} -\@ltj@hook@series{bfseries}{% +\AddToHook{bfseries}{% \ifx\k@family\mcdef@ult \kanjiseries\bfseries@mc \else\ifx\k@family\gtdef@ult \kanjiseries\bfseries@gt \else\ifx\k@family\jttdef@ult\kanjiseries\bfseries@jtt \else \kanjiseries\bfdefault \fi\fi\fi } -\@ltj@hook@series{mdseries}{% +\AddToHook{mdseries}{% \ifx\k@family\mcdef@ult \kanjiseries\mdseries@mc \else\ifx\k@family\gtdef@ult \kanjiseries\mdseries@gt \else\ifx\k@family\jttdef@ult\kanjiseries\mdseries@jtt \else \kanjiseries\mddefault \fi\fi\fi } -\let\@ltj@hook@series\@undefined -\def\@ltj@hook@efd#1#2{% - \ifltj@ltfilehook@avail % 2020-10-01 - \AddToHook{expand@font@defaults}{#1}% - \else\ifdefined\@expandfontdefaultshook %after 2020-04-07 - \g@addto@macro\@expandfontdefaultshook{#1#2}% - \else % 2020-02-02 - \appto\expand@font@defaults{#1#2}% - \fi\fi -} -\@ltj@hook@efd{% +\AddToHook{expand@font@defaults}{% \edef\mcdef@ult{\mcdefault}% \edef\gtdef@ult{\gtdefault}% \edef\jttdef@ult{\jttdefault}% -}{\edef\kanjidef@ult{\kanjifamilydefault}} -\let\@ltj@hook@efd\@undefined + \edef\kanjidef@ult{\kanjifamilydefault}} -\ifltj@ltfilehook@avail % 2020-10-01 - \appto\init@series@setup{% - \ifx\kanjiseriesdefault\kanjiseriesdefault@kernel - \mdseries - \let\kanjiseriesdefault\k@series - \fi - } -\else - \appto\init@series@setup{% - \ifx\kanjidef@ult\mcdef@ult \mcfamily - \else\ifx\kanjidef@ult\gtdef@ult \gtfamily - \else\ifx\kanjidef@ult\jttdef@ult \jttfamily - \fi\fi\fi - } -\fi - -\def\@ltj@hook@dfh#1{% - \ifltj@ltfilehook@avail % 2020-10-01 - \AddToHook{normalfont}{#1}% - \else\ifdefined\@defaultfamilyhook - \g@addto@macro\@defaultfamilyhook{#1}% - \else % 2020-02-02 - \expandafter\patchcmd\csname normalfont \endcsname{\selectfont}{#1\selectfont}{}{}% - \let\reset@font\normalfont - \fi\fi +\appto\init@series@setup{% + \ifx\kanjiseriesdefault\kanjiseriesdefault@kernel + \mdseries + \let\kanjiseriesdefault\k@series + \fi } -\ifnum\ltj@@latex@plv>1499 -\@ltj@hook@dfh{% +\AddToHook{normalfont}{% \kanjiencoding{\kanjiencodingdefault}% \edef\k@family{\kanjifamilydefault}% \edef\k@series{\kanjiseriesdefault}% \edef\k@shape{\kanjishapedefault}% \let\delayed@k@adjustment\empty } -\else -\@ltj@hook@dfh{% - \kanjiencoding{\kanjiencodingdefault}% - \edef\k@family{\kanjifamilydefault}% - \edef\k@series{\kanjiseriesdefault}% - \edef\k@shape{\kanjishapedefault}% -} -\fi -\let\@ltj@hook@dfh\@undefined -%%%% LaTeX >= 2020-02-02 END -\else -%%%% LaTeX 2019-10-01 -\DeclareRobustCommand\normalfont{% - \useroman\encodingdefault\familydefault\seriesdefault\shapedefault - \usekanji\kanjiencodingdefault\kanjifamilydefault\kanjiseriesdefault\kanjishapedefault} -\let\reset@font\normalfont -%%%% LaTeX 2019-10-01 END -\fi - - - -\ifdefined\prepare@family@series@update@kanji\else -%%%% LaTeX 2019-10-01 -\def\prepare@family@series@update@kanji#1{\kanjifamily} -\fi \DeclareRobustCommand\mcfamily{% \unless\ifltj@disablejfam\not@math@alphabet\mcfamily\mathmc\fi diff --git a/macros/luatex/generic/luatexja/src/patches/lltjp-array.sty b/macros/luatex/generic/luatexja/src/patches/lltjp-array.sty index 9575dc3c04..8005153571 100644 --- a/macros/luatex/generic/luatexja/src/patches/lltjp-array.sty +++ b/macros/luatex/generic/luatexja/src/patches/lltjp-array.sty @@ -3,7 +3,7 @@ % \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{lltjp-array}[2019-07-18 Patch to array for LuaTeX-ja] +\ProvidesPackage{lltjp-array}[2024-06-10 Patch to array for LuaTeX-ja] \RequirePackage{etoolbox,array} @@ -11,7 +11,14 @@ \ignorespaces\@sharp\unskip }{% \ltj@sharp -}{}{} +}{}{% >=2024-06-01 + \def\ltj@sharp{\relax\pltx@next@inhibitglue\ltjfakeboxbdd\ignorespaces\@sharp\textonly@unskip\ltjfakeboxbdd} + \patchcmd\insert@column{% + \ignorespaces\@sharp\textonly@unskip + }{% + \ltj@sharp + }{}{} +} \@ifpackageloaded{lltjext}{}{% %% remove extra \xkanjiskip (pLaTeX2e 2016/04/17) diff --git a/macros/luatex/generic/luatexja/src/patches/lltjp-atbegshi.sty b/macros/luatex/generic/luatexja/src/patches/lltjp-atbegshi.sty index 12605ff11b..202cbf5857 100644 --- a/macros/luatex/generic/luatexja/src/patches/lltjp-atbegshi.sty +++ b/macros/luatex/generic/luatexja/src/patches/lltjp-atbegshi.sty @@ -3,11 +3,10 @@ % \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{lltjp-atbegshi}[2022-08-12 Patching \string\shipout\space hooks for LuaTeX-ja] +\ProvidesPackage{lltjp-atbegshi}[2024-05-14 Patching \string\shipout\space hooks for LuaTeX-ja] % concept: execute all hooks inside yoko direction \vbox -\ifltj@ltfilehook@avail %<*ltshipout>----------------------------------- % \RequirePackage{expl3} @@ -60,77 +59,4 @@ \fi: %</ltshipout>----------------------------------- \ExplSyntaxOff -\expandafter\endinput -\fi -\RequirePackage{atbegshi} -%<*atbegshi>------------------------------------- -% patching atbegshi.sty -%%% following codes are almost copied from -%%% pxatbegshi.sty 2019/09/07 v0.5 (in platex-tools bundle, by H. Yamashita). - -\ifdefined\AtBeginShipoutOriginalShipout - \let\AtBeginShipoutOriginalShipout\ltj@shipout -\fi -\AtBeginShipoutInit -\DeclareRobustCommand \AtBeginDvi [1]{% - \global \setbox \@begindvibox - \vbox{\yoko\unvbox \@begindvibox #1}% -} -%% internal macros are locally effective -\begingroup - -% helpers -%% unique tokens -\def\pxabgs@mark{\pxabgs@mark@} -\def\pxabgs@fin{\pxabgs@fin@} - -%% \pxabgs@patch@cmd\CMD{<orig>}{<new>} -\def\pxabgs@patch@cmd#1#2#3{% - \ifx#1\relax\else - \def\pxabgs@next##1#2##2\pxabgs@mark##3\pxabgs@fin{% - \ifx\pxabgs@mark##3\pxabgs@mark\let#1\relax - \else - \def\pxabgs@fragment{##2}\def#1{##1#3##2}% - \fi}% - \expandafter\pxabgs@next#1\pxabgs@mark#2\pxabgs@mark\pxabgs@fin - \fi -} - -% prepare -\ifdefined\AtBegShi@Output - \let\pxabgs@AtBegShi@Output\AtBegShi@Output -\else\let\pxabgs@AtBegShi@Output\relax\fi -% try first patch -\pxabgs@patch@cmd\pxabgs@AtBegShi@Output - {\let\AtBegShi@OrgProtect\protect}% - {\setbox8\vbox\bgroup\yoko\let\AtBegShi@OrgProtect\protect} -\pxabgs@patch@cmd\pxabgs@AtBegShi@Output - {\AtBeginShipoutOriginalShipout\box\AtBeginShipoutBox}% - {\AtBeginShipoutOriginalShipout\box\AtBeginShipoutBox\egroup\setbox8\box\voidb@x} -\pxabgs@patch@cmd\pxabgs@AtBegShi@Output - {% - \begingroup - \setbox\AtBeginShipoutBox\box\AtBeginShipoutBox - \endgroup - \let\protect\AtBegShi@OrgProtect - }{% - \begingroup - \setbox\AtBeginShipoutBox\box\AtBeginShipoutBox - \endgroup - \let\protect\AtBegShi@OrgProtect - \egroup - } -% commit the change only when successful -\ifx\pxabgs@AtBegShi@Output\relax - \@PackageWarningNoLine{lltjp-atbegshi}{% - Failed in patching \string\AtBegShi@Output.\MessageBreak - This may cause error in tate direction% - } -\else - \global\let\AtBegShi@Output\pxabgs@AtBegShi@Output -\fi - -\endgroup -%% internal macros are no longer effective -%</atbegshi>------------------------------------- \endinput diff --git a/macros/luatex/generic/luatexja/src/patches/lltjp-fontspec.sty b/macros/luatex/generic/luatexja/src/patches/lltjp-fontspec.sty index 589a3c5d6e..d688936c5f 100644 --- a/macros/luatex/generic/luatexja/src/patches/lltjp-fontspec.sty +++ b/macros/luatex/generic/luatexja/src/patches/lltjp-fontspec.sty @@ -35,7 +35,7 @@ { \fontspec_set_family:Nnn \l__fontspec_rmfamily_family_tl {#1} {#2} \tl_set_eq:NN \rmdefault \l__fontspec_rmfamily_family_tl - \use:x + \use:e { \exp_not:n { \DeclareRobustCommand \rmfamily } { @@ -54,7 +54,7 @@ { \fontspec_set_family:Nnn \l__fontspec_sffamily_family_tl {#1} {#2} \tl_set_eq:NN \sfdefault \l__fontspec_sffamily_family_tl - \use:x + \use:e { \exp_not:n { \DeclareRobustCommand \sffamily } { @@ -73,7 +73,7 @@ { \fontspec_set_family:Nnn \l__fontspec_ttfamily_family_tl {#1} {#2} \tl_set_eq:NN \ttdefault \l__fontspec_ttfamily_family_tl - \use:x + \use:e { \exp_not:n { \DeclareRobustCommand \ttfamily } { @@ -94,7 +94,7 @@ { \fontspec_set_family:Nnn \l__fontspec_rmfamily_family_tl {#1} {#2} \tl_set_eq:NN \rmdefault \l__fontspec_rmfamily_family_tl - \use:x + \use:e { \exp_not:n { \DeclareRobustCommand \rmfamily } { @@ -113,7 +113,7 @@ { \fontspec_set_family:Nnn \l__fontspec_sffamily_family_tl {#1} {#2} \tl_set_eq:NN \sfdefault \l__fontspec_sffamily_family_tl - \use:x + \use:e { \exp_not:n { \DeclareRobustCommand \sffamily } { @@ -132,7 +132,7 @@ { \fontspec_set_family:Nnn \l__fontspec_ttfamily_family_tl {#1} {#2} \tl_set_eq:NN \ttdefault \l__fontspec_ttfamily_family_tl - \use:x + \use:e { \exp_not:n { \DeclareRobustCommand \ttfamily } { diff --git a/macros/luatex/generic/luatexja/src/patches/lltjp-geometry.sty b/macros/luatex/generic/luatexja/src/patches/lltjp-geometry.sty index 67b0f5de7f..641fa4a34d 100644 --- a/macros/luatex/generic/luatexja/src/patches/lltjp-geometry.sty +++ b/macros/luatex/generic/luatexja/src/patches/lltjp-geometry.sty @@ -3,7 +3,7 @@ % \NeedsTeXFormat{LaTeX2e} -\ProvidesPackage{lltjp-geometry}[2021-10-24 Patch to geometry for LuaTeX-ja with vertical writing mode] +\ProvidesPackage{lltjp-geometry}[2024-05-16 Patch to geometry for LuaTeX-ja with vertical writing mode] \RequirePackage{expl3} \ifdefined\if@ltj@@geometry@tate\expandafter\endinput\fi \newif\if@ltj@@geometry@tate @@ -31,15 +31,6 @@ %============================================ \unless\ifdefined\ltj@ExecuteAfterPackage -\expandafter\newif\csname ifltj@ltfilehook@avail\endcsname -\@ifl@t@r\fmtversion{2020-10-01}{% - \@ifl@t@r\fmtversion{2020-10-02}{\ltj@ltfilehook@availtrue} - {% - \ifnum\patch@level<0\relax \ifnum\patch@level<-6 \ltj@ltfilehook@availtrue\fi - \else\ltj@ltfilehook@availtrue\fi - }% -}{} -\ifltj@ltfilehook@avail %% \ltj@ExecuteBeforePackage <package><code> and \ltj@ExecuteAfterPackage <package><code> %% no-starred version: do nothing if the <package> is loaded %% starred version: do <code> right away if the <package> is loaded @@ -64,11 +55,6 @@ \@ifpackageloaded{#1}{#2}{\@@ltj@ExecuteBeforePackage{#1}{#2}}% } } -\else - \RequirePackage{filehook} - \let\ltj@ExecuteAfterPackage=\AtEndOfPackageFile - \let\ltj@ExecuteBeforePackage=\AtBeginOfPackageFile -\fi \fi %============================================ @@ -89,12 +75,8 @@ \else \@gobble\iftrue\csname iftdir\endcsname \bool_set_true:N \l_tmpa_bool \fi \fi -\ifltj@ltfilehook@avail - \prop_map_inline:Nn \g__hook_begindocument_code_prop - { \tl_if_in:nnT {#2} {\tate} {\bool_set_true:N \l_tmpa_bool} } -\else - \tl_if_in:NnT \@begindocumenthook {\tate} {\bool_set_true:N \l_tmpa_bool} -\fi +\prop_map_inline:Nn \g__hook_begindocument_code_prop + { \tl_if_in:nnT {#2} {\tate} {\bool_set_true:N \l_tmpa_bool} } \bool_if:NT \l_tmpa_bool { \if@ltj@@geometry@forceoff \@ltj@@geometry@tatefalse diff --git a/macros/luatex/generic/luatexja/src/patches/lltjp-siunitx.sty b/macros/luatex/generic/luatexja/src/patches/lltjp-siunitx.sty index 9c4526c3fd..292cbf00bf 100644 --- a/macros/luatex/generic/luatexja/src/patches/lltjp-siunitx.sty +++ b/macros/luatex/generic/luatexja/src/patches/lltjp-siunitx.sty @@ -1,5 +1,5 @@ % -% lltjp-siunitx.sty 2022-12-14 +% lltjp-siunitx.sty 2024-06-10 % \NeedsTeXFormat{LaTeX2e} @@ -7,7 +7,6 @@ \RequirePackage{siunitx} \makeatletter \ExplSyntaxOn -\cs_if_exist:NTF \siunitx_print_text:n {% siunitx v3.00 \cs_set_protected:Npn \siunitx_print_text:n #1 { \text @@ -32,104 +31,26 @@ } } \cs_set_eq:NN \ltj_orig__siunitx_table_collect_begin:w \__siunitx_table_collect_begin:w -\cs_set_protected:Npn \__siunitx_table_collect_begin:w #1 \relax - { \ltj_orig__siunitx_table_collect_begin:w } -\RenewDocumentCommand \tablenum { O { } m } - { - \mode_leave_vertical: - \group_begin: - \keys_set:nn { siunitx } {#1} - \siunitx_cell_begin:w - \relax \ignorespaces #2 - \siunitx_cell_end: - \group_end: - } -}% siunitx v3.00 end -{% siunitx v2.xx -\cs_generate_variant:Nn \tl_if_in:NnT { coT } -\cs_new:Nn \__ltj_siunix_patch_inner:n { - \cs_if_exist:cT { #1_tl } { - \tl_if_in:coT { #1_tl } { \tex_char:D } { - \tl_replace_all:cnn { #1_tl } { \tex_char:D } { \ltjalchar } - } +\cs_set_protected:Npn \__siunitx_table_collect_begin:w #1 { + \token_if_eq_meaning:NNTF #1 \relax + {\ltj_orig__siunitx_table_collect_begin:w } + {\ltj_orig__siunitx_table_collect_begin:w #1 } } -} -\cs_new:Nn \__ltj_siunix_patch_inner_math:n { - \__ltj_siunix_patch_inner:n { l__siunitx_#1_math } - \__ltj_siunix_patch_inner:n { l__siunitx_#1_text } -} -\AtBeginDocument { - \__ltj_siunix_patch_inner:n { c__siunitx_minus } - \__ltj_siunix_patch_inner:n { c__siunitx_mu } - \__ltj_siunix_patch_inner_math:n { angstrom } - \__ltj_siunix_patch_inner_math:n { arcminute } - \__ltj_siunix_patch_inner_math:n { arcsecond } - \__ltj_siunix_patch_inner_math:n { ohm } -} - -%%%% new table column: S and s -\bool_new:N \l__ltj_siunitx_table_collect_relax_bool -\cs_set_protected:Npn \__siunitx_table_collect_begin_s: { - \bool_set_false:N \l__ltj_siunitx_table_collect_relax_bool - \cs_set_eq:NN \__siunitx_table_collect_token:N - \__siunitx_table_collect_token_s:N - \cs_set_eq:NN \__siunitx_table_print: \__siunitx_table_print_s: - \__siunitx_table_collect_init_s: - \__siunitx_table_collect_get: -} - -\cs_set_protected:Npn \__siunitx_table_collect_not_braced:N #1 +\cs_set_protected:Npn \__siunitx_table_collect_token:N #1 { - \token_if_eq_meaning:NNTF #1 \tex_relax:D { - \bool_if:NTF \l__ltj_siunitx_table_collect_relax_bool { - \__siunitx_table_collect_not_braced_aux_i:N #1 - } { - \bool_set_true:N \l__ltj_siunitx_table_collect_relax_bool - } - } { - \token_if_eq_meaning:NNF #1 \ltjfakeboxbdd { - \token_if_eq_meaning:NNF #1 \pltx@next@inhibitglue { - \token_if_eq_meaning:NNF #1 \tex_ignorespaces:D + \__siunitx_table_collect_search:NnF #1 { - \token_if_eq_meaning:NNF #1 \tex_unskip:D - { \__siunitx_table_collect_not_braced_aux_i:N #1 } + \ignorespaces { \__siunitx_table_collect_ignore_spaces:N #1} + \pltx@next@inhibitglue { \__siunitx_table_collect_loop:} + \ltjfakeboxbdd { \__siunitx_table_collect_loop:} + \textonly@unskip { \__siunitx_table_collect_loop:} + \unskip { \__siunitx_table_collect_loop:} + \end { \tabularnewline \end } + \relax { \__siunitx_table_collect_relax:N #1 } + \tabularnewline { \tabularnewline } + \siunitx_cell_end: { \siunitx_cell_end:} } - }}} - \__siunitx_table_collect_next: - } - -\AtBeginDocument - { - \@ifpackageloaded { mdwtab } - { - \cs_set_protected:Npn \__siunitx_table_collect_not_braced:N #1 - { - \token_if_eq_meaning:NNTF #1 \tex_relax:D { - \bool_if:NTF \l__ltj_siunitx_table_collect_relax_bool { - \__siunitx_table_collect_not_braced_aux_i:N #1 - } { - \bool_set_true:N \l__ltj_siunitx_table_collect_relax_bool - } - } { - \token_if_eq_meaning:NNF #1 \ltjfakeboxbdd { - \token_if_eq_meaning:NNF #1 \pltx@next@inhibitglue { - \token_if_eq_meaning:NNF #1 \tex_ignorespaces:D - { - \token_if_eq_meaning:NNF #1 \tex_unskip:D - { - \token_if_eq_meaning:NNF #1 \tab@setcr - { - \token_if_eq_meaning:NNF #1 \@maybe@unskip - { \__siunitx_table_collect_not_braced_aux_i:N #1 } - } - } - } - }}} - \__siunitx_table_collect_next: - } - } - { } - } + { \__siunitx_table_collect_token_aux:N #1 } } \ExplSyntaxOff \endinput diff --git a/macros/luatex/generic/luatexja/src/patches/lltjp-unicode-math.sty b/macros/luatex/generic/luatexja/src/patches/lltjp-unicode-math.sty index 79ba8cbcf5..bc123e6784 100644 --- a/macros/luatex/generic/luatexja/src/patches/lltjp-unicode-math.sty +++ b/macros/luatex/generic/luatexja/src/patches/lltjp-unicode-math.sty @@ -46,9 +46,9 @@ % ltjsclasses: use lua \cs_new:Nn \lltjp_um_unmag_fsize: { - \cs_gset:Nx \lltjp_um_f@size: {\directlua{luatexja.ltjs_unmagnify_fsize(\f@size)}} - \cs_gset:Nx \lltjp_um_sf@size: {\directlua{luatexja.ltjs_unmagnify_fsize(\sf@size)}} - \cs_gset:Nx \lltjp_um_ssf@size: {\directlua{luatexja.ltjs_unmagnify_fsize(\ssf@size)}} + \cs_gset:Ne \lltjp_um_f@size: {\directlua{luatexja.ltjs_unmagnify_fsize(\f@size)}} + \cs_gset:Ne \lltjp_um_sf@size: {\directlua{luatexja.ltjs_unmagnify_fsize(\sf@size)}} + \cs_gset:Ne \lltjp_um_ssf@size: {\directlua{luatexja.ltjs_unmagnify_fsize(\ssf@size)}} } }{ % bxjscls: use \jsc@preadjust@extract@font diff --git a/macros/luatex/generic/luavlna/README.md b/macros/luatex/generic/luavlna/README.md index 1fe76754d5..aeaf7d2bd0 100644 --- a/macros/luatex/generic/luavlna/README.md +++ b/macros/luatex/generic/luavlna/README.md @@ -1,4 +1,4 @@ -# Luavlna, version 0.1l, 2023-06-21 +# Luavlna, version 0.1m, 2024-05-02 # Introduction diff --git a/macros/luatex/generic/luavlna/luavlna-doc.pdf b/macros/luatex/generic/luavlna/luavlna-doc.pdf Binary files differindex a75499a3c9..7f80b780a7 100644 --- a/macros/luatex/generic/luavlna/luavlna-doc.pdf +++ b/macros/luatex/generic/luavlna/luavlna-doc.pdf diff --git a/macros/luatex/generic/luavlna/luavlna-doc.tex b/macros/luatex/generic/luavlna/luavlna-doc.tex index 470822d4ac..698f46e52d 100644 --- a/macros/luatex/generic/luavlna/luavlna-doc.tex +++ b/macros/luatex/generic/luavlna/luavlna-doc.tex @@ -87,7 +87,7 @@ Podpora iniciál a titulů: M. J. Hegel, Ing. Běháková, Ph.D., Ž. Zíbrt, Ch. Borner. Podpora jednotek: 100,5 MN\cdot{}s, 100.5 kJ, 200 µA, $-1$ dag, -12 MiB, 1 m$^3$/s. +12 MiB. Uvnitř matematiky by mělo být zpracování vypnuté: $k \in \mathbb N$. Pokračujeme v příkladu. @@ -113,7 +113,7 @@ Různé možnosti [v závorkách \textless i jiných znacích Podpora iniciál a titulů: M. J. Hegel, Ing. Běháková, Ph.D., Ž. Zíbrt, Ch. Borner. -Podpora jednotek: 100,5 MN\cdot{}s, 100.5 kJ, 200 µA, $-1$ dag, 12 MiB, 1 m$^3$/s. +Podpora jednotek: 100,5 MN\cdot{}s, 100.5 kJ, 200 µA, $-1$ dag, 12 MiB. Uvnitř matematiky by mělo být zpracování vypnuté: $k \in \mathbb N$. Pokračujeme v příkladu. @@ -298,7 +298,9 @@ File \verb|language.dat| is processed to load language names, aliases and assign local luatex = langno.load_languages(fmt) local t = {} for k, v in pairs(luatex.names) do - t[#t+1]=k + if k and k~="" then + t[#t+1]=k + end end table.sort(t) tex.print(table.concat(t,", ")) diff --git a/macros/luatex/generic/luavlna/luavlna-langno.lua b/macros/luatex/generic/luavlna/luavlna-langno.lua index f703e4328a..7f25d84100 100644 --- a/macros/luatex/generic/luavlna/luavlna-langno.lua +++ b/macros/luatex/generic/luavlna/luavlna-langno.lua @@ -58,7 +58,8 @@ local load_lang_dat = function(start) end local load_lang_dat_lualatex = function() - return load_lang_dat(1) + -- it used to be 1, but it seems that in newer LuaLaTeX versions, we should start at 0 + return load_lang_dat(0) end local load_csplain= function() diff --git a/macros/luatex/generic/luavlna/luavlna.lua b/macros/luatex/generic/luavlna/luavlna.lua index 416ecc5841..3e5f79346f 100644 --- a/macros/luatex/generic/luavlna/luavlna.lua +++ b/macros/luatex/generic/luavlna/luavlna.lua @@ -260,6 +260,15 @@ local is_unit = function(word) return false end +local function handle_unit(word, anchor) + -- insert nbsp between numbers and units + word = cut_off_end_chars(word, false) + if is_unit(word) then + anchor = replace_with_thin_space(anchor) + insert_penalty(anchor.prev) + end +end + local predegrees = Set (require "luavlna-predegrees") local sufdegrees = Set (require "luavlna-sufdegrees") @@ -299,11 +308,7 @@ local function prevent_single_letter (head) if wasnumber then if word ~= "" then wasnumber = false - word = cut_off_end_chars(word, false) - if is_unit(word) then - anchor = replace_with_thin_space(anchor) - insert_penalty(anchor.prev) - end + handle_unit(word, anchor) end elseif is_number(word) then wasnumber = true @@ -356,6 +361,10 @@ local function prevent_single_letter (head) end head = head.next end + -- insert spaces at the end of node list + if wasnumber then + handle_unit(word, anchor) + end return true end diff --git a/macros/luatex/generic/luavlna/luavlna.sty b/macros/luatex/generic/luavlna/luavlna.sty index 9f411c5f9f..b49ef89803 100644 --- a/macros/luatex/generic/luavlna/luavlna.sty +++ b/macros/luatex/generic/luavlna/luavlna.sty @@ -1,4 +1,4 @@ -\ProvidesPackage{luavlna}[2023-06-21 luavlna] +\ProvidesPackage{luavlna}[2024-05-02 luavlna] \ifdefined\directlua\else \PackageWarning{luavlna}{Luavlna needs LuaLaTeX, aborting} diff --git a/macros/luatex/generic/luavlna/luavlna.tex b/macros/luatex/generic/luavlna/luavlna.tex index d678854e9a..ddddf8ab9e 100644 --- a/macros/luatex/generic/luavlna/luavlna.tex +++ b/macros/luatex/generic/luavlna/luavlna.tex @@ -72,10 +72,15 @@ end % we can try to find the language ID from macros first, if it fails % we pass the language name to Lua. it will try to find ID in luanguage.dat and other sources \def\singlecharsgetlang#1{% - \ifcsname lang@#1\endcsname% - \the\csname lang@#1\endcsname% - \else% unknown language macro, let langno library to find it - #1% + \ifcsname l@#1\endcsname% + \the\csname l@#1\endcsname% + \else% + \ifcsname lang@#1\endcsname% + \the\csname lang@#1\endcsname% + \else% + % unknown language macro, let langno library to find it + #1% + \fi% \fi% } diff --git a/macros/luatex/generic/luaxml/README b/macros/luatex/generic/luaxml/README index 5df074c453..6a81ab25ce 100644 --- a/macros/luatex/generic/luaxml/README +++ b/macros/luatex/generic/luaxml/README @@ -32,7 +32,7 @@ Author ------ Michal Hoftich Email: michal.h21@gmail.com -Version: v0.1r, 2024-02-23 +Version: v0.2, 2024-07-14 Original authors: Paul Chakravarti and Manoel Campos (http://manoelcampos.com) diff --git a/macros/luatex/generic/luaxml/luaxml-cssquery.lua b/macros/luatex/generic/luaxml/luaxml-cssquery.lua index ebb29abb15..452656845c 100644 --- a/macros/luatex/generic/luaxml/luaxml-cssquery.lua +++ b/macros/luatex/generic/luaxml/luaxml-cssquery.lua @@ -156,7 +156,7 @@ local function cssquery() -- make sure we deal with a string value = tostring(value) -- make the search string safe for pattern matching - local escaped_search = search:gsub("([%(%)%.%%%+%–%*%?%[%^%$])", "%%%1") + local escaped_search = search:gsub("([%(%)%.%%%+%-%#%*%?%[%^%$])", "%%%1") if modifier == "" then return value == search elseif modifier == "|" then @@ -434,6 +434,18 @@ local function cssquery() return querylist end + --- Remove selector from the CSS list object. + -- All actions that literaly match the given selector will be removed. + function CssQuery:remove_selector( + selector -- CSS selector to be removed + ) + for pos, obj in ipairs(self.querylist) do + if obj.source == selector then + table.remove(self.querylist, pos) + end + end + end + --- It tests list of queries agaings a DOM element and executes the --- coresponding function that is saved for the matched query. -- @return nothing diff --git a/macros/luatex/generic/luaxml/luaxml-domobject.lua b/macros/luatex/generic/luaxml/luaxml-domobject.lua index 73689add5a..dca38df0db 100644 --- a/macros/luatex/generic/luaxml/luaxml-domobject.lua +++ b/macros/luatex/generic/luaxml/luaxml-domobject.lua @@ -6,16 +6,20 @@ local dom = {} local xml local handler local css_query +local html if kpse then xml = require("luaxml-mod-xml") handler = require("luaxml-mod-handler") css_query = require("luaxml-cssquery") + html = require("luaxml-mod-html") else xml = require("luaxml.mod-xml") handler = require("luaxml.mod-handler") css_query = require("luaxml.cssquery") + html = require("luaxml.mod-html") end +local HtmlParser = html.HtmlParser local void = {area = true, base = true, br = true, col = true, hr = true, img = true, input = true, link = true, meta = true, param = true} @@ -91,9 +95,14 @@ local function serialize_dom(parser, current,level, output) local format = get_action(typ, "start") insert(format, el, prepare_attributes(attr)) end - local function text(typ, text) + local function text(typ, text, parent) + local parent = parent or {} local format = get_action(typ, "text") - insert(format, escape_element(text)) + if parent.verbatim then + insert(format, text) + else + insert(format, escape_element(text)) + end end local function stop(typ, el) local format = get_action(typ, "stop") @@ -141,7 +150,7 @@ local function serialize_dom(parser, current,level, output) end start(xtype, name, attributes) - text(xtype,text_content) + text(xtype,text_content, (current or {})._parent) local children = root._children or {} for _, child in ipairs(children) do output = serialize_dom(parser,child, level + 1, output) @@ -411,8 +420,8 @@ local parse = function( return strings end - --- Get table with the inner text of an element -- leading and trailing spaces are removed and elements that contain only white space are ignored. - --- @return table + --- Get table with the inner text of an element - leading and trailing spaces are removed and elements that contain only white space are ignored. + -- @return table function DOM_Object:stripped_strings( current --- [optional] element to be selected ) @@ -612,11 +621,83 @@ local parse = function( -- include the methods to all xml nodes save_methods(parser._handler.root) -- parser: - return parser + return parser, DOM_Object +end + +-- table of elements that should be kept without XML escaping in the DOM serialization +local verbatim_elements = {script=true, style=true} + +local function html_to_dom(html_object) + -- convert parsed HTML DOM to the XML DOM + local dom, DOM_Object = parse("") -- use empty text to just initialize the DOM object + -- use root of the DOM object as the original parent + local current_parent = dom._handler.root + + local function create_node(tbl) + -- create node suitable for LuaXML DOM object + tbl._children = {} + -- this should copy methods from the DOM object to the newly created object + tbl.__index = DOM_Object + return setmetatable(tbl, DOM_Object) + end + + local function build_tree(object) + -- convert tree produced by the HTML parser to LuaXML DOM + local typ = object._type + -- process particular node types from the HTML parser + if typ == "doctype" then + current_parent:add_child_node(create_node {_name=object.name, _type="DTD"}) + elseif typ == "comment" then + current_parent:add_child_node(create_node {_text=object.text, _type="COMMENT"}) + elseif typ == "element" then + local attributes = {} + -- convert attributes to the form expected by the DOM object + for _, attr in ipairs(object.attr) do + attributes[attr.name] = attr.value + end + local element = current_parent:create_element(object.tag, attributes) + -- disable escaping of text in dom:serialize() for <script> or <style> elements + if verbatim_elements[string.lower(object.tag)] then element.verbatim = true end + current_parent:add_child_node(element) + -- set the current element as parent for the processing of children + local old_parent = current_parent + current_parent = element + -- process children + for k,v in ipairs(object.children) do + build_tree(v) + end + -- restore original parent + current_parent = old_parent + elseif typ == "text" then + local text = current_parent:create_text_node(object.text) + current_parent:add_child_node(text) + else + -- for other node types, just process the children + for k,v in ipairs(object.children) do + build_tree(v) + end + end + + end + build_tree(html_object) + return dom +end + +--- Parse HTML text as a DOM object. +-- It supports all methods as the object returned by the parse() function. +-- @param html_str string with the HTML code to be parsed +-- @return DOM_Object +local function html_parse(html_str) + local html_obj = HtmlParser:init(html_str) + local html_dom = html_obj:parse() + return html_to_dom(html_dom) end + + --- @export return { parse = parse, - serialize_dom= serialize_dom + serialize_dom= serialize_dom, + html_parse = html_parse } diff --git a/macros/luatex/generic/luaxml/luaxml-encodings.lua b/macros/luatex/generic/luaxml/luaxml-encodings.lua new file mode 100644 index 0000000000..71bfc81dd1 --- /dev/null +++ b/macros/luatex/generic/luaxml/luaxml-encodings.lua @@ -0,0 +1,88 @@ +--- Convert 8-bit encodings to UTF-8 +--- @module luaxml-encodings +-- this table is generated automatically by this command: +-- texlua encodings/make_encodings.lua +local encodings = { + ['ibm866'] = 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмноп░▒▓│┤╡╢╖╕╣║╗╝╜╛┐└┴┬├─┼╞╟╚╔╩╦╠═╬╧╨╤╥╙╘╒╓╫╪┘┌█▄▌▐▀рстуфхцчшщъыьэюяЁёЄєЇїЎў°∙·√№¤■ ', + ['iso-8859-5'] = '�������������������������������� ЁЂЃЄЅІЇЈЉЊЋЌЎЏАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя№ёђѓєѕіїјљњћќ§ўџ', + ['macintosh'] = 'ÄÅÇÉÑÖÜáàâäãåçéèêëíìîïñóòôöõúùûü†°¢£§•¶ß®©™´¨≠ÆØ∞±≤≥¥µ∂∑∏π∫ªºΩæø¿¡¬√ƒ≈∆«»… ÀÃÕŒœ–—“”‘’÷◊ÿŸ⁄€‹›fifl‡·‚„‰ÂÊÁËÈÍÎÏÌÓÔÒÚÛÙıˆ˜¯˘˙˚¸˝˛ˇ', + ['windows-1251'] = 'ЂЃ‚ѓ„…†‡€‰Љ‹ЊЌЋЏђ‘’“”•–—�™љ›њќћџ ЎўЈ¤Ґ¦§Ё©Є«¬®Ї°±Ііґµ¶·ё№є»јЅѕїАБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюя', + ['iso-8859-13'] = '�������������������������������� ”¢£¤„¦§Ø©Ŗ«¬®Æ°±²³“µ¶·ø¹ŗ»¼½¾æĄĮĀĆÄÅĘĒČÉŹĖĢĶĪĻŠŃŅÓŌÕÖ×ŲŁŚŪÜŻŽßąįāćäåęēčéźėģķīļšńņóōõö÷ųłśūüżž’', + ['iso-8859-6'] = '�������������������������������� ���¤�������،�������������؛���؟�ءآأؤإئابةتثجحخدذرزسشصضطظعغ�����ـفقكلمنهوىيًٌٍَُِّْ', + ['iso-8859-8'] = '�������������������������������� �¢£¤¥¦§¨©×«¬®¯°±²³´µ¶·¸¹÷»¼½¾��������������������������������‗אבגדהוזחטיךכלםמןנסעףפץצקרשת��', + ['iso-8859-4'] = '�������������������������������� ĄĸŖ¤ĨĻ§¨ŠĒĢŦŽ¯°ą˛ŗ´ĩļˇ¸šēģŧŊžŋĀÁÂÃÄÅÆĮČÉĘËĖÍÎĪĐŅŌĶÔÕÖ×ØŲÚÛÜŨŪßāáâãäåæįčéęëėíîīđņōķôõö÷øųúûüũū˙', + ['koi8-r'] = '─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥ ⌡°²·÷═║╒ё╓╔╕╖╗╘╙╚╛╜╝╞╟╠╡Ё╢╣╤╥╦╧╨╩╪╫╬©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ', + ['iso-8859-7'] = '�������������������������������� ‘’£€₯¦§¨©ͺ«¬�―°±²³΄΅Ά·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ�ΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ', + ['iso-8859-3'] = '�������������������������������� Ħ˘£¤�Ĥ§¨İŞĞĴ�Ż°ħ²³´µĥ·¸ışğĵ½�żÀÁÂ�ÄĊĈÇÈÉÊËÌÍÎÏ�ÑÒÓÔĠÖ×ĜÙÚÛÜŬŜßàáâ�äċĉçèéêëìíîï�ñòóôġö÷ĝùúûüŭŝ˙', + ['windows-1256'] = '€پ‚ƒ„…†‡ˆ‰ٹ‹Œچژڈگ‘’“”•–—ک™ڑ›œں ،¢£¤¥¦§¨©ھ«¬®¯°±²³´µ¶·¸¹؛»¼½¾؟ہءآأؤإئابةتثجحخدذرزسشصض×طظعغـفقكàلâمنهوçèéêëىيîïًٌٍَôُِ÷ّùْûüے', + ['windows-1258'] = '€�‚ƒ„…†‡ˆ‰�‹Œ����‘’“”•–—˜™�›œ��Ÿ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂĂÄÅÆÇÈÉÊË̀ÍÎÏĐÑ̉ÓÔƠÖ×ØÙÚÛÜỮßàáâăäåæçèéêë́íîïđṇ̃óôơö÷øùúûüư₫ÿ', + ['iso-8859-14'] = '�������������������������������� Ḃḃ£ĊċḊ§Ẁ©ẂḋỲ®ŸḞḟĠġṀṁ¶ṖẁṗẃṠỳẄẅṡÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏŴÑÒÓÔÕÖṪØÙÚÛÜÝŶßàáâãäåæçèéêëìíîïŵñòóôõöṫøùúûüýŷÿ', + ['windows-1252'] = '€�‚ƒ„…†‡ˆ‰Š‹Œ�Ž��‘’“”•–—˜™š›œ�žŸ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ', + ['iso-8859-15'] = '�������������������������������� ¡¢£€¥Š§š©ª«¬®¯°±²³Žµ¶·ž¹º»ŒœŸ¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ', + ['x-mac-cyrillic'] = 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ†°Ґ£§•¶І®©™Ђђ≠Ѓѓ∞±≤≥іµґЈЄєЇїЉљЊњјЅ¬√ƒ≈∆«»… ЋћЌќѕ–—“”‘’÷„ЎўЏџ№Ёёяабвгдежзийклмнопрстуфхцчшщъыьэю€', + ['windows-1254'] = '€�‚ƒ„…†‡ˆ‰Š‹Œ����‘’“”•–—˜™š›œ��Ÿ ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏĞÑÒÓÔÕÖ×ØÙÚÛÜİŞßàáâãäåæçèéêëìíîïğñòóôõö÷øùúûüışÿ', + ['windows-1255'] = '€�‚ƒ„…†‡ˆ‰�‹�����‘’“”•–—˜™�›���� ¡¢£₪¥¦§¨©×«¬®¯°±²³´µ¶·¸¹÷»¼½¾¿ְֱֲֳִֵֶַָֹֺֻּֽ־ֿ׀ׁׂ׃װױײ׳״�������אבגדהוזחטיךכלםמןנסעףפץצקרשת��', + ['windows-1250'] = '€�‚�„…†‡�‰Š‹ŚŤŽŹ�‘’“”•–—�™š›śťžź ˇ˘Ł¤Ą¦§¨©Ş«¬®Ż°±˛ł´µ¶·¸ąş»Ľ˝ľżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙', + ['koi8-u'] = '─│┌┐└┘├┤┬┴┼▀▄█▌▐░▒▓⌠■∙√≈≤≥ ⌡°²·÷═║╒ёє╔ії╗╘╙╚╛ґў╞╟╠╡ЁЄ╣ІЇ╦╧╨╩╪ҐЎ©юабцдефгхийклмнопярстужвьызшэщчъЮАБЦДЕФГХИЙКЛМНОПЯРСТУЖВЬЫЗШЭЩЧЪ', + ['iso-8859-10'] = '�������������������������������� ĄĒĢĪĨĶ§ĻĐŠŦŽŪŊ°ąēģīĩķ·ļđšŧž―ūŋĀÁÂÃÄÅÆĮČÉĘËĖÍÎÏÐŅŌÓÔÕÖŨØŲÚÛÜÝÞßāáâãäåæįčéęëėíîïðņōóôõöũøųúûüýþĸ', + ['windows-1257'] = '€�‚�„…†‡�‰�‹�¨ˇ¸�‘’“”•–—�™�›�¯˛� �¢£¤�¦§Ø©Ŗ«¬®Æ°±²³´µ¶·ø¹ŗ»¼½¾æĄĮĀĆÄÅĘĒČÉŹĖĢĶĪĻŠŃŅÓŌÕÖ×ŲŁŚŪÜŻŽßąįāćäåęēčéźėģķīļšńņóōõö÷ųłśūüżž˙', + ['windows-1253'] = '€�‚ƒ„…†‡�‰�‹�����‘’“”•–—�™�›���� ΅Ά£¤¥¦§¨©�«¬®―°±²³΄µ¶·ΈΉΊ»Ό½ΎΏΐΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡ�ΣΤΥΦΧΨΩΪΫάέήίΰαβγδεζηθικλμνξοπρςστυφχψωϊϋόύώ', + ['iso-8859-2'] = '�������������������������������� Ą˘Ł¤ĽŚ§¨ŠŞŤŹŽŻ°ą˛ł´ľśˇ¸šşťź˝žżŔÁÂĂÄĹĆÇČÉĘËĚÍÎĎĐŃŇÓÔŐÖ×ŘŮÚŰÜÝŢßŕáâăäĺćçčéęëěíîďđńňóôőö÷řůúűüýţ˙', + ['windows-874'] = '€����…�����������‘’“”•–—�������� กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮฯะัาำิีึืฺุู����฿เแโใไๅๆ็่้๊๋์ํ๎๏๐๑๒๓๔๕๖๗๘๙๚๛', + ['iso-8859-16'] = '�������������������������������� ĄąŁ€„Š§š©Ș«ŹźŻ°±ČłŽ”¶·žčș»ŒœŸżÀÁÂĂÄĆÆÇÈÉÊËÌÍÎÏĐŃÒÓÔŐÖŚŰÙÚÛÜĘȚßàáâăäćæçèéêëìíîïđńòóôőöśűùúûüęțÿ', +} + + +local utfchar = utf8.char + +--- Try to find an encoding in HTML string +---@param str string HTML document +---@param len number count of characters from the start of the string where it should search for the encoding metadata +---@return string encoding identifier, or nil and message if no encoding was found +local function find_html_encoding(str, len) + -- try to find encoding in the html document + -- we limit search length, because encoding should be in the document head, ideally near the start + local len = len or 4096 + local sub = str:sub(1, len) + for meta in sub:gmatch("<meta (.-)>") do + local charset = meta:match("charset%s*=%s*[\"']?(.-)[\"']") + if charset then return string.lower(charset) end + end + return nil, "Cannot find the document encoding" +end + +local function load_mapping(enc_name) + local enc_name = enc_name or "" + local enc = encodings[enc_name] + if not enc then return nil, "Cannot load encoding " .. enc_name end + local mapping,i = {}, 128 + for pos, codepoint in utf8.codes(enc) do + mapping[i] = utfchar(codepoint) + i = i + 1 + end + return mapping +end + +--- Convert string to utf-8 +---@param text string for converting +---@param mapping table +---@return string converted string +local function recode(text, mapping) + return text:gsub("(.)", function(char) + local charpoint = string.byte(char) + if charpoint > 127 then + return mapping[charpoint] + else + return false + end + end) +end + + +return { + encodings = encodings, + find_html_encoding = find_html_encoding, + load_mapping = load_mapping, + recode = recode +} + diff --git a/macros/luatex/generic/luaxml/luaxml-mod-html.lua b/macros/luatex/generic/luaxml/luaxml-mod-html.lua index 69e32b16e2..d8c2b7e932 100644 --- a/macros/luatex/generic/luaxml/luaxml-mod-html.lua +++ b/macros/luatex/generic/luaxml/luaxml-mod-html.lua @@ -1,3 +1,6 @@ +--- HTML parsing module for LuaXML +-- @module luaxml-mod-html +-- @author Michal Hoftich <michal.h21@gmail.com -- Copyright Michal Hoftich, 2022 -- HTML parser inspired by https://browser.engineering/html.html -- but then redone using https://html.spec.whatwg.org/multipage/parsing.html @@ -1540,9 +1543,14 @@ local function is_formatting_element(name) return formatting_element_names[name] end -local special_elements = {} +local function hash_from_array(tbl) + local t = {} + for _, v in ipairs(tbl) do t[v] = true end + return t +end + -local special_elements_list = {"address", "applet", "area", "article", "aside", +local special_elements_list = hash_from_array {"address", "applet", "area", "article", "aside", "base", "basefont", "bgsound", "blockquote", "body", "br", "button", "caption", "center", "col", "colgroup", "dd", "details", "dir", "div", "dl", "dt", "embed", "fieldset", "figcaption", "figure", "footer", "form", "frame", @@ -1555,13 +1563,9 @@ local special_elements_list = {"address", "applet", "area", "article", "aside", "mi","mo","mn","ms","mtext", "annotation-xml","foreignObject","desc", "title" } -for k,v in ipairs(special_elements_list) do - special_elements[v] = true -end - local function is_special(name) - return special_elements[name] + return special_elements_list[name] end -- these lists are used in HtmlParser:generate_implied_endtags() @@ -1649,8 +1653,12 @@ local HtmlTreeStates = {} +--- @type HtmlParser local HtmlParser = {} +--- Initialize the HTML Object +---@param body string HTML to be parsed +---@return table initialized object function HtmlParser:init(body) local o ={} setmetatable(o, self) @@ -1686,10 +1694,11 @@ for _,v in ipairs(self_closing_tags_list) do self_closing_tags[v] = true end - +--- Execute the HTML parser +--- @return table Root node of the HTML DOM function HtmlParser:parse() -- we assume utf8 input, you must convert it yourself if the source is - -- in a different encoding + -- in a different encoding. for example using luaxml-encodings library self.text = {} self.state = self.default_state -- this should enable us to pass over some characters that we want to ignore @@ -1791,6 +1800,7 @@ function HtmlParser:emit(token) elseif token_type == "start_tag" then self:add_text() -- self:start_attribute() + self:reset_insertion_mode() self:start_tag() -- print("Emit start tag", table.concat(token.name)) -- save last attribute @@ -1882,8 +1892,139 @@ function HtmlParser:set_xmlns(node, parent) end end +function HtmlParser:pop_element() + -- close the current element and add it to the DOM + local el = self:close_element() + local parent = self:get_parent() + parent:add_child(el) + return el +end + +local close_p_at_start = hash_from_array {"address", "article", "aside", "blockquote", "center", "details", "dialog", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "main", "menu", "nav", "ol", "p", "search", "section", "summary", "ul", "pre", "listing", "form", "table", "xmp", "hr"} + +local close_headers = hash_from_array {"h1", "h2", "h3", "h4", "h5", "h6"} + +local body_modes = hash_from_array {"in_body", "in_cell", "in_row", "in_select", "in_table", "in_table_body", "in_frameset"} + +local list_items = hash_from_array {"li", "dt", "dd"} + +local close_address_at_end = hash_from_array{"address", "article", "aside", "blockquote", "button", "center", "details", "dialog", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "listing", "main", "menu", "nav", "ol", "pre", "search", "section", "summary", "ul", "form"} + + +function HtmlParser:close_unfinished(name) + -- close all unfinished elements until the element with the given name is found + for i = #self.unfinished, 1, -1 do + local el = self:pop_element() + if el.tag == name then + break + end + end +end + + +function HtmlParser:close_paragraph() + -- close currently open <p> elements + self:close_unfinished("p") +end + +function HtmlParser:current_element_name() + -- return name of the current element + return self:get_parent().tag +end + +local not_specials = hash_from_array { "address", "div", "p"} + +local function handle_list_item(self, name) + -- we handle li, dt and dd. dt and dd should close each other, li closes only itself + local names = {dt = true, dd = true} + if name == "li" then names = {li=true} end + for i = #self.unfinished, 1, -1 do + local current = self.unfinished[i] + local current_tag = current.tag + if names[current_tag] then + self:generate_implied_endtags(nil, {current.tag}) + for j = #self.unfinished, i, -1 do + self:pop_element() + end + break + elseif is_special(current_tag) and not not_specials[name] then + break + end + end +end + +local close_paragraph = function(self) + if is_in_button_scope(self, "p") then + self:close_paragraph() + end +end + +function HtmlParser:handle_insertion_mode(token) + -- simple handling of https://html.spec.whatwg.org/multipage/parsing.html#tree-construction + -- we don't support most rules, just the most important for avoiding mismatched tags + + if body_modes[self.insertion_mode] then + if token.type == "start_tag" then + local name = table.concat(token.name) + if close_p_at_start[name] then close_paragraph(self) end + if close_headers[name] then + close_paragraph(self) + -- close current element if it is already header + if close_headers[self:current_element_name()] then + self:pop_element() + end + elseif name == "pre" or name == "listing" then + -- we should ignore next "\n" char token + elseif name == "image" then + -- image tag is an error, change to <img> + token.name = {"img"} + elseif list_items[name] then + handle_list_item(self, name) + close_paragraph(self) + end + elseif token.type == "end_tag" then + local name = table.concat(token.name) + if close_address_at_end[name] then + if is_in_scope(self, name, {}) then + self:close_unfinished(name) + else + token.type = "ignore" + end + elseif name == "p" then + if not is_in_button_scope(self, "p") then + local parent = self:get_parent() + local node = Element:init("p", parent) + table.insert(self.unfinished, node) + end + -- use self:close_paragraph() instead of close_paragraph() because we don't need to check scope at this point + self:close_paragraph() + elseif name == "br" then + token.type = "start_tag" + elseif close_headers[name] then + local header_in_scope = false + -- detect, if there are any open h1-h6 tag and close it + for el, _ in pairs(close_headers) do + if is_in_scope(self, el, {}) then + header_in_scope = el + break + end + end + if not header_in_scope then + token.type = "ignore" + else + self:close_unfinished(header_in_scope) + end + end + end + end +end + +local rawtext_elements = hash_from_array {"style", "textarea", "xmp"} + + function HtmlParser:start_tag() local token = self.current_token + self:handle_insertion_mode(token) if token.type == "start_tag" then -- close all currently opened attributes self:start_attribute() @@ -1894,18 +2035,18 @@ function HtmlParser:start_tag() node.attr = token.attr node.self_closing = token.self_closing self:set_xmlns(node) - -- + -- in this handler we should close <p> or <li> elements without explicit closing tags if token.self_closing -- <img /> or self_closing_tags[name] -- void elements then - parent:add_child(node) + parent:add_child(node, node.tag) else -- add to the unfinished list table.insert(self.unfinished, node) end if name == "title" then self.element_state = "rcdata" - elseif name == "style" then + elseif rawtext_elements[name] then self.element_state = "rawtext" elseif name == "script" then self.element_state = "script_data" @@ -1916,11 +2057,13 @@ end function HtmlParser:end_tag() -- close current opened element local token = self.current_token + self:handle_insertion_mode(token) if token.type == "end_tag" then if #self.unfinished==0 then return nil end - local node = self:close_element() - local parent = self:get_parent() - parent:add_child(node) + -- close the current element only if the token is in the current scope + if is_in_scope(self, table.concat(token.name), {}) then + self:pop_element() + end end end @@ -1964,6 +2107,21 @@ function HtmlParser:adjusted_current_node() end +local simple_modes = { + body = "in_body", + td = "in_cell", + th = "in_cell", + tr = "in_row", + tbody = "in_table_body", + thead = "in_table_body", + tfoot = "in_table_body", + caption = "in_caption", + colgroup = "in_column_group", + table = "in_table", + template = "current_template_insertion_mode", + frameset = "in_frameset" +} + function HtmlParser:reset_insertion_mode() -- https://html.spec.whatwg.org/multipage/parsing.html#reset-the-insertion-mode-appropriately local last = false @@ -1977,16 +2135,33 @@ function HtmlParser:reset_insertion_mode() if name == "head" and last == true then self:switch_insertion("in_head") return - elseif name == "body" then - self:switch_insertion("in_body") - return elseif name == "html" then - if self.head_pointer then + if not self.head_pointer then self:switch_insertion("before_head") return else self:switch_insertion("after_head") + return + end + elseif name == "select" then + if not last then + for x = position -1, 1, -1 do + if x == 1 then break end + local ancestor = self.unfinished[x] + local ancestor_name = ancestor.tag + if ancestor_name == "template" then + break + elseif ancestor_name == "table" then + self:switch_insertion("in_select_in_table") + return + end + end end + self:switch_insertion("in_select") + return + elseif simple_modes[name] then + self:switch_insertion(simple_modes[name]) + return elseif last == true then self:switch_insertion("in_body") return @@ -2006,8 +2181,8 @@ function HtmlParser:generate_implied_endtags(included, ignored) local current = self:current_node() or {} -- keep removing elements while they are in the "included" list if included[current.tag] then - table.remove(self.unfinished) - self:generate_implied_endtags(ignored) + self:pop_element() + self:generate_implied_endtags(included, ignored) end end @@ -2023,9 +2198,7 @@ function HtmlParser:finish() self:start_tag("html") end while #self.unfinished > 0 do - local node = self:close_element() - local parent = self:get_parent() - parent:add_child(node) + self:pop_element() end -- return root element return self.Document -- self:close_element() diff --git a/macros/luatex/generic/luaxml/luaxml-namedentities.lua b/macros/luatex/generic/luaxml/luaxml-namedentities.lua index 0e6399ab13..5c5ff00777 100644 --- a/macros/luatex/generic/luaxml/luaxml-namedentities.lua +++ b/macros/luatex/generic/luaxml/luaxml-namedentities.lua @@ -1,2234 +1,2233 @@ -local utf8 = require "utf8" return { -["Subset"]="⋐", -["Chi"]="Χ", -["tprime"]="‴", -["lneq"]="⪇", -["RightUpTeeVector"]="⥜", -["cscr"]="𝒸", -["leftrightarrows"]="⇆", -["LeftRightVector"]="⥎", -["Laplacetrf"]="ℒ", -["boxHd"]="╤", -["GreaterSlantEqual"]="⩾", -["sqsub"]="⊏", -["nvdash"]="⊬", -["boxHu"]="╧", -["vcy"]="в", -["DiacriticalDoubleAcute"]="˝", -["nvHarr"]="⤄", -["lnapprox"]="⪉", -["fscr"]="𝒻", -["OverBracket"]="⎴", -["pm"]="±", -["ovbar"]="⌽", -["larrhk"]="↩", -["atilde"]="ã", -["Igrave"]="Ì", -["profsurf"]="⌓", -["Sigma"]="Σ", -["rHar"]="⥤", -["Gcedil"]="Ģ", -["sect"]="§", -["nmid"]="∤", -["escr"]="ℯ", -["delta"]="δ", -["male"]="♂", -["Integral"]="∫", -["RightUpVectorBar"]="⥔", -["alefsym"]="ℵ", -["nsqsube"]="⋢", -["Nacute"]="Ń", -["mcomma"]="⨩", -["ApplyFunction"]=utf8.char(0x2061), -["rfisht"]="⥽", -["phmmat"]="ℳ", -["rarrw"]="↝", -["backepsilon"]="϶", -["hscr"]="𝒽", -["middot"]="·", -["ldrushar"]="⥋", -["supne"]="⊋", -["Longleftrightarrow"]="⟺", -["Oacute"]="Ó", -["af"]="", +["Implies"]="⇒", +["longrightarrow"]="⟶", +["precneqq"]="⪵", +["geqslant"]="⩾", +["Product"]="∏", +["Scirc"]="Ŝ", +["lvnE"]="≨︀", +["dotminus"]="∸", +["sscr"]="𝓈", +["capdot"]="⩀", +["dlcrop"]="⌍", +["omacr"]="ō", +["sext"]="✶", +["xutri"]="△", +["xrArr"]="⟹", +["glE"]="⪒", +["NotSupersetEqual"]="⊉", +["backsim"]="∽", ["sup"]="⊃", -["lozenge"]="◊", -["scy"]="с", -["gscr"]="ℊ", -["smallsetminus"]="∖", +["realpart"]="ℜ", ["hardcy"]="ъ", -["DoubleVerticalBar"]="∥", -["Yuml"]="Ÿ", -["plusdu"]="⨥", -["NotSucceedsSlantEqual"]="⋡", -["nwnear"]="⤧", -["lfloor"]="⌊", -["rcy"]="р", -["jscr"]="𝒿", -["AMP"]="&", -["acute"]="´", -["uacute"]="ú", -["Or"]="⩔", -["rdldhar"]="⥩", -["langd"]="⦑", -["Iacute"]="Í", -["spar"]="∥", -["ucy"]="у", -["rsh"]="↱", -["Kcedil"]="Ķ", -["iscr"]="𝒾", -["lambda"]="λ", -["lbrkslu"]="⦍", -["napE"]="⩰̸", -["shcy"]="ш", -["nsupE"]="⫆̸", -["Ycirc"]="Ŷ", -["sect"]="§", -["precnapprox"]="⪹", -["iocy"]="ё", -["dzcy"]="џ", +["sqcap"]="⊓", +["brvbar"]="¦", +["LT"]="<", +["udarr"]="⇅", +["lozf"]="⧫", +["Eogon"]="Ę", +["frac18"]="⅛", +["lesssim"]="≲", +["wedbar"]="⩟", +["EmptyVerySmallSquare"]="▫", +["aring"]="å", +["lesdoto"]="⪁", +["ltquest"]="⩻", +["LeftUpTeeVector"]="⥠", +["FilledSmallSquare"]="◼", +["mho"]="℧", +["NotGreaterTilde"]="≵", +["xharr"]="⟷", +["NotSucceedsEqual"]="⪰̸", +["sqsupset"]="⊐", +["Ccedil"]="Ç", +["aacute"]="á", +["succcurlyeq"]="≽", +["gneq"]="⪈", +["forall"]="∀", +["rightharpoonup"]="⇀", +["leftarrow"]="←", +["ang"]="∠", +["mapstoup"]="↥", +["xscr"]="𝓍", +["NotTildeEqual"]="≄", +["ograve"]="ò", +["boxdl"]="┐", +["DownLeftVectorBar"]="⥖", +["nsup"]="⊅", +["shchcy"]="щ", +["demptyv"]="⦱", +["apos"]="'", +["between"]="≬", +["leftrightsquigarrow"]="↭", +["gtcc"]="⪧", +["grave"]="`", +["bigodot"]="⨀", +["oline"]="‾", +["angmsdad"]="⦫", +["NotCongruent"]="≢", +["gtquest"]="⩼", +["fltns"]="▱", +["smeparsl"]="⧤", +["Eta"]="Η", +["ltdot"]="⋖", +["rhard"]="⇁", +["rscr"]="𝓇", ["ETH"]="Ð", -["GreaterTilde"]="≳", -["coprod"]="∐", -["rpar"]=")", -["lthree"]="⋋", -["ImaginaryI"]="ⅈ", -["DoubleUpDownArrow"]="⇕", -["intercal"]="⊺", -["spadesuit"]="♠", -["boxVH"]="╬", -["smashp"]="⨳", -["nu"]="ν", -["Agrave"]="À", -["boxtimes"]="⊠", -["sext"]="✶", -["nsub"]="⊄", -["oelig"]="œ", -["GreaterEqual"]="≥", -["TRADE"]="™", -["dtrif"]="▾", -["nless"]="≮", -["mu"]="μ", -["larrsim"]="⥳", -["GreaterEqualLess"]="⋛", -["Uuml"]="Ü", -["LeftArrowBar"]="⇤", -["ntrianglerighteq"]="⋭", -["DiacriticalDot"]="˙", -["LongLeftArrow"]="⟵", -["agrave"]="à", -["lmoustache"]="⎰", -["nvDash"]="⊭", -["para"]="¶", -["nlt"]="≮", -["Eacute"]="É", -["spades"]="♠", -["lrcorner"]="⌟", -["checkmark"]="✓", -["lessdot"]="⋖", -["opar"]="⦷", -["nVDash"]="⊯", -["pertenk"]="‱", -["range"]="⦥", -["Pr"]="⪻", -["Gammad"]="Ϝ", -["ape"]="≊", -["Longleftarrow"]="⟸", -["boxV"]="║", -["rightthreetimes"]="⋌", +["iocy"]="ё", +["semi"]=";", +["nexists"]="∄", +["approxeq"]="≊", +["compfn"]="∘", +["sstarf"]="⋆", +["angrtvbd"]="⦝", ["gnap"]="⪊", -["vzigzag"]="⦚", -["Ecirc"]="Ê", -["npar"]="∦", -["notinvb"]="⋷", -["Tau"]="Τ", -["blank"]="␣", -["Kappa"]="Κ", -["rmoust"]="⎱", -["GJcy"]="Ѓ", -["ufisht"]="⥾", -["NotLeftTriangleBar"]="⧏̸", -["bigvee"]="⋁", -["lrhar"]="⇋", -["supset"]="⊃", -["uwangle"]="⦧", -["UpTeeArrow"]="↥", -["supE"]="⫆", -["imof"]="⊷", -["leg"]="⋚", -["notniva"]="∌", -["nvgt"]=">⃒", -["rthree"]="⋌", -["yfr"]="𝔶", -["uHar"]="⥣", -["nshortmid"]="∤", -["biguplus"]="⨄", -["barvee"]="⊽", -["iff"]="⇔", -["boxvH"]="╪", -["simrarr"]="⥲", -["Egrave"]="È", -["ntilde"]="ñ", -["VerticalTilde"]="≀", -["sigmaf"]="ς", -["khcy"]="х", -["planck"]="ℏ", -["NotNestedGreaterGreater"]="⪢̸", -["NonBreakingSpace"]=" ", -["OpenCurlyQuote"]="‘", -["supsim"]="⫈", -["cudarrl"]="⤸", -["theta"]="θ", -["notindot"]="⋵̸", -["Omicron"]="Ο", -["ccedil"]="ç", -["colone"]="≔", -["bscr"]="𝒷", -["Dagger"]="‡", -["comma"]=",", +["mDDot"]="∺", +["udblac"]="ű", ["Acirc"]="Â", -["plankv"]="ℏ", -["boxdr"]="┌", -["rarrap"]="⥵", -["rmoustache"]="⎱", -["LeftAngleBracket"]="⟨", -["Cacute"]="Ć", -["blk34"]="▓", -["rfloor"]="⌋", -["awconint"]="∳", -["sfrown"]="⌢", -["middot"]="·", -["ascr"]="𝒶", -["dot"]="˙", -["caron"]="ˇ", -["image"]="ℑ", -["esdot"]="≐", -["ohbar"]="⦵", -["rarrb"]="⇥", -["submult"]="⫁", -["plusb"]="⊞", -["oopf"]="𝕠", -["breve"]="˘", -["conint"]="∮", -["angrt"]="∟", -["nbump"]="≎̸", -["raquo"]="»", -["Iuml"]="Ï", -["Rcedil"]="Ŗ", -["minus"]="−", -["nsucceq"]="⪰̸", -["telrec"]="⌕", -["CHcy"]="Ч", -["nrightarrow"]="↛", -["NotRightTriangle"]="⋫", -["zfr"]="𝔷", -["succ"]="≻", -["Aacute"]="Á", -["NestedLessLess"]="≪", -["RightTeeArrow"]="↦", -["homtht"]="∻", -["Cup"]="⋓", -["lcub"]="{", -["race"]="∽̱", -["THORN"]="Þ", -["propto"]="∝", -["odblac"]="ő", -["mumap"]="⊸", -["filig"]="fi", -["ecir"]="≖", -["DoubleRightArrow"]="⇒", -["npreceq"]="⪯̸", -["female"]="♀", -["LeftFloor"]="⌊", -["gtrarr"]="⥸", -["dotsquare"]="⊡", -["map"]="↦", -["OverBrace"]="⏞", -["zopf"]="𝕫", -["rang"]="⟩", -["laquo"]="«", -["elsdot"]="⪗", -["frac56"]="⅚", -["Iuml"]="Ï", -["ocirc"]="ô", -["clubs"]="♣", -["IOcy"]="Ё", -["scnE"]="⪶", -["deg"]="°", -["simgE"]="⪠", -["nap"]="≉", -["blacktriangle"]="▴", -["edot"]="ė", -["epsiv"]="ϵ", -["napprox"]="≉", -["NotGreaterSlantEqual"]="⩾̸", -["prap"]="⪷", -["lnap"]="⪉", -["circledS"]="Ⓢ", -["lang"]="⟨", -["qprime"]="⁗", -["aelig"]="æ", -["ncongdot"]="⩭̸", -["supdsub"]="⫘", -["nltrie"]="⋬", -["xopf"]="𝕩", +["UnderParenthesis"]="⏝", +["nisd"]="⋺", +["lneq"]="⪇", +["Dagger"]="‡", +["qscr"]="𝓆", +["gneqq"]="≩", +["doteqdot"]="≑", +["DoubleVerticalBar"]="∥", +["emptyset"]="∅", +["lEg"]="⪋", +["subseteq"]="⊆", +["dwangle"]="⦦", +["dotplus"]="∔", +["NotPrecedesSlantEqual"]="⋠", +["bnot"]="⌐", ["LeftDownVector"]="⇃", -["duarr"]="⇵", -["urcorner"]="⌝", -["nvltrie"]="⊴⃒", -["Pi"]="Π", +["leg"]="⋚", +["Therefore"]="∴", +["Omega"]="Ω", +["acE"]="∾̳", +["Auml"]="Ä", +["xvee"]="⋁", ["Eacute"]="É", -["nGtv"]="≫̸", -["icirc"]="î", -["twoheadleftarrow"]="↞", +["LeftFloor"]="⌊", +["swnwar"]="⤪", +["Jukcy"]="Є", +["nless"]="≮", +["NotSquareSupersetEqual"]="⋣", +["larrfs"]="⤝", +["gcy"]="г", +["solbar"]="⌿", +["rharul"]="⥬", +["dscy"]="ѕ", +["yen"]="¥", +["ForAll"]="∀", +["DownArrow"]="↓", +["qprime"]="⁗", +["NegativeThickSpace"]="", +["part"]="∂", +["Iukcy"]="І", +["ltcc"]="⪦", +["xlArr"]="⟸", +["fcy"]="ф", +["gl"]="≷", +["rsh"]="↱", +["lrhar"]="⇋", ["divide"]="÷", -["yopf"]="𝕪", -["ntlg"]="≸", -["Darr"]="↡", +["bemptyv"]="⦰", +["rx"]="℞", +["ecy"]="э", +["ApplyFunction"]="", +["divideontimes"]="⋇", +["prod"]="∏", +["boxHU"]="╩", +["HARDcy"]="Ъ", +["mstpos"]="∾", +["llcorner"]="⌞", +["rsquor"]="’", +["NotTildeFullEqual"]="≇", +["mlcp"]="⫛", +["cemptyv"]="⦲", +["Proportional"]="∝", +["DiacriticalDoubleAcute"]="˝", +["dcy"]="д", +["Yacute"]="Ý", +["egsdot"]="⪘", ["hslash"]="ℏ", -["Coproduct"]="∐", -["profline"]="⌒", -["imagline"]="ℐ", -["chcy"]="ч", -["ccedil"]="ç", -["PrecedesEqual"]="⪯", -["jcirc"]="ĵ", -["nang"]="∠⃒", -["Icirc"]="Î", -["nbumpe"]="≏̸", -["incare"]="℅", -["tint"]="∭", -["nhArr"]="⇎", -["emsp13"]=" ", -["blacktriangleleft"]="◂", -["Star"]="⋆", -["hkswarow"]="⤦", -["NegativeThickSpace"]="", -["eDot"]="≑", -["Euml"]="Ë", -["scaron"]="š", -["RightDownVectorBar"]="⥕", -["cent"]="¢", -["jukcy"]="є", -["backsimeq"]="⋍", -["Ncy"]="Н", -["DD"]="ⅅ", -["circledast"]="⊛", -["ccirc"]="ĉ", -["rsaquo"]="›", -["YIcy"]="Ї", -["iquest"]="¿", -["NotExists"]="∄", -["iukcy"]="і", -["Tab"]=" ", -["Equilibrium"]="⇌", -["nLt"]="≪⃒", -["yen"]="¥", -["CircleDot"]="⊙", -["CircleMinus"]="⊖", -["topf"]="𝕥", -["equivDD"]="⩸", -["DoubleLeftRightArrow"]="⇔", -["ngsim"]="≵", -["upuparrows"]="⇈", -["ll"]="≪", -["cirscir"]="⧂", -["ShortLeftArrow"]="←", -["angmsdag"]="⦮", -["shortmid"]="∣", -["ngeqslant"]="⩾̸", -["subset"]="⊂", -["curvearrowleft"]="↶", -["gdot"]="ġ", -["circledcirc"]="⊚", -["Pcy"]="П", -["asymp"]="≈", -["boxUr"]="╙", -["uopf"]="𝕦", -["frac15"]="⅕", -["Iacute"]="Í", -["Utilde"]="Ũ", -["Congruent"]="≡", -["nhpar"]="⫲", -["capbrcup"]="⩉", -["ordf"]="ª", -["SOFTcy"]="Ь", -["nlArr"]="⇍", -["not"]="¬", -["ffllig"]="ffl", -["nprec"]="⊀", -["Hat"]="^", +["infin"]="∞", ["Auml"]="Ä", -["ntriangleleft"]="⋪", -["longmapsto"]="⟼", -["nvrtrie"]="⊵⃒", -["timesb"]="⊠", -["lsh"]="↰", -["Jcy"]="Й", -["gcirc"]="ĝ", -["Oacute"]="Ó", -["vartriangleright"]="⊳", -["NotRightTriangleEqual"]="⋭", -["Rightarrow"]="⇒", -["ast"]="*", -["hamilt"]="ℋ", -["Ncedil"]="Ņ", -["apE"]="⩰", -["macr"]="¯", -["cwconint"]="∲", -["Kcy"]="К", -["Ucirc"]="Û", -["hcirc"]="ĥ", -["yacy"]="я", -["uml"]="¨", -["popf"]="𝕡", -["bumpE"]="⪮", -["varnothing"]="∅", -["RightUpVector"]="↾", -["curren"]="¤", -["Scedil"]="Ş", -["FilledVerySmallSquare"]="▪", -["dollar"]="$", -["Lcy"]="Л", -["longrightarrow"]="⟶", -["LeftTee"]="⊣", -["excl"]="!", -["acirc"]="â", -["wp"]="℘", -["lcaron"]="ľ", -["NotGreaterFullEqual"]="≧̸", -["CounterClockwiseContourIntegral"]="∳", -["sup2"]="²", -["rnmid"]="⫮", -["Lcedil"]="Ļ", -["ddotseq"]="⩷", -["tbrk"]="⎴", -["mlcp"]="⫛", -["rarrhk"]="↪", -["Tilde"]="∼", -["Mcy"]="М", -["aring"]="å", -["rarrsim"]="⥴", -["nopf"]="𝕟", -["aelig"]="æ", -["order"]="ℴ", -["diamondsuit"]="♦", -["nvsim"]="∼⃒", -["lhard"]="↽", -["commat"]="@", -["qint"]="⨌", -["lsquo"]="‘", -["sqcaps"]="⊓︀", -["circlearrowleft"]="↺", -["NotElement"]="∉", -["measuredangle"]="∡", -["Atilde"]="Ã", -["CapitalDifferentialD"]="ⅅ", -["kgreen"]="ĸ", -["Cscr"]="𝒞", +["Wcirc"]="Ŵ", +["larrtl"]="↢", +["Aacute"]="Á", +["LeftTriangleEqual"]="⊴", +["NegativeMediumSpace"]="", +["TripleDot"]="⃛", +["utdot"]="⋰", +["isinv"]="∈", +["looparrowright"]="↬", +["loang"]="⟬", +["multimap"]="⊸", ["NotLessEqual"]="≰", -["trpezium"]="⏢", -["ne"]="≠", -["NotSuperset"]="⊃⃒", -["nearrow"]="↗", -["ncong"]="≇", -["doteqdot"]="≑", -["supmult"]="⫂", -["longleftrightarrow"]="⟷", -["Rarr"]="↠", -["DoubleUpArrow"]="⇑", -["Dscr"]="𝒟", -["mp"]="∓", -["jmath"]="ȷ", -["erarr"]="⥱", -["searrow"]="↘", -["Sup"]="⋑", -["lvnE"]="≨︀", -["ffilig"]="ffi", -["NotSquareSupersetEqual"]="⋣", -["bullet"]="•", -["bigstar"]="★", -["cylcty"]="⌭", -["nvle"]="≤⃒", -["TildeFullEqual"]="≅", -["lopf"]="𝕝", -["sqsupseteq"]="⊒", -["lt"]="<", -["geqslant"]="⩾", +["midcir"]="⫰", +["nge"]="≱", ["quot"]="\"", -["le"]="≤", -["square"]="□", -["sigma"]="σ", -["prE"]="⪳", -["rtrie"]="⊵", -["triangleq"]="≜", +["REG"]="®", +["div"]="÷", +["complexes"]="ℂ", +["lhblk"]="▄", +["gvnE"]="≩︀", +["leftharpoonup"]="↼", +["it"]="", +["clubsuit"]="♣", +["iff"]="⇔", +["Hacek"]="ˇ", +["CircleTimes"]="⊗", +["Cacute"]="Ć", +["rarrtl"]="↣", +["RightDownVector"]="⇂", +["rarrfs"]="⤞", +["UpArrowBar"]="⤒", +["male"]="♂", +["RightTriangle"]="⊳", +["GreaterTilde"]="≳", +["Barwed"]="⌆", +["ltlarr"]="⥶", +["Zdot"]="Ż", +["parsim"]="⫳", +["Ugrave"]="Ù", +["Dot"]="¨", +["circleddash"]="⊝", +["rsaquo"]="›", +["hyphen"]="‐", +["angrt"]="∟", +["RightTriangleEqual"]="⊵", +["Darr"]="↡", +["ulcrop"]="⌏", +["olcir"]="⦾", +["gimel"]="ℷ", +["gel"]="⋛", +["SquareSubset"]="⊏", +["Uacute"]="Ú", +["gt"]=">", +["lnap"]="⪉", +["Union"]="⋃", +["nu"]="ν", +["and"]="∧", +["ltcir"]="⩹", ["Fscr"]="ℱ", +["ee"]="ⅇ", +["laquo"]="«", +["Hfr"]="ℌ", +["prec"]="≺", +["imagline"]="ℐ", +["precnsim"]="⋨", +["zhcy"]="ж", +["mu"]="μ", +["rlarr"]="⇄", +["pound"]="£", +["origof"]="⊶", +["rfloor"]="⌋", +["lnsim"]="⋦", +["nVdash"]="⊮", +["otimes"]="⊗", +["iuml"]="ï", +["Cscr"]="𝒞", +["lsime"]="⪍", +["ngeqq"]="≧̸", +["Del"]="∇", +["Coproduct"]="∐", +["NotSubsetEqual"]="⊈", +["HilbertSpace"]="ℋ", +["frac58"]="⅝", +["cap"]="∩", +["roang"]="⟭", +["intlarhk"]="⨗", +["DownTee"]="⊤", +["thickapprox"]="≈", +["prnap"]="⪹", +["laquo"]="«", +["lesdot"]="⩿", +["inodot"]="ı", +["Hscr"]="ℋ", +["YIcy"]="Ї", +["ctdot"]="⋯", +["thetav"]="ϑ", +["DoubleUpDownArrow"]="⇕", +["succ"]="≻", +["nbumpe"]="≏̸", +["ReverseElement"]="∋", +["Oacute"]="Ó", +["equest"]="≟", +["Lt"]="≪", +["Nacute"]="Ń", ["DiacriticalTilde"]="˜", -["SucceedsSlantEqual"]="≽", -["mopf"]="𝕞", -["Ecaron"]="Ě", -["UpArrowDownArrow"]="⇅", -["ges"]="⩾", -["nsqsupe"]="⋣", -["ubrcy"]="ў", -["Gscr"]="𝒢", -["HARDcy"]="Ъ", -["jopf"]="𝕛", -["gtquest"]="⩼", -["iinfin"]="⧜", -["twixt"]="≬", +["Escr"]="ℰ", +["boxvH"]="╪", +["Ifr"]="ℑ", +["mp"]="∓", +["ell"]="ℓ", +["Iacute"]="Í", +["NotNestedGreaterGreater"]="⪢̸", +["raquo"]="»", +["Zcy"]="З", +["micro"]="µ", +["dzigrarr"]="⟿", +["rtrif"]="▸", +["Uuml"]="Ü", +["nvHarr"]="⤄", +["leqslant"]="⩽", +["tritime"]="⨻", +["nlarr"]="↚", +["NotRightTriangle"]="⋫", +["apid"]="≋", +["succeq"]="⪰", +["NotEqualTilde"]="≂̸", +["varphi"]="ϕ", +["Vert"]="‖", +["int"]="∫", +["lurdshar"]="⥊", +["lneqq"]="≨", +["Jsercy"]="Ј", +["Superset"]="⊃", +["subsetneqq"]="⫋", +["gap"]="⪆", +["ssmile"]="⌣", +["Ugrave"]="Ù", +["IOcy"]="Ё", +["ltimes"]="⋉", +["UnderBracket"]="⎵", +["subseteqq"]="⫅", +["Dscr"]="𝒟", +["dtrif"]="▾", +["raquo"]="»", +["hbar"]="ℏ", +["ge"]="≥", +["cudarrr"]="⤵", +["icy"]="и", +["plusdo"]="∔", +["bull"]="•", +["weierp"]="℘", +["mapsto"]="↦", +["Uring"]="Ů", +["supplus"]="⫀", +["Succeeds"]="≻", +["Ascr"]="𝒜", +["cdot"]="ċ", +["nwarr"]="↖", +["target"]="⌖", +["dharr"]="⇂", +["curlyvee"]="⋎", +["supE"]="⫆", +["emsp13"]=" ", ["ltrie"]="⊴", +["olarr"]="↺", +["RightTeeVector"]="⥛", +["Vvdash"]="⊪", +["larrsim"]="⥳", +["varsubsetneq"]="⊊︀", +["Not"]="⫬", +["CenterDot"]="·", +["PlusMinus"]="±", +["aring"]="å", +["Nscr"]="𝒩", +["delta"]="δ", +["npre"]="⪯̸", +["Vcy"]="В", +["NotVerticalBar"]="∤", +["scpolint"]="⨓", +["rcedil"]="ŗ", +["Lmidot"]="Ŀ", +["DScy"]="Ѕ", +["nsubseteq"]="⊈", +["ngE"]="≧̸", +["NotSquareSubsetEqual"]="⋢", +["edot"]="ė", +["Ucy"]="У", +["lessapprox"]="⪅", +["niv"]="∋", +["Kscr"]="𝒦", +["LeftVectorBar"]="⥒", +["nhpar"]="⫲", +["scedil"]="ş", +["Uacute"]="Ú", +["ntrianglelefteq"]="⋬", +["Otilde"]="Õ", +["iexcl"]="¡", +["lbrke"]="⦋", +["simdot"]="⩪", +["sigmaf"]="ς", +["Bfr"]="𝔅", +["pitchfork"]="⋔", +["ngeqslant"]="⩾̸", +["Pscr"]="𝒫", +["gsime"]="⪎", +["Ouml"]="Ö", +["rarrsim"]="⥴", +["subE"]="⫅", +["otimesas"]="⨶", +["lfloor"]="⌊", +["prop"]="∝", +["imacr"]="ī", +["blacktriangleleft"]="◂", +["Ntilde"]="Ñ", +["llarr"]="⇇", +["nsucc"]="⊁", +["PartialD"]="∂", +["Iacute"]="Í", +["gdot"]="ġ", +["Afr"]="𝔄", +["Igrave"]="Ì", ["csub"]="⫏", -["Hscr"]="ℋ", -["leftharpoondown"]="↽", +["Mscr"]="ℳ", +["Scy"]="С", +["bsime"]="⋍", +["nequiv"]="≢", +["scnap"]="⪺", +["Tab"]=" ", +["Equal"]="⩵", +["blacklozenge"]="⧫", +["nrarrc"]="⤳̸", +["divide"]="÷", ["RightUpDownVector"]="⥏", -["LongLeftRightArrow"]="⟷", -["Im"]="ℑ", -["dcaron"]="ď", +["iinfin"]="⧜", +["precnapprox"]="⪹", +["dArr"]="⇓", +["orslope"]="⩗", +["Rcy"]="Р", +["sqsub"]="⊏", +["OverBracket"]="⎴", +["sum"]="∑", +["ncedil"]="ņ", +["ltrPar"]="⦖", +["ii"]="ⅈ", +["Gcirc"]="Ĝ", +["SucceedsTilde"]="≿", +["RightFloor"]="⌋", +["osol"]="⊘", ["barwedge"]="⌅", -["nexist"]="∄", -["blacktriangledown"]="▾", -["fork"]="⋔", -["rhard"]="⇁", -["cent"]="¢", -["RightTriangle"]="⊳", -["Eta"]="Η", -["dotminus"]="∸", -["nles"]="⩽̸", -["larrtl"]="↢", -["LeftTriangleEqual"]="⊴", -["hopf"]="𝕙", -["gammad"]="ϝ", -["gsime"]="⪎", -["llhard"]="⥫", -["precapprox"]="⪷", -["profalar"]="⌮", -["lnE"]="≨", -["ddagger"]="‡", -["leq"]="≤", -["smile"]="⌣", -["robrk"]="⟧", -["Jscr"]="𝒥", -["triangleleft"]="◃", -["acd"]="∿", -["prod"]="∏", -["atilde"]="ã", -["seArr"]="⇘", -["therefore"]="∴", -["iopf"]="𝕚", -["solbar"]="⌿", -["kcedil"]="ķ", -["NotHumpEqual"]="≏̸", -["nspar"]="∦", -["frac14"]="¼", -["nsime"]="≄", -["DoubleLongLeftArrow"]="⟸", -["sccue"]="≽", -["models"]="⊧", -["SupersetEqual"]="⊇", -["iquest"]="¿", -["oline"]="‾", -["lparlt"]="⦓", -["triplus"]="⨹", -["nequiv"]="≢", -["nlE"]="≦̸", -["nldr"]="‥", -["equals"]="=", -["Agrave"]="À", -["ccaron"]="č", -["Yacute"]="Ý", -["Oslash"]="Ø", -["udarr"]="⇅", -["ang"]="∠", -["dopf"]="𝕕", -["comp"]="∁", -["caps"]="∩︀", -["bowtie"]="⋈", -["glj"]="⪤", -["ltquest"]="⩻", -["cirmid"]="⫯", -["ordm"]="º", -["esim"]="≂", -["reals"]="ℝ", -["LeftTriangle"]="⊲", -["flat"]="♭", -["eopf"]="𝕖", -["lap"]="⪅", -["not"]="¬", -["ENG"]="Ŋ", -["DiacriticalAcute"]="´", -["sharp"]="♯", -["longleftarrow"]="⟵", -["dblac"]="˝", -["UpArrow"]="↑", -["npre"]="⪯̸", -["bopf"]="𝕓", -["DScy"]="Ѕ", +["twoheadrightarrow"]="↠", +["Gscr"]="𝒢", +["acy"]="а", +["dtdot"]="⋱", +["rbrke"]="⦌", +["imath"]="ı", +["Hcirc"]="Ĥ", +["num"]="#", +["nprec"]="⊀", +["smallsetminus"]="∖", +["lesges"]="⪓", +["LeftUpVector"]="↿", +["gtdot"]="⋗", +["theta"]="θ", +["kappav"]="ϰ", +["jmath"]="ȷ", +["Lscr"]="ℒ", +["Aogon"]="Ą", +["ltrif"]="◂", +["DownArrowUpArrow"]="⇵", +["prap"]="⪷", +["Racute"]="Ŕ", +["curlyeqprec"]="⋞", ["bepsi"]="϶", -["angrtvb"]="⊾", -["ccaps"]="⩍", -["UnderParenthesis"]="⏝", -["subne"]="⊊", -["succnsim"]="⋩", -["Bumpeq"]="≎", -["xvee"]="⋁", -["colon"]=":", -["deg"]="°", -["fnof"]="ƒ", -["Uarr"]="↟", -["Zcaron"]="Ž", -["copf"]="𝕔", -["Theta"]="Θ", -["omicron"]="ο", -["ntriangleright"]="⋫", -["DoubleLongRightArrow"]="⟹", -["UnderBrace"]="⏟", -["GT"]=">", -["lEg"]="⪋", -["supplus"]="⫀", -["acute"]="´", +["blacktriangle"]="▴", +["nvap"]="≍⃒", +["Supset"]="⋑", +["angmsd"]="∡", +["boxul"]="┘", +["LessSlantEqual"]="⩽", ["GT"]=">", -["upsilon"]="υ", -["sc"]="≻", -["xrarr"]="⟶", -["eng"]="ŋ", -["it"]="", -["Ntilde"]="Ñ", -["Mu"]="Μ", -["CircleTimes"]="⊗", -["NotTildeTilde"]="≉", -["NotLessLess"]="≪̸", -["vellip"]="⋮", -["cularrp"]="⤽", -["UnderBracket"]="⎵", -["aopf"]="𝕒", -["itilde"]="ĩ", -["latail"]="⤙", -["Nu"]="Ν", -["Ascr"]="𝒜", -["complement"]="∁", -["gjcy"]="ѓ", -["radic"]="√", -["maltese"]="✠", -["glE"]="⪒", -["plusmn"]="±", -["curvearrowright"]="↷", -["gt"]=">", -["Colone"]="⩴", -["Bscr"]="ℬ", -["ic"]="", -["clubsuit"]="♣", -["djcy"]="ђ", -["Oopf"]="𝕆", -["ltrPar"]="⦖", -["ngtr"]="≯", -["eqcirc"]="≖", -["Hacek"]="ˇ", -["vdash"]="⊢", -["NotCupCap"]="≭", -["Gdot"]="Ġ", -["jsercy"]="ј", -["marker"]="▮", +["nexist"]="∄", +["ccupssm"]="⩐", +["Eacute"]="É", +["ddarr"]="⇊", +["ntlg"]="≸", +["Iscr"]="ℐ", +["Jcirc"]="Ĵ", +["Sacute"]="Ś", +["capand"]="⩄", +["gesdoto"]="⪂", +["olcross"]="⦻", +["amalg"]="⨿", +["rarrlp"]="↬", +["NotLeftTriangle"]="⋪", +["reals"]="ℝ", +["bigcup"]="⋃", +["NJcy"]="Њ", +["Odblac"]="Ő", +["hArr"]="⇔", +["RightArrowLeftArrow"]="⇄", +["SOFTcy"]="Ь", +["Lambda"]="Λ", +["RightCeiling"]="⌉", +["Vdash"]="⊩", +["elinters"]="⏧", +["lsimg"]="⪏", ["Nopf"]="ℕ", -["Wfr"]="𝔚", -["boxHD"]="╦", -["mho"]="℧", -["ulcrop"]="⌏", -["DifferentialD"]="ⅆ", -["aacute"]="á", -["lpar"]="(", +["Esim"]="⩳", +["vzigzag"]="⦚", +["acd"]="∿", +["ccedil"]="ç", +["lbarr"]="⤌", +["nmid"]="∤", +["Backslash"]="∖", +["Laplacetrf"]="ℒ", +["npr"]="⊀", +["nap"]="≉", +["nsupseteqq"]="⫆̸", +["igrave"]="ì", +["LJcy"]="Љ", +["lessgtr"]="≶", ["angle"]="∠", -["rharu"]="⇀", -["Breve"]="˘", -["Dot"]="¨", -["rect"]="▭", -["NotNestedLessLess"]="⪡̸", -["boxplus"]="⊞", -["NotSucceeds"]="⊁", -["gnapprox"]="⪊", -["DownLeftTeeVector"]="⥞", -["Xfr"]="𝔛", -["Lang"]="⟪", -["Element"]="∈", -["sung"]="♪", -["RightVectorBar"]="⥓", -["simne"]="≆", -["LeftVector"]="↼", -["Idot"]="İ", +["lAarr"]="⇚", +["notin"]="∉", +["orv"]="⩛", +["gtreqqless"]="⪌", +["CircleMinus"]="⊖", +["Diamond"]="⋄", +["map"]="↦", +["nvsim"]="∼⃒", +["pi"]="π", +["pluscir"]="⨢", +["boxVH"]="╬", ["QUOT"]="\"", -["nsmid"]="∤", -["fjlig"]="fj", -["Ufr"]="𝔘", -["cuvee"]="⋎", +["duarr"]="⇵", +["lgE"]="⪑", +["lmoust"]="⎰", +["lsquo"]="‘", +["rightrightarrows"]="⇉", +["times"]="×", +["iuml"]="ï", +["andslope"]="⩘", +["order"]="ℴ", +["Sub"]="⋐", +["capcap"]="⩋", +["nabla"]="∇", +["ntriangleleft"]="⋪", +["blk14"]="░", +["Kopf"]="𝕂", +["lArr"]="⇐", +["Qopf"]="ℚ", +["circledS"]="Ⓢ", +["omid"]="⦶", +["ord"]="⩝", +["lvertneqq"]="≨︀", +["updownarrow"]="↕", +["yacute"]="ý", +["ni"]="∋", +["hamilt"]="ℋ", +["Jopf"]="𝕁", +["CupCap"]="≍", +["lbrack"]="[", +["preccurlyeq"]="≼", +["Ropf"]="ℝ", +["lessdot"]="⋖", +["blank"]="␣", +["SucceedsEqual"]="⪰", +["triangleleft"]="◃", +["ring"]="˚", +["omega"]="ω", +["bowtie"]="⋈", +["Sqrt"]="√", +["uuml"]="ü", +["Udblac"]="Ű", +["diams"]="♦", +["Oslash"]="Ø", ["real"]="ℜ", -["luruhar"]="⥦", -["NotRightTriangleBar"]="⧐̸", -["target"]="⌖", -["lharu"]="↼", -["CloseCurlyQuote"]="’", -["rAtail"]="⤜", -["nparallel"]="∦", -["brvbar"]="¦", -["Vfr"]="𝔙", -["wedbar"]="⩟", -["REG"]="®", -["boxur"]="└", -["Rcaron"]="Ř", -["Rang"]="⟫", -["sqsubseteq"]="⊑", -["div"]="÷", -["boxul"]="┘", -["Cdot"]="Ċ", -["vsupnE"]="⫌︀", -["zeetrf"]="ℨ", -["Sfr"]="𝔖", -["roang"]="⟭", -["LessTilde"]="≲", -["equiv"]="≡", -["frac12"]="½", -["eacute"]="é", -["rrarr"]="⇉", -["nearhk"]="⤤", -["Zopf"]="ℤ", -["SucceedsTilde"]="≿", +["egrave"]="è", +["prurel"]="⊰", +["LeftUpDownVector"]="⥑", +["TildeEqual"]="≃", +["cuwed"]="⋏", +["times"]="×", ["ap"]="≈", -["lfisht"]="⥼", -["timesd"]="⨰", -["UpDownArrow"]="↕", -["xuplus"]="⨄", -["cularr"]="↶", -["iprod"]="⨼", -["AElig"]="Æ", -["rationals"]="ℚ", -["geqq"]="≧", -["Tfr"]="𝔗", -["Yopf"]="𝕐", -["rtimes"]="⋊", -["Tcaron"]="Ť", -["srarr"]="→", -["diam"]="⋄", -["mid"]="∣", -["imath"]="ı", -["PlusMinus"]="±", -["isin"]="∈", -["vprop"]="∝", -["RightArrowLeftArrow"]="⇄", -["NotSubset"]="⊂⃒", -["bigtriangledown"]="▽", -["ldsh"]="↲", -["Qfr"]="𝔔", -["nvap"]="≍⃒", -["vert"]="|", -["Xopf"]="𝕏", -["lBarr"]="⤎", -["egsdot"]="⪘", -["Tcedil"]="Ţ", -["xi"]="ξ", -["LeftUpVectorBar"]="⥘", -["circ"]="ˆ", -["ocir"]="⊚", -["gtlPar"]="⦕", -["Rfr"]="ℜ", -["RightTriangleBar"]="⧐", -["nwarhk"]="⤣", -["zhcy"]="ж", -["Iukcy"]="І", -["plusdo"]="∔", +["lowast"]="∗", +["Lopf"]="𝕃", +["bdquo"]="„", +["blacktriangledown"]="▾", +["vBarv"]="⫩", +["Longleftarrow"]="⟸", +["lesg"]="⋚︀", +["Popf"]="ℙ", +["iogon"]="į", +["vellip"]="⋮", +["Ntilde"]="Ñ", +["cwconint"]="∲", ["boxv"]="│", -["minusb"]="⊟", -["Ncaron"]="Ň", -["angmsdaa"]="⦨", -["varsubsetneqq"]="⫋︀", -["cirfnint"]="⨐", -["LongRightArrow"]="⟶", -["ddarr"]="⇊", -["piv"]="ϖ", -["fopf"]="𝕗", -["Ofr"]="𝔒", -["fflig"]="ff", -["Jukcy"]="Є", -["xhArr"]="⟺", -["ncy"]="н", -["Scaron"]="Š", -["TildeEqual"]="≃", -["subrarr"]="⥹", -["iacute"]="í", -["ogt"]="⧁", -["nvge"]="≥⃒", -["vee"]="∨", -["UnderBar"]="_", -["andslope"]="⩘", -["gopf"]="𝕘", -["Pfr"]="𝔓", -["die"]="¨", +["boxbox"]="⧉", +["langd"]="⦑", +["diam"]="⋄", +["boxHu"]="╧", +["acute"]="´", ["Uopf"]="𝕌", +["Fcy"]="Ф", +["vee"]="∨", +["eqslantless"]="⪕", +["NotLeftTriangleEqual"]="⋬", +["OverBrace"]="⏞", +["beta"]="β", +["Otilde"]="Õ", +["fjlig"]="fj", +["uacute"]="ú", +["CirclePlus"]="⊕", +["Mellintrf"]="ℳ", +["Vopf"]="𝕍", +["Gcy"]="Г", +["searhk"]="⤥", +["boxur"]="└", +["LeftTeeVector"]="⥚", +["nsubE"]="⫅̸", +["gvertneqq"]="≩︀", +["eqcirc"]="≖", +["nrightarrow"]="↛", +["DJcy"]="Ђ", +["tdot"]="⃛", +["Dcy"]="Д", +["Sopf"]="𝕊", +["range"]="⦥", +["agrave"]="à", +["gtrsim"]="≳", ["RightArrowBar"]="⇥", -["orarr"]="↻", -["Precedes"]="≺", -["oror"]="⩖", -["straightepsilon"]="ϵ", -["cong"]="≅", -["TScy"]="Ц", -["nleftarrow"]="↚", -["DZcy"]="Џ", -["horbar"]="―", +["larrlp"]="↫", +["le"]="≤", +["xi"]="ξ", +["gla"]="⪥", +["GT"]=">", +["leftarrowtail"]="↢", +["commat"]="@", +["rightarrowtail"]="↣", +["approx"]="≈", +["sdot"]="⋅", ["Topf"]="𝕋", -["Cayleys"]="ℭ", -["leqq"]="≦", -["curlyeqprec"]="⋞", -["nLeftarrow"]="⇍", -["pcy"]="п", -["realine"]="ℛ", -["nlsim"]="≴", +["Ecy"]="Э", +["eplus"]="⩱", +["cir"]="○", ["Rarrtl"]="⤖", -["CupCap"]="≍", -["vDash"]="⊨", -["shortparallel"]="∥", -["ExponentialE"]="ⅇ", -["Sopf"]="𝕊", -["iiota"]="℩", -["Nfr"]="𝔑", -["pointint"]="⨕", -["NotGreaterLess"]="≹", -["olcross"]="⦻", -["kcy"]="к", -["complexes"]="ℂ", -["varepsilon"]="ϵ", -["Fouriertrf"]="ℱ", -["rho"]="ρ", -["Lsh"]="↰", -["exponentiale"]="ⅇ", -["hookrightarrow"]="↪", -["Ropf"]="ℝ", -["lAtail"]="⤛", -["Kfr"]="𝔎", -["bsim"]="∽", -["jcy"]="й", -["frac34"]="¾", -["DotDot"]="⃜", +["Emacr"]="Ē", +["Dcaron"]="Ď", +["Sc"]="⪼", +["cent"]="¢", +["rtri"]="▹", +["cedil"]="¸", +["spades"]="♠", +["upsilon"]="υ", +["boxminus"]="⊟", +["angmsdaa"]="⦨", +["zdot"]="ż", +["Bcy"]="Б", +["Zscr"]="𝒵", +["looparrowleft"]="↫", +["Dfr"]="𝔇", +["Bumpeq"]="≎", +["nLeftarrow"]="⇍", +["equiv"]="≡", +["Ccaron"]="Č", +["UpperLeftArrow"]="↖", +["SubsetEqual"]="⊆", +["nrArr"]="⇏", +["loarr"]="⇽", +["minusdu"]="⨪", +["sup3"]="³", +["Zopf"]="ℤ", +["elsdot"]="⪗", +["NotLessLess"]="≪̸", +["eta"]="η", +["ubrcy"]="ў", +["Yscr"]="𝒴", +["subset"]="⊂", +["Cfr"]="ℭ", +["harrcir"]="⥈", +["supsetneq"]="⊋", +["LeftUpVectorBar"]="⥘", +["LT"]="<", +["DoubleLeftArrow"]="⇐", +["circledcirc"]="⊚", +["bkarow"]="⤍", +["rangd"]="⦒", +["downharpoonright"]="⇂", +["Wopf"]="𝕎", +["ast"]="*", +["planck"]="ℏ", +["gtrdot"]="⋗", +["Ffr"]="𝔉", +["rArr"]="⇒", +["VeryThinSpace"]=" ", +["Ecaron"]="Ě", +["RightVectorBar"]="⥓", +["divonx"]="⋇", +["Xopf"]="𝕏", +["nsubset"]="⊂⃒", +["Otimes"]="⨷", +["bot"]="⊥", +["nsime"]="≄", ["thorn"]="þ", -["ThickSpace"]=" ", -["SquareUnion"]="⊔", -["frac58"]="⅝", -["dfisht"]="⥿", -["MediumSpace"]=" ", -["Lfr"]="𝔏", -["Qopf"]="ℚ", +["subsetneq"]="⊊", +["nltri"]="⋪", +["Cayleys"]="ℭ", +["Efr"]="𝔈", +["Intersection"]="⋂", +["UnderBar"]="_", +["fpartint"]="⨍", +["Iuml"]="Ï", +["rsquo"]="’", +["ecir"]="≖", +["nis"]="⋼", +["fscr"]="𝒻", +["hellip"]="…", +["ogt"]="⧁", ["ntgl"]="≹", -["LessFullEqual"]="≦", -["malt"]="✠", -["mcy"]="м", -["NotGreaterEqual"]="≱", -["bottom"]="⊥", -["NotSucceedsEqual"]="⪰̸", -["lcedil"]="ļ", -["infintie"]="⧝", -["Lcaron"]="Ľ", -["NotSquareSubset"]="⊏̸", -["brvbar"]="¦", -["fallingdotseq"]="≒", -["AElig"]="Æ", -["swarhk"]="⤦", -["Ifr"]="ℑ", -["pi"]="π", -["lcy"]="л", -["copy"]="©", -["dlcorn"]="⌞", -["oacute"]="ó", -["gtreqless"]="⋛", -["neArr"]="⇗", +["frac14"]="¼", +["squf"]="▪", +["circ"]="ˆ", +["prE"]="⪳", +["ordf"]="ª", ["ZHcy"]="Ж", -["Vdashl"]="⫦", -["darr"]="↓", -["circeq"]="≗", +["NegativeVeryThinSpace"]="", +["quot"]="\"", +["excl"]="!", +["sqcaps"]="⊓︀", +["gfr"]="𝔤", +["varsigma"]="ς", +["nwarrow"]="↖", +["reg"]="®", +["longmapsto"]="⟼", +["And"]="⩓", +["cuvee"]="⋎", +["zwj"]="", +["plankv"]="ℏ", +["varepsilon"]="ϵ", +["Aopf"]="𝔸", +["UpTee"]="⊥", +["lescc"]="⪨", +["ltri"]="◃", +["iiint"]="∭", +["ccups"]="⩌", +["alefsym"]="ℵ", +["succneqq"]="⪶", +["hscr"]="𝒽", +["Or"]="⩔", ["yuml"]="ÿ", -["Jfr"]="𝔍", -["Product"]="∏", -["boxDL"]="╗", -["el"]="⪙", -["supe"]="⊇", -["frac13"]="⅓", -["Barwed"]="⌆", -["larrpl"]="⤹", -["SHCHcy"]="Щ", -["LeftUpDownVector"]="⥑", -["Diamond"]="⋄", -["DownLeftVectorBar"]="⥖", -["Cross"]="⨯", -["ncup"]="⩂", -["supnE"]="⫌", -["lne"]="⪇", -["micro"]="µ", -["lowbar"]="_", -["perp"]="⊥", -["sqcap"]="⊓", -["Gfr"]="𝔊", -["raemptyv"]="⦳", -["gesl"]="⋛︀", -["drcrop"]="⌌", -["boxUL"]="╝", -["becaus"]="∵", -["gne"]="⪈", -["scap"]="⪸", -["swarrow"]="↙", -["nesim"]="≂̸", -["DoubleDot"]="¨", -["Mopf"]="𝕄", -["apid"]="≋", -["InvisibleComma"]="", -["Backslash"]="∖", -["mnplus"]="∓", -["niv"]="∋", -["Hfr"]="ℌ", -["rarrlp"]="↬", -["Because"]="∵", -["parsl"]="⫽", -["sup1"]="¹", -["Lt"]="≪", -["par"]="∥", -["Iota"]="Ι", -["beth"]="ℶ", -["Lopf"]="𝕃", +["rcub"]="}", +["lt"]="<", +["vArr"]="⇕", +["EqualTilde"]="≂", +["vDash"]="⊨", +["RightArrow"]="→", +["dlcorn"]="⌞", +["Barv"]="⫧", +["nsc"]="⊁", +["Proportion"]="∷", +["iota"]="ι", +["gscr"]="ℊ", +["abreve"]="ă", +["ThickSpace"]=" ", +["szlig"]="ß", +["lhard"]="↽", +["emptyv"]="∅", +["Tau"]="Τ", +["sharp"]="♯", +["bNot"]="⫭", +["LongLeftRightArrow"]="⟷", +["frac23"]="⅔", +["NotEqual"]="≠", +["scE"]="⪴", +["jfr"]="𝔧", +["bscr"]="𝒷", +["uhblk"]="▀", +["frac35"]="⅗", +["TSHcy"]="Ћ", +["ntrianglerighteq"]="⋭", +["Tcedil"]="Ţ", +["NotGreaterFullEqual"]="≧̸", +["asympeq"]="≍", +["oror"]="⩖", +["ecirc"]="ê", +["ohbar"]="⦵", +["Rho"]="Ρ", +["iacute"]="í", +["ascr"]="𝒶", +["RightUpVector"]="↾", +["Ocirc"]="Ô", +["cedil"]="¸", +["sect"]="§", +["angmsdab"]="⦩", +["FilledVerySmallSquare"]="▪", +["curlywedge"]="⋏", +["lesdotor"]="⪃", +["esdot"]="≐", +["eqvparsl"]="⧥", ["Cap"]="⋒", -["Aring"]="Å", -["rarr"]="→", -["Efr"]="𝔈", -["bigcup"]="⋃", -["DownLeftRightVector"]="⥐", -["lesges"]="⪓", -["NegativeThinSpace"]="", -["DownRightTeeVector"]="⥟", -["npolint"]="⨔", -["gEl"]="⪌", -["lltri"]="◺", -["ogon"]="˛", -["LessEqualGreater"]="⋚", -["sqsupset"]="⊐", -["NotSubsetEqual"]="⊈", -["Ubrcy"]="Ў", -["ShortDownArrow"]="↓", -["ugrave"]="ù", -["Dcaron"]="Ď", -["subE"]="⫅", -["divide"]="÷", -["bigotimes"]="⨂", -["dscy"]="ѕ", -["wreath"]="≀", -["Jopf"]="𝕁", -["pre"]="⪯", -["tdot"]="⃛", -["Cfr"]="ℭ", -["Uogon"]="Ų", -["softcy"]="ь", -["isinE"]="⋹", -["Dstrok"]="Đ", -["Jsercy"]="Ј", -["capdot"]="⩀", -["realpart"]="ℜ", -["hearts"]="♥", -["Atilde"]="Ã", -["LeftArrowRightArrow"]="⇆", -["upharpoonleft"]="↿", -["Iopf"]="𝕀", -["Intersection"]="⋂", -["midcir"]="⫰", -["ocirc"]="ô", -["sdot"]="⋅", -["Dfr"]="𝔇", -["gla"]="⪥", -["DiacriticalGrave"]="`", +["dscr"]="𝒹", +["rbrace"]="}", +["nsccue"]="⋡", +["neArr"]="⇗", +["rightthreetimes"]="⋌", +["plusmn"]="±", ["Ubreve"]="Ŭ", -["int"]="∫", -["PrecedesSlantEqual"]="≼", -["Square"]="□", -["Acy"]="А", +["ifr"]="𝔦", +["Poincareplane"]="ℌ", +["leftrightarrows"]="⇆", +["scnsim"]="⋩", +["cscr"]="𝒸", +["NotHumpEqual"]="≏̸", +["capbrcup"]="⩉", +["curarr"]="↷", +["notinvb"]="⋷", +["LeftArrow"]="←", +["Gopf"]="𝔾", +["ldrushar"]="⥋", +["nscr"]="𝓃", +["Gg"]="⋙", +["ouml"]="ö", +["nsce"]="⪰̸", +["cupbrcap"]="⩈", +["nLt"]="≪⃒", +["bullet"]="•", +["nsqsupe"]="⋣", +["rect"]="▭", +["lbrace"]="{", +["Fopf"]="𝔽", +["COPY"]="©", +["epar"]="⋕", +["mscr"]="𝓂", +["odsold"]="⦼", +["cupor"]="⩅", +["not"]="¬", +["subsim"]="⫇", +["hoarr"]="⇿", +["Scedil"]="Ş", +["eacute"]="é", +["emsp"]=" ", +["uml"]="¨", +["igrave"]="ì", +["pscr"]="𝓅", +["LeftTee"]="⊣", +["Cedilla"]="¸", +["Iopf"]="𝕀", +["HumpEqual"]="≏", +["les"]="⩽", +["Rcedil"]="Ŗ", +["lsquor"]="‚", +["raemptyv"]="⦳", +["NotSucceedsSlantEqual"]="⋡", +["SuchThat"]="∋", +["vert"]="|", +["backcong"]="≌", ["Hopf"]="ℍ", -["precsim"]="≾", -["nleq"]="≰", -["urcorn"]="⌝", -["hyphen"]="‐", -["FilledSmallSquare"]="◼", -["zdot"]="ż", -["ndash"]="–", -["hbar"]="ℏ", -["Wopf"]="𝕎", -["Esim"]="⩳", -["subsetneq"]="⊊", -["boxhD"]="╥", -["searhk"]="⤥", -["late"]="⪭", +["CircleDot"]="⊙", +["Kappa"]="Κ", +["conint"]="∮", +["DZcy"]="Џ", +["prsim"]="≾", +["Copf"]="ℂ", +["curvearrowright"]="↷", +["twixt"]="≬", +["curren"]="¤", +["rtriltri"]="⧎", +["jscr"]="𝒿", +["cupcup"]="⩊", +["Lcedil"]="Ļ", +["supseteqq"]="⫆", +["bfr"]="𝔟", +["lesseqqgtr"]="⪋", +["leftleftarrows"]="⇇", +["Bopf"]="𝔹", +["acute"]="´", ["blacktriangleright"]="▸", -["auml"]="ä", -["NotLessTilde"]="≴", -["Bfr"]="𝔅", -["grave"]="`", -["ltlarr"]="⥶", -["Aogon"]="Ą", -["sdote"]="⩦", -["gtrsim"]="≳", -["nvinfin"]="⧞", -["lgE"]="⪑", -["mdash"]="—", -["Vopf"]="𝕍", -["leftrightarrow"]="↔", -["RBarr"]="⤐", -["amalg"]="⨿", -["preccurlyeq"]="≼", -["EqualTilde"]="≂", -["scpolint"]="⨓", -["NotHumpDownHump"]="≎̸", -["uparrow"]="↑", -["downarrow"]="↓", -["boxdL"]="╕", -["Hstrok"]="Ħ", -["Ccaron"]="Č", -["succsim"]="≿", -["RightFloor"]="⌋", -["DownBreve"]="̑", -["succapprox"]="⪸", -["dsol"]="⧶", -["napid"]="≋̸", -["nprcue"]="⋠", +["frac34"]="¾", +["Gbreve"]="Ğ", +["Updownarrow"]="⇕", +["iscr"]="𝒾", +["sigmav"]="ς", +["trade"]="™", +["minusb"]="⊟", +["GJcy"]="Ѓ", +["TildeFullEqual"]="≅", +["DoubleRightTee"]="⊨", +["nang"]="∠⃒", +["ddotseq"]="⩷", +["copy"]="©", ["Eopf"]="𝔼", -["ell"]="ℓ", -["cupdot"]="⊍", -["Not"]="⫬", -["zigrarr"]="⇝", -["downharpoonright"]="⇂", -["nisd"]="⋺", -["lotimes"]="⨴", -["plusmn"]="±", -["ngE"]="≧̸", -["odash"]="⊝", -["emptyset"]="∅", +["Psi"]="Ψ", +["UpperRightArrow"]="↗", +["geqq"]="≧", +["subedot"]="⫃", +["nvlArr"]="⤂", +["Ncedil"]="Ņ", +["vsupne"]="⊋︀", +["supset"]="⊃", ["squarf"]="▪", -["NotGreaterTilde"]="≵", -["NotTildeFullEqual"]="≇", -["DownArrowUpArrow"]="⇵", -["nwarrow"]="↖", -["looparrowright"]="↬", +["LeftDoubleBracket"]="⟦", +["utrif"]="▴", ["Dopf"]="𝔻", -["oplus"]="⊕", -["UpEquilibrium"]="⥮", -["leftthreetimes"]="⋋", -["DoubleLeftTee"]="⫤", -["nabla"]="∇", -["RuleDelayed"]="⧴", -["euml"]="ë", -["varsupsetneqq"]="⫌︀", -["upsi"]="υ", -["supsup"]="⫖", -["bsol"]="\\", -["Copf"]="ℂ", -["DDotrahd"]="⤑", -["Upsilon"]="Υ", -["UpperRightArrow"]="↗", -["nedot"]="≐̸", -["NotEqual"]="≠", -["bumpeq"]="≏", -["emsp14"]=" ", -["frac38"]="⅜", -["DownTeeArrow"]="↧", -["Bopf"]="𝔹", -["capand"]="⩄", -["nleqq"]="≦̸", -["ratio"]="∶", -["eplus"]="⩱", -["nge"]="≱", -["laquo"]="«", -["urtri"]="◹", -["LeftUpVector"]="↿", -["gl"]="≷", -["Gt"]="≫", -["andd"]="⩜", +["ape"]="≊", +["gEl"]="⪌", +["COPY"]="©", +["afr"]="𝔞", +["Acy"]="А", +["ldquor"]="„", +["because"]="∵", +["Pr"]="⪻", +["OverBar"]="‾", +["lang"]="⟨", +["mopf"]="𝕞", +["crarr"]="↵", +["Epsilon"]="Ε", +["Nfr"]="𝔑", +["kjcy"]="ќ", +["TildeTilde"]="≈", +["bsim"]="∽", +["lcy"]="л", +["larrb"]="⇤", +["ncong"]="≇", +["ENG"]="Ŋ", +["brvbar"]="¦", +["Rightarrow"]="⇒", +["nopf"]="𝕟", +["Wfr"]="𝔚", +["ljcy"]="љ", +["diamondsuit"]="♦", +["latail"]="⤙", +["lambda"]="λ", +["frac14"]="¼", +["mcy"]="м", +["nparsl"]="⫽⃥", +["lBarr"]="⤎", +["subdot"]="⪽", +["frac12"]="½", +["kopf"]="𝕜", +["LeftCeiling"]="⌈", +["erarr"]="⥱", +["pre"]="⪯", +["varr"]="↕", +["Pi"]="Π", +["sub"]="⊂", +["ncy"]="н", +["marker"]="▮", +["rpargt"]="⦔", +["supe"]="⊇", +["veebar"]="⊻", +["checkmark"]="✓", +["nbsp"]=" ", +["sqsupseteq"]="⊒", +["upharpoonright"]="↾", +["lopf"]="𝕝", +["Omicron"]="Ο", +["ccaps"]="⩍", +["lrhard"]="⥭", ["Lstrok"]="Ł", -["gamma"]="γ", -["Sc"]="⪼", -["Aopf"]="𝔸", -["pluscir"]="⨢", -["Itilde"]="Ĩ", -["DoubleRightTee"]="⊨", -["pluse"]="⩲", -["iiint"]="∭", -["dotplus"]="∔", -["vrtri"]="⊳", -["Proportion"]="∷", -["bne"]="=⃥", -["cuepr"]="⋞", +["Mfr"]="𝔐", +["njcy"]="њ", +["ocy"]="о", +["Zcaron"]="Ž", +["NotSucceeds"]="⊁", +["rarrbfs"]="⤠", +["gtrapprox"]="⪆", +["oS"]="Ⓢ", +["diamond"]="⋄", +["gesdot"]="⪀", +["urcorner"]="⌝", +["lotimes"]="⨴", +["pertenk"]="‱", +["rfisht"]="⥽", +["Zfr"]="ℨ", +["Map"]="⤅", +["cross"]="✗", +["DifferentialD"]="ⅆ", +["boxtimes"]="⊠", +["horbar"]="―", +["lg"]="≶", +["orarr"]="↻", +["Vbar"]="⫫", +["ropf"]="𝕣", +["NotDoubleVerticalBar"]="∦", +["Sfr"]="𝔖", +["Iuml"]="Ï", +["leftharpoondown"]="↽", +["atilde"]="ã", +["VerticalTilde"]="≀", +["DoubleContourIntegral"]="∯", +["longleftarrow"]="⟵", +["Im"]="ℑ", +["RightUpVectorBar"]="⥔", +["nGg"]="⋙̸", +["scap"]="⪸", +["nrarr"]="↛", +["ycy"]="ы", +["ucirc"]="û", +["qopf"]="𝕢", +["oopf"]="𝕠", +["yacute"]="ý", +["Xfr"]="𝔛", +["fork"]="⋔", +["in"]="∈", +["xcap"]="⋂", +["check"]="✓", +["jcy"]="й", +["Phi"]="Φ", +["doteq"]="≐", ["vBar"]="⫨", -["yucy"]="ю", -["PrecedesTilde"]="≾", -["varr"]="↕", -["leftarrowtail"]="↢", -["rangle"]="⟩", -["subsub"]="⫕", -["rightarrowtail"]="↣", -["oslash"]="ø", -["mapstodown"]="↧", -["sqsube"]="⊑", -["NewLine"]="\n", -["Vdash"]="⊩", -["num"]="#", -["umacr"]="ū", -["InvisibleTimes"]="", -["bemptyv"]="⦰", +["frown"]="⌢", ["Iogon"]="Į", -["ssmile"]="⌣", -["timesbar"]="⨱", -["Tstrok"]="Ŧ", -["Icy"]="И", -["zacute"]="ź", -["Cedilla"]="¸", -["daleth"]="ℸ", -["semi"]=";", -["ssetmn"]="∖", -["subdot"]="⪽", -["Bernoullis"]="ℬ", -["otimesas"]="⨶", -["circleddash"]="⊝", -["circlearrowright"]="↻", -["NotLeftTriangleEqual"]="⋬", -["NotTilde"]="≁", -["npart"]="∂̸", -["Gbreve"]="Ğ", -["gtrless"]="≷", -["pound"]="£", -["curlyeqsucc"]="⋟", -["blacklozenge"]="⧫", -["ldca"]="⤶", -["nsucc"]="⊁", -["top"]="⊤", -["ufr"]="𝔲", -["sscr"]="𝓈", -["eDDot"]="⩷", -["Updownarrow"]="⇕", -["loz"]="◊", -["Gcy"]="Г", -["boxdl"]="┐", +["gnsim"]="⋧", +["nsupset"]="⊃⃒", +["equals"]="=", +["angmsdac"]="⦪", +["odash"]="⊝", +["Hstrok"]="Ħ", +["homtht"]="∻", +["maltese"]="✠", +["esim"]="≂", +["realine"]="ℛ", +["straightepsilon"]="ϵ", +["utri"]="▵", +["primes"]="ℙ", +["dbkarow"]="⤏", +["NotLessTilde"]="≴", +["nvrArr"]="⤃", +["cularrp"]="⤽", +["supsup"]="⫖", +["rang"]="⟩", +["nshortmid"]="∤", +["NotCupCap"]="≭", +["gnE"]="≩", +["otilde"]="õ", +["LeftTriangle"]="⊲", +["oelig"]="œ", +["curarrm"]="⤼", +["orderof"]="ℴ", +["DoubleLongLeftArrow"]="⟸", +["OverParenthesis"]="⏜", +["amacr"]="ā", +["copysr"]="℗", +["acirc"]="â", +["LeftArrowRightArrow"]="⇆", +["filig"]="fi", +["uopf"]="𝕦", +["rlhar"]="⇌", +["dharl"]="⇃", +["rAarr"]="⇛", +["rarrw"]="↝", +["isin"]="∈", +["simg"]="⪞", +["NoBreak"]="", +["rAtail"]="⤜", +["ndash"]="–", +["IJlig"]="IJ", +["dfr"]="𝔡", +["ohm"]="Ω", +["breve"]="˘", +["ccedil"]="ç", +["topf"]="𝕥", +["nvDash"]="⊭", +["RBarr"]="⤐", +["clubs"]="♣", ["napos"]="ʼn", -["Sqrt"]="√", -["xsqcup"]="⨆", -["Implies"]="⇒", -["uring"]="ů", -["thetav"]="ϑ", -["iiiint"]="⨌", -["nLeftrightarrow"]="⇎", -["lobrk"]="⟦", -["xfr"]="𝔵", -["Abreve"]="Ă", -["micro"]="µ", -["quatint"]="⨖", -["congdot"]="⩭", -["nrtrie"]="⋭", -["Fcy"]="Ф", -["hksearow"]="⤥", -["LowerLeftArrow"]="↙", -["rdca"]="⤷", -["OverBar"]="‾", -["frac12"]="½", -["imacr"]="ī", -["boxVL"]="╣", -["sfr"]="𝔰", -["ensp"]=" ", -["dwangle"]="⦦", -["boxh"]="─", -["Eogon"]="Ę", +["ngtr"]="≯", +["Tstrok"]="Ŧ", +["lrarr"]="⇆", +["eqslantgtr"]="⪖", +["efr"]="𝔢", +["gne"]="⪈", +["csube"]="⫑", +["Xi"]="Ξ", +["sopf"]="𝕤", +["LeftVector"]="↼", +["ggg"]="⋙", +["Ubrcy"]="Ў", +["die"]="¨", +["topbot"]="⌶", +["Rfr"]="ℜ", +["ofcir"]="⦿", ["imped"]="Ƶ", -["Ecy"]="Э", -["lates"]="⪭︀", -["phi"]="φ", -["minusd"]="∸", -["planckh"]="ℎ", -["Ocirc"]="Ô", -["lE"]="≦", -["sum"]="∑", -["lrtri"]="⊿", -["ruluhar"]="⥨", -["lAarr"]="⇚", -["DownArrow"]="↓", -["zscr"]="𝓏", -["questeq"]="≟", -["ngeqq"]="≧̸", -["And"]="⩓", -["Dcy"]="Д", -["angrtvbd"]="⦝", -["rarrpl"]="⥅", -["thkap"]="≈", -["Otimes"]="⨷", -["lesssim"]="≲", -["gE"]="≧", -["ouml"]="ö", -["nsubseteq"]="⊈", -["bigcirc"]="◯", +["plusmn"]="±", +["nles"]="⩽̸", +["pcy"]="п", +["permil"]="‰", +["notinE"]="⋹̸", +["bigoplus"]="⨁", +["boxplus"]="⊞", +["doublebarwedge"]="⌆", +["ccaron"]="č", +["asymp"]="≈", +["sup1"]="¹", +["bumpeq"]="≏", +["nrtrie"]="⋭", +["larrbfs"]="⤟", +["emacr"]="ē", +["gtrless"]="≷", +["Kfr"]="𝔎", +["plus"]="+", +["risingdotseq"]="≓", +["notindot"]="⋵̸", +["Subset"]="⋐", +["CloseCurlyDoubleQuote"]="”", +["nlsim"]="≴", +["dcaron"]="ď", ["boxVR"]="╠", -["Vert"]="‖", -["naturals"]="ℕ", -["plussim"]="⨦", -["wscr"]="𝓌", -["raquo"]="»", -["bigodot"]="⨀", -["dashv"]="⊣", -["hairsp"]=" ", -["inodot"]="ı", -["vnsup"]="⊃⃒", +["lne"]="⪇", +["Pfr"]="𝔓", +["rightsquigarrow"]="↝", +["phone"]="☎", +["DiacriticalDot"]="˙", +["Congruent"]="≡", +["SquareIntersection"]="⊓", +["ordf"]="ª", +["loz"]="◊", ["cire"]="≗", -["vartriangleleft"]="⊲", -["rbrke"]="⦌", -["boxuL"]="╛", -["sce"]="⪰", -["nrtri"]="⋫", -["loarr"]="⇽", -["ShortRightArrow"]="→", -["xscr"]="𝓍", -["Bcy"]="Б", -["HumpEqual"]="≏", -["lmidot"]="ŀ", -["DownLeftVector"]="↽", -["leftharpoonup"]="↼", +["ecaron"]="ě", +["nsub"]="⊄", +["Fouriertrf"]="ℱ", +["Qfr"]="𝔔", +["dblac"]="˝", +["sc"]="≻", +["xrarr"]="⟶", +["ImaginaryI"]="ⅈ", +["angmsdag"]="⦮", +["wopf"]="𝕨", +["middot"]="·", +["gsiml"]="⪐", +["biguplus"]="⨄", +["Prime"]="″", +["bigcirc"]="◯", +["vsubnE"]="⫋︀", +["lrtri"]="⊿", +["nparallel"]="∦", ["lbbrk"]="❲", -["rarrtl"]="↣", -["SucceedsEqual"]="⪰", -["HumpDownHump"]="≎", -["Vee"]="⋁", -["Gopf"]="𝔾", -["otilde"]="õ", -["ofr"]="𝔬", -["Sub"]="⋐", -["gnE"]="≩", -["SquareSuperset"]="⊐", -["leftrightharpoons"]="⇋", -["tosa"]="⤩", -["Ucirc"]="Û", -["mscr"]="𝓂", -["Exists"]="∃", -["langle"]="⟨", -["rfr"]="𝔯", -["THORN"]="Þ", -["gtreqqless"]="⪌", -["eqvparsl"]="⧥", -["NotCongruent"]="≢", -["phiv"]="ϕ", -["lsquor"]="‚", -["prec"]="≺", -["igrave"]="ì", -["Fopf"]="𝔽", -["nwArr"]="⇖", -["nscr"]="𝓃", -["gescc"]="⪩", -["intprod"]="⨼", -["larrlp"]="↫", -["AMP"]="&", -["psi"]="ψ", -["mDDot"]="∺", -["VDash"]="⊫", -["Lleftarrow"]="⇚", -["mfr"]="𝔪", +["dotsquare"]="⊡", +["rceil"]="⌉", ["gesles"]="⪔", -["kscr"]="𝓀", -["Omega"]="Ω", -["bumpe"]="≏", -["NotDoubleVerticalBar"]="∦", -["frac18"]="⅛", -["ecolon"]="≕", -["compfn"]="∘", -["supdot"]="⪾", -["Alpha"]="Α", -["rsquor"]="’", +["roarr"]="⇾", +["simplus"]="⨤", +["lagran"]="ℒ", +["pr"]="≺", +["mnplus"]="∓", +["Iota"]="Ι", +["NestedLessLess"]="≪", +["utilde"]="ũ", +["mldr"]="…", +["bigstar"]="★", +["micro"]="µ", ["percnt"]="%", -["pfr"]="𝔭", -["frasl"]="⁄", -["lscr"]="𝓁", -["aleph"]="ℵ", -["swArr"]="⇙", -["uuml"]="ü", -["uacute"]="ú", -["scE"]="⪴", -["hellip"]="…", +["fllig"]="fl", +["euml"]="ë", +["circledR"]="®", +["lltri"]="◺", +["IEcy"]="Е", +["notniva"]="∌", +["or"]="∨", +["curvearrowleft"]="↶", +["gnapprox"]="⪊", +["NotLessSlantEqual"]="⩽̸", +["Cconint"]="∰", +["NotSucceedsTilde"]="≿̸", +["gammad"]="ϝ", +["rightharpoondown"]="⇁", +["CounterClockwiseContourIntegral"]="∳", +["supdot"]="⪾", +["upsi"]="υ", +["nvle"]="≤⃒", +["beth"]="ℶ", +["nhArr"]="⇎", +["Gamma"]="Γ", +["complement"]="∁", +["xoplus"]="⨁", +["chi"]="χ", +["backepsilon"]="϶", +["nsube"]="⊈", +["aopf"]="𝕒", +["para"]="¶", +["drbkarow"]="⤐", +["Dstrok"]="Đ", +["isinE"]="⋹", +["Ecirc"]="Ê", +["aelig"]="æ", ["ulcorner"]="⌜", -["prnap"]="⪹", -["Gg"]="⋙", -["wedge"]="∧", -["SquareSubset"]="⊏", -["qscr"]="𝓆", -["kfr"]="𝔨", -["RightTee"]="⊢", -["eqsim"]="≂", -["rbrksld"]="⦎", -["ohm"]="Ω", -["lozf"]="⧫", -["cups"]="∪︀", -["epsilon"]="ε", -["ncap"]="⩃", -["Leftarrow"]="⇐", -["ultri"]="◸", -["egrave"]="è", -["vBarv"]="⫩", -["bNot"]="⫭", -["nfr"]="𝔫", -["rsqb"]="]", -["OpenCurlyDoubleQuote"]="“", -["rsquo"]="’", -["Del"]="∇", -["smtes"]="⪬︀", -["varphi"]="ϕ", -["CirclePlus"]="⊕", -["prcue"]="≼", -["curren"]="¤", -["nltri"]="⋪", -["oscr"]="ℴ", -["Wcirc"]="Ŵ", -["prime"]="′", -["ifr"]="𝔦", -["apos"]="'", -["UpTee"]="⊥", -["lescc"]="⪨", -["NegativeMediumSpace"]="", -["DownTee"]="⊤", -["NotSquareSubsetEqual"]="⋢", -["LowerRightArrow"]="↘", -["wr"]="≀", +["Lcaron"]="Ľ", +["bopf"]="𝕓", +["midast"]="*", +["barvee"]="⊽", +["nvgt"]=">⃒", +["bnequiv"]="≡⃥", +["caron"]="ˇ", ["andand"]="⩕", -["gvnE"]="≩︀", -["lfr"]="𝔩", -["lowast"]="∗", -["gfr"]="𝔤", -["digamma"]="ϝ", -["cemptyv"]="⦲", -["ubreve"]="ŭ", -["dstrok"]="đ", +["eparsl"]="⧣", +["xhArr"]="⟺", +["Yuml"]="Ÿ", +["fallingdotseq"]="≒", +["vltri"]="⊲", +["gtrarr"]="⥸", +["nGtv"]="≫̸", +["congdot"]="⩭", +["lfisht"]="⥼", +["nrtri"]="⋫", +["prnsim"]="⋨", +["nsupE"]="⫆̸", +["Colone"]="⩴", +["SquareSuperset"]="⊐", +["boxUL"]="╝", +["Rrightarrow"]="⇛", +["nleftrightarrow"]="↮", +["Conint"]="∯", +["ffilig"]="ffi", +["nleqq"]="≦̸", +["drcrop"]="⌌", +["boxh"]="─", +["Lang"]="⟪", +["ldrdhar"]="⥧", +["rbrack"]="]", +["nvinfin"]="⧞", +["succsim"]="≿", +["boxhu"]="┴", +["tau"]="τ", +["incare"]="℅", +["flat"]="♭", +["angst"]="Å", +["Oslash"]="Ø", +["Vfr"]="𝔙", +["tscy"]="ц", +["lates"]="⪭︀", +["eopf"]="𝕖", +["Because"]="∵", +["frac25"]="⅖", +["daleth"]="ℸ", +["ic"]="", +["ensp"]=" ", +["lrm"]="", +["DoubleLeftRightArrow"]="⇔", +["kappa"]="κ", +["fopf"]="𝕗", +["cularr"]="↶", +["shy"]="", +["yen"]="¥", +["glj"]="⪤", +["dzcy"]="џ", ["expectation"]="ℰ", -["sime"]="≃", -["ltrif"]="◂", -["iacute"]="í", -["chi"]="χ", +["dash"]="‐", +["female"]="♀", +["UnderBrace"]="⏟", +["rotimes"]="⨵", +["caps"]="∩︀", +["copf"]="𝕔", +["lparlt"]="⦓", +["NotLess"]="≮", +["simrarr"]="⥲", +["dtri"]="▿", +["supne"]="⊋", +["block"]="█", +["siml"]="⪝", +["blk12"]="▒", +["natural"]="♮", +["frac34"]="¾", +["frac38"]="⅜", +["Ufr"]="𝔘", +["gg"]="≫", +["Square"]="□", +["lt"]="<", ["erDot"]="≓", -["Vcy"]="В", +["RightAngleBracket"]="⟩", +["LeftDownTeeVector"]="⥡", +["NotGreaterGreater"]="≫̸", +["uogon"]="ų", +["ocirc"]="ô", +["sung"]="♪", +["dollar"]="$", +["Scaron"]="Š", +["top"]="⊤", +["iopf"]="𝕚", +["udhar"]="⥮", +["gjcy"]="ѓ", +["ncap"]="⩃", +["circlearrowleft"]="↺", +["bernou"]="ℬ", +["angmsdaf"]="⦭", +["ldsh"]="↲", +["isins"]="⋴", +["RoundImplies"]="⥰", +["bigtriangledown"]="▽", +["LeftAngleBracket"]="⟨", +["HorizontalLine"]="─", +["Vdashl"]="⫦", +["rHar"]="⥤", +["Tcaron"]="Ť", +["LeftDownVectorBar"]="⥙", +["jopf"]="𝕛", +["LeftRightVector"]="⥎", +["LessGreater"]="≶", +["npart"]="∂̸", +["nsmid"]="∤", +["RightTriangleBar"]="⧐", +["nesim"]="≂̸", +["deg"]="°", +["LeftTeeArrow"]="↤", +["NotHumpDownHump"]="≎̸", +["tridot"]="◬", +["lceil"]="⌈", +["ExponentialE"]="ⅇ", +["tosa"]="⤩", +["gopf"]="𝕘", +["ContourIntegral"]="∮", +["late"]="⪭", +["bbrk"]="⎵", +["half"]="½", ["boxhd"]="┬", -["DoubleDownArrow"]="⇓", -["lArr"]="⇐", -["demptyv"]="⦱", -["smt"]="⪪", -["intcal"]="⊺", -["in"]="∈", -["capcup"]="⩇", -["kjcy"]="ќ", -["Ccirc"]="Ĉ", -["bnequiv"]="≡⃥", -["Emacr"]="Ē", -["siml"]="⪝", -["jfr"]="𝔧", -["gesdoto"]="⪂", -["efr"]="𝔢", -["precneqq"]="⪵", -["because"]="∵", -["Udblac"]="Ű", -["lg"]="≶", -["boxvr"]="├", -["fpartint"]="⨍", -["rbbrk"]="❳", -["LT"]="<", -["cap"]="∩", -["circledR"]="®", -["notinvc"]="⋶", -["zwj"]="", -["nle"]="≰", -["hfr"]="𝔥", -["bigsqcup"]="⨆", -["nGg"]="⋙̸", -["doublebarwedge"]="⌆", +["hopf"]="𝕙", +["Ouml"]="Ö", +["Atilde"]="Ã", +["planckh"]="ℎ", +["MinusPlus"]="∓", +["uharl"]="↿", +["aleph"]="ℵ", +["boxHD"]="╦", +["lesseqgtr"]="⋚", +["colon"]=":", +["SquareSupersetEqual"]="⊒", +["isinsv"]="⋳", +["lnapprox"]="⪉", +["PrecedesSlantEqual"]="≼", +["boxuL"]="╛", +["csup"]="⫐", +["hstrok"]="ħ", +["leftrightharpoons"]="⇋", +["boxuR"]="╘", +["DD"]="ⅅ", +["Longrightarrow"]="⟹", +["epsilon"]="ε", +["NotTildeTilde"]="≉", +["nfr"]="𝔫", +["Vscr"]="𝒱", +["Ncy"]="Н", +["boxUl"]="╜", +["searr"]="↘", +["ddagger"]="‡", +["KHcy"]="Х", +["NotSuperset"]="⊃⃒", +["Uparrow"]="⇑", +["nsqsube"]="⋢", +["Imacr"]="Ī", +["nspar"]="∦", +["supsetneqq"]="⫌", +["Sscr"]="𝒮", +["lobrk"]="⟦", +["mfr"]="𝔪", +["acirc"]="â", +["subne"]="⊊", +["Icirc"]="Î", +["Re"]="ℜ", +["nearrow"]="↗", ["YUcy"]="Ю", -["empty"]="∅", -["nacute"]="ń", -["Acirc"]="Â", -["bigtriangleup"]="△", -["hybull"]="⁃", -["Ycy"]="Ы", -["isindot"]="⋵", -["iota"]="ι", -["numero"]="№", -["cfr"]="𝔠", -["llarr"]="⇇", -["lrhard"]="⥭", -["cross"]="✗", +["eqsim"]="≂", +["UnionPlus"]="⊎", +["topcir"]="⫱", +["boxVL"]="╣", +["Xscr"]="𝒳", +["QUOT"]="\"", +["RightDownVectorBar"]="⥕", +["epsi"]="ε", +["natur"]="♮", +["leftthreetimes"]="⋋", +["hercon"]="⊹", +["lHar"]="⥢", +["Aring"]="Å", +["Kcedil"]="Ķ", +["kfr"]="𝔨", +["Oacute"]="Ó", ["zwnj"]="", +["plusdu"]="⨥", +["Kcy"]="К", +["sqcup"]="⊔", +["zscr"]="𝓏", +["Assign"]="≔", +["zopf"]="𝕫", +["lstrok"]="ł", +["zigrarr"]="⇝", +["ShortDownArrow"]="↓", +["simlE"]="⪟", +["mid"]="∣", ["zeta"]="ζ", -["precnsim"]="⋨", -["zcy"]="з", +["gE"]="≧", +["zeetrf"]="ℨ", +["qfr"]="𝔮", ["zcaron"]="ž", -["xodot"]="⨀", -["RightDownTeeVector"]="⥝", -["ljcy"]="љ", +["Yacute"]="Ý", +["hksearow"]="⤥", +["Atilde"]="Ã", +["zacute"]="ź", +["bsemi"]="⁏", +["bigtriangleup"]="△", +["yuml"]="ÿ", +["yucy"]="ю", ["yscr"]="𝓎", +["yopf"]="𝕪", ["yicy"]="ї", -["Rcy"]="Р", -["nsubset"]="⊂⃒", -["yen"]="¥", -["ycy"]="ы", -["simeq"]="≃", -["dharr"]="⇂", -["ycirc"]="ŷ", -["hArr"]="⇔", -["yacute"]="ý", -["yacute"]="ý", +["urcorn"]="⌝", +["Aacute"]="Á", +["backsimeq"]="⋍", +["ShortUpArrow"]="↑", ["xwedge"]="⋀", -["xoplus"]="⨁", -["nparsl"]="⫽⃥", -["PartialD"]="∂", -["YAcy"]="Я", -["xrArr"]="⟹", -["xotime"]="⨂", -["sstarf"]="⋆", -["yuml"]="ÿ", -["Int"]="∬", -["bsolb"]="⧅", +["Jcy"]="Й", +["nltrie"]="⋬", +["starf"]="★", +["zfr"]="𝔷", +["comma"]=",", +["xsqcup"]="⨆", +["boxVr"]="╟", +["cirscir"]="⧂", +["ucirc"]="û", +["Cross"]="⨯", +["naturals"]="ℕ", +["quaternions"]="ℍ", +["xopf"]="𝕩", +["xodot"]="⨀", ["xnis"]="⋻", -["xmap"]="⟼", -["hercon"]="⊹", -["xlArr"]="⟸", -["xharr"]="⟷", -["rbrack"]="]", +["lsaquo"]="‹", +["xlarr"]="⟵", +["Zacute"]="Ź", +["vdash"]="⊢", +["submult"]="⫁", +["Oscr"]="𝒪", ["xdtri"]="▽", -["diamond"]="⋄", +["LowerRightArrow"]="↘", ["xcup"]="⋃", -["subsup"]="⫓", -["lneqq"]="≨", -["dharl"]="⇃", -["Scy"]="С", -["wopf"]="𝕨", -["rightleftharpoons"]="⇌", -["wfr"]="𝔴", -["nsupseteqq"]="⫆̸", -["boxuR"]="╘", -["permil"]="‰", +["Ycy"]="Ы", +["timesb"]="⊠", +["Ucirc"]="Û", +["eth"]="ð", +["wscr"]="𝓌", +["ratail"]="⤚", +["wr"]="≀", +["Ograve"]="Ò", +["wp"]="℘", +["euml"]="ë", +["yfr"]="𝔶", +["rangle"]="⟩", +["hearts"]="♥", ["wedgeq"]="≙", -["eparsl"]="⧣", -["RoundImplies"]="⥰", -["afr"]="𝔞", -["vsubne"]="⊊︀", -["sup2"]="²", +["wedge"]="∧", +["gtcir"]="⩺", +["par"]="∥", +["swarr"]="↙", +["phiv"]="ϕ", +["NotElement"]="∉", +["alpha"]="α", +["SquareUnion"]="⊔", +["parsl"]="⫽", ["vscr"]="𝓋", +["rharu"]="⇀", +["vrtri"]="⊳", +["comp"]="∁", +["Agrave"]="À", +["rdca"]="⤷", +["vprop"]="∝", +["Tscr"]="𝒯", ["vopf"]="𝕧", -["lbrace"]="{", +["ldca"]="⤶", ["vnsub"]="⊂⃒", -["vltri"]="⊲", -["Uacute"]="Ú", -["vfr"]="𝔳", -["sacute"]="ś", -["njcy"]="њ", -["frac35"]="⅗", -["squf"]="▪", +["gbreve"]="ğ", +["NotSquareSubset"]="⊏̸", +["verbar"]="|", +["YAcy"]="Я", ["veeeq"]="≚", -["lsime"]="⪍", -["mapstoleft"]="↤", +["downharpoonleft"]="⇃", +["Star"]="⋆", +["xfr"]="𝔵", +["nges"]="⩾̸", +["GreaterGreater"]="⪢", +["vartriangleright"]="⊳", +["rcy"]="р", +["vartheta"]="ϑ", +["varsupsetneqq"]="⫌︀", +["dashv"]="⊣", ["varsupsetneq"]="⊋︀", -["varsubsetneq"]="⊊︀", -["Tcy"]="Т", -["cwint"]="∱", -["varsigma"]="ς", -["LessGreater"]="≶", +["Ncaron"]="Ň", +["varsubsetneqq"]="⫋︀", ["varrho"]="ϱ", -["varpropto"]="∝", -["pr"]="≺", -["backprime"]="‵", +["triangledown"]="▿", +["varpi"]="ϖ", +["sol"]="/", +["ssetmn"]="∖", +["varnothing"]="∅", ["varkappa"]="ϰ", -["Poincareplane"]="ℌ", -["roplus"]="⨮", -["Edot"]="Ė", -["copysr"]="℗", +["vangrt"]="⦜", +["Leftarrow"]="⇐", +["Qscr"]="𝒬", +["uwangle"]="⦧", +["rarrap"]="⥵", ["uuml"]="ü", -["dfr"]="𝔡", ["uuarr"]="⇈", -["uogon"]="ų", -["Uscr"]="𝒰", -["gel"]="⋛", -["olarr"]="↺", -["lsaquo"]="‹", -["omacr"]="ō", -["utdot"]="⋰", -["or"]="∨", -["Ocirc"]="Ô", -["ClockwiseContourIntegral"]="∲", -["SmallCircle"]="∘", -["gtcc"]="⪧", ["uscr"]="𝓊", +["urtri"]="◹", +["uring"]="ů", +["sect"]="§", +["quatint"]="⨖", ["urcrop"]="⌎", -["ContourIntegral"]="∮", -["szlig"]="ß", -["egs"]="⪖", -["Ucy"]="У", -["ange"]="⦤", -["upharpoonright"]="↾", -["xcap"]="⋂", +["wfr"]="𝔴", +["duhar"]="⥯", +["upuparrows"]="⇈", +["macr"]="¯", +["SmallCircle"]="∘", +["upsih"]="ϒ", +["uplus"]="⊎", +["shy"]="", +["uparrow"]="↑", ["uml"]="¨", -["nsubseteqq"]="⫅̸", +["eDot"]="≑", +["blk34"]="▓", +["umacr"]="ū", +["ultri"]="◸", +["rbbrk"]="❳", ["ulcorn"]="⌜", -["uhblk"]="▀", -["scirc"]="ŝ", -["shy"]="", -["uharl"]="↿", +["uharr"]="↾", ["ugrave"]="ù", -["lstrok"]="ł", -["Gamma"]="Γ", -["udhar"]="⥮", -["udblac"]="ű", -["ucirc"]="û", -["loang"]="⟬", -["uarr"]="↑", +["Ograve"]="Ò", +["nsupseteq"]="⊉", +["ufisht"]="⥾", +["Breve"]="˘", +["ucy"]="у", +["cylcty"]="⌭", +["ubreve"]="ŭ", +["SHcy"]="Ш", +["boxdR"]="╒", +["awint"]="⨑", +["uHar"]="⥣", ["uArr"]="⇑", -["twoheadrightarrow"]="↠", +["REG"]="®", +["twoheadleftarrow"]="↞", ["tstrok"]="ŧ", +["iprod"]="⨼", ["tshcy"]="ћ", -["tscy"]="ц", -["angsph"]="∢", -["kappa"]="κ", ["tscr"]="𝓉", -["tritime"]="⨻", -["trisb"]="⧍", +["trpezium"]="⏢", +["ycirc"]="ŷ", +["larrhk"]="↩", +["triplus"]="⨹", ["triminus"]="⨺", -["trie"]="≜", -["tridot"]="◬", -["aacute"]="á", +["Rsh"]="↱", +["becaus"]="∵", +["Acirc"]="Â", ["trianglerighteq"]="⊵", -["RightTeeVector"]="⥛", ["triangleright"]="▹", +["hkswarow"]="⤦", +["triangleq"]="≜", +["AElig"]="Æ", ["trianglelefteq"]="⊴", +["varpropto"]="∝", ["triangle"]="▵", -["NegativeVeryThinSpace"]="", -["triangledown"]="▿", -["dash"]="‐", -["trade"]="™", +["tprime"]="‴", ["topfork"]="⫚", -["Upsi"]="ϒ", -["topcir"]="⫱", -["loplus"]="⨭", -["Zdot"]="Ż", -["lbrke"]="⦋", -["angmsd"]="∡", -["dArr"]="⇓", -["topbot"]="⌶", ["toea"]="⤨", -["iexcl"]="¡", -["acirc"]="â", -["easter"]="⩮", -["CloseCurlyDoubleQuote"]="”", -["cupcup"]="⩊", -["rlhar"]="⇌", -["nsimeq"]="≄", -["Uparrow"]="⇑", -["tau"]="τ", -["npr"]="⊀", -["phone"]="☎", -["emacr"]="ē", -["SHcy"]="Ш", -["gtdot"]="⋗", -["ReverseUpEquilibrium"]="⥯", +["ac"]="∾", +["timesd"]="⨰", +["UpArrowDownArrow"]="⇅", +["timesbar"]="⨱", +["llhard"]="⥫", +["CHcy"]="Ч", +["odblac"]="ő", +["THORN"]="Þ", +["notni"]="∌", +["nbump"]="≎̸", +["eqcolon"]="≕", ["tilde"]="˜", -["angmsdac"]="⦪", -["duhar"]="⥯", -["approxeq"]="≊", -["NotSupersetEqual"]="⊉", -["thorn"]="þ", -["thksim"]="∼", -["subsim"]="⫇", -["bnot"]="⌐", +["simgE"]="⪠", +["intercal"]="⊺", +["thetasym"]="ϑ", +["xcirc"]="◯", ["thinsp"]=" ", ["thicksim"]="∼", -["gt"]=">", -["UpperLeftArrow"]="↖", -["thetasym"]="ϑ", -["simlE"]="⪟", -["bbrktbrk"]="⎶", -["Jcirc"]="Ĵ", -["cedil"]="¸", -["NotLessSlantEqual"]="⩽̸", -["rx"]="℞", -["infin"]="∞", -["curlyvee"]="⋎", -["LeftArrow"]="←", -["tfr"]="𝔱", -["blacksquare"]="▪", -["emptyv"]="∅", -["Mellintrf"]="ℳ", -["aogon"]="ą", -["succnapprox"]="⪺", -["tcy"]="т", -["ecaron"]="ě", +["LeftArrowBar"]="⇤", +["Uuml"]="Ü", +["DownTeeArrow"]="↧", +["cent"]="¢", +["hookleftarrow"]="↩", +["odiv"]="⨸", +["therefore"]="∴", +["ClockwiseContourIntegral"]="∲", +["Ofr"]="𝔒", +["auml"]="ä", +["frac12"]="½", +["nRightarrow"]="⇏", +["kcedil"]="ķ", +["DownRightVectorBar"]="⥗", +["boxDL"]="╗", ["tcedil"]="ţ", -["boxhU"]="╨", -["boxVl"]="╢", -["gacute"]="ǵ", -["tcaron"]="ť", -["boxDr"]="╓", -["bump"]="≎", -["blk12"]="▒", -["RightArrow"]="→", -["els"]="⪕", -["apacir"]="⩯", -["acy"]="а", -["omid"]="⦶", -["boxbox"]="⧉", -["iecy"]="е", -["szlig"]="ß", -["upsih"]="ϒ", -["swnwar"]="⤪", -["Icirc"]="Î", -["swarr"]="↙", -["times"]="×", -["Ograve"]="Ò", -["hoarr"]="⇿", -["NotTildeEqual"]="≄", -["IEcy"]="Е", -["iexcl"]="¡", -["bdquo"]="„", -["TildeTilde"]="≈", +["boxUr"]="╙", +["icirc"]="î", +["lmoustache"]="⎰", +["prime"]="′", +["ngeq"]="≱", ["nshortparallel"]="∦", -["subedot"]="⫃", -["supsetneq"]="⊋", -["CenterDot"]="·", -["lessapprox"]="⪅", -["LeftVectorBar"]="⥒", -["bigoplus"]="⨁", -["supseteqq"]="⫆", -["drcorn"]="⌟", -["hstrok"]="ħ", -["HorizontalLine"]="─", -["curarrm"]="⤼", -["lopar"]="⦅", +["szlig"]="ß", +["Egrave"]="È", +["sqsubset"]="⊏", +["NotRightTriangleEqual"]="⋭", +["swarrow"]="↙", +["Ucirc"]="Û", +["DownArrowBar"]="⤓", +["Lfr"]="𝔏", ["wcirc"]="ŵ", +["LessLess"]="⪡", +["Tilde"]="∼", +["empty"]="∅", +["swarhk"]="⤦", +["DownLeftVector"]="↽", +["Uscr"]="𝒰", +["khcy"]="х", +["gesl"]="⋛︀", +["supsub"]="⫔", +["malt"]="✠", +["cirmid"]="⫯", +["PrecedesTilde"]="≾", +["lharul"]="⥪", +["rightleftharpoons"]="⇌", +["Ccedil"]="Ç", +["plusb"]="⊞", +["nsupe"]="⊉", +["geq"]="≥", +["dHar"]="⥥", +["lcedil"]="ļ", +["ange"]="⦤", +["supseteq"]="⊇", +["Upsi"]="ϒ", +["mapstodown"]="↧", +["profalar"]="⌮", +["cupdot"]="⊍", +["mapstoleft"]="↤", +["xotime"]="⨂", +["tbrk"]="⎴", +["supmult"]="⫂", +["disin"]="⋲", ["suphsub"]="⫗", -["Otilde"]="Õ", -["EmptySmallSquare"]="◻", +["eg"]="⪚", ["supedot"]="⫄", -["Kopf"]="𝕂", -["boxminus"]="⊟", -["csupe"]="⫒", -["Ffr"]="𝔉", -["origof"]="⊶", -["sup3"]="³", -["boxH"]="═", -["vsubnE"]="⫋︀", -["Hcirc"]="Ĥ", -["block"]="█", +["NonBreakingSpace"]=" ", +["Euml"]="Ë", ["bsolhsub"]="⟈", -["Supset"]="⋑", -["GreaterFullEqual"]="≧", +["supdsub"]="⫘", +["sup3"]="³", +["DoubleLeftTee"]="⫤", +["angrtvb"]="⊾", +["supsim"]="⫈", +["sup2"]="²", +["sup2"]="²", +["circledast"]="⊛", +["rfr"]="𝔯", +["darr"]="↓", +["rarrhk"]="↪", +["macr"]="¯", ["sup1"]="¹", -["llcorner"]="⌞", -["sopf"]="𝕤", -["larrbfs"]="⤟", -["succneqq"]="⪶", -["part"]="∂", -["eacute"]="é", -["COPY"]="©", -["frac23"]="⅔", -["dbkarow"]="⤏", -["succeq"]="⪰", -["notni"]="∌", -["Euml"]="Ë", -["harrcir"]="⥈", -["leftrightsquigarrow"]="↭", -["xcirc"]="◯", -["caret"]="⁁", -["les"]="⩽", -["lharul"]="⥪", -["bsime"]="⋍", -["DoubleLeftArrow"]="⇐", -["ecirc"]="ê", -["subsetneqq"]="⫋", -["crarr"]="↵", -["cuwed"]="⋏", -["Ugrave"]="Ù", -["Gcirc"]="Ĝ", -["LeftTriangleBar"]="⧏", +["aacute"]="á", +["oscr"]="ℴ", +["lharu"]="↼", +["telrec"]="⌕", +["Dashv"]="⫤", +["succnsim"]="⋩", +["AElig"]="Æ", +["Vee"]="⋁", +["succnapprox"]="⪺", +["CapitalDifferentialD"]="ⅅ", ["gsim"]="≳", -["RightTriangleEqual"]="⊵", -["lacute"]="ĺ", -["Ccedil"]="Ç", -["ee"]="ⅇ", -["heartsuit"]="♥", -["coloneq"]="≔", -["subseteq"]="⊆", -["NotSucceedsTilde"]="≿̸", +["succapprox"]="⪸", +["rmoustache"]="⎱", +["DotEqual"]="≐", +["subsup"]="⫓", +["Gcedil"]="Ģ", +["questeq"]="≟", +["lthree"]="⋋", +["cong"]="≅", +["lcub"]="{", +["radic"]="√", +["subrarr"]="⥹", +["nvlt"]="<⃒", ["subplus"]="⪿", -["cupcap"]="⩆", -["Amacr"]="Ā", -["angst"]="Å", -["supsetneqq"]="⫌", -["sube"]="⊆", -["imagpart"]="ℑ", -["Lambda"]="Λ", -["Afr"]="𝔄", -["sub"]="⊂", +["bigsqcup"]="⨆", +["downarrow"]="↓", +["auml"]="ä", +["boxdL"]="╕", +["boxvr"]="├", +["lbrkslu"]="⦍", +["bigwedge"]="⋀", +["apacir"]="⩯", +["Wscr"]="𝒲", +["iecy"]="е", +["VerticalSeparator"]="❘", +["Yfr"]="𝔜", ["strns"]="¯", ["straightphi"]="ϕ", -["boxvL"]="╡", -["dagger"]="†", -["eta"]="η", -["KHcy"]="Х", -["Yfr"]="𝔜", -["lbrack"]="[", -["VerticalBar"]="∣", -["rightleftarrows"]="⇄", -["fltns"]="▱", -["verbar"]="|", -["RightAngleBracket"]="⟩", -["DownRightVector"]="⇁", -["Lacute"]="Ĺ", -["sol"]="/", -["lrm"]="", -["lesdot"]="⩿", -["nleqslant"]="⩽̸", -["capcap"]="⩋", +["kcy"]="к", +["aogon"]="ą", +["star"]="☆", +["caret"]="⁁", +["cups"]="∪︀", +["iquest"]="¿", +["spar"]="∥", +["NotExists"]="∄", +["Gt"]="≫", ["squ"]="□", -["xutri"]="△", -["TSHcy"]="Ћ", -["gap"]="⪆", -["gtrdot"]="⋗", -["scnap"]="⪺", -["bkarow"]="⤍", -["NotPrecedes"]="⊀", -["suphsol"]="⟉", +["sqsupe"]="⊒", +["subnE"]="⫋", ["sqsup"]="⊐", -["epsi"]="ε", -["sqsubset"]="⊏", -["check"]="✓", -["UpArrowBar"]="⤒", -["NotPrecedesEqual"]="⪯̸", -["csube"]="⫑", -["nsupset"]="⊃⃒", -["lesdoto"]="⪁", +["sqsubseteq"]="⊑", +["ffr"]="𝔣", +["UpTeeArrow"]="↥", +["middot"]="·", +["DoubleLongRightArrow"]="⟹", +["sqsube"]="⊑", +["sce"]="⪰", +["Sup"]="⋑", +["cacute"]="ć", +["GreaterFullEqual"]="≧", +["pfr"]="𝔭", +["Lleftarrow"]="⇚", +["heartsuit"]="♥", +["precsim"]="≾", +["nsucceq"]="⪰̸", ["sqcups"]="⊔︀", -["suplarr"]="⥻", -["nsim"]="≁", -["NotEqualTilde"]="≂̸", -["nearr"]="↗", -["SquareIntersection"]="⊓", -["intlarhk"]="⨗", -["Ecirc"]="Ê", -["vangrt"]="⦜", -["fllig"]="fl", -["Leftrightarrow"]="⇔", -["primes"]="ℙ", -["nvlArr"]="⤂", +["Igrave"]="Ì", +["iquest"]="¿", +["Pcy"]="П", +["thksim"]="∼", +["djcy"]="ђ", +["hfr"]="𝔥", +["spadesuit"]="♠", +["rbrkslu"]="⦐", +["shcy"]="ш", +["barwed"]="⌅", +["rpar"]=")", +["iiiint"]="⨌", +["solb"]="⧄", +["Integral"]="∫", +["napE"]="⩰̸", +["softcy"]="ь", +["NotRightTriangleBar"]="⧐̸", +["Mu"]="Μ", +["frasl"]="⁄", +["Icy"]="И", +["dfisht"]="⥿", ["smte"]="⪬", -["ltri"]="◃", -["Tscr"]="𝒯", +["smt"]="⪪", +["bottom"]="⊥", +["oacute"]="ó", +["ofr"]="𝔬", ["smid"]="∣", -["smeparsl"]="⧤", -["rarrc"]="⤳", -["divideontimes"]="⋇", -["eth"]="ð", -["boxvR"]="╞", -["copy"]="©", -["nges"]="⩾̸", -["fcy"]="ф", -["ShortUpArrow"]="↑", -["simplus"]="⨤", -["frac45"]="⅘", -["nexists"]="∄", -["LeftTeeArrow"]="↤", -["leftleftarrows"]="⇇", -["simg"]="⪞", -["euro"]="€", -["simdot"]="⩪", -["sim"]="∼", -["sigmav"]="ς", -["iuml"]="ï", -["updownarrow"]="↕", -["shy"]="", -["solb"]="⧄", +["ReverseUpEquilibrium"]="⥯", +["smashp"]="⨳", +["slarr"]="←", +["simne"]="≆", +["LeftRightArrow"]="↔", +["thkap"]="≈", +["nlArr"]="⇍", +["chcy"]="ч", +["not"]="¬", +["kgreen"]="ĸ", +["simeq"]="≃", +["LongRightArrow"]="⟶", +["sime"]="≃", +["sigma"]="σ", +["odot"]="⊙", +["amp"]="&", +["Longleftrightarrow"]="⟺", +["Upsilon"]="Υ", +["upharpoonleft"]="↿", +["bigotimes"]="⨂", +["parallel"]="∥", +["ffllig"]="ffl", +["shortparallel"]="∥", +["boxdr"]="┌", +["shortmid"]="∣", +["Euml"]="Ë", +["UpDownArrow"]="↕", +["lcaron"]="ľ", +["sfrown"]="⌢", +["harr"]="↔", +["dsol"]="⧶", +["Beta"]="Β", +["srarr"]="→", +["boxHd"]="╤", ["nesear"]="⤨", -["Umacr"]="Ū", -["uharr"]="↾", -["Therefore"]="∴", -["Barv"]="⫧", -["amacr"]="ā", ["setmn"]="∖", +["DoubleDot"]="¨", ["setminus"]="∖", -["Sscr"]="𝒮", +["andd"]="⩜", +["leftrightarrow"]="↔", ["seswar"]="⤩", -["ccupssm"]="⩐", -["searr"]="↘", +["eogon"]="ę", +["bne"]="=⃥", +["DownBreve"]="̑", +["nLtv"]="≪̸", +["nprcue"]="⋠", +["SucceedsSlantEqual"]="≽", +["downdownarrows"]="⇊", +["seArr"]="⇘", +["Utilde"]="Ũ", +["Gammad"]="Ϝ", +["sdote"]="⩦", +["iexcl"]="¡", +["nvdash"]="⊬", +["csupe"]="⫒", ["sdotb"]="⊡", -["icirc"]="î", -["amp"]="&", -["gcy"]="г", -["Aacute"]="Á", -["boxvh"]="┼", -["bfr"]="𝔟", -["OverParenthesis"]="⏜", -["sqsupe"]="⊒", -["amp"]="&", -["frac14"]="¼", -["ZeroWidthSpace"]="", -["Colon"]="∷", -["Proportional"]="∝", -["thickapprox"]="≈", -["subseteqq"]="⫅", -["IJlig"]="IJ", -["scedil"]="ş", -["lrarr"]="⇆", -["angmsdaf"]="⦭", -["downharpoonleft"]="⇃", +["scsim"]="≿", +["bcy"]="б", +["NotTilde"]="≁", +["minus"]="−", +["scnE"]="⪶", +["scirc"]="ŝ", +["oplus"]="⊕", +["para"]="¶", +["Ycirc"]="Ŷ", +["notinva"]="∉", +["nLl"]="⋘̸", +["Aring"]="Å", +["THORN"]="Þ", +["numero"]="№", +["scaron"]="š", +["bsol"]="\\", +["harrw"]="↭", +["exponentiale"]="ⅇ", +["eDDot"]="⩷", +["AMP"]="&", +["gamma"]="γ", +["opar"]="⦷", +["cwint"]="∱", +["GreaterEqual"]="≥", +["bigcap"]="⋂", +["rtimes"]="⋊", +["integers"]="ℤ", +["easter"]="⩮", ["RightDoubleBracket"]="⟧", -["half"]="½", -["larr"]="←", ["sbquo"]="‚", -["Vscr"]="𝒱", -["nVdash"]="⊮", -["DownRightVectorBar"]="⥗", -["RightDownVector"]="⇂", -["disin"]="⋲", -["nsce"]="⪰̸", -["rbrace"]="}", -["MinusPlus"]="∓", -["rtrif"]="▸", -["parsim"]="⫳", -["supseteq"]="⊇", -["Superset"]="⊃", -["Verbar"]="‖", +["cfr"]="𝔠", +["ruluhar"]="⥨", +["image"]="ℑ", +["nleqslant"]="⩽̸", +["Yopf"]="𝕐", +["apE"]="⩰", +["NotPrecedesEqual"]="⪯̸", +["rsqb"]="]", +["rtrie"]="⊵", +["rthree"]="⋌", +["amp"]="&", +["eng"]="ŋ", +["ll"]="≪", +["rrarr"]="⇉", +["RightTee"]="⊢", +["ETH"]="Ð", +["ReverseEquilibrium"]="⇋", +["langle"]="⟨", ["Zeta"]="Ζ", -["nsccue"]="⋡", -["bsemi"]="⁏", -["ldquor"]="„", -["curarr"]="↷", -["rscr"]="𝓇", -["rppolint"]="⨒", -["rpargt"]="⦔", -["rotimes"]="⨵", -["Equal"]="⩵", -["ropf"]="𝕣", -["ropar"]="⦆", -["roarr"]="⇾", -["odot"]="⊙", -["natural"]="♮", -["slarr"]="←", -["angmsdae"]="⦬", -["acE"]="∾̳", +["roplus"]="⨮", +["there4"]="∴", +["DownRightTeeVector"]="⥟", +["npar"]="∦", +["robrk"]="⟧", +["exist"]="∃", +["lfr"]="𝔩", +["VDash"]="⊫", +["rnmid"]="⫮", +["rmoust"]="⎱", ["rlm"]="", -["COPY"]="©", -["iogon"]="į", -["nleftrightarrow"]="↮", -["reg"]="®", -["risingdotseq"]="≓", -["rightsquigarrow"]="↝", -["dtri"]="▿", -["Larr"]="↞", -["icy"]="и", -["gimel"]="ℷ", +["Ccirc"]="Ĉ", +["imagpart"]="ℑ", +["Equilibrium"]="⇌", +["dd"]="ⅆ", +["cuepr"]="⋞", +["Agrave"]="À", +["cuesc"]="⋟", +["square"]="□", +["notnivc"]="⋽", +["rbrksld"]="⦎", ["cup"]="∪", -["DJcy"]="Ђ", -["gtrapprox"]="⪆", -["rightharpoonup"]="⇀", -["prsim"]="≾", -["rightharpoondown"]="⇁", -["frac16"]="⅙", -["nbsp"]=" ", -["cedil"]="¸", -["numsp"]=" ", +["OpenCurlyDoubleQuote"]="“", +["Lacute"]="Ĺ", +["NewLine"]="\n", +["Sigma"]="Σ", +["Abreve"]="Ă", +["rightleftarrows"]="⇄", +["tint"]="∭", +["angmsdae"]="⦬", +["Leftrightarrow"]="⇔", +["rdquor"]="”", +["Verbar"]="‖", +["Gfr"]="𝔊", ["rightarrow"]="→", ["rhov"]="ϱ", -["rdquo"]="”", -["rharul"]="⥬", -["frac34"]="¾", -["ldrdhar"]="⥧", -["gnsim"]="⋧", -["rtriltri"]="⧎", -["emsp"]=" ", -["rlarr"]="⇄", -["Oslash"]="Ø", -["LeftDownTeeVector"]="⥡", +["Alpha"]="Α", +["rho"]="ρ", +["DownLeftTeeVector"]="⥞", +["ntriangleright"]="⋫", ["reg"]="®", -["LeftTeeVector"]="⥚", -["gsiml"]="⪐", -["QUOT"]="\"", -["blk14"]="░", -["rightrightarrows"]="⇉", -["NotGreaterGreater"]="≫̸", -["Xscr"]="𝒳", -["Re"]="ℜ", -["Ouml"]="Ö", +["Int"]="∬", +["agrave"]="à", +["Ecirc"]="Ê", +["NotReverseElement"]="∌", +["backprime"]="‵", +["Jfr"]="𝔍", ["rdsh"]="↳", -["and"]="∧", -["larrb"]="⇤", -["TripleDot"]="⃛", -["bcy"]="б", -["diams"]="♦", -["veebar"]="⊻", -["rcub"]="}", -["Scirc"]="Ŝ", -["ac"]="∾", -["rceil"]="⌉", -["rcedil"]="ŗ", -["cupbrcap"]="⩈", -["rcaron"]="ř", -["cuesc"]="⋟", -["HilbertSpace"]="ℋ", -["plus"]="+", -["rbrkslu"]="⦐", -["LessLess"]="⪡", -["macr"]="¯", -["notinE"]="⋹̸", +["jsercy"]="ј", +["Bscr"]="ℬ", +["boxH"]="═", +["leq"]="≤", +["NotPrecedes"]="⊀", +["coloneq"]="≔", +["boxvh"]="┼", +["larr"]="←", +["ncup"]="⩂", +["EmptySmallSquare"]="◻", +["vartriangleleft"]="⊲", +["iacute"]="í", +["nVDash"]="⊯", +["lap"]="⪅", +["precapprox"]="⪷", +["ecolon"]="≕", +["lsqb"]="[", ["rbarr"]="⤍", -["abreve"]="ă", -["sqcup"]="⊔", -["ratail"]="⤚", -["VeryThinSpace"]=" ", -["Uarrocir"]="⥉", -["rarrfs"]="⤞", -["Odblac"]="Ő", -["Imacr"]="Ī", -["ordm"]="º", -["odsold"]="⦼", -["NJcy"]="Њ", -["Yacute"]="Ý", -["rarrbfs"]="⤠", -["prop"]="∝", -["notin"]="∉", -["vsupne"]="⊋︀", -["bigcap"]="⋂", -["Phi"]="Φ", -["Ograve"]="Ò", -["Yscr"]="𝒴", -["approx"]="≈", -["racute"]="ŕ", -["ggg"]="⋙", -["lmoust"]="⎰", +["yacy"]="я", +["efDot"]="≒", +["ratio"]="∶", +["wreath"]="≀", +["nearhk"]="⤤", +["rarrpl"]="⥅", +["nvge"]="≥⃒", +["searrow"]="↘", +["thorn"]="þ", +["rdquo"]="”", +["LessFullEqual"]="≦", +["nvrtrie"]="⊵⃒", +["nsubseteqq"]="⫅̸", +["nedot"]="≐̸", +["VerticalLine"]="|", +["lsh"]="↰", +["DownRightVector"]="⇁", +["ecirc"]="ê", +["andv"]="⩚", +["trie"]="≜", +["race"]="∽̱", ["rBarr"]="⤏", -["gneqq"]="≩", -["isinv"]="∈", -["harr"]="↔", -["rArr"]="⇒", -["rAarr"]="⇛", -["quot"]="\"", +["lbrksld"]="⦏", +["emsp14"]=" ", +["RuleDelayed"]="⧴", +["vsubne"]="⊊︀", +["ShortLeftArrow"]="←", +["gtlPar"]="⦕", ["quest"]="?", -["iuml"]="ï", -["LeftRightArrow"]="↔", -["LeftDoubleBracket"]="⟦", -["gesdot"]="⪀", -["Ntilde"]="Ñ", -["boxUR"]="╚", -["exist"]="∃", -["subnE"]="⫋", -["ograve"]="ò", -["qopf"]="𝕢", -["Zacute"]="Ź", -["qfr"]="𝔮", -["dcy"]="д", -["NotReverseElement"]="∌", -["DotEqual"]="≐", -["VerticalLine"]="|", -["pscr"]="𝓅", -["prurel"]="⊰", -["cdot"]="ċ", -["bprime"]="‵", -["ltdot"]="⋖", -["prnsim"]="⋨", -["curlywedge"]="⋏", -["prnE"]="⪵", -["REG"]="®", -["sup3"]="³", +["dot"]="˙", +["RightVector"]="⇀", +["rppolint"]="⨒", +["Hat"]="^", +["zcy"]="з", +["suplarr"]="⥻", +["boxhU"]="╨", +["puncsp"]=" ", +["GreaterLess"]="≷", +["psi"]="ψ", +["ncaron"]="ň", +["SupersetEqual"]="⊇", +["propto"]="∝", ["preceq"]="⪯", -["LeftDownVectorBar"]="⥙", -["ForAll"]="∀", +["frac56"]="⅚", +["NotLessGreater"]="≸", +["jukcy"]="є", +["swArr"]="⇙", +["profline"]="⌒", +["prnE"]="⪵", +["larrpl"]="⤹", +["af"]="", +["profsurf"]="⌓", +["Larr"]="↞", ["forkv"]="⫙", -["varpi"]="ϖ", -["nrArr"]="⇏", +["prcue"]="≼", +["RightUpTeeVector"]="⥜", ["pound"]="£", +["ugrave"]="ù", +["popf"]="𝕡", +["frac78"]="⅞", +["suphsol"]="⟉", +["loplus"]="⨭", +["pointint"]="⨕", +["cupcap"]="⩆", +["LessTilde"]="≲", +["pm"]="±", +["blacksquare"]="▪", ["plustwo"]="⨧", -["shchcy"]="щ", -["cacute"]="ć", -["Dashv"]="⫤", -["lHar"]="⥢", -["NotLeftTriangle"]="⋪", -["gbreve"]="ğ", -["boxDl"]="╖", -["Beta"]="Β", -["ReverseEquilibrium"]="⇋", +["copy"]="©", +["plussim"]="⨦", +["Lcy"]="Л", +["pluse"]="⩲", +["ropar"]="⦆", +["OpenCurlyQuote"]="‘", ["plusacir"]="⨣", -["eqslantgtr"]="⪖", -["ecy"]="э", -["pitchfork"]="⋔", -["ctdot"]="⋯", -["odiv"]="⨸", -["lesseqqgtr"]="⪋", -["GreaterLess"]="≷", -["Ocy"]="О", -["weierp"]="℘", -["Uring"]="Ů", -["period"]=".", -["nis"]="⋼", -["cudarrr"]="⤵", -["boxHU"]="╩", -["Ouml"]="Ö", -["Assign"]="≔", -["Lscr"]="ℒ", -["parallel"]="∥", -["there4"]="∴", -["cupor"]="⩅", -["nwarr"]="↖", -["para"]="¶", -["ouml"]="ö", -["otimes"]="⊗", -["drbkarow"]="⤐", -["puncsp"]=" ", -["otilde"]="õ", -["Vvdash"]="⊪", -["osol"]="⊘", +["Exists"]="∃", +["piv"]="ϖ", +["phmmat"]="ℳ", +["angzarr"]="⍼", +["vsupnE"]="⫌︀", +["phi"]="φ", +["perp"]="⊥", +["rdldhar"]="⥩", +["ccirc"]="ĉ", +["Tfr"]="𝔗", +["Tcy"]="Т", +["circeq"]="≗", +["InvisibleTimes"]="", +["OElig"]="Œ", +["trisb"]="⧍", +["Rcaron"]="Ř", +["olt"]="⧀", +["UpArrow"]="↑", +["DDotrahd"]="⤑", +["Uarrocir"]="⥉", +["lacute"]="ĺ", ["oslash"]="ø", -["dd"]="ⅆ", -["NotPrecedesSlantEqual"]="⋠", -["orv"]="⩛", -["orslope"]="⩗", -["KJcy"]="Ќ", -["larrfs"]="⤝", -["orderof"]="ℴ", -["asympeq"]="≍", -["ord"]="⩝", -["NotLess"]="≮", -["NotGreater"]="≯", -["ThinSpace"]=" ", -["ominus"]="⊖", +["Uarr"]="↟", +["bsolb"]="⧅", +["gt"]=">", +["ordm"]="º", +["Itilde"]="Ĩ", +["ordm"]="º", +["Jscr"]="𝒥", +["Rarr"]="↠", +["measuredangle"]="∡", ["DoubleLongLeftRightArrow"]="⟺", -["lesseqgtr"]="⋚", +["lmidot"]="ŀ", +["period"]=".", ["operp"]="⦹", -["quaternions"]="ℍ", -["boxdR"]="╒", -["omega"]="ω", -["Kscr"]="𝒦", -["lessgtr"]="≶", -["utilde"]="ũ", -["olt"]="⧀", -["Rho"]="Ρ", -["olcir"]="⦾", -["oint"]="∮", +["bprime"]="‵", +["numsp"]=" ", +["ominus"]="⊖", +["nldr"]="‥", ["ograve"]="ò", -["Succeeds"]="≻", -["Igrave"]="Ì", -["eogon"]="ę", -["Uacute"]="Ú", -["bbrk"]="⎵", -["ocy"]="о", -["bcong"]="≌", +["omicron"]="ο", +["nearr"]="↗", +["jcirc"]="ĵ", +["nlE"]="≦̸", +["deg"]="°", +["frac13"]="⅓", +["tcy"]="т", +["lowbar"]="_", +["vfr"]="𝔳", +["ogon"]="˛", +["sim"]="∼", +["ocirc"]="ô", +["Icirc"]="Î", +["ocir"]="⊚", +["ZeroWidthSpace"]="", ["oast"]="⊛", +["smile"]="⌣", +["bigvee"]="⋁", ["oacute"]="ó", -["cir"]="○", -["angmsdab"]="⦩", -["Iscr"]="ℐ", -["ldquo"]="“", -["RightVector"]="⇀", -["euml"]="ë", -["between"]="≬", -["oS"]="Ⓢ", -["downdownarrows"]="⇊", -["nvlt"]="<⃒", -["lurdshar"]="⥊", -["starf"]="★", -["xlarr"]="⟵", -["Aring"]="Å", -["Xi"]="Ξ", -["gtcir"]="⩺", -["Nscr"]="𝒩", -["elinters"]="⏧", -["ntrianglelefteq"]="⋬", -["Vbar"]="⫫", +["Egrave"]="È", +["nwnear"]="⤧", +["nwarhk"]="⤣", +["rationals"]="ℚ", +["DiacriticalGrave"]="`", +["npreceq"]="⪯̸", +["rarrc"]="⤳", +["Uogon"]="Ų", +["InvisibleComma"]="", +["nvltrie"]="⊴⃒", +["digamma"]="ϝ", +["cirE"]="⧃", +["AMP"]="&", +["Theta"]="Θ", +["frac15"]="⅕", +["fnof"]="ƒ", +["icirc"]="î", +["Cdot"]="Ċ", +["ngsim"]="≵", +["sube"]="⊆", +["tcaron"]="ť", ["ntilde"]="ñ", -["andv"]="⩚", -["Rsh"]="↱", -["angmsdad"]="⦫", -["nsup"]="⊅", -["nbsp"]=" ", -["SquareSupersetEqual"]="⊒", -["ETH"]="Ð", -["nsube"]="⊈", -["DoubleContourIntegral"]="∯", -["nsubE"]="⫅̸", -["angmsdah"]="⦯", -["NotLessGreater"]="≸", -["awint"]="⨑", -["rtri"]="▹", -["nsc"]="⊁", -["boxvl"]="┤", -["beta"]="β", -["LessSlantEqual"]="⩽", -["supsub"]="⫔", -["agrave"]="à", -["LeftUpTeeVector"]="⥠", -["nrarrw"]="↝̸", -["ltcc"]="⪦", -["nrarrc"]="⤳̸", -["frac78"]="⅞", -["nvrArr"]="⤃", -["igrave"]="ì", -["barwed"]="⌅", -["Mscr"]="ℳ", -["nrarr"]="↛", -["SubsetEqual"]="⊆", -["notnivc"]="⋽", -["notnivb"]="⋾", -["succcurlyeq"]="≽", -["eth"]="ð", -["notinva"]="∉", -["Otilde"]="Õ", -["star"]="☆", -["rangd"]="⦒", -["Psi"]="Ψ", -["nsupe"]="⊉", -["mapstoup"]="↥", -["LJcy"]="Љ", -["looparrowleft"]="↫", -["nlarr"]="↚", -["Ll"]="⋘", -["ordf"]="ª", -["ni"]="∋", +["ufr"]="𝔲", +["Mcy"]="М", ["Delta"]="Δ", -["NotVerticalBar"]="∤", -["backcong"]="≌", -["NoBreak"]="", +["vnsup"]="⊃⃒", +["lAtail"]="⤛", +["DoubleUpArrow"]="⇑", +["aelig"]="æ", +["lscr"]="𝓁", +["Rscr"]="ℛ", +["capcup"]="⩇", +["npolint"]="⨔", +["gesdotol"]="⪄", +["uacute"]="ú", +["bumpE"]="⪮", +["drcorn"]="⌟", +["notnivb"]="⋾", +["notinvc"]="⋶", +["ovbar"]="⌽", +["Mopf"]="𝕄", +["NotGreater"]="≯", +["boxDr"]="╓", +["lrcorner"]="⌟", +["nleq"]="≰", +["nleftarrow"]="↚", +["nle"]="≰", +["boxvl"]="┤", +["Downarrow"]="⇓", +["hcirc"]="ĥ", ["nharr"]="↮", +["tfr"]="𝔱", +["nlt"]="≮", +["gacute"]="ǵ", +["colone"]="≔", +["Rang"]="⟫", ["ngt"]="≯", -["Pscr"]="𝒫", -["laemptyv"]="⦴", -["utrif"]="▴", -["ngeq"]="≱", -["ncedil"]="ņ", -["ncaron"]="ň", -["boxhu"]="┴", -["NotSquareSuperset"]="⊐̸", -["bull"]="•", +["ntilde"]="ñ", +["vcy"]="в", +["boxvL"]="╡", +["NotLeftTriangleBar"]="⧏̸", +["NestedGreaterGreater"]="≫", +["xmap"]="⟼", +["napid"]="≋̸", +["LeftTriangleBar"]="⧏", ["SquareSubsetEqual"]="⊑", -["VerticalSeparator"]="❘", -["natur"]="♮", -["ffr"]="𝔣", -["rdquor"]="”", -["lagran"]="ℒ", -["nRightarrow"]="⇏", -["nLtv"]="≪̸", -["nLl"]="⋘̸", -["Epsilon"]="Ε", -["csup"]="⫐", -["leftarrow"]="←", -["nGt"]="≫⃒", -["multimap"]="⊸", -["mstpos"]="∾", -["SuchThat"]="∋", -["mldr"]="…", -["midast"]="*", -["Sum"]="∑", -["vartheta"]="ϑ", -["mapsto"]="↦", -["nsupseteq"]="⊉", -["Oscr"]="𝒪", -["forall"]="∀", -["aring"]="å", -["ltimes"]="⋉", -["ltcir"]="⩹", -["lt"]="<", -["ii"]="ⅈ", -["equest"]="≟", -["scsim"]="≿", -["lsqb"]="[", -["lsimg"]="⪏", -["Egrave"]="È", -["Downarrow"]="⇓", -["lsim"]="≲", -["eqslantless"]="⪕", -["ucirc"]="û", -["Auml"]="Ä", -["lnsim"]="⋦", -["uplus"]="⊎", -["lhblk"]="▄", -["Ugrave"]="Ù", -["dlcrop"]="⌍", -["OElig"]="Œ", -["lesg"]="⋚︀", -["lesdotor"]="⪃", -["eg"]="⪚", -["lvertneqq"]="≨︀", -["leqslant"]="⩽", -["ccups"]="⩌", -["lceil"]="⌈", -["auml"]="ä", -["RightCeiling"]="⌉", -["lbrksld"]="⦏", -["lbarr"]="⤌", +["eacute"]="é", +["ne"]="≠", +["ncongdot"]="⩭̸", +["boxvR"]="╞", +["PrecedesEqual"]="⪯", +["Omacr"]="Ō", +["egs"]="⪖", +["ouml"]="ö", +["nbsp"]=" ", +["xuplus"]="⨄", +["napprox"]="≉", +["CloseCurlyQuote"]="’", +["nacute"]="ń", +["Chi"]="Χ", +["subsub"]="⫕", +["gescc"]="⪩", +["gcirc"]="ĝ", +["Lsh"]="↰", +["sfr"]="𝔰", +["circlearrowright"]="↻", +["rcaron"]="ř", +["ThinSpace"]=" ", +["otilde"]="õ", +["TRADE"]="™", +["cudarrl"]="⤸", ["lat"]="⪫", -["Rscr"]="ℛ", -["Zcy"]="З", -["bigwedge"]="⋀", -["Prime"]="″", +["nLeftrightarrow"]="⇎", +["leqq"]="≦", +["dagger"]="†", +["dstrok"]="đ", +["sacute"]="ś", +["Amacr"]="Ā", +["mumap"]="⊸", +["models"]="⊧", +["DiacriticalAcute"]="´", +["minusd"]="∸", +["hybull"]="⁃", +["ijlig"]="ij", +["fflig"]="ff", +["NotGreaterEqual"]="≱", +["Colon"]="∷", +["boxV"]="║", +["DotDot"]="⃜", +["mdash"]="—", +["hairsp"]=" ", +["bcong"]="≌", +["mcomma"]="⨩", +["cirfnint"]="⨐", +["TScy"]="Ц", +["luruhar"]="⥦", +["awconint"]="∳", +["nsim"]="≁", +["els"]="⪕", +["imof"]="⊷", +["lpar"]="(", +["lozenge"]="◊", +["oint"]="∮", +["Umacr"]="Ū", +["Sum"]="∑", +["lopar"]="⦅", +["racute"]="ŕ", +["LessEqualGreater"]="⋚", +["Wedge"]="⋀", +["bbrktbrk"]="⎶", +["RightDownTeeVector"]="⥝", +["HumpDownHump"]="≎", +["rarrb"]="⇥", +["longleftrightarrow"]="⟷", +["lnE"]="≨", +["NotGreaterSlantEqual"]="⩾̸", +["Nu"]="Ν", +["NotNestedLessLess"]="⪡̸", +["UpEquilibrium"]="⥮", +["boxhD"]="╥", +["el"]="⪙", ["boxDR"]="╔", -["scnsim"]="⋩", -["efDot"]="≒", -["kopf"]="𝕜", -["minusdu"]="⨪", -["kappav"]="ϰ", +["Gdot"]="Ġ", +["itilde"]="ĩ", +["isindot"]="⋵", +["GreaterEqualLess"]="⋛", +["Ll"]="⋘", +["nrarrw"]="↝̸", +["supnE"]="⫌", +["epsiv"]="ϵ", +["Element"]="∈", +["gtreqless"]="⋛", +["laemptyv"]="⦴", +["nGt"]="≫⃒", +["angsph"]="∢", +["lE"]="≦", +["kscr"]="𝓀", +["Ocy"]="О", +["LowerLeftArrow"]="↙", +["dopf"]="𝕕", +["iukcy"]="і", +["atilde"]="ã", +["DoubleRightArrow"]="⇒", +["oslash"]="ø", +["rarr"]="→", +["intprod"]="⨼", +["hookrightarrow"]="↪", +["intcal"]="⊺", +["infintie"]="⧝", +["escr"]="ℯ", +["iiota"]="℩", +["curren"]="¤", +["Bernoullis"]="ℬ", +["angmsdah"]="⦯", +["ShortRightArrow"]="→", +["boxUR"]="╚", +["ges"]="⩾", +["DoubleDownArrow"]="⇓", +["NotSquareSuperset"]="⊐̸", +["lsim"]="≲", +["bump"]="≎", +["curlyeqsucc"]="⋟", +["SHCHcy"]="Щ", +["frac45"]="⅘", +["qint"]="⨌", +["Precedes"]="≺", +["RightTeeArrow"]="↦", +["frac16"]="⅙", +["euro"]="€", +["smtes"]="⪬︀", +["eth"]="ð", +["ldquo"]="“", +["equivDD"]="⩸", +["Oopf"]="𝕆", ["boxVh"]="╫", -["Uuml"]="Ü", -["centerdot"]="·", -["isinsv"]="⋳", -["isins"]="⋴", -["bot"]="⊥", -["integers"]="ℤ", -["Racute"]="Ŕ", -["ijlig"]="ij", -["bernou"]="ℬ", -["Cconint"]="∰", -["doteq"]="≐", -["hookleftarrow"]="↩", -["epar"]="⋕", -["harrw"]="↭", -["dzigrarr"]="⟿", -["Zscr"]="𝒵", -["alpha"]="α", -["times"]="×", +["GreaterSlantEqual"]="⩾", +["KJcy"]="Ќ", ["egrave"]="è", -["UnionPlus"]="⊎", -["Qscr"]="𝒬", -["Omacr"]="Ō", -["Zfr"]="ℨ", -["gneq"]="⪈", -["divonx"]="⋇", -["gesdotol"]="⪄", -["gvertneqq"]="≩︀", -["geq"]="≥", -["utri"]="▵", -["ge"]="≥", -["vArr"]="⇕", -["Rrightarrow"]="⇛", -["frac25"]="⅖", -["LeftCeiling"]="⌈", -["GreaterGreater"]="⪢", -["LT"]="<", -["Longrightarrow"]="⟹", -["eqcolon"]="≕", -["ofcir"]="⦿", -["boxUl"]="╜", -["Wscr"]="𝒲", -["Sacute"]="Ś", -["Union"]="⋃", -["gg"]="≫", -["DownArrowBar"]="⤓", -["Escr"]="ℰ", -["ecirc"]="ê", -["Lmidot"]="Ŀ", -["Wedge"]="⋀", -["frown"]="⌢", -["ring"]="˚", -["dtdot"]="⋱", -["Ccedil"]="Ç", -["Conint"]="∯", -["dscr"]="𝒹", -["Map"]="⤅", -["EmptyVerySmallSquare"]="▫", -["backsim"]="∽", -["angzarr"]="⍼", -["dHar"]="⥥", -["Mfr"]="𝔐", -["cirE"]="⧃", -["Popf"]="ℙ", -["NestedGreaterGreater"]="≫", -["ReverseElement"]="∋", -["boxVr"]="╟", +["NotGreaterLess"]="≹", +["boxVl"]="╢", +["MediumSpace"]=" ", +["LongLeftArrow"]="⟵", +["uarr"]="↑", +["Ocirc"]="Ô", +["Idot"]="İ", +["bumpe"]="≏", +["nwArr"]="⇖", +["NegativeThinSpace"]="", +["coprod"]="∐", +["VerticalBar"]="∣", +["sccue"]="≽", +["boxDl"]="╖", +["NotSubset"]="⊂⃒", +["Edot"]="Ė", +["scy"]="с", +["Cup"]="⋓", +["centerdot"]="·", +["nsimeq"]="≄", +["DownLeftRightVector"]="⥐", } diff --git a/macros/luatex/generic/luaxml/luaxml-transform.lua b/macros/luatex/generic/luaxml/luaxml-transform.lua index b6841fea5f..4b51eed117 100644 --- a/macros/luatex/generic/luaxml/luaxml-transform.lua +++ b/macros/luatex/generic/luaxml/luaxml-transform.lua @@ -198,6 +198,10 @@ local function add_action(selector, template, parameters, csspar) end +local function reset_actions(selector, csspar) + local css = csspar or css + css:remove_selector(selector) +end --- Transform XML string @@ -243,7 +247,7 @@ end local Transformer --- Make new Transformer object --- @return Tranformer object +-- @return Transformer object local function new() local self = setmetatable({}, Transformer) self.css = cssquery() @@ -289,6 +293,12 @@ function Transformer:add_custom_action(selector, fn ) add_custom_action(selector, fn, self.css) end +--- Remove all actions that match the given selector +---@param selector string +function Transformer:reset_actions(selector) + reset_actions(selector, self.css) +end + -- all methods that use transformation functions must -- correctly handle the cssquery object that this library uses @@ -338,6 +348,7 @@ local M = { print_tex = print_tex, add_action = add_action, add_custom_action = add_custom_action, + reset_actions = reset_actions, simple_content = simple_content, load_file = load_file, process_dom = process_dom, diff --git a/macros/luatex/generic/luaxml/luaxml.pdf b/macros/luatex/generic/luaxml/luaxml.pdf Binary files differindex f574a0a528..071fa4e4cd 100644 --- a/macros/luatex/generic/luaxml/luaxml.pdf +++ b/macros/luatex/generic/luaxml/luaxml.pdf diff --git a/macros/luatex/generic/luaxml/luaxml.tex b/macros/luatex/generic/luaxml/luaxml.tex index 5031a0468e..bf3b8fbaa7 100644 --- a/macros/luatex/generic/luaxml/luaxml.tex +++ b/macros/luatex/generic/luaxml/luaxml.tex @@ -7,7 +7,7 @@ \usepackage{framed} % Version is defined in the makefile, use default values when compiled directly \ifdefined\version\else -\def\version{v0.1r} +\def\version{v0.2} \let\gitdate\date \fi \newcommand\modulename[1]{\subsection{#1}\label{sec:#1}} @@ -99,6 +99,67 @@ end \end{luacode*} \end{framed} +\subsection{HTML parsing} + +You can parse HTML documents using the \verb|DOM_Object.html_parse| function. This parser is slower +than the default XML parser, but it can load files that would cause errors in the XML mode. +It can handle wrongly nested HTML tags, inline JavaScript and CSS styles, and other HTML features +that would cause XML errors. + +\begin{verbatim} +dom = require "luaxml-domobject" +local document = [[ +<html> +<head><title>sample</title></head> +<body> +<h1>test</h1> +<p>hello +<p>another paragraph +<ul> +<li>first +<li>second +</ul> +</body> +</html> + ]] + +-- dom.html_parse returns the DOM_Object +obj = dom.html_parse(document) +-- print names of all elements contained in body +for _, x in ipairs(obj:query_selector("body *")) do + tex.print(x:get_element_name().. "\\par") +end +\end{verbatim} + + +\begin{framed} +\begin{luacode*} +dom = require "luaxml-domobject" +local document = [[ +<html> +<head><title>sample</title></head> +<body> +<h1>test</h1> +<p>hello +<p>another paragraph +<ul> +<li>first +<li>second +</ul> +</body> +</html> + ]] + +-- dom.html_parse returns the DOM_Object +obj = dom.html_parse(document) +-- print names of all elements contained in body +for _, x in ipairs(obj:query_selector("body *")) do + tex.print(x:get_element_name().. "\\par") +end +\end{luacode*} +\end{framed} + + \subsection{Void elements} The \verb|DOM_Object.parse| function tries to support the HTML void elements, @@ -641,6 +702,35 @@ transform.print_tex("\\verb|" .. result .. "|") \end{luacode*} \end{framed} +\section{Character sets handling} + +The \texttt{luaxml-encodings} library provides functions to convert texts in legacy 8-bit encodings such as WINDOWS-1250 +or ISO-8859-2 to UTF-8. This can be useful in fixing document encoding before HTML parsing using the \texttt{luaxml-mod-html} +library. + +\subsection{Example} + + +\begin{verbatim} +kpse.set_program_name "luatex" +local encodings = require "luaxml-encodings" + +--read HTML page from the standard input +local text = io.read("*all") +-- find the character encoding in HTML metadata +local enc = encodings.find_html_encoding(text) +if enc then + -- local conversion table for the found encoding + local mapping = encodings.load_mapping(enc) + if mapping then + -- if the mapping exists, recode the HTML input and print it + local converted = encodings.recode(text, mapping) + print(converted) + end +end +\end{verbatim} + + \section{The API documentation} |