diff options
author | Norbert Preining <norbert@preining.info> | 2025-02-10 03:06:01 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2025-02-10 03:06:01 +0000 |
commit | 11251344f7508667fd2c94d2ff940b64d1e4558a (patch) | |
tree | 95651765b07134eef12ba937438e884e258cf7b6 /macros/luatex/generic | |
parent | 6d43cd788622489915bdbcb025ab08c84f4ff54e (diff) |
CTAN sync 202502100306
Diffstat (limited to 'macros/luatex/generic')
33 files changed, 722 insertions, 562 deletions
diff --git a/macros/luatex/generic/minim-math/README b/macros/luatex/generic/minim-math/README index 24fe3397f1..8e3f841e41 100644 --- a/macros/luatex/generic/minim-math/README +++ b/macros/luatex/generic/minim-math/README @@ -1,4 +1,4 @@ -Version: 2024/1.4 +Version: 2025/1.5 SUMMARY @@ -18,6 +18,10 @@ In order to obtain the typeset manual of this package, simply say: HISTORY +2025/1.5 (12/2/2025) + + This version includes a new and experimental latex package. + 2024/1.4 (5/1/2024) * Add \floor and \ceil macros diff --git a/macros/luatex/generic/minim-math/minim-math.doc b/macros/luatex/generic/minim-math/minim-math.doc index 3648458b57..c46d288cb5 100644 --- a/macros/luatex/generic/minim-math/minim-math.doc +++ b/macros/luatex/generic/minim-math/minim-math.doc @@ -8,8 +8,8 @@ \else \startmetadata author {Esger Renkema} title {minim-math} - date {2024-01-05} - version {2024/1.4} + date {2025-02-12} + version {2025/1.5} keywords {LuaTeX; Plain TeX; Unicode mathematics} stopmetadata \maketitle \fi @@ -26,6 +26,26 @@ It will not, however, select mathematical fonts for you. That you will have to do for yourself; see below for instructions. +\section Experimental LaTeX support + +As of version 1.5, an experimental latex package is available as a faster +alternative to unicode-math. +The unicode-math user interface is not replicated though: it adds nothing to +the plain tex version but the ⟦\setfontfam⟧ macro for loading a math font. +Use it like this: + +{\leftskip2em +⟦\usepackage {minim-mp} +% additional fonts can be loaded with \setfontfam +\textfam = 1 % for the \text command; see below +\setfontfam \textfam {Latin Modern Roman} +% the next line is also the default +\setfontfam 0 {Latin Modern Math} ⟧ +\par} + +Bugs are likely many at this point; reports are welcome. + + \section Styles and alphabets For some (mostly alphabetical) characters, multiple variants are available, @@ -167,18 +187,17 @@ Do note that various spacing constants are set according to the \emph{last} math family that is assigned to. Therefore, you should assign your main math font to a family after all others. - -\section Shorthands and additions - You can use ⟦*\text⟧ for adding nonmathematical text to your equations. It will behave well in sub- and superscripts: ⟦\text{word}^\text{word}⟧ gives $\smash{\text{word}^\text{word}}$. By default, the font used is the normal mathematical font. You can change this by setting the ⟦*\textfam⟧ parameter to some nonzero value and assigning -a different font to that family (see above). -You probably want to do this, since most commonly-used mathematical fonts do not +a different font to that family. +You probably want this, since most commonly-used mathematical fonts do not include a normal kerning table. +\section Shorthands and additions + All the usual arrows can be made extensible by prefacing them with an ⟦x⟧, including ⟦\xmapsto⟧ and ⟦\xmapsfrom⟧. Alternatively, you can use ⟦\→⟧ etc. as shorthands. Additionally, you can use the following: @@ -214,9 +233,9 @@ brackets: ⟦$$\underbrace[=1]{(x^2+∥penalty0y^2)}$$⟧ gives $$\underbrace[=1]{(x^2 + y^2)}.$$ -Finally, the following (entirely optional) alternative to using dollar signs is -provided, which also offers slight improvements in the spacing of displayed -equations: +Finally, for plain tex only, the following (entirely optional) alternative to +using dollar signs is provided, which also offers slight improvements in the +spacing of displayed equations: \stopformulatagging\Ustartdisplaymath \halign{# \hfil&#\quad&#\hfil\cr &⟦\[ ... \]⟧&inline mathematics\cr @@ -227,7 +246,8 @@ equations: The automatic display numbering uses the count ⟦\equationnumber⟧ and the token list ⟦\setequationnumber⟧ internally. All displays created this way can be made -left-aligned by saying ⟦\leftdisplaystrue⟧. +left-aligned by saying ⟦\leftdisplaystrue⟧. In that case, the displays are +offset from the margin by ⟦\leftdisplayindent⟧ (a muskip, default value~⟦0mu⟧). \section Best practices diff --git a/macros/luatex/generic/minim-math/minim-math.lua b/macros/luatex/generic/minim-math/minim-math.lua index 2598094fdd..f9bafa5ced 100644 --- a/macros/luatex/generic/minim-math/minim-math.lua +++ b/macros/luatex/generic/minim-math/minim-math.lua @@ -169,13 +169,13 @@ end local alphabets = alloc.saved_table('math:alphabets') local function add_to_alphabet(num, code) - alphabets[code] = (alphabets[code] or '') .. string.utfcharacter(num) + alphabets[code] = (alphabets[code] or '') .. utf8.char(num) end local function chars_iterator(input) local a = alphabets[input] if a then - return string.utfvalues(a) + return a:utfvalues() else local from, to = string.match(input, '^([0-9]+)@([0-9]+)$') if from then @@ -185,7 +185,7 @@ local function chars_iterator(input) if i <= n then return gaps[i] or i end end else - return string.utfvalues(input) + return input:utfvalues() end end end @@ -249,14 +249,14 @@ M.greek_variants = } function M.usevariant (char) - for num in string.utfvalues (char) do + for _, num in utf8.codes(char) do local class, fam, _ = tex.getmathcodes(num) tex.setmathcode (num, class, fam, M.greek_variants[num] or num) end end function M.usedefault (char) - for num in string.utfvalues (char) do + for _, num in utf8.codes(char) do local class, fam, _ = tex.getmathcodes(num) tex.setmathcode (num, class, fam, num) end diff --git a/macros/luatex/generic/minim-math/minim-math.pdf b/macros/luatex/generic/minim-math/minim-math.pdf Binary files differindex 9544068d92..9e6509a0ae 100644 --- a/macros/luatex/generic/minim-math/minim-math.pdf +++ b/macros/luatex/generic/minim-math/minim-math.pdf diff --git a/macros/luatex/generic/minim-math/minim-math.sty b/macros/luatex/generic/minim-math/minim-math.sty new file mode 100644 index 0000000000..ec4141f004 --- /dev/null +++ b/macros/luatex/generic/minim-math/minim-math.sty @@ -0,0 +1,70 @@ + +\ProvidesPackage{minim-math}[2025/02/12 Unicode mathematics] + +\RequirePackage[no-math]{fontspec} + +% load the plain package +\let\minimmathlatex=\relax +\input minim-math + +% do not reset math fonts in everymath +\let\check@mathfonts = \relax +\let\mathgroup = \fam + +% unicode-math compatibility +\let \symup = \mup +\let \symbfup = \mbf +\let \symbf = \mbf +\let \symit = \mit +\let \symbfit = \mbfit +\let \symbb = \mbb +\let \symscr = \scr +\let \symcal = \scr +\let \symbfscr = \bfscr +\let \symfrak = \frak +\let \symbffrak = \bffrak +\def \symsfup #1{{\mathstyle{sf}}} +\def \symbfsfup #1{{\mathstyle{sfbf}}} +\def \symsfit #1{{\mathstyle{sfit}}} +\def \symbfsfit #1{{\mathstyle{sfbfit}}} +\def \symtt #1{{\mathstyle{tt}}} + +% more compatibility +\let \mathup = \symup +\let \mathbfup = \symbfup +\let \mathbf = \symbf +\let \mathit = \symit +\let \mathbfit = \symbfit +\let \mathbb = \symbb +\let \mathscr = \symscr +\let \mathcal = \symcal +\let \mathbfscr = \symbfscr +\let \mathfrak = \symfrak +\let \mathbffrak = \symbffrak +\let \mathsfup = \symsfup +\let \mathbfsfup = \symbfsfup +\let \mathsfit = \symsfit +\let \mathbfsfit = \symbfsfit +\let \mathtt = \symtt + +% \setmathfam 0 [features] {font name or file} +\newcount\set@mathfamcount +\protected\def\setmathfam{\afterassignment\set@mathfam\set@mathfamcount= } +\newcommand\set@mathfam[2][]{% + \calculate@math@sizes \csname S@\f@size\endcsname + \expandafter\font\csname math main font \the\set@mathfamcount\endcsname + {#2:mode=base;script=math;ssty=0;#1} at \tf@size pt + \expandafter\font\csname math script font \the\set@mathfamcount\endcsname + {#2:mode=base;script=math;ssty=1;#1} at \sf@size pt + \expandafter\font\csname math sscript font \the\set@mathfamcount\endcsname + {#2:mode=base;script=math;ssty=2;#1} at \ssf@size pt + \textfont\the\set@mathfamcount + \expandafter\csname math main font \the\set@mathfamcount\endcsname + \scriptfont\the\set@mathfamcount + \expandafter\csname math script font \the\set@mathfamcount\endcsname + \scriptscriptfont\the\set@mathfamcount + \expandafter\csname math sscript font \the\set@mathfamcount\endcsname} + +% load a default font +\setmathfam 0 {Latin Modern Math} + diff --git a/macros/luatex/generic/minim-math/minim-math.tex b/macros/luatex/generic/minim-math/minim-math.tex index 7029952418..f39a26aea2 100644 --- a/macros/luatex/generic/minim-math/minim-math.tex +++ b/macros/luatex/generic/minim-math/minim-math.tex @@ -1,6 +1,6 @@ \ifdefined \minimmathloaded - \message{(skipped)} + \wlog{(skipped)} \expandafter\endinput \fi \chardef\minimmathloaded=\catcode`: \catcode`:=11 @@ -543,22 +543,25 @@ % 1 Displayed equations +% \leftdisplaystrue +\newif\ifleftdisplays +\newif\ifdisplay: +\newif\ifdisplay:nr + +\ifdefined\minimmathlatex\else % for the latex package + % \display \protected\def\display{\display:true} % \displaynr {nr} \protected\def\displaynr{\display:true\display:nrtrue \nextifcat\bgroup\display:specialnr\relax} -% \leftdisplaystrue -\newif\ifleftdisplays % \setdisplaynr {...} \newtoks\setdisplaynr % \equationnumber \newcount\equationnumber \equationnumber = 0 \setdisplaynr{\global\advance\equationnumber1(\the\equationnumber)} -\newif\ifdisplay: -\newif\ifdisplay:nr \newtoks\display:specialnr \display:specialnr{\the\setdisplaynr} @@ -572,6 +575,9 @@ \ifdefined \tagging:tagformula \else \let\tagging:tagformula=\ignore \fi +\newmuskip\leftdisplayindent +\leftdisplayindent = 0mu + \protected\def\startdisplay{% % if the display starts a paragraph, omit baselineskip % and ensure that the long \beforedisplayskip is used @@ -581,7 +587,7 @@ % compatibility with minim-pdf \csname tagging:indisplaytrue\endcsname % for left-aligned equations, force manual placement - \ifleftdisplays\muskip0mu\fi} + \ifleftdisplays\mskip\leftdisplayindent\relax\fi} \protected\def\stopdisplay{% \ifleftdisplays \hskip\displaywidth minus\displaywidth\fi @@ -592,6 +598,7 @@ \Ustopdisplaymath \ignorespaces} +\fi % standard mappings diff --git a/macros/luatex/generic/minim-mp/README b/macros/luatex/generic/minim-mp/README index bf03e5114e..36dd3ffb15 100644 --- a/macros/luatex/generic/minim-mp/README +++ b/macros/luatex/generic/minim-mp/README @@ -1,4 +1,4 @@ -Version: 2024/1.6 +Version: 2025/1.7 SUMMARY @@ -40,22 +40,33 @@ Useful shell aliases are HISTORY +2025/1.7 (12/2/2025) + + This version contains a re-organised and improved manual. + 2024/1.6 (25/3/2024) New features: - * Add per-instance \everymp token lists + * Add per-instance \everymp token lists. + * Provide \mpdim to the latex package. + * Also accept (postscript) font names instead of ids as arguments to the + infont and glyph of operators. * Reduce the number of metapost error messages echoed to the terminal. - * The operators infont and glyph of now also accept font names. - * Provide \mpdim to latex class. + * Add the missing tex.skip macro (read-only). + * Provide more information in debugging mode; standardise its lay-out and + only write debugging info to the log, not to the terminal. Bug fixes: - * Newlines are now handled by metapost too. - * As are all special characters: #$%^&_~ - * Plain and luatex now use the same catcode regime. - * Add the missing tex.skip macro. - * Improve debugging messages. + * Re-work the scanning of metapost code: preserve not only %s but also + newlines; neutralise all other special characters. Only spaces and + csnames are pre-treated on the tex side. + * This means comments are now passed to metapost and handled there. + * Apply the same metapost code scanning method to both plain macros and + latex environments. + * Remove the grouping around metapost code execution in the latex + environments. 2024/1.5 (25/2/2024) @@ -67,7 +78,6 @@ HISTORY Bug fixes: * Make metafun not crash immediately. - * Comments (% characters) are now handled by metapost, not tex. 2024/1.4 (5/1/2024) diff --git a/macros/luatex/generic/minim-mp/minim-mp.doc b/macros/luatex/generic/minim-mp/minim-mp.doc index 9b4806807d..103490ec42 100644 --- a/macros/luatex/generic/minim-mp/minim-mp.doc +++ b/macros/luatex/generic/minim-mp/minim-mp.doc @@ -8,40 +8,19 @@ \else \startmetadata author {Esger Renkema} title {minim-mp} - date {2024-03-25} - version {2024/1.6} + date {2025-02-12} + version {2025/1.7} keywords {LuaTeX; Plain TeX; MetaPost; mplib} stopmetadata \maketitle \fi -This package offers low-level mplib integration for plain luatex. -The use of multiple simultaneous metapost instances is supported, as well as -running tex or lua code from within metapost. -In order to use it, simply say ⟦\input minim-mp.tex⟧. - +This package provides low-level mplib integration for plain lua(la)tex. In +order to use it, simply say ⟦\input minim-mp.tex⟧ (from plain tex) or +⟦\requirepackage {minim-mp}⟧ from latex. After this, ⟦*\directmetapost [ options ] { mp code }⟧ will result in a series of images corresponding to the ⟦beginfig() ... endfig;⟧ statements in your ⟦mp code⟧. Every image will be in a box of its own. -The metapost code to-be-run will be read under a special catcode regime in -which most ‘special’ characters (including {\tt\#} and {\tt\%}) are inert. -However, any control sequences will be expanded fully, as inside an ⟦\edef⟧. -Keep this in mind and define any macros you want to use in a ⟦btex ... etex;⟧ -environment as ⟦\protected⟧ (with the latex package, latex’s ‘protected’ macros -are safe-to-use, too). - -Every call to ⟦\directmetapost⟧ opens and closes a separate metapost instance. -If you want your second call to remember the first, you will have to define -a persistent metapost instance. This will also give you more control over image -extraction. See below under „Metapost instances”. The ⟦options⟧ will also be -explained there (for simple cases, you will not need them). - -The logs of the metapost run will be embedded in the regular log file. If an -error occurs, the log of the last snippet will also be shown on the terminal. - - -\section As a stand-alone Metapost compiler %1 - This package can also be used as a stand-alone metapost compiler. Saying \stopformulatagging$$\hbox{⟦luatex --fmt=minim-mp your_file.mp⟧}$$\startformulatagging will create a pdf file of all images in ⟦your_file.mp⟧, in order, with page @@ -55,153 +34,230 @@ With minim-lamp, for specifying the contents of the preamble, you can use Concluding the preamble with ⟦\begin{document}⟧ is optional, as both ⟦\begin⟧ and ⟦\end{document}⟧ will be inserted automatically if omitted. +\subsection TeX-MetaPost compatibility notes %1 + +All metapost code to-be-run will be read under a special catcode regime in +which most ‘special’ characters (including {\tt\#} and {\tt\%}) are inert. +Any control sequences will be expanded fully, however, as inside an ⟦\edef⟧. +Keep this in mind and define any macros you want to use in a ⟦btex ... etex;⟧ +environment as ⟦\protected⟧. With the latex package, latex’s ‘protected’ macros +are safe-to-use, too. + +Every call to ⟦\directmetapost⟧ opens and closes a separate metapost instance. +If you want your second call to remember the first, you will have to define +a persistent metapost instance. This will also give you more control over image +extraction. See below under „Metapost instances”. The ⟦options⟧ will also be +explained there (for simple cases, you will not need them). -\section LaTeX compatibility %1 +\subsection LaTeX compatibility notes %1 -An experimental latex package is included in ⟦minim-mp.sty⟧. It really is -a rather thin wrapper around the plain tex package, -but does provide a proper ⟦*metapost⟧ latex environment as an -alternative to ⟦\directmetapost⟧. +The latex package minim-mp.sty contains the full plain interface, but also +provides a proper ⟦*metapost⟧ environment as an alternative to +⟦\directmetapost⟧. The ⟦metapost⟧ environment has no persistent backing instance, but you can create a similar environment ⟦envname⟧ that does with ⟦*\newmetapostenvironment [options] {envname}⟧. -If your demands are even more complex, you should fall back to the plain tex -commands described in the next section. - -As in luamplib, you can use ⟦*\mpcolor {name}⟧ to insert the proper colour -values; this macro is only available inside the above environments. -A ⟦\mpdim⟧ macro is present too, but quite superfluous: since the contents of -the metapost environments are fully expanded before metapost sees them, you can -use ⟦\the⟧ and ⟦\the\dimexpr⟧ like everywhere else. Tex’s registers can also be -accessed by metapost itself (see below). - -When the package is loaded with the option ⟦luamplib⟧, minim-mp will try and -act as a drop-in replacement for luamplib. The effort made is not very great -though, but it will define an ⟦mplibcode⟧ environment, as well as the + +Inside the above environments, you can use ⟦*\mpcolor {name}⟧ to insert the +proper colour values. Unlike in luamplib, this will work in any context where +metapost expects a colour. +An ⟦\mpdim⟧ macro is present too, but quite superfluous since the contents of +the metapost environments are fully expanded before metapost sees them: this +means you can use ⟦\the⟧ and ⟦\the\dimexpr⟧ like everywhere else. Tex’s +registers can also be accessed from within metapost itself (see below). + +When the package is loaded with the option ⟦*luamplib⟧, minim-mp will try and +act as a drop-in replacement for luamplib. The effort made is not very great, +but it will define an ⟦mplibcode⟧ environment, as well as the ⟦\mplibcodeinherit⟧, ⟦\mplibshowlog⟧, ⟦\mplibsetformat⟧ and ⟦\mplibnumbersystem⟧ switches; also the macros ⟦\everymplib⟧ and ⟦\everyendmplib⟧. -Please do note that this is not the recommended way of using minim-mp, which -remains the interface documented above and further in the next section. +\subsection MetaFun compatibility notes %1 -\section Metapost instances %1 +The metafun format is supported to the extent that it should not immediately crash. +Otherwise, useing metafun is neither supported nor recommended. -For more complicated uses, you can define your own instances by saying -⟦*\newmetapostinstance [ options ] \id⟧. -An instance can be closed with ⟦*\closemetapostinstance \id⟧. -The ⟦options⟧ are directly passed to lua, as a table, and can contain the -following keys: +% -\smallskip\smallskip\automarktable -\halign{#\quad\hfil&#\quad\hfil&#\hfil\cr -Option&Default&Description\cr -⟦jobname⟧&⟦':metapost:'⟧&Used in error messages.\cr -⟦format⟧&⟦'plain.mp'⟧&Format to initialise the instance with.\cr -⟦mathmode⟧&⟦'scaled'⟧&One of ⟦scaled⟧, ⟦decimal⟧ or ⟦double⟧.\cr -⟦seed⟧&⟦nil⟧&Random seed for this instance.\cr -⟦catcodes⟧&(internal value)&Catcode table for ⟦btex ... etex⟧.\cr -⟦env⟧© of ⟦_G⟧&Lua environment; see below.\cr -}\smallskip +\section Metapost extensions %1 -Now that you have your own instance, you can run chunks of metapost code in it -with ⟦*\runmetapost \id { code }⟧. Any images that your code may have contained -will have to be extracted explicitly. This is possible in a number of ways, -although each image can be retrieved only once. +You can set the baseline of an image with ⟦*baseline(p)⟧. There, ⟦p⟧ must +either be a point through which the baseline should pass, or a number (where an +x~coordinate of zero will be added). Transformations will be taken into +account, hence the specification of two coordinates. The last given baseline +will be used. -⟦*\getnextmpimage \id⟧ -– Writes the first unretrieved image to the current node list. -There, the image will be contained in a single box node. +You can write to tex’s log directly with ⟦*texmessage "hello";⟧. You can feed +it a comma-separated list of strings and numbers, which will be passed through +⟦string.format()⟧ first. -⟦*\getnamedmpimage \id {name}⟧ -– Retrieves an image by name -and writes it to the current node list. +You can write direct pdf statements with ⟦*special "pdf: statements"⟧ and you +can add comments to the pdf file with ⟦*special "pdfcomment: comments"⟧. +Say ⟦*special "latelua: lua code"⟧ to insert a ⟦late_lua⟧ whatsit. +All three specials can also be given as pre- or postscripts to another object. +In that case, they will be added before or after the object they are attached to. +Do note that all ⟦special⟧ statements will appear at the beginning of the +image; use pre- and postscripts to drawing statements if the order matters. -⟦*\boxnextmpimage \id box-nr⟧ -– Puts the next unretrieved image in box ⟦box-nr⟧. The number may be anything -tex can parse as a number. +\subsection Partial paths and the even-odd rule %2 -⟦*\boxnamedmpimage \id box-nr {name}⟧ -– Puts the image named ⟦name⟧ in box ⟦box-nr⟧. +While metapost fills paths according to the winding number, the pdf format also +supports filling according to the even-odd rule. You can use this method with +the ⟦*eofill⟧ and ⟦*eofilldraw⟧ drawing statements. Multiple contours can be +filled at once if all but the last are drawn with ⟦*nofill⟧. The latter is +especially useful for cutting something out of a shape, as it saves you the +hassle of stitching the paths together. -Say ⟦*\remainingmpimages \id⟧ for the number of images not yet retrieved -and ⟦*\getallmpimages \id⟧ to insert all remaining images. +The macros ⟦*multi(draw|fill|filldraw|eofill|eofilldraw)⟧ take a list of paths +between parentheses and can be followed by the usual drawing options. +For example, +⟦multidraw (contours "example" of "tenbf") withpen currentpen scaled 1/10;⟧ +will give the word% +\markelement{Span}{\setactualtext{example }\startsinglecontentitem\space +\directmetapost [jobname='outline'] +{beginfig(1) multidraw (contours "example" of "tenbf") +withpen currentpen scaled 1/10; baseline 0; endfig;}\stopsinglecontentitem} +in a thin outline. -Finally, as a shorthand, ⟦*\runmetapostimage \id { code }⟧ will add -⟦beginfig ... endfig;⟧ to your ⟦code⟧ and write the resulting image immediately -to the current list. +The clipping shorthands ⟦*clipout⟧ and ⟦*clipto⟧ take a list of paths as +a ‘text’ parameter and either clip their ensemble out of the current picture, +or the current picture to the ensemble. +You will have to ensure yourself that the path has the right orientation for +clipping (i.e. you may have to insert the proper ⟦reverse⟧ operator yourself). -Associated to every instance are four token registers containing tex and/or -metapost code to be inserted before or after each executed chunk. -You can access them with ⟦*\everymp \id {pre|post} {tex|mp}⟧. -The token lists where ${\tt id}=0$ do not correspond to any instance and will -apply to every instance instead. -All four token lists are empty by default if you use minim-mp with plain tex. -The latex package, on the other hand, uses them for its own purposes, so take -care in that case to use ⟦\tokspre⟧ and ⟦\toksapp⟧ instead of overwriting their -contents. As a bonus, when using the latex package, you can use the environment -name instead of the numerical ⟦\id⟧. +\subsection Tiling patterns %2 +The specification ⟦*withpattern(<name>)⟧ added to a ⟦fill⟧ statement will fill +the path with a pattern instead of a solid colour. If the pattern itself does +not contain any colour statements, it will have the colour given by ⟦withcolor⟧. +Stroking operations (the ⟦draw⟧ part) will not be affected. +Patterns will always look the same, irrespective of any transformations you +apply to the picture. -\section Lua interface %1 +To define a pattern, sketch it between +⟦*beginpattern(<name>) ... endpattern(xstep, ystep);⟧ +where ⟦<name>⟧ is a suffix and ⟦(xstep, ystep)⟧ are the horizontal and vertical +distances between applications of the pattern. +Inside the definition, you can draw the pattern using whatever coordinates you +like; assign a value to the ⟦*matrix⟧ transformation to specify how the pattern +should be projected onto the page. This ⟦matrix⟧ will also be applied to +⟦xstep⟧ and ⟦ystep⟧. -In what follows, you should assume ⟦M⟧ to be the result of -\stopformulatagging$$\hbox{⟦M = require('minim-mp')⟧}$$\startformulatagging -as this package does not claim a table in the global environment for itself. +You can also change the internal variable ⟦*tilingtype⟧ and the normal variable +⟦*painttype⟧, although the latter will be set to~1 automatically if you use any +colour inside the pattern definition. Consult the pdf specification for more +information on these parameters. -You can open a new instance with ⟦*nr = M.open {options}⟧. -This returns an index in the ⟦*M.instances⟧ table. -Run code with ⟦*M.run (nr, code)⟧ and close the instance with ⟦*M.close (nr)⟧. -Images can be retrieved only with ⟦*box_node = M.get_image(nr, [name])⟧; omit -the ⟦name⟧ to select the first image. -Say ⟦*nr_remaining = M.left(nr)⟧ for the number of remaining images. +You can use text inside patterns, as in this example: +\hfill \vbox to 0pt{ +\startelement alt{A circle filled with red As in a rectangular pattern.}{Figure} +\startsinglecontentitem \directmetapost [jobname='pattern'] +{% define the pattern +picture letter; letter = maketext("a"); +beginpattern(a) + draw letter rotated 45; + matrix = identity rotated 45; +endpattern(12pt,12pt); +% use the pattern +beginfig(1) + fill fullcircle scaled 3cm withpattern(a) withcolor 3/4red; + draw fullcircle scaled 3cm withpen pencircle scaled 1; +endfig;}\stopsinglecontentitem +\stopelement{Figure}\vss}\hskip10pt\strut +\par\nobreak +⟦% define the pattern +picture letter; letter = maketext("a"); +beginpattern(a) + draw letter rotated 45; + matrix = identity rotated 45; +endpattern(12pt,12pt); +% use the pattern +beginfig(1) + fill fullcircle scaled 3cm withpattern(a) withcolor 3/4red; + draw fullcircle scaled 3cm withpen pencircle scaled 1; +endfig;⟧ -Each metapost instance is a table containing the following entries: +A small pattern library is available in the ⟦*minim-hatching.mp⟧ file; see the +accompanying documentation sheet for an overview of patterns. -\smallskip\smallskip -\marktableaslist -\tagattribute List ListNumbering /Description -\halign{\qquad#\quad\hfil&#\hfil\cr -⟦jobname⟧&The jobname.\cr -⟦instance⟧&The primitive metapost instance.\cr -⟦results⟧&A linked list of unretrieved images.\cr -⟦status⟧&The last exit status (will never decrease).\cr -⟦catcodes⟧&Number of the catcode table used with ⟦btex ... etex⟧.\cr -⟦env⟧&The lua environment for ⟦runscript⟧.\cr} -Default values for the format and number system are available in the -⟦*M.default_format⟧ and ⟦*M.default_mathmode⟧ variables. -The full initialisation sequence for new instances (i.e. the first metapost -chunk, that is executed automatically) is contained in the ⟦*M.init_code⟧ -table. +\subsection Box resources %2 + +Box resources (XForms) saved by tex can be included with ⟦*boxresource nr⟧. +(Note that ⟦nr⟧ is not a box number, but the index returned by +⟦\lastsavedboxresourceindex⟧.) +The result will be an image object with the proper dimensions. This image can +be transformed in any way you like, but you cannot inspect the contents of the +resource within metapost. +Box resources can also be created from within metapost: ⟦<id> =⟧ +⟦*saveboxresource (<attributes>) <picture>⟧ returns a number identifying the +resource. The ⟦<attributes>⟧ can be given in the same way as the arguments to +⟦setgstate⟧ (see below). XForms defined through metapost are available to other +metapost instances but not to tex; they are drawn with the same command +(⟦boxresource nr⟧). +There remains a subtle difference, however: metapost-defined box resources are +placed at their original origin, tex-defined resources at their lower left +corner. -\section Logs and debugging %1 -Metapost log output of every processed chunk of metapost code will be printed -to the main log file in a quoted form. -The logs will be duplicated to the terminal if an error occurs or if the -variable ⟦*M.on_line⟧ is ⟦true⟧ (the default is ⟦false⟧, but set to ⟦true⟧ in -the stand-alone format files). -Because a single error message might trigger many others, log output to the -terminal (but not the log file) will be cut after a certain number of errors: -this behaviour is governed by the ⟦*M.max_errprint⟧ variable (default ⟦1⟧; set -to ⟦0⟧ to disable). +\subsection Advanced PDF graphics %2 -You can enable (global) debugging by saying ⟦*debug_pdf⟧ to metapost, -⟦*\debugmetapost⟧ to tex or ⟦*M.enable_debugging()⟧ to lua. This will write -out a summary of metapost object information to the pdf file, just above the -pdf instructions that object was translated into. For this purpose, the pdf -will be generated uncompressed. Additionally, the metapost code itself will be -echoed to the log, as well as ⟦runscript⟧ and ⟦maketext⟧ invocations, and -a small summary of every generated image will be written to log and terminal. +You can use ⟦*savegstate⟧ and ⟦*restoregstate⟧ for inserting the ⟦q⟧ and ⟦Q⟧ +operators; these must always be paired, or horrible errors will occur. You may +need them if you use ⟦*setgstate(<params>)⟧ for modifying the extended +graphical state (ExtGState). The ⟦params⟧ must be a comma-separated +⟦Key=value⟧ list, with all ⟦value⟧s being suffixes. The latter restriction may +require the use of additional variables, but as this is a very low-level +command, it is best to wrap it in a more specialised macro anyway. +The ⟦*withgstate (<params>)⟧ can be added to a drawing statement and includes +saving/restoring the graphical state. -For debugging the results of ⟦maketext⟧ and the like, you can set the -⟦*debug_tex_bboxes⟧ variable to ⟦true⟧ and have their resulting bounding boxes -drawn on the pdf. +Note that while you could try and use ⟦setgstate⟧ for modifying variables like +the line cap or dash pattern, the result of doing so will be unpredictable, +since such changes will be invisible to metapost. Its intended use is +restricted to graphics parameters outside metapost’s scope. -\section Running tex from within metapost %1 +\subsection Transparency + +For applying transparency, ⟦*setalpha(a)⟧ updates the ⟦CA⟧ and ⟦ca⟧ parameters +as a stand-alone command and ⟦*withalpha(a)⟧ can be used in a drawing statement +where it will save/restore the graphical state around it. For applying +transparency to an ensemble of drawing statements, ⟦*transparent (a) <picture>⟧ +instead of ⟦draw <picture>⟧ will create and insert the proper transparency group. +The transparency group attributes can be set with the string internal +⟦*transparency_group_attrs⟧, while for all three macros the blend mode can be +set with the string internal ⟦*blend_mode⟧ (it will be added whenever set). + + +\subsection Additions to plain.mp %2 + +Minim-mp provides a few elementary macros and constants that are conspicuously +absent from plain.mp; I hope their addition is uncontroversial. All are +provided in the file minim.mp. This file is safe for use with other metapost +processors. + +The constants are ⟦*pi⟧ (355/113), ⟦*fullsquare⟧, ⟦*unitcircle⟧ and the +cmyk-colours ⟦*cyan⟧, ⟦*magenta⟧, ⟦*yellow⟧ and ⟦*key⟧. The macros are +⟦*clockwise⟧, ⟦*xshifted⟧, ⟦*yshifted⟧, ⟦*hflip⟧ and ⟦*vflip⟧, where the flips +are defined in such a way that ⟦p & hflip p⟧ gives the expected result. + +Version 1.2 brought the following additions: ⟦*save_pair⟧, ⟦*save_path⟧ etc. +etc. that save and declare in one go; the missing trigonometric functions +⟦*tand⟧, ⟦*arcsind⟧, ⟦*arccosd⟧ and ⟦*arctand⟧, and the unit circle segment +drawing function ⟦*arc(⟧$θ_0$⟦*,⟧$θ_ℓ$⟦*)⟧ (taking a starting angle and arc +length, both in degrees). + +Version 1.6 brought ⟦*empty⟧ for testing empty suffixes, ⟦*typeof(v)⟧ +expanding to the type (⟦numeric⟧, ⟦pair⟧ etc.) of variable ⟦v⟧, +⟦*getbounds⟧ as complement to ⟦setbounds⟧, the (twodimensional) exterior product +⟦*p extprod q⟧ and the test ⟦*collinear(p,q,r)⟧. + +% + +\section Running tex code %1 You can include tex snippets with either ⟦*maketext "tex text"⟧ or ⟦*btex ... etex⟧ statements. The tex code will be executed in the current @@ -214,10 +270,13 @@ Arbitrary tex statements may be included in ⟦*verbatimtex ... etex⟧, which m occur anywhere. These ⟦btex⟧ and ⟦verbatimtex⟧ statements are executed in the order they are given. -Previously-defined box resources can be included with ⟦*boxresource(nr)⟧. The -result will be an image object with the proper dimensions. This image can be -transformed in any way you like, but you cannot inspect the contents of the -resource within metapost. +When including tex code in metapost, do keep in mind that every metapost +snippet read by ⟦\directmetapost⟧ or ⟦\begin{metapost}⟧ will be expanded fully +(as inside an ⟦\edef⟧) before execution. This may expand your macros too early! +The best solution is to define your own macros as ⟦\protected⟧ or using latex’s +more convoluted protection equivalent, although a well-placed ⟦\noexpand⟧ or, +as a last resort, wrapping the entire tex fragment in ⟦\unexpanded{...}⟧ will +work as well. You can also use metapost’s ⟦*infont⟧ operator, which restricts the text to-be-typeset to a single font, but returns an ⟦picture⟧ containing a ⟦picture⟧ @@ -226,7 +285,7 @@ a (numerical) font~id or the (cs)name of a font (without backslash). A traditional font name (e.g. ‘cmtt10’) is also accepted; this will silently load the font. -One possible use of the ⟦infont⟧ operator is setting text along curves: +One possible use of the ⟦infont⟧ operator is setting text along curves: %2 \goodbreak ⟦beginfig(1) @@ -242,7 +301,7 @@ One possible use of the ⟦infont⟧ operator is setting text along curves: endfig;⟧ \vskip-2\parskip plus 2\parskip \quitvmode\hfil -\startelement alt {The text ‘Running TeX from within MetaPost’ set along a half-circle.} {Figure}% +\startelement alt {The text „Running TeX from within MetaPost” set along a half-circle.} {Figure}% \startsinglecontentitem\directmetapost [jobname='tex-in-mp'] {% beginfig(1) save t, w, r, a; picture t; @@ -260,52 +319,65 @@ By default, the ⟦maketext⟧ operator is used for typesetting labels. You can, however, order de ⟦label⟧ macro to use ⟦infont⟧ instead by setting ⟦*maketextlabels⟧ to ⟦false⟧. -For the greatest amount of control, you can use the ⟦*glyph g of f⟧ -operator, which returns the contours that make up a glyph. It is a bit more -versatile than its traditional metapost counterpart: ⟦g⟧ may also be the name -of the glyph instead of its index, while ⟦f⟧ can be a font~id or font name (as -with ⟦infont⟧). +\subsection Access to font contours %2 + +Both the ⟦maketext⟧ and ⟦infont⟧ operators return pictures that are opaque to +metapost. For accessing the contours that make up the characters in a string, +you will need the ⟦*glyph g of f⟧ operator. +It is a bit more versatile than its traditional metapost +counterpart: ⟦g⟧ may also be the name of the glyph instead of its index, while +⟦f⟧ can either be a font~id or font name (as with ⟦infont⟧). -A variant of ⟦glyph of⟧ is the ⟦*contours t of f⟧ macro: it first typesets the -string ⟦t⟧ in the same way as ⟦infont⟧ does (so that kerning and font shaping -are applied), but returns a (comma-separated) list of contours, such as may be -used in a ⟦for⟧ loop. Due to rounding errors, the glyphs will not match exactly. +A variant of ⟦glyph of⟧ is the ⟦*contours s of f⟧ macro, which first typesets +the string ⟦s⟧ in the same way as ⟦infont⟧ does (so that kerning and font +shaping are applied), but returns a (comma-separated) list of contours. This +list is fit for use in a for loop. Note that due to rounding errors, the glyph +contours will not match the output of ⟦infont⟧ exactly. -Be aware that the contours returned by these operators may be disjoint: -a letter ⟦o⟧, for example, will consists of two. This means you cannot recreate -the characters by just filling each contour: this would turn the ⟦o⟧ into -a filled-in circle. Instead, you must use ⟦multifill⟧ on the entire output of -⟦glyph of⟧ or ⟦contours of⟧ (see below under ‘partial paths’). +Be also aware that the contours returned by these operators may be disjoint: +a letter ⟦o⟧, for example, will consists of two paths. This means you cannot +recreate the characters by just filling each contour, as that would turn the +⟦o⟧ into a filled-in circle. Instead, you must use ⟦multifill⟧ on the entire +output of ⟦glyph of⟧ or ⟦contours of⟧ (see above under „Partial paths”). +% -\section Running lua from within metapost %1 +\section Running lua code %1 You can call out to lua with ⟦*runscript "lua code"⟧. For this purpose, each metapost instance carries around its own lua environment so that assignments -you make are local to the instance. (You can of course order the global -environment to be used by giving ⟦env = _G⟧ as option to -⟦\newmetapostinstance⟧.) -Any environment you specify will be supplemented with the contents of the -⟦*M.mp_functions⟧ table. Two useful functions pre-supplied are ⟦quote(s)⟧, -which escapes all double quotes in the string ⟦s⟧ before surrounding it with -the same (so that it may be read as a metapost string literal); and -⟦sp_to_pt(nr)⟧, which prints dimensions in points (preventing overflows). - -When using ⟦runscript⟧ in this way, you must ensure its argument is a correct -lua program. As an escape hatch, raw strings can be passed to lua with +you make are local to the instance. (The global environment can still be +accessed behind the ⟦_G⟧ variable.) + +Every runscript environment is augmented with a small set of useful functions; +this set can be found in the ⟦*M.mp_functions⟧ table (with +⟦M = require 'minim-mp'⟧; see below under „Lua interface”). + +When using ⟦runscript⟧, you must ensure its argument is a correct lua program. +As an escape hatch, raw strings can be passed to lua with ⟦runscript ("[[function_name]]" & raw_string)⟧. This will return the result of the function ⟦function_name⟧ applied to ⟦raw_string⟧ as a lua string. +\subsection Returning values from lua %2 + If your lua snippet returns nothing, the ⟦runscript⟧ call will be invisible to metapost. If on the other hand it does return a value, that value will have to -be translated to metapost. Numbers and strings will be returned as they are -(so make sure the string is surrounded by quotes if you want to return -a metapost string). You can return a point, colour or transform by returning an -array of two to six elements (excluding five). For other return values, -⟦tostring()⟧ will be called. - -\section Passing values to lua +be translated to something metapost can understand. +You can return a point, colour or transform by returning an array of two to six +elements (excluding five). +Numbers and strings will be returned as they are. +For other return values, ⟦tostring()⟧ will be called. + +Note that lua strings will be returned as metapost code, not as metapost string +literals! If you want to return the latter, you must quote the string yourself; +the runscript environment contains a ⟦*quote(s)⟧ function for this purpose, +which also escapes all double quotes in the string~⟦s⟧. +When returning dimensions, you must be wary of arithmetic overflows: every +useful dimension expressed in scaled points will be too large for metapost. Use +⟦*sp_to_pt(nr)⟧ instead, which converts dimensions to points. + +\subsection Passing values to lua %2 Do keep in mind that metapost and lua represent numbers in different ways and that rounding errors may occur. For instance, metapost’s ⟦decimal epsilon⟧ @@ -324,8 +396,7 @@ A generic macro for passing values to lua, finally, is ⟦*quote_for_lua⟧, whi automatically converts strings, numbers, points and colours to (metapost) strings that lua can understand. - -\section Querying tex and lua variables +\subsection Querying tex and lua variables %2 Stitching together lua snippets by hand is not very convenient. Therefore, minim-mp provides three helper macros that should cover most lua interaction. @@ -346,174 +417,112 @@ For accessing count, dimen, attribute or toks registers, the macros are ⟦*set tex.count⟧ ⟦[number] = value⟧ or ⟦*set tex.count⟧⟦.name = value⟧ etc. for setting values. +% -\section Partial paths and the even-odd rule %1 - -You can fill or draw two or more disjoint paths in one go by using ⟦*nofill⟧ as -drawing operator for all paths but the last. This may make it easier to cut -something out of a shape, since you do not have to worry about stitching the -paths together. - -While metapost fills paths according to the winding number, the pdf format also -supports filling according to the even-odd rule. You can use that method -with the ⟦*eofill⟧ and ⟦*eofilldraw⟧ drawing statements, which can of course -also be used as the final statement after a series of nofills. - -The macros ⟦*multi(draw|fill|filldraw|eofill|eofilldraw)⟧ take a list of paths -between parentheses and can be followed by the usual drawing options. -For example, -⟦multidraw (contours "example" of "tenbf") withpen currentpen scaled 1/10;⟧ -will give the word% -\markelement{Span}{\setactualtext{example }\startsinglecontentitem\space -\directmetapost [jobname='outline'] -{beginfig(1) multidraw (contours "example" of "tenbf") -withpen currentpen scaled 1/10; baseline 0; endfig;}\stopsinglecontentitem} -in a thin outline. - -Finally, two handy clipping macros have been added: -⟦*clipout⟧ and ⟦*clipto⟧, which both receive a list of paths as a ‘text’ -parameter and either clip their ensemble out of the picture, or the picture to -the ensemble. - - -\section Tiling patterns %1 +\section Metapost instances %1 -The specification ⟦*withpattern(<name>)⟧ added to a ⟦fill⟧ statement will fill -the path with a pattern instead of a solid colour. If the pattern itself does -not contain any colour statements, it will have the colour given by ⟦withcolor⟧. -Stroking operations (the ⟦draw⟧ part) will not be affected. -Patterns will always look the same, irrespective of any transformations you -apply to the picture. +You can define a new persistent metapost instance with +⟦*\newmetapostinstance [ options ] \id⟧. +An instance can be closed with ⟦*\closemetapostinstance \id⟧. +The ⟦options⟧ are directly passed to lua, as a table, and can contain the +following keys: -To define a pattern, sketch it between -⟦*beginpattern(<name>) ... endpattern(xstep, ystep);⟧ -where ⟦<name>⟧ is a suffix and ⟦(xstep, ystep)⟧ are the horizontal and vertical -distances between applications of the pattern. -Inside the definition, you can draw the pattern using whatever coordinates you -like; assign a value to the ⟦*matrix⟧ transformation to specify how the pattern -should be projected onto the page. This ⟦matrix⟧ will also be applied to -⟦xstep⟧ and ⟦ystep⟧. +\smallskip\smallskip\automarktable +\halign{#\quad\hfil&#\quad\hfil&#\hfil\cr +Option&Default&Description\cr +⟦jobname⟧&⟦':metapost:'⟧&Used in error messages.\cr +⟦format⟧&⟦'plain.mp'⟧&Format to initialise the instance with.\cr +⟦mathmode⟧&⟦'scaled'⟧&One of ⟦scaled⟧, ⟦decimal⟧ or ⟦double⟧.\cr +⟦seed⟧&⟦nil⟧&Random seed for this instance.\cr +⟦catcodes⟧&(internal value)&Catcode table for ⟦btex ... etex⟧.\cr +⟦env⟧© of ⟦_G⟧&Lua environment for ⟦runscript⟧.\cr +}\smallskip -You can also change the internal variable ⟦*tilingtype⟧ and the normal variable -⟦*painttype⟧, although the latter will be set to~1 automatically if you use any -colour inside the pattern definition. Consult the pdf specification for more -information on these parameters. +See below under „Lua interface” for greater control over these parameters. -You can use text inside patterns, as in this example: -\hfill \vbox to 0pt{ -\startelement alt{A circle filled with red As in a rectangular pattern.}{Figure} -\startsinglecontentitem \directmetapost [jobname='pattern'] -{% define the pattern -picture letter; letter = maketext("a"); -beginpattern(a) - draw letter rotated 45; - matrix = identity rotated 45; -endpattern(12pt,12pt); -% use the pattern -beginfig(1) - fill fullcircle scaled 3cm withpattern(a) withcolor 3/4red; - draw fullcircle scaled 3cm withpen pencircle scaled 1; -endfig;}\stopsinglecontentitem -\stopelement{Figure}\vss}\hskip10pt\strut -\par\nobreak -⟦% define the pattern -picture letter; letter = maketext("a"); -beginpattern(a) - draw letter rotated 45; - matrix = identity rotated 45; -endpattern(12pt,12pt); -% use the pattern -beginfig(1) - fill fullcircle scaled 3cm withpattern(a) withcolor 3/4red; - draw fullcircle scaled 3cm withpen pencircle scaled 1; -endfig;⟧ +\subsection Retrieving images from instances %2 -A small pattern library is available in the ⟦*minim-hatching.mp⟧ file; see the -accompanying documentation sheet for an overview of patterns. +Now that you have your own instance, you can run chunks of metapost code in it +with ⟦*\runmetapost \id { code }⟧. Any images that your code may have contained +will have to be extracted explicitly. This is possible in a number of ways, +although each image can be retrieved only once. -\section Advanced PDF graphics %1 +All metapost images have an ⟦\hbox⟧ as outermost container. Do not unpack this +box: doing so will cause its dimensions to be lost. -You can use ⟦*savegstate⟧ and ⟦*restoregstate⟧ for inserting the ⟦q⟧ and ⟦Q⟧ -operators; these must always be paired, or horrible errors will occur. You may -need them if you use ⟦*setgstate(<params>)⟧ for modifying the extended -graphical state (ExtGState). The ⟦params⟧ must be a comma-separated -⟦Key=value⟧ list, with all ⟦value⟧s being suffixes. The latter restriction may -require the use of additional variables, but as this is a very low-level -command, it is best to wrap it in a more specialised macro anyway. -The ⟦*withgstate (<params>)⟧ can be added to a drawing statement and includes -saving/restoring the graphical state. +⟦*\getnextmpimage \id⟧ +– Writes the first unretrieved image to the current node list. +There, the image will be contained in a single box node. -Note that while you could try and use ⟦setgstate⟧ for modifying variables like -the line cap or dash pattern, the result of doing so will be unpredictable, -since such changes will be invisible to metapost. Its intended use is -restricted to graphics parameters outside the scope of metapost. +⟦*\getnamedmpimage \id {name}⟧ +– Retrieves an image by name +and writes it to the current node list. -For applying transparency, ⟦*setalpha(a)⟧ updates the ⟦CA⟧ and ⟦ca⟧ parameters -as a stand-alone command and ⟦*withalpha(a)⟧ can be used in a drawing statement -where it will save/restore the graphical state around it. For applying -transparency to an ensemble of drawing statements, ⟦*transparent (a) <picture>⟧ -instead of ⟦draw <picture>⟧ will create and insert the proper transparency group. -The transparency group attributes can be set with the string internal -⟦*transparency_group_attrs⟧, while for all three macros the blend mode can be -set with the string internal ⟦*blend_mode⟧ (it will be added whenever set). +⟦*\boxnextmpimage \id box-nr⟧ +– Puts the next unretrieved image in box ⟦box-nr⟧. The number may be anything +tex can parse as a number. -A transparency group is a special kind of XForm, and these can be created from -within metapost: ⟦<id> =⟧ ⟦*saveboxresource (<attributes>) <picture>⟧ returns -a number identifying the resource; the ⟦<attributes>⟧ can be given in the same -way as the arguments to ⟦setgstate⟧. XForms defined through metapost are -available to other metapost instances but not to tex, though the macro painting -them, ⟦*boxresource <id>⟧, also accepts identifiers of tex-defined box -resources. There remains a subtle difference, however: metapost-defined box -resources are placed at their original origin. +⟦*\boxnamedmpimage \id box-nr {name}⟧ +– Puts the image named ⟦name⟧ in box ⟦box-nr⟧. +Say ⟦*\remainingmpimages \id⟧ for the number of images not yet retrieved +and ⟦*\getallmpimages \id⟧ to insert all remaining images. -\section Other metapost extensions %1 +Finally, as a shorthand, ⟦*\runmetapostimage \id { code }⟧ will add +⟦beginfig ... endfig;⟧ to your ⟦code⟧ and write the resulting image immediately +to the current list. -You can set the baseline of an image with ⟦*baseline(p)⟧. There, ⟦p⟧ must -either be a point through which the baseline should pass, or a number (where an -x~coordinate of zero will be added). Transformations will be taken into -account, hence the specification of two coordinates. The last given baseline -will be used. +\subsection Associated token lists %2 -You can write to tex’s log directly with ⟦*texmessage "hello";⟧. You can feed -it a comma-separated list of strings and numbers, which will be passed through -⟦string.format()⟧ first. +Associated to every instance are four token registers containing tex and/or +metapost code to be inserted before or after each executed chunk. +You can access them with ⟦*\everymp \id {pre|post} {tex|mp}⟧ +(e.g. ⟦\everymp1{pre}{mp}⟧). +The token lists where ${\tt id}=0$ do not correspond to any instance and will +apply to every instance instead. +All four token lists are empty by default if you use minim-mp with plain tex. +The latex package, on the other hand, uses them for its own purposes, so take +care in that case to use ⟦\tokspre⟧ and ⟦\toksapp⟧ instead of overwriting their +contents. As a bonus, when using the latex package, you can use the environment +name instead of the numerical ⟦\id⟧. -You can write direct pdf statements with ⟦*special "pdf: statements"⟧ and you -can add comments to the pdf file with ⟦*special "pdfcomment: comments"⟧. -Say ⟦*special "latelua: lua code"⟧ to insert a ⟦late_lua⟧ whatsit. -All three specials can also be given as pre- or postscripts to another object. -In that case, they will be added before or after the object they are attached to. -Do note that all ⟦special⟧ statements will appear at the beginning of the -image; use pre- and postscripts to drawing statements if the order matters. +\subsection Lua interface %2 +In what follows, you should assume ⟦M⟧ to be the result of +\stopformulatagging$$\hbox{⟦M = require('minim-mp')⟧}$$\startformulatagging +as this package does not claim a table in the global environment for itself. -\section Additions to plain.mp %1 +You can open a new instance with ⟦*nr = M.open {options}⟧. +This returns an index in the ⟦*M.instances⟧ table. +Run code with ⟦*M.run (nr, code)⟧ and close the instance with ⟦*M.close (nr)⟧. +Images can be retrieved only with ⟦*box_node = M.get_image(nr, [name])⟧; omit +the ⟦name⟧ to select the first image. +Say ⟦*nr_remaining = M.left(nr)⟧ for the number of remaining images. -Minim-mp provides a few elementary macros and constants that are -conspicuously absent from plain.mp; I hope their addition is uncontroversial. -All are provided in the file minim.mp; the contents of this file do not depend -on functions specific to minim-mp and thus it can safely be used with other -metapost processors. It is included automatically right after the format file -(i.e. plain.mp). +Each metapost instance is a table containing the following entries: -The constants are ⟦*pi⟧ (355/113), ⟦*fullsquare⟧, ⟦*unitcircle⟧ and the -cmyk-colours ⟦*cyan⟧, ⟦*magenta⟧, ⟦*yellow⟧ and ⟦*key⟧. The macros are -⟦*clockwise⟧, ⟦*xshifted⟧, ⟦*yshifted⟧, ⟦*hflip⟧ and ⟦*vflip⟧, where the flips -are defined in such a way that ⟦p & hflip p⟧ gives the expected result. +\smallskip\smallskip +\marktableaslist +\tagattribute List ListNumbering /Description +\halign{\qquad#\quad\hfil&#\hfil\cr +⟦jobname⟧&The jobname.\cr +⟦instance⟧&The primitive metapost instance.\cr +⟦results⟧&A linked list of unretrieved images.\cr +⟦status⟧&The last exit status (will never decrease).\cr +⟦catcodes⟧&Number of the catcode table used with ⟦btex ... etex⟧.\cr +⟦env⟧&The lua environment for ⟦runscript⟧.\cr} -Version 1.2 brought the following additions: ⟦*save_pair⟧, ⟦*save_path⟧ etc. -etc. that save and declare in one go; the missing trigonometric functions -⟦*tand⟧, ⟦*arcsind⟧, ⟦*arccosd⟧ and ⟦*arctand⟧, and the unit circle segment -drawing function ⟦*arc(⟧$θ_0$⟦*,⟧$θ_ℓ$⟦*)⟧ (taking a starting angle and arc -length, both in degrees). +Default values for the format and number system are available in the +⟦*M.default_format⟧ and ⟦*M.default_mathmode⟧ variables. +The full initialisation sequence for new instances (i.e. the first metapost +chunk, that is executed automatically) is contained in the ⟦*M.init_code⟧ +table. -Version 1.6 brought ⟦*empty⟧ for testing empty suffixes, ⟦*typeof(v)⟧ -expanding to the type (⟦numeric⟧, ⟦pair⟧ etc.) of variable ⟦v⟧, -⟦*getbounds⟧ as complement to ⟦setbounds⟧, the (twodimensional) exterior product -⟦*p extprod q⟧ and the test ⟦*collinear(p,q,r)⟧. +The table passed to ⟦env⟧ defaults to a copy of the global table ⟦_G⟧, and will +be augmented with the contents of ⟦*M.mp_functions⟧. You can add your own +functions to this table, if you wish. -\section Metapost specials %1 +\subsection Adding new metapost specials %2 You can extend this package by adding new metapost specials. Specials should have the form ⟦"identifier: instructions"⟧ and can be added as pre- or @@ -541,5 +550,32 @@ properly-dimensioned boxes. If a ⟦user.save_fn⟧ function is defined, it will replace the normal saving of the image to the image list and the image node list will be flushed. -\endmanual % +\subsection Logs and debugging %2 + +Metapost log output of every processed chunk of metapost code will be printed +to the main log file in a quoted form. +The logs will be duplicated to the terminal if an error occurs or if the +variable ⟦*M.on_line⟧ is ⟦true⟧ (the default is ⟦false⟧, but set to ⟦true⟧ in +the stand-alone format files). +Because a single error message might trigger many others, log output to the +terminal (but not the log file) will be cut after a certain number of errors: +this behaviour is governed by the ⟦*M.max_errprint⟧ variable (default ⟦1⟧; set +to ⟦0⟧ to disable). + +You can enable (global) debugging by saying ⟦*debug_pdf⟧ to metapost, +⟦*\debugmetapost⟧ to tex or ⟦*M.enable_debugging()⟧ to lua. This will write +out a summary of metapost object information to the pdf file, just above the +pdf instructions that object was translated into. For this purpose, the pdf +will be generated uncompressed. Additionally, the metapost code itself will be +echoed to the log, as well as ⟦runscript⟧ and ⟦maketext⟧ invocations, and +a small summary of every generated image will be written to log and terminal. + +For debugging the results of ⟦maketext⟧ and the like, you can set the +⟦*debug_tex_bboxes⟧ variable to ⟦true⟧ and have their resulting bounding boxes +drawn on the pdf. + + +% + +\endmanual diff --git a/macros/luatex/generic/minim-mp/minim-mp.lua b/macros/luatex/generic/minim-mp/minim-mp.lua index 885a6941e4..762b355015 100644 --- a/macros/luatex/generic/minim-mp/minim-mp.lua +++ b/macros/luatex/generic/minim-mp/minim-mp.lua @@ -1267,7 +1267,7 @@ E.texmessage = alloc.msg local function prepare_env(e) -- in M.open() local env = e or copy_table(_G, { }) - return copy_table(E, env) + return setmetatable(env, { __index = E }) end function E.quote(val) @@ -1330,6 +1330,7 @@ local function maketext(text, mode) make_transform(box.width, box.height, box.depth)) elseif mode == 1 then -- verbatimtex debug('┌ verbatimtex: %s', text) + text = '\\the\\everyverbatimtex\n'..text tex.runtoks(function() tex.print(current_instance.catcodes, text:explode('\n')) end) debug('└ etex') end diff --git a/macros/luatex/generic/minim-mp/minim-mp.pdf b/macros/luatex/generic/minim-mp/minim-mp.pdf Binary files differindex 4760106341..538ac5ba55 100644 --- a/macros/luatex/generic/minim-mp/minim-mp.pdf +++ b/macros/luatex/generic/minim-mp/minim-mp.pdf diff --git a/macros/luatex/generic/minim-mp/minim-mp.sty b/macros/luatex/generic/minim-mp/minim-mp.sty index 948c6034b7..adc194be3e 100644 --- a/macros/luatex/generic/minim-mp/minim-mp.sty +++ b/macros/luatex/generic/minim-mp/minim-mp.sty @@ -1,11 +1,12 @@ -\ProvidesPackage{minim-mp}[2023/03/03 Run MetaPost code from LaTeX] +\ProvidesPackage{minim-mp}[2025/02/12 Run MetaPost code from LaTeX] \input minim-mp % work around latex’s \protect mechanism \let\mnm@protect=\protect \everymaketext{\let\protect=\mnm@protect} +\everyverbatimtex{\let\protect=\mnm@protect} % the defaultfont is the current \normalfont \def\mnm@setnormalfont{{\normalfont diff --git a/macros/luatex/generic/minim-mp/minim-mp.tex b/macros/luatex/generic/minim-mp/minim-mp.tex index ddc925ab3a..6f478bdfdc 100644 --- a/macros/luatex/generic/minim-mp/minim-mp.tex +++ b/macros/luatex/generic/minim-mp/minim-mp.tex @@ -115,6 +115,7 @@ % miscellaneous bits and ends \newtoks \everymaketext +\newtoks \everyverbatimtex \def\mpdim#1{\the\dimexpr#1\relax} \catcode`\: = \minimmploaded diff --git a/macros/luatex/generic/minim-mp/minim.mp b/macros/luatex/generic/minim-mp/minim.mp index ed152a018b..00ac2fa32a 100644 --- a/macros/luatex/generic/minim-mp/minim.mp +++ b/macros/luatex/generic/minim-mp/minim.mp @@ -35,10 +35,10 @@ vardef clockwise primary c = if turningnumber c > 0: reverse fi c enddef; % clipping -vardef clipto text t = +vardef clipout text t = clip currentpicture to bbox currentpicture for c = t: -- c -- cycle endfor -- cycle enddef; -vardef clipout text t = +vardef clipto text t = clip currentpicture to for c = t: c -- cycle -- endfor cycle enddef; vardef getbounds primary p = % without bboxmargin diff --git a/macros/luatex/generic/minim-pdf/README b/macros/luatex/generic/minim-pdf/README index c449a9a2c4..a3ad66e79f 100644 --- a/macros/luatex/generic/minim-pdf/README +++ b/macros/luatex/generic/minim-pdf/README @@ -1,4 +1,4 @@ -Version: 2024/1.5 +Version: 2025/1.6 SUMMARY @@ -27,7 +27,11 @@ In order to obtain the typeset manual of this package, simply say: HISTORY -2024/1.5 (in development) +2025/1.6 (12/2/2025) + + No notable changes. + +2024/1.5 (25/2/2024) New features: diff --git a/macros/luatex/generic/minim-pdf/minim-pdf.doc b/macros/luatex/generic/minim-pdf/minim-pdf.doc index 3dc0349aca..8e0f564632 100644 --- a/macros/luatex/generic/minim-pdf/minim-pdf.doc +++ b/macros/luatex/generic/minim-pdf/minim-pdf.doc @@ -3,7 +3,7 @@ \manual{minim-pdf} -\ifchapter \chapter Advanced PDF features +\ifchapter \chapter Hypertext This chapter and the next document the support of the modern pdf features provided by the minim-pdf package. @@ -14,8 +14,8 @@ all other features of the package are described here. \else \startmetadata author {Esger Renkema} title {minim-pdf} - date {2024-02-25} - version {2024/1.5} + date {2025-02-12} + version {2025/1.6} keywords {LuaTeX; Plain TeX; PDF/A; Tagged PDF; accessibility; a11y; hypertext; bookmarks; document outline; associated files} stopmetadata diff --git a/macros/luatex/generic/minim-pdf/minim-pdf.lua b/macros/luatex/generic/minim-pdf/minim-pdf.lua index 101a548e4b..9d824a829f 100644 --- a/macros/luatex/generic/minim-pdf/minim-pdf.lua +++ b/macros/luatex/generic/minim-pdf/minim-pdf.lua @@ -2,7 +2,6 @@ local M = { } local alloc = require('minim-alloc') local cb = require('minim-callbacks') -alloc.remember('minim-hooks') alloc.remember('minim-pdf') -- 1 helper functions @@ -32,25 +31,10 @@ local pdf_name = alloc.pdf_name local pdf_string = alloc.pdf_string local options_scanner = alloc.options_scanner --- is this table empty? -local function is_empty(t) - for _, _ in pairs(t or {}) do - return false - end - return true -end - --- has this table just one element? local function singleton(t) - local one = false - for _, _ in pairs(t) do - if one then - return false - else - one = true - end - end - return one + local v = next(t) + v = v and not next(t, v) + return v and true or false end -- in-depth node list traversal; returns current and parent node @@ -92,6 +76,7 @@ local structure = { { index = 1, struct = 'Document', children = { }, + level = 0, -- for debugging only } } -- the parent tree will be filled automatically and separately @@ -158,7 +143,7 @@ local structure_types = alloc.saved_table('structure types', { -- block level structure elements (BLSE) P = { type = 'block' }, H = { type = 'block' }, - H1 = { type = 'block' }, -- for nonhierarchical tagging (do not use?) + H1 = { type = 'block' }, -- for nonhierarchical tagging (do not use) H2 = { type = 'block' }, -- __________ „ __________ H3 = { type = 'block' }, -- __________ „ __________ H4 = { type = 'block' }, -- __________ „ __________ @@ -328,7 +313,8 @@ local function make_rolemap() return '' end -local function make_attributes(res, t) +local function make_attributes(t) + local res = { } -- is there just one attribute? local list = not singleton(t) if list then table.insert(res, '[') end @@ -340,6 +326,7 @@ local function make_attributes(res, t) table.insert(res, '>>') end if list then table.insert(res, ']') end + return table.concat(res, ' ') end local attribute_classes = alloc.saved_table('attribute classes') @@ -347,7 +334,7 @@ local function make_classmap() local classes = { } for c, as in pairs(attribute_classes) do insert_formatted(classes, '\n%s', pdf_name(c)) - make_attributes(classes, as) + table.insert(classes, make_attributes(as)) end if #classes > 0 then return '\n/ClassMap << ' .. table.concat(classes, ' ') .. ' >>' @@ -355,11 +342,59 @@ local function make_classmap() return '' end +local id_tree = { } + +local function write_structure_element(se) + local res = { '<<' } + insert_formatted(res, '/Type/StructElem /S%s /P %d 0 R', pdf_name(se.struct), se.parent.objnum) + if se.id then insert_formatted(res, '/ID %s', pdf_string(se.id)) end + if se.lang and se.lang ~= se.parent.lang then insert_formatted(res, '/Lang %s', pdf_string(se.lang)) end + if se.alt then insert_formatted(res, '/Alt %s', pdf_string(se.alt)) end + if se.actual then insert_formatted(res, '/ActualText %s', pdf_string(se.actual)) end + if se.title then insert_formatted(res, '/T %s', pdf_string(se.title)) end + if #se.children > 0 then insert_formatted(res, '\n/K %s', format_K_array(se)) end + if se.mainpage then insert_formatted(res, '/Pg %d 0 R', se.mainpage) end + if se.class then + table.insert(res, '/C') + if #se.class > 1 then table.insert(res, '[') end + for _, c in ipairs(se.class) do + insert_formatted(res, '%s', pdf_name(c)) + end + if #se.class > 1 then table.insert(res, ']') end + end + if se.ref then + table.insert(res, '/Ref') + table.insert(res, '[') + for _, c in ipairs(se.ref) do + local onum = id_tree[c] + if onum then + insert_formatted(res, '%d 0 R', onum) + else + alloc.err('Invalid structure element ID: %s', c) + end + end + table.insert(res, ']') + end + if next(se.attributes or {}) then + table.insert(res, '/A') + table.insert(res, make_attributes(se.attributes)) + end + if se.files then + table.insert(res, '/AF [') + for _, fs in ipairs(se.files) do + insert_formatted(res, '%d 0 R', fs) + end + table.insert(res, ']') + end + table.insert(res, '>>') + pdf.immediateobj(se.objnum, table.concat(res, ' ')) +end + local function write_structure() if #structure == 1 then return end -- reserve object numbers, prepare for writing - local root_obj, parent_tree_obj = pdf.reserveobj(), pdf.reserveobj() - local id_tree, id_tree_obj = { }, pdf.reserveobj() + local root_obj, parent_tree_obj, id_tree_obj = + pdf.reserveobj(), pdf.reserveobj(), pdf.reserveobj() structure[1].parent = { objnum = root_obj } for _, se in ipairs(structure) do if not se.hidden then @@ -383,49 +418,7 @@ local function write_structure() -- write structure elements for _, se in ipairs(structure) do if not se.hidden then - local res = { '<<' } - insert_formatted(res, '/Type/StructElem /S%s /P %d 0 R', pdf_name(se.struct), se.parent.objnum) - if se.id then insert_formatted(res, '/ID %s', pdf_string(se.id)) end - if se.lang and se.lang ~= se.parent.lang then insert_formatted(res, '/Lang %s', pdf_string(se.lang)) end - if se.alt then insert_formatted(res, '/Alt %s', pdf_string(se.alt)) end - if se.actual then insert_formatted(res, '/ActualText %s', pdf_string(se.actual)) end - if se.title then insert_formatted(res, '/T %s', pdf_string(se.title)) end - if #se.children > 0 then insert_formatted(res, '\n/K %s', format_K_array(se)) end - if se.mainpage then insert_formatted(res, '/Pg %d 0 R', se.mainpage) end - if se.class then - table.insert(res, '/C') - if #se.class > 1 then table.insert(res, '[') end - for _, c in ipairs(se.class) do - insert_formatted(res, '%s', pdf_name(c)) - end - if #se.class > 1 then table.insert(res, ']') end - end - if se.ref then - table.insert(res, '/Ref') - table.insert(res, '[') - for _, c in ipairs(se.ref) do - local onum = id_tree[c] - if onum then - insert_formatted(res, '%d 0 R', onum) - else - alloc.err('Invalid structure element ID: %s', c) - end - end - table.insert(res, ']') - end - if not is_empty(se.attributes) then - table.insert(res, '/A') - make_attributes(res, se.attributes) - end - if se.files then - table.insert(res, '/AF [') - for _, fs in ipairs(se.files) do - insert_formatted(res, '%d 0 R', fs) - end - table.insert(res, ']') - end - table.insert(res, '>>') - pdf.immediateobj(se.objnum, table.concat(res, ' ')) + write_structure_element(se) end end -- write the parent tree (a number tree) @@ -519,7 +512,6 @@ end local function get_ancestor_of_type(se, stype) while se and se.struct ~= stype do - if se.level == -1000 then return end se = se.parent end return se and se.parent @@ -527,7 +519,8 @@ end function M.close_structure_node(stype, raiseerror) local strict = tex.count['strictstructuretagging'] > 0 - local current, open = current_structure_element() + local current = current_structure_element() + local open if strict then open = current.struct == stype and current.parent else @@ -574,6 +567,7 @@ function M.open_structure_node(n) n.order = n.order or tex.getattribute(current_order) n.parent = (n.parent and structure[n.parent]) or determine_parent_node(current_structure_element(), n) + n.level = n.parent.level + 1 table.insert(structure, n) -- determine the proper language code if n.lang then @@ -664,7 +658,7 @@ local mcid_list, pageobj local function clear_page_tagging_parameters() mcid_list, pageobj = { }, nil - _open_mci_node_ = function (se_num, order) + _open_mci_node_ = function (se_num, order) --luacheck: ignore 111 pageobj = pageobj or pdf.getpageref(status.total_pages + 1) local se = structure[se_num] pdf.print(string.format('%s <</MCID %d>> BDC ', pdf_name(se.struct), #mcid_list)) @@ -854,7 +848,7 @@ end) local function scan_escaped_argument(chars_to_escape) local stored = { } - for char in string.utfvalues(chars_to_escape) do + for _, char in utf8.codes(chars_to_escape) do stored[char] = tex.getcatcode(char) tex.setcatcode(char, 12) end @@ -1060,7 +1054,7 @@ function M.mark_discretionaries(head, gc) if #actual == 0 and pre and pre.char and pre.char == 0x2D then actual = '' -- soft hyphen U+00AD elseif #actual > 0 then - actual = string.utfcharacter(table.unpack(actual)) + actual = utf8.char(table.unpack(actual)) else goto continue end diff --git a/macros/luatex/generic/minim-pdf/minim-pdf.pdf b/macros/luatex/generic/minim-pdf/minim-pdf.pdf Binary files differindex 2056601eec..9fc6616988 100644 --- a/macros/luatex/generic/minim-pdf/minim-pdf.pdf +++ b/macros/luatex/generic/minim-pdf/minim-pdf.pdf diff --git a/macros/luatex/generic/minim-pdf/minim-pdf.tex b/macros/luatex/generic/minim-pdf/minim-pdf.tex index d5300fd58f..f0b2dff92a 100644 --- a/macros/luatex/generic/minim-pdf/minim-pdf.tex +++ b/macros/luatex/generic/minim-pdf/minim-pdf.tex @@ -1,12 +1,11 @@ \ifdefined\minimpdfloaded - \message{(skipped)} + \wlog{(skipped)} \expandafter\endinput\fi \chardef\minimpdfloaded = \catcode`\: \catcode`\: = 11 \input minim-alloc -\input minim-hooks % Abbreviations used throughout this document: % se structure element @@ -50,6 +49,13 @@ % 1 artifacts and content items +% The following functions have lua-side definitions; all insert a whatsit node +% that will be intercepted in the pre_shipout callback. +% +% \tagging:mci:content +% \tagging:mci:markstart \tagging:mci:markstop +% \tagging:art:markstart \tagging:art:markstop + % \stoptagging ... \starttagging % disables marking structure elements \newif\iftagging:enabled \tagging:enabledtrue @@ -84,6 +90,9 @@ % 1 structure elements +% All macros in this section wrap a lua-defined function; these functions will +% take care of scanning and parsing the actual arguments. + % \savecurrentelement ... \continueelement % \savecurrentelementto\name ... \continueelementfrom\name \protected\def\savecurrentelementto#1{\global\chardef#1\tagging:current:se} @@ -572,10 +581,12 @@ \expandafter\def\csname minim:pdfa:3u\endcsname{\minim:pdfasettings 7U3} % \pdfualavel 1 -\def\pdfualevel{\input minim-xmp - \setmetadata pdfuaid:part {1} - \tagging:enablepdfua +\def\pdfualevel{% + \afterassignment\pdfualevel:set \global\pdfuaconformancelevel= } +\def\pdfualevel:set{\input minim-xmp + \setmetadata pdfuaid:part{\the\pdfuaconformancelevel}% + \tagging:enablepdfua} % diff --git a/macros/luatex/generic/minim-xmp/README b/macros/luatex/generic/minim-xmp/README index 15878c6e17..e74d94eff4 100644 --- a/macros/luatex/generic/minim-xmp/README +++ b/macros/luatex/generic/minim-xmp/README @@ -1,4 +1,4 @@ -Version: 2024/1.3 +Version: 2025/1.4 SUMMARY @@ -21,6 +21,10 @@ In order to obtain the typeset manual of this package, simply say: HISTORY +2025/1.4 (12/2/2025) + + No notable changes. + 2024/1.3 (5/1/2024) New features: diff --git a/macros/luatex/generic/minim-xmp/minim-xmp.doc b/macros/luatex/generic/minim-xmp/minim-xmp.doc index 250edb18af..b069a6a8c8 100644 --- a/macros/luatex/generic/minim-xmp/minim-xmp.doc +++ b/macros/luatex/generic/minim-xmp/minim-xmp.doc @@ -8,8 +8,8 @@ \else \startmetadata author {Esger Renkema} title {minim-xmp} - date {2024-01-05} - version {2024/1.3} + date {2025-02-12} + version {2025/1.4} keywords {LuaTeX; Plain TeX; XMP; metadata; PDF/A;} stopmetadata \maketitle \fi diff --git a/macros/luatex/generic/minim-xmp/minim-xmp.lua b/macros/luatex/generic/minim-xmp/minim-xmp.lua index e3b7a8de70..229ded2deb 100644 --- a/macros/luatex/generic/minim-xmp/minim-xmp.lua +++ b/macros/luatex/generic/minim-xmp/minim-xmp.lua @@ -349,7 +349,7 @@ local function make_xmp_packet(xmp) local rv = { } ; local add = function(...) table.insert(rv, string.format(...)) end -- wrapper and opening tags add('<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>') - add('<x:xmpmeta xmlns:x="adobe:ns:meta/">') + add('<xmp:xmpmeta xmlns:xmp="adobe:ns:meta/">') add('<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">') -- namespaces for id, keys in sorted_pairs(xmp) do @@ -400,7 +400,7 @@ local function make_xmp_packet(xmp) end -- closing tags and wrapper local editable = tex.count['metadatamodification'] > 0 - add('</rdf:RDF>\n</x:xmpmeta>') + add('</rdf:RDF>\n</xmp:xmpmeta>') if editable then add(string.rep(string.rep(' ', 80), 25, '\n')) end add('<?xpacket end="%s"?>', editable and 'w' or 'r') return table.concat(rv, '\n') @@ -437,7 +437,7 @@ local function get_metadata_info(fullkey) end local function get_separator() - return string.utfcharacter(tex.count['metadataseparator']) + return utf8.char(tex.count['metadataseparator']) end function M.get_metadata(k, a) @@ -458,7 +458,7 @@ function M.get_metadata(k, a) end local function split_metadata_input(s) - local rv = string.explode(s, get_separator()) + local rv = s:explode(get_separator()) for i = 1, #rv do rv[i] = string.gsub(rv[i], '^ *', '') rv[i] = string.gsub(rv[i], ' *$', '') diff --git a/macros/luatex/generic/minim-xmp/minim-xmp.pdf b/macros/luatex/generic/minim-xmp/minim-xmp.pdf Binary files differindex fdf38f3a2c..5fd58cc74c 100644 --- a/macros/luatex/generic/minim-xmp/minim-xmp.pdf +++ b/macros/luatex/generic/minim-xmp/minim-xmp.pdf diff --git a/macros/luatex/generic/minim-xmp/minim-xmp.tex b/macros/luatex/generic/minim-xmp/minim-xmp.tex index 2548ad857b..e26edf9249 100644 --- a/macros/luatex/generic/minim-xmp/minim-xmp.tex +++ b/macros/luatex/generic/minim-xmp/minim-xmp.tex @@ -1,6 +1,6 @@ \ifdefined\minimxmploaded - \message{(skipped)} + \wlog{(skipped)} \expandafter\endinput\fi \chardef\minimxmploaded=\catcode`\: \catcode`\:=11 diff --git a/macros/luatex/generic/minim/README b/macros/luatex/generic/minim/README index 751c428bad..f237e9d1a5 100644 --- a/macros/luatex/generic/minim/README +++ b/macros/luatex/generic/minim/README @@ -1,4 +1,4 @@ -Version: 2024/1.6 +Version: 2025/1.7 SUMMARY @@ -31,6 +31,13 @@ the packages mentioned above. HISTORY +2025/1.7 (12/2/2025) + + Major changes: + + * The minim-hooks.{tex,lua} files are gone; their contents have been + included (and documented) in minim-alloc. + 2024/1.6 (25/3/2024) No changes. diff --git a/macros/luatex/generic/minim/minim-alloc.doc b/macros/luatex/generic/minim/minim-alloc.doc index b1f6ed77bd..f535320269 100644 --- a/macros/luatex/generic/minim/minim-alloc.doc +++ b/macros/luatex/generic/minim/minim-alloc.doc @@ -162,15 +162,21 @@ Finally, for the ⟦*simple⟧ callbacks ⟦process_rule⟧. all registered functions are called in order with the same arguments. -Two callbacks are new: -the new ⟦*mlist_to_mlist⟧ callback is called before ⟦mlist_to_hlist⟧ and should -not convert noads to nodes, while the ⟦*uselanguage⟧ callback is called from -⟦\uselanguage⟧. +Three callbacks are new: +\startlist +\item 1. ⟦*mlist_to_mlist⟧ is called before ⟦mlist_to_hlist⟧ and should not +convert noads to nodes; +\item 2. ⟦*uselanguage⟧ is called from ⟦\uselanguage⟧ and receives the +language name (not the numerical id) as argument; +\item 3. ⟦*pre_shipout⟧ is called just before a box is shipped out, +opposite to ⟦finish_pdfpage⟧, and receives the to-be-shipped-out box number as +argument. If you create a new callback with a number for a name, that callback will replace the ⟦*process_rule⟧ callback when its number matches the index property of the rule. + \section PDF resources This package can perform sophisticated pdf resource management, assigning to @@ -269,6 +275,7 @@ Finally the function ⟦*M.table_to_text(table)⟧ may be useful when debugging code: it dumps a table as a (lua-readable) string. Cyclic references will spin in into an eternal loop, however. + \section Miscellaneous helper macros On the tex side, ⟦*\voidbox⟧, ⟦*\ignore⟧, ⟦*\spacechar⟧, ⟦*\unbrace⟧, diff --git a/macros/luatex/generic/minim/minim-alloc.lua b/macros/luatex/generic/minim/minim-alloc.lua index 3b14f5cc80..8e84553c2f 100644 --- a/macros/luatex/generic/minim/minim-alloc.lua +++ b/macros/luatex/generic/minim/minim-alloc.lua @@ -195,10 +195,6 @@ function M.table_to_text (tbl) return '{ ' .. table.concat (r,', ') .. ' }' end -local cb = require('minim-callbacks') -M.remember('minim-callbacks') -M.remember('minim-alloc') - -- 1 allocation functions -- like \unset @@ -271,6 +267,21 @@ make_alloc_old ('box', globoffset + 4 ) make_alloc_old ('toks', globoffset + 5 ) make_alloc_old ('marks', globoffset + 6 ) +-- 1 other extensions + +local cb = require('minim-callbacks') +M.remember('minim-callbacks') +M.remember('minim-alloc') + +-- Add a callback just before a box is shipped out, opposite to 'finish_pdfpage'. +cb.new_callback('pre_shipout', 'simple') +M.primitive_shipout = tex.shipout +function tex.shipout(nr) + cb.call_callback('pre_shipout', nr) + M.primitive_shipout(nr) +end + +-- define tex commands from lua function M.luadef (csname, fn, ...) local nr = M.new_function(csname) lua.get_functions_table()[nr] = fn diff --git a/macros/luatex/generic/minim/minim-alloc.tex b/macros/luatex/generic/minim/minim-alloc.tex index f83e043ad4..40e01f66a0 100644 --- a/macros/luatex/generic/minim/minim-alloc.tex +++ b/macros/luatex/generic/minim/minim-alloc.tex @@ -115,10 +115,10 @@ \ifdefined \documentclass % latex has no \globcount etc. \alloc:globoffset = 10 - \ifnum\count10<256 \count10=256 \fi - \ifnum\count11<256 \count11=256 \fi - \ifnum\count12<256 \count12=256 \fi - \ifnum\count14<256 \count14=256 \fi + \ifnum\count10<256 \count10=300 \fi + \ifnum\count11<256 \count11=300 \fi + \ifnum\count12<256 \count12=300 \fi + \ifnum\count14<256 \count14=300 \fi \else \ifdefined \globcount % use global allocation (see etex.src) \let\newcount = \globcount @@ -189,6 +189,39 @@ \ifdefined\minim:uselanguagehook \noexpand\minim:uselanguagehook{#1}\fi} +%1 hooks + +% the pre_shipout callback +\newbox\minim:shipout:box \let\minim:shipout:orig = \shipout +\def\minim:shipout:do{\minim:shipout:orig\box\minim:shipout:box} +\protected\def\minim:shipout:new{\directlua{ + tex.box[\the\minim:shipout:box] = token.scan_list() + require('minim-callbacks').call_callback('pre_shipout', \the\minim:shipout:box) + token.put_next(token.create('minim:shipout:do'))}} +\let\shipout = \minim:shipout:new + +% invisibly adding to \everypar +\let\minim:everypar = \everypar +\newtoks\minim:ateverypar +\newtoks\minim:atnextpar +\newtoks\everypar \everypar\minim:everypar +\minim:everypar\expandafter{\expandafter + \minim:changeparindent + % expansion makes this process repeatable + \expandafter\the\everypar + \the\minim:ateverypar + \minim:atnextpar\expandafter + {\expandafter}\the\minim:atnextpar} +\let\minim:changeparindent = \relax % as of yet unused + +% There is presently no need for the following. + +%\let\minim:par = \par +%\newtoks\minim:aftereverypar +%\protected\def\par{\ifhmode \unskip +% \the\minim:aftereverypar \fi \minim:par} + + % 1 format file compatibility % all other work is done at the lua end diff --git a/macros/luatex/generic/minim/minim-callbacks.lua b/macros/luatex/generic/minim/minim-callbacks.lua index b0ecc1a711..63100bd5b2 100644 --- a/macros/luatex/generic/minim/minim-callbacks.lua +++ b/macros/luatex/generic/minim/minim-callbacks.lua @@ -254,11 +254,12 @@ register_list ('process_jobname', call_list_data) -- node list processing callbacks register_list ('pre_linebreak_filter', call_list_node) register_list ('post_linebreak_filter', call_list_node) ---register_list ('append_to_vlist_filter', call_list_node) -- TODO this breaks something register_list ('hpack_filter', call_list_node) register_list ('vpack_filter', call_list_node) register_list ('pre_output_filter', call_list_node) +-- TODO 'append_to_vlist_filter' needs second return value + -- mlist_to_mlist and mlist_to_mlist M.new_callback ('mlist_to_mlist', 'node') M.new_callback ('mlist_to_hlist', 'stack') diff --git a/macros/luatex/generic/minim/minim-doc.sty b/macros/luatex/generic/minim/minim-doc.sty index 32c8a1e991..86d218ea6f 100644 --- a/macros/luatex/generic/minim/minim-doc.sty +++ b/macros/luatex/generic/minim/minim-doc.sty @@ -22,6 +22,8 @@ \uselanguage{ukenglish} \hyphenation { mark-tab-le-cell + mark-tab-le-hea-der + no-de-ci-mal-com-ma } \parindent 0pt @@ -135,7 +137,7 @@ endfig;} \hbox to 2em{\hss\startelement{Lbl}#1.~~}% \startelement{LBody}\ignorespaces} -\sectionstructure{section, chapter} +\sectionstructure{subsection, section, chapter} % \chapter Title \par \protected\def\chapter#1 \par{% @@ -150,12 +152,21 @@ endfig;} \protected\def\section#1 \par{% \bigskip\penalty-50\relax \marksection[Section \the\chapternr.\the\sectionnr]% - \outline closed {#1}% + \outline open {#1}% \addtotoc{\section{#1}{\lastdestinationname}}% \nextpartag{H}\quitvmode \red{\title#1}% \par\nobreak} +% \subsection Title \par +\protected\def\subsection#1 \par{% + \smallskip\penalty-50\relax + \marksubsection[Section \the\chapternr.\the\sectionnr.\the\subsectionnr]% + \outline closed {#1}% + \nextpartag{H}\quitvmode + \red{\tenbf#1}% + \par\nobreak} + % table of contents \newtoks\toc \newif\iftoc \toctrue \def\addtotoc#1{% @@ -193,8 +204,9 @@ endfig;} \mailname\tmp elrenkema\TMP nl}\cr} \smallskip} -% 1 Chapters and full manuals +% 1 chapters and full manuals +% the EUPL \def\licencesection{\section Licence \embedfile global file {EUPL-1.2-EN.txt} @@ -219,6 +231,21 @@ obtained at \def\endmanual{\ifchapter\expandafter\endinput\else \licencesection\expandafter\bye\fi} +% typesetting a table of comtents +\def\makecontents{% + \tocfalse \section Contents \par + \smallskip \begingroup \parskip1pt + \protected\def\chapter##1##2##3{% + \stopelement{TOC}\smallskip + \nextpartag{}\red{\tenbf\marktocentry{##2}{}{\strut##1}{\hfill~}{##3}}% + \smallskip\startelement{TOC}} + \protected\def\section##1##2##3{% + \marktocentry{##2}{}{\strut\quad##1}{\dotfill~}{##3}\par} + \startelement{TOC} \startelement{TOC} + \the\toc + \stopelement{TOC} \stopelement{TOC} + \endgroup} + % introduction \endinput diff --git a/macros/luatex/generic/minim/minim-hooks.lua b/macros/luatex/generic/minim/minim-hooks.lua deleted file mode 100644 index f11ce27875..0000000000 --- a/macros/luatex/generic/minim/minim-hooks.lua +++ /dev/null @@ -1,18 +0,0 @@ - -local cb = require ('minim-callbacks') - -local M = { } - --- Add a callback just before a box is shipped out, opposite to --- 'finish_pdfpage'. - -cb.new_callback('pre_shipout', 'simple') - -M.primitive_shipout = tex.shipout -function tex.shipout(nr) - cb.call_callback('pre_shipout', nr) - M.primitive_shipout(nr) -end - -return M - diff --git a/macros/luatex/generic/minim/minim-hooks.tex b/macros/luatex/generic/minim/minim-hooks.tex deleted file mode 100644 index da19182a48..0000000000 --- a/macros/luatex/generic/minim/minim-hooks.tex +++ /dev/null @@ -1,60 +0,0 @@ - -% The purpose of this module is allowing arbitrary code be run at specific -% places. I have not yet included it in the manual, because I still am a bit -% unsure about the details of the implementation. -% -% The first thing done here is inserting a callback into \shipout (and -% tex.shipout) mirroring finish_pdf, allowing last-minute manipulation before -% the pdf code will be assembled. -% -% The second feature is adding things to the beginning of a paragraph without -% (seemingly) disturbing \everypar, and also adding things to the next -% paragraph only. -% -% Both features are implemented in a way that is repeatable and should coexist -% peacefully with other packages doing something of the same. But please let me -% know if you run into any problems. - -\ifdefined\minimhooksloaded - \wlog{(skipped)} - \expandafter\endinput\fi -\chardef\minimhooksloaded = \catcode`\: -\catcode`\: = 11 - -\directlua{ require('minim-hooks') } - -% 1 the pre_shipout callback - -\newbox\minim:shipout:box \let\minim:shipout:orig = \shipout -\def\minim:shipout:do{\minim:shipout:orig\box\minim:shipout:box} -\protected\def\minim:shipout:new{\directlua{ - tex.box[\the\minim:shipout:box] = token.scan_list() - require('minim-callbacks').call_callback('pre_shipout', \the\minim:shipout:box) - token.put_next(token.create('minim:shipout:do'))}} -\let\shipout = \minim:shipout:new - -% 1 invisibly adding to \everypar - -\let\minim:everypar = \everypar -\newtoks\minim:ateverypar -\newtoks\minim:atnextpar -\newtoks\everypar \everypar\minim:everypar -\minim:everypar\expandafter{\expandafter - \minim:changeparindent - % expansion makes this process repeatable - \expandafter\the\everypar - \the\minim:ateverypar - \minim:atnextpar\expandafter - {\expandafter}\the\minim:atnextpar} -\let\minim:changeparindent = \relax % as of yet unused - -% There is presently no need for the following. - -%\let\minim:par = \par -%\newtoks\minim:aftereverypar -%\protected\def\par{\ifhmode \unskip -% \the\minim:aftereverypar \fi \minim:par} - -\catcode`\: = \minimhooksloaded - - diff --git a/macros/luatex/generic/minim/minim.doc b/macros/luatex/generic/minim/minim.doc index f1538c5724..faec9d6b6c 100644 --- a/macros/luatex/generic/minim/minim.doc +++ b/macros/luatex/generic/minim/minim.doc @@ -4,8 +4,8 @@ \startmetadata author {Esger Renkema} title {minim} - date {2024-03-25} - version {2024/1.6} + date {2025-02-12} + version {2025/1.7} keywords {LuaTeX; Plain TeX; MetaPost; PDF/A; Tagged PDF; accessibility; a11y; Unicode mathematics; XMP; metadata; hypertext; bookmarks} stopmetadata @@ -39,18 +39,7 @@ For building your own format files, you can re-use the file \red{minim.ini}: if you define ⟦\fmtname⟧ before inputting this file, no ⟦\dump⟧ will be performed. -\tocfalse \section Contents \par -\smallskip \begingroup \parskip1pt -\protected\def\chapter#1#2#3{% - \stopelement{TOC}\smallskip - \nextpartag{}\red{\tenbf\marktocentry{#2}{}{\strut#1}{\hfill~}{#3}}% - \smallskip\startelement{TOC}} -\protected\def\section#1#2#3{% - \marktocentry{#2}{}{\strut\quad#1}{\dotfill~}{#3}\par} -\startelement{TOC} \startelement{TOC} -\the\toc -\stopelement{TOC} \stopelement{TOC} -\endgroup +\makecontents \section Compatibility diff --git a/macros/luatex/generic/minim/minim.pdf b/macros/luatex/generic/minim/minim.pdf Binary files differindex e7a0519965..bd46c62c35 100644 --- a/macros/luatex/generic/minim/minim.pdf +++ b/macros/luatex/generic/minim/minim.pdf |