mlib-pps.lmt /size: 57 Kb    last modification: 2021-10-28 13:51
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
mlib-pps
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to mlib-ctx.mkiv
"
,
4
author
=
"
Hans Hagen, PRAGMA-ADE, Hasselt NL
"
,
5
copyright
=
"
PRAGMA ADE / ConTeXt Development Team
"
,
6
license
=
"
see context related readme files
"
,
7
}
8 9
local
next
=
next
10
local
format
,
gmatch
,
match
,
split
,
gsub
=
string
.
format
,
string
.
gmatch
,
string
.
match
,
string
.
split
,
string
.
gsub
11
local
tonumber
,
type
,
unpack
,
next
,
select
=
tonumber
,
type
,
unpack
,
next
,
select
12
local
round
,
sqrt
,
min
,
max
,
abs
=
math
.
round
,
math
.
sqrt
,
math
.
min
,
math
.
max
,
math
.
abs
13
local
insert
,
remove
,
concat
=
table
.
insert
,
table
.
remove
,
table
.
concat
14
local
Cs
,
Cf
,
C
,
Cg
,
Ct
,
P
,
S
,
V
,
Carg
=
lpeg
.
Cs
,
lpeg
.
Cf
,
lpeg
.
C
,
lpeg
.
Cg
,
lpeg
.
Ct
,
lpeg
.
P
,
lpeg
.
S
,
lpeg
.
V
,
lpeg
.
Carg
15
local
lpegmatch
,
tsplitat
,
tsplitter
=
lpeg
.
match
,
lpeg
.
tsplitat
,
lpeg
.
tsplitter
16
local
formatters
,
toboolean
=
string
.
formatters
,
string
.
toboolean
17
local
exists
,
savedata
=
io
.
exists
,
io
.
savedata
18
local
stepper
=
utilities
.
parsers
.
stepper
19 20
local
mplib
=
mplib
21
local
metapost
=
metapost
22
local
lpdf
=
lpdf
23
local
context
=
context
24 25
local
scan
=
mp
.
scan
26
local
inject
=
mp
.
inject
27 28
local
mpscanstring
=
scan
.
string
29
local
mpscannumeric
=
scan
.
numeric
30 31
local
injecttriplet
=
inject
.
triplet
32 33
local
registerdirect
=
metapost
.
registerdirect
34 35
local
implement
=
interfaces
.
implement
36
local
setmacro
=
interfaces
.
setmacro
37 38
local
texsetbox
=
tex
.
setbox
39
local
textakebox
=
tex
.
takebox
-- or: nodes.takebox
40
local
texrunlocal
=
tex
.
runlocal
41
local
copylist
=
nodes
.
copylist
42
local
flushlist
=
nodes
.
flushlist
43
local
setmetatableindex
=
table
.
setmetatableindex
44
local
sortedhash
=
table
.
sortedhash
45 46
local
new_hlist
=
nodes
.
pool
.
hlist
47 48
local
starttiming
=
statistics
.
starttiming
49
local
stoptiming
=
statistics
.
stoptiming
50 51
local
trace_runs
=
false
trackers
.
register
(
"
metapost.runs
"
,
function
(
v
)
trace_runs
=
v
end
)
52
local
trace_textexts
=
false
trackers
.
register
(
"
metapost.textexts
"
,
function
(
v
)
trace_textexts
=
v
end
)
53
local
trace_scripts
=
false
trackers
.
register
(
"
metapost.scripts
"
,
function
(
v
)
trace_scripts
=
v
end
)
54
local
trace_btexetex
=
false
trackers
.
register
(
"
metapost.btexetex
"
,
function
(
v
)
trace_btexetex
=
v
end
)
55 56
local
report_metapost
=
logs
.
reporter
(
"
metapost
"
)
57
local
report_textexts
=
logs
.
reporter
(
"
metapost
"
,
"
textexts
"
)
58
local
report_scripts
=
logs
.
reporter
(
"
metapost
"
,
"
scripts
"
)
59 60
local
colors
=
attributes
.
colors
61
local
defineprocesscolor
=
colors
.
defineprocesscolor
62
local
definespotcolor
=
colors
.
definespotcolor
63
local
definemultitonecolor
=
colors
.
definemultitonecolor
64
local
colorvalue
=
colors
.
value
65 66
local
transparencies
=
attributes
.
transparencies
67
local
registertransparency
=
transparencies
.
register
68
local
transparencyvalue
=
transparencies
.
value
69 70
local
rgbtocmyk
=
colors
.
rgbtocmyk
-- or function() return 0,0,0,1 end
71
local
cmyktorgb
=
colors
.
cmyktorgb
-- or function() return 0,0,0 end
72
local
rgbtogray
=
colors
.
rgbtogray
-- or function() return 0 end
73
local
cmyktogray
=
colors
.
cmyktogray
-- or function() return 0 end
74 75
local
nooutercolor
=
"
0 g 0 G
"
76
local
nooutertransparency
=
"
/Tr0 gs
"
-- only when set
77
local
outercolormode
=
0
78
local
outercolormodel
=
1
79
local
outercolor
=
nooutercolor
80
local
outertransparency
=
nooutertransparency
81
local
innercolor
=
nooutercolor
82
local
innertransparency
=
nooutertransparency
83 84
local
pdfcolor
=
lpdf
.
color
85
local
pdftransparency
=
lpdf
.
transparency
86 87
function
metapost
.
setoutercolor
(
mode
,
colormodel
,
colorattribute
,
transparencyattribute
)
88
-- has always to be called before conversion
89
-- todo: transparency (not in the mood now)
90
outercolormode
=
mode
91
outercolormodel
=
colormodel
92
if
mode
=
=
1
or
mode
=
=
3
then
93
-- inherit from outer (registered color)
94
outercolor
=
pdfcolor
(
colormodel
,
colorattribute
)
or
nooutercolor
95
outertransparency
=
pdftransparency
(
transparencyattribute
)
or
nooutertransparency
96
elseif
mode
=
=
2
then
97
-- stand alone (see m-punk.tex)
98
outercolor
=
"
"
99
outertransparency
=
"
"
100
else
-- 0
101
outercolor
=
nooutercolor
102
outertransparency
=
nooutertransparency
103
end
104
innercolor
=
outercolor
105
innertransparency
=
outertransparency
-- not yet used
106
end
107 108
-- todo: get this from the lpdf module
109 110
local
f_f
=
formatters
[
"
%.6N
"
]
111
local
f_f3
=
formatters
[
"
%.3N
"
]
112
local
f_gray
=
formatters
[
"
%.3N g %.3N G
"
]
113
local
f_rgb
=
formatters
[
"
%.3N %.3N %.3N rg %.3N %.3N %.3N RG
"
]
114
local
f_cmyk
=
formatters
[
"
%.3N %.3N %.3N %.3N k %.3N %.3N %.3N %.3N K
"
]
115
local
f_cm_b
=
formatters
[
"
q %.6N %.6N %.6N %.6N %.6N %.6N cm
"
]
116
local
f_scn
=
formatters
[
"
%.3N
"
]
117 118
local
f_shade
=
formatters
[
"
MpSh%s
"
]
119
local
f_spot
=
formatters
[
"
/%s cs /%s CS %s SCN %s scn
"
]
120 121
local
s_cm_e
<const>
=
"
Q
"
122 123
local
function
checked_color_pair
(
color
,
...
)
124
if
not
color
then
125
return
innercolor
,
outercolor
126
end
127
if
outercolormode
=
=
3
then
128
innercolor
=
color
(
...
)
129
return
innercolor
,
innercolor
130
else
131
return
color
(
...
)
,
outercolor
132
end
133
end
134 135
function
metapost
.
colorinitializer
(
)
136
innercolor
=
outercolor
137
innertransparency
=
outertransparency
138
return
outercolor
,
outertransparency
139
end
140 141
--~
142 143
local
specificationsplitter
=
tsplitat
(
"
"
)
144
local
colorsplitter
=
tsplitter
(
"
:
"
,
tonumber
)
-- no need for :
145
local
domainsplitter
=
tsplitter
(
"
"
,
tonumber
)
146
local
centersplitter
=
domainsplitter
147
local
coordinatesplitter
=
domainsplitter
148 149
-- thanks to taco's reading of the postscript manual:
150
--
151
-- x' = sx * x + ry * y + tx
152
-- y' = rx * x + sy * y + ty
153 154
local
nofshades
=
0
-- todo: hash resources, start at 1000 in order not to clash with older
155 156
local
function
normalize
(
ca
,
cb
)
157
if
#
cb
=
=
1
then
158
if
#
ca
=
=
4
then
159
cb
[
1
]
,
cb
[
2
]
,
cb
[
3
]
,
cb
[
4
]
=
0
,
0
,
0
,
1
-
cb
[
1
]
160
else
161
cb
[
1
]
,
cb
[
2
]
,
cb
[
3
]
=
cb
[
1
]
,
cb
[
1
]
,
cb
[
1
]
162
end
163
elseif
#
cb
=
=
3
then
164
if
#
ca
=
=
4
then
165
cb
[
1
]
,
cb
[
2
]
,
cb
[
3
]
,
cb
[
4
]
=
rgbtocmyk
(
cb
[
1
]
,
cb
[
2
]
,
cb
[
3
]
)
166
else
167
cb
[
1
]
,
cb
[
2
]
,
cb
[
3
]
=
cmyktorgb
(
cb
[
1
]
,
cb
[
2
]
,
cb
[
3
]
,
cb
[
4
]
)
168
end
169
end
170
end
171 172 173
local
commasplitter
=
tsplitat
(
"
,
"
)
174 175
local
function
checkandconvertspot
(
n_a
,
f_a
,
c_a
,
v_a
,
n_b
,
f_b
,
c_b
,
v_b
)
176
-- must be the same but we don't check
177
local
name
=
f_shade
(
nofshades
)
178
local
ca
=
lpegmatch
(
commasplitter
,
v_a
)
179
local
cb
=
lpegmatch
(
commasplitter
,
v_b
)
180
if
#
ca
=
=
0
or
#
cb
=
=
0
then
181
return
{
0
}
,
{
1
}
,
"
DeviceGray
"
,
name
182
else
183
for
i
=
1
,
#
ca
do
ca
[
i
]
=
tonumber
(
ca
[
i
]
)
or
0
end
184
for
i
=
1
,
#
cb
do
cb
[
i
]
=
tonumber
(
cb
[
i
]
)
or
1
end
185
--~ spotcolorconverter(n_a,f_a,c_a,v_a) -- not really needed
186
return
ca
,
cb
,
n_a
or
n_b
,
name
187
end
188
end
189 190
local
function
checkandconvert
(
ca
,
cb
,
model
)
191
local
name
=
f_shade
(
nofshades
)
192
if
not
ca
or
not
cb
or
type
(
ca
)
=
=
"
string
"
then
193
return
{
0
}
,
{
1
}
,
"
DeviceGray
"
,
name
194
else
195
if
#
ca
>
#
cb
then
196
normalize
(
ca
,
cb
)
197
elseif
#
ca
<
#
cb
then
198
normalize
(
cb
,
ca
)
199
end
200
if
not
model
then
201
model
=
colors
.
currentnamedmodel
(
)
202
end
203
if
model
=
=
"
all
"
then
204
model
=
(
#
ca
=
=
4
and
"
cmyk
"
)
or
(
#
ca
=
=
3
and
"
rgb
"
)
or
"
gray
"
205
end
206
if
model
=
=
"
rgb
"
then
207
if
#
ca
=
=
4
then
208
ca
=
{
cmyktorgb
(
ca
[
1
]
,
ca
[
2
]
,
ca
[
3
]
,
ca
[
4
]
)
}
209
cb
=
{
cmyktorgb
(
cb
[
1
]
,
cb
[
2
]
,
cb
[
3
]
,
cb
[
4
]
)
}
210
elseif
#
ca
=
=
1
then
211
local
a
=
1
-
ca
[
1
]
212
local
b
=
1
-
cb
[
1
]
213
ca
=
{
a
,
a
,
a
}
214
cb
=
{
b
,
b
,
b
}
215
end
216
return
ca
,
cb
,
"
DeviceRGB
"
,
name
,
model
217
elseif
model
=
=
"
cmyk
"
then
218
if
#
ca
=
=
3
then
219
ca
=
{
rgbtocmyk
(
ca
[
1
]
,
ca
[
2
]
,
ca
[
3
]
)
}
220
cb
=
{
rgbtocmyk
(
cb
[
1
]
,
cb
[
2
]
,
cb
[
3
]
)
}
221
elseif
#
ca
=
=
1
then
222
ca
=
{
0
,
0
,
0
,
ca
[
1
]
}
223
cb
=
{
0
,
0
,
0
,
ca
[
1
]
}
224
end
225
return
ca
,
cb
,
"
DeviceCMYK
"
,
name
,
model
226
else
227
if
#
ca
=
=
4
then
228
ca
=
{
cmyktogray
(
ca
[
1
]
,
ca
[
2
]
,
ca
[
3
]
,
ca
[
4
]
)
}
229
cb
=
{
cmyktogray
(
cb
[
1
]
,
cb
[
2
]
,
cb
[
3
]
,
cb
[
4
]
)
}
230
elseif
#
ca
=
=
3
then
231
ca
=
{
rgbtogray
(
ca
[
1
]
,
ca
[
2
]
,
ca
[
3
]
)
}
232
cb
=
{
rgbtogray
(
cb
[
1
]
,
cb
[
2
]
,
cb
[
3
]
)
}
233
end
234
-- backend specific (will be renamed)
235
return
ca
,
cb
,
"
DeviceGray
"
,
name
,
model
236
end
237
end
238
end
239 240
-- We keep textexts in a shared list (as it's easier that way and we also had that in
241
-- the beginning). Each graphic gets its own (1 based) subtable so that we can also
242
-- handle multiple conversions in one go which is needed when we process mp files
243
-- directly.
244 245
local
stack
=
{
}
-- quick hack, we will pass topofstack around
246
local
top
=
nil
247
local
nofruns
=
0
-- askedfig: "all", "first", number
248 249
local
function
preset
(
t
,
k
)
250
-- references to textexts by mp index
251
local
v
=
{
252
textrial
=
0
,
253
texfinal
=
0
,
254
texslots
=
{
}
,
255
texorder
=
{
}
,
256
texhash
=
{
}
,
257
}
258
t
[
k
]
=
v
259
return
v
260
end
261 262
-- todo: nested startMPcode .. stopMPcode does weird
263 264
local
function
startjob
(
plugmode
,
kind
,
mpx
)
265
insert
(
stack
,
top
)
266
top
=
{
267
textexts
=
{
}
,
-- all boxes, optionally with a different color
268
texstrings
=
{
}
,
269
texregimes
=
{
}
,
270
mapstrings
=
{
}
,
271
mapindices
=
{
}
,
272
mapmoves
=
{
}
,
273
texlast
=
0
,
274
texdata
=
setmetatableindex
(
{
}
,
preset
)
,
-- references to textexts in order or usage
275
plugmode
=
plugmode
,
-- some day we can then skip all pre/postscripts
276
extradata
=
mpx
and
metapost
.
getextradata
(
mpx
)
,
277
}
278
if
trace_runs
then
279
report_metapost
(
"
starting %s run at level %i in %s mode
"
,
280
kind
,
#
stack
+
1
,
plugmode
and
"
plug
"
or
"
normal
"
)
281
end
282
return
top
283
end
284 285
local
function
stopjob
(
)
286
if
top
then
287
for
slot
,
content
in
next
,
top
.
textexts
do
288
if
content
then
289
flushlist
(
content
)
290
if
trace_textexts
then
291
report_textexts
(
"
freeing text %s
"
,
slot
)
292
end
293
end
294
end
295
if
trace_runs
then
296
report_metapost
(
"
stopping run at level %i
"
,
#
stack
+
1
)
297
end
298
top
=
remove
(
stack
)
299
return
top
300
end
301
end
302 303
function
metapost
.
getjobdata
(
)
304
return
top
305
end
306 307
-- end of new
308 309
local
settext
=
function
(
box
,
slot
,
str
)
310
if
top
then
311
-- if trace_textexts then
312
-- report_textexts("getting text %s from box %s",slot,box)
313
-- end
314
top
.
textexts
[
slot
]
=
textakebox
(
box
)
315
end
316
end
317 318
local
gettext
=
function
(
box
,
slot
)
319
if
top
then
320
texsetbox
(
box
,
top
.
textexts
[
slot
]
)
321
top
.
textexts
[
slot
]
=
false
322
-- if trace_textexts then
323
-- report_textexts("putting text %s in box %s",slot,box)
324
-- end
325
end
326
end
327 328
metapost
.
settext
=
settext
329
metapost
.
gettext
=
gettext
330 331
implement
{
name
=
"
mpsettext
"
,
actions
=
settext
,
arguments
=
{
"
integer
"
,
"
integer
"
}
}
-- box slot
332
implement
{
name
=
"
mpgettext
"
,
actions
=
gettext
,
arguments
=
{
"
integer
"
,
"
integer
"
}
}
-- box slot
333 334
-- rather generic pdf, so use this elsewhere too it no longer pays
335
-- off to distinguish between outline and fill (we now have both
336
-- too, e.g. in arrows)
337 338
metapost
.
reducetogray
=
true
339 340
local
models
=
{
}
341 342
function
models
.
all
(
cr
)
343
local
n
=
#
cr
344
if
n
=
=
0
then
345
return
checked_color_pair
(
)
346
elseif
metapost
.
reducetogray
then
347
if
n
=
=
1
then
348
local
s
=
cr
[
1
]
349
return
checked_color_pair
(
f_gray
,
s
,
s
)
350
elseif
n
=
=
3
then
351
local
r
=
cr
[
1
]
352
local
g
=
cr
[
2
]
353
local
b
=
cr
[
3
]
354
if
r
=
=
g
and
g
=
=
b
then
355
return
checked_color_pair
(
f_gray
,
r
,
r
)
356
else
357
return
checked_color_pair
(
f_rgb
,
r
,
g
,
b
,
r
,
g
,
b
)
358
end
359
else
360
local
c
=
cr
[
1
]
361
local
m
=
cr
[
2
]
362
local
y
=
cr
[
3
]
363
local
k
=
cr
[
4
]
364
if
c
=
=
m
and
m
=
=
y
and
y
=
=
0
then
365
k
=
1
-
k
366
return
checked_color_pair
(
f_gray
,
k
,
k
)
367
else
368
return
checked_color_pair
(
f_cmyk
,
c
,
m
,
y
,
k
,
c
,
m
,
y
,
k
)
369
end
370
end
371
elseif
n
=
=
1
then
372
local
s
=
cr
[
1
]
373
return
checked_color_pair
(
f_gray
,
s
,
s
)
374
elseif
n
=
=
3
then
375
local
r
=
cr
[
1
]
376
local
g
=
cr
[
2
]
377
local
b
=
cr
[
3
]
378
return
checked_color_pair
(
f_rgb
,
r
,
g
,
b
,
r
,
g
,
b
)
379
else
380
local
c
=
cr
[
1
]
381
local
m
=
cr
[
2
]
382
local
y
=
cr
[
3
]
383
local
k
=
cr
[
4
]
384
return
checked_color_pair
(
f_cmyk
,
c
,
m
,
y
,
k
,
c
,
m
,
y
,
k
)
385
end
386
end
387 388
function
models
.
rgb
(
cr
)
389
local
n
=
#
cr
390
if
n
=
=
0
then
391
return
checked_color_pair
(
)
392
elseif
metapost
.
reducetogray
then
393
if
n
=
=
1
then
394
local
s
=
cr
[
1
]
395
return
checked_color_pair
(
f_gray
,
s
,
s
)
396
elseif
n
=
=
3
then
397
local
r
=
cr
[
1
]
398
local
g
=
cr
[
2
]
399
local
b
=
cr
[
3
]
400
if
r
=
=
g
and
g
=
=
b
then
401
return
checked_color_pair
(
f_gray
,
r
,
r
)
402
else
403
return
checked_color_pair
(
f_rgb
,
r
,
g
,
b
,
r
,
g
,
b
)
404
end
405
else
406
local
c
=
cr
[
1
]
407
local
m
=
cr
[
2
]
408
local
y
=
cr
[
3
]
409
local
k
=
cr
[
4
]
410
if
c
=
=
m
and
m
=
=
y
and
y
=
=
0
then
411
k
=
1
-
k
412
return
checked_color_pair
(
f_gray
,
k
,
k
)
413
else
414
local
r
,
g
,
b
=
cmyktorgb
(
c
,
m
,
y
,
k
)
415
return
checked_color_pair
(
f_rgb
,
r
,
g
,
b
,
r
,
g
,
b
)
416
end
417
end
418
elseif
n
=
=
1
then
419
local
s
=
cr
[
1
]
420
return
checked_color_pair
(
f_gray
,
s
,
s
)
421
else
422
local
r
=
cr
[
1
]
423
local
g
=
cr
[
2
]
424
local
b
=
cr
[
3
]
425
local
r
,
g
,
b
426
if
n
=
=
3
then
427
r
,
g
,
b
=
cmyktorgb
(
r
,
g
,
b
,
cr
[
4
]
)
428
end
429
return
checked_color_pair
(
f_rgb
,
r
,
g
,
b
,
r
,
g
,
b
)
430
end
431
end
432 433
function
models
.
cmyk
(
cr
)
434
local
n
=
#
cr
435
if
n
=
=
0
then
436
return
checked_color_pair
(
)
437
elseif
metapost
.
reducetogray
then
438
if
n
=
=
1
then
439
local
s
=
cr
[
1
]
440
return
checked_color_pair
(
f_gray
,
s
,
s
)
441
elseif
n
=
=
3
then
442
local
r
=
cr
[
1
]
443
local
g
=
cr
[
2
]
444
local
b
=
cr
[
3
]
445
if
r
=
=
g
and
g
=
=
b
then
446
return
checked_color_pair
(
f_gray
,
r
,
r
)
447
else
448
local
c
,
m
,
y
,
k
=
rgbtocmyk
(
r
,
g
,
b
)
449
return
checked_color_pair
(
f_cmyk
,
c
,
m
,
y
,
k
,
c
,
m
,
y
,
k
)
450
end
451
else
452
local
c
=
cr
[
1
]
453
local
m
=
cr
[
2
]
454
local
y
=
cr
[
3
]
455
local
k
=
cr
[
4
]
456
if
c
=
=
m
and
m
=
=
y
and
y
=
=
0
then
457
k
=
1
-
k
458
return
checked_color_pair
(
f_gray
,
k
,
k
)
459
else
460
return
checked_color_pair
(
f_cmyk
,
c
,
m
,
y
,
k
,
c
,
m
,
y
,
k
)
461
end
462
end
463
elseif
n
=
=
1
then
464
local
s
=
cr
[
1
]
465
return
checked_color_pair
(
f_gray
,
s
,
s
)
466
else
467
local
c
=
cr
[
1
]
468
local
m
=
cr
[
2
]
469
local
y
=
cr
[
3
]
470
local
k
=
cr
[
4
]
471
if
n
=
=
3
then
472
if
c
=
=
m
and
m
=
=
y
then
473
k
,
c
,
m
,
y
=
1
-
c
,
0
,
0
,
0
474
else
475
c
,
m
,
y
,
k
=
rgbtocmyk
(
c
,
m
,
y
)
476
end
477
end
478
return
checked_color_pair
(
f_cmyk
,
c
,
m
,
y
,
k
,
c
,
m
,
y
,
k
)
479
end
480
end
481 482
function
models
.
gray
(
cr
)
483
local
n
=
#
cr
484
local
s
=
0
485
if
n
=
=
0
then
486
return
checked_color_pair
(
)
487
elseif
n
=
=
4
then
488
s
=
cmyktogray
(
cr
[
1
]
,
cr
[
2
]
,
cr
[
3
]
,
cr
[
4
]
)
489
elseif
n
=
=
3
then
490
s
=
rgbtogray
(
cr
[
1
]
,
cr
[
2
]
,
cr
[
3
]
)
491
else
492
s
=
cr
[
1
]
493
end
494
return
checked_color_pair
(
f_gray
,
s
,
s
)
495
end
496 497
models
[
1
]
=
models
.
all
498
models
[
2
]
=
models
.
gray
499
models
[
3
]
=
models
.
rgb
500
models
[
4
]
=
models
.
cmyk
501 502
setmetatableindex
(
models
,
function
(
t
,
k
)
503
local
v
=
models
.
gray
504
t
[
k
]
=
v
505
return
v
506
end
)
507 508
local
function
colorconverter
(
cs
)
509
return
models
[
outercolormodel
]
(
cs
)
510
end
511 512
local
factor
=
65536
*
(
7227
/
7200
)
513 514
implement
{
515
name
=
"
mpsetsxsy
"
,
516
arguments
=
{
"
dimen
"
,
"
dimen
"
,
"
dimen
"
}
,
517
actions
=
function
(
wd
,
ht
,
dp
)
518
local
hd
=
ht
+
dp
519
setmacro
(
"
mlib_sx
"
,
wd
~
=
0
and
factor
/
wd
or
0
)
520
setmacro
(
"
mlib_sy
"
,
hd
~
=
0
and
factor
/
hd
or
0
)
521
end
522
}
523 524
local
function
sxsy
(
wd
,
ht
,
dp
)
-- helper for text
525
local
hd
=
ht
+
dp
526
return
(
wd
~
=
0
and
factor
/
wd
)
or
0
,
(
hd
~
=
0
and
factor
/
hd
)
or
0
527
end
528 529
metapost
.
sxsy
=
sxsy
530 531
-- for stock mp we need to declare the booleans first
532 533
local
do_begin_fig
<const>
=
"
; beginfig(1) ;
"
534
local
do_end_fig
<const>
=
"
; endfig ;
"
535
local
do_safeguard
<const>
=
"
;
"
536 537
function
metapost
.
preparetextextsdata
(
)
538
local
textexts
=
top
.
textexts
539
local
collected
=
{
}
540
for
k
,
data
in
sortedhash
(
top
.
texdata
)
do
-- sort is nicer in trace
541
local
texorder
=
data
.
texorder
542
for
n
=
1
,
#
texorder
do
543
local
box
=
textexts
[
texorder
[
n
]
]
544
if
box
then
545
collected
[
n
]
=
box
546
else
547
break
548
end
549
end
550
end
551
mp
.
mf_tt_initialize
(
collected
)
552
end
553 554
local
runmetapost
=
metapost
.
run
555 556
local
function
checkaskedfig
(
askedfig
)
-- return askedfig, wrappit
557
if
not
askedfig
then
558
return
"
direct
"
,
true
559
elseif
askedfig
=
=
"
all
"
then
560
return
"
all
"
,
false
561
elseif
askedfig
=
=
"
direct
"
then
562
return
"
all
"
,
true
563
else
564
askedfig
=
tonumber
(
askedfig
)
565
if
askedfig
then
566
return
askedfig
,
false
567
else
568
return
"
direct
"
,
true
569
end
570
end
571
end
572 573
-- This one is called from the \TEX\ end so the specification is different
574
-- from the specification to metapost.run cum suis! The definitions and
575
-- extension used to be handled here but are now delegated to the format
576
-- initializers because we need to accumulate them for nested instances (a
577
-- side effect of going single pass).
578 579
function
metapost
.
graphic_base_pass
(
specification
)
580
local
mpx
=
specification
.
mpx
-- mandate
581
local
top
=
startjob
(
true
,
"
base
"
,
mpx
)
582
local
data
=
specification
.
data
or
"
"
583
local
inclusions
=
specification
.
inclusions
or
"
"
584
local
filtering
=
specification
.
filtering
585
local
initializations
=
specification
.
initializations
or
"
"
586
local
askedfig
,
587
wrappit
=
checkaskedfig
(
specification
.
figure
)
588
nofruns
=
nofruns
+
1
589
top
.
askedfig
=
askedfig
590
top
.
wrappit
=
wrappit
591
top
.
nofruns
=
nofruns
592
metapost
.
namespace
=
specification
.
namespace
or
"
"
593
top
.
mpx
=
mpx
594
top
.
data
=
data
595
top
.
initializations
=
initializations
596
if
filtering
then
597
if
#
filtering
>
0
then
598
local
t
=
{
}
599
stepper
(
filtering
,
function
(
k
)
t
[
k
]
=
true
end
)
600
filtering
=
next
(
t
)
and
t
or
false
601
else
602
filtering
=
false
603
end
604
end
605
if
trace_runs
then
606
report_metapost
(
"
running job %s, asked figure %a
"
,
nofruns
,
askedfig
)
607
end
608
runmetapost
{
609
mpx
=
mpx
,
610
askedfig
=
askedfig
,
611
incontext
=
true
,
612
filtering
=
filtering
,
613
data
=
{
614
inclusions
,
615
wrappit
and
do_begin_fig
or
"
"
,
616
initializations
,
617
do_safeguard
,
618
data
,
619
wrappit
and
do_end_fig
or
"
"
,
620
}
,
621
}
622
context
(
stopjob
)
623
end
624 625
local
function
oldschool
(
mpx
,
data
,
trial_run
,
flusher
,
was_multi_pass
,
is_extra_pass
,
askedfig
,
incontext
)
626
metapost
.
process
{
627
mpx
=
mpx
,
628
flusher
=
flusher
,
629
askedfig
=
askedfig
,
630
useplugins
=
incontext
,
631
incontext
=
incontext
,
632
data
=
data
,
633
}
634
end
635 636
function
metapost
.
process
(
specification
,
...
)
637
if
type
(
specification
)
~
=
"
table
"
then
638
oldschool
(
specification
,
...
)
639
else
640
startjob
(
specification
.
incontext
or
specification
.
useplugins
,
"
process
"
,
false
)
641
runmetapost
(
specification
)
642
stopjob
(
)
643
end
644
end
645 646
-- -- the new plugin handler -- --
647 648
local
sequencers
=
utilities
.
sequencers
649
local
appendgroup
=
sequencers
.
appendgroup
650
local
appendaction
=
sequencers
.
appendaction
651 652
local
resetteractions
=
sequencers
.
new
{
arguments
=
"
t
"
}
653
local
processoractions
=
sequencers
.
new
{
arguments
=
"
object,prescript,before,after
"
}
654 655
appendgroup
(
resetteractions
,
"
system
"
)
656
appendgroup
(
processoractions
,
"
system
"
)
657 658
-- later entries come first
659 660
local
scriptsplitter
=
Ct
(
Ct
(
661
C
(
(
1
-
S
(
"
=
"
)
)
^
1
)
*
S
(
"
=
"
)
^
1
*
C
(
(
1
-
S
(
"
\n\r
"
)
)
^
0
)
*
S
(
"
\n\r
"
)
^
0
662
)
^
0
)
663 664
local
function
splitprescript
(
script
)
665
local
hash
=
lpegmatch
(
scriptsplitter
,
script
)
666
for
i
=
#
hash
,
1
,
-1
do
667
local
h
=
hash
[
i
]
668
if
h
=
=
"
reset
"
then
669
for
k
,
v
in
next
,
hash
do
670
if
type
(
k
)
~
=
"
number
"
then
671
hash
[
k
]
=
nil
672
end
673
end
674
else
675
hash
[
h
[
1
]
]
=
h
[
2
]
676
end
677
end
678
if
trace_scripts
then
679
report_scripts
(
table
.
serialize
(
hash
,
"
prescript
"
)
)
680
end
681
return
hash
682
end
683 684
metapost
.
splitprescript
=
splitprescript
685 686
-- -- not used:
687
--
688
-- local function splitpostscript(script)
689
-- local hash = lpegmatch(scriptsplitter,script)
690
-- for i=1,#hash do
691
-- local h = hash[i]
692
-- hash[h[1]] = h[2]
693
-- end
694
-- if trace_scripts then
695
-- report_scripts(table.serialize(hash,"postscript"))
696
-- end
697
-- return hash
698
-- end
699 700
function
metapost
.
pluginactions
(
what
,
t
,
flushfigure
)
-- before/after object, depending on what
701
if
top
and
top
.
plugmode
then
-- hm, what about other features
702
for
i
=
1
,
#
what
do
703
local
wi
=
what
[
i
]
704
if
type
(
wi
)
=
=
"
function
"
then
705
-- assume injection
706
flushfigure
(
t
)
-- to be checked: too many 0 g 0 G
707
t
=
{
}
708
wi
(
)
709
else
710
t
[
#
t
+
1
]
=
wi
711
end
712
end
713
return
t
714
end
715
end
716 717
function
metapost
.
resetplugins
(
t
)
-- intialize plugins, before figure
718
if
top
and
top
.
plugmode
then
719
outercolormodel
=
colors
.
currentmodel
(
)
-- currently overloads the one set at the tex end
720
resetteractions
.
runner
(
t
)
721
end
722
end
723 724
function
metapost
.
processplugins
(
object
)
-- each object (second pass)
725
if
top
and
top
.
plugmode
then
726
local
prescript
=
object
.
prescript
-- specifications
727
if
prescript
and
#
prescript
>
0
then
728
local
before
=
{
}
729
local
after
=
{
}
730
local
options
=
splitprescript
(
prescript
)
or
{
}
731
processoractions
.
runner
(
object
,
options
,
before
,
after
)
732
return
#
before
>
0
and
before
,
#
after
>
0
and
after
,
options
733
else
734
local
c
=
object
.
color
735
if
c
and
#
c
>
0
then
736
local
b
,
a
=
colorconverter
(
c
)
737
return
{
b
}
,
{
a
}
,
{
}
738
end
739
end
740
end
741
end
742 743
-- helpers
744 745
local
basepoints
=
number
.
dimenfactors
[
"
bp
"
]
746 747
local
function
cm
(
object
)
748
local
op
=
object
.
path
749
if
op
then
750
local
first
=
op
[
1
]
751
local
second
=
op
[
2
]
752
local
fourth
=
op
[
4
]
753
if
fourth
then
754
local
tx
=
first
.
x_coord
755
local
ty
=
first
.
y_coord
756
local
sx
=
second
.
x_coord
-
tx
757
local
sy
=
fourth
.
y_coord
-
ty
758
local
rx
=
second
.
y_coord
-
ty
759
local
ry
=
fourth
.
x_coord
-
tx
760
if
sx
=
=
0
then
sx
=
0
.
00001
end
761
if
sy
=
=
0
then
sy
=
0
.
00001
end
762
return
sx
,
rx
,
ry
,
sy
,
tx
,
ty
763
end
764
end
765
return
1
,
0
,
0
,
1
,
0
,
0
-- weird case
766
end
767 768
metapost
.
cm
=
cm
769 770
-- color
771 772
local
function
cl_reset
(
t
)
773
t
[
#
t
+
1
]
=
metapost
.
colorinitializer
(
)
-- only color
774
end
775 776
-- text
777 778
local
tx_reset
,
tx_process
do
779 780
-- The dilemma is that we need to process the text in order to know the
781
-- dimensions but afterwards also need to apply color and such. So, we need
782
-- two passes, one immediately and one when we use it.
783 784
local
eol
=
S
(
"
\n\r
"
)
^
1
785
local
cleaner
=
Cs
(
(
P
(
"
@@
"
)
/
"
@
"
+
P
(
"
@
"
)
/
"
%%
"
+
P
(
1
)
)
^
0
)
786
local
splitter
=
Ct
(
787
(
(
788
P
(
"
s:
"
)
*
C
(
(
1
-
eol
)
^
1
)
789
+
P
(
"
n:
"
)
*
(
(
1
-
eol
)
^
1
/
tonumber
)
790
+
P
(
"
b:
"
)
*
(
(
1
-
eol
)
^
1
/
toboolean
)
791
)
*
eol
^
0
)
^
0
)
792 793
local
function
applyformat
(
s
)
794
local
t
=
lpegmatch
(
splitter
,
s
)
795
if
#
t
=
=
1
then
796
return
s
797
else
798
local
f
=
lpegmatch
(
cleaner
,
t
[
1
]
)
799
return
formatters
[
f
]
(
unpack
(
t
,
2
)
)
800
end
801
end
802 803
local
fmt
=
formatters
[
"
%s %s %s % t
"
]
804
----- pat = tsplitat(":")
805
local
pat
=
lpeg
.
tsplitter
(
"
:
"
,
tonumber
)
-- so that %F can do its work
806 807
local
f_gray_yes
=
formatters
[
"
s=%.3N,a=%i,t=%.3N
"
]
808
local
f_gray_nop
=
formatters
[
"
s=%.3N
"
]
809
local
f_rgb_yes
=
formatters
[
"
r=%.3N,g=%.3N,b=%.3N,a=%.3N,t=%.3N
"
]
810
local
f_rgb_nop
=
formatters
[
"
r=%.3N,g=%.3N,b=%.3N
"
]
811
local
f_cmyk_yes
=
formatters
[
"
c=%.3N,m=%.3N,y=%.3N,k=%.3N,a=%.3N,t=%.3N
"
]
812
local
f_cmyk_nop
=
formatters
[
"
c=%.3N,m=%.3N,y=%.3N,k=%.3N
"
]
813 814
local
ctx_MPLIBsetNtext
=
context
.
MPLIBsetNtextX
815
local
ctx_MPLIBsetCtext
=
context
.
MPLIBsetCtextX
816
local
ctx_MPLIBsettext
=
context
.
MPLIBsettextX
817 818
local
bp
=
number
.
dimenfactors
.
bp
819 820
local
mp_index
=
0
821
local
mp_target
=
0
822
local
mp_c
=
nil
823
local
mp_a
=
nil
824
local
mp_t
=
nil
825 826
local
function
processtext
(
)
827
local
mp_text
=
top
.
texstrings
[
mp_index
]
828
local
mp_regime
=
top
.
texregimes
[
mp_index
]
829
if
mp_regime
and
tonumber
(
mp_regime
)
>
=
0
then
830
mp_text
=
function
(
)
831
context
.
sprint
(
mp_regime
,
top
.
texstrings
[
mp_index
]
or
"
"
)
832
end
833
end
834
if
not
mp_text
then
835
report_textexts
(
"
missing text for index %a
"
,
mp_index
)
836
elseif
not
mp_c
then
837
ctx_MPLIBsetNtext
(
mp_target
,
mp_text
)
838
elseif
#
mp_c
=
=
1
then
839
if
mp_a
and
mp_t
then
840
ctx_MPLIBsetCtext
(
mp_target
,
f_gray_yes
(
mp_c
[
1
]
,
mp_a
,
mp_t
)
,
mp_text
)
841
else
842
ctx_MPLIBsetCtext
(
mp_target
,
f_gray_nop
(
mp_c
[
1
]
)
,
mp_text
)
843
end
844
elseif
#
mp_c
=
=
3
then
845
if
mp_a
and
mp_t
then
846
ctx_MPLIBsetCtext
(
mp_target
,
f_rgb_yes
(
mp_c
[
1
]
,
mp_c
[
2
]
,
mp_c
[
3
]
,
mp_a
,
mp_t
)
,
mp_text
)
847
else
848
ctx_MPLIBsetCtext
(
mp_target
,
f_rgb_nop
(
mp_c
[
1
]
,
mp_c
[
2
]
,
mp_c
[
3
]
)
,
mp_text
)
849
end
850
elseif
#
mp_c
=
=
4
then
851
if
mp_a
and
mp_t
then
852
ctx_MPLIBsetCtext
(
mp_target
,
f_cmyk_yes
(
mp_c
[
1
]
,
mp_c
[
2
]
,
mp_c
[
3
]
,
mp_c
[
4
]
,
mp_a
,
mp_t
)
,
mp_text
)
853
else
854
ctx_MPLIBsetCtext
(
mp_target
,
f_cmyk_nop
(
mp_c
[
1
]
,
mp_c
[
2
]
,
mp_c
[
3
]
,
mp_c
[
4
]
)
,
mp_text
)
855
end
856
else
857
-- can't happen
858
ctx_MPLIBsetNtext
(
mp_target
,
mp_text
)
859
end
860
end
861 862
local
madetext
=
nil
863 864
local
function
mf_some_text
(
index
,
str
,
regime
)
865
mp_target
=
index
866
mp_index
=
index
867
mp_c
=
nil
868
mp_a
=
nil
869
mp_t
=
nil
870
top
.
texstrings
[
mp_index
]
=
str
871
top
.
texregimes
[
mp_index
]
=
regime
or
-1
872
texrunlocal
(
"
mptexttoks
"
)
873
local
box
=
textakebox
(
"
mptextbox
"
)
874
top
.
textexts
[
mp_target
]
=
box
875
injecttriplet
(
bp
*
box
.
width
,
bp
*
box
.
height
,
bp
*
box
.
depth
)
876
madetext
=
nil
877
end
878 879
local
function
mf_made_text
(
index
)
880
mf_some_text
(
index
,
madetext
,
catcodes
.
numbers
.
ctxcatcodes
)
-- btex/etex ..
881
end
882 883
registerdirect
(
"
sometextext
"
,
function
(
)
mf_some_text
(
mpscannumeric
(
)
,
mpscanstring
(
)
,
mpscannumeric
(
)
)
end
)
884
registerdirect
(
"
madetextext
"
,
function
(
)
mf_made_text
(
mpscannumeric
(
)
)
end
)
885 886
-- a label can be anything, also something mp doesn't like in strings
887
-- so we return an index instead
888 889
function
metapost
.
processing
(
)
890
return
top
and
true
or
false
891
end
892 893
function
metapost
.
remaptext
(
replacement
)
894
if
top
then
895
local
mapstrings
=
top
.
mapstrings
896
local
mapindices
=
top
.
mapindices
897
local
label
=
replacement
.
label
898
local
index
=
0
899
if
label
then
900
local
found
=
mapstrings
[
label
]
901
if
found
then
902
setmetatableindex
(
found
,
replacement
)
903
index
=
found
.
index
904
else
905
index
=
#
mapindices
+
1
906
replacement
.
index
=
index
907
mapindices
[
index
]
=
replacement
908
mapstrings
[
label
]
=
replacement
909
end
910
end
911
return
index
912
else
913
return
0
914
end
915
end
916 917
function
metapost
.
remappedtext
(
what
)
918
return
top
and
(
top
.
mapstrings
[
what
]
or
top
.
mapindices
[
tonumber
(
what
)
]
)
919
end
920 921
function
mp
.
mf_map_move
(
index
)
922
mp
.
triplet
(
top
.
mapmoves
[
index
]
)
923
end
924 925
function
mp
.
mf_map_text
(
index
,
str
,
regime
)
926
local
map
=
top
.
mapindices
[
tonumber
(
str
)
]
927
if
type
(
map
)
=
=
"
table
"
then
928
local
text
=
map
.
text
929
local
overload
=
map
.
overload
930
local
offset
=
0
931
local
width
=
0
932
local
where
=
nil
933
--
934
mp_index
=
index
935
-- the image text
936
if
overload
then
937
top
.
texstrings
[
mp_index
]
=
map
.
template
or
map
.
label
or
"
error
"
938
top
.
texregimes
[
mp_index
]
=
regime
or
-1
939
texrunlocal
(
"
mptexttoks
"
)
940
local
box
=
textakebox
(
"
mptextbox
"
)
or
new_hlist
(
)
941
width
=
bp
*
box
.
width
942
where
=
overload
.
where
943
end
944
-- the real text
945
top
.
texstrings
[
mp_index
]
=
overload
and
overload
.
text
or
text
or
"
error
"
946
top
.
texregimes
[
mp_index
]
=
regime
or
-1
947
texrunlocal
(
"
mptexttoks
"
)
948
local
box
=
textakebox
(
"
mptextbox
"
)
or
new_hlist
(
)
949
local
twd
=
bp
*
box
.
width
950
local
tht
=
bp
*
box
.
height
951
local
tdp
=
bp
*
box
.
depth
952
-- the check
953
if
where
then
954
local
scale
=
1
-- / (map.scale or 1)
955
if
where
=
=
"
l
"
or
where
=
=
"
left
"
then
956
offset
=
scale
*
(
twd
-
width
)
957
elseif
where
=
=
"
m
"
or
where
=
=
"
middle
"
then
958
offset
=
scale
*
(
twd
-
width
)
/
2
959
end
960
end
961
-- the result
962
top
.
textexts
[
mp_index
]
=
box
963
top
.
mapmoves
[
mp_index
]
=
{
offset
,
map
.
dx
or
0
,
map
.
dy
or
0
}
964
--
965
mp
.
triplet
(
twd
,
tht
,
tdp
)
966
madetext
=
nil
967
return
968
else
969
map
=
type
(
map
)
=
=
"
string
"
and
map
or
str
970
return
mf_some_text
(
index
,
context
.
escape
(
map
)
or
map
)
971
end
972
end
973 974
-- This is a bit messy. In regular metapost it's a kind of immediate replacement
975
-- so embedded btex ... etex is not really working as one would expect. We now have
976
-- a mix: it's immediate when we are at the outer level (rawmadetext) and indirect
977
-- (with the danger of stuff that doesn't work well in strings) when we are for
978
-- instance in a macro definition (rawtextext (pass back string)) ... of course one
979
-- should use textext so this is just a catch. When not in lmtx it's never immediate.
980 981
local
reported
=
false
982
local
alwayswrap
=
false
-- CONTEXTLMTXMODE <= 1 -- was always nil due to typo
983 984
function
metapost
.
maketext
(
s
,
mode
)
985
if
not
reported
then
986
reported
=
true
987
report_metapost
(
"
use 'textext(.....)' instead of 'btex ..... etex'
"
)
988
end
989
if
mode
and
mode
=
=
1
then
990
if
trace_btexetex
then
991
report_metapost
(
"
ignoring verbatimtex: [[%s]]
"
,
s
)
992
end
993
elseif
alwayswrap
then
994
if
trace_btexetex
then
995
report_metapost
(
"
rewrapping btex ... etex [[%s]]
"
,
s
)
996
end
997
return
'
rawtextext("
'
.
.
gsub
(
s
,
'
"
'
,
'
"&ditto&"
'
)
.
.
'
")
'
-- nullpicture
998
elseif
metapost
.
currentmpxstatus
(
)
~
=
0
then
999
if
trace_btexetex
then
1000
report_metapost
(
"
rewrapping btex ... etex at the outer level [[%s]]
"
,
s
)
1001
end
1002
return
'
rawtextext("
'
.
.
gsub
(
s
,
'
"
'
,
'
"&ditto&"
'
)
.
.
'
")
'
-- nullpicture
1003
else
1004
if
trace_btexetex
then
1005
report_metapost
(
"
handling btex ... etex: [[%s]]
"
,
s
)
1006
end
1007
-- madetext = utilities.strings.collapse(s)
1008
madetext
=
s
1009
return
"
rawmadetext
"
-- is assuming immediate processing
1010
end
1011
end
1012 1013
function
mp
.
mf_formatted_text
(
index
,
fmt
,
...
)
1014
local
t
=
{
}
1015
for
i
=
1
,
select
(
"
#
"
,
...
)
do
1016
local
ti
=
select
(
i
,
...
)
1017
if
type
(
ti
)
~
=
"
table
"
then
1018
t
[
#
t
+
1
]
=
ti
1019
end
1020
end
1021
local
f
=
lpegmatch
(
cleaner
,
fmt
)
1022
local
s
=
formatters
[
f
]
(
unpack
(
t
)
)
or
"
"
1023
mf_some_text
(
index
,
s
)
1024
end
1025 1026
interfaces
.
implement
{
1027
name
=
"
mptexttoks
"
,
1028
actions
=
processtext
,
1029
}
1030 1031
tx_reset
=
function
(
)
1032
if
top
then
1033
top
.
texhash
=
{
}
1034
top
.
texlast
=
0
1035
end
1036
end
1037 1038
local
fasttrack
=
false
-- we loose colors done with withcolor when true
1039 1040
directives
.
register
(
"
metapost.text.fasttrack
"
,
function
(
v
)
fasttrack
=
v
end
)
1041 1042
tx_process
=
function
(
object
,
prescript
,
before
,
after
)
1043
local
data
=
top
.
texdata
[
metapost
.
properties
.
number
]
-- the current figure number, messy
1044
local
index
=
tonumber
(
prescript
.
tx_index
)
1045
if
index
then
1046
if
trace_textexts
then
1047
report_textexts
(
"
using index %a
"
,
index
)
1048
end
1049
--
1050
mp_c
=
object
.
color
1051
if
#
mp_c
=
=
0
then
1052
local
txc
=
prescript
.
tx_color
1053
if
txc
then
1054
mp_c
=
lpegmatch
(
pat
,
txc
)
1055
end
1056
end
1057
mp_a
=
tonumber
(
prescript
.
tr_alternative
)
1058
mp_t
=
tonumber
(
prescript
.
tr_transparency
)
1059
--
1060
mp_index
=
index
1061
mp_target
=
top
.
texlast
-
1
1062
top
.
texlast
=
mp_target
1063
--
1064
local
mp_text
=
top
.
texstrings
[
mp_index
]
1065
local
mp_hash
=
prescript
.
tx_cache
1066
local
box
1067
local
donebox
=
fasttrack
and
top
.
textexts
[
mp_index
]
1068
if
mp_hash
=
=
"
no
"
then
1069
if
donebox
then
1070
box
=
copylist
(
donebox
)
1071
else
1072
texrunlocal
(
"
mptexttoks
"
)
1073
box
=
textakebox
(
"
mptextbox
"
)
1074
end
1075
else
1076
local
cache
=
data
.
texhash
1077
if
mp_hash
then
1078
mp_hash
=
tonumber
(
mp_hash
)
1079
end
1080
if
mp_hash
then
1081
local
extradata
=
top
.
extradata
1082
if
extradata
then
1083
cache
=
extradata
.
globalcache
1084
if
not
cache
then
1085
cache
=
{
}
1086
extradata
.
globalcache
=
cache
1087
end
1088
if
trace_runs
then
1089
if
cache
[
mp_hash
]
then
1090
report_textexts
(
"
reusing global entry %i
"
,
mp_hash
)
1091
else
1092
report_textexts
(
"
storing global entry %i
"
,
mp_hash
)
1093
end
1094
end
1095
else
1096
mp_hash
=
nil
1097
end
1098
end
1099
if
not
mp_hash
then
1100
mp_hash
=
fmt
(
mp_text
,
mp_a
or
"
-
"
,
mp_t
or
"
-
"
,
mp_c
or
"
-
"
)
1101
end
1102
box
=
cache
[
mp_hash
]
1103
if
box
then
1104
box
=
copylist
(
box
)
1105
else
1106
if
donebox
then
1107
box
=
copylist
(
donebox
)
1108
else
1109
texrunlocal
(
"
mptexttoks
"
)
1110
box
=
textakebox
(
"
mptextbox
"
)
1111
end
1112
cache
[
mp_hash
]
=
box
1113
end
1114
end
1115
top
.
textexts
[
mp_target
]
=
box
1116
--
1117
if
box
then
1118
-- we need to freeze the variables outside the function
1119
local
sx
,
rx
,
ry
,
sy
,
tx
,
ty
=
cm
(
object
)
1120
local
target
=
mp_target
1121
before
[
#
before
+
1
]
=
function
(
)
1122
context
.
MPLIBgettextscaledcm
(
target
,
1123
f_f
(
sx
)
,
-- bah ... %s no longer checks
1124
f_f
(
rx
)
,
-- bah ... %s no longer checks
1125
f_f
(
ry
)
,
-- bah ... %s no longer checks
1126
f_f
(
sy
)
,
-- bah ... %s no longer checks
1127
f_f
(
tx
)
,
-- bah ... %s no longer checks
1128
f_f
(
ty
)
,
-- bah ... %s no longer checks
1129
sxsy
(
box
.
width
,
box
.
height
,
box
.
depth
)
)
1130
end
1131
else
1132
before
[
#
before
+
1
]
=
function
(
)
1133
report_textexts
(
"
unknown %s
"
,
index
)
1134
end
1135
end
1136
if
not
trace_textexts
then
1137
object
.
path
=
false
-- else: keep it
1138
end
1139
object
.
color
=
false
1140
object
.
grouped
=
true
1141
object
.
istext
=
true
1142
end
1143
end
1144 1145
end
1146 1147
-- we could probably redo normal textexts in the next way but as it's rather optimized
1148
-- we keep away from that (at least for now)
1149 1150
local
function
bx_process
(
object
,
prescript
,
before
,
after
)
1151
local
bx_category
=
prescript
.
bx_category
1152
local
bx_name
=
prescript
.
bx_name
1153
if
bx_category
and
bx_name
then
1154
if
trace_textexts
then
1155
report_textexts
(
"
category %a, name %a
"
,
bx_category
,
bx_name
)
1156
end
1157
local
sx
,
rx
,
ry
,
sy
,
tx
,
ty
=
cm
(
object
)
-- needs to be frozen outside the function
1158
local
wd
,
ht
,
dp
=
nodes
.
boxes
.
dimensions
(
bx_category
,
bx_name
)
1159
before
[
#
before
+
1
]
=
function
(
)
1160
context
.
MPLIBgetboxscaledcm
(
bx_category
,
bx_name
,
1161
f_f
(
sx
)
,
-- bah ... %s no longer checks
1162
f_f
(
rx
)
,
-- bah ... %s no longer checks
1163
f_f
(
ry
)
,
-- bah ... %s no longer checks
1164
f_f
(
sy
)
,
-- bah ... %s no longer checks
1165
f_f
(
tx
)
,
-- bah ... %s no longer checks
1166
f_f
(
ty
)
,
-- bah ... %s no longer checks
1167
sxsy
(
wd
,
ht
,
dp
)
)
1168
end
1169
if
not
trace_textexts
then
1170
object
.
path
=
false
-- else: keep it
1171
end
1172
object
.
color
=
false
1173
object
.
grouped
=
true
1174
object
.
istext
=
true
1175
end
1176
end
1177 1178
-- graphics (we use the given index because pictures can be reused)
1179 1180 1181
local
gt_reset
,
gt_process
do
1182 1183
local
graphics
=
{
}
1184 1185 1186
local
mp_index
=
0
1187
local
mp_str
=
"
"
1188 1189
function
mp
.
mf_graphic_text
(
index
,
str
)
1190
if
not
graphics
[
index
]
then
1191
mp_index
=
index
1192
mp_str
=
str
1193
texrunlocal
(
"
mpgraphictexttoks
"
)
1194
end
1195
end
1196 1197
interfaces
.
implement
{
1198
name
=
"
mpgraphictexttoks
"
,
1199
actions
=
function
(
)
1200
context
.
MPLIBgraphictext
(
mp_index
,
mp_str
)
1201
end
,
1202
}
1203 1204
end
1205 1206
-- shades
1207 1208
local
function
sh_process
(
object
,
prescript
,
before
,
after
)
1209
local
sh_type
=
prescript
.
sh_type
1210
if
sh_type
then
1211
nofshades
=
nofshades
+
1
1212
local
domain
=
lpegmatch
(
domainsplitter
,
prescript
.
sh_domain
or
"
0 1
"
)
1213
local
centera
=
lpegmatch
(
centersplitter
,
prescript
.
sh_center_a
or
"
0 0
"
)
1214
local
centerb
=
lpegmatch
(
centersplitter
,
prescript
.
sh_center_b
or
"
0 0
"
)
1215
local
transform
=
toboolean
(
prescript
.
sh_transform
or
"
yes
"
,
true
)
1216
-- compensation for scaling
1217
local
sx
=
1
1218
local
sy
=
1
1219
local
sr
=
1
1220
local
dx
=
0
1221
local
dy
=
0
1222
if
transform
then
1223
local
first
=
lpegmatch
(
coordinatesplitter
,
prescript
.
sh_first
or
"
0 0
"
)
1224
local
setx
=
lpegmatch
(
coordinatesplitter
,
prescript
.
sh_set_x
or
"
0 0
"
)
1225
local
sety
=
lpegmatch
(
coordinatesplitter
,
prescript
.
sh_set_y
or
"
0 0
"
)
1226 1227
local
x
=
setx
[
1
]
-- point that has different x
1228
local
y
=
sety
[
1
]
-- point that has different y
1229 1230
if
x
=
=
0
or
y
=
=
0
then
1231
-- forget about it
1232
else
1233
local
path
=
object
.
path
1234
local
path1x
=
path
[
1
]
.
x_coord
1235
local
path1y
=
path
[
1
]
.
y_coord
1236
local
path2x
=
path
[
x
]
.
x_coord
1237
local
path2y
=
path
[
y
]
.
y_coord
1238 1239
local
dxa
=
path2x
-
path1x
1240
local
dya
=
path2y
-
path1y
1241
local
dxb
=
setx
[
2
]
-
first
[
1
]
1242
local
dyb
=
sety
[
2
]
-
first
[
2
]
1243 1244
if
dxa
=
=
0
or
dya
=
=
0
or
dxb
=
=
0
or
dyb
=
=
0
then
1245
-- forget about it
1246
else
1247
sx
=
dxa
/
dxb
;
if
sx
<
0
then
sx
=
-
sx
end
-- yes or no
1248
sy
=
dya
/
dyb
;
if
sy
<
0
then
sy
=
-
sy
end
-- yes or no
1249 1250
sr
=
sqrt
(
sx
^
2
+
sy
^
2
)
1251 1252
dx
=
path1x
-
sx
*
first
[
1
]
1253
dy
=
path1y
-
sy
*
first
[
2
]
1254
end
1255
end
1256
end
1257
-- local transformation = prescript.sh_transformation
1258
-- if transformation then
1259
-- print("todo: " .. transformation)
1260
-- end
1261
local
steps
=
tonumber
(
prescript
.
sh_step
)
or
1
1262
local
sh_color_a
=
prescript
.
sh_color_a_1
or
prescript
.
sh_color_a
or
"
1
"
1263
local
sh_color_b
=
prescript
.
sh_color_b_1
or
prescript
.
sh_color_b
or
"
1
"
-- sh_color_b_<sh_steps>
1264
local
ca
,
cb
,
colorspace
,
name
,
model
,
separation
,
fractions
1265
if
prescript
.
sh_color
=
=
"
into
"
and
prescript
.
sp_name
then
1266
-- some spotcolor
1267
local
value_a
,
components_a
,
fractions_a
,
name_a
1268
local
value_b
,
components_b
,
fractions_b
,
name_b
1269
for
i
=
1
,
#
prescript
do
1270
-- { "sh_color_a", "1" },
1271
-- { "sh_color", "into" },
1272
-- { "sh_radius_b", "0" },
1273
-- { "sh_radius_a", "141.73225" },
1274
-- { "sh_center_b", "425.19676 141.73225" },
1275
-- { "sh_center_a", "425.19676 0" },
1276
-- { "sh_factor", "1" },
1277
local
tag
=
prescript
[
i
]
[
1
]
1278
if
not
name_a
and
tag
=
=
"
sh_color_a
"
then
1279
value_a
=
prescript
[
i
-5
]
[
2
]
1280
components_a
=
prescript
[
i
-4
]
[
2
]
1281
fractions_a
=
prescript
[
i
-3
]
[
2
]
1282
name_a
=
prescript
[
i
-2
]
[
2
]
1283
elseif
not
name_b
and
tag
=
=
"
sh_color_b
"
then
1284
value_b
=
prescript
[
i
-5
]
[
2
]
1285
components_b
=
prescript
[
i
-4
]
[
2
]
1286
fractions_b
=
prescript
[
i
-3
]
[
2
]
1287
name_b
=
prescript
[
i
-2
]
[
2
]
1288
end
1289
if
name_a
and
name_b
then
1290
break
1291
end
1292
end
1293
ca
,
cb
,
separation
,
name
=
checkandconvertspot
(
1294
name_a
,
fractions_a
,
components_a
,
value_a
,
1295
name_b
,
fractions_b
,
components_b
,
value_b
1296
)
1297
else
1298
local
colora
=
lpegmatch
(
colorsplitter
,
sh_color_a
)
1299
local
colorb
=
lpegmatch
(
colorsplitter
,
sh_color_b
)
1300
ca
,
cb
,
colorspace
,
name
,
model
=
checkandconvert
(
colora
,
colorb
)
1301
-- test:
1302
if
steps
>
1
then
1303
ca
=
{
ca
}
1304
cb
=
{
cb
}
1305
fractions
=
{
tonumber
(
prescript
[
formatters
[
"
sh_fraction_%i
"
]
(
1
)
]
)
or
0
}
1306
for
i
=
2
,
steps
do
1307
local
colora
=
lpegmatch
(
colorsplitter
,
prescript
[
formatters
[
"
sh_color_a_%i
"
]
(
i
)
]
)
1308
local
colorb
=
lpegmatch
(
colorsplitter
,
prescript
[
formatters
[
"
sh_color_b_%i
"
]
(
i
)
]
)
1309
ca
[
i
]
,
cb
[
i
]
=
checkandconvert
(
colora
,
colorb
,
model
)
1310
fractions
[
i
]
=
tonumber
(
prescript
[
formatters
[
"
sh_fraction_%i
"
]
(
i
)
]
)
or
(
i
/
steps
)
1311
end
1312
end
1313
end
1314
if
not
ca
or
not
cb
then
1315
ca
,
cb
,
colorspace
,
name
=
checkandconvert
(
)
1316
steps
=
1
1317
end
1318
if
sh_type
=
=
"
linear
"
then
1319
local
coordinates
=
{
dx
+
sx
*
centera
[
1
]
,
dy
+
sy
*
centera
[
2
]
,
dx
+
sx
*
centerb
[
1
]
,
dy
+
sy
*
centerb
[
2
]
}
1320
lpdf
.
linearshade
(
name
,
domain
,
ca
,
cb
,
1
,
colorspace
,
coordinates
,
separation
,
steps
>
1
and
steps
,
fractions
)
-- backend specific (will be renamed)
1321
elseif
sh_type
=
=
"
circular
"
then
1322
local
factor
=
tonumber
(
prescript
.
sh_factor
)
or
1
1323
local
radiusa
=
factor
*
tonumber
(
prescript
.
sh_radius_a
)
1324
local
radiusb
=
factor
*
tonumber
(
prescript
.
sh_radius_b
)
1325
local
coordinates
=
{
dx
+
sx
*
centera
[
1
]
,
dy
+
sy
*
centera
[
2
]
,
sr
*
radiusa
,
dx
+
sx
*
centerb
[
1
]
,
dy
+
sy
*
centerb
[
2
]
,
sr
*
radiusb
}
1326
lpdf
.
circularshade
(
name
,
domain
,
ca
,
cb
,
1
,
colorspace
,
coordinates
,
separation
,
steps
>
1
and
steps
,
fractions
)
-- backend specific (will be renamed)
1327
else
1328
-- fatal error
1329
end
1330
before
[
#
before
+
1
]
=
"
q /Pattern cs
"
1331
after
[
#
after
+
1
]
=
formatters
[
"
W n /%s sh Q
"
]
(
name
)
1332
-- false, not nil, else mt triggered
1333
object
.
colored
=
false
-- hm, not object.color ?
1334
object
.
type
=
false
1335
object
.
grouped
=
true
1336
end
1337
end
1338 1339
-- bitmaps
1340 1341
local
function
bm_process
(
object
,
prescript
,
before
,
after
)
1342
local
bm_xresolution
=
prescript
.
bm_xresolution
1343
if
bm_xresolution
then
1344
before
[
#
before
+
1
]
=
f_cm_b
(
cm
(
object
)
)
1345
before
[
#
before
+
1
]
=
function
(
)
1346
figures
.
bitmapimage
{
1347
xresolution
=
tonumber
(
bm_xresolution
)
,
1348
yresolution
=
tonumber
(
prescript
.
bm_yresolution
)
,
1349
width
=
1
/
basepoints
,
1350
height
=
1
/
basepoints
,
1351
data
=
object
.
postscript
1352
}
1353
end
1354
before
[
#
before
+
1
]
=
s_cm_e
1355
object
.
path
=
false
1356
object
.
color
=
false
1357
object
.
grouped
=
true
1358
end
1359
end
1360 1361
-- positions
1362 1363
local
function
ps_process
(
object
,
prescript
,
before
,
after
)
1364
local
ps_label
=
prescript
.
ps_label
1365
if
ps_label
then
1366
local
op
=
object
.
path
1367
local
first
=
op
[
1
]
1368
local
third
=
op
[
3
]
1369
local
x
=
first
.
x_coord
1370
local
y
=
first
.
y_coord
1371
local
w
=
third
.
x_coord
-
x
1372
local
h
=
third
.
y_coord
-
y
1373
local
properties
=
metapost
.
properties
1374
x
=
x
-
properties
.
llx
1375
y
=
properties
.
ury
-
y
1376
before
[
#
before
+
1
]
=
function
(
)
1377
context
.
MPLIBpositionwhd
(
ps_label
,
x
,
y
,
w
,
h
)
1378
end
1379
object
.
path
=
false
1380
end
1381
end
1382 1383
-- figures
1384 1385
-- local sx, rx, ry, sy, tx, ty = cm(object)
1386
-- sxsy(box.width,box.height,box.depth))
1387 1388
function
mp
.
mf_external_figure
(
filename
)
1389
local
f
=
figures
.
getinfo
(
filename
)
1390
local
w
=
0
1391
local
h
=
0
1392
if
f
then
1393
local
u
=
f
.
used
1394
if
u
and
u
.
fullname
then
1395
w
=
u
.
width
or
0
1396
h
=
u
.
height
or
0
1397
end
1398
else
1399
report_metapost
(
"
external figure %a not found
"
,
filename
)
1400
end
1401
mp
.
triplet
(
w
/
65536
,
h
/
65536
,
0
)
1402
end
1403 1404
local
function
fg_process
(
object
,
prescript
,
before
,
after
)
1405
local
fg_name
=
prescript
.
fg_name
1406
if
fg_name
then
1407
before
[
#
before
+
1
]
=
f_cm_b
(
cm
(
object
)
)
-- beware: does not use the cm stack
1408
before
[
#
before
+
1
]
=
function
(
)
1409
context
.
MPLIBfigure
(
fg_name
,
prescript
.
fg_mask
or
"
"
)
1410
end
1411
before
[
#
before
+
1
]
=
s_cm_e
1412
object
.
path
=
false
1413
object
.
grouped
=
true
1414
end
1415
end
1416 1417
-- color and transparency
1418 1419
local
value
=
Cs
(
(
1420
(
Carg
(
1
)
*
C
(
(
1
-
P
(
"
,
"
)
)
^
1
)
)
/
function
(
a
,
b
)
return
f_f3
(
a
*
tonumber
(
b
)
)
end
1421
+
P
(
"
,
"
)
)
^
1
1422
)
1423 1424
-- should be codeinjections
1425 1426
local
t_list
=
attributes
.
list
[
attributes
.
private
(
'
transparency
'
)
]
1427
local
c_list
=
attributes
.
list
[
attributes
.
private
(
'
color
'
)
]
1428 1429
local
remappers
=
{
1430
[
1
]
=
formatters
[
"
s=%s
"
]
,
1431
[
3
]
=
formatters
[
"
r=%s,g=%s,b=%s
"
]
,
1432
[
4
]
=
formatters
[
"
c=%s,m=%s,y=%s,k=%s
"
]
,
1433
}
1434 1435
local
processlast
=
0
1436
local
processhash
=
setmetatableindex
(
function
(
t
,
k
)
1437
processlast
=
processlast
+
1
1438
local
v
=
formatters
[
"
mp_%s
"
]
(
processlast
)
1439
defineprocesscolor
(
v
,
k
,
true
,
true
)
1440
t
[
k
]
=
v
1441
return
v
1442
end
)
1443 1444
local
function
checked_transparency
(
alternative
,
transparency
,
before
,
after
)
1445
alternative
=
tonumber
(
alternative
)
or
1
1446
transparency
=
tonumber
(
transparency
)
or
0
1447
before
[
#
before
+
1
]
=
formatters
[
"
/Tr%s gs
"
]
(
registertransparency
(
nil
,
alternative
,
transparency
,
true
)
)
1448
after
[
#
after
+
1
]
=
"
/Tr0 gs
"
-- outertransparency
1449
end
1450 1451
local
function
tr_process
(
object
,
prescript
,
before
,
after
)
1452
-- before can be shortcut to t
1453
local
tr_alternative
=
prescript
.
tr_alternative
1454
if
tr_alternative
then
1455
checked_transparency
(
tr_alternative
,
prescript
.
tr_transparency
,
before
,
after
)
1456
end
1457
local
cs
=
object
.
color
1458
if
cs
and
#
cs
>
0
then
1459
local
c_b
,
c_a
1460
local
sp_type
=
prescript
.
sp_type
1461
if
not
sp_type
then
1462
c_b
,
c_a
=
colorconverter
(
cs
)
1463
else
1464
local
sp_name
=
prescript
.
sp_name
or
"
black
"
1465
if
sp_type
=
=
"
spot
"
then
1466
local
sp_value
=
prescript
.
sp_value
or
"
1
"
1467
local
components
=
split
(
sp_value
,
"
:
"
)
1468
local
specification
=
remappers
[
#
components
]
1469
if
specification
then
1470
specification
=
specification
(
unpack
(
components
)
)
1471
else
1472
specification
=
"
s=0
"
1473
end
1474
local
sp_spec
=
processhash
[
specification
]
1475
definespotcolor
(
sp_name
,
sp_spec
,
"
p=1
"
,
true
)
1476
sp_type
=
"
named
"
1477
elseif
sp_type
=
=
"
multitone
"
then
-- (fractions of a multitone) don't work well in mupdf
1478
local
sp_value
=
prescript
.
sp_value
or
"
1
"
1479
local
sp_specs
=
{
}
1480
local
sp_list
=
split
(
sp_value
,
"
"
)
1481
for
i
=
1
,
#
sp_list
do
1482
local
sp_value
=
sp_list
[
i
]
1483
local
components
=
split
(
sp_value
,
"
:
"
)
1484
local
specification
=
remappers
[
#
components
]
1485
if
specification
then
1486
specification
=
specification
(
unpack
(
components
)
)
1487
else
1488
specification
=
"
s=0
"
1489
end
1490
local
sp_spec
=
processhash
[
specification
]
1491
sp_specs
[
i
]
=
formatters
[
"
%s=1
"
]
(
sp_spec
)
1492
end
1493
sp_specs
=
concat
(
sp_specs
,
"
,
"
)
1494
definemultitonecolor
(
sp_name
,
sp_specs
,
"
"
,
"
"
)
1495
sp_type
=
"
named
"
1496
elseif
sp_type
=
=
"
named
"
then
1497
cs
=
{
1
}
-- factor 1
1498
end
1499
if
sp_type
=
=
"
named
"
then
1500
-- we might move this to another namespace .. also, named can be a spotcolor
1501
-- so we need to check for that too ... also we need to resolve indirect
1502
-- colors so we might need the second pass for this (draw dots with \MPcolor)
1503
if
not
tr_alternative
then
1504
-- todo: sp_name is not yet registered at this time
1505
local
t
=
t_list
[
sp_name
]
-- string or attribute
1506
local
v
=
t
and
transparencyvalue
(
t
)
1507
if
v
then
1508
checked_transparency
(
v
[
1
]
,
v
[
2
]
,
before
,
after
)
1509
end
1510
end
1511
local
c
=
c_list
[
sp_name
]
-- string or attribute
1512
local
v
=
c
and
colorvalue
(
c
)
1513
if
v
then
1514
-- all=1 gray=2 rgb=3 cmyk=4
1515
local
colorspace
=
v
[
1
]
1516
local
factor
=
cs
[
1
]
1517
if
colorspace
=
=
2
then
1518
local
s
=
factor
*
v
[
2
]
1519
c_b
,
c_a
=
checked_color_pair
(
f_gray
,
s
,
s
)
1520
elseif
colorspace
=
=
3
then
1521
local
r
=
factor
*
v
[
3
]
1522
local
g
=
factor
*
v
[
4
]
1523
local
b
=
factor
*
v
[
5
]
1524
c_b
,
c_a
=
checked_color_pair
(
f_rgb
,
r
,
g
,
b
,
r
,
g
,
b
)
1525
elseif
colorspace
=
=
4
or
colorspace
=
=
1
then
1526
local
c
=
factor
*
v
[
6
]
1527
local
m
=
factor
*
v
[
7
]
1528
local
y
=
factor
*
v
[
8
]
1529
local
k
=
factor
*
v
[
9
]
1530
c_b
,
c_a
=
checked_color_pair
(
f_cmyk
,
c
,
m
,
y
,
k
,
c
,
m
,
y
,
k
)
1531
elseif
colorspace
=
=
5
then
1532
-- not all viewers show the fractions ok
1533
local
name
=
v
[
10
]
1534
local
value
=
split
(
v
[
13
]
,
"
,
"
)
1535
if
factor
~
=
1
then
1536
for
i
=
1
,
#
value
do
1537
value
[
i
]
=
f_scn
(
factor
*
(
tonumber
(
value
[
i
]
)
or
1
)
)
1538
end
1539
end
1540
value
=
concat
(
value
,
"
"
)
1541
c_b
,
c_a
=
checked_color_pair
(
f_spot
,
name
,
name
,
value
,
value
)
1542
else
1543
local
s
=
factor
*
v
[
2
]
1544
c_b
,
c_a
=
checked_color_pair
(
f_gray
,
s
,
s
)
1545
end
1546
end
1547
end
1548
end
1549
if
c_a
and
c_b
then
1550
before
[
#
before
+
1
]
=
c_b
1551
after
[
#
after
+
1
]
=
c_a
1552
end
1553
end
1554
end
1555 1556
-- layers (nasty: we need to keep the 'grouping' right
1557 1558
local
function
la_process
(
object
,
prescript
,
before
,
after
)
1559
local
la_name
=
prescript
.
la_name
1560
if
la_name
then
1561
before
[
#
before
+
1
]
=
backends
.
codeinjections
.
startlayer
(
la_name
)
1562
insert
(
after
,
1
,
backends
.
codeinjections
.
stoplayer
(
)
)
1563
end
1564
end
1565 1566
-- groups
1567 1568
local
function
getcorners
(
path
)
1569
-- if #path == 1 then
1570
-- return 0, 0, 0, 0
1571
-- else
1572
local
p1
=
path
[
1
]
1573
local
p2
=
path
[
2
]
1574
local
p3
=
path
[
3
]
1575
local
p4
=
path
[
4
]
1576
return
1577
min
(
p1
.
x_coord
,
p2
.
x_coord
,
p3
.
x_coord
,
p4
.
x_coord
)
,
1578
min
(
p1
.
y_coord
,
p2
.
y_coord
,
p3
.
y_coord
,
p4
.
y_coord
)
,
1579
max
(
p1
.
x_coord
,
p2
.
x_coord
,
p3
.
x_coord
,
p4
.
x_coord
)
,
1580
max
(
p1
.
y_coord
,
p2
.
y_coord
,
p3
.
y_coord
,
p4
.
y_coord
)
1581
-- end
1582
end
1583 1584
local
function
gr_process
(
object
,
prescript
,
before
,
after
)
1585
local
gr_state
=
prescript
.
gr_state
1586
if
not
gr_state
then
1587
return
1588
elseif
gr_state
=
=
"
start
"
then
1589
local
gr_type
=
utilities
.
parsers
.
settings_to_set
(
prescript
.
gr_type
)
1590
local
llx
,
lly
,
urx
,
ury
=
getcorners
(
object
.
path
)
1591
before
[
#
before
+
1
]
=
function
(
)
1592
context
.
MPLIBstartgroup
(
1593
gr_type
.
isolated
and
1
or
0
,
1594
gr_type
.
knockout
and
1
or
0
,
1595
llx
,
lly
,
urx
,
ury
1596
)
1597
end
1598
elseif
gr_state
=
=
"
stop
"
then
1599
after
[
#
after
+
1
]
=
function
(
)
1600
context
.
MPLIBstopgroup
(
)
1601
end
1602
end
1603
object
.
path
=
false
1604
object
.
color
=
false
1605
object
.
grouped
=
true
1606
end
1607 1608
-- patterns
1609 1610
local
pattern_index
=
0
1611 1612
local
function
pt_process
(
object
,
prescript
,
before
,
after
)
1613
local
pt_state
=
prescript
.
pt_state
1614
if
not
pt_state
then
1615
return
1616
else
1617
local
pt_action
=
prescript
.
pt_action
1618
if
pt_state
=
=
"
start
"
then
1619
local
float
=
toboolean
(
prescript
.
pt_float
)
and
1
or
0
1620
local
llx
,
lly
,
urx
,
ury
=
getcorners
(
object
.
path
)
1621
if
abs
(
llx
)
<
0
.
0001
then
llx
=
0
end
1622
if
abs
(
lly
)
<
0
.
0001
then
lly
=
0
end
1623
before
[
#
before
+
1
]
=
function
(
)
1624
if
pt_action
=
=
"
set
"
then
1625
pattern_index
=
pattern_index
+
1
1626
context
.
MPLIBstartsetpattern
(
pattern_index
,
llx
,
lly
,
urx
,
ury
,
float
)
1627
else
1628
context
.
MPLIBstartgetpattern
(
pattern_index
,
llx
,
lly
,
urx
,
ury
,
float
)
1629
end
1630
end
1631
elseif
pt_state
=
=
"
stop
"
then
1632
after
[
#
after
+
1
]
=
function
(
)
1633
if
pt_action
=
=
"
set
"
then
1634
context
.
MPLIBstopsetpattern
(
)
1635
else
1636
context
.
MPLIBstopgetpattern
(
)
1637
end
1638
end
1639
end
1640
end
1641
object
.
path
=
false
1642
object
.
color
=
false
1643
object
.
grouped
=
true
1644
end
1645 1646
-- outlines
1647 1648
local
ot_reset
,
ot_process
do
1649 1650
local
outlinetexts
=
{
}
-- also in top data
1651 1652
ot_reset
=
function
(
)
1653
outlinetexts
=
{
}
1654
end
1655 1656
local
mp_index
=
0
1657
local
mp_kind
=
"
"
1658
local
mp_str
=
"
"
1659 1660
function
mp
.
mf_outline_text
(
index
,
str
,
kind
)
1661
if
not
outlinetexts
[
index
]
then
1662
mp_index
=
index
1663
mp_kind
=
kind
1664
mp_str
=
str
1665
texrunlocal
(
"
mpoutlinetoks
"
)
1666
end
1667
end
1668 1669
interfaces
.
implement
{
1670
name
=
"
mpoutlinetoks
"
,
1671
actions
=
function
(
)
1672
context
.
MPLIBoutlinetext
(
mp_index
,
mp_kind
,
mp_str
)
1673
end
,
1674
}
1675 1676
implement
{
1677
name
=
"
MPLIBconvertoutlinetext
"
,
1678
arguments
=
{
"
integer
"
,
"
string
"
,
"
integer
"
}
,
1679
actions
=
function
(
index
,
kind
,
box
)
1680
local
boxtomp
=
fonts
.
metapost
.
boxtomp
1681
if
boxtomp
then
1682
outlinetexts
[
index
]
=
boxtomp
(
box
,
kind
)
1683
else
1684
outlinetexts
[
index
]
=
"
"
1685
end
1686
end
1687
}
1688 1689
function
mp
.
mf_get_outline_text
(
index
)
-- maybe we need a more private namespace
1690
mp
.
print
(
outlinetexts
[
index
]
or
"
draw origin;
"
)
1691
end
1692 1693
end
1694 1695
-- mf_object=<string>
1696 1697
local
p1
=
P
(
"
mf_object=
"
)
1698
local
p2
=
lpeg
.
patterns
.
eol
*
p1
1699
local
pattern
=
(
1
-
p2
)
^
0
*
p2
+
p1
1700 1701
function
metapost
.
isobject
(
str
)
1702
return
pattern
and
str
~
=
"
"
and
lpegmatch
(
p
,
str
)
and
true
or
false
1703
end
1704 1705
local
function
installplugin
(
specification
)
1706
local
reset
=
specification
.
reset
1707
local
process
=
specification
.
process
1708
local
object
=
specification
.
object
1709
if
reset
then
1710
appendaction
(
resetteractions
,
"
system
"
,
reset
)
1711
end
1712
if
process
then
1713
appendaction
(
processoractions
,
"
system
"
,
process
)
1714
end
1715
end
1716 1717
metapost
.
installplugin
=
installplugin
1718 1719
-- definitions
1720 1721
installplugin
{
name
=
"
outline
"
,
reset
=
ot_reset
,
process
=
ot_process
}
1722
installplugin
{
name
=
"
color
"
,
reset
=
cl_reset
,
process
=
cl_process
}
1723
installplugin
{
name
=
"
text
"
,
reset
=
tx_reset
,
process
=
tx_process
}
1724
installplugin
{
name
=
"
group
"
,
reset
=
gr_reset
,
process
=
gr_process
}
1725
installplugin
{
name
=
"
pattern
"
,
reset
=
pt_reset
,
process
=
pt_process
}
1726
installplugin
{
name
=
"
graphictext
"
,
reset
=
gt_reset
,
process
=
gt_process
}
1727
installplugin
{
name
=
"
shade
"
,
reset
=
sh_reset
,
process
=
sh_process
}
1728
installplugin
{
name
=
"
bitmap
"
,
reset
=
bm_reset
,
process
=
bm_process
}
1729
installplugin
{
name
=
"
box
"
,
reset
=
bx_reset
,
process
=
bx_process
}
1730
installplugin
{
name
=
"
position
"
,
reset
=
ps_reset
,
process
=
ps_process
}
1731
installplugin
{
name
=
"
figure
"
,
reset
=
fg_reset
,
process
=
fg_process
}
1732
installplugin
{
name
=
"
layer
"
,
reset
=
la_reset
,
process
=
la_process
}
1733
installplugin
{
name
=
"
transparency
"
,
reset
=
tr_reset
,
process
=
tr_process
}
1734