summaryrefslogtreecommitdiff
path: root/macros/luatex/generic/minim-mp/minim-mp.doc
blob: 2f7541ba759f25a6a86d8b964aeb0b0851848fc3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434

\input minim-doc.sty

\manual{minim-mp}

\ifchapter \chapter Metapost

\else \startmetadata
    author   {Esger Renkema}
    title    {minim-mp}
    date     {2023-10-20}
    version  {2023/1.3}
    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⟧.

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.

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 logging of the metapost run will be included in the regular log file. If an 
error occurs, the logging 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 
sizes adjusted to image dimensions. You might need generate the format first, 
this is done with
\stopformulatagging$$\hbox{⟦luatex  --ini  minim-mp.ini⟧}$$\startformulatagging
Use minim-lamp instead of minim-mp for a latex-based version of the minim-mp 
format.
With minim-lamp, for specifying the contents of the preamble, you can use
⟦verbatimtex ... etex;⟧ statements at the top of your file.
Concluding the preamble with ⟦\begin{document}⟧ is optional, as both ⟦\begin⟧ 
and ⟦\end{document}⟧ will be inserted automatically if omitted.

\section LaTeX compatibility %1

An experimental latex package is included in ⟦minim-mp.sty⟧. It accepts no 
options, as it really is a rather thin wrapper around the plain tex package.
It does, however, provide a proper ⟦*metapost⟧ latex environment as an 
alternative to ⟦\directmetapost⟧.

The ⟦metapost⟧ environment has no persistent backing instance.
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 below.


\section Metapost instances %1

For more complicated uses, you can define your own instances by saying
⟦*\newmetapostinstance [ options ] \id⟧.
An instance can be closed with ⟦*\closemetapostinstance \id⟧.
These are the options you can use:

\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
⟦math⟧&⟦'scaled'⟧&One of ⟦scaled⟧, ⟦decimal⟧ or ⟦double⟧.\cr
⟦seed⟧&⟦nil⟧&Random seed for this instance.\cr
⟦catcodes⟧&⟦0⟧&Catcode table for ⟦btex ... etex⟧.\cr
⟦env⟧&copy of ⟦_G⟧&Lua environment; see below.\cr
}\smallskip

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.

⟦*\getnextmpimage  \id⟧
– Writes the first unretrieved image to the current node list.
There, the image will be contained in a single box node.

⟦*\getnamedmpimage \id {name}⟧
– Retrieves an image by name
regardless of its position,
and writes it to the current node list.

⟦*\boxnextmpimage  \id box-nr⟧
– Puts the next unretrieved image in box ⟦box-nr⟧. The number may be anything 
tex can parse as a number.

⟦*\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.

Finally, as a shorthand, ⟦*\runmetapostimage \id { code }⟧ will add
⟦beginfig ... endfig⟧ to your ⟦code⟧ and write the resulting image immediately 
to the current list.


\section Running tex from within metapost %1

You can include tex snippets with either ⟦*maketext "tex text"⟧ or
⟦*btex ... etex⟧ statements. The tex code will be executed in the current 
environment without an extra grouping level. The result of either statement at 
the place where it is invoked is an image object of the proper dimensions that 
can be moved, scaled, rotated and mirrored. You can even specify a colour. Its 
contents, however, will only be added afterwards and are invisible to metapost.

Arbitrary tex statements may be included in ⟦*verbatimtex ... etex⟧, which may 
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.

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⟧ 
for each character. The right-hand argument of ⟦infont⟧ should either be 
a (numerical) font~id or the (cs)name of a font (without backslash).

One possible use of the ⟦infont⟧ operator is setting text along curves:

\nobreak
⟦beginfig(1)
    save t, w, r, a; picture t;
    t = "Running TeX from within MetaPost" infont "tenrm";
    w = xpart lrcorner t = 3.141593 r;
    for c within t :
        x := xpart (llcorner c + lrcorner c)/2;
        a := 90 - 180 x/w;
        draw c rotatedaround((x,0), a)
               shifted (-r*sind(a)-x, r*cosd(a));
    endfor
endfig;⟧
\vskip-2\parskip plus 2\parskip
\quitvmode\hfil
\startelement alt {The text ‘Running TeX from within MetaPost’ set along a half-circle.} {Figure}%
\stoptagging\directmetapost{%
beginfig(1)
    save t, w, r, a; picture t;
    t = "Running TeX from within MetaPost" infont "tenrm";
    w = xpart lrcorner t = 3.141593 r;
    for c within t :
        x := xpart (llcorner c + lrcorner c)/2;
        a := 90 - 180 x/w;
        draw c rotatedaround((x,0), a)
               shifted (-r*sind(a)-x, r*cosd(a));
    endfor
endfig;}\starttagging \stopelement{Figure}

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⟧).

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.

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 the next section).


\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. This has been made possible 
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 }
\directmetapost{beginfig(1) multidraw (contours "example" of "tenbf")
withpen currentpen scaled 1/10; baseline 0; endfig;}}
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 Running lua from within metapost %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. It currently contains two functions: ⟦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
⟦runscript ("[[function_name]]" & raw_string)⟧.
This will return the result of the function ⟦function_name⟧ applied to 
⟦raw_string⟧ as a lua string.

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 or colour by returning an array of 
two to four elements. For other return values, ⟦tostring()⟧ will be called.


\section Passing values to lua

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⟧ 
returns ⟦0.00002⟧, which metapost understands as ⟦1/65536⟧, but lua as 
⟦1/50000⟧. Use the metapost macro ⟦*hexadecimal⟧ instead of ⟦decimal⟧ for 
passing unambiguous numbers to lua.

Additionally, you should be aware that metapost uses slightly bigger points 
than tex, so that ⟦epsilon⟧ when taken as a dimension is not quite equal to 
⟦1sp⟧. Use the metapost macro ⟦*scaledpoints⟧ for passing to lua a metapost 
dimension as an integral number of scaled points.

Strings can be passed to lua with the ⟦*lua_string⟧ macro, which escapes the 
necessary characters and then surrounds its argument with quotes.
A generic macro for passing values to lua, finally, is ⟦*quote_for_lua⟧, which 
automatically converts strings, numbers, points and colours to (metapost) 
strings that lua can understand.


\section Querying tex and lua variables

Stitching together lua snippets by hand is not very convenient. Therefore, 
minim-mp provides three helper macros that should cover most lua interaction.
For running a single lua function, ⟦*luafunction⟧ ⟦<suffix> (<arguments>)⟧ 
returns the result of the function ⟦str <suffix>⟧ applied to any number of 
arguments, which are quoted automatically.
Variables can be queried with ⟦*luavariable⟧ ⟦<suffix>⟧
and set with ⟦*setluavariable⟧ ⟦<suffix> = <value>;⟧.

The details of metapost tokenisation make these macros rather powerful: you can 
not only say e.g. ⟦luavariable tex.jobname⟧ to get the current jobname, but 
even define a ⟦texvariable⟧ macro with
\stopformulatagging$$\hbox{⟦vardef texvariable @# = luavariable tex @# enddef;⟧}$$\startformulatagging
and have ⟦texvariable jobname⟧ work as expected.

For accessing count, dimen, attribute or toks registers, the macros are
⟦*tex.count⟧ ⟦[number]⟧ or ⟦*tex.count⟧⟦.name⟧ [etc. etc.] for getting and
⟦*set tex.count⟧ ⟦[number] = value⟧ or ⟦*tex.count⟧⟦.name = value⟧ etc. for 
setting values.


\section Tiling patterns %1

The condition ⟦*withpattern(<name>)⟧ added to a ⟦fill⟧ statement will fill the path with 
a pattern instead of a solid colour. If the patterns contains no colour 
information of itself, 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.

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⟧.

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 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}
\directmetapost{
% 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;}\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;⟧

A small pattern library is available in the ⟦*minim-hatching.mp⟧ file; see the 
accompanying documentation sheet for an overview of patterns.


\section Other metapost extensions %1

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.

You can write to tex’s log directly with ⟦*texmessage "hello"⟧.

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.

Minim-mp also provides a few elementary macros and constants that are 
conspicuously absent from plain.mp; I hope their addition is uncontroversial.
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).

\section Lua interface %1

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 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.

Each metapost instance is a table containing the following entries:

\smallskip\smallskip
\marktableaslist \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}


\section Debugging %1

You can enable (global) debugging by saying ⟦*debug_pdf⟧ to metapost 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, a small summary of every generated image will be written to log 
and terminal.


\section Extending metapost %1

You can extend this package by adding new metapost specials. Specials should 
have the form ⟦"identifier: instructions"⟧ and can be added as pre- or 
postscript to metapost objects. A single object can carry multiple specials and a
⟦*special "..."⟧ statement is equivalent to an empty object with a single 
prefix.

Handling of specials is specified in three lua tables: ⟦*M.specials⟧, 
⟦*M.prescripts⟧ and ⟦*M.postscripts⟧.
The ⟦identifier⟧ above should equal the key of an entry in the relevant table,
while the value of an entry in one of these tables should be a function with 
three parameters: the internal image processor state, the ⟦instructions⟧ from 
above and the metapost object itself.

If the ⟦identifier⟧ of a prescript is present in the first table, the 
corresponding function will replace normal object processing.
Only one prescript may match with this table.
Functions in the the other two tables will run before or after normal 
processing.

Specials can store information in the ⟦user⟧ table of the picture that is being 
processed; this information is still available inside the ⟦*finish_mpfigure⟧ 
callback that is executed just before the processed image is surrounded by 
properly-dimensioned boxes.

The ⟦*M.init_code⟧ table contains the code used for initialing new instances. 
In it, the string ⟦INIT⟧ will be replaced with the value of the ⟦format⟧ option 
(normally ⟦plain.mp⟧).

\endmanual %