lpdf-wid.lua /size: 28 Kb    last modification: 2020-07-01 14:35
1
if
not
modules
then
modules
=
{
}
end
modules
[
'
lpdf-wid
'
]
=
{
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
-- It's about time to give up on media in pdf and admit that pdf lost it to html.
10
-- First we had movies and sound, quite easy to deal with, but obsolete now. Then we
11
-- had renditions but they turned out to be unreliable from the start and look
12
-- obsolete too or at least they are bound to the (obsolete) flash technology for
13
-- rendering. They were already complex constructs. Now we have rich media which
14
-- instead of providing a robust future proof framework for general media types
15
-- again seems to depend on viewers built in (yes, also kind of obsolete) flash
16
-- technology, and we cannot expect this non-open technology to show up in open
17
-- browsers. So, in the end we can best just use links to external resources to be
18
-- future proof. Just look at the viewer preferences pane to see how fragile support
19
-- is. Interestingly u3d support is kind of built in, while e.g. mp4 support relies
20
-- on wrapping in swf. We used to stay ahead of the pack with support of the fancy
21
-- pdf features but it backfires and is not worth the trouble. And yes, for control
22
-- (even simple like starting and stopping videos) one has to revert to JavaScript,
23
-- the other fragile bit. And, now that adobe quits flash in 2020 we're without any
24
-- video anyway. Also, it won't play on all platforms and devices so let's wait for
25
-- html5 media in pdf then.
26 27
local
tonumber
,
next
=
tonumber
,
next
28
local
gmatch
,
gsub
,
find
,
lower
=
string
.
gmatch
,
string
.
gsub
,
string
.
find
,
string
.
lower
29
local
filenameonly
,
basefilename
,
filesuffix
,
addfilesuffix
=
file
.
nameonly
,
file
.
basename
,
file
.
suffix
,
file
.
addsuffix
30
local
isfile
,
modificationtime
=
lfs
.
isfile
,
lfs
.
modification
31
local
stripstring
=
string
.
strip
32
local
settings_to_array
=
utilities
.
parsers
.
settings_to_array
33
local
settings_to_hash
=
utilities
.
parsers
.
settings_to_hash
34
local
sortedhash
,
sortedkeys
=
table
.
sortedhash
,
table
.
sortedkeys
35 36
local
report_media
=
logs
.
reporter
(
"
backend
"
,
"
media
"
)
37
local
report_attachment
=
logs
.
reporter
(
"
backend
"
,
"
attachment
"
)
38 39
local
backends
=
backends
40
local
lpdf
=
lpdf
41
local
nodes
=
nodes
42
local
context
=
context
43 44
local
texgetcount
=
tex
.
getcount
45 46
local
nodeinjections
=
backends
.
pdf
.
nodeinjections
47
local
codeinjections
=
backends
.
pdf
.
codeinjections
48
local
registrations
=
backends
.
pdf
.
registrations
49 50
local
executers
=
structures
.
references
.
executers
51
local
variables
=
interfaces
.
variables
52 53
local
v_hidden
=
variables
.
hidden
54
local
v_auto
=
variables
.
auto
55
local
v_embed
=
variables
.
embed
56
local
v_max
=
variables
.
max
57
local
v_yes
=
variables
.
yes
58 59
local
pdfconstant
=
lpdf
.
constant
60
local
pdfnull
=
lpdf
.
null
61
local
pdfdictionary
=
lpdf
.
dictionary
62
local
pdfarray
=
lpdf
.
array
63
local
pdfreference
=
lpdf
.
reference
64
local
pdfunicode
=
lpdf
.
unicode
65
local
pdfstring
=
lpdf
.
string
66
local
pdfboolean
=
lpdf
.
boolean
67
local
pdfflushobject
=
lpdf
.
flushobject
68
local
pdfflushstreamobject
=
lpdf
.
flushstreamobject
69
local
pdfflushstreamfileobject
=
lpdf
.
flushstreamfileobject
70
local
pdfreserveobject
=
lpdf
.
reserveobject
71
local
pdfpagereference
=
lpdf
.
pagereference
72
local
pdfshareobjectreference
=
lpdf
.
shareobjectreference
73
local
pdfaction
=
lpdf
.
action
74
local
pdfborder
=
lpdf
.
border
75 76
local
pdftransparencyvalue
=
lpdf
.
transparencyvalue
77
local
pdfcolorvalues
=
lpdf
.
colorvalues
78 79
local
hpack_node
=
node
.
hpack
80
local
write_node
=
node
.
write
-- test context(...) instead
81 82
-- symbols
83 84
local
presets
=
{
}
-- xforms
85 86
local
function
registersymbol
(
name
,
n
)
87
presets
[
name
]
=
pdfreference
(
n
)
88
end
89 90
local
function
registeredsymbol
(
name
)
91
return
presets
[
name
]
92
end
93 94
local
function
presetsymbol
(
symbol
)
95
if
not
presets
[
symbol
]
then
96
context
.
predefinesymbol
{
symbol
}
97
end
98
end
99 100
local
function
presetsymbollist
(
list
)
101
if
list
then
102
for
symbol
in
gmatch
(
list
,
"
[^, ]+
"
)
do
103
presetsymbol
(
symbol
)
104
end
105
end
106
end
107 108
codeinjections
.
registersymbol
=
registersymbol
109
codeinjections
.
registeredsymbol
=
registeredsymbol
110
codeinjections
.
presetsymbol
=
presetsymbol
111
codeinjections
.
presetsymbollist
=
presetsymbollist
112 113
-- comments
114 115
-- local symbols = {
116
-- Addition = pdfconstant("NewParagraph"),
117
-- Attachment = pdfconstant("Attachment"),
118
-- Balloon = pdfconstant("Comment"),
119
-- Check = pdfconstant("Check Mark"),
120
-- CheckMark = pdfconstant("Check Mark"),
121
-- Circle = pdfconstant("Circle"),
122
-- Cross = pdfconstant("Cross"),
123
-- CrossHairs = pdfconstant("Cross Hairs"),
124
-- Graph = pdfconstant("Graph"),
125
-- InsertText = pdfconstant("Insert Text"),
126
-- New = pdfconstant("Insert"),
127
-- Paperclip = pdfconstant("Paperclip"),
128
-- RightArrow = pdfconstant("Right Arrow"),
129
-- RightPointer = pdfconstant("Right Pointer"),
130
-- Star = pdfconstant("Star"),
131
-- Tag = pdfconstant("Tag"),
132
-- Text = pdfconstant("Note"),
133
-- TextNote = pdfconstant("Text Note"),
134
-- UpArrow = pdfconstant("Up Arrow"),
135
-- UpLeftArrow = pdfconstant("Up-Left Arrow"),
136
-- }
137 138
local
attachment_symbols
=
{
139
Graph
=
pdfconstant
(
"
Graph
"
)
,
140
Paperclip
=
pdfconstant
(
"
Paperclip
"
)
,
141
Pushpin
=
pdfconstant
(
"
PushPin
"
)
,
142
}
143 144
attachment_symbols
.
PushPin
=
attachment_symbols
.
Pushpin
145
attachment_symbols
.
Default
=
attachment_symbols
.
Pushpin
146 147
function
lpdf
.
attachmentsymbols
(
)
148
return
sortedkeys
(
comment_symbols
)
149
end
150 151
local
comment_symbols
=
{
152
Comment
=
pdfconstant
(
"
Comment
"
)
,
153
Help
=
pdfconstant
(
"
Help
"
)
,
154
Insert
=
pdfconstant
(
"
Insert
"
)
,
155
Key
=
pdfconstant
(
"
Key
"
)
,
156
Newparagraph
=
pdfconstant
(
"
NewParagraph
"
)
,
157
Note
=
pdfconstant
(
"
Note
"
)
,
158
Paragraph
=
pdfconstant
(
"
Paragraph
"
)
,
159
}
160 161
comment_symbols
.
NewParagraph
=
Newparagraph
162
comment_symbols
.
Default
=
Note
163 164
function
lpdf
.
commentsymbols
(
)
165
return
sortedkeys
(
comment_symbols
)
166
end
167 168
local
function
analyzesymbol
(
symbol
,
collection
)
169
if
not
symbol
or
symbol
=
=
"
"
then
170
return
collection
and
collection
.
Default
,
nil
171
elseif
collection
and
collection
[
symbol
]
then
172
return
collection
[
symbol
]
,
nil
173
else
174
local
setn
,
setr
,
setd
175
local
set
=
settings_to_array
(
symbol
)
176
if
#
set
=
=
1
then
177
setn
,
setr
,
setd
=
set
[
1
]
,
set
[
1
]
,
set
[
1
]
178
elseif
#
set
=
=
2
then
179
setn
,
setr
,
setd
=
set
[
1
]
,
set
[
1
]
,
set
[
2
]
180
else
181
setn
,
setr
,
setd
=
set
[
1
]
,
set
[
2
]
,
set
[
3
]
182
end
183
local
appearance
=
pdfdictionary
{
184
N
=
setn
and
registeredsymbol
(
setn
)
,
185
R
=
setr
and
registeredsymbol
(
setr
)
,
186
D
=
setd
and
registeredsymbol
(
setd
)
,
187
}
188
local
appearanceref
=
pdfshareobjectreference
(
appearance
)
189
return
nil
,
appearanceref
190
end
191
end
192 193
local
function
analyzenormalsymbol
(
symbol
)
194
local
appearance
=
pdfdictionary
{
195
N
=
registeredsymbol
(
symbol
)
,
196
}
197
local
appearanceref
=
pdfshareobjectreference
(
appearance
)
198
return
appearanceref
199
end
200 201
codeinjections
.
analyzesymbol
=
analyzesymbol
202
codeinjections
.
analyzenormalsymbol
=
analyzenormalsymbol
203 204
local
function
analyzelayer
(
layer
)
205
-- todo: (specification.layer ~= "" and pdfreference(specification.layer)) or nil, -- todo: ref to layer
206
end
207 208
local
function
analyzecolor
(
colorvalue
,
colormodel
)
209
local
cvalue
=
colorvalue
and
tonumber
(
colorvalue
)
210
local
cmodel
=
colormodel
and
tonumber
(
colormodel
)
or
3
211
return
cvalue
and
pdfarray
{
pdfcolorvalues
(
cmodel
,
cvalue
)
}
or
nil
212
end
213 214
local
function
analyzetransparency
(
transparencyvalue
)
215
local
tvalue
=
transparencyvalue
and
tonumber
(
transparencyvalue
)
216
return
tvalue
and
pdftransparencyvalue
(
tvalue
)
or
nil
217
end
218 219
-- Attachments
220 221
local
nofattachments
=
0
222
local
attachments
=
{
}
223
local
filestreams
=
{
}
224
local
referenced
=
{
}
225
local
ignorereferenced
=
true
-- fuzzy pdf spec .. twice in attachment list, can become an option
226
local
tobesavedobjrefs
=
utilities
.
storage
.
allocate
(
)
227
local
collectedobjrefs
=
utilities
.
storage
.
allocate
(
)
228
local
permitted
=
true
229
local
enabled
=
true
230 231
function
codeinjections
.
setattachmentsupport
(
option
)
232
if
option
=
=
false
then
233
permitted
=
false
234
enabled
=
false
235
end
236
end
237 238
local
fileobjreferences
=
{
239
collected
=
collectedobjrefs
,
240
tobesaved
=
tobesavedobjrefs
,
241
}
242 243
job
.
fileobjreferences
=
fileobjreferences
244 245
local
function
initializer
(
)
246
collectedobjrefs
=
job
.
fileobjreferences
.
collected
or
{
}
247
tobesavedobjrefs
=
job
.
fileobjreferences
.
tobesaved
or
{
}
248
end
249 250
job
.
register
(
'
job.fileobjreferences.collected
'
,
tobesavedobjrefs
,
initializer
)
251 252
local
function
flushembeddedfiles
(
)
253
if
enabled
and
next
(
filestreams
)
then
254
local
e
=
pdfarray
(
)
255
local
f
=
pdfarray
(
)
256
for
tag
,
reference
in
sortedhash
(
filestreams
)
do
257
if
not
reference
then
258
report_attachment
(
"
unreferenced file, tag %a
"
,
tag
)
259
elseif
referenced
[
tag
]
=
=
"
hidden
"
then
260
e
[
#
e
+
1
]
=
pdfstring
(
tag
)
261
e
[
#
e
+
1
]
=
reference
-- already a reference
262
f
[
#
f
+
1
]
=
reference
-- collect all file description references
263
else
264
-- messy spec ... when annot not in named else twice in menu list acrobat
265
f
[
#
f
+
1
]
=
reference
266
end
267
end
268
if
#
e
>
0
then
269
lpdf
.
addtonames
(
"
EmbeddedFiles
"
,
pdfreference
(
pdfflushobject
(
pdfdictionary
{
Names
=
e
}
)
)
)
270
end
271
if
#
f
>
0
then
-- PDF/A-2|3: all associated files must have a relationship to the PDF document (global or part)
272
lpdf
.
addtocatalog
(
"
AF
"
,
pdfreference
(
pdfflushobject
(
f
)
)
)
-- global (Catalog)
273
end
274
end
275
end
276 277
lpdf
.
registerdocumentfinalizer
(
flushembeddedfiles
,
"
embeddedfiles
"
)
278 279
function
codeinjections
.
embedfile
(
specification
)
280
if
enabled
then
281
local
data
=
specification
.
data
282
local
filename
=
specification
.
file
283
local
name
=
specification
.
name
or
"
"
284
local
title
=
specification
.
title
or
"
"
285
local
hash
=
specification
.
hash
or
filename
286
local
keepdir
=
specification
.
keepdir
-- can change
287
local
usedname
=
specification
.
usedname
288
local
filetype
=
specification
.
filetype
289
local
compress
=
specification
.
compress
290
local
mimetype
=
specification
.
mimetype
or
specification
.
mime
291
if
filename
=
=
"
"
then
292
filename
=
nil
293
end
294
if
compress
=
=
nil
then
295
compress
=
true
296
end
297
if
data
then
298
local
r
=
filestreams
[
hash
]
299
if
r
=
=
false
then
300
return
nil
301
elseif
r
then
302
return
r
303
elseif
not
filename
then
304
filename
=
specification
.
tag
305
if
not
filename
or
filename
=
=
"
"
then
306
filename
=
specification
.
registered
307
end
308
if
not
filename
or
filename
=
=
"
"
then
309
filename
=
hash
310
end
311
end
312
else
313
if
not
filename
then
314
return
nil
315
end
316
local
r
=
filestreams
[
hash
]
317
if
r
=
=
false
then
318
return
nil
319
elseif
r
then
320
return
r
321
else
322
local
foundname
=
resolvers
.
findbinfile
(
filename
)
or
"
"
323
if
foundname
=
=
"
"
or
not
isfile
(
foundname
)
then
324
filestreams
[
filename
]
=
false
325
return
nil
326
else
327
specification
.
foundname
=
foundname
328
end
329
end
330
end
331
-- needs to be cleaned up:
332
usedname
=
usedname
~
=
"
"
and
usedname
or
filename
or
name
333
local
basename
=
keepdir
=
=
true
and
usedname
or
basefilename
(
usedname
)
334
local
basename
=
gsub
(
basename
,
"
%./
"
,
"
"
)
335
local
savename
=
name
~
=
"
"
and
name
or
basename
336
local
foundname
=
specification
.
foundname
or
filename
337
if
not
filetype
or
filetype
=
=
"
"
then
338
filetype
=
name
and
(
filename
and
filesuffix
(
filename
)
)
or
"
txt
"
339
end
340
savename
=
addfilesuffix
(
savename
,
filetype
)
-- type is mandate for proper working in viewer
341
local
a
=
pdfdictionary
{
342
Type
=
pdfconstant
(
"
EmbeddedFile
"
)
,
343
Subtype
=
mimetype
and
mimetype
~
=
"
"
and
pdfconstant
(
mimetype
)
or
nil
,
344
}
345
local
f
346
if
data
then
347
f
=
pdfflushstreamobject
(
data
,
a
)
348
specification
.
data
=
true
-- signal that still data but already flushed
349
else
350
local
attributes
=
lfs
.
attributes
(
foundname
)
351
local
modification
=
modificationtime
(
foundname
)
352
a
.
Params
=
{
353
Size
=
attributes
.
size
,
354
ModDate
=
lpdf
.
pdftimestamp
(
modification
)
,
355
}
356
f
=
pdfflushstreamfileobject
(
foundname
,
a
,
compress
)
357
end
358
local
d
=
pdfdictionary
{
359
Type
=
pdfconstant
(
"
Filespec
"
)
,
360
F
=
pdfstring
(
savename
)
,
361
-- UF = pdfstring(savename),
362
UF
=
pdfunicode
(
savename
)
,
363
EF
=
pdfdictionary
{
F
=
pdfreference
(
f
)
}
,
364
Desc
=
title
~
=
"
"
and
pdfunicode
(
title
)
or
nil
,
365
AFRelationship
=
pdfconstant
(
"
Unspecified
"
)
,
-- Supplement, Data, Source, Alternative, Data
366
}
367
local
r
=
pdfreference
(
pdfflushobject
(
d
)
)
368
filestreams
[
hash
]
=
r
369
return
r
370
end
371
end
372 373
function
nodeinjections
.
attachfile
(
specification
)
374
if
enabled
then
375
local
registered
=
specification
.
registered
or
"
<unset>
"
376
local
data
=
specification
.
data
377
local
hash
378
local
filename
379
if
data
then
380
hash
=
md5
.
HEX
(
data
)
381
else
382
filename
=
specification
.
file
383
if
not
filename
or
filename
=
=
"
"
then
384
report_attachment
(
"
no file specified, using registered %a instead
"
,
registered
)
385
filename
=
registered
386
specification
.
file
=
registered
387
end
388
local
foundname
=
resolvers
.
findbinfile
(
filename
)
or
"
"
389
if
foundname
=
=
"
"
or
not
isfile
(
foundname
)
then
390
report_attachment
(
"
invalid filename %a, ignoring registered %a
"
,
filename
,
registered
)
391
return
nil
392
else
393
specification
.
foundname
=
foundname
394
end
395
hash
=
filename
396
end
397
specification
.
hash
=
hash
398
nofattachments
=
nofattachments
+
1
399
local
registered
=
specification
.
registered
or
"
"
400
local
title
=
specification
.
title
or
"
"
401
local
subtitle
=
specification
.
subtitle
or
"
"
402
local
author
=
specification
.
author
or
"
"
403
local
onlyname
=
filename
and
filenameonly
(
filename
)
or
"
"
404
if
registered
=
=
"
"
then
405
registered
=
filename
406
end
407
if
author
=
=
"
"
and
title
~
=
"
"
then
408
author
=
title
409
title
=
onlyname
or
"
"
410
end
411
if
author
=
=
"
"
then
412
author
=
onlyname
or
"
<unknown>
"
413
end
414
if
title
=
=
"
"
then
415
title
=
registered
416
end
417
if
title
=
=
"
"
and
filename
then
418
title
=
onlyname
419
end
420
local
aref
=
attachments
[
registered
]
421
if
not
aref
then
422
aref
=
codeinjections
.
embedfile
(
specification
)
423
attachments
[
registered
]
=
aref
424
end
425
local
reference
=
specification
.
reference
426
if
reference
and
aref
then
427
tobesavedobjrefs
[
reference
]
=
aref
[
1
]
428
end
429
if
not
aref
then
430
report_attachment
(
"
skipping attachment, registered %a
"
,
registered
)
431
-- already reported
432
elseif
specification
.
method
=
=
v_hidden
then
433
referenced
[
hash
]
=
"
hidden
"
434
else
435
referenced
[
hash
]
=
"
annotation
"
436
local
name
,
appearance
=
analyzesymbol
(
specification
.
symbol
,
attachment_symbols
)
437
local
flags
=
specification
.
flags
or
0
-- to keep it expandable
438
local
d
=
pdfdictionary
{
439
Subtype
=
pdfconstant
(
"
FileAttachment
"
)
,
440
FS
=
aref
,
441
Contents
=
pdfunicode
(
title
)
,
442
Name
=
name
,
443
NM
=
pdfstring
(
"
attachment:
"
.
.
nofattachments
)
,
444
T
=
author
~
=
"
"
and
pdfunicode
(
author
)
or
nil
,
445
Subj
=
subtitle
~
=
"
"
and
pdfunicode
(
subtitle
)
or
nil
,
446
C
=
analyzecolor
(
specification
.
colorvalue
,
specification
.
colormodel
)
,
447
CA
=
analyzetransparency
(
specification
.
transparencyvalue
)
,
448
AP
=
appearance
,
449
OC
=
analyzelayer
(
specification
.
layer
)
,
450
-- F = pdfnull(), -- another rediculous need to satisfy validation
451
F
=
bit32
.
band
(
bit32
.
bor
(
flags
,
4
)
,
(
1023
-1
-2
-32
-256
)
)
,
-- set 3, clear 1,2,6,9; PDF 32000-1, p385
452
}
453
local
width
=
specification
.
width
or
0
454
local
height
=
specification
.
height
or
0
455
local
depth
=
specification
.
depth
or
0
456
local
box
=
hpack_node
(
nodeinjections
.
annotation
(
width
,
height
,
depth
,
d
(
)
)
)
457
box
.
width
=
width
458
box
.
height
=
height
459
box
.
depth
=
depth
460
return
box
461
end
462
end
463
end
464 465
function
codeinjections
.
attachmentid
(
filename
)
-- not used in context
466
return
filestreams
[
filename
]
467
end
468 469
-- Comments
470 471
local
nofcomments
=
0
472
local
usepopupcomments
=
false
473 474
local
defaultattributes
=
{
475
[
"
xmlns
"
]
=
"
http://www.w3.org/1999/xhtml
"
,
476
[
"
xmlns:xfa
"
]
=
"
http://www.xfa.org/schema/xfa-data/1.0/
"
,
477
[
"
xfa:contentType
"
]
=
"
text/html
"
,
478
[
"
xfa:APIVersion
"
]
=
"
Acrobat:8.0.0
"
,
479
[
"
xfa:spec
"
]
=
"
2.4
"
,
480
}
481 482
local
function
checkcontent
(
text
,
option
)
483
if
option
and
option
.
xml
then
484
local
root
=
xml
.
convert
(
text
)
485
if
root
and
not
root
.
er
then
486
xml
.
checkbom
(
root
)
487
local
body
=
xml
.
first
(
root
,
"
/body
"
)
488
if
body
then
489
local
at
=
body
.
at
490
for
k
,
v
in
next
,
defaultattributes
do
491
if
not
at
[
k
]
then
492
at
[
k
]
=
v
493
end
494
end
495
-- local content = xml.textonly(root)
496
local
richcontent
=
xml
.
tostring
(
root
)
497
return
nil
,
pdfunicode
(
richcontent
)
498
end
499
end
500
end
501
return
pdfunicode
(
text
)
502
end
503 504
function
nodeinjections
.
comment
(
specification
)
-- brrr: seems to be done twice
505
nofcomments
=
nofcomments
+
1
506
local
text
=
specification
.
data
or
"
"
507
if
specification
.
space
~
=
v_yes
then
508
text
=
stripstring
(
text
)
509
text
=
gsub
(
text
,
"
[\n\r] *
"
,
"
\n
"
)
510
end
511
text
=
gsub
(
text
,
"
\r
"
,
"
\n
"
)
512
local
name
,
appearance
=
analyzesymbol
(
specification
.
symbol
,
comment_symbols
)
513
local
tag
=
specification
.
tag
or
"
"
-- this is somewhat messy as recent
514
local
title
=
specification
.
title
or
"
"
-- versions of acrobat see the title
515
local
subtitle
=
specification
.
subtitle
or
"
"
-- as author
516
local
author
=
specification
.
author
or
"
"
517
local
option
=
settings_to_hash
(
specification
.
option
or
"
"
)
518
if
author
~
=
"
"
then
519
if
subtitle
=
=
"
"
then
520
subtitle
=
title
521
elseif
title
~
=
"
"
then
522
subtitle
=
subtitle
.
.
"
,
"
.
.
title
523
end
524
title
=
author
525
end
526
if
title
=
=
"
"
then
527
title
=
tag
528
end
529
local
content
,
richcontent
=
checkcontent
(
text
,
option
)
530
local
d
=
pdfdictionary
{
531
Subtype
=
pdfconstant
(
"
Text
"
)
,
532
Open
=
option
[
v_max
]
and
pdfboolean
(
true
)
or
nil
,
533
Contents
=
content
,
534
RC
=
richcontent
,
535
T
=
title
~
=
"
"
and
pdfunicode
(
title
)
or
nil
,
536
Subj
=
subtitle
~
=
"
"
and
pdfunicode
(
subtitle
)
or
nil
,
537
C
=
analyzecolor
(
specification
.
colorvalue
,
specification
.
colormodel
)
,
538
CA
=
analyzetransparency
(
specification
.
transparencyvalue
)
,
539
OC
=
analyzelayer
(
specification
.
layer
)
,
540
Name
=
name
,
541
NM
=
pdfstring
(
"
comment:
"
.
.
nofcomments
)
,
542
AP
=
appearance
,
543
}
544
local
width
=
specification
.
width
or
0
545
local
height
=
specification
.
height
or
0
546
local
depth
=
specification
.
depth
or
0
547
local
box
548
if
usepopupcomments
then
549
-- rather useless as we can hide/vide
550
local
nd
=
pdfreserveobject
(
)
551
local
nc
=
pdfreserveobject
(
)
552
local
c
=
pdfdictionary
{
553
Subtype
=
pdfconstant
(
"
Popup
"
)
,
554
Parent
=
pdfreference
(
nd
)
,
555
}
556
d
.
Popup
=
pdfreference
(
nc
)
557
box
=
hpack_node
(
558
nodeinjections
.
annotation
(
0
,
0
,
0
,
d
(
)
,
nd
)
,
559
nodeinjections
.
annotation
(
width
,
height
,
depth
,
c
(
)
,
nc
)
560
)
561
else
562
box
=
hpack_node
(
nodeinjections
.
annotation
(
width
,
height
,
depth
,
d
(
)
)
)
563
end
564
box
.
width
=
width
-- redundant
565
box
.
height
=
height
-- redundant
566
box
.
depth
=
depth
-- redundant
567
return
box
568
end
569 570
-- rendering stuff
571
--
572
-- object_1 -> <</Type /Rendition /S /MR /C << /Type /MediaClip ... >> >>
573
-- object_2 -> <</Type /Rendition /S /MR /C << /Type /MediaClip ... >> >>
574
-- rendering -> <</Type /Rendition /S /MS [objref_1 objref_2]>>
575
--
576
-- we only work foreward here (currently)
577
-- annotation is to be packed at the tex end
578 579
-- aiff audio/aiff
580
-- au audio/basic
581
-- avi video/avi
582
-- mid audio/midi
583
-- mov video/quicktime
584
-- mp3 audio/x-mp3 (mpeg)
585
-- mp4 audio/mp4
586
-- mp4 video/mp4
587
-- mpeg video/mpeg
588
-- smil application/smil
589
-- swf application/x-shockwave-flash
590 591
-- P media play parameters (evt /BE for controls etc
592
-- A boolean (audio)
593
-- C boolean (captions)
594
-- O boolean (overdubs)
595
-- S boolean (subtitles)
596
-- PL pdfconstant("ADBE_MCI"),
597 598
-- F = flags,
599
-- T = title,
600
-- Contents = rubish,
601
-- AP = irrelevant,
602 603
-- sound is different, no window (or zero) so we need to collect them and
604
-- force them if not set
605 606
local
ms
,
mu
,
mf
=
{
}
,
{
}
,
{
}
607 608
local
function
delayed
(
label
)
609
local
a
=
pdfreserveobject
(
)
610
mu
[
label
]
=
a
611
return
pdfreference
(
a
)
612
end
613 614
local
function
insertrenderingwindow
(
specification
)
615
local
label
=
specification
.
label
616
-- local openpage = specification.openpage
617
-- local closepage = specification.closepage
618
if
specification
.
option
=
=
v_auto
then
619
if
openpageaction
then
620
-- \handlereferenceactions{\v!StartRendering{#2}}
621
end
622
if
closepageaction
then
623
-- \handlereferenceactions{\v!StopRendering {#2}}
624
end
625
end
626
local
actions
=
nil
627
if
openpage
or
closepage
then
628
actions
=
pdfdictionary
{
629
PO
=
(
openpage
and
lpdfaction
(
openpage
)
)
or
nil
,
630
PC
=
(
closepage
and
lpdfaction
(
closepage
)
)
or
nil
,
631
}
632
end
633
local
page
=
tonumber
(
specification
.
page
)
or
texgetcount
(
"
realpageno
"
)
-- todo
634
local
r
=
mu
[
label
]
or
pdfreserveobject
(
)
-- why the reserve here?
635
local
a
=
pdfdictionary
{
636
S
=
pdfconstant
(
"
Rendition
"
)
,
637
R
=
mf
[
label
]
,
638
OP
=
0
,
639
AN
=
pdfreference
(
r
)
,
640
}
641
local
bs
,
bc
=
pdfborder
(
)
642
local
d
=
pdfdictionary
{
643
Subtype
=
pdfconstant
(
"
Screen
"
)
,
644
P
=
pdfreference
(
pdfpagereference
(
page
)
)
,
645
A
=
a
,
-- needed in order to make the annotation clickable (i.e. don't bark)
646
Border
=
bs
,
647
C
=
bc
,
648
AA
=
actions
,
649
}
650
local
width
=
specification
.
width
or
0
651
local
height
=
specification
.
height
or
0
652
if
height
=
=
0
or
width
=
=
0
then
653
-- todo: sound needs no window
654
end
655
write_node
(
nodeinjections
.
annotation
(
width
,
height
,
0
,
d
(
)
,
r
)
)
-- save ref
656
return
pdfreference
(
r
)
657
end
658 659
-- some dictionaries can have a MH (must honor) or BE (best effort) capsule
660 661
local
function
insertrendering
(
specification
)
662
local
label
=
specification
.
label
663
local
option
=
settings_to_hash
(
specification
.
option
)
664
if
not
mf
[
label
]
then
665
local
filename
=
specification
.
filename
666
local
isurl
=
find
(
filename
,
"
://
"
,
1
,
true
)
667
local
mimetype
=
specification
.
mimetype
or
specification
.
mime
668
-- local start = pdfdictionary {
669
-- Type = pdfconstant("MediaOffset"),
670
-- S = pdfconstant("T"), -- time
671
-- T = pdfdictionary { -- time
672
-- Type = pdfconstant("Timespan"),
673
-- S = pdfconstant("S"),
674
-- V = 3, -- time in seconds
675
-- },
676
-- }
677
-- local start = pdfdictionary {
678
-- Type = pdfconstant("MediaOffset"),
679
-- S = pdfconstant("F"), -- frame
680
-- F = 100 -- framenumber
681
-- }
682
-- local start = pdfdictionary {
683
-- Type = pdfconstant("MediaOffset"),
684
-- S = pdfconstant("M"), -- mark
685
-- M = "somemark",
686
-- }
687
-- local parameters = pdfdictionary {
688
-- BE = pdfdictionary {
689
-- B = start,
690
-- }
691
-- }
692
-- local parameters = pdfdictionary {
693
-- Type = pdfconstant(MediaPermissions),
694
-- TF = pdfstring("TEMPALWAYS") }, -- TEMPNEVER TEMPEXTRACT TEMPACCESS TEMPALWAYS
695
-- }
696
local
descriptor
=
pdfdictionary
{
697
Type
=
pdfconstant
(
"
Filespec
"
)
,
698
F
=
filename
,
699
}
700
if
isurl
then
701
descriptor
.
FS
=
pdfconstant
(
"
URL
"
)
702
elseif
option
[
v_embed
]
then
703
descriptor
.
EF
=
codeinjections
.
embedfile
{
704
file
=
filename
,
705
mimetype
=
mimetype
,
-- yes or no
706
compress
=
false
,
707
}
708
end
709
local
clip
=
pdfdictionary
{
710
Type
=
pdfconstant
(
"
MediaClip
"
)
,
711
S
=
pdfconstant
(
"
MCD
"
)
,
712
N
=
label
,
713
CT
=
mimetype
,
714
Alt
=
pdfarray
{
"
"
,
"
file not found
"
}
,
-- language id + message
715
D
=
pdfreference
(
pdfflushobject
(
descriptor
)
)
,
716
-- P = pdfreference(pdfflushobject(parameters)),
717
}
718
local
rendition
=
pdfdictionary
{
719
Type
=
pdfconstant
(
"
Rendition
"
)
,
720
S
=
pdfconstant
(
"
MR
"
)
,
721
N
=
label
,
722
C
=
pdfreference
(
pdfflushobject
(
clip
)
)
,
723
}
724
mf
[
label
]
=
pdfreference
(
pdfflushobject
(
rendition
)
)
725
end
726
end
727 728
local
function
insertrenderingobject
(
specification
)
-- todo
729
local
label
=
specification
.
label
730
if
not
mf
[
label
]
then
731
report_media
(
"
unknown medium, label %a
"
,
label
)
732
local
clip
=
pdfdictionary
{
-- does not work that well one level up
733
Type
=
pdfconstant
(
"
MediaClip
"
)
,
734
S
=
pdfconstant
(
"
MCD
"
)
,
735
N
=
label
,
736
D
=
pdfreference
(
unknown
)
,
-- not label but objectname, hm .. todo?
737
}
738
local
rendition
=
pdfdictionary
{
739
Type
=
pdfconstant
(
"
Rendition
"
)
,
740
S
=
pdfconstant
(
"
MR
"
)
,
741
N
=
label
,
742
C
=
pdfreference
(
pdfflushobject
(
clip
)
)
,
743
}
744
mf
[
label
]
=
pdfreference
(
pdfflushobject
(
rendition
)
)
745
end
746
end
747 748
function
codeinjections
.
processrendering
(
label
)
749
local
specification
=
interactions
.
renderings
.
rendering
(
label
)
750
if
not
specification
then
751
-- error
752
elseif
specification
.
type
=
=
"
external
"
then
753
insertrendering
(
specification
)
754
else
755
insertrenderingobject
(
specification
)
756
end
757
end
758 759
function
codeinjections
.
insertrenderingwindow
(
specification
)
760
local
label
=
specification
.
label
761
codeinjections
.
processrendering
(
label
)
762
ms
[
label
]
=
insertrenderingwindow
(
specification
)
763
end
764 765
local
function
set
(
operation
,
arguments
)
766
codeinjections
.
processrendering
(
arguments
)
767
return
pdfdictionary
{
768
S
=
pdfconstant
(
"
Rendition
"
)
,
769
OP
=
operation
,
770
R
=
mf
[
arguments
]
,
771
AN
=
ms
[
arguments
]
or
delayed
(
arguments
)
,
772
}
773
end
774 775
function
executers
.
startrendering
(
arguments
)
return
set
(
0
,
arguments
)
end
776
function
executers
.
stoprendering
(
arguments
)
return
set
(
1
,
arguments
)
end
777
function
executers
.
pauserendering
(
arguments
)
return
set
(
2
,
arguments
)
end
778
function
executers
.
resumerendering
(
arguments
)
return
set
(
3
,
arguments
)
end
779