1if 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
10
11local tostring , tonumber , next = tostring , tonumber , next
12local concat = table . concat
13local formatters = string . formatters
14local settings_to_array = utilities . parsers . settings_to_array
15local getrandom = utilities . randomizer . get
16
17local backends , lpdf , nodes , node = backends , lpdf , nodes , node
18
19local nodeinjections = backends . pdf . nodeinjections
20local codeinjections = backends . pdf . codeinjections
21local registrations = backends . pdf . registrations
22local viewerlayers = attributes . viewerlayers
23
24local references = structures . references
25
26references . executers = references . executers or { }
27local executers = references . executers
28
29local variables = interfaces . variables
30
31local v_no = variables . no
32local v_yes = variables . yes
33local v_start = variables . start
34local v_stop = variables . stop
35local v_reset = variables . reset
36local v_auto = variables . auto
37local v_random = variables . random
38
39local pdfconstant = lpdf . constant
40local pdfdictionary = lpdf . dictionary
41local pdfarray = lpdf . array
42local pdfreference = lpdf . reference
43local pdfflushobject = lpdf . flushobject
44local pdfreserveobject = lpdf . reserveobject
45
46local addtopageattributes = lpdf . addtopageattributes
47local addtopageresources = lpdf . addtopageresources
48local addtocatalog = lpdf . addtocatalog
49
50local escaped = lpdf . escaped
51
52local nuts = nodes . nuts
53local copy_node = nuts . copy
54
55local nodepool = nuts . pool
56local register = nodepool . register
57local pageliteral = nodepool . pageliteral
58
59local pdf_ocg = pdfconstant ( " OCG " )
60local pdf_ocmd = pdfconstant ( " OCMD " )
61local pdf_off = pdfconstant ( " OFF " )
62local pdf_on = pdfconstant ( " ON " )
63local pdf_view = pdfconstant ( " View " )
64local pdf_design = pdfconstant ( " Design " )
65local pdf_toggle = pdfconstant ( " Toggle " )
66local pdf_setocgstate = pdfconstant ( " SetOCGState " )
67
68local pdf_print = {
69 [ v_yes ] = pdfdictionary { PrintState = pdf_on } ,
70 [ v_no ] = pdfdictionary { PrintState = pdf_off } ,
71}
72
73local pdf_intent = {
74 [ v_yes ] = pdf_view ,
75 [ v_no ] = pdf_design ,
76}
77
78local pdf_export = {
79 [ v_yes ] = pdf_on ,
80 [ v_no ] = pdf_off ,
81}
82
83
84
85
86
87
88
89local pdfln , pdfld = { } , { }
90local textlayers , hidelayers , videlayers = pdfarray ( ) , pdfarray ( ) , pdfarray ( )
91local pagelayers , pagelayersreference , cache = nil , nil , { }
92local alphabetic = { }
93
94local escapednames = table . setmetatableindex ( function ( t , k )
95 local v = escaped ( k )
96 t [ k ] = v
97 return v
98end )
99
100local specifications = { }
101local initialized = { }
102
103function 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
110end
111
112local function useviewerlayer ( name )
113 if not environment . initex and not initialized [ name ] then
114 local specification = specifications [ name ]
115 if specification then
116 specifications [ name ] = nil
117 initialized [ name ] = true
118 if not pagelayers then
119 pagelayers = pdfdictionary ( )
120 pagelayersreference = pdfreserveobject ( )
121 end
122 local tag = specification . tag
123
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 ] ,
131 Print = pdf_print [ specification . printable or v_yes ] ,
132 Export = pdf_export [ specification . export or v_yes ] ,
133 } ,
134 }
135 cache [ # cache + 1 ] = { nn , nd }
136 pdfln [ tag ] = nr
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
153 else
154
155 end
156 end
157end
158
159codeinjections . useviewerlayer = useviewerlayer
160
161local 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
169end
170
171lpdf . layerreference = layerreference
172
173local 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
183 local sortedlayers = { }
184 for k , v in table . sortedhash ( alphabetic ) do
185 sortedlayers [ # sortedlayers + 1 ] = v
186 end
187 local d = pdfdictionary {
188 OCGs = textlayers ,
189 D = pdfdictionary {
190 Name = " Document " ,
191
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
209end
210
211local function flushpagelayers ( )
212 if pagelayers then
213 addtopageresources ( " Properties " , pdfreference ( pagelayersreference ) )
214 end
215end
216
217lpdf . registerpagefinalizer ( flushpagelayers , " layers " )
218lpdf . registerdocumentfinalizer ( flushtextlayers , " layers " )
219
220local function setlayer ( what , arguments )
221
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 }
234end
235
236function executers . hidelayer ( arguments ) return setlayer ( pdf_off , arguments ) end
237function executers . videlayer ( arguments ) return setlayer ( pdf_on , arguments ) end
238function executers . togglelayer ( arguments ) return setlayer ( pdf_toggle , arguments ) end
239
240
241
242local f_bdc = formatters [ " /OC /%s BDC " ]
243local s_emc = " EMC "
244
245function codeinjections . startlayer ( name )
246 if not name then
247 name = " unknown "
248 end
249 useviewerlayer ( name )
250 return f_bdc ( escapednames [ name ] )
251end
252
253function codeinjections . stoplayer ( name )
254 return s_emc
255end
256
257local cache = { }
258local stop = nil
259
260function 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 )
268end
269
270function nodeinjections . stoplayer ( )
271 if not stop then
272 stop = register ( pageliteral ( s_emc ) )
273 end
274 return copy_node ( stop )
275end
276
277
278
279local values = viewerlayers . values
280local startlayer = codeinjections . startlayer
281local stoplayer = codeinjections . stoplayer
282
283function 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 )
290end
291
292function 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 )
299end
300
301function 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 )
311end
312
313
314
315local 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
331local 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
354local last = 0
355
356
357
358function codeinjections . setpagetransition ( specification )
359 local n , delay = specification . n , specification . delay
360 if not n or n = = " " then
361 return
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
393end
394 |