lpdf-ren.lua /size: 12 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
lpdf-ren
'
]
=
{
2
version
=
1
.
001
,
3
comment
=
"
companion to lpdf-ini.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
-- rendering
10 11
local
tostring
,
tonumber
,
next
=
tostring
,
tonumber
,
next
12
local
concat
=
table
.
concat
13
local
formatters
=
string
.
formatters
14
local
settings_to_array
=
utilities
.
parsers
.
settings_to_array
15
local
getrandom
=
utilities
.
randomizer
.
get
16 17
local
backends
,
lpdf
,
nodes
,
node
=
backends
,
lpdf
,
nodes
,
node
18 19
local
nodeinjections
=
backends
.
pdf
.
nodeinjections
20
local
codeinjections
=
backends
.
pdf
.
codeinjections
21
local
registrations
=
backends
.
pdf
.
registrations
22
local
viewerlayers
=
attributes
.
viewerlayers
23 24
local
references
=
structures
.
references
25 26
references
.
executers
=
references
.
executers
or
{
}
27
local
executers
=
references
.
executers
28 29
local
variables
=
interfaces
.
variables
30 31
local
v_no
=
variables
.
no
32
local
v_yes
=
variables
.
yes
33
local
v_start
=
variables
.
start
34
local
v_stop
=
variables
.
stop
35
local
v_reset
=
variables
.
reset
36
local
v_auto
=
variables
.
auto
37
local
v_random
=
variables
.
random
38 39
local
pdfconstant
=
lpdf
.
constant
40
local
pdfdictionary
=
lpdf
.
dictionary
41
local
pdfarray
=
lpdf
.
array
42
local
pdfreference
=
lpdf
.
reference
43
local
pdfflushobject
=
lpdf
.
flushobject
44
local
pdfreserveobject
=
lpdf
.
reserveobject
45 46
local
addtopageattributes
=
lpdf
.
addtopageattributes
47
local
addtopageresources
=
lpdf
.
addtopageresources
48
local
addtocatalog
=
lpdf
.
addtocatalog
49 50
local
escaped
=
lpdf
.
escaped
51 52
local
nuts
=
nodes
.
nuts
53
local
copy_node
=
nuts
.
copy
54 55
local
nodepool
=
nuts
.
pool
56
local
register
=
nodepool
.
register
57
local
pageliteral
=
nodepool
.
pageliteral
58 59
local
pdf_ocg
=
pdfconstant
(
"
OCG
"
)
60
local
pdf_ocmd
=
pdfconstant
(
"
OCMD
"
)
61
local
pdf_off
=
pdfconstant
(
"
OFF
"
)
62
local
pdf_on
=
pdfconstant
(
"
ON
"
)
63
local
pdf_view
=
pdfconstant
(
"
View
"
)
64
local
pdf_design
=
pdfconstant
(
"
Design
"
)
65
local
pdf_toggle
=
pdfconstant
(
"
Toggle
"
)
66
local
pdf_setocgstate
=
pdfconstant
(
"
SetOCGState
"
)
67 68
local
pdf_print
=
{
69
[
v_yes
]
=
pdfdictionary
{
PrintState
=
pdf_on
}
,
70
[
v_no
]
=
pdfdictionary
{
PrintState
=
pdf_off
}
,
71
}
72 73
local
pdf_intent
=
{
74
[
v_yes
]
=
pdf_view
,
75
[
v_no
]
=
pdf_design
,
76
}
77 78
local
pdf_export
=
{
79
[
v_yes
]
=
pdf_on
,
80
[
v_no
]
=
pdf_off
,
81
}
82 83
-- We can have references to layers before they are places, for instance from
84
-- hide and vide actions. This is why we need to be able to force usage of layers
85
-- at several moments.
86 87
-- management
88 89
local
pdfln
,
pdfld
=
{
}
,
{
}
90
local
textlayers
,
hidelayers
,
videlayers
=
pdfarray
(
)
,
pdfarray
(
)
,
pdfarray
(
)
91
local
pagelayers
,
pagelayersreference
,
cache
=
nil
,
nil
,
{
}
92
local
alphabetic
=
{
}
93 94
local
escapednames
=
table
.
setmetatableindex
(
function
(
t
,
k
)
95
local
v
=
escaped
(
k
)
96
t
[
k
]
=
v
97
return
v
98
end
)
99 100
local
specifications
=
{
}
101
local
initialized
=
{
}
102 103
function
codeinjections
.
defineviewerlayer
(
specification
)
104
if
viewerlayers
.
supported
and
textlayers
then
105
local
tag
=
specification
.
tag
106
if
not
specifications
[
tag
]
then
107
specifications
[
tag
]
=
specification
108
end
109
end
110
end
111 112
local
function
useviewerlayer
(
name
)
-- move up so that we can use it as local
113
if
not
environment
.
initex
and
not
initialized
[
name
]
then
114
local
specification
=
specifications
[
name
]
115
if
specification
then
116
specifications
[
name
]
=
nil
-- or not
117
initialized
[
name
]
=
true
118
if
not
pagelayers
then
119
pagelayers
=
pdfdictionary
(
)
120
pagelayersreference
=
pdfreserveobject
(
)
121
end
122
local
tag
=
specification
.
tag
123
-- todo: reserve
124
local
nn
=
pdfreserveobject
(
)
125
local
nr
=
pdfreference
(
nn
)
126
local
nd
=
pdfdictionary
{
127
Type
=
pdf_ocg
,
128
Name
=
specification
.
title
or
"
unknown
"
,
129
Usage
=
{
130
Intent
=
pdf_intent
[
specification
.
editable
or
v_yes
]
,
-- disable layer hiding by user (useless)
131
Print
=
pdf_print
[
specification
.
printable
or
v_yes
]
,
-- printable or not
132
Export
=
pdf_export
[
specification
.
export
or
v_yes
]
,
-- export or not
133
}
,
134
}
135
cache
[
#
cache
+
1
]
=
{
nn
,
nd
}
136
pdfln
[
tag
]
=
nr
-- was n
137
local
dn
=
pdfreserveobject
(
)
138
local
dr
=
pdfreference
(
dn
)
139
local
dd
=
pdfdictionary
{
140
Type
=
pdf_ocmd
,
141
OCGs
=
pdfarray
{
nr
}
,
142
}
143
cache
[
#
cache
+
1
]
=
{
dn
,
dd
}
144
pdfld
[
tag
]
=
dr
145
textlayers
[
#
textlayers
+
1
]
=
nr
146
alphabetic
[
tag
]
=
nr
147
if
specification
.
visible
=
=
v_start
then
148
videlayers
[
#
videlayers
+
1
]
=
nr
149
else
150
hidelayers
[
#
hidelayers
+
1
]
=
nr
151
end
152
pagelayers
[
escapednames
[
tag
]
]
=
dr
-- check
153
else
154
-- todo: message
155
end
156
end
157
end
158 159
codeinjections
.
useviewerlayer
=
useviewerlayer
160 161
local
function
layerreference
(
name
)
162
local
r
=
pdfln
[
name
]
163
if
r
then
164
return
r
165
else
166
useviewerlayer
(
name
)
167
return
pdfln
[
name
]
168
end
169
end
170 171
lpdf
.
layerreference
=
layerreference
-- also triggered when a hide or vide happens
172 173
local
function
flushtextlayers
(
)
174
if
viewerlayers
.
supported
then
175
if
pagelayers
then
176
pdfflushobject
(
pagelayersreference
,
pagelayers
)
177
end
178
for
i
=
1
,
#
cache
do
179
local
ci
=
cache
[
i
]
180
pdfflushobject
(
ci
[
1
]
,
ci
[
2
]
)
181
end
182
if
textlayers
and
#
textlayers
>
0
then
-- we can group them if needed, like: layout
183
local
sortedlayers
=
{
}
184
for
k
,
v
in
table
.
sortedhash
(
alphabetic
)
do
185
sortedlayers
[
#
sortedlayers
+
1
]
=
v
-- maybe do a proper numeric sort as well
186
end
187
local
d
=
pdfdictionary
{
188
OCGs
=
textlayers
,
189
D
=
pdfdictionary
{
190
Name
=
"
Document
"
,
191
-- Order = (viewerlayers.hasorder and textlayers) or nil,
192
Order
=
(
viewerlayers
.
hasorder
and
sortedlayers
)
or
nil
,
193
ON
=
videlayers
,
194
OFF
=
hidelayers
,
195
BaseState
=
pdf_on
,
196
AS
=
pdfarray
{
197
pdfdictionary
{
198
Category
=
pdfarray
{
pdfconstant
(
"
Print
"
)
}
,
199
Event
=
pdfconstant
(
"
Print
"
)
,
200
OCGs
=
(
viewerlayers
.
hasorder
and
sortedlayers
)
or
nil
,
201
}
202
}
,
203
}
,
204
}
205
addtocatalog
(
"
OCProperties
"
,
d
)
206
textlayers
=
nil
207
end
208
end
209
end
210 211
local
function
flushpagelayers
(
)
-- we can share these
212
if
pagelayers
then
213
addtopageresources
(
"
Properties
"
,
pdfreference
(
pagelayersreference
)
)
-- we could cache this
214
end
215
end
216 217
lpdf
.
registerpagefinalizer
(
flushpagelayers
,
"
layers
"
)
218
lpdf
.
registerdocumentfinalizer
(
flushtextlayers
,
"
layers
"
)
219 220
local
function
setlayer
(
what
,
arguments
)
221
-- maybe just a gmatch of even better, earlier in lpeg
222
arguments
=
(
type
(
arguments
)
=
=
"
table
"
and
arguments
)
or
settings_to_array
(
arguments
)
223
local
state
=
pdfarray
{
what
}
224
for
i
=
1
,
#
arguments
do
225
local
p
=
layerreference
(
arguments
[
i
]
)
226
if
p
then
227
state
[
#
state
+
1
]
=
p
228
end
229
end
230
return
pdfdictionary
{
231
S
=
pdf_setocgstate
,
232
State
=
state
,
233
}
234
end
235 236
function
executers
.
hidelayer
(
arguments
)
return
setlayer
(
pdf_off
,
arguments
)
end
237
function
executers
.
videlayer
(
arguments
)
return
setlayer
(
pdf_on
,
arguments
)
end
238
function
executers
.
togglelayer
(
arguments
)
return
setlayer
(
pdf_toggle
,
arguments
)
end
239 240
-- injection
241 242
local
f_bdc
=
formatters
[
"
/OC /%s BDC
"
]
243
local
s_emc
=
"
EMC
"
244 245
function
codeinjections
.
startlayer
(
name
)
-- used in mp
246
if
not
name
then
247
name
=
"
unknown
"
248
end
249
useviewerlayer
(
name
)
250
return
f_bdc
(
escapednames
[
name
]
)
251
end
252 253
function
codeinjections
.
stoplayer
(
name
)
-- used in mp
254
return
s_emc
255
end
256 257
local
cache
=
{
}
258
local
stop
=
nil
259 260
function
nodeinjections
.
startlayer
(
name
)
261
local
c
=
cache
[
name
]
262
if
not
c
then
263
useviewerlayer
(
name
)
264
c
=
register
(
pageliteral
(
f_bdc
(
escapednames
[
name
]
)
)
)
265
cache
[
name
]
=
c
266
end
267
return
copy_node
(
c
)
268
end
269 270
function
nodeinjections
.
stoplayer
(
)
271
if
not
stop
then
272
stop
=
register
(
pageliteral
(
s_emc
)
)
273
end
274
return
copy_node
(
stop
)
275
end
276 277
-- experimental stacker code (slow, can be optimized): !!!! TEST CODE !!!!
278 279
local
values
=
viewerlayers
.
values
280
local
startlayer
=
codeinjections
.
startlayer
281
local
stoplayer
=
codeinjections
.
stoplayer
282 283
function
nodeinjections
.
startstackedlayer
(
s
,
t
,
first
,
last
)
284
local
r
=
{
}
285
for
i
=
first
,
last
do
286
r
[
#
r
+
1
]
=
startlayer
(
values
[
t
[
i
]
]
)
287
end
288
r
=
concat
(
r
,
"
"
)
289
return
pageliteral
(
r
)
290
end
291 292
function
nodeinjections
.
stopstackedlayer
(
s
,
t
,
first
,
last
)
293
local
r
=
{
}
294
for
i
=
last
,
first
,
-1
do
295
r
[
#
r
+
1
]
=
stoplayer
(
)
296
end
297
r
=
concat
(
r
,
"
"
)
298
return
pageliteral
(
r
)
299
end
300 301
function
nodeinjections
.
changestackedlayer
(
s
,
t1
,
first1
,
last1
,
t2
,
first2
,
last2
)
302
local
r
=
{
}
303
for
i
=
last1
,
first1
,
-1
do
304
r
[
#
r
+
1
]
=
stoplayer
(
)
305
end
306
for
i
=
first2
,
last2
do
307
r
[
#
r
+
1
]
=
startlayer
(
values
[
t2
[
i
]
]
)
308
end
309
r
=
concat
(
r
,
"
"
)
310
return
pageliteral
(
r
)
311
end
312 313
-- transitions
314 315
local
pagetransitions
=
{
316
{
"
split
"
,
"
in
"
,
"
vertical
"
}
,
{
"
split
"
,
"
in
"
,
"
horizontal
"
}
,
317
{
"
split
"
,
"
out
"
,
"
vertical
"
}
,
{
"
split
"
,
"
out
"
,
"
horizontal
"
}
,
318
{
"
blinds
"
,
"
horizontal
"
}
,
{
"
blinds
"
,
"
vertical
"
}
,
319
{
"
box
"
,
"
in
"
}
,
{
"
box
"
,
"
out
"
}
,
320
{
"
wipe
"
,
"
east
"
}
,
{
"
wipe
"
,
"
west
"
}
,
{
"
wipe
"
,
"
north
"
}
,
{
"
wipe
"
,
"
south
"
}
,
321
{
"
dissolve
"
}
,
322
{
"
glitter
"
,
"
east
"
}
,
{
"
glitter
"
,
"
south
"
}
,
323
{
"
fly
"
,
"
in
"
,
"
east
"
}
,
{
"
fly
"
,
"
in
"
,
"
west
"
}
,
{
"
fly
"
,
"
in
"
,
"
north
"
}
,
{
"
fly
"
,
"
in
"
,
"
south
"
}
,
324
{
"
fly
"
,
"
out
"
,
"
east
"
}
,
{
"
fly
"
,
"
out
"
,
"
west
"
}
,
{
"
fly
"
,
"
out
"
,
"
north
"
}
,
{
"
fly
"
,
"
out
"
,
"
south
"
}
,
325
{
"
push
"
,
"
east
"
}
,
{
"
push
"
,
"
west
"
}
,
{
"
push
"
,
"
north
"
}
,
{
"
push
"
,
"
south
"
}
,
326
{
"
cover
"
,
"
east
"
}
,
{
"
cover
"
,
"
west
"
}
,
{
"
cover
"
,
"
north
"
}
,
{
"
cover
"
,
"
south
"
}
,
327
{
"
uncover
"
,
"
east
"
}
,
{
"
uncover
"
,
"
west
"
}
,
{
"
uncover
"
,
"
north
"
}
,
{
"
uncover
"
,
"
south
"
}
,
328
{
"
fade
"
}
,
329
}
330 331
local
mapping
=
{
332
split
=
{
"
S
"
,
pdfconstant
(
"
Split
"
)
}
,
333
blinds
=
{
"
S
"
,
pdfconstant
(
"
Blinds
"
)
}
,
334
box
=
{
"
S
"
,
pdfconstant
(
"
Box
"
)
}
,
335
wipe
=
{
"
S
"
,
pdfconstant
(
"
Wipe
"
)
}
,
336
dissolve
=
{
"
S
"
,
pdfconstant
(
"
Dissolve
"
)
}
,
337
glitter
=
{
"
S
"
,
pdfconstant
(
"
Glitter
"
)
}
,
338
replace
=
{
"
S
"
,
pdfconstant
(
"
R
"
)
}
,
339
fly
=
{
"
S
"
,
pdfconstant
(
"
Fly
"
)
}
,
340
push
=
{
"
S
"
,
pdfconstant
(
"
Push
"
)
}
,
341
cover
=
{
"
S
"
,
pdfconstant
(
"
Cover
"
)
}
,
342
uncover
=
{
"
S
"
,
pdfconstant
(
"
Uncover
"
)
}
,
343
fade
=
{
"
S
"
,
pdfconstant
(
"
Fade
"
)
}
,
344
horizontal
=
{
"
Dm
"
,
pdfconstant
(
"
H
"
)
}
,
345
vertical
=
{
"
Dm
"
,
pdfconstant
(
"
V
"
)
}
,
346
[
"
in
"
]
=
{
"
M
"
,
pdfconstant
(
"
I
"
)
}
,
347
out
=
{
"
M
"
,
pdfconstant
(
"
O
"
)
}
,
348
east
=
{
"
Di
"
,
0
}
,
349
north
=
{
"
Di
"
,
90
}
,
350
west
=
{
"
Di
"
,
180
}
,
351
south
=
{
"
Di
"
,
270
}
,
352
}
353 354
local
last
=
0
355 356
-- n: number, "stop", "reset", "random", "a,b,c" delay: number, "none"
357 358
function
codeinjections
.
setpagetransition
(
specification
)
359
local
n
,
delay
=
specification
.
n
,
specification
.
delay
360
if
not
n
or
n
=
=
"
"
then
361
return
-- let's forget about it
362
elseif
n
=
=
v_auto
then
363
if
last
>
=
#
pagetransitions
then
364
last
=
0
365
end
366
n
=
last
+
1
367
elseif
n
=
=
v_stop
then
368
return
369
elseif
n
=
=
v_reset
then
370
last
=
0
371
return
372
elseif
n
=
=
v_random
then
373
n
=
getrandom
(
"
transition
"
,
1
,
#
pagetransitions
)
374
else
375
n
=
tonumber
(
n
)
376
end
377
local
t
=
n
and
pagetransitions
[
n
]
or
pagetransitions
[
1
]
378
if
not
t
then
379
t
=
settings_to_array
(
n
)
380
end
381
if
t
and
#
t
>
0
then
382
local
d
=
pdfdictionary
(
)
383
for
i
=
1
,
#
t
do
384
local
m
=
mapping
[
t
[
i
]
]
385
d
[
m
[
1
]
]
=
m
[
2
]
386
end
387
delay
=
tonumber
(
delay
)
388
if
delay
and
delay
>
0
then
389
addtopageattributes
(
"
Dur
"
,
delay
)
390
end
391
addtopageattributes
(
"
Trans
"
,
d
)
392
end
393
end
394