1if not modules then modules = { } end modules [ ' lpdf-ini ' ] = {
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 setmetatable , getmetatable , type , next , tostring , tonumber , rawset = setmetatable , getmetatable , type , next , tostring , tonumber , rawset
12local char , byte , format , gsub , concat , match , sub , gmatch = string . char , string . byte , string . format , string . gsub , table . concat , string . match , string . sub , string . gmatch
13local utfchar , utfbyte , utfvalues = utf . char , utf . byte , utf . values
14local sind , cosd , max , min = math . sind , math . cosd , math . max , math . min
15local sort , sortedhash = table . sort , table . sortedhash
16local P , C , R , S , Cc , Cs , V = lpeg . P , lpeg . C , lpeg . R , lpeg . S , lpeg . Cc , lpeg . Cs , lpeg . V
17local lpegmatch , lpegpatterns = lpeg . match , lpeg . patterns
18local formatters = string . formatters
19local isboolean = string . is_boolean
20local rshift = bit32 . rshift
21local osdate , ostime = os . date , os . time
22
23local report_objects = logs . reporter ( " backend " , " objects " )
24local report_finalizing = logs . reporter ( " backend " , " finalizing " )
25local report_blocked = logs . reporter ( " backend " , " blocked " )
26
27local implement = interfaces . implement
28
29local context = context
30
31
32
33
34
35pdf = type ( pdf ) = = " table " and pdf or { }
36local factor = number . dimenfactors . bp
37
38local codeinjections = { }
39local nodeinjections = { }
40
41local backends = backends
42
43local pdfbackend = {
44 comment = " backend for directly generating pdf output " ,
45 nodeinjections = nodeinjections ,
46 codeinjections = codeinjections ,
47 registrations = { } ,
48 tables = { } ,
49}
50
51backends . pdf = pdfbackend
52
53lpdf = lpdf or { }
54local lpdf = lpdf
55lpdf . flags = lpdf . flags or { }
56
57local trace_finalizers = false trackers . register ( " backend.finalizers " , function ( v ) trace_finalizers = v end )
58local trace_resources = false trackers . register ( " backend.resources " , function ( v ) trace_resources = v end )
59local trace_objects = false trackers . register ( " backend.objects " , function ( v ) trace_objects = v end )
60local trace_details = false trackers . register ( " backend.details " , function ( v ) trace_details = v end )
61
62do
63
64 local pdfsetmajorversion , pdfsetminorversion , pdfgetmajorversion , pdfgetminorversion
65 local pdfsetcompresslevel , pdfsetobjectcompresslevel , pdfgetcompresslevel , pdfgetobjectcompresslevel
66 local pdfsetsuppressoptionalinfo , pdfsetomitcidset , pdfsetomitcharset
67
68 updaters . register ( " backend.update.lpdf " , function ( )
69 pdfsetmajorversion = pdf . setmajorversion
70 pdfsetminorversion = pdf . setminorversion
71 pdfgetmajorversion = pdf . getmajorversion
72 pdfgetminorversion = pdf . getminorversion
73
74 pdfsetcompresslevel = pdf . setcompresslevel
75 pdfsetobjectcompresslevel = pdf . setobjcompresslevel
76 pdfgetcompresslevel = pdf . getcompresslevel
77 pdfgetobjectcompresslevel = pdf . getobjcompresslevel
78
79 pdfsetsuppressoptionalinfo = pdf . setsuppressoptionalinfo
80 pdfsetomitcidset = pdf . setomitcidset
81 pdfsetomitcharset = pdf . setomitcharset
82 end )
83
84 function lpdf . setversion ( major , minor )
85 pdfsetmajorversion ( major or 1 )
86 pdfsetminorversion ( minor or 7 )
87 end
88
89 function lpdf . getversion ( major , minor )
90 return pdfgetmajorversion ( ) , pdfgetminorversion ( )
91 end
92
93 function lpdf . majorversion ( ) return pdfgetmajorversion ( ) end
94 function lpdf . minorversion ( ) return pdfgetminorversion ( ) end
95
96 local frozen = false
97 local clevel = 3
98 local olevel = 1
99
100 function lpdf . setcompression ( level , objectlevel , freeze )
101 if not frozen then
102 if pdfsetcompresslevel then
103 pdfsetcompresslevel ( level or 3 )
104 pdfsetobjectcompresslevel ( objectlevel or level or 3 )
105 else
106 clevel = level
107 olevel = objectlevel
108 end
109 frozen = freeze
110 end
111 end
112
113 function lpdf . getcompression ( )
114 if pdfgetcompresslevel then
115 return pdfgetcompresslevel ( ) , pdfgetobjectcompresslevel ( )
116 else
117 return clevel , olevel
118 end
119 end
120
121 function lpdf . compresslevel ( )
122 if pdfgetcompresslevel then
123 return pdfgetcompresslevel ( )
124 else
125 return clevel
126 end
127 end
128
129 function lpdf . objectcompresslevel ( )
130 if pdfgetobjectcompresslevel then
131 return pdfgetobjectcompresslevel ( )
132 else
133 return olevel
134 end
135 end
136
137 function lpdf . setsuppressoptionalinfo ( n )
138 if pdfsetsuppressoptionalinfo then
139 pdfsetsuppressoptionalinfo ( n )
140 end
141 end
142
143 function lpdf . setomitcidset ( v )
144 return pdfsetomitcidset ( v )
145 end
146
147 function lpdf . setomitcharset ( v )
148 return pdfsetomitcharset ( v )
149 end
150
151end
152
153do
154
155 local pdfgetxformname , pdfincludeimage
156
157 updaters . register ( " backend.update.lpdf " , function ( )
158 pdfgetxformname = pdf . getxformname
159 pdfincludeimage = pdf . includeimage
160 end )
161
162 function lpdf . getxformname ( id ) return pdfgetxformname ( id ) end
163 function lpdf . includeimage ( id ) return pdfincludeimage ( id ) end
164
165end
166
167 local pdfsetpageresources , pdfsetpageattributes , pdfsetpagesattributes
168 local pdfreserveobject , pdfimmediateobject , pdfdeferredobject , pdfreferenceobject
169 local pdfgetpagereference
170
171 updaters . register ( " backend.update.lpdf " , function ( )
172 pdfreserveobject = pdf . reserveobj
173 pdfimmediateobject = pdf . immediateobj
174 pdfdeferredobject = pdf . obj
175 pdfreferenceobject = pdf . refobj
176
177 pdfgetpagereference = pdf . getpageref
178
179 pdfsetpageresources = pdf . setpageresources
180 pdfsetpageattributes = pdf . setpageattributes
181 pdfsetpagesattributes = pdf . setpagesattributes
182 end )
183
184local jobpositions = job . positions
185local getpos = jobpositions . getpos
186local getrpos = jobpositions . getrpos
187
188jobpositions . registerhandlers {
189 getpos = pdf . getpos ,
190
191 gethpos = pdf . gethpos ,
192 getvpos = pdf . getvpos ,
193}
194
195do
196
197 local pdfgetmatrix , pdfhasmatrix , pdfprint
198
199 updaters . register ( " backend.update.lpdf " , function ( )
200 pdfgetmatrix = pdf . getmatrix
201 pdfhasmatrix = pdf . hasmatrix
202 pdfprint = pdf . print
203 end )
204
205 function lpdf . print ( ... )
206 return pdfprint ( ... )
207 end
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238 function lpdf . rectangle ( width , height , depth , offset )
239 local tx , ty = getpos ( )
240 if offset then
241 tx = tx - offset
242 ty = ty + offset
243 width = width + 2 * offset
244 height = height + offset
245 depth = depth + offset
246 end
247 if pdfhasmatrix ( ) then
248 local rx , sx , sy , ry = pdfgetmatrix ( )
249 return
250 factor * tx ,
251 factor * ( ty - ry * depth + sx * width ) ,
252 factor * ( tx + rx * width - sy * height ) ,
253 factor * ( ty + ry * height - sx * width )
254 else
255 return
256 factor * tx ,
257 factor * ( ty - depth ) ,
258 factor * ( tx + width ) ,
259 factor * ( ty + height )
260 end
261 end
262
263end
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286local tosixteen , fromsixteen , topdfdoc , frompdfdoc , toeight , fromeight
287
288do
289
290 local escaped = Cs ( Cc ( " ( " ) * ( S ( " \\()\n\r\t\b\f " ) / " \\%0 " + P ( 1 ) ) ^ 0 * Cc ( " ) " ) )
291
292 local cache = table . setmetatableindex ( function ( t , k )
293 local v = utfbyte ( k )
294 if v < 0x10000 then
295 v = format ( " %04x " , v )
296 else
297 v = format ( " %04x%04x " , rshift ( v , 10 ) , v % 1024 + 0xDC00 )
298 end
299 t [ k ] = v
300 return v
301 end )
302
303 local unified = Cs ( Cc ( " <feff " ) * ( lpeg . patterns . utf8character / cache ) ^ 1 * Cc ( " > " ) )
304
305 tosixteen = function ( str )
306 if not str or str = = " " then
307 return " <feff> "
308 else
309 return lpegmatch ( unified , str )
310 end
311 end
312
313 local more = 0
314
315 local pattern = C ( 4 ) / function ( s )
316 local now = tonumber ( s , 16 )
317 if more > 0 then
318 now = ( more -0xD800 ) * 0x400 + ( now -0xDC00 ) + 0x10000
319 more = 0
320 return utfchar ( now )
321 elseif now > = 0xD800 and now < = 0xDBFF then
322 more = now
323 return " "
324 else
325 return utfchar ( now )
326 end
327 end
328
329 local pattern = P ( true ) / function ( ) more = 0 end * Cs ( pattern ^ 0 )
330
331 fromsixteen = function ( str )
332 if not str or str = = " " then
333 return " "
334 else
335 return lpegmatch ( pattern , str )
336 end
337 end
338
339 local toregime = regimes . toregime
340 local fromregime = regimes . fromregime
341
342 topdfdoc = function ( str , default )
343 if not str or str = = " " then
344 return " "
345 else
346 return lpegmatch ( escaped , toregime ( " pdfdoc " , str , default ) )
347 end
348 end
349
350 frompdfdoc = function ( str )
351 if not str or str = = " " then
352 return " "
353 else
354 return fromregime ( " pdfdoc " , str )
355 end
356 end
357
358 if not toregime then topdfdoc = function ( s ) return s end end
359 if not fromregime then frompdfdoc = function ( s ) return s end end
360
361 toeight = function ( str )
362 if not str or str = = " " then
363 return " () "
364 else
365 return lpegmatch ( escaped , str )
366 end
367 end
368
369 local b_pattern = Cs ( ( P ( " \\ " ) / " " * (
370 S ( " () " )
371 + S ( " nrtbf " ) / { n = " \n " , r = " \r " , t = " \t " , b = " \b " , f = " \f " }
372 + lpegpatterns . octdigit ^ -3 / function ( s ) return char ( tonumber ( s , 8 ) ) end )
373 + P ( 1 ) ) ^ 0 )
374
375 fromeight = function ( str )
376 if not str or str = = " " then
377 return " "
378 else
379 return lpegmatch ( unescape , str )
380 end
381 end
382
383 local u_pattern = lpegpatterns . utfbom_16_be * lpegpatterns . utf16_to_utf8_be
384 + lpegpatterns . utfbom_16_le * lpegpatterns . utf16_to_utf8_le
385
386 local h_pattern = lpegpatterns . hextobytes
387
388 local zero = S ( " \n\r\t " ) + P ( " \\ " )
389 local one = C ( 4 )
390 local two = P ( " d " ) * R ( " 89 " , " af " ) * C ( 2 ) * C ( 4 )
391
392 local x_pattern = P { " start " ,
393 start = V ( " wrapped " ) + V ( " unwrapped " ) + V ( " original " ) ,
394 original = Cs ( P ( 1 ) ^ 0 ) ,
395 wrapped = P ( " < " ) * V ( " unwrapped " ) * P ( " > " ) * P ( -1 ) ,
396 unwrapped = P ( " feff " )
397 * Cs ( (
398 zero / " "
399 + two / function ( a , b )
400 a = ( tonumber ( a , 16 ) - 0xD800 ) * 1024
401 b = ( tonumber ( b , 16 ) - 0xDC00 )
402 return utfchar ( a + b )
403 end
404 + one / function ( a )
405 return utfchar ( tonumber ( a , 16 ) )
406 end
407 ) ^ 1 ) * P ( -1 )
408 }
409
410 function lpdf . frombytes ( s , hex )
411 if not s or s = = " " then
412 return " "
413 end
414 if hex then
415 local x = lpegmatch ( x_pattern , s )
416 if x then
417 return x
418 end
419 local h = lpegmatch ( h_pattern , s )
420 if h then
421 return h
422 end
423 else
424 local u = lpegmatch ( u_pattern , s )
425 if u then
426 return u
427 end
428 end
429 return lpegmatch ( b_pattern , s )
430 end
431
432 lpdf . tosixteen = tosixteen
433 lpdf . toeight = toeight
434 lpdf . topdfdoc = topdfdoc
435 lpdf . fromsixteen = fromsixteen
436 lpdf . fromeight = fromeight
437 lpdf . frompdfdoc = frompdfdoc
438
439end
440
441local tostring_a , tostring_d
442
443do
444
445 local f_key_null = formatters [ " /%s null " ]
446 local f_key_value = formatters [ " /%s %s " ]
447 local f_key_dictionary = formatters [ " /%s << % t >> " ]
448 local f_dictionary = formatters [ " << % t >> " ]
449 local f_key_array = formatters [ " /%s [ % t ] " ]
450 local f_array = formatters [ " [ % t ] " ]
451 local f_key_number = formatters [ " /%s %N " ]
452 local f_tonumber = formatters [ " %N " ]
453
454 tostring_d = function ( t , contentonly , key )
455 if next ( t ) then
456 local r = { }
457 local n = 0
458 local e
459 for k , v in next , t do
460 if k = = " __extra__ " then
461 e = v
462 elseif k = = " __stream__ " then
463
464 else
465 n = n + 1
466 r [ n ] = k
467 end
468 end
469 if n > 1 then
470 sort ( r )
471 end
472 for i = 1 , n do
473 local k = r [ i ]
474 local v = t [ k ]
475 local tv = type ( v )
476
477 if tv = = " table " then
478
479
480 if v . __lpdftype__ then
481
482
483
484
485 r [ i ] = f_key_value ( k , tostring ( v ) )
486
487 elseif v [ 1 ] then
488 r [ i ] = f_key_value ( k , tostring_a ( v ) )
489 else
490 r [ i ] = f_key_value ( k , tostring_d ( v ) )
491 end
492 elseif tv = = " string " then
493 r [ i ] = f_key_value ( k , toeight ( v ) )
494 elseif tv = = " number " then
495 r [ i ] = f_key_number ( k , v )
496 else
497 r [ i ] = f_key_value ( k , tostring ( v ) )
498 end
499 end
500 if e then
501 r [ n + 1 ] = e
502 end
503 if contentonly then
504 return concat ( r , " " )
505 elseif key then
506 return f_key_dictionary ( key , r )
507 else
508 return f_dictionary ( r )
509 end
510 elseif contentonly then
511 return " "
512 else
513 return " << >> "
514 end
515 end
516
517 tostring_a = function ( t , contentonly , key )
518 local tn = # t
519 if tn ~ = 0 then
520 local r = { }
521 for k = 1 , tn do
522 local v = t [ k ]
523 local tv = type ( v )
524
525 if tv = = " number " then
526 r [ k ] = f_tonumber ( v )
527 elseif tv = = " table " then
528
529
530 if v . __lpdftype__ then
531
532
533
534
535 r [ k ] = tostring ( v )
536
537 elseif v [ 1 ] then
538 r [ k ] = tostring_a ( v )
539 else
540 r [ k ] = tostring_d ( v )
541 end
542 elseif tv = = " string " then
543 r [ k ] = toeight ( v )
544 else
545 r [ k ] = tostring ( v )
546 end
547 end
548 local e = t . __extra__
549 if e then
550 r [ tn + 1 ] = e
551 end
552 if contentonly then
553 return concat ( r , " " )
554 elseif key then
555 return f_key_array ( key , r )
556 else
557 return f_array ( r )
558 end
559 elseif contentonly then
560 return " "
561 else
562 return " [ ] "
563 end
564 end
565
566end
567
568local f_tonumber = formatters [ " %N " ]
569
570local tostring_x = function ( t ) return concat ( t , " " ) end
571local tostring_s = function ( t ) return toeight ( t [ 1 ] ) end
572local tostring_p = function ( t ) return topdfdoc ( t [ 1 ] , t [ 2 ] ) end
573local tostring_u = function ( t ) return tosixteen ( t [ 1 ] ) end
574
575local tostring_n = function ( t ) return f_tonumber ( t [ 1 ] ) end
576local tostring_c = function ( t ) return t [ 1 ] end
577local tostring_z = function ( ) return " null " end
578local tostring_t = function ( ) return " true " end
579local tostring_f = function ( ) return " false " end
580local tostring_r = function ( t ) local n = t [ 1 ] return n and n > 0 and ( n . . " 0 R " ) or " null " end
581
582local tostring_v = function ( t )
583 local s = t [ 1 ]
584 if type ( s ) = = " table " then
585 return concat ( s )
586 else
587 return s
588 end
589end
590
591local tostring_l = function ( t )
592 local s = t [ 1 ]
593 if not s or s = = " " then
594 return " () "
595 elseif t [ 2 ] then
596 return " < " . . s . . " > "
597 else
598 return " ( " . . s . . " ) "
599 end
600end
601
602local function value_x ( t ) return t end
603local function value_s ( t ) return t [ 1 ] end
604local function value_p ( t ) return t [ 1 ] end
605local function value_u ( t ) return t [ 1 ] end
606local function value_n ( t ) return t [ 1 ] end
607local function value_c ( t ) return sub ( t [ 1 ] , 2 ) end
608local function value_d ( t ) return tostring_d ( t , true ) end
609local function value_a ( t ) return tostring_a ( t , true ) end
610local function value_z ( ) return nil end
611local function value_t ( t ) return t . value or true end
612local function value_f ( t ) return t . value or false end
613local function value_r ( t ) return t [ 1 ] or 0 end
614local function value_v ( t ) return t [ 1 ] end
615local function value_l ( t ) return t [ 1 ] end
616
617local function add_to_d ( t , v )
618 local k = type ( v )
619 if k = = " string " then
620 if t . __extra__ then
621 t . __extra__ = t . __extra__ . . " " . . v
622 else
623 t . __extra__ = v
624 end
625 elseif k = = " table " then
626 for k , v in next , v do
627 t [ k ] = v
628 end
629 end
630 return t
631end
632
633local function add_to_a ( t , v )
634 local k = type ( v )
635 if k = = " string " then
636 if t . __extra__ then
637 t . __extra__ = t . __extra__ . . " " . . v
638 else
639 t . __extra__ = v
640 end
641 elseif k = = " table " then
642 local n = # t
643 for i = 1 , # v do
644 n = n + 1
645 t [ n ] = v [ i ]
646 end
647 end
648 return t
649end
650
651local function add_x ( t , k , v ) rawset ( t , k , tostring ( v ) ) end
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668local mt_x = { __index = { __lpdftype__ = " stream " } , __tostring = tostring_x , __call = value_x , __newindex = add_x }
669local mt_d = { __index = { __lpdftype__ = " dictionary " } , __tostring = tostring_d , __call = value_d , __add = add_to_d }
670local mt_a = { __index = { __lpdftype__ = " array " } , __tostring = tostring_a , __call = value_a , __add = add_to_a }
671local mt_u = { __index = { __lpdftype__ = " unicode " } , __tostring = tostring_u , __call = value_u }
672local mt_s = { __index = { __lpdftype__ = " string " } , __tostring = tostring_s , __call = value_s }
673local mt_p = { __index = { __lpdftype__ = " docstring " } , __tostring = tostring_p , __call = value_p }
674local mt_n = { __index = { __lpdftype__ = " number " } , __tostring = tostring_n , __call = value_n }
675local mt_c = { __index = { __lpdftype__ = " constant " } , __tostring = tostring_c , __call = value_c }
676local mt_z = { __index = { __lpdftype__ = " null " } , __tostring = tostring_z , __call = value_z }
677local mt_t = { __index = { __lpdftype__ = " true " } , __tostring = tostring_t , __call = value_t }
678local mt_f = { __index = { __lpdftype__ = " false " } , __tostring = tostring_f , __call = value_f }
679local mt_r = { __index = { __lpdftype__ = " reference " } , __tostring = tostring_r , __call = value_r }
680local mt_v = { __index = { __lpdftype__ = " verbose " } , __tostring = tostring_v , __call = value_v }
681local mt_l = { __index = { __lpdftype__ = " literal " } , __tostring = tostring_l , __call = value_l }
682
683local function pdfstream ( t )
684 if t then
685 local tt = type ( t )
686 if tt = = " table " then
687 for i = 1 , # t do
688 t [ i ] = tostring ( t [ i ] )
689 end
690 elseif tt = = " string " then
691 t = { t }
692 else
693 t = { tostring ( t ) }
694 end
695 end
696 return setmetatable ( t or { } , mt_x )
697end
698
699local function pdfdictionary ( t )
700 return setmetatable ( t or { } , mt_d )
701end
702
703local function pdfarray ( t )
704 if type ( t ) = = " string " then
705 return setmetatable ( { t } , mt_a )
706 else
707 return setmetatable ( t or { } , mt_a )
708 end
709end
710
711local function pdfstring ( str , default )
712 return setmetatable ( { str or default or " " } , mt_s )
713end
714
715local function pdfdocstring ( str , default , defaultchar )
716 return setmetatable ( { str or default or " " , defaultchar or " " } , mt_p )
717end
718
719local function pdfunicode ( str , default )
720 return setmetatable ( { str or default or " " } , mt_u )
721end
722
723local function pdfliteral ( str , hex )
724 return setmetatable ( { str , hex } , mt_l )
725end
726
727local pdfnumber , pdfconstant
728
729do
730
731 local cache = { }
732
733 pdfnumber = function ( n , default )
734 if not n then
735 n = default
736 end
737 local c = cache [ n ]
738 if not c then
739 c = setmetatable ( { n } , mt_n )
740
741 end
742 return c
743 end
744
745 for i = -1 , 9 do cache [ i ] = pdfnumber ( i ) end
746
747 local replacer = S ( " \0\t\n\r\f ()[]{}/%%#\\ " ) / {
748 [ " \00 " ] = " #00 " ,
749 [ " \09 " ] = " #09 " ,
750 [ " \10 " ] = " #0a " ,
751 [ " \12 " ] = " #0c " ,
752 [ " \13 " ] = " #0d " ,
753 [ " " ] = " #20 " ,
754 [ " # " ] = " #23 " ,
755 [ " % " ] = " #25 " ,
756 [ " ( " ] = " #28 " ,
757 [ " ) " ] = " #29 " ,
758 [ " / " ] = " #2f " ,
759 [ " [ " ] = " #5b " ,
760 [ " \\ " ] = " #5c " ,
761 [ " ] " ] = " #5d " ,
762 [ " { " ] = " #7b " ,
763 [ " } " ] = " #7d " ,
764 } + P ( 1 )
765
766 local escaped = Cs ( Cc ( " / " ) * replacer ^ 0 )
767
768 local cache = table . setmetatableindex ( function ( t , k )
769 local v = setmetatable ( { lpegmatch ( escaped , k ) } , mt_c )
770 t [ k ] = v
771 return v
772 end )
773
774 pdfconstant = function ( str , default )
775 if not str then
776 str = default or " none "
777 end
778 return cache [ str ]
779 end
780
781 local escaped = Cs ( replacer ^ 0 )
782
783 function lpdf . escaped ( str )
784 return lpegmatch ( escaped , str ) or str
785 end
786
787end
788
789local pdfnull , pdfboolean , pdfreference , pdfverbose
790
791do
792
793 local p_null = { } setmetatable ( p_null , mt_z )
794 local p_true = { } setmetatable ( p_true , mt_t )
795 local p_false = { } setmetatable ( p_false , mt_f )
796
797 pdfnull = function ( )
798 return p_null
799 end
800
801 pdfboolean = function ( b , default )
802 if type ( b ) = = " boolean " then
803 return b and p_true or p_false
804 else
805 return default and p_true or p_false
806 end
807 end
808
809
810
811
812
813 local r_zero = setmetatable ( { 0 } , mt_r )
814
815 pdfreference = function ( r )
816 if r and r ~ = 0 then
817 return setmetatable ( { r } , mt_r )
818 else
819 return r_zero
820 end
821 end
822
823 local v_zero = setmetatable ( { 0 } , mt_v )
824 local v_empty = setmetatable ( { " " } , mt_v )
825
826 pdfverbose = function ( t )
827 if t = = 0 then
828 return v_zero
829 elseif t = = " " then
830 return v_empty
831 else
832 return setmetatable ( { t } , mt_v )
833 end
834 end
835
836end
837
838lpdf . stream = pdfstream
839lpdf . dictionary = pdfdictionary
840lpdf . array = pdfarray
841lpdf . docstring = pdfdocstring
842lpdf . string = pdfstring
843lpdf . unicode = pdfunicode
844lpdf . number = pdfnumber
845lpdf . constant = pdfconstant
846lpdf . null = pdfnull
847lpdf . boolean = pdfboolean
848lpdf . reference = pdfreference
849lpdf . verbose = pdfverbose
850lpdf . literal = pdfliteral
851
852local names , cache = { } , { }
853
854function lpdf . reserveobject ( name )
855 local r = pdfreserveobject ( )
856 if name then
857 names [ name ] = r
858 if trace_objects then
859 report_objects ( " reserving number %a under name %a " , r , name )
860 end
861 elseif trace_objects then
862 report_objects ( " reserving number %a " , r )
863 end
864 return r
865end
866
867local nofpages = 0
868
869local texgetcount = tex . getcount
870
871function lpdf . pagereference ( n , complete )
872 if nofpages = = 0 then
873 nofpages = structures . pages . nofpages
874 if nofpages = = 0 then
875 nofpages = 1
876 end
877 end
878 if n = = true or not n then
879 complete = n
880 n = texgetcount ( " realpageno " )
881 end
882 local r = n > nofpages and pdfgetpagereference ( nofpages ) or pdfgetpagereference ( n )
883 return complete and pdfreference ( r ) or r
884end
885
886function lpdf . nofpages ( )
887 return structures . pages . nofpages
888end
889
890function lpdf . obj ( ... )
891 pdfdeferredobject ( ... )
892end
893
894function lpdf . immediateobj ( ... )
895 pdfimmediateobject ( ... )
896end
897
898function lpdf . delayedobject ( data , n )
899 if n then
900 pdfdeferredobject ( n , data )
901 else
902 n = pdfdeferredobject ( data )
903 end
904 pdfreferenceobject ( n )
905 return n
906end
907
908function lpdf . flushobject ( name , data )
909 if data then
910 local named = names [ name ]
911 if named then
912 if not trace_objects then
913 elseif trace_details then
914 report_objects ( " flushing data to reserved object with name %a, data: %S " , name , data )
915 else
916 report_objects ( " flushing data to reserved object with name %a " , name )
917 end
918 return pdfimmediateobject ( named , tostring ( data ) )
919 else
920 if not trace_objects then
921 elseif trace_details then
922 report_objects ( " flushing data to reserved object with number %s, data: %S " , name , data )
923 else
924 report_objects ( " flushing data to reserved object with number %s " , name )
925 end
926 return pdfimmediateobject ( name , tostring ( data ) )
927 end
928 else
929 if trace_objects and trace_details then
930 report_objects ( " flushing data: %S " , name )
931 end
932 return pdfimmediateobject ( tostring ( name ) )
933 end
934end
935
936function lpdf . flushstreamobject ( data , dict , compressed , objnum )
937 if trace_objects then
938 report_objects ( " flushing stream object of %s bytes " , # data )
939 end
940 local dtype = type ( dict )
941 local kind = compressed = = " raw " and " raw " or " stream "
942 local nolength = nil
943 if compressed = = " raw " then
944 compressed = nil
945 nolength = true
946
947 end
948 return pdfdeferredobject {
949 objnum = objnum ,
950 immediate = true ,
951 nolength = nolength ,
952 compresslevel = compressed = = false and 0 or nil ,
953 type = " stream " ,
954 string = data ,
955 attr = ( dtype = = " string " and dict ) or ( dtype = = " table " and dict ( ) ) or nil ,
956 }
957end
958
959function lpdf . flushstreamfileobject ( filename , dict , compressed , objnum )
960 if trace_objects then
961 report_objects ( " flushing stream file object %a " , filename )
962 end
963 local dtype = type ( dict )
964 return pdfdeferredobject {
965 objnum = objnum ,
966 immediate = true ,
967 compresslevel = compressed = = false and 0 or nil ,
968 type = " stream " ,
969 file = filename ,
970 attr = ( dtype = = " string " and dict ) or ( dtype = = " table " and dict ( ) ) or nil ,
971 }
972end
973
974local shareobjectcache , shareobjectreferencecache = { } , { }
975
976function lpdf . shareobject ( content )
977 if content = = nil then
978
979 else
980 content = tostring ( content )
981 local o = shareobjectcache [ content ]
982 if not o then
983 o = pdfimmediateobject ( content )
984 shareobjectcache [ content ] = o
985 end
986 return o
987 end
988end
989
990function lpdf . shareobjectreference ( content )
991 if content = = nil then
992
993 else
994 content = tostring ( content )
995 local r = shareobjectreferencecache [ content ]
996 if not r then
997 local o = shareobjectcache [ content ]
998 if not o then
999 o = pdfimmediateobject ( content )
1000 shareobjectcache [ content ] = o
1001 end
1002 r = pdfreference ( o )
1003 shareobjectreferencecache [ content ] = r
1004 end
1005 return r
1006 end
1007end
1008
1009
1010
1011local pagefinalizers = { { } , { } , { } }
1012local documentfinalizers = { { } , { } , { } }
1013
1014local pageresources , pageattributes , pagesattributes
1015
1016local function resetpageproperties ( )
1017 pageresources = pdfdictionary ( )
1018 pageattributes = pdfdictionary ( )
1019 pagesattributes = pdfdictionary ( )
1020end
1021
1022function lpdf . getpageproperties ( )
1023 return {
1024 pageresources = pageresources ,
1025 pageattributes = pageattributes ,
1026 pagesattributes = pagesattributes ,
1027 }
1028end
1029
1030resetpageproperties ( )
1031
1032local function setpageproperties ( )
1033 pdfsetpageresources ( pageresources ( ) )
1034 pdfsetpageattributes ( pageattributes ( ) )
1035 pdfsetpagesattributes ( pagesattributes ( ) )
1036end
1037
1038local function addtopageresources ( k , v ) pageresources [ k ] = v end
1039local function addtopageattributes ( k , v ) pageattributes [ k ] = v end
1040local function addtopagesattributes ( k , v ) pagesattributes [ k ] = v end
1041
1042lpdf . addtopageresources = addtopageresources
1043lpdf . addtopageattributes = addtopageattributes
1044lpdf . addtopagesattributes = addtopagesattributes
1045
1046local function set ( where , what , f , when , comment )
1047 if type ( when ) = = " string " then
1048 when , comment = 2 , when
1049 elseif not when then
1050 when = 2
1051 end
1052 local w = where [ when ]
1053 w [ # w + 1 ] = { f , comment }
1054 if trace_finalizers then
1055 report_finalizing ( " %s set: [%s,%s] " , what , when , # w )
1056 end
1057end
1058
1059local function run ( where , what )
1060 if trace_finalizers then
1061 report_finalizing ( " start backend, category %a, n %a " , what , # where )
1062 end
1063 for i = 1 , # where do
1064 local w = where [ i ]
1065 for j = 1 , # w do
1066 local wj = w [ j ]
1067 if trace_finalizers then
1068 report_finalizing ( " %s finalizer: [%s,%s] %s " , what , i , j , wj [ 2 ] or " " )
1069 end
1070 wj [ 1 ] ( )
1071 end
1072 end
1073 if trace_finalizers then
1074 report_finalizing ( " stop finalizing " )
1075 end
1076end
1077
1078local function registerpagefinalizer ( f , when , comment )
1079 set ( pagefinalizers , " page " , f , when , comment )
1080end
1081
1082local function registerdocumentfinalizer ( f , when , comment )
1083 set ( documentfinalizers , " document " , f , when , comment )
1084end
1085
1086lpdf . registerpagefinalizer = registerpagefinalizer
1087lpdf . registerdocumentfinalizer = registerdocumentfinalizer
1088
1089function lpdf . finalizepage ( shipout )
1090 if shipout and not environment . initex then
1091
1092 run ( pagefinalizers , " page " )
1093 setpageproperties ( )
1094 resetpageproperties ( )
1095 end
1096end
1097
1098function lpdf . finalizedocument ( )
1099 if not environment . initex then
1100 run ( documentfinalizers , " document " )
1101 function lpdf . finalizedocument ( )
1102
1103 function lpdf . finalizedocument ( ) end
1104 end
1105 end
1106end
1107
1108callbacks . register ( " finish_pdfpage " , lpdf . finalizepage )
1109callbacks . register ( " finish_pdffile " , lpdf . finalizedocument )
1110
1111do
1112
1113 local pdfsetinfo , pdfsetcatalog , pdfsettrailerid
1114
1115 updaters . register ( " backend.update.lpdf " , function ( )
1116 pdfsetinfo = pdf . setinfo
1117 pdfsetcatalog = pdf . setcatalog
1118 pdfsettrailerid = pdf . settrailerid
1119 end )
1120
1121 function lpdf . settrailerid ( id )
1122 pdfsettrailerid ( id )
1123 end
1124
1125
1126
1127 local function trace_set ( what , key )
1128 if trace_resources then
1129 report_finalizing ( " setting key %a in %a " , key , what )
1130 end
1131 end
1132
1133 local function trace_flush ( what )
1134 if trace_resources then
1135 report_finalizing ( " flushing %a " , what )
1136 end
1137 end
1138
1139 lpdf . protectresources = true
1140
1141 local catalog = pdfdictionary { Type = pdfconstant ( " Catalog " ) }
1142 local info = pdfdictionary { Type = pdfconstant ( " Info " ) }
1143
1144
1145 local function checkcatalog ( )
1146 if not environment . initex then
1147 trace_flush ( " catalog " )
1148 return true
1149 end
1150 end
1151
1152 local function checkinfo ( )
1153 if not environment . initex then
1154 trace_flush ( " info " )
1155 if lpdf . majorversion ( ) > 1 then
1156 for k , v in next , info do
1157 if k = = " CreationDate " or k = = " ModDate " then
1158
1159 else
1160 info [ k ] = nil
1161 end
1162 end
1163 end
1164 return true
1165 end
1166 end
1167
1168 local function flushcatalog ( )
1169 if checkcatalog ( ) then
1170 catalog . Type = nil
1171 pdfsetcatalog ( catalog ( ) )
1172 end
1173 end
1174
1175 local function flushinfo ( )
1176 if checkinfo ( ) then
1177 info . Type = nil
1178 pdfsetinfo ( info ( ) )
1179 end
1180 end
1181
1182 function lpdf . getcatalog ( )
1183 if checkcatalog ( ) then
1184 catalog . Type = pdfconstant ( " Catalog " )
1185 return pdfreference ( pdfimmediateobject ( tostring ( catalog ) ) )
1186 end
1187 end
1188
1189 function lpdf . getinfo ( )
1190 if checkinfo ( ) then
1191 return pdfreference ( pdfimmediateobject ( tostring ( info ) ) )
1192 end
1193 end
1194
1195 function lpdf . addtocatalog ( k , v )
1196 if not ( lpdf . protectresources and catalog [ k ] ) then
1197 trace_set ( " catalog " , k )
1198 catalog [ k ] = v
1199 end
1200 end
1201
1202 function lpdf . addtoinfo ( k , v )
1203 if not ( lpdf . protectresources and info [ k ] ) then
1204 trace_set ( " info " , k )
1205 info [ k ] = v
1206 end
1207 end
1208
1209
1210
1211
1212
1213
1214
1215
1216 local names = pdfdictionary {
1217
1218 }
1219
1220 local function flushnames ( )
1221 if next ( names ) and not environment . initex then
1222 names . Type = pdfconstant ( " Names " )
1223 trace_flush ( " names " )
1224 lpdf . addtocatalog ( " Names " , pdfreference ( pdfimmediateobject ( tostring ( names ) ) ) )
1225 end
1226 end
1227
1228 function lpdf . addtonames ( k , v )
1229 if not ( lpdf . protectresources and names [ k ] ) then
1230 trace_set ( " names " , k )
1231 names [ k ] = v
1232 end
1233 end
1234
1235 local r_extgstates , r_colorspaces , r_patterns , r_shades
1236 local d_extgstates , d_colorspaces , d_patterns , d_shades
1237 local p_extgstates , p_colorspaces , p_patterns , p_shades
1238
1239 local function checkextgstates ( ) if d_extgstates then addtopageresources ( " ExtGState " , p_extgstates ) end end
1240 local function checkcolorspaces ( ) if d_colorspaces then addtopageresources ( " ColorSpace " , p_colorspaces ) end end
1241 local function checkpatterns ( ) if d_patterns then addtopageresources ( " Pattern " , p_patterns ) end end
1242 local function checkshades ( ) if d_shades then addtopageresources ( " Shading " , p_shades ) end end
1243
1244 local function flushextgstates ( ) if d_extgstates then trace_flush ( " extgstates " ) pdfimmediateobject ( r_extgstates , tostring ( d_extgstates ) ) end end
1245 local function flushcolorspaces ( ) if d_colorspaces then trace_flush ( " colorspaces " ) pdfimmediateobject ( r_colorspaces , tostring ( d_colorspaces ) ) end end
1246 local function flushpatterns ( ) if d_patterns then trace_flush ( " patterns " ) pdfimmediateobject ( r_patterns , tostring ( d_patterns ) ) end end
1247 local function flushshades ( ) if d_shades then trace_flush ( " shades " ) pdfimmediateobject ( r_shades , tostring ( d_shades ) ) end end
1248
1249
1250
1251
1252
1253
1254
1255 local f_font = formatters [ " %s%d " ]
1256
1257 function lpdf . collectedresources ( options )
1258 local ExtGState = d_extgstates and next ( d_extgstates ) and p_extgstates
1259 local ColorSpace = d_colorspaces and next ( d_colorspaces ) and p_colorspaces
1260 local Pattern = d_patterns and next ( d_patterns ) and p_patterns
1261 local Shading = d_shades and next ( d_shades ) and p_shades
1262 local Font
1263 if options and options . patterns = = false then
1264 Pattern = nil
1265 end
1266 local fonts = options and options . fonts
1267 if fonts and next ( fonts ) then
1268 local pdfgetfontobjnumber = lpdf . getfontobjnumber
1269 if pdfgetfontobjnumber then
1270 local prefix = options . fontprefix or " F "
1271 Font = pdfdictionary { }
1272 for k , v in sortedhash ( fonts ) do
1273 Font [ f_font ( prefix , v ) ] = pdfreference ( pdfgetfontobjnumber ( k ) )
1274 end
1275 end
1276 end
1277 if ExtGState or ColorSpace or Pattern or Shading or Font then
1278 local collected = pdfdictionary {
1279 ExtGState = ExtGState ,
1280 ColorSpace = ColorSpace ,
1281 Pattern = Pattern ,
1282 Shading = Shading ,
1283 Font = Font ,
1284 }
1285 if options and options . serialize = = false then
1286 return collected
1287 else
1288 return collected ( )
1289 end
1290 elseif options and options . notempty then
1291 return nil
1292 elseif options and options . serialize = = false then
1293 return pdfdictionary { }
1294 else
1295 return " "
1296 end
1297 end
1298
1299 function lpdf . adddocumentextgstate ( k , v )
1300 if not d_extgstates then
1301 r_extgstates = pdfreserveobject ( )
1302 d_extgstates = pdfdictionary ( )
1303 p_extgstates = pdfreference ( r_extgstates )
1304 end
1305 d_extgstates [ k ] = v
1306 end
1307
1308 function lpdf . adddocumentcolorspace ( k , v )
1309 if not d_colorspaces then
1310 r_colorspaces = pdfreserveobject ( )
1311 d_colorspaces = pdfdictionary ( )
1312 p_colorspaces = pdfreference ( r_colorspaces )
1313 end
1314 d_colorspaces [ k ] = v
1315 end
1316
1317 function lpdf . adddocumentpattern ( k , v )
1318 if not d_patterns then
1319 r_patterns = pdfreserveobject ( )
1320 d_patterns = pdfdictionary ( )
1321 p_patterns = pdfreference ( r_patterns )
1322 end
1323 d_patterns [ k ] = v
1324 end
1325
1326 function lpdf . adddocumentshade ( k , v )
1327 if not d_shades then
1328 r_shades = pdfreserveobject ( )
1329 d_shades = pdfdictionary ( )
1330 p_shades = pdfreference ( r_shades )
1331 end
1332 d_shades [ k ] = v
1333 end
1334
1335 registerdocumentfinalizer ( flushextgstates , 3 , " extended graphic states " )
1336 registerdocumentfinalizer ( flushcolorspaces , 3 , " color spaces " )
1337 registerdocumentfinalizer ( flushpatterns , 3 , " patterns " )
1338 registerdocumentfinalizer ( flushshades , 3 , " shades " )
1339
1340 registerdocumentfinalizer ( flushnames , 3 , " names " )
1341 registerdocumentfinalizer ( flushcatalog , 3 , " catalog " )
1342 registerdocumentfinalizer ( flushinfo , 3 , " info " )
1343
1344 registerpagefinalizer ( checkextgstates , 3 , " extended graphic states " )
1345 registerpagefinalizer ( checkcolorspaces , 3 , " color spaces " )
1346 registerpagefinalizer ( checkpatterns , 3 , " patterns " )
1347 registerpagefinalizer ( checkshades , 3 , " shades " )
1348
1349end
1350
1351
1352
1353function lpdf . rotationcm ( a )
1354 local s = sind ( a )
1355 local c = cosd ( a )
1356 return format ( " %.6F %.6F %.6F %.6F 0 0 cm " , c , s , - s , c )
1357end
1358
1359
1360
1361do
1362
1363
1364
1365 local metadata = nil
1366 local timestamp = backends . timestamp ( )
1367
1368 function lpdf . getmetadata ( )
1369 if not metadata then
1370 local contextversion = environment . version
1371 local luatexversion = format ( " %1.2f " , LUATEXVERSION )
1372 local luatexfunctionality = tostring ( LUATEXFUNCTIONALITY )
1373 metadata = {
1374 producer = format ( " LuaTeX-%s " , luatexversion ) ,
1375 creator = format ( " LuaTeX %s %s + ConTeXt MkIV %s " , luatexversion , luatexfunctionality , contextversion ) ,
1376 luatexversion = luatexversion ,
1377 contextversion = contextversion ,
1378 luatexfunctionality = luatexfunctionality ,
1379 luaversion = tostring ( LUAVERSION ) ,
1380 platform = os . platform ,
1381 time = timestamp ,
1382 }
1383 end
1384 return metadata
1385 end
1386
1387 function lpdf . settime ( n )
1388 if n then
1389 n = converters . totime ( n )
1390 if n then
1391 converters . settime ( n )
1392 timestamp = backends . timestamp ( )
1393 end
1394 end
1395 if metadata then
1396 metadata . time = timestamp
1397 end
1398 return timestamp
1399 end
1400
1401 lpdf . settime ( tonumber ( resolvers . variable ( " start_time " ) ) or tonumber ( resolvers . variable ( " SOURCE_DATE_EPOCH " ) ) )
1402
1403 function lpdf . pdftimestamp ( str )
1404 local t = type ( str )
1405 if t = = " string " then
1406 local Y , M , D , h , m , s , Zs , Zh , Zm = match ( str , " ^(%d%d%d%d)%-(%d%d)%-(%d%d)T(%d%d):(%d%d):(%d%d)([%+%-])(%d%d):(%d%d)$ " )
1407 return Y and format ( " D:%s%s%s%s%s%s%s%s'%s' " , Y , M , D , h , m , s , Zs , Zh , Zm )
1408 else
1409 return osdate ( " D:%Y%m%d%H%M%S " , t = = " number " and str or ostime ( ) )
1410 end
1411 end
1412
1413 function lpdf . id ( date )
1414 local banner = environment . jobname or tex . jobname or " unknown "
1415 if not date then
1416 return banner
1417 else
1418 return format ( " %s | %s " , banner , timestamp )
1419 end
1420 end
1421
1422end
1423
1424
1425
1426function lpdf . checkedkey ( t , key , variant )
1427 local pn = t and t [ key ]
1428 if pn ~ = nil then
1429 local tn = type ( pn )
1430 if tn = = variant then
1431 if variant = = " string " then
1432 if pn ~ = " " then
1433 return pn
1434 end
1435 elseif variant = = " table " then
1436 if next ( pn ) then
1437 return pn
1438 end
1439 else
1440 return pn
1441 end
1442 elseif tn = = " string " then
1443 if variant = = " number " then
1444 return tonumber ( pn )
1445 elseif variant = = " boolean " then
1446 return isboolean ( pn , nil , true )
1447 end
1448 end
1449 end
1450
1451end
1452
1453function lpdf . checkedvalue ( value , variant )
1454 if value ~ = nil then
1455 local tv = type ( value )
1456 if tv = = variant then
1457 if variant = = " string " then
1458 if value ~ = " " then
1459 return value
1460 end
1461 elseif variant = = " table " then
1462 if next ( value ) then
1463 return value
1464 end
1465 else
1466 return value
1467 end
1468 elseif tv = = " string " then
1469 if variant = = " number " then
1470 return tonumber ( value )
1471 elseif variant = = " boolean " then
1472 return isboolean ( value , nil , true )
1473 end
1474 end
1475 end
1476end
1477
1478function lpdf . limited ( n , min , max , default )
1479 if not n then
1480 return default
1481 else
1482 n = tonumber ( n )
1483 if not n then
1484 return default
1485 elseif n > max then
1486 return max
1487 elseif n < min then
1488 return min
1489 else
1490 return n
1491 end
1492 end
1493end
1494
1495
1496
1497
1498
1499
1500
1501
1502do
1503
1504 local f_actual_text_p = formatters [ " BT /Span << /ActualText <feff%s> >> BDC %s EMC ET " ]
1505 local f_actual_text_b = formatters [ " BT /Span << /ActualText <feff%s> >> BDC " ]
1506 local s_actual_text_e = " EMC ET "
1507 local f_actual_text_b_not = formatters [ " /Span << /ActualText <feff%s> >> BDC " ]
1508 local s_actual_text_e_not = " EMC "
1509 local f_actual_text = formatters [ " /Span <</ActualText %s >> BDC " ]
1510
1511 local context = context
1512 local pdfdirect = nodes . pool . directliteral
1513 local tounicode = fonts . mappings . tounicode
1514
1515 function codeinjections . unicodetoactualtext ( unicode , pdfcode )
1516 return f_actual_text_p ( type ( unicode ) = = " string " and unicode or tounicode ( unicode ) , pdfcode )
1517 end
1518
1519 function codeinjections . startunicodetoactualtext ( unicode )
1520 return f_actual_text_b ( type ( unicode ) = = " string " and unicode or tounicode ( unicode ) )
1521 end
1522
1523 function codeinjections . stopunicodetoactualtext ( )
1524 return s_actual_text_e
1525 end
1526
1527 function codeinjections . startunicodetoactualtextdirect ( unicode )
1528 return f_actual_text_b_not ( type ( unicode ) = = " string " and unicode or tounicode ( unicode ) )
1529 end
1530
1531 function codeinjections . stopunicodetoactualtextdirect ( )
1532 return s_actual_text_e_not
1533 end
1534
1535 implement {
1536 name = " startactualtext " ,
1537 arguments = " string " ,
1538 actions = function ( str )
1539 context ( pdfdirect ( f_actual_text ( tosixteen ( str ) ) ) )
1540 end
1541 }
1542
1543 implement {
1544 name = " stopactualtext " ,
1545 actions = function ( )
1546 context ( pdfdirect ( " EMC " ) )
1547 end
1548 }
1549
1550end
1551
1552
1553
1554implement { name = " lpdf_collectedresources " , actions = { lpdf . collectedresources , context } }
1555implement { name = " lpdf_addtocatalog " , arguments = " 2 strings " , actions = lpdf . addtocatalog }
1556implement { name = " lpdf_addtoinfo " , arguments = " 2 strings " , actions = function ( a , b , c ) lpdf . addtoinfo ( a , b , c ) end }
1557implement { name = " lpdf_addtonames " , arguments = " 2 strings " , actions = lpdf . addtonames }
1558implement { name = " lpdf_addtopageattributes " , arguments = " 2 strings " , actions = lpdf . addtopageattributes }
1559implement { name = " lpdf_addtopagesattributes " , arguments = " 2 strings " , actions = lpdf . addtopagesattributes }
1560implement { name = " lpdf_addtopageresources " , arguments = " 2 strings " , actions = lpdf . addtopageresources }
1561implement { name = " lpdf_adddocumentextgstate " , arguments = " 2 strings " , actions = function ( a , b ) lpdf . adddocumentextgstate ( a , pdfverbose ( b ) ) end }
1562implement { name = " lpdf_adddocumentcolorspace " , arguments = " 2 strings " , actions = function ( a , b ) lpdf . adddocumentcolorspace ( a , pdfverbose ( b ) ) end }
1563implement { name = " lpdf_adddocumentpattern " , arguments = " 2 strings " , actions = function ( a , b ) lpdf . adddocumentpattern ( a , pdfverbose ( b ) ) end }
1564implement { name = " lpdf_adddocumentshade " , arguments = " 2 strings " , actions = function ( a , b ) lpdf . adddocumentshade ( a , pdfverbose ( b ) ) end }
1565
1566
1567
1568function lpdf . copyconstant ( v )
1569 if v ~ = nil then
1570 return pdfconstant ( v )
1571 end
1572end
1573
1574function lpdf . copyboolean ( v )
1575 if v ~ = nil then
1576 return pdfboolean ( v )
1577 end
1578end
1579
1580function lpdf . copyunicode ( v )
1581 if v then
1582 return pdfunicode ( v )
1583 end
1584end
1585
1586function lpdf . copyarray ( a )
1587 if a then
1588 local t = pdfarray ( )
1589 for i = 1 , # a do
1590 t [ i ] = a ( i )
1591 end
1592 return t
1593 end
1594end
1595
1596function lpdf . copydictionary ( d )
1597 if d then
1598 local t = pdfdictionary ( )
1599 for k , v in next , d do
1600 t [ k ] = d ( k )
1601 end
1602 return t
1603 end
1604end
1605
1606function lpdf . copynumber ( v )
1607 return v
1608end
1609
1610function lpdf . copyinteger ( v )
1611 return v
1612end
1613
1614function lpdf . copyfloat ( v )
1615 return v
1616end
1617
1618function lpdf . copystring ( v )
1619 if v then
1620 return pdfstring ( v )
1621 end
1622end
1623
1624do
1625
1626 local pdfincludechar , pdfincludecharlist , pdfincludefont
1627 local pdfgetfontname , pdfgetfontobjnum
1628 local pdfsetmapfile , pdfsetmapline
1629
1630 updaters . register ( " backend.update.lpdf " , function ( )
1631 pdfincludechar = pdf . includechar
1632 pdfincludefont = pdf . includefont
1633 pdfincludecharlist = pdf . includecharlist
1634 pdfgetfontname = pdf . getfontname
1635 pdfgetfontobjnum = pdf . getfontobjnum
1636 pdfsetmapfile = pdf . mapfile
1637 pdfsetmapline = pdf . mapline
1638 end )
1639
1640 function lpdf . includechar ( f , c ) pdfincludechar ( f , c ) end
1641 function lpdf . includefont ( ... ) pdfincludefont ( ... ) end
1642
1643 function lpdf . includecharlist ( f , c ) pdfincludecharlist ( f , c ) end
1644
1645 function lpdf . getfontname ( id ) return pdfgetfontname ( id ) end
1646 function lpdf . getfontobjnumber ( id ) return pdfgetfontobjnum ( id ) end
1647
1648 function lpdf . setmapfile ( ... ) pdfsetmapfile ( ... ) end
1649 function lpdf . setmapline ( ... ) pdfsetmapline ( ... ) end
1650
1651end
1652
1653do
1654
1655
1656
1657
1658 local a_procset , d_procset
1659
1660 function lpdf . procset ( dict )
1661 if not a_procset then
1662 a_procset = pdfarray {
1663 pdfconstant ( " PDF " ) ,
1664 pdfconstant ( " Text " ) ,
1665 pdfconstant ( " ImageB " ) ,
1666 pdfconstant ( " ImageC " ) ,
1667 pdfconstant ( " ImageI " ) ,
1668 }
1669 a_procset = pdfreference ( pdfimmediateobject ( tostring ( a_procset ) ) )
1670 end
1671 if dict then
1672 if not d_procset then
1673 d_procset = pdfdictionary {
1674 ProcSet = a_procset
1675 }
1676 d_procset = pdfreference ( pdfimmediateobject ( tostring ( d_procset ) ) )
1677 end
1678 return d_procset
1679 else
1680 return a_procset
1681 end
1682 end
1683
1684end
1685
1686
1687
1688if environment . arguments . nocompression then
1689 lpdf . setcompression ( 0 , 0 , true )
1690end
1691 |