meta-pdh.lua /size: 20 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
meta-pdf
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to meta-pdf.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
if
true
then
10
return
-- or os.exit()
11
end
12 13
-- This file contains the history of the converter. We keep it around as it
14
-- relates to the development of luatex.
15 16
-- This is the third version. Version 1 converted to Lua code,
17
-- version 2 gsubbed the file into TeX code, and version 3 uses
18
-- the new lpeg functionality and streams the result into TeX.
19 20
-- We will move old stuff to edu.
21 22
--~ old lpeg 0.4 lpeg 0.5
23
--~ 100 times test graphic 2.45 (T:1.07) 0.72 (T:0.24) 0.580 (0.560 no table) -- 0.54 optimized for one space (T:0.19)
24
--~ 100 times big graphic 10.44 4.30/3.35 nogb 2.914 (2.050 no table) -- 1.99 optimized for one space (T:0.85)
25
--~ 500 times test graphic T:1.29 T:1.16 (T:1.10 no table) -- T:1.10
26 27
-- only needed for mp output on disk
28 29
local
concat
,
format
,
find
,
gsub
,
gmatch
=
table
.
concat
,
string
.
format
,
string
.
find
,
string
.
gsub
,
string
.
gmatch
30
local
tostring
,
tonumber
,
select
=
tostring
,
tonumber
,
select
31
local
lpegmatch
=
lpeg
.
match
32 33
metapost
=
metapost
or
{
}
34
local
metapost
=
metapost
35
local
context
=
context
36 37
metapost
.
mptopdf
=
metapost
.
mptopdf
or
{
}
38
local
mptopdf
=
metapost
.
mptopdf
39 40
mptopdf
.
parsers
=
{
}
41
mptopdf
.
parser
=
'
none
'
42
mptopdf
.
nofconverted
=
0
43 44
function
mptopdf
.
reset
(
)
45
mptopdf
.
data
=
"
"
46
mptopdf
.
path
=
{
}
47
mptopdf
.
stack
=
{
}
48
mptopdf
.
texts
=
{
}
49
mptopdf
.
version
=
0
50
mptopdf
.
shortcuts
=
false
51
mptopdf
.
resetpath
(
)
52
end
53 54
function
mptopdf
.
resetpath
(
)
55
mptopdf
.
stack
.
close
=
false
56
mptopdf
.
stack
.
path
=
{
}
57
mptopdf
.
stack
.
concat
=
nil
58
mptopdf
.
stack
.
special
=
false
59
end
60 61
mptopdf
.
reset
(
)
62 63
function
mptopdf
.
parsers
.
none
(
)
64
-- no parser set
65
end
66 67
function
mptopdf
.
parse
(
)
68
mptopdf
.
parsers
[
mptopdf
.
parser
]
(
)
69
end
70 71
-- old code
72 73
mptopdf
.
steps
=
{
}
74 75
mptopdf
.
descapes
=
{
76
[
'
(
'
]
=
"
\\\\char40
"
,
77
[
'
)
'
]
=
"
\\\\char41
"
,
78
[
'
"
'
]
=
"
\\\\char92
"
79
}
80 81
function
mptopdf
.
descape
(
str
)
82
str
=
gsub
(
str
,
"
\\(%d%d%d)
"
,
function
(
n
)
83
return
"
\\char
"
.
.
tonumber
(
n
,
8
)
.
.
"
"
84
end
)
85
return
gsub
(
str
,
"
\\([%(%)\\])
"
,
mptopdf
.
descapes
)
86
end
87 88
function
mptopdf
.
steps
.
descape
(
str
)
89
str
=
gsub
(
str
,
"
\\(%d%d%d)
"
,
function
(
n
)
90
return
"
\\\\char
"
.
.
tonumber
(
n
,
8
)
.
.
"
"
91
end
)
92
return
gsub
(
str
,
"
\\([%(%)\\])
"
,
mptopdf
.
descapes
)
93
end
94 95
function
mptopdf
.
steps
.
strip
(
)
-- .3 per expr
96
mptopdf
.
data
=
gsub
(
mptopdf
.
data
,
"
^(.-)%%+Page:.-%c+(.*)%s+%a+%s+%%+EOF.*$
"
,
function
(
preamble
,
graphic
)
97
local
bbox
=
"
0 0 0 0
"
98
for
b
in
gmatch
(
preamble
,
"
%%%%%a+oundingBox: +(.-)%c+
"
)
do
99
bbox
=
b
100
end
101
local
name
,
version
=
gmatch
(
preamble
,
"
%%%%Creator: +(.-) +(.-)
"
)
102
mptopdf
.
version
=
tostring
(
version
or
"
0
"
)
103
if
find
(
preamble
,
"
/hlw{0 dtransform
"
,
1
,
true
)
then
104
mptopdf
.
shortcuts
=
true
105
end
106
-- the boundingbox specification needs to come before data, well, not really
107
return
bbox
.
.
"
boundingbox\n
"
.
.
"
\nbegindata\n
"
.
.
graphic
.
.
"
\nenddata\n
"
108
end
,
1
)
109
mptopdf
.
data
=
gsub
(
mptopdf
.
data
,
"
%%%%MetaPostSpecials: +(.-)%c+
"
,
"
%1 specials\n
"
,
1
)
110
mptopdf
.
data
=
gsub
(
mptopdf
.
data
,
"
%%%%MetaPostSpecial: +(.-)%c+
"
,
"
%1 special\n
"
)
111
mptopdf
.
data
=
gsub
(
mptopdf
.
data
,
"
%%.-%c+
"
,
"
"
)
112
end
113 114
function
mptopdf
.
steps
.
cleanup
(
)
115
if
not
mptopdf
.
shortcuts
then
116
mptopdf
.
data
=
gsub
(
mptopdf
.
data
,
"
gsave%s+fill%s+grestore%s+stroke
"
,
"
both
"
)
117
mptopdf
.
data
=
gsub
(
mptopdf
.
data
,
"
([%d%.]+)%s+([%d%.]+)%s+dtransform%s+exch%s+truncate%s+exch%s+idtransform%s+pop%s+setlinewidth
"
,
function
(
wx
,
wy
)
118
if
tonumber
(
wx
)
>
0
then
return
wx
.
.
"
setlinewidth
"
else
return
wy
.
.
"
setlinewidth
"
end
119
end
)
120
mptopdf
.
data
=
gsub
(
mptopdf
.
data
,
"
([%d%.]+)%s+([%d%.]+)%s+dtransform%s+truncate%s+idtransform%s+setlinewidth%s+pop
"
,
function
(
wx
,
wy
)
121
if
tonumber
(
wx
)
>
0
then
return
wx
.
.
"
setlinewidth
"
else
return
wy
.
.
"
setlinewidth
"
end
122
end
)
123
end
124
end
125 126
function
mptopdf
.
steps
.
convert
(
)
127
mptopdf
.
data
=
gsub
(
mptopdf
.
data
,
"
%c%((.-)%) (.-) (.-) fshow
"
,
function
(
str
,
font
,
scale
)
128
mptopdf
.
texts
[
mptopdf
.
texts
+
1
]
=
{
mptopdf
.
steps
.
descape
(
str
)
,
font
,
scale
}
129
return
"
\n
"
.
.
#
mptopdf
.
texts
.
.
"
textext
"
130
end
)
131
mptopdf
.
data
=
gsub
(
mptopdf
.
data
,
"
%[%s*(.-)%s*%]
"
,
function
(
str
)
132
return
gsub
(
str
,
"
%s+
"
,
"
"
)
133
end
)
134
local
t
135
mptopdf
.
data
=
gsub
(
mptopdf
.
data
,
"
%s*([^%a]-)%s*(%a+)
"
,
function
(
args
,
cmd
)
136
if
cmd
=
=
"
textext
"
then
137
t
=
mptopdf
.
texts
[
tonumber
(
args
)
]
138
return
"
metapost.mps.textext(
"
.
.
"
\"
"
.
.
t
[
2
]
.
.
"
\",
"
.
.
t
[
3
]
.
.
"
,\"
"
.
.
t
[
1
]
.
.
"
\")\n
"
139
else
140
return
"
metapost.mps.
"
.
.
cmd
.
.
"
(
"
.
.
gsub
(
args
,
"
+
"
,
"
,
"
)
.
.
"
)\n
"
141
end
142
end
)
143
end
144 145
function
mptopdf
.
steps
.
process
(
)
146
assert
(
loadstring
(
mptopdf
.
data
)
)
(
)
-- () runs the loaded chunk
147
end
148 149
function
mptopdf
.
parsers
.
gsub
(
)
150
mptopdf
.
steps
.
strip
(
)
151
mptopdf
.
steps
.
cleanup
(
)
152
mptopdf
.
steps
.
convert
(
)
153
mptopdf
.
steps
.
process
(
)
154
end
155 156
-- end of old code
157 158
-- from lua to tex
159 160
function
mptopdf
.
pdfcode
(
str
)
161
context
.
pdfliteral
(
str
)
-- \\MPScode
162
end
163 164
function
mptopdf
.
texcode
(
str
)
165
context
(
str
)
166
end
167 168
-- auxiliary functions
169 170
function
mptopdf
.
flushconcat
(
)
171
if
mptopdf
.
stack
.
concat
then
172
mptopdf
.
pdfcode
(
concat
(
mptopdf
.
stack
.
concat
,
"
"
)
.
.
"
cm
"
)
173
mptopdf
.
stack
.
concat
=
nil
174
end
175
end
176 177
function
mptopdf
.
flushpath
(
cmd
)
178
-- faster: no local function and loop
179
if
#
mptopdf
.
stack
.
path
>
0
then
180
local
path
=
{
}
181
if
mptopdf
.
stack
.
concat
then
182
local
sx
,
sy
=
mptopdf
.
stack
.
concat
[
1
]
,
mptopdf
.
stack
.
concat
[
4
]
183
local
rx
,
ry
=
mptopdf
.
stack
.
concat
[
2
]
,
mptopdf
.
stack
.
concat
[
3
]
184
local
tx
,
ty
=
mptopdf
.
stack
.
concat
[
5
]
,
mptopdf
.
stack
.
concat
[
6
]
185
local
d
=
(
sx
*
sy
)
-
(
rx
*
ry
)
186
local
function
mpconcat
(
px
,
py
)
187
return
(
sy
*
(
px
-
tx
)
-
ry
*
(
py
-
ty
)
)
/
d
,
(
sx
*
(
py
-
ty
)
-
rx
*
(
px
-
tx
)
)
/
d
188
end
189
local
stackpath
=
mptopdf
.
stack
.
path
190
for
k
=
1
,
#
stackpath
do
191
local
v
=
stackpath
[
k
]
192
v
[
1
]
,
v
[
2
]
=
mpconcat
(
v
[
1
]
,
v
[
2
]
)
193
if
#
v
=
=
7
then
194
v
[
3
]
,
v
[
4
]
=
mpconcat
(
v
[
3
]
,
v
[
4
]
)
195
v
[
5
]
,
v
[
6
]
=
mpconcat
(
v
[
5
]
,
v
[
6
]
)
196
end
197
path
[
#
path
+
1
]
=
concat
(
v
,
"
"
)
198
end
199
else
200
local
stackpath
=
mptopdf
.
stack
.
path
201
for
k
=
1
,
#
stackpath
do
202
path
[
#
path
+
1
]
=
concat
(
stackpath
[
k
]
,
"
"
)
203
end
204
end
205
mptopdf
.
flushconcat
(
)
206
mptopdf
.
texcode
(
"
\\MPSpath{
"
.
.
concat
(
path
,
"
"
)
.
.
"
}
"
)
207
if
mptopdf
.
stack
.
close
then
208
mptopdf
.
texcode
(
"
\\MPScode{h
"
.
.
cmd
.
.
"
}
"
)
209
else
210
mptopdf
.
texcode
(
"
\\MPScode{
"
.
.
cmd
.
.
"
}
"
)
211
end
212
end
213
mptopdf
.
resetpath
(
)
214
end
215 216
function
mptopdf
.
loaded
(
name
)
217
local
ok
,
n
218
mptopdf
.
reset
(
)
219
ok
,
mptopdf
.
data
,
n
=
resolvers
.
loadbinfile
(
name
,
'
tex
'
)
-- we need a binary load !
220
return
ok
221
end
222 223
if
not
mptopdf
.
parse
then
224
function
mptopdf
.
parse
(
)
end
-- forward declaration
225
end
226 227
function
mptopdf
.
convertmpstopdf
(
name
)
228
if
mptopdf
.
loaded
(
name
)
then
229
mptopdf
.
nofconverted
=
mptopdf
.
nofconverted
+
1
230
statistics
.
starttiming
(
mptopdf
)
231
mptopdf
.
parse
(
)
232
mptopdf
.
reset
(
)
233
statistics
.
stoptiming
(
mptopdf
)
234
else
235
context
(
"
file
"
.
.
name
.
.
"
not found
"
)
236
end
237
end
238 239
-- mp interface
240 241
metapost
.
mps
=
metapost
.
mps
or
{
}
242
local
mps
=
metapost
.
mps
or
{
}
243 244
function
mps
.
creator
(
a
,
b
,
c
)
245
mptopdf
.
version
=
tonumber
(
b
)
246
end
247 248
function
mps
.
creationdate
(
a
)
249
mptopdf
.
date
=
a
250
end
251 252
function
mps
.
newpath
(
)
253
mptopdf
.
stack
.
path
=
{
}
254
end
255 256
function
mps
.
boundingbox
(
llx
,
lly
,
urx
,
ury
)
257
mptopdf
.
texcode
(
"
\\MPSboundingbox{
"
.
.
llx
.
.
"
}{
"
.
.
lly
.
.
"
}{
"
.
.
urx
.
.
"
}{
"
.
.
ury
.
.
"
}
"
)
258
end
259 260
function
mps
.
moveto
(
x
,
y
)
261
mptopdf
.
stack
.
path
[
#
mptopdf
.
stack
.
path
+
1
]
=
{
x
,
y
,
"
m
"
}
262
end
263 264
function
mps
.
curveto
(
ax
,
ay
,
bx
,
by
,
cx
,
cy
)
265
mptopdf
.
stack
.
path
[
#
mptopdf
.
stack
.
path
+
1
]
=
{
ax
,
ay
,
bx
,
by
,
cx
,
cy
,
"
c
"
}
266
end
267 268
function
mps
.
lineto
(
x
,
y
)
269
mptopdf
.
stack
.
path
[
#
mptopdf
.
stack
.
path
+
1
]
=
{
x
,
y
,
"
l
"
}
270
end
271 272
function
mps
.
rlineto
(
x
,
y
)
273
local
dx
,
dy
=
0
,
0
274
if
#
mptopdf
.
stack
.
path
>
0
then
275
dx
,
dy
=
mptopdf
.
stack
.
path
[
#
mptopdf
.
stack
.
path
]
[
1
]
,
mptopdf
.
stack
.
path
[
#
mptopdf
.
stack
.
path
]
[
2
]
276
end
277
mptopdf
.
stack
.
path
[
#
mptopdf
.
stack
.
path
+
1
]
=
{
dx
,
dy
,
"
l
"
}
278
end
279 280
function
mps
.
translate
(
tx
,
ty
)
281
mptopdf
.
pdfcode
(
"
1 0 0 0 1
"
.
.
tx
.
.
"
"
.
.
ty
.
.
"
cm
"
)
282
end
283 284
function
mps
.
scale
(
sx
,
sy
)
285
mptopdf
.
stack
.
concat
=
{
sx
,
0
,
0
,
sy
,
0
,
0
}
286
end
287 288
function
mps
.
concat
(
sx
,
rx
,
ry
,
sy
,
tx
,
ty
)
289
mptopdf
.
stack
.
concat
=
{
sx
,
rx
,
ry
,
sy
,
tx
,
ty
}
290
end
291 292
function
mps
.
setlinejoin
(
d
)
293
mptopdf
.
pdfcode
(
d
.
.
"
j
"
)
294
end
295 296
function
mps
.
setlinecap
(
d
)
297
mptopdf
.
pdfcode
(
d
.
.
"
J
"
)
298
end
299 300
function
mps
.
setmiterlimit
(
d
)
301
mptopdf
.
pdfcode
(
d
.
.
"
M
"
)
302
end
303 304
function
mps
.
gsave
(
)
305
mptopdf
.
pdfcode
(
"
q
"
)
306
end
307 308
function
mps
.
grestore
(
)
309
mptopdf
.
pdfcode
(
"
Q
"
)
310
end
311 312
function
mps
.
setdash
(
...
)
313
local
n
=
select
(
"
#
"
,
...
)
314
mptopdf
.
pdfcode
(
"
[
"
.
.
concat
(
{
...
}
,
"
"
,
1
,
n
-1
)
.
.
"
]
"
.
.
select
(
n
,
...
)
.
.
"
d
"
)
315
end
316 317
function
mps
.
resetdash
(
)
318
mptopdf
.
pdfcode
(
"
[ ] 0 d
"
)
319
end
320 321
function
mps
.
setlinewidth
(
d
)
322
mptopdf
.
pdfcode
(
d
.
.
"
w
"
)
323
end
324 325
function
mps
.
closepath
(
)
326
mptopdf
.
stack
.
close
=
true
327
end
328 329
function
mps
.
fill
(
)
330
mptopdf
.
flushpath
(
'
f
'
)
331
end
332 333
function
mps
.
stroke
(
)
334
mptopdf
.
flushpath
(
'
S
'
)
335
end
336 337
function
mps
.
both
(
)
338
mptopdf
.
flushpath
(
'
B
'
)
339
end
340 341
function
mps
.
clip
(
)
342
mptopdf
.
flushpath
(
'
W n
'
)
343
end
344 345
function
mps
.
textext
(
font
,
scale
,
str
)
-- old parser
346
local
dx
,
dy
=
0
,
0
347
if
#
mptopdf
.
stack
.
path
>
0
then
348
dx
,
dy
=
mptopdf
.
stack
.
path
[
1
]
[
1
]
,
mptopdf
.
stack
.
path
[
1
]
[
2
]
349
end
350
mptopdf
.
flushconcat
(
)
351
mptopdf
.
texcode
(
"
\\MPStextext{
"
.
.
font
.
.
"
}{
"
.
.
scale
.
.
"
}{
"
.
.
str
.
.
"
}{
"
.
.
dx
.
.
"
}{
"
.
.
dy
.
.
"
}
"
)
352
mptopdf
.
resetpath
(
)
353
end
354 355
--~ function mps.handletext(font,scale.str,dx,dy)
356
--~ local one, two = string.match(str, "^(%d+)::::(%d+)")
357
--~ if one and two then
358
--~ mptopdf.texcode("\\MPTOPDFtextext{"..font.."}{"..scale.."}{"..one.."}{"..two.."}{"..dx.."}{"..dy.."}")
359
--~ else
360
--~ mptopdf.texcode("\\MPTOPDFtexcode{"..font.."}{"..scale.."}{"..str.."}{"..dx.."}{"..dy.."}")
361
--~ end
362
--~ end
363 364
function
mps
.
setrgbcolor
(
r
,
g
,
b
)
-- extra check
365
r
,
g
=
tonumber
(
r
)
,
tonumber
(
g
)
-- needed when we use lpeg
366
if
r
=
=
0
.
0123
and
g
<
0
.
1
then
367
mptopdf
.
texcode
(
"
\\MPSspecial{
"
.
.
g
*
10000
.
.
"
}{
"
.
.
b
*
10000
.
.
"
}
"
)
368
elseif
r
=
=
0
.
123
and
g
<
0
.
1
then
369
mptopdf
.
texcode
(
"
\\MPSspecial{
"
.
.
g
*
1000
.
.
"
}{
"
.
.
b
*
1000
.
.
"
}
"
)
370
else
371
mptopdf
.
texcode
(
"
\\MPSrgb{
"
.
.
r
.
.
"
}{
"
.
.
g
.
.
"
}{
"
.
.
b
.
.
"
}
"
)
372
end
373
end
374 375
function
mps
.
setcmykcolor
(
c
,
m
,
y
,
k
)
376
mptopdf
.
texcode
(
"
\\MPScmyk{
"
.
.
c
.
.
"
}{
"
.
.
m
.
.
"
}{
"
.
.
y
.
.
"
}{
"
.
.
k
.
.
"
}
"
)
377
end
378 379
function
mps
.
setgray
(
s
)
380
mptopdf
.
texcode
(
"
\\MPSgray{
"
.
.
s
.
.
"
}
"
)
381
end
382 383
function
mps
.
specials
(
version
,
signal
,
factor
)
-- 2.0 123 1000
384
end
385 386
function
mps
.
special
(
...
)
-- 7 1 0.5 1 0 0 1 3
387
local
n
=
select
(
"
#
"
,
...
)
388
mptopdf
.
texcode
(
"
\\MPSbegin\\MPSset{
"
.
.
concat
(
{
...
}
,
"
}\\MPSset{
"
,
2
,
n
)
.
.
"
}\\MPSend
"
)
389
end
390 391
function
mps
.
begindata
(
)
392
end
393 394
function
mps
.
enddata
(
)
395
end
396 397
function
mps
.
showpage
(
)
398
end
399 400
mps
.
n
=
mps
.
newpath
-- n
401
mps
.
p
=
mps
.
closepath
-- h
402
mps
.
l
=
mps
.
lineto
-- l
403
mps
.
r
=
mps
.
rlineto
-- r
404
mps
.
m
=
mps
.
moveto
-- m
405
mps
.
c
=
mps
.
curveto
-- c
406
mps
.
hlw
=
mps
.
setlinewidth
407
mps
.
vlw
=
mps
.
setlinewidth
408 409
mps
.
C
=
mps
.
setcmykcolor
-- k
410
mps
.
G
=
mps
.
setgray
-- g
411
mps
.
R
=
mps
.
setrgbcolor
-- rg
412 413
mps
.
lj
=
mps
.
setlinejoin
-- j
414
mps
.
ml
=
mps
.
setmiterlimit
-- M
415
mps
.
lc
=
mps
.
setlinecap
-- J
416
mps
.
sd
=
mps
.
setdash
-- d
417
mps
.
rd
=
mps
.
resetdash
418 419
mps
.
S
=
mps
.
stroke
-- S
420
mps
.
F
=
mps
.
fill
-- f
421
mps
.
B
=
mps
.
both
-- B
422
mps
.
W
=
mps
.
clip
-- W
423 424
mps
.
q
=
mps
.
gsave
-- q
425
mps
.
Q
=
mps
.
grestore
-- Q
426 427
mps
.
s
=
mps
.
scale
-- (not in pdf)
428
mps
.
t
=
mps
.
concat
-- (not the same as pdf anyway)
429 430
mps
.
P
=
mps
.
showpage
431 432
-- experimental
433 434
function
mps
.
attribute
(
id
,
value
)
435
mptopdf
.
texcode
(
"
\\attribute
"
.
.
id
.
.
"
=
"
.
.
value
.
.
"
"
)
436
-- mptopdf.texcode("\\dompattribute{" .. id .. "}{" .. value .. "}")
437
end
438 439
-- lpeg parser
440 441
-- The lpeg based parser is rather optimized for the kind of output
442
-- that MetaPost produces. It's my first real lpeg code, which may
443
-- show. Because the parser binds to functions, we define it last.
444 445
do
-- assumes \let\c\char
446 447
local
byte
=
string
.
byte
448
local
digit
=
lpeg
.
R
(
"
09
"
)
449
local
spec
=
digit
^
2
*
lpeg
.
P
(
"
::::
"
)
*
digit
^
2
450
local
text
=
lpeg
.
Cc
(
"
{
"
)
*
(
451
lpeg
.
P
(
"
\\
"
)
*
(
(
digit
*
digit
*
digit
)
/
function
(
n
)
return
"
c
"
.
.
tonumber
(
n
,
8
)
end
)
+
452
lpeg
.
P
(
"
"
)
/
function
(
n
)
return
"
\\c32
"
end
+
-- never in new mp
453
lpeg
.
P
(
1
)
/
function
(
n
)
return
"
\\c
"
.
.
byte
(
n
)
end
454
)
*
lpeg
.
Cc
(
"
}
"
)
455
local
package
=
lpeg
.
Cs
(
spec
+
text
^
0
)
456 457
function
mps
.
fshow
(
str
,
font
,
scale
)
-- lpeg parser
458
mps
.
textext
(
font
,
scale
,
lpegmatch
(
package
,
str
)
)
459
end
460 461
end
462 463
do
464 465
local
eol
=
lpeg
.
S
(
'
\r\n
'
)
^
1
466
local
sp
=
lpeg
.
P
(
'
'
)
^
1
467
local
space
=
lpeg
.
S
(
'
\r\n
'
)
^
1
468
local
number
=
lpeg
.
S
(
'
0123456789.-+
'
)
^
1
469
local
nonspace
=
lpeg
.
P
(
1
-
lpeg
.
S
(
'
\r\n
'
)
)
^
1
470 471
local
cnumber
=
lpeg
.
C
(
number
)
472
local
cstring
=
lpeg
.
C
(
nonspace
)
473 474
local
specials
=
(
lpeg
.
P
(
"
%%MetaPostSpecials:
"
)
*
sp
*
(
cstring
*
sp
^
0
)
^
0
*
eol
)
/
mps
.
specials
475
local
special
=
(
lpeg
.
P
(
"
%%MetaPostSpecial:
"
)
*
sp
*
(
cstring
*
sp
^
0
)
^
0
*
eol
)
/
mps
.
special
476
local
boundingbox
=
(
lpeg
.
P
(
"
%%BoundingBox:
"
)
*
sp
*
(
cnumber
*
sp
^
0
)
^
4
*
eol
)
/
mps
.
boundingbox
477
local
highresboundingbox
=
(
lpeg
.
P
(
"
%%HiResBoundingBox:
"
)
*
sp
*
(
cnumber
*
sp
^
0
)
^
4
*
eol
)
/
mps
.
boundingbox
478 479
local
setup
=
lpeg
.
P
(
"
%%BeginSetup
"
)
*
(
1
-
lpeg
.
P
(
"
%%EndSetup
"
)
)
^
1
480
local
prolog
=
lpeg
.
P
(
"
%%BeginProlog
"
)
*
(
1
-
lpeg
.
P
(
"
%%EndProlog
"
)
)
^
1
481
local
comment
=
lpeg
.
P
(
'
%
'
)
^
1
*
(
1
-
eol
)
^
1
482 483
local
curveto
=
(
(
cnumber
*
sp
)
^
6
*
lpeg
.
P
(
"
curveto
"
)
)
/
mps
.
curveto
484
local
lineto
=
(
(
cnumber
*
sp
)
^
2
*
lpeg
.
P
(
"
lineto
"
)
)
/
mps
.
lineto
485
local
rlineto
=
(
(
cnumber
*
sp
)
^
2
*
lpeg
.
P
(
"
rlineto
"
)
)
/
mps
.
rlineto
486
local
moveto
=
(
(
cnumber
*
sp
)
^
2
*
lpeg
.
P
(
"
moveto
"
)
)
/
mps
.
moveto
487
local
setrgbcolor
=
(
(
cnumber
*
sp
)
^
3
*
lpeg
.
P
(
"
setrgbcolor
"
)
)
/
mps
.
setrgbcolor
488
local
setcmykcolor
=
(
(
cnumber
*
sp
)
^
4
*
lpeg
.
P
(
"
setcmykcolor
"
)
)
/
mps
.
setcmykcolor
489
local
setgray
=
(
(
cnumber
*
sp
)
^
1
*
lpeg
.
P
(
"
setgray
"
)
)
/
mps
.
setgray
490
local
newpath
=
(
lpeg
.
P
(
"
newpath
"
)
)
/
mps
.
newpath
491
local
closepath
=
(
lpeg
.
P
(
"
closepath
"
)
)
/
mps
.
closepath
492
local
fill
=
(
lpeg
.
P
(
"
fill
"
)
)
/
mps
.
fill
493
local
stroke
=
(
lpeg
.
P
(
"
stroke
"
)
)
/
mps
.
stroke
494
local
clip
=
(
lpeg
.
P
(
"
clip
"
)
)
/
mps
.
clip
495
local
both
=
(
lpeg
.
P
(
"
gsave fill grestore
"
)
)
/
mps
.
both
496
local
showpage
=
(
lpeg
.
P
(
"
showpage
"
)
)
497
local
setlinejoin
=
(
(
cnumber
*
sp
)
^
1
*
lpeg
.
P
(
"
setlinejoin
"
)
)
/
mps
.
setlinejoin
498
local
setlinecap
=
(
(
cnumber
*
sp
)
^
1
*
lpeg
.
P
(
"
setlinecap
"
)
)
/
mps
.
setlinecap
499
local
setmiterlimit
=
(
(
cnumber
*
sp
)
^
1
*
lpeg
.
P
(
"
setmiterlimit
"
)
)
/
mps
.
setmiterlimit
500
local
gsave
=
(
lpeg
.
P
(
"
gsave
"
)
)
/
mps
.
gsave
501
local
grestore
=
(
lpeg
.
P
(
"
grestore
"
)
)
/
mps
.
grestore
502 503
local
setdash
=
(
lpeg
.
P
(
"
[
"
)
*
(
cnumber
*
sp
^
0
)
^
0
*
lpeg
.
P
(
"
]
"
)
*
sp
*
cnumber
*
sp
*
lpeg
.
P
(
"
setdash
"
)
)
/
mps
.
setdash
504
local
concat
=
(
lpeg
.
P
(
"
[
"
)
*
(
cnumber
*
sp
^
0
)
^
6
*
lpeg
.
P
(
"
]
"
)
*
sp
*
lpeg
.
P
(
"
concat
"
)
)
/
mps
.
concat
505
local
scale
=
(
(
cnumber
*
sp
^
0
)
^
6
*
sp
*
lpeg
.
P
(
"
concat
"
)
)
/
mps
.
concat
506 507
local
fshow
=
(
lpeg
.
P
(
"
(
"
)
*
lpeg
.
C
(
(
1
-
lpeg
.
P
(
"
)
"
)
)
^
1
)
*
lpeg
.
P
(
"
)
"
)
*
space
*
cstring
*
space
*
cnumber
*
space
*
lpeg
.
P
(
"
fshow
"
)
)
/
mps
.
fshow
508
local
fshow
=
(
lpeg
.
P
(
"
(
"
)
*
509
lpeg
.
Cs
(
(
lpeg
.
P
(
"
\\(
"
)
/
"
\\050
"
+
lpeg
.
P
(
"
\\)
"
)
/
"
\\051
"
+
(
1
-
lpeg
.
P
(
"
)
"
)
)
)
^
1
)
510
*
lpeg
.
P
(
"
)
"
)
*
space
*
cstring
*
space
*
cnumber
*
space
*
lpeg
.
P
(
"
fshow
"
)
)
/
mps
.
fshow
511 512
local
setlinewidth_x
=
(
lpeg
.
P
(
"
0
"
)
*
sp
*
cnumber
*
sp
*
lpeg
.
P
(
"
dtransform truncate idtransform setlinewidth pop
"
)
)
/
mps
.
setlinewidth
513
local
setlinewidth_y
=
(
cnumber
*
sp
*
lpeg
.
P
(
"
0 dtransform exch truncate exch idtransform pop setlinewidth
"
)
)
/
mps
.
setlinewidth
514 515
local
c
=
(
(
cnumber
*
sp
)
^
6
*
lpeg
.
P
(
"
c
"
)
)
/
mps
.
curveto
-- ^6 very inefficient, ^1 ok too
516
local
l
=
(
(
cnumber
*
sp
)
^
2
*
lpeg
.
P
(
"
l
"
)
)
/
mps
.
lineto
517
local
r
=
(
(
cnumber
*
sp
)
^
2
*
lpeg
.
P
(
"
r
"
)
)
/
mps
.
rlineto
518
local
m
=
(
(
cnumber
*
sp
)
^
2
*
lpeg
.
P
(
"
m
"
)
)
/
mps
.
moveto
519
local
vlw
=
(
(
cnumber
*
sp
)
^
1
*
lpeg
.
P
(
"
vlw
"
)
)
/
mps
.
setlinewidth
520
local
hlw
=
(
(
cnumber
*
sp
)
^
1
*
lpeg
.
P
(
"
hlw
"
)
)
/
mps
.
setlinewidth
521 522
local
R
=
(
(
cnumber
*
sp
)
^
3
*
lpeg
.
P
(
"
R
"
)
)
/
mps
.
setrgbcolor
523
local
C
=
(
(
cnumber
*
sp
)
^
4
*
lpeg
.
P
(
"
C
"
)
)
/
mps
.
setcmykcolor
524
local
G
=
(
(
cnumber
*
sp
)
^
1
*
lpeg
.
P
(
"
G
"
)
)
/
mps
.
setgray
525 526
local
lj
=
(
(
cnumber
*
sp
)
^
1
*
lpeg
.
P
(
"
lj
"
)
)
/
mps
.
setlinejoin
527
local
ml
=
(
(
cnumber
*
sp
)
^
1
*
lpeg
.
P
(
"
ml
"
)
)
/
mps
.
setmiterlimit
528
local
lc
=
(
(
cnumber
*
sp
)
^
1
*
lpeg
.
P
(
"
lc
"
)
)
/
mps
.
setlinecap
529 530
local
n
=
lpeg
.
P
(
"
n
"
)
/
mps
.
newpath
531
local
p
=
lpeg
.
P
(
"
p
"
)
/
mps
.
closepath
532
local
S
=
lpeg
.
P
(
"
S
"
)
/
mps
.
stroke
533
local
F
=
lpeg
.
P
(
"
F
"
)
/
mps
.
fill
534
local
B
=
lpeg
.
P
(
"
B
"
)
/
mps
.
both
535
local
W
=
lpeg
.
P
(
"
W
"
)
/
mps
.
clip
536
local
P
=
lpeg
.
P
(
"
P
"
)
/
mps
.
showpage
537 538
local
q
=
lpeg
.
P
(
"
q
"
)
/
mps
.
gsave
539
local
Q
=
lpeg
.
P
(
"
Q
"
)
/
mps
.
grestore
540 541
local
sd
=
(
lpeg
.
P
(
"
[
"
)
*
(
cnumber
*
sp
^
0
)
^
0
*
lpeg
.
P
(
"
]
"
)
*
sp
*
cnumber
*
sp
*
lpeg
.
P
(
"
sd
"
)
)
/
mps
.
setdash
542
local
rd
=
(
lpeg
.
P
(
"
rd
"
)
)
/
mps
.
resetdash
543 544
local
s
=
(
(
cnumber
*
sp
^
0
)
^
2
*
lpeg
.
P
(
"
s
"
)
)
/
mps
.
scale
545
local
t
=
(
lpeg
.
P
(
"
[
"
)
*
(
cnumber
*
sp
^
0
)
^
6
*
lpeg
.
P
(
"
]
"
)
*
sp
*
lpeg
.
P
(
"
t
"
)
)
/
mps
.
concat
546 547
-- experimental
548 549
local
attribute
=
(
(
cnumber
*
sp
)
^
2
*
lpeg
.
P
(
"
attribute
"
)
)
/
mps
.
attribute
550
local
A
=
(
(
cnumber
*
sp
)
^
2
*
lpeg
.
P
(
"
A
"
)
)
/
mps
.
attribute
551 552
local
preamble
=
(
553
prolog
+
setup
+
554
boundingbox
+
highresboundingbox
+
specials
+
special
+
555
comment
556
)
557 558
local
procset
=
(
559
lj
+
ml
+
lc
+
560
c
+
l
+
m
+
n
+
p
+
r
+
561
A
+
562
R
+
C
+
G
+
563
S
+
F
+
B
+
W
+
564
vlw
+
hlw
+
565
Q
+
q
+
566
sd
+
rd
+
567
t
+
s
+
568
fshow
+
569
P
570
)
571 572
local
verbose
=
(
573
curveto
+
lineto
+
moveto
+
newpath
+
closepath
+
rlineto
+
574
setrgbcolor
+
setcmykcolor
+
setgray
+
575
attribute
+
576
setlinejoin
+
setmiterlimit
+
setlinecap
+
577
stroke
+
fill
+
clip
+
both
+
578
setlinewidth_x
+
setlinewidth_y
+
579
gsave
+
grestore
+
580
concat
+
scale
+
581
fshow
+
582
setdash
+
-- no resetdash
583
showpage
584
)
585 586
-- order matters in terms of speed / we could check for procset first
587 588
local
captures_old
=
(
space
+
verbose
+
preamble
)
^
0
589
local
captures_new
=
(
space
+
procset
+
preamble
+
verbose
)
^
0
590 591
function
mptopdf
.
parsers
.
lpeg
(
)
592
if
find
(
mptopdf
.
data
,
"
%%BeginResource: procset mpost
"
,
1
,
true
)
then
593
lpegmatch
(
captures_new
,
mptopdf
.
data
)
594
else
595
lpegmatch
(
captures_old
,
mptopdf
.
data
)
596
end
597
end
598 599
end
600 601
mptopdf
.
parser
=
'
lpeg
'
602 603
-- status info
604 605
statistics
.
register
(
"
mps conversion time
"
,
function
(
)
606
local
n
=
mptopdf
.
nofconverted
607
if
n
>
0
then
608
return
format
(
"
%s seconds, %s conversions
"
,
statistics
.
elapsedtime
(
mptopdf
)
,
n
)
609
else
610
return
nil
611
end
612
end
)
613