1
2
3\environment luametafunstyle
4
5\startcomponent luametafuninterface
6
7\startchapter[title={Interface}]
8
9\startsection[title=Macros]
10
11Because graphic solutions are always kind of personal or domain driven it makes not
12much sense to cook up very generic solutions. If you have a project where \METAPOST\
13can be of help, it also makes sense to spend some time on implementing the basics that
14you need. In that case you can just copy and tweak what is there. The easiest way to
15do that is to make a test file and use:
16
17\starttyping[option=TEX]
18\startMPpage
19
20\stopMPpage
21\stoptyping
22
23Often you dont need to write macros, and standard drawing commands will do the
24job, but when you find yourself repeating code, a wapper might make sense. And
25this is why we have this keyvalue interface: its easier to abstract your
26settings than to pass them as (expression or text) arguments to a macro,
27especially when there are many.
28
29You can find many examples of the keyvalue driven user interface in the source
30files and these are actually not that hard to understand when you know a bit of
31\METAPOST\ and the additional macros that come with \METAFUN. In case you wonder
32about overhead: the performance of this mechanism is pretty good.
33
34Although the parameter handler runs on top of the \LUA\ interface, you dont need
35to use \LUA\ unless you find that \METAPOST\ cant do the job. I wont give
36examples of coding because I think that the source of \METAFUN\ provides enough
37clues, especially the file \type {mplmtx.mpxl}. As the name suggests this is
38part of the \CONTEXT\ version \LMTX, which runs on top of \LUAMETATEX. I leave it
39open if I will backport this functionality to \LUATEX\ and therefore \MKIV.
40
41An excellent explanation of this interface can be found at:
42
43\starttyping
44https:adityam.github.iocontextblogpostnewmetafuninterface
45\stoptyping
46
47So (at least for now) here I can stick to just mentioning the currently stable
48interface macros:
49
50\starttabulate[Tlpl]
51\FL
52\NC presetparameters \NC \type {name [...]} \NC
53 Assign default values to a category of parameters. Sometimes it makes sense
54 not to set a default, because then you can check if a parameter has been set
55 at all.
56 \NC \NR
57\NC applyparameters \NC \type {name macro} \NC
58 This prepares the parameter handler for the given category and calls the
59 given macro when that is done.
60 \NC \NR
61\NC getparameters \NC \type {name [...]} \NC
62 The parameters given after the category name are set.
63 \NC \NR
64\ML
65\NC hasparameter \NC \type {names} \NC
66 Returns \type {true} when a parameter is set, and \type {false} otherwise.
67 \NC \NR
68\NC hasoption \NC \type {names options} \NC
69 Returns \type {true} when there is overlap in given options, and \type
70 {false} otherwise.
71 \NC \NR
72\ML
73\NC getparameter \NC \type {names} \NC
74 Resolves the parameter with the given name. because a parameter itself can
75 have a parameter list you can pass additional names to reach the final
76 destination.
77 \NC \NR
78\NC getparameterdefault \NC \type {names} \NC
79 Resolves the parameter with the given name. because a parameter itself can
80 have a parameter list you can pass additional names to reach the final
81 destination. The last value is used when no parameter is found.
82 \NC \NR
83\ML
84\NC getparametercount \NC \type {names} \NC
85 Returns the size if a list (array).
86 \NC \NR
87\NC getmaxparametercount \NC \type {names} \NC
88 Returns the size if a list (array) but descends into lists to find the largest size
89 of a sublist.
90 \NC \NR
91\ML
92\NC getparameterpath \NC \type {names string boolean} \NC
93 Returns the parameter as path. The optional string is one of \type {},
94 \type {..} or \type {...} and the also optional boolean will force a closed
95 path.
96 \NC \NR
97\NC getparameterpen \NC \type {names} \NC
98 Returns the parameter as pen (path).
99 \NC \NR
100\NC getparametertext \NC \type {names boolean} \NC
101 Returns the parameter as string. The boolean can be used to force prepending
102 a so called \type {\strut}.
103 \NC \NR
104\ML
105\NC pushparameters \NC \type {category} \NC
106 Pushed the given (sub) category onto the stack so that we dont need to give
107 the category each time.
108 \NC \NR
109\NC popparameters \NC \NC
110 Pops the current (sub) category from the stack.
111 \NC \NR
112\LL
113\stoptabulate
114
115Most commands accept a list of strings separated by one or more spaces, The
116resolved will then stepwise descend into the parameter tree. This means that a
117parameter itself can refer to a list. When a value is an array and the last name
118is a number, the value at the given index will be returned.
119
120\starttyping
121"category" "name" ... "name"
122"category" "name" ... number
123\stoptyping
124
125The \type {category} is not used when we have pushed a (sub) category which can
126save you some typing and also is more efficient. Of course than can mean that you
127need to store values at a higher level when you need them at a deeper level.
128
129There are quite some extra helpers that relate to this mechanism, at the
130\METAPOST\ end as well as at the \LUA\ end. They aim for instance at efficiently
131dealing with paths and can be seen at work in the mentioned module.
132
133There is one thing you should notice. While \METAPOST\ has numeric, string,
134boolean and path variables that can be conveniently be passed to and from \LUA,
135communicating colors is a bit of a hassle. This is because \RGB\ and \CMYK\
136colors and gray scales use different types. For this reason it is strongly
137recommended to use strings that refer to predefined colors instead. This also
138enforces consistency with the \TEX\ end. As convenience you can define colors at
139the \METAFUN\ end.
140
141\startbuffer
142\startMPcode
143 definecolor [ name = "MyColor", r = .5, g = .25, b = .25 ]
144
145 fill fullsquare xyscaled (TextWidth,5mm) withcolor "MyColor" ;
146\stopMPcode
147\stopbuffer
148
149\typebuffer[option=TEX]
150
151\startlinecorrection
152\getbuffer
153\stoplinecorrection
154
155\stopsection
156
157\startsection[title=Units]
158
159Many dimensions used at the \TEX\ end are also available in \METAFUN. Examples
160are \typ {TextWidth}, \typ {EmHeight} and \typ {StrutHeight}. In \MKIV\ they are
161numeric variables that get set every graphic but in \MKXL\ these are not numeric
162variables but (hidden) \LUA\ calls so they cant be set at the \METAPOST\ end;
163but they are injected as numeric quantities so you can efficiently them in
164calculations.
165
166In \METAPOST\ examples you often find \type {u} being used as unit, like:
167
168\starttyping
169u := 1cm ; draw (u,0) (u,u) (3u,0);
170\stoptyping
171
172However, what if you want to set such a unit at the \TEX\ end? For this purpose
173we have a dedicated variable, which is demonstrated in the following examples.
174First we set a variable:
175
176\starttyping[option=TEX]
177\uunit=1cm
178\stoptyping
179
180\typebuffer[option=TEX]
181
182and next we apply it:
183
184\startbuffer
185\framed[offset=.2uu,strut=no]
186 \bgroup
187 \startMPcode
188 fill fullcircle scaled (2uu) withcolor "darkblue" ;
189 fill fullcircle scaled (8mm) withcolor "middlegray" ;
190 \stopMPcode
191 \egroup
192\stopbuffer
193
194\typebuffer[option=TEX]
195
196The \type {\uunit} dimension register is hooked into \TEXs unit parser as type
197{uu} (user unit). At the \METAPOST\ end \type {uu} is effectively a \LUA\ call
198that fetches the of the dimension from the \TEX end and presents it a a numeric.
199
200\startlinecorrection \uunit=1cm \getbuffer \stoplinecorrection
201
202When we set
203
204\starttyping[option=TEX]
205\uunit=5mm
206\stoptyping
207
208The same code gives::
209
210\startlinecorrection \uunit=5mm \getbuffer \stoplinecorrection
211
212\startbuffer
213\framed[offset=.1uu,strut=no]
214 \bgroup
215 \startMPcode
216 save uu ; numeric uu ; uu := 5mm ;
217 fill fullcircle scaled (3uu) withcolor "darkred" ;
218 fill fullcircle scaled (2uu) withcolor "middlegray" ;
219 \stopMPcode
220 \egroup
221\stopbuffer
222
223\typebuffer[option=TEX]
224
225This demonstrates that we can overload \type {uu} but make sure to save it first
226so that later it is available again.
227
228\startlinecorrection \getbuffer \stoplinecorrection
229
230\stopsection
231
232\startsection[title=Paths from \LUA]
233
234Passing paths to \METAPOST\ using specific properties is sort of tricky because
235once the points are set, the solver will be applied. This translates curls,
236tensions andor explicit control points into the final control points.
237
238In the next example we show a few interfaces. Not all of that might be perfect
239yes but in most cases it works out.
240
241\startbuffer
242\startluacode
243 local shapes = { }
244 shapes[1] = { {0,0}, {-1,-1}, {-1, 0}, {0,0}, "cycle" }
245 shapes[2] = { {0,1}, { 1, 0}, { 1,-1}, {0,1}, "cycle" }
246 shapes[3] = { {0,2}, { 2, 0}, { 2, 1}, {0,2}, "cycle" }
247 shapes[4] = {
248 {0,0}, {-1,-1}, {-1, 0}, {0,0}, "cycle", "append",
249 {0,1}, { 1, 0}, { 1,-1}, {0,1}, "cycle", "append",
250 {0,2}, { 2, 0}, { 2, 1}, {0,2}, "cycle", "append",
251 }
252 shapes[5] = {
253 { path = shapes[1], append = true },
254 { path = shapes[2], append = true },
255 { path = shapes[3], append = true },
256 }
257 function mp.getshapepath(n)
258 mp.inject.path(shapes[n])
259 end
260\stopluacode
261\stopbuffer
262
263\typebuffer[option=TEX] \getbuffer
264
265\startbuffer
266\startMPcode
267 path p ;
268 p := lua.mp.getshapepath(1) scaled 1cm ;
269 draw p withpen pencircle scaled 2pt withcolor red ;
270 p := lua.mp.getshapepath(2) scaled 1cm ;
271 draw p withpen pencircle scaled 2pt withcolor blue ;
272 p := lua.mp.getshapepath(3) scaled 1cm ;
273 draw p withpen pencircle scaled 2pt withcolor green ;
274 p := lua.mp.getshapepath(4) scaled 1cm cycle ;
275 fill p withcolor 0.9 ;
276 draw p withpen pencircle scaled 1pt withcolor 0.7 ;
277 p := lua.mp.getshapepath(5) scaled 1cm ;
278 draw p withpen pencircle scaled .25pt withcolor 0.2 ;
279\stopMPcode
280\stopbuffer
281
282\typebuffer[option=TEX]
283
284Especially cycling and appending needs to be done precisely in order not to get
285redundant (or bad) points.
286
287\startlinecorrection \getbuffer \stoplinecorrection
288
289This combines the first three paths similar to the fourth and fifths. If you
290doubt what you get you can always \type {show} the path and look for \type
291{{begin}} and \type {{end}} indicators.
292
293\startbuffer
294\startMPcode
295 path p ;
296 p := lua.mp.getshapepath(1) scaled 1cm &&
297 lua.mp.getshapepath(2) scaled 1cm &&
298 lua.mp.getshapepath(3) scaled 1cm ;
299 draw p withpen pencircle scaled 1pt withcolor 0.7 ;
300
301\stopMPcode
302\stopbuffer
303
304\typebuffer[option=TEX]
305
306We draw the result and see that they are decoupled indeed thanks to some \type
307{} magic:
308
309\startlinecorrection \getbuffer \stoplinecorrection
310
311\stopsection
312
313\stopchapter
314
315\stopcomponent
316 |