mlib-pdf.lua /size: 32 Kb    last modification: 2021-10-28 13:50
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
mlib-pdf
'
]
=
{
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
gsub
=
string
.
gsub
10
local
concat
,
insert
,
remove
=
table
.
concat
,
table
.
insert
,
table
.
remove
11
local
abs
,
sqrt
,
round
=
math
.
abs
,
math
.
sqrt
,
math
.
round
12
local
setmetatable
,
rawset
,
tostring
,
tonumber
,
type
=
setmetatable
,
rawset
,
tostring
,
tonumber
,
type
13
local
P
,
S
,
C
,
Ct
,
Cc
,
Cg
,
Cf
,
Carg
=
lpeg
.
P
,
lpeg
.
S
,
lpeg
.
C
,
lpeg
.
Ct
,
lpeg
.
Cc
,
lpeg
.
Cg
,
lpeg
.
Cf
,
lpeg
.
Carg
14
local
lpegmatch
=
lpeg
.
match
15
local
formatters
=
string
.
formatters
16 17
local
report_metapost
=
logs
.
reporter
(
"
metapost
"
)
18 19
local
trace_variables
=
false
trackers
.
register
(
"
metapost.variables
"
,
function
(
v
)
trace_variables
=
v
end
)
20 21
local
mplib
=
mplib
22
local
context
=
context
23 24
local
allocate
=
utilities
.
storage
.
allocate
25 26
local
pen_info
=
mplib
.
pen_info
27
local
getfields
=
mplib
.
getfields
or
mplib
.
fields
-- todo: in lmtx get them once and then use gettype
28 29
local
save_table
=
false
30
local
force_stroke
=
false
31 32
metapost
=
metapost
or
{
}
33
local
metapost
=
metapost
34 35
metapost
.
flushers
=
metapost
.
flushers
or
{
}
36
local
pdfflusher
=
{
}
37
metapost
.
flushers
.
pdf
=
pdfflusher
38 39
metapost
.
n
=
0
40 41
local
experiment
=
true
-- uses context(node) that already does delayed nodes
42
local
savedliterals
=
nil
-- needs checking
43
local
mpsliteral
=
nodes
.
pool
.
originliteral
44 45
local
f_f
=
formatters
[
"
%.6N
"
]
46
local
f_m
=
formatters
[
"
%.6N %.6N m
"
]
47
local
f_c
=
formatters
[
"
%.6N %.6N %.6N %.6N %.6N %.6N c
"
]
48
local
f_l
=
formatters
[
"
%.6N %.6N l
"
]
49
local
f_cm
=
formatters
[
"
%.6N %.6N %.6N %.6N %.6N %.6N cm
"
]
50
local
f_M
=
formatters
[
"
%.6N M
"
]
51
local
f_j
=
formatters
[
"
%i j
"
]
52
local
f_J
=
formatters
[
"
%i J
"
]
53
local
f_d
=
formatters
[
"
[%s] %.6N d
"
]
54
local
f_w
=
formatters
[
"
%.6N w
"
]
55 56
directives
.
register
(
"
metapost.savetable
"
,
function
(
v
)
57
if
type
(
v
)
=
=
"
string
"
then
58
save_table
=
file
.
addsuffix
(
v
,
"
mpl
"
)
59
elseif
v
then
60
save_table
=
file
.
addsuffix
(
environment
.
jobname
.
.
"
-graphic
"
,
"
mpl
"
)
61
else
62
save_table
=
false
63
end
64
end
)
65 66
trackers
.
register
(
"
metapost.forcestroke
"
,
function
(
v
)
67
force_stroke
=
v
68
end
)
69 70
-- Because in MKiV we always have two passes, we save the objects. When an extra
71
-- mp run is done (due to for instance texts identifier in the parse pass), we
72
-- get a new result table and the stored objects are forgotten. Otherwise they
73
-- are reused.
74 75
local
function
getobjects
(
result
,
figure
,
index
)
76
return
figure
:
objects
(
)
77
end
78 79
function
metapost
.
convert
(
specification
,
result
)
80
local
flusher
=
specification
.
flusher
81
local
askedfig
=
specification
.
askedfig
82
if
save_table
then
83
table
.
save
(
save_table
,
metapost
.
totable
(
result
,
1
)
)
-- direct
84
end
85
metapost
.
flush
(
specification
,
result
)
86
return
true
-- done
87
end
88 89
function
metapost
.
flushliteral
(
d
)
90
if
savedliterals
then
91
context
(
mpsliteral
(
savedliterals
[
d
]
)
)
92
else
93
report_metapost
(
"
problem flushing literal %a
"
,
d
)
94
end
95
end
96 97
function
metapost
.
flushreset
(
)
-- will become obsolete and internal
98
savedliterals
=
nil
99
end
100 101
function
pdfflusher
.
comment
(
message
)
102
if
message
then
103
message
=
formatters
[
"
%% mps graphic %s: %s
"
]
(
metapost
.
n
,
message
)
104
if
experiment
then
105
context
(
mpsliteral
(
message
)
)
106
elseif
savedliterals
then
107
local
last
=
#
savedliterals
+
1
108
savedliterals
[
last
]
=
message
109
context
.
MPLIBtoPDF
(
last
)
110
else
111
savedliterals
=
{
message
}
112
context
.
MPLIBtoPDF
(
1
)
113
end
114
end
115
end
116 117
function
pdfflusher
.
startfigure
(
n
,
llx
,
lly
,
urx
,
ury
,
message
)
118
savedliterals
=
nil
119
metapost
.
n
=
metapost
.
n
+
1
120
context
.
startMPLIBtoPDF
(
f_f
(
llx
)
,
f_f
(
lly
)
,
f_f
(
urx
)
,
f_f
(
ury
)
)
121
if
message
then
pdfflusher
.
comment
(
message
)
end
122
end
123 124
function
pdfflusher
.
stopfigure
(
message
)
125
if
message
then
pdfflusher
.
comment
(
message
)
end
126
context
.
stopMPLIBtoPDF
(
)
127
context
.
MPLIBflushreset
(
)
-- maybe just at the beginning
128
end
129 130
function
pdfflusher
.
flushfigure
(
pdfliterals
)
-- table
131
if
#
pdfliterals
>
0
then
132
pdfliterals
=
concat
(
pdfliterals
,
"
\n
"
)
133
if
experiment
then
134
context
(
mpsliteral
(
pdfliterals
)
)
135
else
136
if
savedliterals
then
137
local
last
=
#
savedliterals
+
1
138
savedliterals
[
last
]
=
pdfliterals
139
context
.
MPLIBtoPDF
(
last
)
140
else
141
savedliterals
=
{
pdfliterals
}
142
context
.
MPLIBtoPDF
(
1
)
143
end
144
end
145
end
146
end
147 148
function
pdfflusher
.
textfigure
(
font
,
size
,
text
,
width
,
height
,
depth
)
-- we could save the factor
149
text
=
gsub
(
text
,
"
.
"
,
"
\\hbox{%1}
"
)
-- kerning happens in metapost (i have to check if this is true for mplib)
150
context
.
MPtextext
(
font
,
size
,
text
,
0
,
-
number
.
dimenfactors
.
bp
*
depth
)
151
end
152 153
local
bend_tolerance
=
131
/
65536
154 155
local
rx
,
sx
,
sy
,
ry
,
tx
,
ty
,
divider
=
1
,
0
,
0
,
1
,
0
,
0
,
1
156 157
local
function
pen_characteristics
(
object
)
158
local
t
=
pen_info
(
object
)
159
rx
,
ry
,
sx
,
sy
,
tx
,
ty
=
t
.
rx
,
t
.
ry
,
t
.
sx
,
t
.
sy
,
t
.
tx
,
t
.
ty
160
divider
=
sx
*
sy
-
rx
*
ry
161
return
not
(
sx
=
=
1
and
rx
=
=
0
and
ry
=
=
0
and
sy
=
=
1
and
tx
=
=
0
and
ty
=
=
0
)
,
t
.
width
162
end
163 164
local
function
mpconcat
(
px
,
py
)
-- no tx, ty here / we can move this one inline if needed
165
return
(
sy
*
px
-
ry
*
py
)
/
divider
,
(
sx
*
py
-
rx
*
px
)
/
divider
166
end
167 168
local
function
curved
(
ith
,
pth
)
169
local
d
=
pth
.
left_x
-
ith
.
right_x
170
if
abs
(
ith
.
right_x
-
ith
.
x_coord
-
d
)
<
=
bend_tolerance
and
abs
(
pth
.
x_coord
-
pth
.
left_x
-
d
)
<
=
bend_tolerance
then
171
d
=
pth
.
left_y
-
ith
.
right_y
172
if
abs
(
ith
.
right_y
-
ith
.
y_coord
-
d
)
<
=
bend_tolerance
and
abs
(
pth
.
y_coord
-
pth
.
left_y
-
d
)
<
=
bend_tolerance
then
173
return
false
174
end
175
end
176
return
true
177
end
178 179
local
function
flushnormalpath
(
path
,
t
,
open
)
180
local
pth
,
ith
,
nt
181
local
length
=
#
path
182
if
t
then
183
nt
=
#
t
184
else
185
t
=
{
}
186
nt
=
0
187
end
188
for
i
=
1
,
length
do
189
nt
=
nt
+
1
190
pth
=
path
[
i
]
191
if
not
ith
then
192
t
[
nt
]
=
f_m
(
pth
.
x_coord
,
pth
.
y_coord
)
193
elseif
curved
(
ith
,
pth
)
then
194
t
[
nt
]
=
f_c
(
ith
.
right_x
,
ith
.
right_y
,
pth
.
left_x
,
pth
.
left_y
,
pth
.
x_coord
,
pth
.
y_coord
)
195
else
196
t
[
nt
]
=
f_l
(
pth
.
x_coord
,
pth
.
y_coord
)
197
end
198
ith
=
pth
199
end
200
if
not
open
then
201
nt
=
nt
+
1
202
local
one
=
path
[
1
]
203
if
curved
(
pth
,
one
)
then
204
t
[
nt
]
=
f_c
(
pth
.
right_x
,
pth
.
right_y
,
one
.
left_x
,
one
.
left_y
,
one
.
x_coord
,
one
.
y_coord
)
205
else
206
t
[
nt
]
=
f_l
(
one
.
x_coord
,
one
.
y_coord
)
207
end
208
elseif
length
=
=
1
then
209
-- special case .. draw point
210
local
one
=
path
[
1
]
211
nt
=
nt
+
1
212
t
[
nt
]
=
f_l
(
one
.
x_coord
,
one
.
y_coord
)
213
end
214
return
t
215
end
216 217
local
function
flushconcatpath
(
path
,
t
,
open
,
transform
)
218
local
pth
,
ith
,
nt
219
local
length
=
#
path
220
if
t
then
221
nt
=
#
t
222
else
223
t
=
{
}
224
nt
=
0
225
end
226
if
transform
then
227
nt
=
nt
+
1
228
t
[
nt
]
=
f_cm
(
sx
,
rx
,
ry
,
sy
,
tx
,
ty
)
229
end
230
for
i
=
1
,
length
do
231
nt
=
nt
+
1
232
pth
=
path
[
i
]
233
if
not
ith
then
234
t
[
nt
]
=
f_m
(
mpconcat
(
pth
.
x_coord
,
pth
.
y_coord
)
)
235
elseif
curved
(
ith
,
pth
)
then
236
local
a
,
b
=
mpconcat
(
ith
.
right_x
,
ith
.
right_y
)
237
local
c
,
d
=
mpconcat
(
pth
.
left_x
,
pth
.
left_y
)
238
t
[
nt
]
=
f_c
(
a
,
b
,
c
,
d
,
mpconcat
(
pth
.
x_coord
,
pth
.
y_coord
)
)
239
else
240
t
[
nt
]
=
f_l
(
mpconcat
(
pth
.
x_coord
,
pth
.
y_coord
)
)
241
end
242
ith
=
pth
243
end
244
if
not
open
then
245
nt
=
nt
+
1
246
local
one
=
path
[
1
]
247
if
curved
(
pth
,
one
)
then
248
local
a
,
b
=
mpconcat
(
pth
.
right_x
,
pth
.
right_y
)
249
local
c
,
d
=
mpconcat
(
one
.
left_x
,
one
.
left_y
)
250
t
[
nt
]
=
f_c
(
a
,
b
,
c
,
d
,
mpconcat
(
one
.
x_coord
,
one
.
y_coord
)
)
251
else
252
t
[
nt
]
=
f_l
(
mpconcat
(
one
.
x_coord
,
one
.
y_coord
)
)
253
end
254
elseif
length
=
=
1
then
255
-- special case .. draw point
256
nt
=
nt
+
1
257
local
one
=
path
[
1
]
258
t
[
nt
]
=
f_l
(
mpconcat
(
one
.
x_coord
,
one
.
y_coord
)
)
259
end
260
return
t
261
end
262 263
local
function
toboundingbox
(
path
)
264
local
size
=
#
path
265
if
size
=
=
4
then
266
local
pth
=
path
[
1
]
267
local
x
=
pth
.
x_coord
268
local
y
=
pth
.
y_coord
269
local
llx
,
lly
,
urx
,
ury
=
x
,
y
,
x
,
y
270
for
i
=
2
,
size
do
271
pth
=
path
[
i
]
272
x
=
pth
.
x_coord
273
y
=
pth
.
y_coord
274
if
x
<
llx
then
275
llx
=
x
276
elseif
x
>
urx
then
277
urx
=
x
278
end
279
if
y
<
lly
then
280
lly
=
y
281
elseif
y
>
ury
then
282
ury
=
y
283
end
284
end
285
return
{
llx
,
lly
,
urx
,
ury
}
286
else
287
return
{
0
,
0
,
0
,
0
}
288
end
289
end
290 291
metapost
.
flushnormalpath
=
flushnormalpath
292 293
-- The flusher is pdf based, if another backend is used, we need to overload the
294
-- flusher; this is beta code, the organization will change (already upgraded in
295
-- sync with mplib)
296
--
297
-- We can avoid the before table but I like symmetry. There is of course a small
298
-- performance penalty, but so is passing extra arguments (result, flusher, after)
299
-- and returning stuff.
300
--
301
-- This variable stuff will change in lmtx.
302 303
local
ignore
=
function
(
)
end
304 305
local
space
=
P
(
"
"
)
306
local
equal
=
P
(
"
=
"
)
307
local
key
=
C
(
(
1
-
equal
)
^
1
)
*
equal
308
local
newline
=
S
(
"
\n\r
"
)
^
1
309
local
number
=
(
(
(
1
-
space
-
newline
)
^
1
)
/
tonumber
)
*
(
space
^
0
)
310 311
local
p_number
=
number
312
local
p_string
=
C
(
(
1
-
newline
)
^
0
)
313
local
p_boolean
=
P
(
"
false
"
)
*
Cc
(
false
)
+
P
(
"
true
"
)
*
Cc
(
true
)
314
local
p_set
=
Ct
(
number
^
1
)
315
local
p_path
=
Ct
(
Ct
(
number
*
number
^
-5
)
^
1
)
316 317
local
variable
=
318
P
(
"
1:
"
)
*
p_number
319
+
P
(
"
2:
"
)
*
p_string
320
+
P
(
"
3:
"
)
*
p_boolean
321
+
S
(
"
4568
"
)
*
P
(
"
:
"
)
*
p_set
322
+
P
(
"
7:
"
)
*
p_path
323 324
local
pattern_tab
=
Cf
(
Carg
(
1
)
*
(
Cg
(
variable
*
newline
^
0
)
^
0
)
,
rawset
)
325 326
local
variable
=
327
P
(
"
1:
"
)
*
p_number
328
+
P
(
"
2:
"
)
*
p_string
329
+
P
(
"
3:
"
)
*
p_boolean
330
+
S
(
"
4568
"
)
*
P
(
"
:
"
)
*
number
^
1
331
+
P
(
"
7:
"
)
*
(
number
*
number
^
-5
)
^
1
332 333
local
pattern_lst
=
(
variable
*
newline
^
0
)
^
0
334 335
metapost
.
variables
=
{
}
-- currently across instances
336
metapost
.
properties
=
{
}
-- to be stacked
337 338
function
metapost
.
untagvariable
(
str
,
variables
)
-- will be redone
339
if
variables
=
=
false
then
340
return
lpegmatch
(
pattern_lst
,
str
)
341
else
342
return
lpegmatch
(
pattern_tab
,
str
,
1
,
variables
or
{
}
)
343
end
344
end
345 346
-- function metapost.processspecial(str)
347
-- lpegmatch(pattern_key,object.prescript,1,variables)
348
-- end
349 350
function
metapost
.
processspecial
(
str
)
351
local
code
=
loadstring
(
str
)
352
if
code
then
353
if
trace_variables
then
354
report_metapost
(
"
executing special code: %s
"
,
str
)
355
end
356
code
(
)
357
else
358
report_metapost
(
"
invalid special code: %s
"
,
str
)
359
end
360
end
361 362
local
stack
=
{
}
363 364
local
function
pushproperties
(
figure
)
365
-- maybe there will be getters in lmtx
366
local
boundingbox
=
figure
:
boundingbox
(
)
367
local
slot
=
figure
:
charcode
(
)
or
0
368
local
properties
=
{
369
llx
=
boundingbox
[
1
]
,
370
lly
=
boundingbox
[
2
]
,
371
urx
=
boundingbox
[
3
]
,
372
ury
=
boundingbox
[
4
]
,
373
slot
=
slot
,
374
width
=
figure
:
width
(
)
,
375
height
=
figure
:
height
(
)
,
376
depth
=
figure
:
depth
(
)
,
377
italic
=
figure
:
italcorr
(
)
,
-- figure:italic() in lmtx
378
number
=
slot
,
379
}
380
insert
(
stack
,
properties
)
381
metapost
.
properties
=
properties
382
return
properties
383
end
384 385
local
function
popproperties
(
)
386
metapost
.
properties
=
remove
(
stack
)
387
end
388 389
local
function
nocomment
(
)
end
390 391
metapost
.
comment
=
nocomment
392 393
function
metapost
.
flush
(
specification
,
result
)
394
if
result
then
395
local
flusher
=
specification
.
flusher
396
local
askedfig
=
specification
.
askedfig
397
local
incontext
=
specification
.
incontext
398
local
figures
=
result
.
fig
399
if
figures
then
400
flusher
=
flusher
or
pdfflusher
401
local
resetplugins
=
metapost
.
resetplugins
or
ignore
-- before figure
402
local
processplugins
=
metapost
.
processplugins
or
ignore
-- each object
403
local
synchronizeplugins
=
metapost
.
synchronizeplugins
or
ignore
404
local
pluginactions
=
metapost
.
pluginactions
or
ignore
-- before / after
405
local
startfigure
=
flusher
.
startfigure
406
local
stopfigure
=
flusher
.
stopfigure
407
local
flushfigure
=
flusher
.
flushfigure
408
local
textfigure
=
flusher
.
textfigure
409
local
processspecial
=
flusher
.
processspecial
or
metapost
.
processspecial
410
metapost
.
comment
=
flusher
.
comment
or
nocomment
411
for
index
=
1
,
#
figures
do
412
local
figure
=
figures
[
index
]
413
local
properties
=
pushproperties
(
figure
)
414
if
askedfig
=
=
"
direct
"
or
askedfig
=
=
"
all
"
or
askedfig
=
=
properties
.
number
then
415
local
objects
=
getobjects
(
result
,
figure
,
index
)
416
local
result
=
{
}
417
local
miterlimit
=
-1
418
local
linecap
=
-1
419
local
linejoin
=
-1
420
local
dashed
=
false
421
local
linewidth
=
false
422
local
llx
=
properties
.
llx
423
local
lly
=
properties
.
lly
424
local
urx
=
properties
.
urx
425
local
ury
=
properties
.
ury
426
if
urx
<
llx
then
427
-- invalid
428
startfigure
(
properties
.
number
,
0
,
0
,
0
,
0
,
"
invalid
"
,
figure
)
429
stopfigure
(
)
430
else
431 432
-- we need to be indirect if we want the one-pass solution
433 434
local
groupstack
=
{
}
435 436
local
function
processfigure
(
)
437
result
[
#
result
+
1
]
=
"
q
"
438
if
objects
then
439
-- resetplugins(result) -- we should move the colorinitializer here
440
local
savedpath
=
nil
441
local
savedhtap
=
nil
442
for
o
=
1
,
#
objects
do
443
local
object
=
objects
[
o
]
444
local
objecttype
=
object
.
type
445
if
objecttype
=
=
"
text
"
then
446
result
[
#
result
+
1
]
=
"
q
"
447
local
ot
=
object
.
transform
-- 3,4,5,6,1,2
448
result
[
#
result
+
1
]
=
f_cm
(
ot
[
3
]
,
ot
[
4
]
,
ot
[
5
]
,
ot
[
6
]
,
ot
[
1
]
,
ot
[
2
]
)
449
flushfigure
(
result
)
-- flush accumulated literals
450
result
=
{
}
451
textfigure
(
object
.
font
,
object
.
dsize
,
object
.
text
,
object
.
width
,
object
.
height
,
object
.
depth
)
452
result
[
#
result
+
1
]
=
"
Q
"
453
elseif
objecttype
=
=
"
special
"
then
454
if
processspecial
then
455
processspecial
(
object
.
prescript
)
456
end
457
elseif
objecttype
=
=
"
start_clip
"
then
458
local
evenodd
=
not
object
.
istext
and
object
.
postscript
=
=
"
evenodd
"
459
result
[
#
result
+
1
]
=
"
q
"
460
flushnormalpath
(
object
.
path
,
result
,
false
)
461
result
[
#
result
+
1
]
=
evenodd
and
"
W* n
"
or
"
W n
"
462
elseif
objecttype
=
=
"
stop_clip
"
then
463
result
[
#
result
+
1
]
=
"
Q
"
464
miterlimit
,
linecap
,
linejoin
,
dashed
,
linewidth
=
-1
,
-1
,
-1
,
"
"
,
false
465
elseif
objecttype
=
=
"
start_bounds
"
or
objecttype
=
=
"
stop_bounds
"
then
466
-- skip
467
elseif
objecttype
=
=
"
start_group
"
then
468
if
lpdf
.
flushgroup
then
469
local
before
,
after
=
processplugins
(
object
)
470
if
before
then
471
result
[
#
result
+
1
]
=
"
q
"
472
result
=
pluginactions
(
before
,
result
,
flushfigure
)
473
insert
(
groupstack
,
{
474
after
=
after
,
475
result
=
result
,
476
bbox
=
toboundingbox
(
object
.
path
)
,
477
}
)
478
result
=
{
}
479
miterlimit
,
linecap
,
linejoin
,
dashed
,
linewidth
=
-1
,
-1
,
-1
,
"
"
,
false
480
else
481
insert
(
groupstack
,
false
)
482
end
483
else
484
insert
(
groupstack
,
false
)
485
end
486
elseif
objecttype
=
=
"
stop_group
"
then
487
local
data
=
remove
(
groupstack
)
488
if
data
then
489
local
reference
=
lpdf
.
flushgroup
(
concat
(
result
,
"
\r
"
)
,
data
.
bbox
)
490
result
=
data
.
result
491
result
[
#
result
+
1
]
=
reference
492
result
=
pluginactions
(
data
.
after
,
result
,
flushfigure
)
493
result
[
#
result
+
1
]
=
"
Q
"
494
miterlimit
,
linecap
,
linejoin
,
dashed
,
linewidth
=
-1
,
-1
,
-1
,
"
"
,
false
495
end
496
else
497
-- we use an indirect table as we want to overload
498
-- entries but this is not possible in userdata
499
--
500
-- can be optimized if no path
501
--
502
local
original
=
object
503
local
object
=
{
}
504
setmetatable
(
object
,
{
505
__index
=
original
506
}
)
507
local
before
,
508
after
=
processplugins
(
object
)
509
local
evenodd
=
false
510
local
collect
=
false
511
local
both
=
false
512
local
flush
=
false
513
local
postscript
=
object
.
postscript
514
if
not
object
.
istext
then
515
if
postscript
=
=
"
evenodd
"
then
516
evenodd
=
true
517
elseif
postscript
=
=
"
collect
"
then
518
collect
=
true
519
elseif
postscript
=
=
"
flush
"
then
520
flush
=
true
521
elseif
postscript
=
=
"
both
"
then
522
both
=
true
523
elseif
postscript
=
=
"
eoboth
"
then
524
evenodd
=
true
525
both
=
true
526
end
527
end
528
--
529
if
flush
and
not
savedpath
then
530
-- forget about it
531
elseif
collect
then
532
if
not
savedpath
then
533
savedpath
=
{
object
.
path
or
false
}
534
savedhtap
=
{
object
.
htap
or
false
}
535
else
536
savedpath
[
#
savedpath
+
1
]
=
object
.
path
or
false
537
savedhtap
[
#
savedhtap
+
1
]
=
object
.
htap
or
false
538
end
539
else
540
local
objecttype
=
object
.
type
-- can have changed
541
if
before
then
542
result
=
pluginactions
(
before
,
result
,
flushfigure
)
543
end
544
local
ml
=
object
.
miterlimit
545
if
ml
and
ml
~
=
miterlimit
then
546
miterlimit
=
ml
547
result
[
#
result
+
1
]
=
f_M
(
ml
)
548
end
549
local
lj
=
object
.
linejoin
550
if
lj
and
lj
~
=
linejoin
then
551
linejoin
=
lj
552
result
[
#
result
+
1
]
=
f_j
(
lj
)
553
end
554
local
lc
=
object
.
linecap
555
if
lc
and
lc
~
=
linecap
then
556
linecap
=
lc
557
result
[
#
result
+
1
]
=
f_J
(
lc
)
558
end
559
if
both
then
560
if
dashed
~
=
false
then
-- was just dashed test
561
result
[
#
result
+
1
]
=
"
[] 0 d
"
562
dashed
=
false
563
end
564
else
565
local
dl
=
object
.
dash
566
if
dl
then
567
local
d
=
f_d
(
concat
(
dl
.
dashes
or
{
}
,
"
"
)
,
dl
.
offset
)
568
if
d
~
=
dashed
then
569
dashed
=
d
570
result
[
#
result
+
1
]
=
d
571
end
572
elseif
dashed
~
=
false
then
-- was just dashed test
573
result
[
#
result
+
1
]
=
"
[] 0 d
"
574
dashed
=
false
575
end
576
end
577
local
path
=
object
.
path
-- newpath
578
local
transformed
=
false
579
local
penwidth
=
1
580
local
open
=
path
and
path
[
1
]
.
left_type
and
path
[
#
path
]
.
right_type
-- at this moment only "end_point"
581
local
pen
=
object
.
pen
582
if
pen
then
583
if
pen
.
type
=
=
"
elliptical
"
then
584
transformed
,
penwidth
=
pen_characteristics
(
original
)
-- boolean, value
585
if
penwidth
~
=
linewidth
then
586
result
[
#
result
+
1
]
=
f_w
(
penwidth
)
587
linewidth
=
penwidth
588
end
589
if
objecttype
=
=
"
fill
"
then
590
objecttype
=
"
both
"
591
end
592
else
-- calculated by mplib itself
593
objecttype
=
"
fill
"
594
end
595
end
596
if
transformed
then
597
result
[
#
result
+
1
]
=
"
q
"
598
end
599
if
path
then
600
if
savedpath
then
601
for
i
=
1
,
#
savedpath
do
602
local
path
=
savedpath
[
i
]
603
if
transformed
then
604
flushconcatpath
(
path
,
result
,
open
,
i
=
=
1
)
605
else
606
flushnormalpath
(
path
,
result
,
open
)
607
end
608
end
609
savedpath
=
nil
610
end
611
if
flush
then
612
-- ignore this path
613
elseif
transformed
then
614
flushconcatpath
(
path
,
result
,
open
,
true
)
615
else
616
flushnormalpath
(
path
,
result
,
open
)
617
end
618
if
force_stroke
then
619
result
[
#
result
+
1
]
=
open
and
"
S
"
or
"
h S
"
620
elseif
objecttype
=
=
"
fill
"
then
621
result
[
#
result
+
1
]
=
evenodd
and
"
h f*
"
or
"
h f
"
-- f* = eo
622
elseif
objecttype
=
=
"
outline
"
then
623
if
both
then
624
result
[
#
result
+
1
]
=
evenodd
and
"
h B*
"
or
"
h B
"
-- B* = eo
625
else
626
result
[
#
result
+
1
]
=
open
and
"
S
"
or
"
h S
"
627
end
628
elseif
objecttype
=
=
"
both
"
then
629
result
[
#
result
+
1
]
=
evenodd
and
"
h B*
"
or
"
h B
"
-- B* = eo -- b includes closepath
630
end
631
end
632
if
transformed
then
633
result
[
#
result
+
1
]
=
"
Q
"
634
end
635
local
path
=
object
.
htap
636
if
path
then
637
if
transformed
then
638
result
[
#
result
+
1
]
=
"
q
"
639
end
640
if
savedhtap
then
641
for
i
=
1
,
#
savedhtap
do
642
local
path
=
savedhtap
[
i
]
643
if
transformed
then
644
flushconcatpath
(
path
,
result
,
open
,
i
=
=
1
)
645
else
646
flushnormalpath
(
path
,
result
,
open
)
647
end
648
end
649
savedhtap
=
nil
650
evenodd
=
true
651
end
652
if
transformed
then
653
flushconcatpath
(
path
,
result
,
open
,
true
)
654
else
655
flushnormalpath
(
path
,
result
,
open
)
656
end
657
if
force_stroke
then
658
result
[
#
result
+
1
]
=
open
and
"
S
"
or
"
h S
"
659
elseif
objecttype
=
=
"
fill
"
then
660
result
[
#
result
+
1
]
=
evenodd
and
"
h f*
"
or
"
h f
"
-- f* = eo
661
elseif
objecttype
=
=
"
outline
"
then
662
result
[
#
result
+
1
]
=
open
and
"
S
"
or
"
h S
"
663
elseif
objecttype
=
=
"
both
"
then
664
result
[
#
result
+
1
]
=
evenodd
and
"
h B*
"
or
"
h B
"
-- B* = eo -- b includes closepath
665
end
666
if
transformed
then
667
result
[
#
result
+
1
]
=
"
Q
"
668
end
669
end
670
if
after
then
671
result
=
pluginactions
(
after
,
result
,
flushfigure
)
672
end
673
end
674
if
object
.
grouped
then
675
-- can be qQ'd so changes can end up in groups
676
miterlimit
,
linecap
,
linejoin
,
dashed
,
linewidth
=
-1
,
-1
,
-1
,
"
"
,
false
677
end
678
end
679
end
680
end
681
result
[
#
result
+
1
]
=
"
Q
"
682
flushfigure
(
result
)
683
end
684
startfigure
(
properties
.
number
,
llx
,
lly
,
urx
,
ury
,
"
begin
"
,
figure
)
685
if
incontext
then
686
context
(
function
(
)
processfigure
(
)
end
)
687
else
688
processfigure
(
)
689
end
690
stopfigure
(
"
end
"
)
691 692
end
693
if
askedfig
~
=
"
all
"
then
694
break
695
end
696
end
697
popproperties
(
)
698
end
699
metapost
.
comment
=
nocomment
700
resetplugins
(
result
)
-- we should move the colorinitializer here
701
end
702
end
703
end
704 705
-- tracing:
706 707
do
708 709
local
result
=
{
}
710 711
local
flusher
=
{
712
startfigure
=
function
(
)
713
result
=
{
}
714
context
.
startnointerference
(
)
715
end
,
716
flushfigure
=
function
(
literals
)
717
local
n
=
#
result
718
for
i
=
1
,
#
literals
do
719
result
[
n
+
i
]
=
literals
[
i
]
720
end
721
end
,
722
stopfigure
=
function
(
)
723
context
.
stopnointerference
(
)
724
end
725
}
726 727
local
specification
=
{
728
flusher
=
flusher
,
729
-- incontext = true,
730
}
731 732
function
metapost
.
pdfliterals
(
result
)
733
metapost
.
flush
(
specification
,
result
)
734
return
result
735
end
736 737
end
738 739
function
metapost
.
totable
(
result
,
askedfig
)
740
local
askedfig
=
askedfig
or
1
741
local
figure
=
result
and
result
.
fig
and
result
.
fig
[
1
]
742
if
figure
then
743
local
results
=
{
}
744
local
objects
=
getobjects
(
result
,
figure
,
askedfig
)
745
for
o
=
1
,
#
objects
do
746
local
object
=
objects
[
o
]
747
local
result
=
{
}
748
local
fields
=
getfields
(
object
)
-- hm, is this the whole list, if so, we can get it once
749
for
f
=
1
,
#
fields
do
750
local
field
=
fields
[
f
]
751
result
[
field
]
=
object
[
field
]
752
end
753
results
[
o
]
=
result
754
end
755
local
boundingbox
=
figure
:
boundingbox
(
)
756
return
{
757
boundingbox
=
{
758
llx
=
boundingbox
[
1
]
,
759
lly
=
boundingbox
[
2
]
,
760
urx
=
boundingbox
[
3
]
,
761
ury
=
boundingbox
[
4
]
,
762
}
,
763
objects
=
results
764
}
765
else
766
return
nil
767
end
768
end
769