summaryrefslogtreecommitdiff
path: root/macros/luatex/generic
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2025-02-10 03:06:01 +0000
committerNorbert Preining <norbert@preining.info>2025-02-10 03:06:01 +0000
commit11251344f7508667fd2c94d2ff940b64d1e4558a (patch)
tree95651765b07134eef12ba937438e884e258cf7b6 /macros/luatex/generic
parent6d43cd788622489915bdbcb025ab08c84f4ff54e (diff)
CTAN sync 202502100306
Diffstat (limited to 'macros/luatex/generic')
-rw-r--r--macros/luatex/generic/minim-math/README6
-rw-r--r--macros/luatex/generic/minim-math/minim-math.doc42
-rw-r--r--macros/luatex/generic/minim-math/minim-math.lua10
-rw-r--r--macros/luatex/generic/minim-math/minim-math.pdfbin114067 -> 117893 bytes
-rw-r--r--macros/luatex/generic/minim-math/minim-math.sty70
-rw-r--r--macros/luatex/generic/minim-math/minim-math.tex19
-rw-r--r--macros/luatex/generic/minim-mp/README30
-rw-r--r--macros/luatex/generic/minim-mp/minim-mp.doc688
-rw-r--r--macros/luatex/generic/minim-mp/minim-mp.lua3
-rw-r--r--macros/luatex/generic/minim-mp/minim-mp.pdfbin134407 -> 142408 bytes
-rw-r--r--macros/luatex/generic/minim-mp/minim-mp.sty3
-rw-r--r--macros/luatex/generic/minim-mp/minim-mp.tex1
-rw-r--r--macros/luatex/generic/minim-mp/minim.mp4
-rw-r--r--macros/luatex/generic/minim-pdf/README8
-rw-r--r--macros/luatex/generic/minim-pdf/minim-pdf.doc6
-rw-r--r--macros/luatex/generic/minim-pdf/minim-pdf.lua138
-rw-r--r--macros/luatex/generic/minim-pdf/minim-pdf.pdfbin145084 -> 145153 bytes
-rw-r--r--macros/luatex/generic/minim-pdf/minim-pdf.tex21
-rw-r--r--macros/luatex/generic/minim-xmp/README6
-rw-r--r--macros/luatex/generic/minim-xmp/minim-xmp.doc4
-rw-r--r--macros/luatex/generic/minim-xmp/minim-xmp.lua8
-rw-r--r--macros/luatex/generic/minim-xmp/minim-xmp.pdfbin73080 -> 73284 bytes
-rw-r--r--macros/luatex/generic/minim-xmp/minim-xmp.tex2
-rw-r--r--macros/luatex/generic/minim/README9
-rw-r--r--macros/luatex/generic/minim/minim-alloc.doc15
-rw-r--r--macros/luatex/generic/minim/minim-alloc.lua19
-rw-r--r--macros/luatex/generic/minim/minim-alloc.tex41
-rw-r--r--macros/luatex/generic/minim/minim-callbacks.lua3
-rw-r--r--macros/luatex/generic/minim/minim-doc.sty33
-rw-r--r--macros/luatex/generic/minim/minim-hooks.lua18
-rw-r--r--macros/luatex/generic/minim/minim-hooks.tex60
-rw-r--r--macros/luatex/generic/minim/minim.doc17
-rw-r--r--macros/luatex/generic/minim/minim.pdfbin397133 -> 405337 bytes
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
index 9544068d92..9e6509a0ae 100644
--- a/macros/luatex/generic/minim-math/minim-math.pdf
+++ b/macros/luatex/generic/minim-math/minim-math.pdf
Binary files differ
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⟧&copy 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⟧&copy 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
index 4760106341..538ac5ba55 100644
--- a/macros/luatex/generic/minim-mp/minim-mp.pdf
+++ b/macros/luatex/generic/minim-mp/minim-mp.pdf
Binary files differ
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
index 2056601eec..9fc6616988 100644
--- a/macros/luatex/generic/minim-pdf/minim-pdf.pdf
+++ b/macros/luatex/generic/minim-pdf/minim-pdf.pdf
Binary files differ
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
index fdf38f3a2c..5fd58cc74c 100644
--- a/macros/luatex/generic/minim-xmp/minim-xmp.pdf
+++ b/macros/luatex/generic/minim-xmp/minim-xmp.pdf
Binary files differ
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
index e7a0519965..bd46c62c35 100644
--- a/macros/luatex/generic/minim/minim.pdf
+++ b/macros/luatex/generic/minim/minim.pdf
Binary files differ