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
/>.
24 #include
<kpathsea
/c-dir.h
>
25 #include
<kpathsea
/c-ctype.h
>
26 #include
"lua/luatex-api.h"
29 #define is_hex_char isxdigit
31 #define check_nprintf
(size_get
, size_want
) \
32 if
((unsigned
)(size_get
) >= (unsigned
)(size_want
)) \
33 formatted_error
("pdf backend","snprintf() failed in file %s at line %d", __FILE__
, __LINE__
);
35 PDF static_pdf
= NULL;
37 @ commandline interface
41 int output_mode_option
;
42 int output_mode_value
;
43 int draft_mode_option
;
46 halfword pdf_info_toks
; /* additional keys of Info dictionary
*/
47 halfword pdf_catalog_toks
; /* additional keys of Catalog dictionary
*/
48 halfword pdf_catalog_openaction
;
49 halfword pdf_names_toks
; /* additional keys of Names dictionary
*/
50 halfword pdf_trailer_toks
; /* additional keys of Trailer dictionary
*/
51 shipping_mode_e global_shipping_mode
= NOT_SHIPPING
; /* set to |shipping_mode| when |ship_out| starts
*/
53 @ Create a new buffer |strbuf_s| of size |size| and maximum allowed size |limit|.
54 Initialize it and set |p| to begin of data.
57 strbuf_s
*new_strbuf
(size_t size
, size_t limit
)
60 b
= xtalloc
(1, strbuf_s
);
64 b-
>p
= b-
>data
= xtalloc
(b-
>size
, unsigned char
);
66 b-
>p
= b-
>data
= NULL; /* for other alloc
*/
70 @ Check that |n| bytes more fit into buffer
; increase it if required.
73 static void strbuf_room
(strbuf_s
* b
, size_t n
)
76 size_t l
= (size_t
) (b-
>p
- b-
>data
);
78 overflow
("PDF buffer", (unsigned
) b-
>size
);
79 if
(n
+ l
> b-
>size
) {
80 a
= (unsigned int
) (b-
>size
>> 2);
81 if
(n
+ l
> b-
>size
+ a
)
83 else if
(b-
>size
< b-
>limit
- a
)
84 b-
>size
= b-
>size
+ a
;
87 b-
>data
= xreallocarray
(b-
>data
, unsigned char
, (unsigned
) b-
>size
);
92 @ Seek to position |offset| within buffer. Position must be valid.
95 void strbuf_seek
(strbuf_s
* b
, off_t offset
)
97 b-
>p
= b-
>data
+ offset
;
100 @ 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.
111 void strbuf_putchar
(strbuf_s
* b
, unsigned char c
)
113 if
((size_t
) (b-
>p
- b-
>data
+ 1) > b-
>size
)
118 @ Dump filled buffer part to PDF.
121 void strbuf_flush
(PDF pdf
, strbuf_s
* b
)
123 pdf_out_block
(pdf
, (const char
*) b-
>data
, strbuf_offset
(b
));
127 @ Free all dynamically allocated buffer structures.
130 void strbuf_free
(strbuf_s
* b
)
136 @ |init_pdf_struct
()| is called early
, only once
, from maincontrol.w
139 PDF init_pdf_struct
(PDF pdf
)
142 pdf
= xtalloc
(1, pdf_output_file
);
143 memset
(pdf
, 0, sizeof
(pdf_output_file
));
144 pdf-
>job_name
= makecstring
(job_name
);
146 output_mode_used
= OMODE_NONE
; /* will be set by |fix_o_mode
()|
*/
147 pdf-
>o_mode
= output_mode_used
; /* used by synctex
, we need to use output_mode_used there
*/
148 pdf-
>o_state
= ST_INITIAL
;
150 /* init PDF and object stream writing
*/
151 pdf-
>os
= os
= xtalloc
(1, os_struct
);
152 memset
(pdf-
>os
, 0, sizeof
(os_struct
));
153 os-
>buf
[PDFOUT_BUF
] = new_strbuf
(inf_pdfout_buf_size
, sup_pdfout_buf_size
);
154 os-
>buf
[OBJSTM_BUF
] = new_strbuf
(inf_objstm_buf_size
, sup_objstm_buf_size
);
155 os-
>obj
= xtalloc
(PDF_OS_MAX_OBJS
, os_obj_data
);
158 os-
>curbuf
= PDFOUT_BUF
;
159 pdf-
>buf
= os-
>buf
[os-
>curbuf
];
161 Later ttf_seek_outbuf
(TABDIR_OFF
+ n
* 4 * TTF_ULONG_SIZE
); in ttf_init_font
162 we need
236 bytes
, so we start with
256 bytes as in pdftex.
164 pdf-
>fb
= new_strbuf
(256, 100000000);
166 pdf-
>stream_deflate
= false
;
167 pdf-
>stream_writing
= false
;
170 Sometimes it is neccesary to allocate memory for PDF output that cannot be
171 deallocated then
, so we use |mem| for this purpose.
173 pdf-
>mem_size
= inf_pdf_mem_size
;
174 pdf-
>mem
= xtalloc
(pdf-
>mem_size
, int
);
176 The first word is not used so we can use zero as a value for testing
177 whether a pointer to |mem| is valid.
183 pdf-
>posstruct
= xtalloc
(1, posstructure
);
184 pdf-
>posstruct-
>pos.h
= 0;
185 pdf-
>posstruct-
>pos.v
= 0;
186 pdf-
>posstruct-
>dir
= dir_TLT
;
188 /* allocated size of |obj_tab| array
*/
189 pdf-
>obj_tab_size
= (unsigned
) inf_obj_tab_size
;
190 pdf-
>obj_tab
= xtalloc
(pdf-
>obj_tab_size
+ 1, obj_entry
);
191 memset
(pdf-
>obj_tab
, 0, sizeof
(obj_entry
));
193 pdf-
>minor_version
= -1;
194 pdf-
>decimal_digits
= 4;
196 pdf-
>image_gamma
= 65536;
197 pdf-
>image_hicolor
= 1;
198 pdf-
>image_apply_gamma
= 0;
199 pdf-
>objcompresslevel
= 0;
200 pdf-
>compress_level
= 0;
202 pdf-
>inclusion_copy_font
= 1;
203 pdf-
>pk_resolution
= 0;
204 pdf-
>pk_fixed_dpi
= 0;
205 pdf-
>pk_scale_factor
= 0;
207 init_dest_names
(pdf
);
208 pdf-
>page_resources
= NULL;
210 init_pdf_pagecalculations
(pdf
);
212 pdf-
>vfstruct
= new_vfstruct
();
217 @ We use |pdf_get_mem| to allocate memory in |mem|.
220 int pdf_get_mem
(PDF pdf
, int s
)
224 if
(s
> sup_pdf_mem_size
- pdf-
>mem_ptr
)
225 overflow
("pdf memory size (pdf_mem_size)", (unsigned
) pdf-
>mem_size
);
226 if
(pdf-
>mem_ptr
+ s
> pdf-
>mem_size
) {
227 a
= pdf-
>mem_size
>> 2;
228 if
(pdf-
>mem_ptr
+ s
> pdf-
>mem_size
+ a
) {
229 pdf-
>mem_size
= pdf-
>mem_ptr
+ s
;
230 } else if
(pdf-
>mem_size
< sup_pdf_mem_size
- a
) {
231 pdf-
>mem_size
= pdf-
>mem_size
+ a
;
233 pdf-
>mem_size
= sup_pdf_mem_size
;
235 pdf-
>mem
= xreallocarray
(pdf-
>mem
, int
, (unsigned
) pdf-
>mem_size
);
238 pdf-
>mem_ptr
= pdf-
>mem_ptr
+ s
;
242 @ there are defined in |luatex-api.h|
, so we need |luatex-api.c|
:
245 output_mode get_o_mode
(void
)
248 if
(int_par
(output_mode_code
) > 0) {
255 void fix_o_mode
(void
)
257 output_mode o_mode
= get_o_mode
();
258 if
(output_mode_used
== OMODE_NONE
) {
259 output_mode_used
= o_mode
;
260 static_pdf-
>o_mode
= output_mode_used
; /* used by synctex
, we need to use output_mode_used there
*/
261 } else if
(output_mode_used
!= o_mode
) {
262 normal_error
("pdf backend", "\\outputmode can only be changed before anything is written to the output");
266 @ This ensures that |pdfminorversion| is set only before any bytes have been
267 written to the generated \.
{PDF
} file. Here also all variables for \.
{PDF
} output
268 are initialized
, the \.
{PDF
} file is opened by |ensure_pdf_open|
, and the \.
{PDF
}
272 void fix_pdf_minorversion
(PDF pdf
)
274 if
(pdf-
>minor_version
< 0) { /* unset
*/
275 if
((pdf_minor_version
< 0) ||
(pdf_minor_version
> 9)) {
276 const char
*hlp
[] = { "The pdfminorversion must be between 0 and 9.", "I changed this to 4.", NULL };
278 (void
) snprintf
(msg
, 255, "LuaTeX error (illegal pdfminorversion %d)", (int
) pdf_minor_version
);
280 pdf-
>minor_version
= 4;
282 pdf-
>minor_version
= pdf_minor_version
;
285 /* Check that variables for \.
{PDF
} output are unchanged
*/
286 if
(pdf-
>minor_version
!= pdf_minor_version
)
287 normal_error
("pdf backend", "minorversion cannot be changed after data is written to the PDF file");
288 if
(pdf-
>draftmode
!= int_par
(draft_mode_code
))
289 normal_error
("pdf backend", "draftmode cannot be changed after data is written to the PDF file");
291 if
(pdf-
>draftmode
!= 0) {
292 pdf-
>compress_level
= 0; /* re-fix it
, might have been changed inbetween
*/
293 pdf-
>objcompresslevel
= 0;
298 #define ZIP_BUF_SIZE
32768
300 #define check_err
(f
, fn
) \
302 formatted_error
("pdf backend","zlib %s() failed (error code %d)", fn
, f
)
305 static void write_zip
(PDF pdf
)
307 int flush
, err
= Z_OK
;
309 strbuf_s
*buf
= pdf-
>buf
;
310 z_stream
*s
= pdf-
>c_stream
;
311 boolean finish
= pdf-
>zip_write_state
== ZIP_FINISH
;
312 if
(pdf-
>stream_length
== 0) {
314 s
= pdf-
>c_stream
= xtalloc
(1, z_stream
);
315 s-
>zalloc
= (alloc_func
) 0;
316 s-
>zfree
= (free_func
) 0;
317 s-
>opaque
= (voidpf
) 0;
318 check_err
(deflateInit
(s
, pdf-
>compress_level
), "deflateInit");
319 pdf-
>zipbuf
= xtalloc
(ZIP_BUF_SIZE
, char
);
321 check_err
(deflateReset
(s
), "deflateReset");
322 s-
>next_out
= (Bytef
*) pdf-
>zipbuf
;
323 s-
>avail_out
= ZIP_BUF_SIZE
;
325 s-
>next_in
= buf-
>data
;
326 s-
>avail_in
= (uInt
) (buf-
>p
- buf-
>data
);
328 if
(s-
>avail_out
== 0 ||
(finish
&& s->avail_out < ZIP_BUF_SIZE)) {
329 zip_len
= ZIP_BUF_SIZE
- s-
>avail_out
;
330 pdf-
>gone
+= (off_t
) xfwrite
(pdf-
>zipbuf
, 1, zip_len
, pdf-
>file
);
331 pdf-
>last_byte
= pdf-
>zipbuf
[zip_len
- 1];
332 s-
>next_out
= (Bytef
*) pdf-
>zipbuf
;
333 s-
>avail_out
= ZIP_BUF_SIZE
;
336 if
(err
== Z_STREAM_END
) {
338 pdf-
>zip_write_state
= NO_ZIP
;
343 if
(s-
>avail_in
== 0)
347 err
= deflate
(s
, flush
);
348 if
(err
!= Z_OK
&& err != Z_STREAM_END)
349 formatted_error
("pdf backend","zlib deflate() failed (error code %d)", err
);
351 pdf-
>stream_length
= (off_t
) s-
>total_out
;
355 void zip_free
(PDF pdf
)
357 if
(pdf-
>zipbuf
!= NULL) {
358 check_err
(deflateEnd
(pdf-
>c_stream
), "deflateEnd");
361 xfree
(pdf-
>c_stream
);
365 static void write_nozip
(PDF pdf
)
367 strbuf_s
*buf
= pdf-
>buf
;
368 size_t l
= strbuf_offset
(buf
);
371 pdf-
>stream_length
= pdf_offset
(pdf
) - pdf-
>save_offset
;
372 pdf-
>gone
+= (off_t
) xfwrite
((char
*) buf-
>data
, sizeof
(char
), l
, pdf-
>file
);
373 pdf-
>last_byte
= *(buf-
>p
- 1);
376 @ The PDF buffer is flushed by calling |pdf_flush|
, which checks the
377 variable |zip_write_state| and will compress the buffer before flushing if
378 neccesary. We call |pdf_begin_stream| to begin a stream and |pdf_end_stream|
379 to finish it. The stream contents will be compressed if compression is turn on.
382 void pdf_flush
(PDF pdf
)
384 os_struct
*os
= pdf-
>os
;
385 off_t saved_pdf_gone
= pdf-
>gone
;
386 switch
(os-
>curbuf
) {
388 if
(pdf-
>draftmode
== 0) {
389 switch
(pdf-
>zip_write_state
) {
398 normal_error
("pdf backend", "bad zip state");
401 pdf-
>zip_write_state
= NO_ZIP
;
402 strbuf_seek
(pdf-
>buf
, 0);
403 if
(saved_pdf_gone
> pdf-
>gone
)
404 normal_error
("pdf backend", "file size exceeds architectural limits (pdf_gone wraps around)");
409 normal_error
("pdf backend", "bad buffer state");
414 static void pdf_buffer_select
(PDF pdf
, buffer_e buf
)
416 os_struct
*os
= pdf-
>os
;
417 if
(pdf-
>os_enable
&& buf == OBJSTM_BUF)
418 os-
>curbuf
= OBJSTM_BUF
; /* switch to object stream
*/
420 os-
>curbuf
= PDFOUT_BUF
; /* switch to PDF stream
*/
421 pdf-
>buf
= os-
>buf
[pdf-
>os-
>curbuf
];
424 @ create new \.
{/ObjStm
} object if required
, and set up cross reference info
427 static void pdf_prepare_obj
(PDF pdf
, int k
, int pdf_os_threshold
)
429 os_struct
*os
= pdf-
>os
;
430 strbuf_s
*obuf
= os-
>buf
[OBJSTM_BUF
];
431 if
(pdf-
>objcompresslevel
>= pdf_os_threshold
)
432 pdf_buffer_select
(pdf
, OBJSTM_BUF
);
434 pdf_buffer_select
(pdf
, PDFOUT_BUF
);
435 switch
(os-
>curbuf
) {
437 obj_offset
(pdf
, k
) = pdf_offset
(pdf
);
438 obj_os_idx
(pdf
, k
) = PDF_OS_MAX_OBJS
; /* mark it as not included in any ObjStm
*/
441 if
(os-
>cur_objstm
== 0) {
443 (unsigned int
) pdf_create_obj
(pdf
, obj_type_objstm
, 0);
445 obuf-
>p
= obuf-
>data
; /* start fresh object stream
*/
446 os-
>ostm_ctr
++; /* only for statistics
*/
448 obj_os_idx
(pdf
, k
) = (int
) os-
>idx
;
449 obj_os_objnum
(pdf
, k
) = (int
) os-
>cur_objstm
;
450 os-
>obj
[os-
>idx
].num
= k
;
451 os-
>obj
[os-
>idx
].off
= obuf-
>p
- obuf-
>data
;
454 normal_error
("pdf backend", "bad object state");
458 @
* Low-level buffer checkers.
460 @ Set the active buffer pointer. Make sure that there are at least |n| bytes free
461 in that buffer
, flush if needed.
464 inline void pdf_room
(PDF pdf
, int n
)
466 strbuf_s
*buf
= pdf-
>buf
;
467 if
((size_t
) (n
+ buf-
>p
- buf-
>data
) <= buf-
>size
)
469 if
(pdf-
>os-
>curbuf
== PDFOUT_BUF
) {
470 if
((size_t
) n
> buf-
>size
)
471 overflow
("PDF output buffer", (unsigned
) buf-
>size
);
472 if
((size_t
) (n
+ buf-
>p
- buf-
>data
) < buf-
>limit
)
473 strbuf_room
(buf
, (size_t
) n
);
477 strbuf_room
(buf
, (size_t
) n
);
482 void pdf_out_block
(PDF pdf
, const char
*s
, size_t n
)
485 strbuf_s
*buf
= pdf-
>buf
;
490 pdf_room
(pdf
, (int
) l
);
491 (void
) memcpy
(buf-
>p
, s
, l
);
499 __attribute__
((format
(printf
, 2, 3)))
500 void pdf_printf
(PDF pdf
, const char
*fmt
, ...
)
504 if
(pdf-
>printf_buf
== NULL) {
505 pdf-
>printf_buf
= xtalloc
(PRINTF_BUF_SIZE
, char
);
507 (void
) vsnprintf
(pdf-
>printf_buf
, PRINTF_BUF_SIZE
, fmt
, args
);
508 pdf_puts
(pdf
, pdf-
>printf_buf
);
512 @ print out a string to PDF buffer
515 void pdf_print
(PDF pdf
, str_number s
)
519 if
(s
>= STRING_OFFSET
) {
520 ss
= (const char
*) str_string
(s
);
522 pdf_out_block
(pdf
, ss
, l
);
528 @ print out a integer to PDF buffer
531 void pdf_print_int
(PDF pdf
, longinteger n
)
535 w
= snprintf
(s
, 23, "%" LONGINTEGER_PRI
"d", (LONGINTEGER_TYPE
) n
);
536 check_nprintf
(w
, 23);
537 pdf_out_block
(pdf
, (const char
*) s
, (size_t
) w
);
542 void print_pdffloat
(PDF pdf
, pdffloat f
)
552 pdf_print_int
(pdf
, l
);
556 snprintf
(a
, 23, "%d", l
+ ten_pow
[e
]);
557 for
(i
= e
; i
> 0; i--
) {
562 pdf_puts
(pdf
, (a
+ 1));
567 void print_pdffloat
(PDF pdf
, pdffloat f
)
575 /* division by ten_pow
[0] == 1 */
580 snprintf
(a
, 23, "%" LONGINTEGER_PRI
"i", m
);
595 w
= snprintf
(a
, 23, "%i", l
);
596 pdf_out_block
(pdf
, (const char
*) a
, (size_t
) w
);
600 snprintf
(a
, 23, "%d", l
+ t
);
601 for
(i
= e
; i
> 0; i--
) {
606 pdf_puts
(pdf
, (a
+ 1));
613 @ print out |s| as string in PDF output
616 void pdf_print_str
(PDF pdf
, const char
*s
)
618 const char
*orig
= s
;
619 int l
= (int
) strlen
(s
) - 1; /* last string index
*/
624 /* the next is not really safe
, the string could be
"(a)xx(b)" */
625 if
((s
[0] == '
('
) && (s[l] == ')')) {
629 if
((s
[0] != '
<'
) ||
(s
[l
] != '
>'
) || odd
((l
+ 1))) {
636 while
(is_hex_char
((unsigned char
)*s
))
644 pdf_puts
(pdf
, orig
); /* it was a hex string after all
*/
647 @ begin a stream
(needs to have a stream dictionary also
)
650 void pdf_begin_stream
(PDF pdf
)
652 pdf_puts
(pdf
, "\nstream\n");
653 pdf_save_offset
(pdf
);
655 if
(pdf-
>stream_deflate
) {
656 pdf-
>zip_write_state
= ZIP_WRITING
;
658 pdf-
>stream_writing
= true
;
659 pdf-
>stream_length
= 0;
666 void pdf_end_stream
(PDF pdf
)
668 os_struct
*os
= pdf-
>os
;
669 switch
(os-
>curbuf
) {
671 if
(pdf-
>zip_write_state
== ZIP_WRITING
)
672 pdf-
>zip_write_state
= ZIP_FINISH
;
673 pdf_flush
(pdf
); /* sets pdf-
>last_byte
*/
676 normal_error
("pdf backend", "bad buffer in end stream, case 1");
679 normal_error
("pdf backend", "bad buffer in end stream, case 2");
681 pdf-
>stream_deflate
= false
;
682 pdf-
>stream_writing
= false
;
683 pdf_out
(pdf
, '\n'
); /* doesn't really belong to the stream
*/
684 pdf_puts
(pdf
, "endstream");
685 /* write stream
/Length
*/
686 if
(pdf-
>seek_write_length
&& pdf->draftmode == 0) {
687 xfseeko
(pdf-
>file
, (off_t
)pdf-
>stream_length_offset
, SEEK_SET
, pdf-
>job_name
);
688 fprintf
(pdf-
>file
, "%" LONGINTEGER_PRI
"i", (LONGINTEGER_TYPE
) pdf-
>stream_length
);
689 xfseeko
(pdf-
>file
, 0, SEEK_END
, pdf-
>job_name
);
691 pdf-
>seek_write_length
= false
;
694 @ To print |scaled| value to PDF output we need some subroutines to ensure
698 #define max_integer
0x7FFFFFFF /* $
2^
{31}-1$
*/
700 scaled one_hundred_inch
= 7227 * 65536; /* scaled value corresponds to
100in
, exact
, 473628672 */
701 scaled one_inch
= (7227 * 65536 + 50) / 100; /* scaled value corresponds to
1in
(rounded to
4736287) */
702 scaled one_true_inch
= (7227 * 65536 + 50) / 100; /* scaled value corresponds to
1truein
(rounded
!) */
703 scaled one_hundred_bp
= (7227 * 65536) / 72; /* scaled value corresponds to
100bp
*/
704 scaled one_bp
= 65781; /* scaled value corresponds to
1bp
(rounded to
65782) */
707 one_bp is changed on
20110411 to be exactly
65781, as in tex itself
, because this value
708 is also used for \pdfpxdimen
712 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 /* $
10^
0.
.10^
9$
*/
715 @ The function |divide_scaled| divides |s| by |m| using |dd| decimal
716 digits of precision. It is defined in C because it is a good candidate
717 for optimizations that are not possible in pascal.
720 scaled round_xn_over_d
(scaled x
, int n
, unsigned int d
)
722 boolean positive
= true
;
725 positive
= !positive
;
729 positive
= !positive
;
732 t
= (unsigned
) ((x
% 0100000) * n
);
733 u
= (unsigned
) (((unsigned
) (x
) / 0100000) * (unsigned
) n
+ (t
/ 0100000));
734 v
= (u
% d
) * 0100000 + (t
% 0100000);
735 if
(u
/ d
>= 0100000)
738 u
= 0100000 * (u
/ d
) + (v
/ d
);
745 return
(-(scaled
) u
);
749 void pdf_add_bp
(PDF pdf
, scaled s
)
752 pdfstructure
*p
= pdf-
>pstruct
;
753 a.m
= i64round
(s
* p-
>k1
);
754 a.e
= pdf-
>decimal_digits
;
757 print_pdffloat
(pdf
, a
);
761 @
* handling page resources.
766 pdf_object_list
*list
;
770 static int comp_page_resources
(const void
*pa
, const void
*pb
, void
*p
)
772 int a
= ((const pr_entry
*) pa
)->obj_type
;
773 int b
= ((const pr_entry
*) pb
)->obj_type
;
783 void addto_page_resources
(PDF pdf
, pdf_obj_type t
, int k
)
785 pdf_resource_struct
*re
;
788 pdf_object_list
*p
, *item
= NULL;
789 re
= pdf-
>page_resources
;
790 if
(re-
>resources_tree
== NULL) {
791 re-
>resources_tree
= avl_create
(comp_page_resources
, NULL, &avl_xallocator);
792 if
(re-
>resources_tree
== NULL)
793 formatted_error
("pdf backend","addto_page_resources(): avl_create() page_resource_tree failed");
796 pr
= (pr_entry
*) avl_find
(re-
>resources_tree
, &tmp);
798 pr
= xtalloc
(1, pr_entry
);
801 pp
= avl_probe
(re-
>resources_tree
, pr
);
803 formatted_error
("pdf backend","addto_page_resources(): avl_probe() out of memory in insertion");
805 if
(pr-
>list
== NULL) {
806 item
= xtalloc
(1, pdf_object_list
);
810 if
(obj_type
(pdf
, k
) == (int
)t
)
811 set_obj_scheduled
(pdf
, k
); /* k is an object number
*/
813 for
(p
= pr-
>list
; p-
>info
!= k
&& p->link != NULL; p = p->link);
815 item
= xtalloc
(1, pdf_object_list
);
819 if
(obj_type
(pdf
, k
) == (int
)t
)
820 set_obj_scheduled
(pdf
, k
);
826 pdf_object_list
*get_page_resources_list
(PDF pdf
, pdf_obj_type t
)
828 pdf_resource_struct
*re
= pdf-
>page_resources
;
830 if
(re
== NULL || re-
>resources_tree
== NULL)
833 pr
= (pr_entry
*) avl_find
(re-
>resources_tree
, &tmp);
840 static void reset_page_resources
(PDF pdf
)
842 pdf_resource_struct
*re
= pdf-
>page_resources
;
844 struct avl_traverser t
;
845 pdf_object_list
*l1
, *l2
;
846 if
(re
== NULL || re-
>resources_tree
== NULL)
848 avl_t_init
(&t, re->resources_tree);
849 for
(p
= avl_t_first
(&t, re->resources_tree); p != NULL; p = avl_t_next(&t)) {
850 if
(p-
>list
!= NULL) {
851 for
(l1
= p-
>list
; l1
!= NULL; l1
= l2
) {
855 p-
>list
= NULL; /* but the AVL tree remains
*/
861 static void destroy_pg_res_tree
(void
*pa
, void
*param
)
868 static void destroy_page_resources_tree
(PDF pdf
)
870 pdf_resource_struct
*re
= pdf-
>page_resources
;
871 reset_page_resources
(pdf
);
872 if
(re-
>resources_tree
!= NULL)
873 avl_destroy
(re-
>resources_tree
, destroy_pg_res_tree
);
874 re-
>resources_tree
= NULL;
877 @
* Subroutines to print out various PDF objects.
879 @ print out an integer |n| with fixed width |w|
; used for outputting cross-reference table. The
880 specification says that an offset must take
10 bytes.
882 static void pdf_print_fw_int
(PDF pdf
, longinteger n
)
884 unsigned char digits
[11];
889 digits
[k
] = (unsigned char
) ('
0'
+ (n
% 10));
893 /* the absolute value of $n$ is greater than
9999999999 */
894 normal_error
("pdf backend", "offset exceeds 10 bytes, try enabling object compression.");
896 pdf_puts
(pdf
, (const char
*) digits
);
899 @ print out an integer |n| as a fixed number |w| of bytes
; used for outputting \.
{/XRef
} cross-reference stream
901 static void pdf_out_bytes
(PDF pdf
, longinteger n
, size_t w
)
904 unsigned char bytes
[8]; /* digits in a number being output
*/
908 bytes
[k
] = (unsigned char
) (n
% 256);
911 pdf_out_block
(pdf
, (const char
*) bytes
, w
);
914 @ print out |s| as string in PDF output
917 void pdf_print_str_ln
(PDF pdf
, const char
*s
)
919 pdf_print_str
(pdf
, s
);
924 void pdf_print_toks
(PDF pdf
, halfword p
)
927 char
*s
= tokenlist_to_cstring
(p
, true
, &len);
940 void pdf_add_rect_spec
(PDF pdf
, halfword r
)
942 pdf_add_bp
(pdf
, pdf_ann_left
(r
));
943 pdf_add_bp
(pdf
, pdf_ann_bottom
(r
));
944 pdf_add_bp
(pdf
, pdf_ann_right
(r
));
945 pdf_add_bp
(pdf
, pdf_ann_top
(r
));
948 @ output a rectangle specification to PDF file
951 void pdf_rectangle
(PDF pdf
, halfword r
)
953 pdf_add_name
(pdf
, "Rect");
954 pdf_begin_array
(pdf
);
955 pdf_add_rect_spec
(pdf
, r
);
960 static void init_pdf_outputparameters
(PDF pdf
)
963 pdf-
>draftmode
= fix_int
(int_par
(draft_mode_code
), 0, 1);
964 pdf-
>compress_level
= fix_int
(pdf_compress_level
, 0, 9);
965 pdf-
>decimal_digits
= fix_int
(pdf_decimal_digits
, 3, 5);
966 /* pdf-
>decimal_digits
= fix_int
(pdf_decimal_digits
, 3, 6);*//* later
, maybe
(LS
)*/
967 pdf-
>gamma
= fix_int
(pdf_gamma
, 0, 1000000);
968 pdf-
>image_gamma
= fix_int
(pdf_image_gamma
, 0, 1000000);
969 pdf-
>image_hicolor
= fix_int
(pdf_image_hicolor
, 0, 1);
970 pdf-
>image_apply_gamma
= fix_int
(pdf_image_apply_gamma
, 0, 1);
971 pdf-
>objcompresslevel
= fix_int
(pdf_objcompresslevel
, 0, MAX_OBJ_COMPRESS_LEVEL
);
972 pdf-
>inclusion_copy_font
= fix_int
(pdf_inclusion_copy_font
, 0, 1);
973 pdf-
>pk_resolution
= fix_int
(pdf_pk_resolution
, 72, 8000);
974 pdf-
>pk_fixed_dpi
= fix_int
(pdf_pk_fixed_dpi
, 0, 1);
975 if
((pdf-
>minor_version
>= 5) && (pdf->objcompresslevel > 0)) {
976 pdf-
>os_enable
= true
;
978 if
(pdf-
>objcompresslevel
> 0) {
979 normal_warning
("pdf backend","objcompresslevel > 0 requires minorversion > 4");
980 pdf-
>objcompresslevel
= 0;
982 pdf-
>os_enable
= false
;
984 if
(pdf-
>pk_resolution
== 0) /* if not set from format file or by user
*/
985 pdf-
>pk_resolution
= pk_dpi
; /* take it from \.
{texmf.cnf
} */
986 pdf-
>pk_scale_factor
= divide_scaled
(72, pdf-
>pk_resolution
, pk_decimal_digits
(pdf
,5));
987 if
(!callback_defined
(read_pk_file_callback
)) {
988 pk_mode
= pdf_pk_mode
; /* lookup once
*/
989 if
(pk_mode
!= null
) {
990 char
*s
= tokenlist_to_cstring
(pk_mode
, true
, NULL);
991 kpse_init_prog
("PDFTEX", (unsigned
) pdf-
>pk_resolution
, s
, nil
);
994 kpse_init_prog
("PDFTEX", (unsigned
) pdf-
>pk_resolution
, nil
, nil
);
996 if
(!kpse_var_value
("MKTEXPK"))
997 kpse_set_program_enabled
(kpse_pk_format
, 1, kpse_src_cmdline
);
999 set_job_id
(pdf
, int_par
(year_code
), int_par
(month_code
), int_par
(day_code
), int_par
(time_code
));
1000 if
((pdf_unique_resname
> 0) && (pdf->resname_prefix == NULL))
1001 pdf-
>resname_prefix
= get_resname_prefix
(pdf
);
1004 @ Checks that we have a name for the generated PDF file and that it's open.
1007 static void ensure_output_file_open
(PDF pdf
, const char
*ext
)
1010 if
(pdf-
>file_name
!= NULL)
1014 fn
= pack_job_name
(ext
);
1015 if
(pdf-
>draftmode
== 0 || output_mode_used
== OMODE_DVI
) {
1016 while
(!lua_b_open_out
(&pdf->file, fn))
1017 fn
= prompt_file_name
("file name for output", ext
);
1019 pdf-
>file_name
= fn
;
1023 static void ensure_pdf_header_written
(PDF pdf
)
1025 /* Initialize variables for \.
{PDF
} output
*/
1026 fix_pdf_minorversion
(pdf
);
1027 init_pdf_outputparameters
(pdf
);
1028 /* Write \.
{PDF
} header
*/
1029 pdf_printf
(pdf
, "%%PDF-1.%d\n", pdf-
>minor_version
);
1031 pdf_out
(pdf
, 'P'
+ 128);
1032 pdf_out
(pdf
, 'T'
+ 128);
1033 pdf_out
(pdf
, 'E'
+ 128);
1034 pdf_out
(pdf
, '
X'
+ 128);
1039 void ensure_output_state
(PDF pdf
, output_state s
)
1041 if
(pdf-
>o_state
< s
) {
1043 ensure_output_state
(pdf
, s
- 1);
1049 switch
(output_mode_used
) {
1051 ensure_output_file_open
(pdf
, ".dvi");
1054 ensure_output_file_open
(pdf
, ".pdf");
1057 normal_error
("pdf backend","weird output state");
1061 switch
(output_mode_used
) {
1063 ensure_dvi_header_written
(pdf
);
1066 ensure_pdf_header_written
(pdf
);
1069 normal_error
("pdf backend","weird output state");
1072 case ST_HEADER_WRITTEN
:
1074 case ST_FILE_CLOSED
:
1077 normal_error
("pdf backend","weird output state");
1083 @ Write out an accumulated object stream.
1085 First the object number and byte offset pairs are generated and appended to the
1086 ready buffered object stream. By this the value of \.
{/First
} can be calculated.
1087 Then a new \.
{/ObjStm
} object is generated
, and everything is copied to the PDF
1088 output buffer
, where also compression is done. When calling this procedure
,
1089 |pdf_os_mode| must be |true|.
1092 static void pdf_os_write_objstream
(PDF pdf
)
1094 os_struct
*os
= pdf-
>os
;
1095 unsigned int i
, j
, n1
, n2
; /* n1
, n2
: ObjStm buffer may be reallocated
! */
1096 strbuf_s
*obuf
= os-
>buf
[OBJSTM_BUF
];
1097 if
(os-
>cur_objstm
== 0) /* no object stream started
*/
1099 n1
= (unsigned int
) strbuf_offset
(obuf
); /* remember end of collected object stream contents
*/
1100 /* this is needed here to calculate
/First for the ObjStm dict
*/
1101 for
(i
= 0, j
= 0; i
< os-
>idx
; i
++) { /* add object-number
/byte-offset list to buffer
*/
1102 pdf_print_int
(pdf
, (int
) os-
>obj
[i
].num
);
1104 pdf_print_int
(pdf
, (int
) os-
>obj
[i
].off
);
1105 if
(j
== 9 || i
== os-
>idx
- 1) { /* print out in groups of ten for better readability
*/
1113 n2
= (unsigned int
) strbuf_offset
(obuf
); /* remember current buffer end
*/
1114 pdf_begin_obj
(pdf
, (int
) os-
>cur_objstm
, OBJSTM_NEVER
); /* switch to PDF stream writing
*/
1115 pdf_begin_dict
(pdf
);
1116 pdf_dict_add_name
(pdf
, "Type", "ObjStm");
1117 pdf_dict_add_int
(pdf
, "N", (int
) os-
>idx
); /* number of objects in ObjStm
*/
1118 pdf_dict_add_int
(pdf
, "First", (int
) (n2
- n1
));
1119 pdf_dict_add_streaminfo
(pdf
);
1121 pdf_begin_stream
(pdf
);
1122 /* write object-number
/byte-offset list
*/
1123 pdf_out_block
(pdf
, (const char
*) (obuf-
>data
+ n1
), (size_t
) (n2
- n1
));
1124 /* write collected object stream contents
*/
1125 pdf_out_block
(pdf
, (const char
*) obuf-
>data
, (size_t
) n1
);
1126 pdf_end_stream
(pdf
);
1128 os-
>cur_objstm
= 0; /* to force object stream generation next time
*/
1131 @ begin a PDF dictionary
1134 void pdf_begin_dict
(PDF pdf
)
1136 pdf_puts
(pdf
, "<<");
1140 @ end a PDF dictionary
1143 void pdf_end_dict
(PDF pdf
)
1145 pdf_puts
(pdf
, ">>");
1149 @ add integer object to dict
1152 void pdf_dict_add_bool
(PDF pdf
, const char
*key
, int i
)
1154 pdf_add_name
(pdf
, key
);
1155 pdf_add_bool
(pdf
, i
);
1158 @ add integer object to dict
1161 void pdf_dict_add_int
(PDF pdf
, const char
*key
, int i
)
1163 pdf_add_name
(pdf
, key
);
1164 pdf_add_int
(pdf
, i
);
1167 @ add name object to dict
1170 void pdf_dict_add_name
(PDF pdf
, const char
*key
, const char
*val
)
1172 pdf_add_name
(pdf
, key
);
1173 pdf_add_name
(pdf
, val
);
1176 @ add string object to dict
1179 void pdf_dict_add_string
(PDF pdf
, const char
*key
, const char
*val
)
1183 pdf_add_name
(pdf
, key
);
1187 pdf_print_str
(pdf
, val
);
1190 @ add name reference to dict
1193 void pdf_dict_add_ref
(PDF pdf
, const char
*key
, int num
)
1195 pdf_add_name
(pdf
, key
);
1196 pdf_add_ref
(pdf
, num
);
1199 @ add objects of different types
1202 void pdf_add_null
(PDF pdf
)
1206 pdf_puts
(pdf
, "null");
1210 void pdf_add_bool
(PDF pdf
, int i
)
1215 pdf_puts
(pdf
, "false");
1217 pdf_puts
(pdf
, "true");
1221 void pdf_add_int
(PDF pdf
, int i
)
1225 pdf_print_int
(pdf
, i
);
1229 void pdf_add_longint
(PDF pdf
, longinteger n
)
1233 pdf_print_int
(pdf
, n
);
1237 void pdf_add_string
(PDF pdf
, const char
*s
)
1241 pdf_print_str
(pdf
, s
);
1245 void pdf_add_name
(PDF pdf
, const char
*name
)
1248 pdf_puts
(pdf
, name
);
1252 void pdf_add_ref
(PDF pdf
, int num
)
1256 pdf_print_int
(pdf
, num
);
1257 pdf_puts
(pdf
, " 0 R");
1261 @ add stream length and filter entries to a stream dictionary
,
1262 remember file position for seek
1265 void pdf_dict_add_streaminfo
(PDF pdf
)
1267 pdf_add_name
(pdf
, "Length");
1268 pdf-
>stream_length_offset
= pdf_offset
(pdf
) + 1;
1269 pdf-
>seek_write_length
= true
; /* fill in length at |pdf_end_stream| call
*/
1270 pdf_puts
(pdf
, " x "); /* space for
10 decimal digits
*/
1272 if
(pdf-
>compress_level
> 0) {
1273 pdf_dict_add_name
(pdf
, "Filter", "FlateDecode");
1274 pdf-
>stream_deflate
= true
;
1281 void pdf_begin_array
(PDF pdf
)
1290 void pdf_end_array
(PDF pdf
)
1296 @ begin a PDF object
1299 void pdf_begin_obj
(PDF pdf
, int i
, int pdf_os_threshold
)
1301 os_struct
*os
= pdf-
>os
;
1302 ensure_output_state
(pdf
, ST_HEADER_WRITTEN
);
1303 pdf_prepare_obj
(pdf
, i
, pdf_os_threshold
);
1304 switch
(os-
>curbuf
) {
1306 pdf_printf
(pdf
, "%d 0 obj\n", (int
) i
);
1309 if
(pdf-
>compress_level
== 0)
1310 pdf_printf
(pdf
, "%% %d 0 obj\n", (int
) i
); /* debugging help
*/
1313 normal_error
("pdf backend","weird begin object");
1321 void pdf_end_obj
(PDF pdf
)
1323 os_struct
*os
= pdf-
>os
;
1324 switch
(os-
>curbuf
) {
1326 pdf_puts
(pdf
, "\nendobj\n"); /* end a PDF object
*/
1329 os-
>idx
++; /* = number of objects collected so far in ObjStm
*/
1330 os-
>o_ctr
++; /* only for statistics
*/
1331 if
(os-
>idx
== PDF_OS_MAX_OBJS
)
1332 pdf_os_write_objstream
(pdf
);
1334 pdf_out
(pdf
, '\n'
); /* Adobe Reader seems to need this
*/
1337 normal_error
("pdf backend","weird end object");
1341 @ Converts any string given in in in an allowed PDF string which can be
1342 handled by printf et.al.
: \.
{\\
} is escaped to \.
{\\\\
}, parenthesis are escaped and
1343 control characters are octal encoded.
1344 This assumes that the string does not contain any already escaped
1348 char
*convertStringToPDFString
(const char
*in
, int len
)
1350 static char pstrbuf
[MAX_PSTRING_LEN
];
1351 char
*out
= pstrbuf
;
1355 for
(i
= 0; i
< len
; i
++) {
1356 check_buf
((unsigned
) j
+ sizeof
(buf
), MAX_PSTRING_LEN
);
1357 if
(((unsigned char
) in
[i
] < '
!'
) ||
((unsigned char
) in
[i
] > '~'
)) {
1358 /* convert control characters into oct
*/
1359 k
= snprintf
(buf
, sizeof
(buf
), "\\%03o", (unsigned int
) (unsigned char
) in
[i
]);
1360 check_nprintf
(k
, sizeof
(buf
));
1365 } else if
((in
[i
] == '
('
) ||
(in
[i
] == '
)'
)) {
1366 /* escape paranthesis
*/
1369 } else if
(in
[i
] == '\\'
) {
1370 /* escape backslash
*/
1382 @ Converts any string given in in in an allowed PDF string which is hexadecimal
1383 encoded
; |sizeof
(out
)| should be at least $|lin|
*2+1$.
1386 static void convertStringToHexString
(const char
*in
, char
*out
, int lin
)
1391 for
(i
= 0; i
< lin
; i
++) {
1392 k
= snprintf
(buf
, sizeof
(buf
), "%02X", (unsigned int
) (unsigned char
) in
[i
]);
1393 check_nprintf
(k
, sizeof
(buf
));
1400 @ Compute the ID string as per PDF1.4
9.3:
1402 File identifers are defined by the optional ID entry in a PDF file's trailer
1403 dictionary
(see Section
3.4.4, "File Trailer"; see also implementation note
105
1404 in Appendix H
). The value of this entry is an array of two strings. The first
1405 string is a permanent identifier based on the contents of the file at the time it
1406 was originally created
, and does not change when the file is incrementally
1407 updated. The second string is a changing identifier based on the file's contents
1408 at the time it was last updated. When a file is first written
, both identifiers
1409 are set to the same value. If both identifiers match when a file reference is
1410 resolved
, it is very likely that the correct file has been found
; if only the
1411 first identifier matches
, then a different version of the correct file has been
1412 found. To help ensure the uniqueness of file identifiers
, it is recommend that
1413 they be computed using a message digest algorithm such as MD5
(described in
1414 Internet RFC
1321, The MD5 Message-Digest Algorithm
; see the Bibliography
), using
1415 the following information
(see implementation note
106 in Appendix H
): - The
1418 - A string representation of the file's location
, usually a pathname
1419 - The size of the file in bytes
1420 - The values of all entries in the file's document information
1421 dictionary
(see Section
9.2.1, Document Information Dictionary
)
1423 This stipulates only that the two IDs must be identical when the file is created
1424 and that they should be reasonably unique. Since it's difficult to get the file
1425 size at this point in the execution of pdfTeX and scanning the info dict is also
1426 difficult
, we start with a simpler implementation using just the first two items.
1429 static void print_ID
(PDF pdf
)
1435 md5_byte_t digest
[16];
1442 size
= strftime
(time_str
, sizeof
(time_str
), "%Y%m%dT%H%M%SZ", gmtime
(&t));
1443 md5_append
(&state, (const md5_byte_t *) time_str, (int) size);
1444 /* get the file name
*/
1445 if
(getcwd
(pwd
, sizeof
(pwd
)) == NULL)
1446 formatted_error
("pdf backend","getcwd() failed (%s), (path too long?)", strerror
(errno
));
1450 for
(p
= pwd
; *p
; p
++) {
1453 else if
(IS_KANJI
(p
))
1458 md5_append
(&state, (const md5_byte_t *) pwd, (int) strlen(pwd));
1459 md5_append
(&state, (const md5_byte_t *) "/", 1);
1460 md5_append
(&state, (const md5_byte_t *) pdf->file_name,
1461 (int
) strlen
(pdf-
>file_name
));
1463 md5_finish
(&state, digest);
1465 convertStringToHexString
((char
*) digest
, id
, 16);
1466 pdf_add_name
(pdf
, "ID");
1467 pdf_begin_array
(pdf
);
1468 pdf_printf
(pdf
, "<%s> <%s>", id
, id
);
1472 @ Print the
/CreationDate entry.
1474 PDF Reference
, third edition says about the expected date format
:
1478 PDF defines a standard date format
, which closely follows that of the
1479 international standard ASN
.1 (Abstract Syntax Notation One
), defined in ISO
/IEC
1480 8824 (see the Bibliography
). A date is a string of the form
1482 (D
:YYYYMMDDHHmmSSOHH'mm'
)
1488 DD is the day
(01-31)
1489 HH is the hour
(00-23)
1490 mm is the minute
(00-59)
1491 SS is the second
(00-59)
1492 O is the relationship of local time to Universal Time
(UT
), denoted by one
1493 of the characters
+, -, or Z
(see below
)
1494 HH followed by ' is the absolute value of the offset from UT in hours
(00-23)
1495 mm followed by ' is the absolute value of the offset from UT in minutes
(00-59)
1497 The apostrophe character
('
) after HH and mm is part of the syntax. All fields
1498 after the year are optional.
(The prefix D
:, although also optional
, is strongly
1499 recommended.
) The default values for MM and DD are both
01; all other numerical
1500 fields default to zero values. A plus sign
(+) as the value of the O field
1501 signifies that local time is later than UT
, a minus sign
(-) that local time is
1502 earlier than UT
, and the letter Z that local time is equal to UT. If no UT
1503 information is specified
, the relationship of the specified time to UT is
1504 considered to be unknown. Whether or not the time zone is known
, the rest of the
1505 date should be specified in local time.
1507 For example
, December
23, 1998, at
7:52 PM
, U.S. Pacific Standard Time
, is
1508 represented by the string
1510 D
:199812231952-08'
00'
1512 The main difficulty is get the time zone offset. |strftime
()| does this in ISO
1513 C99
(e.g. newer glibc
) with \
%z
, but we have to work with other systems
(e.g.
1517 #define TIME_STR_SIZE
30 /* minimum size for |time_str| is
24: |
"D:YYYYmmddHHMMSS+HH'MM'"|
*/
1519 static void makepdftime
(PDF pdf
)
1523 int i
, off
, off_hours
, off_mins
;
1524 time_t t
= pdf-
>start_time
;
1525 char
*time_str
= pdf-
>start_time_str
;
1527 lt
= *localtime
(&t);
1528 size
= strftime
(time_str
, TIME_STR_SIZE
, "D:%Y%m%d%H%M%S", <);
1529 /* expected format
: "YYYYmmddHHMMSS" */
1531 /* unexpected
, contents of |time_str| is undefined
*/
1536 correction for seconds
: \
%S can be in range
00.
.61, the PDF reference
1537 expects
00.
.59, therefore we map
"60" and
"61" to
"59"
1539 if
(time_str
[14] == '
6'
) {
1543 time_str
[16] = '\
0'
;
1545 /* get the time zone offset
*/
1547 /* this calculation method was found in exim's tod.c
*/
1548 off
= 60 * (lt.tm_hour
- gmt.tm_hour
) + lt.tm_min
- gmt.tm_min
;
1549 if
(lt.tm_year
!= gmt.tm_year
) {
1550 off
+= (lt.tm_year
> gmt.tm_year
) ?
1440 : -1440;
1551 } else if
(lt.tm_yday
!= gmt.tm_yday
) {
1552 off
+= (lt.tm_yday
> gmt.tm_yday
) ?
1440 : -1440;
1555 time_str
[size
++] = 'Z'
;
1558 off_hours
= off
/ 60;
1559 off_mins
= abs
(off
- off_hours
* 60);
1560 i
= snprintf
(&time_str[size], 9, "%+03d'%02d'", off_hours, off_mins);
1561 check_nprintf
(i
, 9);
1563 pdf-
>start_time
= t
;
1567 void init_start_time
(PDF pdf
)
1569 if
(pdf-
>start_time
== 0) {
1570 pdf-
>start_time
= time
((time_t
*) NULL);
1571 pdf-
>start_time_str
= xtalloc
(TIME_STR_SIZE
, char
);
1577 char
*getcreationdate
(PDF pdf
)
1579 init_start_time
(pdf
);
1580 return pdf-
>start_time_str
;
1584 void remove_pdffile
(PDF pdf
)
1587 if
(!kpathsea_debug
&& pdf->file_name && (pdf->draftmode == 0)) {
1588 xfclose
(pdf-
>file
, pdf-
>file_name
);
1589 remove
(pdf-
>file_name
);
1594 @ Use |check_o_mode
()| in the backend-specific
"Implement..." chunks
1597 void check_o_mode
(PDF pdf
, const char
*s
, int o_mode_bitpattern
, boolean strict
) /* s ignored now
*/
1601 const char
*m
= NULL;
1603 normal_error
("lua only","no backend present, needed for what you asked for");
1607 in warn mode
(strict
== false
): only check
, don't do |fix_o_mode
()| here
! |output_mode_used|
1608 is left in possibly wrong state until real output
, ok.
1610 if
(output_mode_used
== OMODE_NONE
)
1611 o_mode
= get_o_mode
();
1613 o_mode
= output_mode_used
;
1614 pdf-
>o_mode
= output_mode_used
; /* used by synctex
, we need to use output_mode_used there
*/
1615 if
(!((1 << o_mode
) & o_mode_bitpattern)) { /* warning or error */
1624 normal_error
("pdf backend","weird output state");
1627 formatted_error
("pdf backend", "%s not allowed in %s mode (outputmode = %d)",s
, m
, (int
) int_par
(output_mode_code
));
1629 formatted_warning
("pdf backend", "%s not allowed in %s mode (outputmode = %d)",s
, m
, (int
) int_par
(output_mode_code
));
1631 ensure_output_state
(pdf
, ST_HEADER_WRITTEN
);
1635 void set_job_id
(PDF pdf
, int year
, int month
, int day
, int time
)
1637 char
*name_string
, *format_string
, *s
;
1640 if
(pdf-
>job_id_string
!= NULL)
1642 name_string
= makecstring
(job_name
);
1643 format_string
= makecstring
(format_ident
);
1644 slen
= SMALL_BUF_SIZE
+ strlen
(name_string
) + strlen
(format_string
) + strlen
(luatex_banner
);
1645 s
= xtalloc
(slen
, char
);
1646 /* The Web2c version string starts with a space.
*/
1647 i
= snprintf
(s
, slen
, "%.4d/%.2d/%.2d %.2d:%.2d %s %s %s", year
, month
, day
, time
/ 60, time
% 60, name_string
, format_string
, luatex_banner
);
1648 check_nprintf
(i
, slen
);
1649 pdf-
>job_id_string
= xstrdup
(s
);
1652 xfree
(format_string
);
1656 char
*get_resname_prefix
(PDF pdf
)
1658 static char name_str
[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1659 static char prefix
[7]; /* make a tag of
6 chars long
*/
1661 size_t base
= strlen
(name_str
);
1662 unsigned long crc
= crc32
(0L, Z_NULL
, 0);
1663 crc
= crc32
(crc
, (Bytef
*) pdf-
>job_id_string
, (uInt
) strlen
(pdf-
>job_id_string
));
1664 for
(i
= 0; i
< 6; i
++) {
1665 prefix
[i
] = name_str
[crc
% base
];
1673 #define mag int_par
(mag_code
)
1675 void pdf_begin_page
(PDF pdf
)
1678 int xform_attributes
;
1679 scaled form_margin
= pdf_xform_margin
; /* was one_bp until SVN4066
*/
1680 ensure_output_state
(pdf
, ST_HEADER_WRITTEN
);
1681 init_pdf_pagecalculations
(pdf
);
1682 if
(pdf-
>page_resources
== NULL) {
1683 pdf-
>page_resources
= xtalloc
(1, pdf_resource_struct
);
1684 pdf-
>page_resources-
>resources_tree
= NULL;
1686 pdf-
>page_resources-
>last_resources
= pdf_create_obj
(pdf
, obj_type_others
, 0);
1687 reset_page_resources
(pdf
);
1689 if
(global_shipping_mode
== SHIPPING_PAGE
) {
1690 pdf-
>last_page
= pdf_get_obj
(pdf
, obj_type_page
, total_pages
+ 1, 0);
1691 set_obj_aux
(pdf
, pdf-
>last_page
, 1); /* mark that this page has been created
*/
1692 pdf-
>last_stream
= pdf_create_obj
(pdf
, obj_type_pagestream
, 0);
1693 pdf_begin_obj
(pdf
, pdf-
>last_stream
, OBJSTM_NEVER
);
1694 pdf-
>last_thread
= null
;
1695 pdf_begin_dict
(pdf
);
1697 pdf_begin_obj
(pdf
, pdf_cur_form
, OBJSTM_NEVER
);
1698 pdf-
>last_stream
= pdf_cur_form
;
1699 /* Write out Form stream header
*/
1700 pdf_begin_dict
(pdf
);
1701 pdf_dict_add_name
(pdf
, "Type", "XObject");
1702 pdf_dict_add_name
(pdf
, "Subtype", "Form");
1703 xform_attributes
= pdf_xform_attr
; /* lookup once
*/
1704 if
(xform_attributes
!= null
)
1705 pdf_print_toks
(pdf
, xform_attributes
);
1706 if
(obj_xform_attr
(pdf
, pdf_cur_form
) != null
) {
1707 pdf_print_toks
(pdf
, obj_xform_attr
(pdf
, pdf_cur_form
));
1708 delete_token_ref
(obj_xform_attr
(pdf
, pdf_cur_form
));
1709 set_obj_xform_attr
(pdf
, pdf_cur_form
, null
);
1711 if
(obj_xform_attr_str
(pdf
, pdf_cur_form
) != null
) {
1712 lua_pdf_literal
(pdf
, obj_xform_attr_str
(pdf
, pdf_cur_form
));
1713 luaL_unref
(Luas
, LUA_REGISTRYINDEX
, obj_xform_attr_str
(pdf
, pdf_cur_form
));
1714 set_obj_xform_attr_str
(pdf
, pdf_cur_form
, null
);
1716 pdf_add_name
(pdf
, "BBox");
1717 pdf_begin_array
(pdf
);
1718 pdf_add_bp
(pdf
, -form_margin
);
1719 pdf_add_bp
(pdf
, -form_margin
);
1720 pdf_add_bp
(pdf
, pdf-
>page_size.h
+ form_margin
);
1721 pdf_add_bp
(pdf
, pdf-
>page_size.v
+ form_margin
);
1723 pdf_dict_add_int
(pdf
, "FormType", 1);
1724 pdf_add_name
(pdf
, "Matrix");
1725 pdf_begin_array
(pdf
);
1726 pdf_add_int
(pdf
, 1);
1727 pdf_add_int
(pdf
, 0);
1728 pdf_add_int
(pdf
, 0);
1729 pdf_add_int
(pdf
, 1);
1730 pdf_add_int
(pdf
, 0);
1731 pdf_add_int
(pdf
, 0);
1733 pdf_dict_add_ref
(pdf
, "Resources", pdf-
>page_resources-
>last_resources
);
1735 /* Start stream of page
/form contents
*/
1736 pdf_dict_add_streaminfo
(pdf
);
1738 pdf_begin_stream
(pdf
);
1739 if
(global_shipping_mode
== SHIPPING_PAGE
) {
1740 /* Adjust transformation matrix for the magnification ratio
*/
1742 setpdffloat
(f
, mag
, 3);
1743 print_pdffloat
(pdf
, f
);
1744 pdf_puts
(pdf
, " 0 0 ");
1745 print_pdffloat
(pdf
, f
);
1746 pdf_puts
(pdf
, " 0 0 cm\n");
1749 pos_stack_used
= 0; /* start with empty stack
*/
1750 if
(global_shipping_mode
== SHIPPING_PAGE
) {
1751 colorstackpagestart
();
1753 if
(global_shipping_mode
== SHIPPING_PAGE
)
1754 pdf_out_colorstack_startpage
(pdf
);
1758 void print_pdf_table_string
(PDF pdf
, const char
*s
)
1762 lua_rawgeti
(Luas
, LUA_REGISTRYINDEX
, lua_key_index
(pdf_data
));
1763 lua_rawget
(Luas
, LUA_REGISTRYINDEX
);
1764 lua_pushstring
(Luas
, s
); /* s t ...
*/
1765 lua_rawget
(Luas
, -2); /* s? t ...
*/
1766 if
(lua_type
(Luas
, -1) == LUA_TSTRING
) { /* s t ...
*/
1767 ls
= lua_tolstring
(Luas
, -1, &len);
1771 pdf_out_block
(pdf
, ls
, len
);
1779 const char
*get_pdf_table_string
(const char
*s
)
1782 lua_rawgeti
(Luas
, LUA_REGISTRYINDEX
, lua_key_index
(pdf_data
));
1783 lua_rawget
(Luas
, LUA_REGISTRYINDEX
);
1784 lua_pushstring
(Luas
, s
); /* s t ...
*/
1785 lua_rawget
(Luas
, -2); /* s? t ...
*/
1786 if
(lua_type
(Luas
, -1) == LUA_TSTRING
) { /* s t ...
*/
1787 ls.s
= lua_tolstring
(Luas
, -1, &ls.l);
1789 s is supposed to be anchored
(e.g in the registry
)
1790 so it's not garbage collected
1800 void pdf_end_page
(PDF pdf
)
1803 int j
, annots
= 0, beads
= 0, callback_id
;
1804 pdf_resource_struct
*res_p
= pdf-
>page_resources
;
1805 pdf_resource_struct local_page_resources
;
1806 pdf_object_list
*annot_list
, *bead_list
, *link_list
, *ol
, *ol1
;
1807 scaledpos save_cur_page_size
; /* to save |pdf-
>page_size| during flushing pending forms
*/
1808 shipping_mode_e save_shipping_mode
;
1809 int xform_resources
;
1810 int page_resources
, page_attributes
;
1811 int procset
= PROCSET_PDF
;
1812 /* Finish stream of page
/form contents
*/
1813 pdf_goto_pagemode
(pdf
);
1814 if
(pos_stack_used
> 0) {
1815 formatted_error
("pdf backend","%u unmatched 'save' after %s shipout", (unsigned int
) pos_stack_used
,
1816 ((global_shipping_mode
== SHIPPING_PAGE
) ?
"page" : "form"));
1818 pdf_end_stream
(pdf
);
1820 callback_id
= callback_defined
(finish_pdfpage_callback
);
1821 if
(callback_id
> 0)
1822 run_callback
(callback_id
, "b->",(global_shipping_mode
== SHIPPING_PAGE
));
1823 if
(global_shipping_mode
== SHIPPING_PAGE
) {
1824 pdf-
>last_pages
= pdf_do_page_divert
(pdf
, pdf-
>last_page
, 0);
1825 /* Write out
/Page object
*/
1826 pdf_begin_obj
(pdf
, pdf-
>last_page
, OBJSTM_ALWAYS
);
1827 pdf_begin_dict
(pdf
);
1828 pdf_dict_add_name
(pdf
, "Type", "Page");
1829 pdf_dict_add_ref
(pdf
, "Contents", pdf-
>last_stream
);
1830 pdf_dict_add_ref
(pdf
, "Resources", res_p-
>last_resources
);
1831 pdf_add_name
(pdf
, "MediaBox");
1832 pdf_begin_array
(pdf
);
1833 pdf_add_int
(pdf
, 0);
1834 pdf_add_int
(pdf
, 0);
1835 pdf_add_bp
(pdf
, pdf-
>page_size.h
);
1836 pdf_add_bp
(pdf
, pdf-
>page_size.v
);
1838 page_attributes
= pdf_page_attr
; /* lookup once
*/
1839 if
(page_attributes
!= null
)
1840 pdf_print_toks
(pdf
, page_attributes
);
1841 print_pdf_table_string
(pdf
, "pageattributes");
1842 pdf_dict_add_ref
(pdf
, "Parent", pdf-
>last_pages
);
1843 if
(pdf-
>img_page_group_val
!= 0) {
1844 pdf_dict_add_ref
(pdf
, "Group", pdf-
>img_page_group_val
);
1846 annot_list
= get_page_resources_list
(pdf
, obj_type_annot
);
1847 link_list
= get_page_resources_list
(pdf
, obj_type_link
);
1848 if
(annot_list
!= NULL || link_list
!= NULL) {
1849 annots
= pdf_create_obj
(pdf
, obj_type_annots
, 0);
1850 pdf_dict_add_ref
(pdf
, "Annots", annots
);
1852 bead_list
= get_page_resources_list
(pdf
, obj_type_bead
);
1853 if
(bead_list
!= NULL) {
1854 beads
= pdf_create_obj
(pdf
, obj_type_beads
, 0);
1855 pdf_dict_add_ref
(pdf
, "B", beads
);
1859 pdf-
>img_page_group_val
= 0;
1860 /* Generate array of annotations or beads in page
*/
1861 if
(annot_list
!= NULL || link_list
!= NULL) {
1862 pdf_begin_obj
(pdf
, annots
, OBJSTM_ALWAYS
);
1863 pdf_begin_array
(pdf
);
1864 while
(annot_list
!= NULL) {
1865 pdf_add_ref
(pdf
, annot_list-
>info
);
1866 annot_list
= annot_list-
>link
;
1868 while
(link_list
!= NULL) {
1869 pdf_add_ref
(pdf
, link_list-
>info
);
1870 link_list
= link_list-
>link
;
1875 if
(bead_list
!= NULL) {
1876 pdf_begin_obj
(pdf
, beads
, OBJSTM_ALWAYS
);
1877 pdf_begin_array
(pdf
);
1878 while
(bead_list
!= NULL) {
1879 pdf_add_ref
(pdf
, bead_list-
>info
);
1880 bead_list
= bead_list-
>link
;
1886 /* Write out resource lists and pending raw objects
*/
1887 ol
= get_page_resources_list
(pdf
, obj_type_obj
);
1888 while
(ol
!= NULL) {
1889 if
(!is_obj_written
(pdf
, ol-
>info
))
1890 pdf_write_obj
(pdf
, ol-
>info
);
1895 When flushing pending forms we need to save and restore resource lists
1896 which are also used by page shipping. Saving and restoring
1897 |pdf-
>page_size| is needed for proper writing out pending PDF marks.
1899 ol
= get_page_resources_list
(pdf
, obj_type_xform
);
1900 while
(ol
!= NULL) {
1901 if
(!is_obj_written
(pdf
, ol-
>info
)) {
1902 pdf_cur_form
= ol-
>info
;
1903 save_cur_page_size
= pdf-
>page_size
;
1904 save_shipping_mode
= global_shipping_mode
;
1905 pdf-
>page_resources
= &local_page_resources;
1906 local_page_resources.resources_tree
= NULL;
1907 ship_out
(pdf
, obj_xform_box
(pdf
, pdf_cur_form
), SHIPPING_FORM
);
1908 /* Restore page size and page resources
*/
1909 pdf-
>page_size
= save_cur_page_size
;
1910 global_shipping_mode
= save_shipping_mode
;
1911 destroy_page_resources_tree
(pdf
);
1912 pdf-
>page_resources
= res_p
;
1916 /* Write out pending images
*/
1917 ol
= get_page_resources_list
(pdf
, obj_type_ximage
);
1918 while
(ol
!= NULL) {
1919 if
(!is_obj_written
(pdf
, ol-
>info
))
1920 pdf_write_image
(pdf
, ol-
>info
);
1923 if
(global_shipping_mode
== SHIPPING_PAGE
) {
1924 /* Write out pending PDF marks and annotations
*/
1925 ol
= get_page_resources_list
(pdf
, obj_type_annot
);
1926 while
(ol
!= NULL) {
1927 if
(ol-
>info
> 0 && obj_type(pdf, ol->info) == obj_type_annot) {
1928 j
= obj_annot_ptr
(pdf
, ol-
>info
); /* |j| points to |pdf_annot_node|
*/
1929 pdf_begin_obj
(pdf
, ol-
>info
, OBJSTM_ALWAYS
);
1930 pdf_begin_dict
(pdf
);
1931 pdf_dict_add_name
(pdf
, "Type", "Annot");
1932 pdf_print_toks
(pdf
, pdf_annot_data
(j
));
1933 pdf_rectangle
(pdf
, j
);
1939 /* Write out PDF link annotations
*/
1940 if
((ol
= get_page_resources_list
(pdf
, obj_type_link
)) != NULL) {
1941 while
(ol
!= NULL) {
1942 j
= obj_annot_ptr
(pdf
, ol-
>info
);
1943 pdf_begin_obj
(pdf
, ol-
>info
, OBJSTM_ALWAYS
);
1944 pdf_begin_dict
(pdf
);
1945 pdf_dict_add_name
(pdf
, "Type", "Annot");
1946 if
(pdf_action_type
(pdf_link_action
(j
)) != pdf_action_user
)
1947 pdf_dict_add_name
(pdf
, "Subtype", "Link");
1948 if
(pdf_link_attr
(j
) != null
)
1949 pdf_print_toks
(pdf
, pdf_link_attr
(j
));
1950 pdf_rectangle
(pdf
, j
);
1951 if
(pdf_action_type
(pdf_link_action
(j
)) != pdf_action_user
)
1952 pdf_puts
(pdf
, "/A ");
1953 write_action
(pdf
, pdf_link_action
(j
));
1958 /* Flush |pdf_start_link_node|'s created by |append_link|
*/
1959 ol
= get_page_resources_list
(pdf
, obj_type_link
);
1960 while
(ol
!= NULL) {
1961 j
= obj_annot_ptr
(pdf
, ol-
>info
);
1963 nodes with |subtype
= pdf_link_data_node| were created by |append_link| and
1964 must be flushed here
, as they are not linked in any list
1966 if
(subtype
(j
) == pdf_link_data_node
)
1971 /* Write out PDF mark destinations
*/
1972 write_out_pdf_mark_destinations
(pdf
);
1973 /* Write out PDF bead rectangle specifications
*/
1974 print_bead_rectangles
(pdf
);
1976 /* Write out resources dictionary
*/
1977 pdf_begin_obj
(pdf
, res_p-
>last_resources
, OBJSTM_ALWAYS
);
1978 pdf_begin_dict
(pdf
);
1979 /* Print additional resources
*/
1980 if
(global_shipping_mode
== SHIPPING_PAGE
) {
1981 page_resources
= pdf_page_resources
; /* lookup once
*/
1982 if
(page_resources
!= null
)
1983 pdf_print_toks
(pdf
, page_resources
);
1984 print_pdf_table_string
(pdf
, "pageresources");
1986 xform_resources
= pdf_xform_resources
; /* lookup once
*/
1987 if
(xform_resources
!= null
)
1988 pdf_print_toks
(pdf
, xform_resources
);
1989 if
(obj_xform_resources
(pdf
, pdf_cur_form
) != null
) {
1990 pdf_print_toks
(pdf
, obj_xform_resources
(pdf
, pdf_cur_form
));
1991 delete_token_ref
(obj_xform_resources
(pdf
, pdf_cur_form
));
1992 set_obj_xform_resources
(pdf
, pdf_cur_form
, null
);
1994 if
(obj_xform_resources_str
(pdf
, pdf_cur_form
) != null
) {
1995 lua_pdf_literal
(pdf
, obj_xform_resources_str
(pdf
, pdf_cur_form
));
1996 luaL_unref
(Luas
, LUA_REGISTRYINDEX
, obj_xform_resources_str
(pdf
, pdf_cur_form
));
1997 set_obj_xform_resources_str
(pdf
, pdf_cur_form
, null
);
2000 /* Generate font resources
*/
2001 if
((ol
= get_page_resources_list
(pdf
, obj_type_font
)) != NULL) {
2002 pdf_add_name
(pdf
, "Font");
2003 pdf_begin_dict
(pdf
);
2004 while
(ol
!= NULL) {
2006 p
+= snprintf
(p
, 20, "F%i", obj_info
(pdf
, ol-
>info
));
2007 if
(pdf-
>resname_prefix
!= NULL)
2008 p
+= snprintf
(p
, 20, "%s", pdf-
>resname_prefix
);
2009 pdf_dict_add_ref
(pdf
, s
, ol-
>info
);
2013 procset |
= PROCSET_TEXT
;
2015 /* Generate XObject resources
*/
2016 ol
= get_page_resources_list
(pdf
, obj_type_xform
);
2017 ol1
= get_page_resources_list
(pdf
, obj_type_ximage
);
2018 if
(ol
!= NULL || ol1
!= NULL) {
2019 pdf_add_name
(pdf
, "XObject");
2020 pdf_begin_dict
(pdf
);
2021 while
(ol
!= NULL) {
2023 p
+= snprintf
(p
, 20, "Fm%i", obj_info
(pdf
, ol-
>info
));
2024 if
(pdf-
>resname_prefix
!= NULL)
2025 p
+= snprintf
(p
, 20, "%s", pdf-
>resname_prefix
);
2026 pdf_dict_add_ref
(pdf
, s
, ol-
>info
);
2029 while
(ol1
!= null
) {
2031 p
+= snprintf
(p
, 20, "Im%i", obj_info
(pdf
, ol1-
>info
));
2032 if
(pdf-
>resname_prefix
!= NULL)
2033 p
+= snprintf
(p
, 20, "%s", pdf-
>resname_prefix
);
2034 pdf_dict_add_ref
(pdf
, s
, ol1-
>info
);
2035 procset |
= img_procset
(idict_array
[obj_data_ptr
(pdf
, ol1-
>info
)]);
2040 /* Generate ProcSet
*/
2041 pdf_add_name
(pdf
, "ProcSet");
2042 pdf_begin_array
(pdf
);
2043 if
((procset
& PROCSET_PDF) != 0)
2044 pdf_add_name
(pdf
, "PDF");
2045 if
((procset
& PROCSET_TEXT) != 0)
2046 pdf_add_name
(pdf
, "Text");
2047 if
((procset
& PROCSET_IMAGE_B) != 0)
2048 pdf_add_name
(pdf
, "ImageB");
2049 if
((procset
& PROCSET_IMAGE_C) != 0)
2050 pdf_add_name
(pdf
, "ImageC");
2051 if
((procset
& PROCSET_IMAGE_I) != 0)
2052 pdf_add_name
(pdf
, "ImageI");
2058 @
* Finishing the PDF output file.
2060 @ Destinations that have been referenced but don't exists have
2061 |obj_dest_ptr
=null|. Leaving them undefined might cause troubles for PDF
2062 browsers
, so we need to fix them
; they point to the last page.
2065 static void check_nonexisting_destinations
(PDF pdf
)
2068 for
(k
= pdf-
>head_tab
[obj_type_dest
]; k
!= 0; k
= obj_link
(pdf
, k
)) {
2069 if
(obj_dest_ptr
(pdf
, k
) == null
) {
2070 if
(obj_info
(pdf
, k
) < 0) {
2071 char
*ss
= makecstring
(-obj_info
(pdf
, k
));
2072 formatted_warning
("pdf backend", "unreferenced destination with name '%s'",ss
);
2074 formatted_warning
("pdf backend", "unreferenced destination with num '%d'",obj_info
(pdf
,k
));
2077 pdf_begin_obj
(pdf
, k
, OBJSTM_ALWAYS
);
2078 pdf_begin_array
(pdf
);
2079 pdf_add_ref
(pdf
, pdf-
>last_page
);
2080 pdf_add_name
(pdf
, "Fit");
2088 static void check_nonexisting_pages
(PDF pdf
)
2090 struct avl_traverser t
;
2092 struct avl_table
*page_tree
= pdf-
>obj_tree
[obj_type_page
];
2093 avl_t_init
(&t, page_tree);
2094 /* search from the end backward until the last real page is found
*/
2095 for
(p
= avl_t_last
(&t, page_tree); p != NULL && obj_aux(pdf, p->objptr) == 0; p = avl_t_prev(&t)) {
2096 formatted_warning
("pdf backend", "page %d has been referenced but does not exist",obj_info
(pdf
, p-
>objptr
));
2100 @ If the same keys in a dictionary are given several times
, then it is not
2101 defined which value is choosen by an application. Therefore the keys |
/Producer|
2102 and |
/Creator| are only set if the token list |pdf_info_toks| converted to a
2103 string does not contain these key strings.
2106 static boolean substr_of_str
(const char
*s
, const char
*t
)
2108 if
(strstr
(t
, s
) == NULL)
2113 static int pdf_print_info
(PDF pdf
, int luatexversion
,
2114 str_number luatexrevision
)
2115 { /* print info object
*/
2116 boolean creator_given
= false
;
2117 boolean producer_given
= false
;
2118 boolean creationdate_given
= false
;
2119 boolean moddate_given
= false
;
2120 boolean trapped_given
= false
;
2122 const char
*p
= NULL;
2124 k
= pdf_create_obj
(pdf
, obj_type_info
, 0);
2125 pdf_begin_obj
(pdf
, k
, 3); /* keep Info readable unless explicitely forced
*/
2126 pdf_begin_dict
(pdf
);
2127 if
(pdf_info_toks
!= 0) {
2128 s
= tokenlist_to_cstring
(pdf_info_toks
, true
, &len);
2129 creator_given
= substr_of_str
("/Creator", s
);
2130 producer_given
= substr_of_str
("/Producer", s
);
2131 creationdate_given
= substr_of_str
("/CreationDate", s
);
2132 moddate_given
= substr_of_str
("/ModDate", s
);
2133 trapped_given
= substr_of_str
("/Trapped", s
);
2135 p
= get_pdf_table_string
("info");
2136 if
(p
&& strlen(p) > 0) {
2137 creator_given
= creator_given || substr_of_str
("/Creator", p
);
2138 producer_given
= producer_given || substr_of_str
("/Producer", p
);
2139 creationdate_given
= creationdate_given || substr_of_str
("/CreationDate", p
);
2140 moddate_given
= moddate_given || substr_of_str
("/ModDate", p
);
2141 trapped_given
= trapped_given || substr_of_str
("/Trapped", p
);
2143 if
(pdf_info_toks
!= null
) {
2150 delete_token_ref
(pdf_info_toks
);
2151 pdf_info_toks
= null
;
2153 if
(p
&& strlen(p) > 0) {
2155 pdf_puts
(pdf
, p
); /* no free
, pointer
*/
2158 if
(!producer_given
) {
2159 /* Print the Producer key
*/
2160 pdf_add_name
(pdf
, "Producer");
2161 pdf_puts
(pdf
, " (LuaTeX-");
2162 pdf_print_int
(pdf
, luatexversion
/ 100);
2164 pdf_print_int
(pdf
, luatexversion
% 100);
2166 pdf_print
(pdf
, luatexrevision
);
2170 pdf_dict_add_string
(pdf
, "Creator", "TeX");
2171 if
(!creationdate_given
) {
2172 init_start_time
(pdf
);
2173 pdf_dict_add_string
(pdf
, "CreationDate", pdf-
>start_time_str
);
2175 if
(!moddate_given
) {
2176 init_start_time
(pdf
);
2177 pdf_dict_add_string
(pdf
, "ModDate", pdf-
>start_time_str
);
2179 if
(!trapped_given
) {
2180 pdf_dict_add_name
(pdf
, "Trapped", "False");
2182 pdf_dict_add_string
(pdf
, "PTEX.Fullbanner", luatex_banner
);
2188 static void build_free_object_list
(PDF pdf
)
2192 set_obj_fresh
(pdf
, l
); /* null object at begin of list of free objects
*/
2193 for
(k
= 1; k
<= pdf-
>obj_ptr
; k
++) {
2194 if
(!is_obj_written
(pdf
, k
)) {
2195 set_obj_link
(pdf
, l
, k
);
2199 set_obj_link
(pdf
, l
, 0);
2202 @ Now the finish of PDF output file. At this moment all Page objects
2203 are already written completely to PDF output file.
2206 void finish_pdf_file
(PDF pdf
, int luatexversion
, str_number luatexrevision
)
2209 int root
, info
, xref_stm
= 0, outlines
, threads
, names_tree
;
2210 size_t xref_offset_width
;
2211 int callback_id
= callback_defined
(stop_run_callback
);
2212 int callback_id1
= callback_defined
(finish_pdffile_callback
);
2213 if
(total_pages
== 0) {
2214 if
(callback_id
== 0) {
2215 normal_warning
("pdf backend","no pages of output.");
2216 } else if
(callback_id
> 0) {
2217 run_callback
(callback_id
, "->");
2220 normal_error
("pdf backend","dangling objects discarded, no output file produced.");
2222 if
(pdf-
>draftmode
== 0) {
2223 pdf_flush
(pdf
); /* to make sure that the output file name has been already created
*/
2224 flush_jbig2_page0_objects
(pdf
); /* flush page
0 objects from JBIG2 images
, if any
*/
2225 if
(callback_id1
> 0)
2226 run_callback
(callback_id1
, "->");
2227 check_nonexisting_pages
(pdf
);
2228 check_nonexisting_destinations
(pdf
);
2229 /* Output fonts definition
*/
2230 for
(k
= 1; k
<= max_font_id
(); k
++) {
2231 if
(font_used
(k
) && (pdf_font_num(k) < 0)) {
2232 i
= -pdf_font_num
(k
);
2233 for
(j
= font_bc
(k
); j
<= font_ec
(k
); j
++)
2234 if
(quick_char_exists
(k
, j
) && pdf_char_marked(k, j))
2235 pdf_mark_char
(i
, j
);
2236 if
((pdf_font_attr
(i
) == 0) && (pdf_font_attr(k) != 0)) {
2237 set_pdf_font_attr
(i
, pdf_font_attr
(k
));
2238 } else if
((pdf_font_attr
(k
) == 0) && (pdf_font_attr(i) != 0)) {
2239 set_pdf_font_attr
(k
, pdf_font_attr
(i
));
2240 } else if
((pdf_font_attr
(i
) != 0) && (pdf_font_attr(k) != 0) && (!str_eq_str(pdf_font_attr(i), pdf_font_attr(k)))) {
2241 formatted_warning
("pdf backend","fontattr of font %d and %d are conflicting, %k is used",i
,k
,i
);
2245 pdf-
>gen_tounicode
= pdf_gen_tounicode
;
2246 k
= pdf-
>head_tab
[obj_type_font
];
2248 int f
= obj_info
(pdf
, k
);
2249 do_pdf_font
(pdf
, f
);
2250 k
= obj_link
(pdf
, k
);
2252 write_fontstuff
(pdf
);
2253 pdf-
>last_pages
= output_pages_tree
(pdf
);
2254 /* Output outlines
*/
2255 outlines
= print_outlines
(pdf
);
2257 Output name tree. The name tree is very similiar to Pages tree so
2258 its construction should be certain from Pages tree construction.
2259 For intermediate node |obj_info| will be the first name and
2260 |obj_link| will be the last name in \.
{\\Limits
} array. Note that
2261 |pdf_dest_names_ptr| will be less than |obj_ptr|
, so we test if
2262 |k
< pdf_dest_names_ptr| then |k| is index of leaf in
2263 |dest_names|
; else |k| will be index in |obj_tab| of some
2266 names_tree
= output_name_tree
(pdf
);
2268 /* Output article threads
*/
2269 if
(pdf-
>head_tab
[obj_type_thread
] != 0) {
2270 threads
= pdf_create_obj
(pdf
, obj_type_others
, 0);
2271 pdf_begin_obj
(pdf
, threads
, OBJSTM_ALWAYS
);
2272 pdf_begin_array
(pdf
);
2273 k
= pdf-
>head_tab
[obj_type_thread
];
2275 pdf_add_ref
(pdf
, k
);
2276 k
= obj_link
(pdf
, k
);
2280 k
= pdf-
>head_tab
[obj_type_thread
];
2283 k
= obj_link
(pdf
, k
);
2288 /* Output the
/Catalog object
*/
2289 root
= pdf_create_obj
(pdf
, obj_type_catalog
, 0);
2290 pdf_begin_obj
(pdf
, root
, OBJSTM_ALWAYS
);
2291 pdf_begin_dict
(pdf
);
2292 pdf_dict_add_name
(pdf
, "Type", "Catalog");
2293 pdf_dict_add_ref
(pdf
, "Pages", pdf-
>last_pages
);
2295 pdf_dict_add_ref
(pdf
, "Threads", threads
);
2297 pdf_dict_add_ref
(pdf
, "Outlines", outlines
);
2298 if
(names_tree
!= 0)
2299 pdf_dict_add_ref
(pdf
, "Names", names_tree
);
2300 if
(pdf_catalog_toks
!= null
) {
2301 pdf_print_toks
(pdf
, pdf_catalog_toks
);
2302 delete_token_ref
(pdf_catalog_toks
);
2303 pdf_catalog_toks
= null
;
2305 print_pdf_table_string
(pdf
, "catalog");
2306 if
(pdf_catalog_openaction
!= 0)
2307 pdf_dict_add_ref
(pdf
, "OpenAction", pdf_catalog_openaction
);
2310 /* last candidate for object stream
*/
2311 info
= pdf_print_info
(pdf
, luatexversion
, luatexrevision
);
2312 /* final object for pdf-
>os_enable
== false
*/
2313 if
(pdf-
>os_enable
) {
2314 pdf_buffer_select
(pdf
, OBJSTM_BUF
);
2315 pdf_os_write_objstream
(pdf
);
2317 pdf_buffer_select
(pdf
, PDFOUT_BUF
);
2318 /* Output the cross-reference stream dictionary
*/
2319 xref_stm
= pdf_create_obj
(pdf
, obj_type_others
, 0);
2320 pdf_begin_obj
(pdf
, xref_stm
, OBJSTM_NEVER
); /* final object for pdf-
>os_enable
== true
*/
2321 if
((obj_offset
(pdf
, pdf-
>obj_ptr
) / 256) > 16777215)
2322 xref_offset_width
= 5;
2323 else if
(obj_offset
(pdf
, pdf-
>obj_ptr
) > 16777215)
2324 xref_offset_width
= 4;
2325 else if
(obj_offset
(pdf
, pdf-
>obj_ptr
) > 65535)
2326 xref_offset_width
= 3;
2328 xref_offset_width
= 2;
2329 /* Build a linked list of free objects
*/
2330 build_free_object_list
(pdf
);
2331 pdf_begin_dict
(pdf
);
2332 pdf_dict_add_name
(pdf
, "Type", "XRef");
2333 pdf_add_name
(pdf
, "Index");
2334 pdf_begin_array
(pdf
);
2335 pdf_add_int
(pdf
, 0);
2336 pdf_add_int
(pdf
, pdf-
>obj_ptr
+ 1);
2338 pdf_dict_add_int
(pdf
, "Size", pdf-
>obj_ptr
+ 1);
2339 pdf_add_name
(pdf
, "W");
2340 pdf_begin_array
(pdf
);
2341 pdf_add_int
(pdf
, 1);
2342 pdf_add_int
(pdf
, (int
) xref_offset_width
);
2343 pdf_add_int
(pdf
, 1);
2345 pdf_dict_add_ref
(pdf
, "Root", root
);
2346 pdf_dict_add_ref
(pdf
, "Info", info
);
2347 if
(pdf_trailer_toks
!= null
) {
2348 pdf_print_toks
(pdf
, pdf_trailer_toks
);
2349 delete_token_ref
(pdf_trailer_toks
);
2350 pdf_trailer_toks
= null
;
2352 print_pdf_table_string
(pdf
, "trailer");
2354 pdf_dict_add_streaminfo
(pdf
);
2356 pdf_begin_stream
(pdf
);
2357 for
(k
= 0; k
<= pdf-
>obj_ptr
; k
++) {
2358 if
(!is_obj_written
(pdf
, k
)) { /* a free object
*/
2360 pdf_out_bytes
(pdf
, obj_link
(pdf
, k
), xref_offset_width
);
2362 } else if
(obj_os_idx
(pdf
, k
) == PDF_OS_MAX_OBJS
) { /* object not in object stream
*/
2364 pdf_out_bytes
(pdf
, obj_offset
(pdf
, k
),
2367 } else
{ /* object in object stream
*/
2369 pdf_out_bytes
(pdf
, obj_offset
(pdf
, k
),
2371 pdf_out
(pdf
, obj_os_idx
(pdf
, k
));
2374 pdf_end_stream
(pdf
);
2378 /* Output the |obj_tab| and build a linked list of free objects
*/
2379 build_free_object_list
(pdf
);
2380 pdf_save_offset
(pdf
);
2381 pdf_puts
(pdf
, "xref\n");
2382 pdf_puts
(pdf
, "0 ");
2383 pdf_print_int_ln
(pdf
, pdf-
>obj_ptr
+ 1);
2384 pdf_print_fw_int
(pdf
, obj_link
(pdf
, 0));
2385 pdf_puts
(pdf
, " 65535 f \n");
2386 for
(k
= 1; k
<= pdf-
>obj_ptr
; k
++) {
2387 if
(!is_obj_written
(pdf
, k
)) {
2388 pdf_print_fw_int
(pdf
, obj_link
(pdf
, k
));
2389 pdf_puts
(pdf
, " 00000 f \n");
2391 pdf_print_fw_int
(pdf
, obj_offset
(pdf
, k
));
2392 pdf_puts
(pdf
, " 00000 n \n");
2396 /* Output the trailer
*/
2397 if
(!pdf-
>os_enable
) {
2398 pdf_puts
(pdf
, "trailer\n");
2399 pdf_begin_dict
(pdf
);
2400 pdf_dict_add_int
(pdf
, "Size", pdf-
>obj_ptr
+ 1);
2401 pdf_dict_add_ref
(pdf
, "Root", root
);
2402 pdf_dict_add_ref
(pdf
, "Info", info
);
2403 if
(pdf_trailer_toks
!= null
) {
2404 pdf_print_toks
(pdf
, pdf_trailer_toks
);
2405 delete_token_ref
(pdf_trailer_toks
);
2406 pdf_trailer_toks
= null
;
2412 pdf_puts
(pdf
, "startxref\n");
2415 pdf_add_longint
(pdf
, (longinteger
) obj_offset
(pdf
, xref_stm
));
2417 pdf_add_longint
(pdf
, (longinteger
) pdf-
>save_offset
);
2418 pdf_puts
(pdf
, "\n%%EOF\n");
2420 if
(callback_id
== 0) {
2421 tprint_nl
("Output written on ");
2422 tprint
(pdf-
>file_name
);
2424 print_int
(total_pages
);
2426 if
(total_pages
!= 1)
2429 print_int
(pdf_offset
(pdf
));
2432 } else if
(callback_id
> 0) {
2433 run_callback
(callback_id
, "->");
2436 if
(callback_id
> 0) {
2437 run_callback
(callback_id
, "->");
2441 if
(pdf-
>draftmode
== 0)
2442 close_file
(pdf-
>file
);
2444 normal_warning
("pdf backend","draftmode enabled, not changing output pdf");
2446 if
(callback_id
== 0) {
2447 if
(log_opened_global
) {
2448 fprintf
(log_file
, "\nPDF statistics: %d PDF objects out of %d (max. %d)\n",
2449 (int
) pdf-
>obj_ptr
, (int
) pdf-
>obj_tab_size
,
2450 (int
) sup_obj_tab_size
);
2451 if
(pdf-
>os-
>ostm_ctr
> 0) {
2452 fprintf
(log_file
, " %d compressed objects within %d object stream%s\n",
2453 (int
) pdf-
>os-
>o_ctr
, (int
) pdf-
>os-
>ostm_ctr
,
2454 (pdf-
>os-
>ostm_ctr
> 1 ?
"s" : ""));
2456 fprintf
(log_file
, " %d named destinations out of %d (max. %d)\n",
2457 (int
) pdf-
>dest_names_ptr
, (int
) pdf-
>dest_names_size
,
2458 (int
) sup_dest_names_size
);
2459 fprintf
(log_file
, " %d words of extra memory for PDF output out of %d (max. %d)\n",
2460 (int
) pdf-
>mem_ptr
, (int
) pdf-
>mem_size
,
2461 (int
) sup_pdf_mem_size
);
2467 void scan_pdfcatalog
(PDF pdf
)
2470 scan_toks
(false
, true
);
2471 pdf_catalog_toks
= concat_tokens
(pdf_catalog_toks
, def_ref
);
2472 if
(scan_keyword
("openaction")) {
2473 if
(pdf_catalog_openaction
!= 0) {
2474 normal_error
("pdf backend", "duplicate of openaction");
2476 check_o_mode
(pdf
, "catalog", 1 << OMODE_PDF
, true
);
2477 p
= scan_action
(pdf
);
2478 pdf_catalog_openaction
= pdf_create_obj
(pdf
, obj_type_others
, 0);
2479 pdf_begin_obj
(pdf
, pdf_catalog_openaction
, OBJSTM_ALWAYS
);
2480 write_action
(pdf
, p
);
2482 delete_action_ref
(p
);