3 % Copyright
2009-2013 Taco Hoekwater
<taco@@luatex.org
>
5 % This file is part of LuaTeX.
7 % LuaTeX is free software
; you can redistribute it and
/or modify it under
8 % the terms of the GNU General Public License as published by the Free
9 % Software Foundation
; either version
2 of the License
, or
(at your
10 % option
) any later version.
12 % LuaTeX is distributed in the hope that it will be useful
, but WITHOUT
13 % ANY WARRANTY
; without even the implied warranty of MERCHANTABILITY or
14 % FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 % License for more details.
17 % You should have received a copy of the GNU General Public License along
18 % with LuaTeX
; if not
, see
<http
://www.gnu.org
/licenses
/>.
21 static const char _svn_version
[] =
28 #include
<kpathsea
/c-dir.h
>
29 #include
<kpathsea
/c-ctype.h
>
30 #include
"lua/luatex-api.h"
33 #define is_hex_char isxdigit
35 #define check_nprintf
(size_get
, size_want
) \
36 if
((unsigned
)(size_get
) >= (unsigned
)(size_want
)) \
37 luatex_fail
("snprintf failed: file %s, line %d", __FILE__
, __LINE__
);
39 PDF static_pdf
= NULL;
41 @ commandline interface
43 int pdf_output_option
;
45 int pdf_draftmode_option
;
46 int pdf_draftmode_value
;
48 halfword pdf_info_toks
; /* additional keys of Info dictionary
*/
49 halfword pdf_catalog_toks
; /* additional keys of Catalog dictionary
*/
50 halfword pdf_catalog_openaction
;
51 halfword pdf_names_toks
; /* additional keys of Names dictionary
*/
52 halfword pdf_trailer_toks
; /* additional keys of Trailer dictionary
*/
53 shipping_mode_e global_shipping_mode
= NOT_SHIPPING
; /* set to |shipping_mode| when |ship_out| starts
*/
55 @ Create a new buffer |strbuf_s| of size |size| and maximum allowed size |limit|.
56 Initialize it and set |p| to begin of data.
58 strbuf_s
*new_strbuf
(size_t size
, size_t limit
)
61 assert
(limit
>= size
);
62 b
= xtalloc
(1, strbuf_s
);
66 b-
>p
= b-
>data
= xtalloc
(b-
>size
, unsigned char
);
68 b-
>p
= b-
>data
= NULL; /* for other alloc
*/
72 @ Check that |n| bytes more fit into buffer
; increase it if required.
74 static void strbuf_room
(strbuf_s
* b
, size_t n
)
77 size_t l
= (size_t
) (b-
>p
- b-
>data
);
79 overflow
("PDF buffer", (unsigned
) b-
>size
);
80 if
(n
+ l
> b-
>size
) {
81 a
= (unsigned int
) (b-
>size
>> 2);
82 if
(n
+ l
> b-
>size
+ a
)
84 else if
(b-
>size
< b-
>limit
- a
)
85 b-
>size
= b-
>size
+ a
;
88 b-
>data
= xreallocarray
(b-
>data
, unsigned char
, (unsigned
) b-
>size
);
93 @ Seek to position |offset| within buffer. Position must be valid.
95 void strbuf_seek
(strbuf_s
* b
, off_t offset
)
97 assert
(offset
>= 0 && offset < (off_t) b->size);
98 b-
>p
= b-
>data
+ offset
;
101 @ Get the current buffer fill level
, the number of characters.
103 size_t strbuf_offset
(strbuf_s
* b
)
105 return
(size_t
) (b-
>p
- b-
>data
);
108 @ Put one character into buffer. Make room before if needed.
110 void strbuf_putchar
(strbuf_s
* b
, unsigned char c
)
112 if
((size_t
) (b-
>p
- b-
>data
+ 1) > b-
>size
)
117 @ Dump filled buffer part to PDF.
119 void strbuf_flush
(PDF pdf
, strbuf_s
* b
)
121 pdf_out_block
(pdf
, (const char
*) b-
>data
, strbuf_offset
(b
));
125 @ Free all dynamically allocated buffer structures.
127 void strbuf_free
(strbuf_s
* b
)
133 @ |init_pdf_struct
()| is called early
, only once
, from maincontrol.w
135 PDF init_pdf_struct
(PDF pdf
)
139 pdf
= xtalloc
(1, pdf_output_file
);
140 memset
(pdf
, 0, sizeof
(pdf_output_file
));
141 pdf-
>job_name
= makecstring
(job_name
);
143 pdf-
>o_mode
= OMODE_NONE
; /* will be set by |fix_o_mode
()|
*/
144 pdf-
>o_state
= ST_INITIAL
;
146 /* init PDF and object stream writing
*/
147 pdf-
>os
= os
= xtalloc
(1, os_struct
);
148 memset
(pdf-
>os
, 0, sizeof
(os_struct
));
149 os-
>buf
[PDFOUT_BUF
] = new_strbuf
(inf_pdfout_buf_size
, sup_pdfout_buf_size
);
150 os-
>buf
[OBJSTM_BUF
] = new_strbuf
(inf_objstm_buf_size
, sup_objstm_buf_size
);
151 os-
>buf
[LUASTM_BUF
] = new_strbuf
(0, 0);
152 os-
>obj
= xtalloc
(PDF_OS_MAX_OBJS
, os_obj_data
);
154 os-
>trigger_luastm
= false
;
156 os-
>curbuf
= PDFOUT_BUF
;
157 pdf-
>buf
= os-
>buf
[os-
>curbuf
];
159 pdf-
>fb
= new_strbuf
(1, 100000000);
161 pdf-
>stream_deflate
= false
;
162 pdf-
>stream_writing
= false
;
164 /* Sometimes it is neccesary to allocate memory for PDF output that cannot
165 be deallocated then
, so we use |mem| for this purpose.
*/
166 pdf-
>mem_size
= inf_pdf_mem_size
; /* allocated size of |mem| array
*/
167 pdf-
>mem
= xtalloc
(pdf-
>mem_size
, int
);
168 pdf-
>mem_ptr
= 1; /* the first word is not used so we can use zero as a value for testing
169 whether a pointer to |mem| is valid
*/
172 pdf-
>posstruct
= xtalloc
(1, posstructure
);
173 pdf-
>posstruct-
>pos.h
= 0;
174 pdf-
>posstruct-
>pos.v
= 0;
175 pdf-
>posstruct-
>dir
= dir_TLT
;
177 pdf-
>obj_tab_size
= (unsigned
) inf_obj_tab_size
; /* allocated size of |obj_tab| array
*/
178 pdf-
>obj_tab
= xtalloc
(pdf-
>obj_tab_size
+ 1, obj_entry
);
179 memset
(pdf-
>obj_tab
, 0, sizeof
(obj_entry
));
181 pdf-
>minor_version
= -1; /* unset
*/
182 pdf-
>decimal_digits
= 4;
184 pdf-
>image_gamma
= 65536;
185 pdf-
>image_hicolor
= 1;
186 pdf-
>image_apply_gamma
= 0;
187 pdf-
>objcompresslevel
= 0;
188 pdf-
>compress_level
= 0;
190 pdf-
>inclusion_copy_font
= 1;
191 pdf-
>replace_font
= 0;
192 pdf-
>pk_resolution
= 0;
193 pdf-
>pk_scale_factor
= 0;
195 init_dest_names
(pdf
);
196 pdf-
>page_resources
= NULL;
198 init_pdf_pagecalculations
(pdf
);
199 pdf-
>pdflua_ref
= new_pdflua
();
201 pdf-
>vfstruct
= new_vfstruct
();
206 @ We use |pdf_get_mem| to allocate memory in |mem|.
209 int pdf_get_mem
(PDF pdf
, int s
)
210 { /* allocate |s| words in |mem|
*/
213 if
(s
> sup_pdf_mem_size
- pdf-
>mem_ptr
)
214 overflow
("PDF memory size (pdf_mem_size)", (unsigned
) pdf-
>mem_size
);
215 if
(pdf-
>mem_ptr
+ s
> pdf-
>mem_size
) {
216 a
= pdf-
>mem_size
>> 2;
217 if
(pdf-
>mem_ptr
+ s
> pdf-
>mem_size
+ a
) {
218 pdf-
>mem_size
= pdf-
>mem_ptr
+ s
;
219 } else if
(pdf-
>mem_size
< sup_pdf_mem_size
- a
) {
220 pdf-
>mem_size
= pdf-
>mem_size
+ a
;
222 pdf-
>mem_size
= sup_pdf_mem_size
;
224 pdf-
>mem
= xreallocarray
(pdf-
>mem
, int
, (unsigned
) pdf-
>mem_size
);
227 pdf-
>mem_ptr
= pdf-
>mem_ptr
+ s
;
231 @ |get_o_mode| translates from |pdf_output| to |o_mode|.
234 static output_mode get_o_mode
(void
)
237 if
(pdf_output
> 0) {
238 if
(pdf_output
== 2009)
247 @ |fix_o_mode| freezes |pdf-
>o_mode| as soon as anything goes through
248 the backend
, be it \.
{PDF
}, \.
{DVI
}, or \.
{Lua
}.
251 void fix_o_mode
(PDF pdf
)
253 output_mode o_mode
= get_o_mode
();
254 if
(pdf-
>o_mode
== OMODE_NONE
)
255 pdf-
>o_mode
= o_mode
;
256 else if
(pdf-
>o_mode
!= o_mode
)
257 pdf_error
("setup", "\\pdfoutput can only be changed before anything is written to the output");
260 @ This ensures that |pdfminorversion| is set only before any bytes have
261 been written to the generated \.
{PDF
} file. Here also all variables for
262 \.
{PDF
} output are initialized
, the \.
{PDF
} file is opened by |ensure_pdf_open|
,
263 and the \.
{PDF
} header is written.
266 void fix_pdf_minorversion
(PDF pdf
)
268 if
(pdf-
>minor_version
< 0) { /* unset
*/
269 if
((pdf_minor_version
< 0) ||
(pdf_minor_version
> 9)) {
270 const char
*hlp
[] = { "The pdfminorversion must be between 0 and 9.", "I changed this to 4.", NULL };
272 (void
) snprintf
(msg
, 255, "LuaTeX error (illegal pdfminorversion %d)", (int
) pdf_minor_version
);
274 pdf_minor_version
= 4;
276 pdf-
>minor_version
= pdf_minor_version
;
278 /* Check that variables for \.
{PDF
} output are unchanged
*/
279 if
(pdf-
>minor_version
!= pdf_minor_version
)
280 pdf_error
("setup", "\\pdfminorversion cannot be changed after data is written to the PDF file");
281 if
(pdf-
>draftmode
!= pdf_draftmode
)
282 pdf_error
("setup", "\\pdfdraftmode cannot be changed after data is written to the PDF file");
284 if
(pdf-
>draftmode
!= 0) {
285 pdf-
>compress_level
= 0; /* re-fix it
, might have been changed inbetween
*/
286 pdf-
>objcompresslevel
= 0;
291 #define ZIP_BUF_SIZE
32768
293 #define check_err
(f
, fn
) \
295 luatex_fail
("zlib: %s() failed (error code %d)", fn
, f
)
298 static void write_zip
(PDF pdf
)
300 int flush
, err
= Z_OK
;
302 strbuf_s
*buf
= pdf-
>buf
;
303 z_stream
*s
= pdf-
>c_stream
;
304 boolean finish
= pdf-
>zip_write_state
== ZIP_FINISH
;
305 assert
(pdf-
>compress_level
> 0);
306 /* This was just to suppress the filename report in |luatex_fail|
307 but zlib errors are rare enough
(especially now that the
308 compress level is fixed
) that I don't care about the slightly
309 ugly error message that could result.
312 cur_file_name
= NULL;
314 if
(pdf-
>stream_length
== 0) {
316 s
= pdf-
>c_stream
= xtalloc
(1, z_stream
);
317 s-
>zalloc
= (alloc_func
) 0;
318 s-
>zfree
= (free_func
) 0;
319 s-
>opaque
= (voidpf
) 0;
320 check_err
(deflateInit
(s
, pdf-
>compress_level
), "deflateInit");
321 assert
(pdf-
>zipbuf
== NULL);
322 pdf-
>zipbuf
= xtalloc
(ZIP_BUF_SIZE
, char
);
324 check_err
(deflateReset
(s
), "deflateReset");
325 s-
>next_out
= (Bytef
*) pdf-
>zipbuf
;
326 s-
>avail_out
= ZIP_BUF_SIZE
;
329 assert
(pdf-
>zipbuf
!= NULL);
330 s-
>next_in
= buf-
>data
;
331 s-
>avail_in
= (uInt
) (buf-
>p
- buf-
>data
);
333 if
(s-
>avail_out
== 0 ||
(finish
&& s->avail_out < ZIP_BUF_SIZE)) {
334 zip_len
= ZIP_BUF_SIZE
- s-
>avail_out
;
335 pdf-
>gone
+= (off_t
) xfwrite
(pdf-
>zipbuf
, 1, zip_len
, pdf-
>file
);
336 pdf-
>last_byte
= pdf-
>zipbuf
[zip_len
- 1];
337 s-
>next_out
= (Bytef
*) pdf-
>zipbuf
;
338 s-
>avail_out
= ZIP_BUF_SIZE
;
341 if
(err
== Z_STREAM_END
) {
342 assert
(s-
>avail_in
== 0);
343 assert
(s-
>avail_out
== ZIP_BUF_SIZE
);
345 pdf-
>zip_write_state
= NO_ZIP
;
350 if
(s-
>avail_in
== 0)
354 err
= deflate
(s
, flush
);
355 if
(err
!= Z_OK
&& err != Z_STREAM_END)
356 luatex_fail
("zlib: deflate() failed (error code %d)", err
);
358 pdf-
>stream_length
= (off_t
) s-
>total_out
;
362 void zip_free
(PDF pdf
)
364 if
(pdf-
>zipbuf
!= NULL) {
365 check_err
(deflateEnd
(pdf-
>c_stream
), "deflateEnd");
368 xfree
(pdf-
>c_stream
);
372 static void write_nozip
(PDF pdf
)
374 strbuf_s
*buf
= pdf-
>buf
;
375 size_t l
= strbuf_offset
(buf
);
378 pdf-
>stream_length
= pdf_offset
(pdf
) - pdf-
>save_offset
;
380 (off_t
) xfwrite
((char
*) buf-
>data
, sizeof
(char
), l
, pdf-
>file
);
381 pdf-
>last_byte
= *(buf-
>p
- 1);
384 @ The PDF buffer is flushed by calling |pdf_flush|
, which checks the
385 variable |zip_write_state| and will compress the buffer before flushing if
386 neccesary. We call |pdf_begin_stream| to begin a stream and |pdf_end_stream|
387 to finish it. The stream contents will be compressed if compression is turn on.
390 void pdf_flush
(PDF pdf
)
391 { /* flush out the |pdf-
>buf|
*/
392 os_struct
*os
= pdf-
>os
;
393 off_t saved_pdf_gone
= pdf-
>gone
;
394 assert
(pdf-
>buf
== os-
>buf
[os-
>curbuf
]);
395 switch
(os-
>curbuf
) {
397 if
(pdf-
>draftmode
== 0) {
398 switch
(pdf-
>zip_write_state
) {
410 pdf-
>zip_write_state
= NO_ZIP
;
411 strbuf_seek
(pdf-
>buf
, 0);
412 if
(saved_pdf_gone
> pdf-
>gone
)
413 pdf_error
("file size", "File size exceeds architectural limits (pdf_gone wraps around)");
416 luaL_addsize
(&(os->b), strbuf_offset(pdf->buf));
417 pdf-
>buf-
>p
= pdf-
>buf-
>data
= (unsigned char
*) luaL_prepbuffer
(&(os->b)); /* for next stream piece */
427 static void pdf_buffer_select
(PDF pdf
, buffer_e buf
)
429 os_struct
*os
= pdf-
>os
;
430 if
(pdf-
>os_enable
&& buf == OBJSTM_BUF)
431 os-
>curbuf
= OBJSTM_BUF
; /* switch to object stream
*/
433 os-
>curbuf
= PDFOUT_BUF
; /* switch to PDF stream
*/
434 pdf-
>buf
= os-
>buf
[pdf-
>os-
>curbuf
];
437 @ create new \.
{/ObjStm
} object if required
, and set up cross reference info
440 static void pdf_prepare_obj
(PDF pdf
, int k
, int pdf_os_threshold
)
442 os_struct
*os
= pdf-
>os
;
443 strbuf_s
*obuf
= os-
>buf
[OBJSTM_BUF
];
444 assert
(os-
>curbuf
!= LUASTM_BUF
);
445 assert
(pdf_os_threshold
>= OBJSTM_ALWAYS
);
446 if
(pdf-
>objcompresslevel
>= pdf_os_threshold
)
447 pdf_buffer_select
(pdf
, OBJSTM_BUF
);
449 pdf_buffer_select
(pdf
, PDFOUT_BUF
);
450 assert
(pdf-
>buf
== os-
>buf
[os-
>curbuf
]);
451 switch
(os-
>curbuf
) {
453 obj_offset
(pdf
, k
) = pdf_offset
(pdf
);
454 obj_os_idx
(pdf
, k
) = PDF_OS_MAX_OBJS
; /* mark it as not included in any ObjStm
*/
460 if
(os-
>cur_objstm
== 0) {
462 (unsigned int
) pdf_create_obj
(pdf
, obj_type_objstm
, 0);
464 obuf-
>p
= obuf-
>data
; /* start fresh object stream
*/
465 os-
>ostm_ctr
++; /* only for statistics
*/
467 assert
(os-
>idx
< PDF_OS_MAX_OBJS
); /* for marking below
*/
468 obj_os_idx
(pdf
, k
) = (int
) os-
>idx
;
469 obj_os_objnum
(pdf
, k
) = (int
) os-
>cur_objstm
;
470 os-
>obj
[os-
>idx
].num
= k
;
471 os-
>obj
[os-
>idx
].off
= obuf-
>p
- obuf-
>data
;
478 @
* Low-level buffer checkers.
480 @ Set the active buffer pointer.
481 Make sure that there are at least |n| bytes free in that buffer
,
484 void pdf_room
(PDF pdf
, int n
)
486 os_struct
*os
= pdf-
>os
;
487 strbuf_s
*buf
= pdf-
>buf
;
488 if
((size_t
) (n
+ buf-
>p
- buf-
>data
) <= buf-
>size
)
490 assert
(buf
== os-
>buf
[os-
>curbuf
]);
491 switch
(os-
>curbuf
) {
493 if
((size_t
) n
> buf-
>size
)
494 overflow
("PDF output buffer", (unsigned
) buf-
>size
);
495 if
((size_t
) (n
+ buf-
>p
- buf-
>data
) < buf-
>limit
)
496 strbuf_room
(buf
, (size_t
) n
); /* grow it if possible
*/
501 if
((size_t
) n
> buf-
>size
)
502 overflow
("PDF output buffer", (unsigned
) buf-
>size
);
506 strbuf_room
(buf
, (size_t
) n
); /* just grow it
*/
514 void pdf_out_block
(PDF pdf
, const char
*s
, size_t n
)
517 strbuf_s
*buf
= pdf-
>buf
;
522 pdf_room
(pdf
, (int
) l
);
523 (void
) memcpy
(buf-
>p
, s
, l
);
531 __attribute__
((format
(printf
, 2, 3)))
532 void pdf_printf
(PDF pdf
, const char
*fmt
, ...
)
536 if
(pdf-
>printf_buf
== NULL) {
537 pdf-
>printf_buf
= xtalloc
(PRINTF_BUF_SIZE
, char
);
539 (void
) vsnprintf
(pdf-
>printf_buf
, PRINTF_BUF_SIZE
, fmt
, args
);
540 pdf_puts
(pdf
, pdf-
>printf_buf
);
544 @ print out a string to PDF buffer
546 void pdf_print
(PDF pdf
, str_number s
)
550 if
(s
>= STRING_OFFSET
) {
551 ss
= (const char
*) str_string
(s
);
553 pdf_out_block
(pdf
, ss
, l
);
560 @ print out a integer to PDF buffer
562 void pdf_print_int
(PDF pdf
, longinteger n
)
566 w
= snprintf
(s
, 23, "%" LONGINTEGER_PRI
"d", (LONGINTEGER_TYPE
) n
);
567 check_nprintf
(w
, 23);
568 pdf_out_block
(pdf
, (const char
*) s
, (size_t
) w
);
572 void print_pdffloat
(PDF pdf
, pdffloat f
)
575 int e
= f.e
, i
, j
, l
;
582 pdf_print_int
(pdf
, l
);
586 j
= snprintf
(a
, 23, "%d", l
+ ten_pow
[e
]);
588 for
(i
= e
; i
> 0; i--
) {
593 pdf_puts
(pdf
, (a
+ 1));
597 @ print out |s| as string in PDF output
599 void pdf_print_str
(PDF pdf
, const char
*s
)
601 const char
*orig
= s
;
602 int l
= (int
) strlen
(s
) - 1; /* last string index
*/
607 /* the next is not really safe
, the string could be
"(a)xx(b)" */
608 if
((s
[0] == '
('
) && (s[l] == ')')) {
612 if
((s
[0] != '
<'
) ||
(s
[l
] != '
>'
) || odd
((l
+ 1))) {
619 while
(is_hex_char
(*s
))
627 pdf_puts
(pdf
, orig
); /* it was a hex string after all
*/
630 @ begin a stream
(needs to have a stream dictionary also
)
632 void pdf_begin_stream
(PDF pdf
)
634 os_struct
*os
= pdf-
>os
;
635 strbuf_s
*lbuf
= os-
>buf
[LUASTM_BUF
];
636 assert
(os-
>curbuf
== PDFOUT_BUF
);
637 assert
(pdf-
>buf
== os-
>buf
[os-
>curbuf
]);
638 assert
(pdf-
>zip_write_state
== NO_ZIP
);
639 pdf_puts
(pdf
, "\nstream\n");
640 pdf_save_offset
(pdf
);
642 if
(os-
>trigger_luastm
) {
643 os-
>trigger_luastm
= false
; /* this was just a trigger
*/
644 luaL_buffinit
(Luas
, &(os->b));
645 lbuf-
>p
= lbuf-
>data
= (unsigned char
*) luaL_prepbuffer
(&(os->b));
646 lbuf-
>size
= lbuf-
>limit
= LUAL_BUFFERSIZE
;
647 os-
>curbuf
= LUASTM_BUF
;
648 pdf-
>buf
= os-
>buf
[os-
>curbuf
];
650 if
(pdf-
>stream_deflate
) {
651 assert
(pdf-
>compress_level
> 0);
652 pdf-
>zip_write_state
= ZIP_WRITING
;
654 pdf-
>stream_writing
= true
;
655 pdf-
>stream_length
= 0;
661 void pdf_end_stream
(PDF pdf
)
663 os_struct
*os
= pdf-
>os
;
664 strbuf_s
*lbuf
= os-
>buf
[LUASTM_BUF
];
666 assert
(pdf-
>buf
== os-
>buf
[os-
>curbuf
]);
667 switch
(os-
>curbuf
) {
669 if
(pdf-
>zip_write_state
== ZIP_WRITING
)
670 pdf-
>zip_write_state
= ZIP_FINISH
;
671 pdf_flush
(pdf
); /* sets pdf-
>last_byte
*/
674 luaL_addsize
(&(os->b), strbuf_offset(os->buf[LUASTM_BUF]));
675 luaL_pushresult
(&(os->b));
677 /* now the complete page stream is on the Lua stack
*/
678 /* TODO
: pagestream filter callback here
*/
680 ls.s
= lua_tolstring
(Luas
, -1, &ls.l);
681 lbuf-
>data
= (unsigned char
*) ls.s
;
682 lbuf-
>p
= lbuf-
>data
+ ls.l
;
683 os-
>curbuf
= LUASTM_BUF
;
684 pdf-
>buf
= os-
>buf
[os-
>curbuf
];
685 if
(pdf-
>zip_write_state
== ZIP_WRITING
) {
686 pdf-
>zip_write_state
= ZIP_FINISH
;
691 os-
>curbuf
= PDFOUT_BUF
;
692 pdf-
>buf
= os-
>buf
[os-
>curbuf
];
693 assert
(pdf-
>buf-
>data
== pdf-
>buf-
>p
);
701 assert
(pdf-
>zip_write_state
== NO_ZIP
);
702 assert
(os-
>curbuf
== PDFOUT_BUF
);
703 assert
(pdf-
>buf
== os-
>buf
[os-
>curbuf
]);
704 pdf-
>stream_deflate
= false
;
705 pdf-
>stream_writing
= false
;
706 pdf_out
(pdf
, '\n'
); /* doesn't really belong to the stream
*/
707 pdf_puts
(pdf
, "endstream");
708 /* write stream
/Length
*/
709 if
(pdf-
>seek_write_length
&& pdf->draftmode == 0) {
710 xfseeko
(pdf-
>file
, (off_t
)pdf-
>stream_length_offset
, SEEK_SET
,
712 fprintf
(pdf-
>file
, "%" LONGINTEGER_PRI
"i", (LONGINTEGER_TYPE
) pdf-
>stream_length
);
713 xfseeko
(pdf-
>file
, 0, SEEK_END
, pdf-
>job_name
);
715 pdf-
>seek_write_length
= false
;
718 @ To print |scaled| value to PDF output we need some subroutines to ensure
722 #define max_integer
0x7FFFFFFF /* $
2^
{31}-1$
*/
724 /* scaled value corresponds to
100in
, exact
, 473628672 */
725 scaled one_hundred_inch
= 7227 * 65536;
727 /* scaled value corresponds to
1in
(rounded to
4736287) */
728 scaled one_inch
= (7227 * 65536 + 50) / 100;
730 /* scaled value corresponds to
1truein
(rounded
!) */
731 scaled one_true_inch
= (7227 * 65536 + 50) / 100;
733 /* scaled value corresponds to
100bp
*/
734 scaled one_hundred_bp
= (7227 * 65536) / 72;
736 /* scaled value corresponds to
1bp
(rounded to
65782) */
737 /* changed on
20110411 to be exactly
65781, as in tex itself
,
738 because this value is also used for \pdfpxdimen
*/
739 scaled one_bp
= 65781;
743 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
747 @ The function |divide_scaled| divides |s| by |m| using |dd| decimal
748 digits of precision. It is defined in C because it is a good candidate
749 for optimizations that are not possible in pascal.
752 scaled round_xn_over_d
(scaled x
, int n
, unsigned int d
)
754 boolean positive
; /* was |x
>=0|?
*/
755 unsigned t
, u
, v
; /* intermediate quantities
*/
762 t
= (unsigned
) ((x
% 0100000) * n
);//printf
("t=%d\n",t
);
763 u
= (unsigned
) (((unsigned
) (x
) / 0100000) * (unsigned
) n
+ (t
/ 0100000));//printf
("u=%d\n",u
);
764 v
= (u
% d
) * 0100000 + (t
% 0100000);//printf
("v=%d\n",v
);
765 if
(u
/ d
>= 0100000)
768 u
= 0100000 * (u
/ d
) + (v
/ d
);
775 return
(-(scaled
) u
);
780 void pdf_add_bp
(PDF pdf
, scaled s
)
781 { /* print scaled as |bp|
*/
783 pdfstructure
*p
= pdf-
>pstruct
;
785 a.m
= i64round
(s
* p-
>k1
);
786 a.e
= pdf-
>decimal_digits
;
789 print_pdffloat
(pdf
, a
);
793 void pdf_add_mag_bp
(PDF pdf
, scaled s
)
794 { /* take |mag| into account
*/
796 pdfstructure
*p
= pdf-
>pstruct
;
798 if
(int_par
(mag_code
) != 1000)
799 a.m
= i64round
(s
* (double
) int_par
(mag_code
) / 1000.0 * p-
>k1
);
801 a.m
= i64round
(s
* p-
>k1
);
802 a.e
= pdf-
>decimal_digits
;
805 print_pdffloat
(pdf
, a
);
809 @
* handling page resources.
814 pdf_object_list
*list
;
818 static int comp_page_resources
(const void
*pa
, const void
*pb
, void
*p
)
822 a
= ((const pr_entry
*) pa
)->obj_type
;
823 b
= ((const pr_entry
*) pb
)->obj_type
;
832 void addto_page_resources
(PDF pdf
, pdf_obj_type t
, int k
)
834 pdf_resource_struct
*re
;
837 pdf_object_list
*p
, *item
= NULL;
839 re
= pdf-
>page_resources
;
841 assert
(t
<= PDF_OBJ_TYPE_MAX
);
842 if
(re-
>resources_tree
== NULL) {
844 avl_create
(comp_page_resources
, NULL, &avl_xallocator);
845 if
(re-
>resources_tree
== NULL)
847 ("addto_page_resources(): avl_create() page_resource_tree failed");
850 pr
= (pr_entry
*) avl_find
(re-
>resources_tree
, &tmp);
852 pr
= xtalloc
(1, pr_entry
);
855 pp
= avl_probe
(re-
>resources_tree
, pr
);
858 ("addto_page_resources(): avl_probe() out of memory in insertion");
860 if
(pr-
>list
== NULL) {
861 item
= xtalloc
(1, pdf_object_list
);
865 if
(obj_type
(pdf
, k
) == (int
)t
)
866 set_obj_scheduled
(pdf
, k
); /* k is an object number
*/
868 for
(p
= pr-
>list
; p-
>info
!= k
&& p->link != NULL; p = p->link);
870 item
= xtalloc
(1, pdf_object_list
);
874 if
(obj_type
(pdf
, k
) == (int
)t
)
875 set_obj_scheduled
(pdf
, k
);
881 pdf_object_list
*get_page_resources_list
(PDF pdf
, pdf_obj_type t
)
883 pdf_resource_struct
*re
= pdf-
>page_resources
;
885 if
(re
== NULL || re-
>resources_tree
== NULL)
888 pr
= (pr_entry
*) avl_find
(re-
>resources_tree
, &tmp);
895 static void reset_page_resources
(PDF pdf
)
897 pdf_resource_struct
*re
= pdf-
>page_resources
;
899 struct avl_traverser t
;
900 pdf_object_list
*l1
, *l2
;
901 if
(re
== NULL || re-
>resources_tree
== NULL)
903 avl_t_init
(&t, re->resources_tree);
904 for
(p
= avl_t_first
(&t, re->resources_tree); p != NULL; p = avl_t_next(&t)) {
905 if
(p-
>list
!= NULL) {
906 for
(l1
= p-
>list
; l1
!= NULL; l1
= l2
) {
910 p-
>list
= NULL; /* but the AVL tree remains
*/
916 static void destroy_pg_res_tree
(void
*pa
, void
*param
)
923 static void destroy_page_resources_tree
(PDF pdf
)
925 pdf_resource_struct
*re
= pdf-
>page_resources
;
926 reset_page_resources
(pdf
);
927 if
(re-
>resources_tree
!= NULL)
928 avl_destroy
(re-
>resources_tree
, destroy_pg_res_tree
);
929 re-
>resources_tree
= NULL;
932 @
* Subroutines to print out various PDF objects.
934 @ print out an integer |n| with fixed width |w|
; used for outputting cross-reference table
936 static void pdf_print_fw_int
(PDF pdf
, longinteger n
, size_t w
)
938 int k
; /* $
0\le k\le23$
*/
939 unsigned char digits
[24];
943 digits
[k
] = (unsigned char
) ('
0'
+ (n
% 10));
946 pdf_out_block
(pdf
, (const char
*) digits
, w
);
949 @ print out an integer |n| as a fixed number |w| of bytes
; used for outputting \.
{/XRef
} cross-reference stream
951 static void pdf_out_bytes
(PDF pdf
, longinteger n
, size_t w
)
954 unsigned char bytes
[8]; /* digits in a number being output
*/
958 bytes
[k
] = (unsigned char
) (n
% 256);
961 pdf_out_block
(pdf
, (const char
*) bytes
, w
);
964 @ print out |s| as string in PDF output
966 void pdf_print_str_ln
(PDF pdf
, const char
*s
)
968 pdf_print_str
(pdf
, s
);
973 void pdf_print_toks
(PDF pdf
, halfword p
)
976 char
*s
= tokenlist_to_cstring
(p
, true
, &len);
988 void pdf_add_rect_spec
(PDF pdf
, halfword r
)
990 pdf_add_mag_bp
(pdf
, pdf_ann_left
(r
));
991 pdf_add_mag_bp
(pdf
, pdf_ann_bottom
(r
));
992 pdf_add_mag_bp
(pdf
, pdf_ann_right
(r
));
993 pdf_add_mag_bp
(pdf
, pdf_ann_top
(r
));
996 @ output a rectangle specification to PDF file
998 void pdf_rectangle
(PDF pdf
, halfword r
)
1001 pdf_add_name
(pdf
, "Rect");
1002 pdf_begin_array
(pdf
);
1003 pdf_add_rect_spec
(pdf
, r
);
1008 static void init_pdf_outputparameters
(PDF pdf
)
1010 assert
(pdf-
>o_mode
== OMODE_PDF
);
1011 pdf-
>draftmode
= fix_int
(pdf_draftmode
, 0, 1);
1012 pdf-
>compress_level
= fix_int
(pdf_compress_level
, 0, 9);
1013 pdf-
>decimal_digits
= fix_int
(pdf_decimal_digits
, 0, 4);
1014 pdf-
>gamma
= fix_int
(pdf_gamma
, 0, 1000000);
1015 pdf-
>image_gamma
= fix_int
(pdf_image_gamma
, 0, 1000000);
1016 pdf-
>image_hicolor
= fix_int
(pdf_image_hicolor
, 0, 1);
1017 pdf-
>image_apply_gamma
= fix_int
(pdf_image_apply_gamma
, 0, 1);
1018 pdf-
>objcompresslevel
= fix_int
(pdf_objcompresslevel
, 0, MAX_OBJ_COMPRESS_LEVEL
);
1019 pdf-
>inclusion_copy_font
= fix_int
(pdf_inclusion_copy_font
, 0, 1);
1020 pdf-
>replace_font
= fix_int
(pdf_replace_font
, 0, 1);
1021 pdf-
>pk_resolution
= fix_int
(pdf_pk_resolution
, 72, 8000);
1022 if
((pdf-
>minor_version
>= 5) && (pdf->objcompresslevel > 0)) {
1023 pdf-
>os_enable
= true
;
1025 if
(pdf-
>objcompresslevel
> 0) {
1026 pdf_warning
("Object streams",
1027 "\\pdfobjcompresslevel > 0 requires \\pdfminorversion > 4. Object streams disabled now.",
1029 pdf-
>objcompresslevel
= 0;
1031 pdf-
>os_enable
= false
;
1033 if
(pdf-
>pk_resolution
== 0) /* if not set from format file or by user
*/
1034 pdf-
>pk_resolution
= pk_dpi
; /* take it from \.
{texmf.cnf
} */
1035 pdf-
>pk_scale_factor
=
1036 divide_scaled
(72, pdf-
>pk_resolution
, 5 + pdf-
>decimal_digits
);
1037 if
(!callback_defined
(read_pk_file_callback
)) {
1038 if
(pdf_pk_mode
!= null
) {
1039 char
*s
= tokenlist_to_cstring
(pdf_pk_mode
, true
, NULL);
1040 kpse_init_prog
("PDFTEX", (unsigned
) pdf-
>pk_resolution
, s
, nil
);
1043 kpse_init_prog
("PDFTEX", (unsigned
) pdf-
>pk_resolution
, nil
, nil
);
1045 if
(!kpse_var_value
("MKTEXPK"))
1046 kpse_set_program_enabled
(kpse_pk_format
, 1, kpse_src_cmdline
);
1048 set_job_id
(pdf
, int_par
(year_code
),
1049 int_par
(month_code
), int_par
(day_code
), int_par
(time_code
));
1050 if
((pdf_unique_resname
> 0) && (pdf->resname_prefix == NULL))
1051 pdf-
>resname_prefix
= get_resname_prefix
(pdf
);
1054 @ Checks that we have a name for the generated PDF file and that it's open.
1057 static void ensure_output_file_open
(PDF pdf
, const char
*ext
)
1060 if
(pdf-
>file_name
!= NULL)
1064 fn
= pack_job_name
(ext
);
1065 if
(pdf-
>draftmode
== 0 || pdf-
>o_mode
== OMODE_DVI
) {
1066 while
(!lua_b_open_out
(&pdf->file, fn))
1067 fn
= prompt_file_name
("file name for output", ext
);
1069 pdf-
>file_name
= fn
;
1073 static void ensure_pdf_header_written
(PDF pdf
)
1075 assert
(pdf-
>o_state
== ST_FILE_OPEN
);
1076 assert
(pdf-
>o_mode
== OMODE_PDF
);
1077 /* Initialize variables for \.
{PDF
} output
*/
1078 fix_pdf_minorversion
(pdf
);
1079 init_pdf_outputparameters
(pdf
);
1080 /* Write \.
{PDF
} header
*/
1081 pdf_printf
(pdf
, "%%PDF-1.%d\n", pdf-
>minor_version
);
1083 pdf_out
(pdf
, 'P'
+ 128);
1084 pdf_out
(pdf
, 'T'
+ 128);
1085 pdf_out
(pdf
, 'E'
+ 128);
1086 pdf_out
(pdf
, '
X'
+ 128);
1091 void ensure_output_state
(PDF pdf
, output_state s
)
1093 if
(pdf-
>o_state
< s
) {
1095 ensure_output_state
(pdf
, s
- 1);
1101 switch
(pdf-
>o_mode
) {
1103 ensure_output_file_open
(pdf
, ".dvi");
1106 ensure_output_file_open
(pdf
, ".pdf");
1115 switch
(pdf-
>o_mode
) {
1117 ensure_dvi_header_written
(pdf
);
1120 ensure_pdf_header_written
(pdf
);
1128 case ST_HEADER_WRITTEN
:
1130 case ST_FILE_CLOSED
:
1139 @ Write out an accumulated object stream.
1141 First the object number and byte offset pairs are generated
1142 and appended to the ready buffered object stream.
1143 By this the value of \.
{/First
} can be calculated.
1144 Then a new \.
{/ObjStm
} object is generated
, and everything is
1145 copied to the PDF output buffer
, where also compression is done.
1146 When calling this procedure
, |pdf_os_mode| must be |true|.
1149 static void pdf_os_write_objstream
(PDF pdf
)
1151 os_struct
*os
= pdf-
>os
;
1152 unsigned int i
, j
, n1
, n2
; /* n1
, n2
: ObjStm buffer may be reallocated
! */
1153 strbuf_s
*obuf
= os-
>buf
[OBJSTM_BUF
];
1154 if
(os-
>cur_objstm
== 0) /* no object stream started
*/
1156 assert
(pdf-
>buf
== obuf
); /* yes
, pdf_out
() still goes into ObjStm
*/
1157 assert
(os-
>idx
> 0); /* yes
, there are objects for the ObjStm
*/
1158 n1
= (unsigned int
) strbuf_offset
(obuf
); /* remember end of collected object stream contents
*/
1159 /* this is needed here to calculate
/First for the ObjStm dict
*/
1160 for
(i
= 0, j
= 0; i
< os-
>idx
; i
++) { /* add object-number
/byte-offset list to buffer
*/
1161 pdf_print_int
(pdf
, (int
) os-
>obj
[i
].num
);
1163 pdf_print_int
(pdf
, (int
) os-
>obj
[i
].off
);
1164 if
(j
== 9 || i
== os-
>idx
- 1) { /* print out in groups of ten for better readability
*/
1172 n2
= (unsigned int
) strbuf_offset
(obuf
); /* remember current buffer end
*/
1173 pdf_begin_obj
(pdf
, (int
) os-
>cur_objstm
, OBJSTM_NEVER
); /* switch to PDF stream writing
*/
1174 pdf_begin_dict
(pdf
);
1175 pdf_dict_add_name
(pdf
, "Type", "ObjStm");
1176 pdf_dict_add_int
(pdf
, "N", (int
) os-
>idx
); /* number of objects in ObjStm
*/
1177 pdf_dict_add_int
(pdf
, "First", (int
) (n2
- n1
));
1178 pdf_dict_add_streaminfo
(pdf
);
1180 pdf_begin_stream
(pdf
);
1181 /* write object-number
/byte-offset list
*/
1182 pdf_out_block
(pdf
, (const char
*) (obuf-
>data
+ n1
), (size_t
) (n2
- n1
));
1183 /* write collected object stream contents
*/
1184 pdf_out_block
(pdf
, (const char
*) obuf-
>data
, (size_t
) n1
);
1185 pdf_end_stream
(pdf
);
1187 os-
>cur_objstm
= 0; /* to force object stream generation next time
*/
1190 @ begin a PDF dictionary
1192 void pdf_begin_dict
(PDF pdf
)
1194 pdf_puts
(pdf
, "<<");
1198 @ end a PDF dictionary
1200 void pdf_end_dict
(PDF pdf
)
1202 pdf_puts
(pdf
, ">>");
1206 @ add integer object to dict
1208 void pdf_dict_add_bool
(PDF pdf
, const char
*key
, int i
)
1210 pdf_add_name
(pdf
, key
);
1211 pdf_add_bool
(pdf
, i
);
1214 @ add integer object to dict
1216 void pdf_dict_add_int
(PDF pdf
, const char
*key
, int i
)
1218 pdf_add_name
(pdf
, key
);
1219 pdf_add_int
(pdf
, i
);
1222 @ add name object to dict
1224 void pdf_dict_add_name
(PDF pdf
, const char
*key
, const char
*val
)
1226 pdf_add_name
(pdf
, key
);
1227 pdf_add_name
(pdf
, val
);
1230 @ add string object to dict
1232 void pdf_dict_add_string
(PDF pdf
, const char
*key
, const char
*val
)
1236 pdf_add_name
(pdf
, key
);
1240 pdf_print_str
(pdf
, val
);
1243 @ add name reference to dict
1245 void pdf_dict_add_ref
(PDF pdf
, const char
*key
, int num
)
1247 pdf_add_name
(pdf
, key
);
1248 pdf_add_ref
(pdf
, num
);
1251 @ add objects of different types
1253 void pdf_add_null
(PDF pdf
)
1257 pdf_puts
(pdf
, "null");
1261 void pdf_add_bool
(PDF pdf
, int i
)
1266 pdf_puts
(pdf
, "false");
1268 pdf_puts
(pdf
, "true");
1272 void pdf_add_int
(PDF pdf
, int i
)
1276 pdf_print_int
(pdf
, i
);
1280 void pdf_add_longint
(PDF pdf
, longinteger n
)
1284 pdf_print_int
(pdf
, n
);
1288 void pdf_add_string
(PDF pdf
, const char
*s
)
1292 pdf_print_str
(pdf
, s
);
1296 void pdf_add_name
(PDF pdf
, const char
*name
)
1299 pdf_puts
(pdf
, name
);
1303 void pdf_add_ref
(PDF pdf
, int num
)
1307 pdf_print_int
(pdf
, num
);
1308 pdf_puts
(pdf
, " 0 R");
1312 @ add stream length and filter entries to a stream dictionary
,
1313 remember file position for seek
1315 void pdf_dict_add_streaminfo
(PDF pdf
)
1317 assert
(pdf-
>buf
== pdf-
>os-
>buf
[PDFOUT_BUF
]);
1318 pdf_add_name
(pdf
, "Length");
1319 pdf-
>stream_length_offset
= pdf_offset
(pdf
) + 1;
1320 pdf-
>seek_write_length
= true
; /* fill in length at |pdf_end_stream| call
*/
1321 pdf_puts
(pdf
, " x "); /* space for
10 decimal digits
*/
1323 if
(pdf-
>compress_level
> 0) {
1324 pdf_dict_add_name
(pdf
, "Filter", "FlateDecode");
1325 pdf-
>stream_deflate
= true
;
1331 void pdf_begin_array
(PDF pdf
)
1339 void pdf_end_array
(PDF pdf
)
1345 @ begin a PDF object
1347 void pdf_begin_obj
(PDF pdf
, int i
, int pdf_os_threshold
)
1349 os_struct
*os
= pdf-
>os
;
1350 ensure_output_state
(pdf
, ST_HEADER_WRITTEN
);
1351 pdf_prepare_obj
(pdf
, i
, pdf_os_threshold
);
1352 assert
(pdf-
>buf
== os-
>buf
[os-
>curbuf
]);
1353 switch
(os-
>curbuf
) {
1355 pdf_printf
(pdf
, "%d 0 obj\n", (int
) i
);
1361 if
(pdf-
>compress_level
== 0)
1362 pdf_printf
(pdf
, "%% %d 0 obj\n", (int
) i
); /* debugging help
*/
1372 void pdf_end_obj
(PDF pdf
)
1374 os_struct
*os
= pdf-
>os
;
1375 assert
(pdf-
>buf
== os-
>buf
[os-
>curbuf
]);
1376 switch
(os-
>curbuf
) {
1378 pdf_puts
(pdf
, "\nendobj\n"); /* end a PDF object
*/
1384 os-
>idx
++; /* = number of objects collected so far in ObjStm
*/
1385 os-
>o_ctr
++; /* only for statistics
*/
1386 if
(os-
>idx
== PDF_OS_MAX_OBJS
)
1387 pdf_os_write_objstream
(pdf
);
1389 pdf_out
(pdf
, '\n'
); /* Adobe Reader seems to need this
*/
1396 @ Converts any string given in in in an allowed PDF string which can be
1397 handled by printf et.al.
: \.
{\\
} is escaped to \.
{\\\\
}, parenthesis are escaped and
1398 control characters are octal encoded.
1399 This assumes that the string does not contain any already escaped
1403 char
*convertStringToPDFString
(const char
*in
, int len
)
1405 static char pstrbuf
[MAX_PSTRING_LEN
];
1406 char
*out
= pstrbuf
;
1410 for
(i
= 0; i
< len
; i
++) {
1411 check_buf
((unsigned
) j
+ sizeof
(buf
), MAX_PSTRING_LEN
);
1412 if
(((unsigned char
) in
[i
] < '
!'
) ||
((unsigned char
) in
[i
] > '~'
)) {
1413 /* convert control characters into oct
*/
1414 k
= snprintf
(buf
, sizeof
(buf
), "\\%03o", (unsigned int
) (unsigned char
) in
[i
]);
1415 check_nprintf
(k
, sizeof
(buf
));
1420 } else if
((in
[i
] == '
('
) ||
(in
[i
] == '
)'
)) {
1421 /* escape paranthesis
*/
1424 } else if
(in
[i
] == '\\'
) {
1425 /* escape backslash
*/
1437 @ Converts any string given in in in an allowed PDF string which is
1438 hexadecimal encoded
;
1439 |sizeof
(out
)| should be at least $|lin|
*2+1$.
1442 static void convertStringToHexString
(const char
*in
, char
*out
, int lin
)
1447 for
(i
= 0; i
< lin
; i
++) {
1448 k
= snprintf
(buf
, sizeof
(buf
), "%02X", (unsigned int
) (unsigned char
) in
[i
]);
1449 check_nprintf
(k
, sizeof
(buf
));
1456 @ Compute the ID string as per PDF1.4
9.3:
1458 {\obeylines\obeyspaces
1459 File identifers are defined by the optional ID entry in a PDF file's
1460 trailer dictionary
(see Section
3.4.4, "File Trailer"; see also
1461 implementation note
105 in Appendix H
). The value of this entry is an
1462 array of two strings. The first string is a permanent identifier based
1463 on the contents of the file at the time it was originally created
, and
1464 does not change when the file is incrementally updated. The second
1465 string is a changing identifier based on the file's contents at the
1466 time it was last updated. When a file is first written
, both
1467 identifiers are set to the same value. If both identifiers match when a
1468 file reference is resolved
, it is very likely that the correct file has
1469 been found
; if only the first identifier matches
, then a different
1470 version of the correct file has been found.
1471 To help ensure the uniqueness of file identifiers
, it is recommend
1472 that they be computed using a message digest algorithm such as MD5
1473 (described in Internet RFC
1321, The MD5 Message-Digest Algorithm
; see
1474 the Bibliography
), using the following information
(see implementation
1475 note
106 in Appendix H
):
1477 - A string representation of the file's location
, usually a pathname
1478 - The size of the file in bytes
1479 - The values of all entries in the file's document information
1480 dictionary
(see Section
9.2.1, Document Information Dictionary
)
1483 This stipulates only that the two IDs must be identical when the file is
1484 created and that they should be reasonably unique. Since it's difficult
1485 to get the file size at this point in the execution of pdfTeX and
1486 scanning the info dict is also difficult
, we start with a simpler
1487 implementation using just the first two items.
1490 static void print_ID
(PDF pdf
)
1496 md5_byte_t digest
[16];
1503 size
= strftime
(time_str
, sizeof
(time_str
), "%Y%m%dT%H%M%SZ", gmtime
(&t));
1504 md5_append
(&state, (const md5_byte_t *) time_str, (int) size);
1505 /* get the file name
*/
1506 if
(getcwd
(pwd
, sizeof
(pwd
)) == NULL)
1507 luatex_fail
("getcwd() failed (%s), (path too long?)", strerror
(errno
));
1511 for
(p
= pwd
; *p
; p
++) {
1514 else if
(IS_KANJI
(p
))
1519 md5_append
(&state, (const md5_byte_t *) pwd, (int) strlen(pwd));
1520 md5_append
(&state, (const md5_byte_t *) "/", 1);
1521 md5_append
(&state, (const md5_byte_t *) pdf->file_name,
1522 (int
) strlen
(pdf-
>file_name
));
1524 md5_finish
(&state, digest);
1526 convertStringToHexString
((char
*) digest
, id
, 16);
1527 pdf_add_name
(pdf
, "ID");
1528 pdf_begin_array
(pdf
);
1529 pdf_printf
(pdf
, "<%s> <%s>", id
, id
);
1533 @ Print the
/CreationDate entry.
1535 PDF Reference
, third edition says about the expected date format
:
1537 {\obeylines\obeyspaces
1540 PDF defines a standard date format
, which closely follows that of
1541 the international standard ASN
.1 (Abstract Syntax Notation One
),
1542 defined in ISO
/IEC
8824 (see the Bibliography
). A date is a string
1545 (D
:YYYYMMDDHHmmSSOHH'mm'
)
1551 DD is the day
(01-31)
1552 HH is the hour
(00-23)
1553 mm is the minute
(00-59)
1554 SS is the second
(00-59)
1555 O is the relationship of local time to Universal Time
(UT
),
1556 denoted by one of the characters
+, -, or Z
(see below
)
1557 HH followed by ' is the absolute value of the offset from UT
1559 mm followed by ' is the absolute value of the offset from UT
1562 The apostrophe character
('
) after HH and mm is part of the syntax.
1563 All fields after the year are optional.
(The prefix D
:, although also
1564 optional
, is strongly recommended.
) The default values for MM and DD
1565 are both
01; all other numerical fields default to zero values. A plus
1566 sign
(+) as the value of the O field signifies that local time is
1567 later than UT
, a minus sign
(-) that local time is earlier than UT
,
1568 and the letter Z that local time is equal to UT. If no UT information
1569 is specified
, the relationship of the specified time to UT is
1570 considered to be unknown. Whether or not the time zone is known
, the
1571 rest of the date should be specified in local time.
1573 For example
, December
23, 1998, at
7:52 PM
, U.S. Pacific Standard
1574 Time
, is represented by the string
1576 D
:199812231952-08'
00'
1579 The main difficulty is get the time zone offset. |strftime
()| does this in ISO
1580 C99
(e.g. newer glibc
) with \
%z
, but we have to work with other systems
(e.g.
1584 #define TIME_STR_SIZE
30 /* minimum size for |time_str| is
24: |
"D:YYYYmmddHHMMSS+HH'MM'"|
*/
1586 static void makepdftime
(PDF pdf
)
1590 int i
, off
, off_hours
, off_mins
;
1591 time_t t
= pdf-
>start_time
;
1592 char
*time_str
= pdf-
>start_time_str
;
1595 lt
= *localtime
(&t);
1596 size
= strftime
(time_str
, TIME_STR_SIZE
, "D:%Y%m%d%H%M%S", <);
1597 /* expected format
: "YYYYmmddHHMMSS" */
1599 /* unexpected
, contents of |time_str| is undefined
*/
1604 /* correction for seconds
: \
%S can be in range
00.
.61,
1605 the PDF reference expects
00.
.59,
1606 therefore we map
"60" and
"61" to
"59" */
1607 if
(time_str
[14] == '
6'
) {
1610 time_str
[16] = '\
0'
; /* for safety
*/
1613 /* get the time zone offset
*/
1616 /* this calculation method was found in exim's tod.c
*/
1617 off
= 60 * (lt.tm_hour
- gmt.tm_hour
) + lt.tm_min
- gmt.tm_min
;
1618 if
(lt.tm_year
!= gmt.tm_year
) {
1619 off
+= (lt.tm_year
> gmt.tm_year
) ?
1440 : -1440;
1620 } else if
(lt.tm_yday
!= gmt.tm_yday
) {
1621 off
+= (lt.tm_yday
> gmt.tm_yday
) ?
1440 : -1440;
1625 time_str
[size
++] = 'Z'
;
1628 off_hours
= off
/ 60;
1629 off_mins
= abs
(off
- off_hours
* 60);
1630 i
= snprintf
(&time_str[size], 9, "%+03d'%02d'", off_hours, off_mins);
1631 check_nprintf
(i
, 9);
1633 pdf-
>start_time
= t
;
1637 void init_start_time
(PDF pdf
)
1640 if
(pdf-
>start_time
== 0) {
1641 pdf-
>start_time
= time
((time_t
*) NULL);
1642 pdf-
>start_time_str
= xtalloc
(TIME_STR_SIZE
, char
);
1648 char
*getcreationdate
(PDF pdf
)
1651 init_start_time
(pdf
);
1652 return pdf-
>start_time_str
;
1656 void remove_pdffile
(PDF pdf
)
1659 if
(!kpathsea_debug
&& pdf->file_name && (pdf->draftmode != 0)) {
1660 xfclose
(pdf-
>file
, pdf-
>file_name
);
1661 remove
(pdf-
>file_name
);
1667 void pdf_error
(const char
*t
, const char
*p
)
1669 normalize_selector
();
1670 print_err
("LuaTeX error");
1683 void pdf_warning
(const char
*t
, const char
*p
, boolean prepend_nl
,
1688 tprint
("LuaTeX warning");
1699 if
(history
== spotless
)
1700 history
= warning_issued
;
1703 @ Use |check_o_mode
()| in the backend-specific
"Implement..." chunks
1706 void check_o_mode
(PDF pdf
, const char
*s
, int o_mode_bitpattern
, boolean strict
)
1709 char warn_string
[100];
1711 const char
*m
= NULL;
1713 /* in warn mode
(strict
== false
):
1714 only check
, don't do |fix_o_mode
()| here
! |pdf-
>o_mode| is left
1715 in possibly wrong state until real output
, ok.
1718 if
(pdf-
>o_mode
== OMODE_NONE
)
1719 o_mode
= get_o_mode
();
1721 o_mode
= pdf-
>o_mode
;
1722 if
(!((1 << o_mode
) & o_mode_bitpattern)) { /* warning or error */
1736 snprintf
(warn_string
, 99, "not allowed in %s mode (\\pdfpoutput = %d)",
1737 m
, (int
) pdf_output
);
1739 pdf_error
(s
, warn_string
);
1741 pdf_warning
(s
, warn_string
, true
, true
);
1743 ensure_output_state
(pdf
, ST_HEADER_WRITTEN
);
1747 void set_job_id
(PDF pdf
, int year
, int month
, int day
, int time
)
1749 char
*name_string
, *format_string
, *s
;
1753 if
(pdf-
>job_id_string
!= NULL)
1756 name_string
= makecstring
(job_name
);
1757 format_string
= makecstring
(format_ident
);
1758 make_pdftex_banner
();
1759 slen
= SMALL_BUF_SIZE
+
1760 strlen
(name_string
) + strlen
(format_string
) + strlen
(pdftex_banner
);
1761 s
= xtalloc
(slen
, char
);
1762 /* The Web2c version string starts with a space.
*/
1763 i
= snprintf
(s
, slen
,
1764 "%.4d/%.2d/%.2d %.2d:%.2d %s %s %s",
1765 year
, month
, day
, time
/ 60, time
% 60,
1766 name_string
, format_string
, pdftex_banner
);
1767 check_nprintf
(i
, slen
);
1768 pdf-
>job_id_string
= xstrdup
(s
);
1771 xfree
(format_string
);
1775 char
*get_resname_prefix
(PDF pdf
)
1777 static char name_str
[] =
1778 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1779 static char prefix
[7]; /* make a tag of
6 chars long
*/
1782 size_t base
= strlen
(name_str
);
1783 crc
= crc32
(0L, Z_NULL
, 0);
1785 crc32
(crc
, (Bytef
*) pdf-
>job_id_string
,
1786 (uInt
) strlen
(pdf-
>job_id_string
));
1787 for
(i
= 0; i
< 6; i
++) {
1788 prefix
[i
] = name_str
[crc
% base
];
1796 #define mag int_par
(mag_code
)
1798 #define pdf_xform_attr equiv
(pdf_xform_attr_loc
)
1799 #define pdf_xform_resources equiv
(pdf_xform_resources_loc
)
1801 void pdf_begin_page
(PDF pdf
)
1804 scaled form_margin
= 0; /* was one_bp until SVN4066
*/
1805 ensure_output_state
(pdf
, ST_HEADER_WRITTEN
);
1806 init_pdf_pagecalculations
(pdf
);
1807 if
(pdf-
>page_resources
== NULL) {
1808 pdf-
>page_resources
= xtalloc
(1, pdf_resource_struct
);
1809 pdf-
>page_resources-
>resources_tree
= NULL;
1811 pdf-
>page_resources-
>last_resources
=
1812 pdf_create_obj
(pdf
, obj_type_others
, 0);
1813 reset_page_resources
(pdf
);
1815 if
(global_shipping_mode
== SHIPPING_PAGE
) {
1816 pdf-
>last_page
= pdf_get_obj
(pdf
, obj_type_page
, total_pages
+ 1, 0);
1817 set_obj_aux
(pdf
, pdf-
>last_page
, 1); /* mark that this page has been created
*/
1818 pdf-
>last_stream
= pdf_create_obj
(pdf
, obj_type_pagestream
, 0);
1819 pdf_begin_obj
(pdf
, pdf-
>last_stream
, OBJSTM_NEVER
);
1820 pdf-
>last_thread
= null
;
1821 pdf_begin_dict
(pdf
);
1822 pdflua_begin_page
(pdf
);
1824 assert
(global_shipping_mode
== SHIPPING_FORM
);
1825 pdf_begin_obj
(pdf
, pdf_cur_form
, OBJSTM_NEVER
);
1826 pdf-
>last_stream
= pdf_cur_form
;
1828 /* Write out Form stream header
*/
1829 pdf_begin_dict
(pdf
);
1830 pdf_dict_add_name
(pdf
, "Type", "XObject");
1831 pdf_dict_add_name
(pdf
, "Subtype", "Form");
1832 if
(pdf_xform_attr
!= null
)
1833 pdf_print_toks
(pdf
, pdf_xform_attr
);
1834 if
(obj_xform_attr
(pdf
, pdf_cur_form
) != null
) {
1835 pdf_print_toks
(pdf
, obj_xform_attr
(pdf
, pdf_cur_form
));
1836 delete_token_ref
(obj_xform_attr
(pdf
, pdf_cur_form
));
1837 set_obj_xform_attr
(pdf
, pdf_cur_form
, null
);
1839 pdf_add_name
(pdf
, "BBox");
1840 pdf_begin_array
(pdf
);
1841 pdf_add_bp
(pdf
, -form_margin
);
1842 pdf_add_bp
(pdf
, -form_margin
);
1843 pdf_add_bp
(pdf
, pdf-
>page_size.h
+ form_margin
);
1844 pdf_add_bp
(pdf
, pdf-
>page_size.v
+ form_margin
);
1846 pdf_dict_add_int
(pdf
, "FormType", 1);
1847 pdf_add_name
(pdf
, "Matrix");
1848 pdf_begin_array
(pdf
);
1849 pdf_add_int
(pdf
, 1);
1850 pdf_add_int
(pdf
, 0);
1851 pdf_add_int
(pdf
, 0);
1852 pdf_add_int
(pdf
, 1);
1853 pdf_add_int
(pdf
, 0);
1854 pdf_add_int
(pdf
, 0);
1856 pdf_dict_add_ref
(pdf
, "Resources", pdf-
>page_resources-
>last_resources
);
1858 /* Start stream of page
/form contents
*/
1859 pdf_dict_add_streaminfo
(pdf
);
1861 pdf-
>os-
>trigger_luastm
= false
; /* if it's true
, the page stream goes through Lua
*/
1862 pdf_begin_stream
(pdf
);
1863 if
(global_shipping_mode
== SHIPPING_PAGE
) {
1864 /* Adjust transformation matrix for the magnification ratio
*/
1866 setpdffloat
(f
, mag
, 3);
1867 print_pdffloat
(pdf
, f
);
1868 pdf_puts
(pdf
, " 0 0 ");
1869 print_pdffloat
(pdf
, f
);
1870 pdf_puts
(pdf
, " 0 0 cm\n");
1873 pos_stack_used
= 0; /* start with empty stack
*/
1875 if
(global_shipping_mode
== SHIPPING_PAGE
) {
1876 colorstackpagestart
();
1878 if
(global_shipping_mode
== SHIPPING_PAGE
)
1879 pdf_out_colorstack_startpage
(pdf
);
1883 void print_pdf_table_string
(PDF pdf
, const char
*s
)
1887 lua_rawgeti
(Luas
, LUA_REGISTRYINDEX
, lua_key_index
(pdf_data
));
1888 lua_rawget
(Luas
, LUA_REGISTRYINDEX
);
1889 lua_pushstring
(Luas
, s
); /* s t ...
*/
1890 lua_rawget
(Luas
, -2); /* s? t ...
*/
1891 if
(lua_isstring
(Luas
, -1)) { /* s t ...
*/
1892 ls
= lua_tolstring
(Luas
, -1, &len);
1896 pdf_out_block
(pdf
, ls
, len
);
1900 lua_pop
(Luas
, 2); /* ...
*/
1904 char
*get_pdf_table_string
(const char
*s
)
1907 lua_rawgeti
(Luas
, LUA_REGISTRYINDEX
, lua_key_index
(pdf_data
));
1908 lua_rawget
(Luas
, LUA_REGISTRYINDEX
);
1909 lua_pushstring
(Luas
, s
); /* s t ...
*/
1910 lua_rawget
(Luas
, -2); /* s? t ...
*/
1911 if
(lua_isstring
(Luas
, -1)) { /* s t ...
*/
1912 ls.s
= lua_tolstring
(Luas
, -1, &ls.l);
1913 lua_pop
(Luas
, 2); /* ...
*/
1914 return
(char
*)ls.s
;
1916 lua_pop
(Luas
, 2); /* ...
*/
1921 #define pdf_page_attr equiv
(pdf_page_attr_loc
)
1922 #define pdf_page_resources equiv
(pdf_page_resources_loc
)
1924 void pdf_end_page
(PDF pdf
)
1927 int j
, annots
= 0, beads
= 0, callback_id
;
1928 pdf_resource_struct
*res_p
= pdf-
>page_resources
;
1929 pdf_resource_struct local_page_resources
;
1930 pdf_object_list
*annot_list
, *bead_list
, *link_list
, *ol
, *ol1
;
1931 scaledpos save_cur_page_size
; /* to save |pdf-
>page_size| during flushing pending forms
*/
1932 shipping_mode_e save_shipping_mode
;
1933 int procset
= PROCSET_PDF
;
1935 /* Finish stream of page
/form contents
*/
1936 pdf_goto_pagemode
(pdf
);
1937 if
(pos_stack_used
> 0) {
1938 luatex_fail
("%u unmatched \\pdfsave after %s shipout",
1939 (unsigned int
) pos_stack_used
,
1940 ((global_shipping_mode
==
1941 SHIPPING_PAGE
) ?
"page" : "form"));
1943 pdf_end_stream
(pdf
);
1946 /* hh-ls
: new call back finish_pdfpage_callback
*/
1947 callback_id
= callback_defined
(finish_pdfpage_callback
);
1948 if
(callback_id
> 0)
1949 run_callback
(callback_id
, "b->",(global_shipping_mode
== SHIPPING_PAGE
));
1951 if
(global_shipping_mode
== SHIPPING_PAGE
) {
1953 pdf-
>last_pages
= pdf_do_page_divert
(pdf
, pdf-
>last_page
, 0);
1955 /* Write out
/Page object
*/
1956 pdf_begin_obj
(pdf
, pdf-
>last_page
, OBJSTM_ALWAYS
);
1957 pdf_begin_dict
(pdf
);
1958 pdf_dict_add_name
(pdf
, "Type", "Page");
1959 pdf_dict_add_ref
(pdf
, "Contents", pdf-
>last_stream
);
1960 pdf_dict_add_ref
(pdf
, "Resources", res_p-
>last_resources
);
1961 pdf_add_name
(pdf
, "MediaBox");
1962 pdf_begin_array
(pdf
);
1963 pdf_add_int
(pdf
, 0);
1964 pdf_add_int
(pdf
, 0);
1965 pdf_add_mag_bp
(pdf
, pdf-
>page_size.h
);
1966 pdf_add_mag_bp
(pdf
, pdf-
>page_size.v
);
1968 if
(pdf_page_attr
!= null
)
1969 pdf_print_toks
(pdf
, pdf_page_attr
);
1970 print_pdf_table_string
(pdf
, "pageattributes");
1971 pdf_dict_add_ref
(pdf
, "Parent", pdf-
>last_pages
);
1972 if
(pdf-
>img_page_group_val
!= 0) {
1973 assert
(pdf-
>img_page_group_val
> 0);
1974 pdf_dict_add_ref
(pdf
, "Group", pdf-
>img_page_group_val
);
1976 annot_list
= get_page_resources_list
(pdf
, obj_type_annot
);
1977 link_list
= get_page_resources_list
(pdf
, obj_type_link
);
1978 if
(annot_list
!= NULL || link_list
!= NULL) {
1979 annots
= pdf_create_obj
(pdf
, obj_type_annots
, 0);
1980 pdf_dict_add_ref
(pdf
, "Annots", annots
);
1982 bead_list
= get_page_resources_list
(pdf
, obj_type_bead
);
1983 if
(bead_list
!= NULL) {
1984 beads
= pdf_create_obj
(pdf
, obj_type_beads
, 0);
1985 pdf_dict_add_ref
(pdf
, "B", beads
);
1989 pdflua_end_page
(pdf
, annots
, beads
);
1991 pdf-
>img_page_group_val
= 0;
1993 /* Generate array of annotations or beads in page
*/
1994 if
(annot_list
!= NULL || link_list
!= NULL) {
1995 pdf_begin_obj
(pdf
, annots
, OBJSTM_ALWAYS
);
1996 pdf_begin_array
(pdf
);
1997 while
(annot_list
!= NULL) {
1998 assert
(annot_list-
>info
> 0);
1999 pdf_add_ref
(pdf
, annot_list-
>info
);
2000 annot_list
= annot_list-
>link
;
2002 while
(link_list
!= NULL) {
2003 pdf_add_ref
(pdf
, link_list-
>info
);
2004 link_list
= link_list-
>link
;
2009 if
(bead_list
!= NULL) {
2010 pdf_begin_obj
(pdf
, beads
, OBJSTM_ALWAYS
);
2011 pdf_begin_array
(pdf
);
2012 while
(bead_list
!= NULL) {
2013 pdf_add_ref
(pdf
, bead_list-
>info
);
2014 bead_list
= bead_list-
>link
;
2021 /* Write out resource lists
*/
2022 /* Write out pending raw objects
*/
2023 ol
= get_page_resources_list
(pdf
, obj_type_obj
);
2024 while
(ol
!= NULL) {
2025 if
(!is_obj_written
(pdf
, ol-
>info
))
2026 pdf_write_obj
(pdf
, ol-
>info
);
2030 /* Write out pending forms
*/
2031 /* When flushing pending forms we need to save and restore resource lists
2032 which are also used by page shipping.
2033 Saving and restoring |pdf-
>page_size| is needed for proper
2034 writing out pending PDF marks.
*/
2035 ol
= get_page_resources_list
(pdf
, obj_type_xform
);
2036 while
(ol
!= NULL) {
2037 if
(!is_obj_written
(pdf
, ol-
>info
)) {
2038 pdf_cur_form
= ol-
>info
;
2039 save_cur_page_size
= pdf-
>page_size
;
2040 save_shipping_mode
= global_shipping_mode
;
2041 pdf-
>page_resources
= &local_page_resources;
2042 local_page_resources.resources_tree
= NULL;
2043 ship_out
(pdf
, obj_xform_box
(pdf
, pdf_cur_form
), SHIPPING_FORM
);
2044 /* Restore page size and page resources
*/
2045 pdf-
>page_size
= save_cur_page_size
;
2046 global_shipping_mode
= save_shipping_mode
;
2047 destroy_page_resources_tree
(pdf
);
2048 pdf-
>page_resources
= res_p
;
2053 /* Write out pending images
*/
2054 ol
= get_page_resources_list
(pdf
, obj_type_ximage
);
2055 while
(ol
!= NULL) {
2056 if
(!is_obj_written
(pdf
, ol-
>info
))
2057 pdf_write_image
(pdf
, ol-
>info
);
2061 if
(global_shipping_mode
== SHIPPING_PAGE
) {
2062 /* Write out pending PDF marks
*/
2063 /* Write out PDF annotations
*/
2064 ol
= get_page_resources_list
(pdf
, obj_type_annot
);
2065 while
(ol
!= NULL) {
2066 if
(ol-
>info
> 0 && obj_type(pdf, ol->info) == obj_type_annot) {
2067 j
= obj_annot_ptr
(pdf
, ol-
>info
); /* |j| points to |pdf_annot_node|
*/
2068 pdf_begin_obj
(pdf
, ol-
>info
, OBJSTM_ALWAYS
);
2069 pdf_begin_dict
(pdf
);
2070 pdf_dict_add_name
(pdf
, "Type", "Annot");
2071 pdf_print_toks
(pdf
, pdf_annot_data
(j
));
2072 pdf_rectangle
(pdf
, j
);
2079 /* Write out PDF link annotations
*/
2080 if
((ol
= get_page_resources_list
(pdf
, obj_type_link
)) != NULL) {
2081 while
(ol
!= NULL) {
2082 j
= obj_annot_ptr
(pdf
, ol-
>info
);
2083 pdf_begin_obj
(pdf
, ol-
>info
, OBJSTM_ALWAYS
);
2084 pdf_begin_dict
(pdf
);
2085 pdf_dict_add_name
(pdf
, "Type", "Annot");
2086 if
(pdf_action_type
(pdf_link_action
(j
)) != pdf_action_user
)
2087 pdf_dict_add_name
(pdf
, "Subtype", "Link");
2088 if
(pdf_link_attr
(j
) != null
)
2089 pdf_print_toks
(pdf
, pdf_link_attr
(j
));
2090 pdf_rectangle
(pdf
, j
);
2091 if
(pdf_action_type
(pdf_link_action
(j
)) != pdf_action_user
)
2092 pdf_puts
(pdf
, "/A ");
2093 write_action
(pdf
, pdf_link_action
(j
));
2098 /* Flush |pdf_start_link_node|'s created by |append_link|
*/
2099 ol
= get_page_resources_list
(pdf
, obj_type_link
);
2100 while
(ol
!= NULL) {
2101 j
= obj_annot_ptr
(pdf
, ol-
>info
);
2102 /* nodes with |subtype
= pdf_link_data_node| were created by |append_link| and
2103 must be flushed here
, as they are not linked in any list
*/
2104 if
(subtype
(j
) == pdf_link_data_node
)
2110 /* Write out PDF mark destinations
*/
2111 write_out_pdf_mark_destinations
(pdf
);
2112 /* Write out PDF bead rectangle specifications
*/
2113 print_bead_rectangles
(pdf
);
2116 /* Write out resources dictionary
*/
2117 pdf_begin_obj
(pdf
, res_p-
>last_resources
, OBJSTM_ALWAYS
);
2118 pdf_begin_dict
(pdf
);
2119 /* Print additional resources
*/
2120 if
(global_shipping_mode
== SHIPPING_PAGE
) {
2121 if
(pdf_page_resources
!= null
)
2122 pdf_print_toks
(pdf
, pdf_page_resources
);
2123 print_pdf_table_string
(pdf
, "pageresources");
2125 if
(pdf_xform_resources
!= null
)
2126 pdf_print_toks
(pdf
, pdf_xform_resources
);
2127 if
(obj_xform_resources
(pdf
, pdf_cur_form
) != null
) {
2128 pdf_print_toks
(pdf
, obj_xform_resources
(pdf
, pdf_cur_form
));
2129 delete_token_ref
(obj_xform_resources
(pdf
, pdf_cur_form
));
2130 set_obj_xform_resources
(pdf
, pdf_cur_form
, null
);
2134 /* Generate font resources
*/
2135 if
((ol
= get_page_resources_list
(pdf
, obj_type_font
)) != NULL) {
2136 pdf_add_name
(pdf
, "Font");
2137 pdf_begin_dict
(pdf
);
2138 while
(ol
!= NULL) {
2139 assert
(ol-
>info
> 0); /* always base font
: an object number
*/
2141 p
+= snprintf
(p
, 20, "F%i", obj_info
(pdf
, ol-
>info
));
2142 if
(pdf-
>resname_prefix
!= NULL)
2143 p
+= snprintf
(p
, 20, "%s", pdf-
>resname_prefix
);
2144 pdf_dict_add_ref
(pdf
, s
, ol-
>info
);
2148 procset |
= PROCSET_TEXT
;
2151 /* Generate XObject resources
*/
2152 ol
= get_page_resources_list
(pdf
, obj_type_xform
);
2153 ol1
= get_page_resources_list
(pdf
, obj_type_ximage
);
2154 if
(ol
!= NULL || ol1
!= NULL) {
2155 pdf_add_name
(pdf
, "XObject");
2156 pdf_begin_dict
(pdf
);
2157 while
(ol
!= NULL) {
2159 p
+= snprintf
(p
, 20, "Fm%i", obj_info
(pdf
, ol-
>info
));
2160 if
(pdf-
>resname_prefix
!= NULL)
2161 p
+= snprintf
(p
, 20, "%s", pdf-
>resname_prefix
);
2162 pdf_dict_add_ref
(pdf
, s
, ol-
>info
);
2165 while
(ol1
!= null
) {
2167 p
+= snprintf
(p
, 20, "Im%i", obj_info
(pdf
, ol1-
>info
));
2168 if
(pdf-
>resname_prefix
!= NULL)
2169 p
+= snprintf
(p
, 20, "%s", pdf-
>resname_prefix
);
2170 pdf_dict_add_ref
(pdf
, s
, ol1-
>info
);
2171 procset |
= img_procset
(idict_array
[obj_data_ptr
(pdf
, ol1-
>info
)]);
2177 /* Generate ProcSet
*/
2178 pdf_add_name
(pdf
, "ProcSet");
2179 pdf_begin_array
(pdf
);
2180 if
((procset
& PROCSET_PDF) != 0)
2181 pdf_add_name
(pdf
, "PDF");
2182 if
((procset
& PROCSET_TEXT) != 0)
2183 pdf_add_name
(pdf
, "Text");
2184 if
((procset
& PROCSET_IMAGE_B) != 0)
2185 pdf_add_name
(pdf
, "ImageB");
2186 if
((procset
& PROCSET_IMAGE_C) != 0)
2187 pdf_add_name
(pdf
, "ImageC");
2188 if
((procset
& PROCSET_IMAGE_I) != 0)
2189 pdf_add_name
(pdf
, "ImageI");
2195 @
* Finishing the PDF output file.
2197 @ Destinations that have been referenced but don't exists have
2198 |obj_dest_ptr
=null|. Leaving them undefined might cause troubles for
2199 PDF browsers
, so we need to fix them
; they point to the last page.
2202 static void check_nonexisting_destinations
(PDF pdf
)
2205 for
(k
= pdf-
>head_tab
[obj_type_dest
]; k
!= 0; k
= obj_link
(pdf
, k
)) {
2206 if
(obj_dest_ptr
(pdf
, k
) == null
) {
2207 pdf_warning
("dest", NULL, false
, false
);
2208 if
(obj_info
(pdf
, k
) < 0) {
2210 print
(-obj_info
(pdf
, k
));
2214 print_int
(obj_info
(pdf
, k
));
2217 (" has been referenced but does not exist, replaced by a fixed one");
2221 pdf_begin_obj
(pdf
, k
, OBJSTM_ALWAYS
);
2222 pdf_begin_array
(pdf
);
2223 pdf_add_ref
(pdf
, pdf-
>last_page
);
2224 pdf_add_name
(pdf
, "Fit");
2232 static void check_nonexisting_pages
(PDF pdf
)
2234 struct avl_traverser t
;
2236 struct avl_table
*page_tree
= pdf-
>obj_tree
[obj_type_page
];
2237 avl_t_init
(&t, page_tree);
2238 /* search from the end backward until the last real page is found
*/
2239 for
(p
= avl_t_last
(&t, page_tree);
2240 p
!= NULL && obj_aux(pdf, p->objptr) == 0; p = avl_t_prev(&t)) {
2241 pdf_warning
("dest", "Page ", false
, false
);
2242 print_int
(obj_info
(pdf
, p-
>objptr
));
2243 tprint
(" has been referenced but does not exist!");
2249 @ If the same keys in a dictionary are given several times
, then it is not
2250 defined which value is choosen by an application. Therefore the keys
2251 |
/Producer| and |
/Creator| are only set if the token list
2252 |pdf_info_toks| converted to a string does not contain these key strings.
2255 static boolean substr_of_str
(const char
*s
, const char
*t
)
2257 if
(strstr
(t
, s
) == NULL)
2262 static int pdf_print_info
(PDF pdf
, int luatexversion
,
2263 str_number luatexrevision
)
2264 { /* print info object
*/
2265 boolean creator_given
, producer_given
, creationdate_given
, moddate_given
,
2270 k
= pdf_create_obj
(pdf
, obj_type_info
, 0);
2271 pdf_begin_obj
(pdf
, k
, 3); /* keep Info readable unless explicitely forced
*/
2272 creator_given
= false
;
2273 producer_given
= false
;
2274 creationdate_given
= false
;
2275 moddate_given
= false
;
2276 trapped_given
= false
;
2277 pdf_begin_dict
(pdf
);
2278 if
(pdf_info_toks
!= 0) {
2279 s
= tokenlist_to_cstring
(pdf_info_toks
, true
, &len);
2280 creator_given
= substr_of_str
("/Creator", s
);
2281 producer_given
= substr_of_str
("/Producer", s
);
2282 creationdate_given
= substr_of_str
("/CreationDate", s
);
2283 moddate_given
= substr_of_str
("/ModDate", s
);
2284 trapped_given
= substr_of_str
("/Trapped", s
);
2286 p
= get_pdf_table_string
("info");
2287 if
(strlen
(p
) > 0) {
2288 creator_given
= creator_given || substr_of_str
("/Creator", p
);
2289 producer_given
= producer_given || substr_of_str
("/Producer", p
);
2290 creationdate_given
= creationdate_given || substr_of_str
("/CreationDate", p
);
2291 moddate_given
= moddate_given || substr_of_str
("/ModDate", p
);
2292 trapped_given
= trapped_given || substr_of_str
("/Trapped", p
);
2294 if
(pdf_info_toks
!= null
) {
2301 delete_token_ref
(pdf_info_toks
);
2302 pdf_info_toks
= null
;
2304 if
(strlen
(p
) > 0) {
2306 pdf_puts
(pdf
, p
); /* no free
, pointer
*/
2309 if
(!producer_given
) {
2310 /* Print the Producer key
*/
2311 pdf_add_name
(pdf
, "Producer");
2312 pdf_puts
(pdf
, " (LuaTeX-");
2313 pdf_print_int
(pdf
, luatexversion
/ 100);
2315 pdf_print_int
(pdf
, luatexversion
% 100);
2317 pdf_print
(pdf
, luatexrevision
);
2321 pdf_dict_add_string
(pdf
, "Creator", "TeX");
2322 if
(!creationdate_given
) {
2323 init_start_time
(pdf
);
2324 pdf_dict_add_string
(pdf
, "CreationDate", pdf-
>start_time_str
);
2326 if
(!moddate_given
) {
2327 init_start_time
(pdf
);
2328 pdf_dict_add_string
(pdf
, "ModDate", pdf-
>start_time_str
);
2330 if
(!trapped_given
) {
2331 pdf_dict_add_name
(pdf
, "Trapped", "False");
2333 pdf_dict_add_string
(pdf
, "PTEX.Fullbanner", pdftex_banner
);
2339 static void build_free_object_list
(PDF pdf
)
2343 set_obj_fresh
(pdf
, l
); /* null object at begin of list of free objects
*/
2344 for
(k
= 1; k
<= pdf-
>obj_ptr
; k
++) {
2345 if
(!is_obj_written
(pdf
, k
)) {
2346 set_obj_link
(pdf
, l
, k
);
2350 set_obj_link
(pdf
, l
, 0);
2353 @ Now the finish of PDF output file. At this moment all Page objects
2354 are already written completely to PDF output file.
2357 void finish_pdf_file
(PDF pdf
, int luatexversion
, str_number luatexrevision
)
2360 int root
, info
, xref_stm
= 0, outlines
, threads
, names_tree
;
2361 size_t xref_offset_width
;
2362 int callback_id
= callback_defined
(stop_run_callback
);
2363 int callback_id1
= callback_defined
(finish_pdffile_callback
);
2365 if
(total_pages
== 0) {
2366 if
(callback_id
== 0) {
2367 tprint_nl
("No pages of output.");
2369 } else if
(callback_id
> 0) {
2370 run_callback
(callback_id
, "->");
2375 if
(pdf-
>draftmode
== 0) {
2376 pdf_flush
(pdf
); /* to make sure that the output file name has been already created
*/
2377 flush_jbig2_page0_objects
(pdf
); /* flush page
0 objects from JBIG2 images
, if any
*/
2378 if
(callback_id1
> 0)
2379 run_callback
(callback_id1
, "->");
2381 check_nonexisting_pages
(pdf
);
2382 check_nonexisting_destinations
(pdf
);
2384 /* Output fonts definition
*/
2385 for
(k
= 1; k
<= max_font_id
(); k
++) {
2386 if
(font_used
(k
) && (pdf_font_num(k) < 0)) {
2387 i
= -pdf_font_num
(k
);
2388 assert
(pdf_font_num
(i
) > 0);
2389 for
(j
= font_bc
(k
); j
<= font_ec
(k
); j
++)
2390 if
(quick_char_exists
(k
, j
) && pdf_char_marked(k, j))
2391 pdf_mark_char
(i
, j
);
2392 if
((pdf_font_attr
(i
) == 0) && (pdf_font_attr(k) != 0)) {
2393 set_pdf_font_attr
(i
, pdf_font_attr
(k
));
2394 } else if
((pdf_font_attr
(k
) == 0)
2395 && (pdf_font_attr(i) != 0)) {
2396 set_pdf_font_attr
(k
, pdf_font_attr
(i
));
2397 } else if
((pdf_font_attr
(i
) != 0)
2398 && (pdf_font_attr(k) != 0)
2401 (pdf_font_attr
(i
), pdf_font_attr
(k
)))) {
2402 pdf_warning
("\\pdffontattr", "fonts ", false
, false
);
2403 print_font_identifier
(i
);
2405 print_font_identifier
(k
);
2407 (" have conflicting attributes; I will ignore the attributes assigned to ");
2408 print_font_identifier
(i
);
2414 pdf-
>gen_tounicode
= pdf_gen_tounicode
;
2415 k
= pdf-
>head_tab
[obj_type_font
];
2417 int f
= obj_info
(pdf
, k
);
2418 assert
(pdf_font_num
(f
) > 0);
2419 assert
(pdf_font_num
(f
) == k
);
2420 do_pdf_font
(pdf
, f
);
2421 k
= obj_link
(pdf
, k
);
2423 write_fontstuff
(pdf
);
2425 pdf-
>last_pages
= output_pages_tree
(pdf
);
2426 pdflua_output_pages_tree
(pdf
);
2427 /* Output outlines
*/
2428 outlines
= print_outlines
(pdf
);
2430 /* Output name tree
*/
2431 /* The name tree is very similiar to Pages tree so its construction should be
2432 certain from Pages tree construction. For intermediate node |obj_info| will be
2433 the first name and |obj_link| will be the last name in \.
{\\Limits
} array.
2434 Note that |pdf_dest_names_ptr| will be less than |obj_ptr|
, so we test if
2435 |k
< pdf_dest_names_ptr| then |k| is index of leaf in |dest_names|
; else
2436 |k| will be index in |obj_tab| of some intermediate node.
2438 names_tree
= output_name_tree
(pdf
);
2440 /* Output article threads
*/
2441 if
(pdf-
>head_tab
[obj_type_thread
] != 0) {
2442 threads
= pdf_create_obj
(pdf
, obj_type_others
, 0);
2443 pdf_begin_obj
(pdf
, threads
, OBJSTM_ALWAYS
);
2444 pdf_begin_array
(pdf
);
2445 k
= pdf-
>head_tab
[obj_type_thread
];
2447 pdf_add_ref
(pdf
, k
);
2448 k
= obj_link
(pdf
, k
);
2452 k
= pdf-
>head_tab
[obj_type_thread
];
2455 k
= obj_link
(pdf
, k
);
2461 /* Output the
/Catalog object
*/
2462 root
= pdf_create_obj
(pdf
, obj_type_catalog
, 0);
2463 pdf_begin_obj
(pdf
, root
, OBJSTM_ALWAYS
);
2464 pdf_begin_dict
(pdf
);
2465 pdf_dict_add_name
(pdf
, "Type", "Catalog");
2466 pdf_dict_add_ref
(pdf
, "Pages", pdf-
>last_pages
);
2468 pdf_dict_add_ref
(pdf
, "Threads", threads
);
2470 pdf_dict_add_ref
(pdf
, "Outlines", outlines
);
2471 if
(names_tree
!= 0)
2472 pdf_dict_add_ref
(pdf
, "Names", names_tree
);
2473 if
(pdf_catalog_toks
!= null
) {
2474 pdf_print_toks
(pdf
, pdf_catalog_toks
);
2475 delete_token_ref
(pdf_catalog_toks
);
2476 pdf_catalog_toks
= null
;
2478 print_pdf_table_string
(pdf
, "catalog");
2479 if
(pdf_catalog_openaction
!= 0)
2480 pdf_dict_add_ref
(pdf
, "OpenAction", pdf_catalog_openaction
);
2484 /* last candidate for object stream
*/
2485 info
= pdf_print_info
(pdf
, luatexversion
, luatexrevision
); /* final object for pdf-
>os_enable
== false
*/
2487 if
(pdf-
>os_enable
) {
2488 pdf_buffer_select
(pdf
, OBJSTM_BUF
);
2489 pdf_os_write_objstream
(pdf
);
2491 pdf_buffer_select
(pdf
, PDFOUT_BUF
);
2492 /* Output the cross-reference stream dictionary
*/
2493 xref_stm
= pdf_create_obj
(pdf
, obj_type_others
, 0);
2494 pdf_begin_obj
(pdf
, xref_stm
, OBJSTM_NEVER
); /* final object for pdf-
>os_enable
== true
*/
2495 if
((obj_offset
(pdf
, pdf-
>obj_ptr
) / 256) > 16777215)
2496 xref_offset_width
= 5;
2497 else if
(obj_offset
(pdf
, pdf-
>obj_ptr
) > 16777215)
2498 xref_offset_width
= 4;
2499 else if
(obj_offset
(pdf
, pdf-
>obj_ptr
) > 65535)
2500 xref_offset_width
= 3;
2502 xref_offset_width
= 2;
2503 /* Build a linked list of free objects
*/
2504 build_free_object_list
(pdf
);
2505 pdf_begin_dict
(pdf
);
2506 pdf_dict_add_name
(pdf
, "Type", "XRef");
2507 pdf_add_name
(pdf
, "Index");
2508 pdf_begin_array
(pdf
);
2509 pdf_add_int
(pdf
, 0);
2510 pdf_add_int
(pdf
, pdf-
>obj_ptr
+ 1);
2512 pdf_dict_add_int
(pdf
, "Size", pdf-
>obj_ptr
+ 1);
2513 pdf_add_name
(pdf
, "W");
2514 pdf_begin_array
(pdf
);
2515 pdf_add_int
(pdf
, 1);
2516 pdf_add_int
(pdf
, (int
) xref_offset_width
);
2517 pdf_add_int
(pdf
, 1);
2519 pdf_dict_add_ref
(pdf
, "Root", root
);
2520 pdf_dict_add_ref
(pdf
, "Info", info
);
2521 if
(pdf_trailer_toks
!= null
) {
2522 pdf_print_toks
(pdf
, pdf_trailer_toks
);
2523 delete_token_ref
(pdf_trailer_toks
);
2524 pdf_trailer_toks
= null
;
2526 print_pdf_table_string
(pdf
, "trailer");
2528 pdf_dict_add_streaminfo
(pdf
);
2530 pdf_begin_stream
(pdf
);
2531 for
(k
= 0; k
<= pdf-
>obj_ptr
; k
++) {
2532 if
(!is_obj_written
(pdf
, k
)) { /* a free object
*/
2534 pdf_out_bytes
(pdf
, obj_link
(pdf
, k
), xref_offset_width
);
2536 } else if
(obj_os_idx
(pdf
, k
) == PDF_OS_MAX_OBJS
) { /* object not in object stream
*/
2538 pdf_out_bytes
(pdf
, obj_offset
(pdf
, k
),
2541 } else
{ /* object in object stream
*/
2543 pdf_out_bytes
(pdf
, obj_offset
(pdf
, k
),
2545 pdf_out
(pdf
, obj_os_idx
(pdf
, k
));
2548 pdf_end_stream
(pdf
);
2550 /* TODO
: generate a debug version of the crossref
*/
2554 /* Output the |obj_tab|
*/
2555 /* Build a linked list of free objects
*/
2556 build_free_object_list
(pdf
);
2558 pdf_save_offset
(pdf
);
2559 pdf_puts
(pdf
, "xref\n");
2560 pdf_puts
(pdf
, "0 ");
2561 pdf_print_int_ln
(pdf
, pdf-
>obj_ptr
+ 1);
2562 pdf_print_fw_int
(pdf
, obj_link
(pdf
, 0), 10);
2563 pdf_puts
(pdf
, " 65535 f \n");
2564 for
(k
= 1; k
<= pdf-
>obj_ptr
; k
++) {
2565 if
(!is_obj_written
(pdf
, k
)) {
2566 pdf_print_fw_int
(pdf
, obj_link
(pdf
, k
), 10);
2567 pdf_puts
(pdf
, " 00000 f \n");
2569 pdf_print_fw_int
(pdf
, obj_offset
(pdf
, k
), 10);
2570 pdf_puts
(pdf
, " 00000 n \n");
2576 /* Output the trailer
*/
2577 if
(!pdf-
>os_enable
) {
2578 pdf_puts
(pdf
, "trailer\n");
2579 pdf_begin_dict
(pdf
);
2580 pdf_dict_add_int
(pdf
, "Size", pdf-
>obj_ptr
+ 1);
2581 pdf_dict_add_ref
(pdf
, "Root", root
);
2582 pdf_dict_add_ref
(pdf
, "Info", info
);
2583 if
(pdf_trailer_toks
!= null
) {
2584 pdf_print_toks
(pdf
, pdf_trailer_toks
);
2585 delete_token_ref
(pdf_trailer_toks
);
2586 pdf_trailer_toks
= null
;
2592 pdf_puts
(pdf
, "startxref\n");
2595 pdf_add_longint
(pdf
, (longinteger
) obj_offset
(pdf
, xref_stm
));
2597 pdf_add_longint
(pdf
, (longinteger
) pdf-
>save_offset
);
2598 pdf_puts
(pdf
, "\n%%EOF\n");
2602 if
(callback_id
== 0) {
2603 tprint_nl
("Output written on ");
2604 tprint
(pdf-
>file_name
);
2606 print_int
(total_pages
);
2608 if
(total_pages
!= 1)
2611 print_int
(pdf_offset
(pdf
));
2614 } else if
(callback_id
> 0) {
2615 run_callback
(callback_id
, "->");
2619 if
(pdf-
>draftmode
== 0)
2620 close_file
(pdf-
>file
);
2623 "\\pdfdraftmode enabled, not changing output pdf",
2627 if
(callback_id
== 0) {
2628 if
(log_opened_global
) {
2630 "\nPDF statistics: %d PDF objects out of %d (max. %d)\n",
2631 (int
) pdf-
>obj_ptr
, (int
) pdf-
>obj_tab_size
,
2632 (int
) sup_obj_tab_size
);
2633 if
(pdf-
>os-
>ostm_ctr
> 0) {
2635 " %d compressed objects within %d object stream%s\n",
2636 (int
) pdf-
>os-
>o_ctr
, (int
) pdf-
>os-
>ostm_ctr
,
2637 (pdf-
>os-
>ostm_ctr
> 1 ?
"s" : ""));
2639 fprintf
(log_file
, " %d named destinations out of %d (max. %d)\n",
2640 (int
) pdf-
>dest_names_ptr
, (int
) pdf-
>dest_names_size
,
2641 (int
) sup_dest_names_size
);
2643 " %d words of extra memory for PDF output out of %d (max. %d)\n",
2644 (int
) pdf-
>mem_ptr
, (int
) pdf-
>mem_size
,
2645 (int
) sup_pdf_mem_size
);
2651 void scan_pdfcatalog
(PDF pdf
)
2654 scan_pdf_ext_toks
();
2655 pdf_catalog_toks
= concat_tokens
(pdf_catalog_toks
, def_ref
);
2656 if
(scan_keyword
("openaction")) {
2657 if
(pdf_catalog_openaction
!= 0) {
2658 pdf_error
("ext1", "duplicate of openaction");
2660 check_o_mode
(pdf
, "\\pdfcatalog", 1 << OMODE_PDF
, true
);
2661 p
= scan_action
(pdf
);
2662 pdf_catalog_openaction
= pdf_create_obj
(pdf
, obj_type_others
, 0);
2663 pdf_begin_obj
(pdf
, pdf_catalog_openaction
, OBJSTM_ALWAYS
);
2664 write_action
(pdf
, p
);
2666 delete_action_ref
(p
);