3
Copyright 2009 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/>. */
20
static const char __svn_version[] =
21
"$Id: pdfgen.c 3261 2009-12-18 11:38:21Z taco $"
22
"$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.50.0/source/texk/web2c/luatexdir/pdf/pdfgen.c $";
28
/* for tokenlist_to_cstring */
30
#define is_hex_char isxdigit
32
#define check_nprintf(size_get, size_want) \
33
if ((unsigned)(size_get) >= (unsigned)(size_want)) \
34
pdftex_fail ("snprintf failed: file %s, line %d", __FILE__, __LINE__);
36
PDF static_pdf = NULL;
38
static char *jobname_cstr = NULL;
40
/* commandline interface */
41
int pdf_output_option;
43
int pdf_draftmode_option;
44
int pdf_draftmode_value;
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
boolean is_shipping_page; /* set to |shipping_page| when |ship_out| starts */
53
/* init_pdf_struct() is called early, only once, from maincontrol.c */
55
PDF init_pdf_struct(PDF pdf)
58
pdf = xmalloc(sizeof(pdf_output_file));
59
memset(pdf, 0, sizeof(pdf_output_file));
61
pdf->o_mode = OMODE_NONE; /* will be set by fix_o_mode() */
62
pdf->o_state = ST_INITIAL;
64
pdf->os_obj = xmalloc(pdf_os_max_objs * sizeof(os_obj_data));
65
pdf->os_buf_size = inf_pdf_os_buf_size;
66
pdf->os_buf = xmalloc(pdf->os_buf_size * sizeof(unsigned char));
67
pdf->op_buf_size = inf_pdf_op_buf_size;
68
pdf->op_buf = xmalloc(pdf->op_buf_size * sizeof(unsigned char));
70
pdf->buf_size = pdf->op_buf_size;
71
pdf->buf = pdf->op_buf;
73
/* Sometimes it is neccesary to allocate memory for PDF output that cannot
74
be deallocated then, so we use |mem| for this purpose. */
75
pdf->mem_size = inf_pdf_mem_size; /* allocated size of |mem| array */
76
pdf->mem = xmalloc(pdf->mem_size * sizeof(int));
77
pdf->mem_ptr = 1; /* the first word is not used so we can use zero as a value for testing
78
whether a pointer to |mem| is valid */
81
pdf->posstruct = xmalloc(sizeof(posstructure));
82
pdf->posstruct->pos.h = 0;
83
pdf->posstruct->pos.v = 0;
84
pdf->posstruct->dir = dir_TLT;
86
pdf->obj_tab_size = inf_obj_tab_size; /* allocated size of |obj_tab| array */
87
pdf->obj_tab = xmalloc((pdf->obj_tab_size + 1) * sizeof(obj_entry));
88
memset(pdf->obj_tab, 0, sizeof(obj_entry));
90
pdf->minor_version = -1; /* unset */
91
pdf->decimal_digits = 4;
93
pdf->image_gamma = 65536;
94
pdf->image_hicolor = 1;
95
pdf->image_apply_gamma = 0;
96
pdf->objcompresslevel = 0;
97
pdf->compress_level = 0;
99
pdf->inclusion_copy_font = 1;
100
pdf->replace_font = 0;
101
pdf->pk_resolution = 0;
102
pdf->pk_scale_factor = 0;
104
init_dest_names(pdf);
105
pdf->resources = NULL;
107
init_pdf_pagecalculations(pdf);
112
static void pdf_shipout_begin(boolean shipping_page)
114
pos_stack_used = 0; /* start with empty stack */
116
page_mode = shipping_page;
118
colorstackpagestart();
122
static void pdf_shipout_end(boolean shipping_page)
124
if (pos_stack_used > 0) {
125
pdftex_fail("%u unmatched \\pdfsave after %s shipout",
126
(unsigned int) pos_stack_used,
127
((shipping_page) ? "page" : "form"));
132
We use |pdf_get_mem| to allocate memory in |mem|
135
int pdf_get_mem(PDF pdf, int s)
136
{ /* allocate |s| words in |mem| */
139
if (s > sup_pdf_mem_size - pdf->mem_ptr)
140
overflow("PDF memory size (pdf_mem_size)", pdf->mem_size);
141
if (pdf->mem_ptr + s > pdf->mem_size) {
142
a = 0.2 * pdf->mem_size;
143
if (pdf->mem_ptr + s > pdf->mem_size + a) {
144
pdf->mem_size = pdf->mem_ptr + s;
145
} else if (pdf->mem_size < sup_pdf_mem_size - a) {
146
pdf->mem_size = pdf->mem_size + a;
148
pdf->mem_size = sup_pdf_mem_size;
150
pdf->mem = xreallocarray(pdf->mem, int, pdf->mem_size);
153
pdf->mem_ptr = pdf->mem_ptr + s;
158
|fix_o_mode| freezes |pdf->o_mode| as soon as anything goes through
159
the backend, be it \.{PDF}, \.{DVI}, or \.{Lua}.
162
#define pdf_output int_par(pdf_output_code)
164
void fix_o_mode(PDF pdf)
166
static int fixed_pdf_output = 0;
167
if (pdf->o_mode == OMODE_NONE) {
168
if (pdf_output > 0) {
169
if (pdf_output == 2009)
170
pdf->o_mode = OMODE_LUA;
172
pdf->o_mode = OMODE_PDF;
174
pdf->o_mode = OMODE_DVI;
175
fixed_pdf_output = pdf_output;
176
} else if (pdf_output != fixed_pdf_output) {
178
"\\pdfoutput can only be changed before anything is written to the output");
183
This ensures that |pdfminorversion| is set only before any bytes have
184
been written to the generated \.{PDF} file. Here also all variables for
185
\.{PDF} output are initialized, the \.{PDF} file is opened by |ensure_pdf_open|,
186
and the \.{PDF} header is written.
189
void fix_pdf_minorversion(PDF pdf)
191
if (pdf->minor_version < 0) { /* unset */
192
if ((pdf_minor_version < 0) || (pdf_minor_version > 9)) {
193
char *hlp[] = { "The pdfminorversion must be between 0 and 9.",
194
"I changed this to 4.", NULL
197
(void) snprintf(msg, 255,
198
"LuaTeX error (illegal pdfminorversion %d)",
199
(int) pdf_minor_version);
201
pdf_minor_version = 4;
203
pdf->minor_version = pdf_minor_version;
205
/* Check that variables for \.{PDF} output are unchanged */
206
if (pdf->minor_version != int_par(pdf_minor_version_code))
208
"\\pdfminorversion cannot be changed after data is written to the PDF file");
209
if (pdf->draftmode != int_par(pdf_draftmode_code))
211
"\\pdfdraftmode cannot be changed after data is written to the PDF file");
213
if (pdf->draftmode != 0) {
214
pdf->compress_level = 0; /* re-fix it, might have been changed inbetween */
215
pdf->objcompresslevel = 0;
220
The PDF buffer is flushed by calling |pdf_flush|, which checks the
221
variable |zip_write_state| and will compress the buffer before flushing if
222
neccesary. We call |pdf_begin_stream| to begin a stream and |pdf_end_stream|
223
to finish it. The stream contents will be compressed if compression is turn on.
226
/* writepdf() always writes by fwrite() */
228
static void write_pdf(PDF pdf, int a, int b)
230
(void) fwrite((char *) &pdf->buf[a], sizeof(pdf->buf[a]),
231
(int) ((b) - (a) + 1), pdf->file);
234
void pdf_flush(PDF pdf)
235
{ /* flush out the |pdf_buf| */
237
off_t saved_pdf_gone;
239
saved_pdf_gone = pdf->gone;
240
switch (pdf->zip_write_state) {
243
if (pdf->draftmode == 0)
244
write_pdf(pdf, 0, pdf->ptr - 1);
245
pdf->gone += pdf->ptr;
246
pdf->last_byte = pdf->buf[pdf->ptr - 1];
250
if (pdf->draftmode == 0)
251
write_zip(pdf, false);
254
if (pdf->draftmode == 0)
255
write_zip(pdf, true);
256
pdf->zip_write_state = no_zip;
260
if (saved_pdf_gone > pdf->gone)
261
pdf_error("file size",
262
"File size exceeds architectural limits (pdf_gone wraps around)");
267
/* switch between PDF stream and object stream mode */
268
void pdf_os_switch(PDF pdf, boolean pdf_os)
270
if (pdf_os && pdf->os_enable) {
271
if (!pdf->os_mode) { /* back up PDF stream variables */
272
pdf->op_ptr = pdf->ptr;
273
pdf->ptr = pdf->os_ptr;
274
pdf->buf = pdf->os_buf;
275
pdf->buf_size = pdf->os_buf_size;
276
pdf->os_mode = true; /* switch to object stream */
279
if (pdf->os_mode) { /* back up object stream variables */
280
pdf->os_ptr = pdf->ptr;
281
pdf->ptr = pdf->op_ptr;
282
pdf->buf = pdf->op_buf;
283
pdf->buf_size = pdf->op_buf_size;
284
pdf->os_mode = false; /* switch to PDF stream */
289
/* create new \.{/ObjStm} object if required, and set up cross reference info */
290
void pdf_os_prepare_obj(PDF pdf, int i, int pdf_os_level)
292
pdf_os_switch(pdf, ((pdf_os_level > 0)
293
&& (pdf->objcompresslevel >= pdf_os_level)));
295
if (pdf->os_cur_objnum == 0) {
296
pdf_create_obj(pdf, obj_type_objstm, pdf->sys_obj_ptr + 1);
297
pdf->os_cur_objnum = pdf->sys_obj_ptr;
298
pdf->obj_ptr--; /* object stream is not accessible to user */
299
pdf->os_cntr++; /* only for statistics */
301
pdf->ptr = 0; /* start fresh object stream */
305
obj_os_idx(pdf, i) = pdf->os_idx;
306
obj_offset(pdf, i) = pdf->os_cur_objnum;
307
pdf->os_obj[pdf->os_idx].num = i;
308
pdf->os_obj[pdf->os_idx].off = pdf->ptr;
310
obj_offset(pdf, i) = pdf_offset(pdf);
311
obj_os_idx(pdf, i) = -1; /* mark it as not included in object stream */
315
/* low-level buffer checkers */
317
/* check that |s| bytes more fit into |pdf_os_buf|; increase it if required */
318
static void pdf_os_get_os_buf(PDF pdf, int s)
321
if (s > sup_pdf_os_buf_size - pdf->ptr)
322
overflow("PDF object stream buffer", pdf->os_buf_size);
323
if (pdf->ptr + s > pdf->os_buf_size) {
324
a = 0.2 * pdf->os_buf_size;
325
if (pdf->ptr + s > pdf->os_buf_size + a)
326
pdf->os_buf_size = pdf->ptr + s;
327
else if (pdf->os_buf_size < sup_pdf_os_buf_size - a)
328
pdf->os_buf_size = pdf->os_buf_size + a;
330
pdf->os_buf_size = sup_pdf_os_buf_size;
332
xreallocarray(pdf->os_buf, unsigned char, pdf->os_buf_size);
333
pdf->buf = pdf->os_buf;
334
pdf->buf_size = pdf->os_buf_size;
338
/* make sure that there are at least |n| bytes free in PDF buffer */
339
void pdf_room(PDF pdf, int n)
341
if (pdf->os_mode && (n + pdf->ptr > pdf->buf_size))
342
pdf_os_get_os_buf(pdf, n);
343
else if ((!pdf->os_mode) && (n > pdf->buf_size))
344
overflow("PDF output buffer", pdf->op_buf_size);
345
else if ((!pdf->os_mode) && (n + pdf->ptr > pdf->buf_size))
350
/* print out a character to PDF buffer; the character will be printed in octal
351
* form in the following cases: chars <= 32, backslash (92), left parenthesis
352
* (40) and right parenthesis (41)
355
#define pdf_print_escaped(c) \
356
if ((c)<=32||(c)=='\\'||(c)=='('||(c)==')'||(c)>127) { \
358
pdf_quick_out(pdf,'\\'); \
359
pdf_quick_out(pdf,'0' + (((c)>>6) & 0x3)); \
360
pdf_quick_out(pdf,'0' + (((c)>>3) & 0x7)); \
361
pdf_quick_out(pdf,'0' + ( (c) & 0x7)); \
366
void pdf_print_char(PDF pdf, int c)
370
pdf_print_escaped(c);
373
void pdf_print_wide_char(PDF pdf, int c)
376
snprintf(hex, 5, "%04X", c);
378
pdf_quick_out(pdf, hex[0]);
379
pdf_quick_out(pdf, hex[1]);
380
pdf_quick_out(pdf, hex[2]);
381
pdf_quick_out(pdf, hex[3]);
384
void pdf_puts(PDF pdf, const char *s)
387
size_t l = strlen(s);
388
if (l < (size_t) pdf->buf_size) {
391
pdf_quick_out(pdf, *s++);
398
__attribute__ ((format(printf, 2, 3)))
399
void pdf_printf(PDF pdf, const char *fmt, ...)
403
if (pdf->printf_buf == NULL) {
404
pdf->printf_buf = xtalloc(PRINTF_BUF_SIZE, char);
406
(void) vsnprintf(pdf->printf_buf, PRINTF_BUF_SIZE, fmt, args);
407
pdf_puts(pdf, pdf->printf_buf);
411
/* print out a string to PDF buffer */
413
void pdf_print(PDF pdf, str_number s)
415
if (s < number_chars) {
419
unsigned char *k, *j;
420
j = str_string(s) + str_length(s);
421
for (k = str_string(s); k < j; k++) {
427
/* print out a integer to PDF buffer */
429
void pdf_print_int(PDF pdf, longinteger n)
431
register int k = 0; /* current digit; we assume that $|n|<10^{23}$ */
435
if (n < -0x7FFFFFFF) { /* need to negate |n| more carefully */
436
register longinteger m;
457
pdf_quick_out(pdf, '0' + dig[k]);
461
/* print $m/10^d$ as real */
463
void pdf_print_real(PDF pdf, int m, int d)
469
pdf_print_int(pdf, m / ten_pow[d]);
474
while (m < ten_pow[d]) {
480
pdf_print_int(pdf, m);
484
/* print out |s| as string in PDF output */
486
void pdf_print_str(PDF pdf, char *s)
489
int l = strlen(s) - 1; /* last string index */
494
/* the next is not really safe, the string could be "(a)xx(b)" */
495
if ((s[0] == '(') && (s[l] == ')')) {
499
if ((s[0] != '<') || (s[l] != '>') || odd((l + 1))) {
506
while (is_hex_char(*s))
514
pdf_puts(pdf, orig); /* it was a hex string after all */
519
void pdf_begin_stream(PDF pdf)
521
assert(pdf->os_mode == false);
522
pdf_puts(pdf, "/Length \n");
523
pdf->seek_write_length = true; /* fill in length at |pdf_end_stream| call */
524
pdf->stream_length_offset = pdf_offset(pdf) - 11;
525
pdf->stream_length = 0;
527
if (pdf->compress_level > 0) {
528
pdf_puts(pdf, "/Filter /FlateDecode\n");
529
pdf_puts(pdf, ">>\n");
530
pdf_puts(pdf, "stream\n");
532
pdf->zip_write_state = zip_writing;
534
pdf_puts(pdf, ">>\n");
535
pdf_puts(pdf, "stream\n");
536
pdf_save_offset(pdf);
542
void pdf_end_stream(PDF pdf)
544
if (pdf->zip_write_state == zip_writing)
545
pdf->zip_write_state = zip_finish;
547
pdf->stream_length = pdf_offset(pdf) - pdf_saved_offset(pdf);
549
if (pdf->seek_write_length)
550
write_stream_length(pdf, pdf->stream_length, pdf->stream_length_offset);
551
pdf->seek_write_length = false;
552
if (pdf->last_byte != pdf_new_line_char)
553
pdf_out(pdf, pdf_new_line_char);
554
pdf_puts(pdf, "endstream\n");
558
void pdf_remove_last_space(PDF pdf)
560
if ((pdf->ptr > 0) && (pdf->buf[pdf->ptr - 1] == ' '))
565
To print |scaled| value to PDF output we need some subroutines to ensure
569
#define max_integer 0x7FFFFFFF /* $2^{31}-1$ */
571
/* scaled value corresponds to 100in, exact, 473628672 */
572
scaled one_hundred_inch = 7227 * 65536;
574
/* scaled value corresponds to 1in (rounded to 4736287) */
575
scaled one_inch = (7227 * 65536 + 50) / 100;
577
/* scaled value corresponds to 1truein (rounded!) */
578
scaled one_true_inch = (7227 * 65536 + 50) / 100;
580
/* scaled value corresponds to 100bp */
581
scaled one_hundred_bp = (7227 * 65536) / 72;
583
/* scaled value corresponds to 1bp (rounded to 65782) */
584
scaled one_bp = ((7227 * 65536) / 72 + 50) / 100;
588
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000
592
The function |divide_scaled| divides |s| by |m| using |dd| decimal
593
digits of precision. It is defined in C because it is a good candidate
594
for optimizations that are not possible in pascal.
597
scaled round_xn_over_d(scaled x, int n, int d)
599
boolean positive; /* was |x>=0|? */
600
unsigned t, u, v; /* intermediate quantities */
607
t = (x % 0100000) * n;
608
u = (x / 0100000) * n + (t / 0100000);
609
v = (u % d) * 0100000 + (t % 0100000);
610
if (u / d >= 0100000)
613
u = 0100000 * (u / d) + (v / d);
615
if (2 * v >= (unsigned) d)
623
#define lround(a) (long) floor((a) + 0.5)
625
void pdf_print_bp(PDF pdf, scaled s)
626
{ /* print scaled as |bp| */
628
pdfstructure *p = pdf->pstruct;
630
a.m = lround(s * p->k1);
631
a.e = pdf->decimal_digits;
632
print_pdffloat(pdf, a);
635
void pdf_print_mag_bp(PDF pdf, scaled s)
636
{ /* take |mag| into account */
638
pdfstructure *p = pdf->pstruct;
640
if (int_par(mag_code) != 1000)
641
a.m = lround(s * (long) int_par(mag_code) / 1000.0 * p->k1);
643
a.m = lround(s * p->k1);
644
a.e = pdf->decimal_digits;
645
print_pdffloat(pdf, a);
648
#define set_p_or_return(a) do { \
657
/**********************************************************************/
659
void reset_resource_lists(pdf_resource_struct * p)
663
p->xform_list = NULL;
664
p->ximage_list = NULL;
667
p->annot_list = NULL;
669
p->text_procset = false;
670
p->image_procset = 0;
673
void append_object_list(PDF pdf, pdf_obj_type t, int objnum)
676
pdf_object_list *item = xmalloc(sizeof(pdf_object_list));
681
case obj_type_obj: set_p_or_return(pdf->resources->obj_list); break;
682
case obj_type_font: set_p_or_return(pdf->resources->font_list); break;
683
case obj_type_xform: set_p_or_return(pdf->resources->xform_list); break;
684
case obj_type_ximage: set_p_or_return(pdf->resources->ximage_list); break;
685
case obj_type_dest: set_p_or_return(pdf->resources->dest_list); break;
686
case obj_type_link: set_p_or_return(pdf->resources->link_list); break;
687
case obj_type_annot: set_p_or_return(pdf->resources->annot_list); break;
688
case obj_type_bead: set_p_or_return(pdf->resources->bead_list); break;
689
default: assert(0); break;
692
while (p->link != NULL)
695
set_obj_scheduled(pdf, objnum);
699
/* return zero on failure, or the object */
700
pdf_object_list *lookup_object_list(PDF pdf, pdf_obj_type t, int f)
705
case obj_type_obj: p = pdf->resources->obj_list; break;
706
case obj_type_font: p = pdf->resources->font_list; break;
707
case obj_type_xform: p = pdf->resources->xform_list; break;
708
case obj_type_ximage: p = pdf->resources->ximage_list; break;
709
case obj_type_dest: p = pdf->resources->dest_list; break;
710
case obj_type_link: p = pdf->resources->link_list; break;
711
case obj_type_annot: p = pdf->resources->annot_list; break;
712
case obj_type_bead: p = pdf->resources->bead_list; break;
713
default: return NULL; break; /* shouldnt happen */
724
static void flush_object_list(PDF pdf, pdf_obj_type t)
726
pdf_object_list *q, *p;
729
case obj_type_obj: p = pdf->resources->obj_list; break;
730
case obj_type_font: p = pdf->resources->font_list; break;
731
case obj_type_xform: p = pdf->resources->xform_list; break;
732
case obj_type_ximage: p = pdf->resources->ximage_list; break;
733
case obj_type_dest: p = pdf->resources->dest_list; break;
734
case obj_type_link: p = pdf->resources->link_list; break;
735
case obj_type_annot: p = pdf->resources->annot_list; break;
736
case obj_type_bead: p = pdf->resources->bead_list; break;
737
default: return; break;
747
case obj_type_obj: pdf->resources->obj_list = NULL; break;
748
case obj_type_font: pdf->resources->font_list = NULL; break;
749
case obj_type_xform: pdf->resources->xform_list = NULL; break;
750
case obj_type_ximage: pdf->resources->ximage_list = NULL; break;
751
case obj_type_dest: pdf->resources->dest_list = NULL; break;
752
case obj_type_link: pdf->resources->link_list = NULL; break;
753
case obj_type_annot: pdf->resources->annot_list = NULL; break;
754
case obj_type_bead: pdf->resources->bead_list = NULL; break;
755
default: break; /* cant happen */
760
void flush_resource_lists(PDF pdf)
762
flush_object_list(pdf, obj_type_font);
763
flush_object_list(pdf, obj_type_obj);
764
flush_object_list(pdf, obj_type_xform);
765
flush_object_list(pdf, obj_type_ximage);
766
/* the following lists are nonzero only if shipping_page */
767
flush_object_list(pdf, obj_type_annot);
768
flush_object_list(pdf, obj_type_link);
769
flush_object_list(pdf, obj_type_dest);
770
flush_object_list(pdf, obj_type_bead);
773
/**********************************************************************/
775
/* Subroutines to print out various PDF objects */
777
/* print out an integer with fixed width; used for outputting cross-reference table */
778
void pdf_print_fw_int(PDF pdf, longinteger n, int w)
780
int k; /* $0\le k\le23$ */
790
pdf_quick_out(pdf, '0' + dig[k]);
793
/* print out an integer as a number of bytes; used for outputting \.{/XRef} cross-reference stream */
794
void pdf_out_bytes(PDF pdf, longinteger n, int w)
797
int bytes[8]; /* digits in a number being output */
806
pdf_quick_out(pdf, bytes[k]);
809
/* print out an entry in dictionary with integer value to PDF buffer */
811
void pdf_int_entry(PDF pdf, char *s, int v)
813
pdf_printf(pdf, "/%s ", s);
814
pdf_print_int(pdf, v);
815
} void pdf_int_entry_ln(PDF pdf, char *s, int v)
818
pdf_int_entry(pdf, s, v);
822
/* print out an indirect entry in dictionary */
823
void pdf_indirect(PDF pdf, char *s, int o)
825
pdf_printf(pdf, "/%s %d 0 R", s, (int) o);
826
} void pdf_indirect_ln(PDF pdf, char *s, int o)
829
pdf_indirect(pdf, s, o);
833
/* print out |s| as string in PDF output */
834
void pdf_print_str_ln(PDF pdf, char *s)
836
pdf_print_str(pdf, s);
840
/* print out an entry in dictionary with string value to PDF buffer */
841
void pdf_str_entry(PDF pdf, char *s, char *v)
845
pdf_printf(pdf, "/%s ", s);
846
pdf_print_str(pdf, v);
849
void pdf_str_entry_ln(PDF pdf, char *s, char *v)
853
pdf_str_entry(pdf, s, v);
857
void pdf_print_toks(PDF pdf, halfword p)
860
char *s = tokenlist_to_cstring(p, true, &len);
867
void pdf_print_toks_ln(PDF pdf, halfword p)
870
char *s = tokenlist_to_cstring(p, true, &len);
878
/* prints a rect spec */
879
void pdf_print_rect_spec(PDF pdf, halfword r)
881
pdf_print_mag_bp(pdf, pdf_ann_left(r));
883
pdf_print_mag_bp(pdf, pdf_ann_bottom(r));
885
pdf_print_mag_bp(pdf, pdf_ann_right(r));
887
pdf_print_mag_bp(pdf, pdf_ann_top(r));
890
/* output a rectangle specification to PDF file */
891
void pdf_rectangle(PDF pdf, halfword r)
894
pdf_puts(pdf, "/Rect [");
895
pdf_print_rect_spec(pdf, r);
896
pdf_puts(pdf, "]\n");
899
static void init_pdf_outputparameters(PDF pdf)
901
assert(pdf->o_mode == OMODE_PDF);
902
pdf->draftmode = fix_int(pdf_draftmode, 0, 1);
903
pdf->compress_level = fix_int(pdf_compress_level, 0, 9);
904
pdf->decimal_digits = fix_int(pdf_decimal_digits, 0, 4);
905
pdf->gamma = fix_int(pdf_gamma, 0, 1000000);
906
pdf->image_gamma = fix_int(pdf_image_gamma, 0, 1000000);
907
pdf->image_hicolor = fix_int(pdf_image_hicolor, 0, 1);
908
pdf->image_apply_gamma = fix_int(pdf_image_apply_gamma, 0, 1);
909
pdf->objcompresslevel = fix_int(pdf_objcompresslevel, 0, 3);
910
pdf->inclusion_copy_font = fix_int(pdf_inclusion_copy_font, 0, 1);
911
pdf->replace_font = fix_int(pdf_replace_font, 0, 1);
912
pdf->pk_resolution = fix_int(pdf_pk_resolution, 72, 8000);
913
if ((pdf->minor_version >= 5) && (pdf->objcompresslevel > 0)) {
914
pdf->os_enable = true;
916
if (pdf->objcompresslevel > 0) {
917
pdf_warning("Object streams",
918
"\\pdfobjcompresslevel > 0 requires \\pdfminorversion > 4. Object streams disabled now.",
920
pdf->objcompresslevel = 0;
922
pdf->os_enable = false;
924
if (pdf->pk_resolution == 0) /* if not set from format file or by user */
925
pdf->pk_resolution = pk_dpi; /* take it from \.{texmf.cnf} */
926
pdf->pk_scale_factor =
927
divide_scaled(72, pdf->pk_resolution, 5 + pdf->decimal_digits);
928
if (!callback_defined(read_pk_file_callback)) {
929
if (pdf_pk_mode != null) {
930
char *s = tokenlist_to_cstring(pdf_pk_mode, true, NULL);
931
kpseinitprog("PDFTEX", pdf->pk_resolution, s, nil);
934
kpseinitprog("PDFTEX", pdf->pk_resolution, nil, nil);
936
if (!kpsevarvalue("MKTEXPK"))
937
kpsesetprogramenabled(kpsepkformat, 1, kpsesrccmdline);
939
set_job_id(pdf, int_par(year_code),
940
int_par(month_code), int_par(day_code), int_par(time_code));
941
if ((pdf_unique_resname > 0) && (pdf->resname_prefix == NULL))
942
pdf->resname_prefix = get_resname_prefix(pdf);
945
/**********************************************************************/
947
/* Checks that we have a name for the generated PDF file and that it's open. */
949
static void ensure_output_file_open(PDF pdf, char *ext)
952
if (pdf->file_name != NULL)
956
fn = pack_job_name(ext);
957
if (pdf->draftmode == 0 || pdf->o_mode == OMODE_DVI) {
958
while (!lua_b_open_out(&pdf->file, fn))
959
fn = prompt_file_name("file name for output", ext);
964
static void ensure_pdf_header_written(PDF pdf)
966
assert(pdf->o_state == ST_FILE_OPEN);
967
assert(pdf->o_mode == OMODE_PDF);
968
/* Initialize variables for \.{PDF} output */
969
fix_pdf_minorversion(pdf);
970
init_pdf_outputparameters(pdf);
971
/* Write \.{PDF} header */
972
pdf_printf(pdf, "%%PDF-1.%d\n", pdf->minor_version);
974
pdf_out(pdf, 'P' + 128);
975
pdf_out(pdf, 'T' + 128);
976
pdf_out(pdf, 'E' + 128);
977
pdf_out(pdf, 'X' + 128);
981
void ensure_output_state(PDF pdf, output_state s)
983
if (pdf->o_state < s) {
985
ensure_output_state(pdf, s - 1);
991
switch (pdf->o_mode) {
993
ensure_output_file_open(pdf, ".dvi");
996
ensure_output_file_open(pdf, ".pdf");
1005
switch (pdf->o_mode) {
1007
ensure_dvi_header_written(pdf);
1010
ensure_pdf_header_written(pdf);
1018
case ST_HEADER_WRITTEN:
1020
case ST_FILE_CLOSED:
1029
/**********************************************************************/
1031
/* begin a PDF dictionary object */
1032
void pdf_begin_dict(PDF pdf, int i, int pdf_os_level)
1034
ensure_output_state(pdf, ST_HEADER_WRITTEN);
1035
pdf_os_prepare_obj(pdf, i, pdf_os_level);
1036
if (!pdf->os_mode) {
1037
pdf_printf(pdf, "%d 0 obj <<\n", (int) i);
1039
if (pdf->compress_level == 0)
1040
pdf_printf(pdf, "%% %d 0 obj\n", (int) i); /* debugging help */
1041
pdf_puts(pdf, "<<\n");
1045
/* begin a new PDF dictionary object */
1046
void pdf_new_dict(PDF pdf, int t, int i, int pdf_os)
1048
pdf_create_obj(pdf, t, i);
1049
pdf_begin_dict(pdf, pdf->obj_ptr, pdf_os);
1052
/* end a PDF dictionary object */
1053
void pdf_end_dict(PDF pdf)
1056
pdf_puts(pdf, ">>\n");
1057
if (pdf->os_idx == pdf_os_max_objs - 1)
1058
pdf_os_write_objstream(pdf);
1060
pdf_puts(pdf, ">> endobj\n");
1066
Write out an accumulated object stream.
1067
First the object number and byte offset pairs are generated
1068
and appended to the ready buffered object stream.
1069
By this the value of \.{/First} can be calculated.
1070
Then a new \.{/ObjStm} object is generated, and everything is
1071
copied to the PDF output buffer, where also compression is done.
1072
When calling this procedure, |pdf_os_mode| must be |true|.
1075
void pdf_os_write_objstream(PDF pdf)
1077
halfword i, j, p, q;
1078
if (pdf->os_cur_objnum == 0) /* no object stream started */
1083
while (i <= pdf->os_idx) { /* assemble object number and byte offset pairs */
1084
pdf_printf(pdf, "%d %d", (int) pdf->os_obj[i].num,
1085
(int) pdf->os_obj[i].off);
1086
if (j == 9) { /* print out in groups of ten for better readability */
1087
pdf_out(pdf, pdf_new_line_char);
1095
pdf->buf[pdf->ptr - 1] = pdf_new_line_char; /* no risk of flush, as we are in |pdf_os_mode| */
1097
pdf_begin_dict(pdf, pdf->os_cur_objnum, 0); /* switch to PDF stream writing */
1098
pdf_puts(pdf, "/Type /ObjStm\n");
1099
pdf_printf(pdf, "/N %d\n", (int) (pdf->os_idx + 1));
1100
pdf_printf(pdf, "/First %d\n", (int) (q - p));
1101
pdf_begin_stream(pdf);
1102
pdf_room(pdf, q - p); /* should always fit into the PDF output buffer */
1104
while (i < q) { /* write object number and byte offset pairs */
1105
pdf_quick_out(pdf, pdf->os_buf[i]);
1110
q = i + pdf->buf_size;
1113
pdf_room(pdf, q - i);
1114
while (i < q) { /* write the buffered objects */
1115
pdf_quick_out(pdf, pdf->os_buf[i]);
1119
pdf_end_stream(pdf);
1120
pdf->os_cur_objnum = 0; /* to force object stream generation next time */
1123
/* begin a PDF object */
1124
void pdf_begin_obj(PDF pdf, int i, int pdf_os_level)
1126
ensure_output_state(pdf, ST_HEADER_WRITTEN);
1127
pdf_os_prepare_obj(pdf, i, pdf_os_level);
1128
if (!pdf->os_mode) {
1129
pdf_printf(pdf, "%d 0 obj\n", (int) i);
1130
} else if (pdf->compress_level == 0) {
1131
pdf_printf(pdf, "%% %d 0 obj\n", (int) i); /* debugging help */
1135
/* begin a new PDF object */
1136
void pdf_new_obj(PDF pdf, int t, int i, int pdf_os)
1138
pdf_create_obj(pdf, t, i);
1139
pdf_begin_obj(pdf, pdf->obj_ptr, pdf_os);
1142
/* end a PDF object */
1143
void pdf_end_obj(PDF pdf)
1146
if (pdf->os_idx == pdf_os_max_objs - 1)
1147
pdf_os_write_objstream(pdf);
1149
pdf_puts(pdf, "endobj\n"); /* end a PDF object */
1153
void write_stream_length(PDF pdf, int length, longinteger offset)
1155
if (jobname_cstr == NULL)
1156
jobname_cstr = makecstring(job_name);
1157
if (pdf->draftmode == 0) {
1158
xfseeko(pdf->file, (off_t) offset, SEEK_SET, jobname_cstr);
1159
fprintf(pdf->file, "%li", (long int) length);
1160
xfseeko(pdf->file, pdf_offset(pdf), SEEK_SET, jobname_cstr);
1164
/* Converts any string given in in in an allowed PDF string which can be
1165
* handled by printf et.al.: \ is escaped to \\, parenthesis are escaped and
1166
* control characters are octal encoded.
1167
* This assumes that the string does not contain any already escaped
1170
char *convertStringToPDFString(const char *in, int len)
1172
static char pstrbuf[MAX_PSTRING_LEN];
1173
char *out = pstrbuf;
1177
for (i = 0; i < len; i++) {
1178
check_buf(j + sizeof(buf), MAX_PSTRING_LEN);
1179
if (((unsigned char) in[i] < '!') || ((unsigned char) in[i] > '~')) {
1180
/* convert control characters into oct */
1181
k = snprintf(buf, sizeof(buf),
1182
"\\%03o", (unsigned int) (unsigned char) in[i]);
1183
check_nprintf(k, sizeof(buf));
1188
} else if ((in[i] == '(') || (in[i] == ')')) {
1189
/* escape paranthesis */
1192
} else if (in[i] == '\\') {
1193
/* escape backslash */
1205
/* Converts any string given in in in an allowed PDF string which is
1206
* hexadecimal encoded;
1207
* sizeof(out) should be at least lin*2+1.
1210
static void convertStringToHexString(const char *in, char *out, int lin)
1215
for (i = 0; i < lin; i++) {
1216
k = snprintf(buf, sizeof(buf),
1217
"%02X", (unsigned int) (unsigned char) in[i]);
1218
check_nprintf(k, sizeof(buf));
1225
/* Compute the ID string as per PDF1.4 9.3:
1227
File identifers are defined by the optional ID entry in a PDF file's
1228
trailer dictionary (see Section 3.4.4, "File Trailer"; see also
1229
implementation note 105 in Appendix H). The value of this entry is an
1230
array of two strings. The first string is a permanent identifier based
1231
on the contents of the file at the time it was originally created, and
1232
does not change when the file is incrementally updated. The second
1233
string is a changing identifier based on the file's contents at the
1234
time it was last updated. When a file is first written, both
1235
identifiers are set to the same value. If both identifiers match when a
1236
file reference is resolved, it is very likely that the correct file has
1237
been found; if only the first identifier matches, then a different
1238
version of the correct file has been found.
1239
To help ensure the uniqueness of file identifiers, it is recommend
1240
that they be computed using a message digest algorithm such as MD5
1241
(described in Internet RFC 1321, The MD5 Message-Digest Algorithm; see
1242
the Bibliography), using the following information (see implementation
1243
note 106 in Appendix H):
1245
- A string representation of the file's location, usually a pathname
1246
- The size of the file in bytes
1247
- The values of all entries in the file's document information
1248
dictionary (see Section 9.2.1, Document Information Dictionary )
1250
This stipulates only that the two IDs must be identical when the file is
1251
created and that they should be reasonably unique. Since it's difficult
1252
to get the file size at this point in the execution of pdfTeX and
1253
scanning the info dict is also difficult, we start with a simpler
1254
implementation using just the first two items.
1256
void print_ID(PDF pdf, char *file_name)
1262
md5_byte_t digest[16];
1269
size = strftime(time_str, sizeof(time_str), "%Y%m%dT%H%M%SZ", gmtime(&t));
1270
md5_append(&state, (const md5_byte_t *) time_str, size);
1271
/* get the file name */
1272
if (getcwd(pwd, sizeof(pwd)) == NULL)
1273
pdftex_fail("getcwd() failed (%s), (path too long?)", strerror(errno));
1274
md5_append(&state, (const md5_byte_t *) pwd, strlen(pwd));
1275
md5_append(&state, (const md5_byte_t *) "/", 1);
1276
md5_append(&state, (const md5_byte_t *) file_name, strlen(file_name));
1278
md5_finish(&state, digest);
1280
convertStringToHexString((char *) digest, id, 16);
1281
pdf_printf(pdf, "/ID [<%s> <%s>]", id, id);
1284
/* Print the /CreationDate entry.
1286
PDF Reference, third edition says about the expected date format:
1290
PDF defines a standard date format, which closely follows that of
1291
the international standard ASN.1 (Abstract Syntax Notation One),
1292
defined in ISO/IEC 8824 (see the Bibliography). A date is a string
1295
(D:YYYYMMDDHHmmSSOHH'mm')
1301
DD is the day (01-31)
1302
HH is the hour (00-23)
1303
mm is the minute (00-59)
1304
SS is the second (00-59)
1305
O is the relationship of local time to Universal Time (UT),
1306
denoted by one of the characters +, -, or Z (see below)
1307
HH followed by ' is the absolute value of the offset from UT
1309
mm followed by ' is the absolute value of the offset from UT
1312
The apostrophe character (') after HH and mm is part of the syntax.
1313
All fields after the year are optional. (The prefix D:, although also
1314
optional, is strongly recommended.) The default values for MM and DD
1315
are both 01; all other numerical fields default to zero values. A plus
1316
sign (+) as the value of the O field signifies that local time is
1317
later than UT, a minus sign (-) that local time is earlier than UT,
1318
and the letter Z that local time is equal to UT. If no UT information
1319
is specified, the relationship of the specified time to UT is
1320
considered to be unknown. Whether or not the time zone is known, the
1321
rest of the date should be specified in local time.
1323
For example, December 23, 1998, at 7:52 PM, U.S. Pacific Standard
1324
Time, is represented by the string
1326
D:199812231952-08'00'
1329
The main difficulty is get the time zone offset. strftime() does this in ISO
1330
C99 (e.g. newer glibc) with %z, but we have to work with other systems (e.g.
1333
#define TIME_STR_SIZE 30 /* minimum size for time_str is 24: "D:YYYYmmddHHMMSS+HH'MM'" */
1334
static void makepdftime(PDF pdf)
1338
int i, off, off_hours, off_mins;
1339
time_t t = pdf->start_time;
1340
char *time_str = pdf->start_time_str;
1343
lt = *localtime(&t);
1344
size = strftime(time_str, TIME_STR_SIZE, "D:%Y%m%d%H%M%S", <);
1345
/* expected format: "YYYYmmddHHMMSS" */
1347
/* unexpected, contents of time_str is undefined */
1352
/* correction for seconds: %S can be in range 00..61,
1353
the PDF reference expects 00..59,
1354
therefore we map "60" and "61" to "59" */
1355
if (time_str[14] == '6') {
1358
time_str[16] = '\0'; /* for safety */
1361
/* get the time zone offset */
1364
/* this calculation method was found in exim's tod.c */
1365
off = 60 * (lt.tm_hour - gmt.tm_hour) + lt.tm_min - gmt.tm_min;
1366
if (lt.tm_year != gmt.tm_year) {
1367
off += (lt.tm_year > gmt.tm_year) ? 1440 : -1440;
1368
} else if (lt.tm_yday != gmt.tm_yday) {
1369
off += (lt.tm_yday > gmt.tm_yday) ? 1440 : -1440;
1373
time_str[size++] = 'Z';
1376
off_hours = off / 60;
1377
off_mins = abs(off - off_hours * 60);
1378
i = snprintf(&time_str[size], 9, "%+03d'%02d'", off_hours, off_mins);
1379
check_nprintf(i, 9);
1381
pdf->start_time = t;
1384
void init_start_time(PDF pdf)
1387
if (pdf->start_time == 0) {
1388
pdf->start_time = time((time_t *) NULL);
1389
pdf->start_time_str = xtalloc(TIME_STR_SIZE, char);
1394
void print_creation_date(PDF pdf)
1396
init_start_time(pdf);
1397
pdf_printf(pdf, "/CreationDate (%s)\n", pdf->start_time_str);
1400
void print_mod_date(PDF pdf)
1402
init_start_time(pdf);
1403
pdf_printf(pdf, "/ModDate (%s)\n", pdf->start_time_str);
1406
char *getcreationdate(PDF pdf)
1409
init_start_time(pdf);
1410
return pdf->start_time_str;
1413
void remove_pdffile(PDF pdf)
1416
if (!kpathsea_debug && pdf->file_name && (pdf->draftmode != 0)) {
1417
xfclose(pdf->file, pdf->file_name);
1418
remove(pdf->file_name);
1423
static void realloc_fb(PDF pdf)
1425
if (pdf->fb_array == NULL) {
1426
pdf->fb_limit = SMALL_ARRAY_SIZE;
1427
pdf->fb_array = xtalloc(pdf->fb_limit, char);
1428
pdf->fb_ptr = pdf->fb_array;
1429
} else if ((size_t) (pdf->fb_ptr - pdf->fb_array + 1) > pdf->fb_limit) {
1430
size_t last_ptr_index = pdf->fb_ptr - pdf->fb_array;
1432
if ((size_t) (pdf->fb_ptr - pdf->fb_array + 1) > pdf->fb_limit)
1433
pdf->fb_limit = pdf->fb_ptr - pdf->fb_array + 1;
1434
xretalloc(pdf->fb_array, pdf->fb_limit, char);
1435
pdf->fb_ptr = pdf->fb_array + last_ptr_index;
1439
int fb_offset(PDF pdf)
1441
return pdf->fb_ptr - pdf->fb_array;
1444
void fb_seek(PDF pdf, int offset)
1446
pdf->fb_ptr = pdf->fb_array + offset;
1450
void fb_putchar(PDF pdf, eight_bits b)
1452
if ((size_t) (pdf->fb_ptr - pdf->fb_array + 1) > pdf->fb_limit)
1454
*(pdf->fb_ptr)++ = b;
1457
void fb_flush(PDF pdf)
1461
for (p = pdf->fb_array; p < pdf->fb_ptr;) {
1462
n = pdf->buf_size - pdf->ptr;
1463
if (pdf->fb_ptr - p < n)
1464
n = pdf->fb_ptr - p;
1465
memcpy(pdf->buf + pdf->ptr, p, (unsigned) n);
1467
if (pdf->ptr == pdf->buf_size)
1471
pdf->fb_ptr = pdf->fb_array;
1474
void fb_free(PDF pdf)
1476
xfree(pdf->fb_array);
1480
#define ZIP_BUF_SIZE 32768
1482
#define check_err(f, fn) \
1484
pdftex_fail("zlib: %s() failed (error code %d)", fn, f)
1486
void write_zip(PDF pdf, boolean finish)
1489
int level = pdf->compress_level;
1491
/* This was just to suppress the filename report in |pdftex_fail|
1492
but zlib errors are rare enough (especially now that the
1493
compress level is fixed) that I don't care about the slightly
1494
ugly error message that could result.
1496
/* cur_file_name = NULL; */
1497
if (pdf->stream_length == 0) {
1498
if (pdf->zipbuf == NULL) {
1499
pdf->zipbuf = xtalloc(ZIP_BUF_SIZE, char);
1500
pdf->c_stream.zalloc = (alloc_func) 0;
1501
pdf->c_stream.zfree = (free_func) 0;
1502
pdf->c_stream.opaque = (voidpf) 0;
1503
check_err(deflateInit(&pdf->c_stream, level), "deflateInit");
1505
check_err(deflateReset(&pdf->c_stream), "deflateReset");
1507
pdf->c_stream.next_out = (Bytef *) pdf->zipbuf;
1508
pdf->c_stream.avail_out = ZIP_BUF_SIZE;
1510
assert(pdf->zipbuf != NULL);
1511
pdf->c_stream.next_in = pdf->buf;
1512
pdf->c_stream.avail_in = pdf->ptr;
1514
if (pdf->c_stream.avail_out == 0) {
1515
pdf->gone += xfwrite(pdf->zipbuf, 1, ZIP_BUF_SIZE, pdf->file);
1516
pdf->last_byte = pdf->zipbuf[ZIP_BUF_SIZE - 1]; /* not needed */
1517
pdf->c_stream.next_out = (Bytef *) pdf->zipbuf;
1518
pdf->c_stream.avail_out = ZIP_BUF_SIZE;
1520
err = deflate(&pdf->c_stream, finish ? Z_FINISH : Z_NO_FLUSH);
1521
if (finish && err == Z_STREAM_END)
1523
check_err(err, "deflate");
1524
if (!finish && pdf->c_stream.avail_in == 0)
1528
if (pdf->c_stream.avail_out < ZIP_BUF_SIZE) { /* at least one byte has been output */
1530
xfwrite(pdf->zipbuf, 1, ZIP_BUF_SIZE - pdf->c_stream.avail_out,
1533
pdf->zipbuf[ZIP_BUF_SIZE - pdf->c_stream.avail_out - 1];
1537
pdf->stream_length = pdf->c_stream.total_out;
1540
void zip_free(PDF pdf)
1542
if (pdf->zipbuf != NULL) {
1543
check_err(deflateEnd(&pdf->c_stream), "deflateEnd");
1548
void pdf_error(char *t, char *p)
1550
normalize_selector();
1551
print_err("LuaTeX error");
1563
void pdf_warning(char *t, char *p, boolean prepend_nl, boolean append_nl)
1567
tprint("LuaTeX warning");
1578
if (history == spotless)
1579
history = warning_issued;
1582
/**********************************************************************/
1583
/* Use check_o_mode() in the backend-specific "Implement..." chunks */
1585
void check_o_mode(PDF pdf, char *s, int o_mode_bitpattern, boolean strict)
1588
char warn_string[100];
1592
/* in warn mode (strict == false):
1593
only check, don't do fix_o_mode() here! pdf->o_mode is left
1594
in possibly wrong state until real output, ok.
1597
if (pdf->o_mode == OMODE_NONE) {
1598
if (pdf_output > 0) {
1599
if (pdf_output == 2009)
1606
o_mode = pdf->o_mode;
1607
if (!((1 << o_mode) & o_mode_bitpattern)) { /* warning or error */
1621
snprintf(warn_string, 99, "not allowed in %s mode (\\pdfpoutput = %d)",
1622
m, (int) pdf_output);
1624
pdf_error(s, warn_string);
1626
pdf_warning(s, warn_string, true, true);
1628
ensure_output_state(pdf, ST_HEADER_WRITTEN);
1631
/**********************************************************************/
1633
void set_job_id(PDF pdf, int year, int month, int day, int time)
1635
char *name_string, *format_string, *s;
1639
if (pdf->job_id_string != NULL)
1642
name_string = makecstring(job_name);
1643
format_string = makecstring(format_ident);
1644
make_pdftex_banner();
1645
slen = SMALL_BUF_SIZE +
1646
strlen(name_string) + strlen(format_string) + strlen(pdftex_banner);
1647
s = xtalloc(slen, char);
1648
/* The Web2c version string starts with a space. */
1649
i = snprintf(s, slen,
1650
"%.4d/%.2d/%.2d %.2d:%.2d %s %s %s",
1651
year, month, day, time / 60, time % 60,
1652
name_string, format_string, pdftex_banner);
1653
check_nprintf(i, slen);
1654
pdf->job_id_string = xstrdup(s);
1657
xfree(format_string);
1658
} char *get_resname_prefix(PDF pdf)
1661
/* static char name_str[] = */
1662
/* "!\"$&'*+,-.0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\" */
1663
/* "^_`abcdefghijklmnopqrstuvwxyz|~"; */
1664
static char name_str[] =
1665
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1666
static char prefix[7]; /* make a tag of 6 chars long */
1669
size_t base = strlen(name_str);
1670
crc = crc32(0L, Z_NULL, 0);
1671
crc = crc32(crc, (Bytef *) pdf->job_id_string, strlen(pdf->job_id_string));
1672
for (i = 0; i < 6; i++) {
1673
prefix[i] = name_str[crc % base];
1680
#define mag int_par(mag_code)
1682
#define pdf_xform_attr equiv(pdf_xform_attr_loc)
1683
#define pdf_xform_resources equiv(pdf_xform_resources_loc)
1685
void pdf_begin_page(PDF pdf, boolean shipping_page)
1687
scaled form_margin = one_bp;
1688
ensure_output_state(pdf, ST_HEADER_WRITTEN);
1689
init_pdf_pagecalculations(pdf);
1691
if (pdf->resources == NULL)
1692
pdf->resources = xmalloc(sizeof(pdf_resource_struct));
1693
reset_resource_lists(pdf->resources);
1694
pdf->resources->last_resources = pdf_new_objnum(pdf);
1696
if (shipping_page) {
1697
pdf->last_page = get_obj(pdf, obj_type_page, total_pages + 1, 0);
1698
set_obj_aux(pdf, pdf->last_page, 1); /* mark that this page has been created */
1699
pdf_new_dict(pdf, obj_type_pagestream, 0, 0);
1700
pdf->last_stream = pdf->obj_ptr;
1701
pdf->last_thread = null;
1703
pdf_begin_dict(pdf, pdf_cur_form, 0);
1704
pdf->last_stream = pdf_cur_form;
1706
/* Write out Form stream header */
1707
pdf_puts(pdf, "/Type /XObject\n");
1708
pdf_puts(pdf, "/Subtype /Form\n");
1709
if (pdf_xform_attr != null)
1710
pdf_print_toks_ln(pdf, pdf_xform_attr);
1711
if (obj_xform_attr(pdf, pdf_cur_form) != null) {
1712
pdf_print_toks_ln(pdf, obj_xform_attr(pdf, pdf_cur_form));
1713
delete_token_ref(obj_xform_attr(pdf, pdf_cur_form));
1714
set_obj_xform_attr(pdf, pdf_cur_form, null);
1716
pdf_puts(pdf, "/BBox [");
1717
pdf_print_bp(pdf, -form_margin);
1719
pdf_print_bp(pdf, -form_margin);
1721
pdf_print_bp(pdf, cur_page_size.h + form_margin);
1723
pdf_print_bp(pdf, cur_page_size.v + form_margin);
1724
pdf_puts(pdf, "]\n");
1725
pdf_puts(pdf, "/FormType 1\n");
1726
pdf_puts(pdf, "/Matrix [1 0 0 1 0 0]\n");
1727
pdf_indirect_ln(pdf, "Resources", pdf->resources->last_resources);
1729
/* Start stream of page/form contents */
1730
pdf_begin_stream(pdf);
1731
if (shipping_page) {
1732
/* Adjust transformation matrix for the magnification ratio */
1734
pdf_print_real(pdf, mag, 3);
1735
pdf_puts(pdf, " 0 0 ");
1736
pdf_print_real(pdf, mag, 3);
1737
pdf_puts(pdf, " 0 0 cm\n");
1740
pdf_shipout_begin(shipping_page);
1743
pdf_out_colorstack_startpage(pdf);
1746
#define pdf_page_attr equiv(pdf_page_attr_loc)
1747
#define pdf_page_resources equiv(pdf_page_resources_loc)
1749
void pdf_end_page(PDF pdf, boolean shipping_page)
1752
pdf_resource_struct *res_p = pdf->resources;
1753
pdf_resource_struct local_resources;
1754
pdf_object_list *ol;
1755
scaledpos save_cur_page_size; /* to save |cur_page_size| during flushing pending forms */
1758
/* Finish stream of page/form contents */
1759
pdf_goto_pagemode(pdf);
1760
pdf_shipout_end(shipping_page);
1761
pdf_end_stream(pdf);
1763
if (shipping_page) {
1764
/* Write out page object */
1766
pdf_begin_dict(pdf, pdf->last_page, 1);
1767
pdf->last_pages = pdf_do_page_divert(pdf, pdf->last_page, 0);
1768
pdf_puts(pdf, "/Type /Page\n");
1769
pdf_indirect_ln(pdf, "Contents", pdf->last_stream);
1770
pdf_indirect_ln(pdf, "Resources", res_p->last_resources);
1771
pdf_puts(pdf, "/MediaBox [0 0 ");
1772
pdf_print_mag_bp(pdf, cur_page_size.h);
1774
pdf_print_mag_bp(pdf, cur_page_size.v);
1775
pdf_puts(pdf, "]\n");
1776
if (pdf_page_attr != null)
1777
pdf_print_toks_ln(pdf, pdf_page_attr);
1778
pdf_indirect_ln(pdf, "Parent", pdf->last_pages);
1779
if (pdf->img_page_group_val > 0) {
1780
pdf_printf(pdf, "/Group %d 0 R\n", pdf->img_page_group_val);
1781
pdf->img_page_group_val = 0;
1783
/* Generate array of annotations or beads in page */
1784
if ((res_p->annot_list != NULL)
1785
|| (res_p->link_list != NULL)) {
1786
pdf_puts(pdf, "/Annots [ ");
1787
ol = res_p->annot_list;
1788
while (ol != NULL) {
1790
pdf_print_int(pdf, ol->info);
1792
pdf_print_int(pdf, (-ol->info));
1793
pdf_puts(pdf, " 0 R ");
1796
ol = res_p->link_list;
1797
while (ol != NULL) {
1798
pdf_print_int(pdf, ol->info);
1799
pdf_puts(pdf, " 0 R ");
1802
pdf_puts(pdf, "]\n");
1804
print_beads_list(pdf);
1808
/* Write out resource lists */
1809
/* Write out pending raw objects */
1810
if ((ol = res_p->obj_list) != NULL) {
1811
while (ol != NULL) {
1812
if (!is_obj_written(pdf, ol->info))
1813
pdf_write_obj(pdf, ol->info);
1818
/* Write out pending forms */
1819
/* When flushing pending forms we need to save and restore resource lists
1820
(|font_list|, |pdf_obj_list|, |pdf_xform_list| and |pdf_ximage_list|),
1821
which are also used by page shipping.
1822
Saving and restoring |cur_page_size| is needed for proper
1823
writing out pending PDF marks. */
1824
if ((ol = res_p->xform_list) != NULL) {
1825
while (ol != NULL) {
1826
if (!is_obj_written(pdf, ol->info)) {
1827
pdf_cur_form = ol->info;
1828
save_cur_page_size = cur_page_size;
1829
pdf->resources = &local_resources;
1830
ship_out(pdf, obj_xform_box(pdf, pdf_cur_form), false);
1831
cur_page_size = save_cur_page_size;
1832
/* Restore resource lists */
1833
pdf->resources = res_p;
1839
/* Write out pending images */
1840
if ((ol = res_p->ximage_list) != NULL) {
1841
while (ol != NULL) {
1842
if (!is_obj_written(pdf, ol->info))
1843
pdf_write_image(pdf, ol->info);
1848
if (shipping_page) {
1849
/* Write out pending PDF marks */
1850
/* Write out PDF annotations */
1851
if ((ol = res_p->annot_list) != NULL) {
1852
while (ol != NULL) {
1854
j = obj_annot_ptr(pdf, ol->info); /* |j| points to |pdf_annot_node| */
1855
pdf_begin_dict(pdf, ol->info, 1);
1856
pdf_puts(pdf, "/Type /Annot\n");
1857
pdf_print_toks_ln(pdf, pdf_annot_data(j));
1858
pdf_rectangle(pdf, j);
1865
/* Write out PDF link annotations */
1866
if ((ol = res_p->link_list) != NULL) {
1867
while (ol != NULL) {
1868
j = obj_annot_ptr(pdf, ol->info);
1869
pdf_begin_dict(pdf, ol->info, 1);
1870
pdf_puts(pdf, "/Type /Annot\n");
1871
if (pdf_action_type(pdf_link_action(j)) != pdf_action_user)
1872
pdf_puts(pdf, "/Subtype /Link\n");
1873
if (pdf_link_attr(j) != null)
1874
pdf_print_toks_ln(pdf, pdf_link_attr(j));
1875
pdf_rectangle(pdf, j);
1876
if (pdf_action_type(pdf_link_action(j)) != pdf_action_user)
1877
pdf_puts(pdf, "/A ");
1878
write_action(pdf, pdf_link_action(j));
1882
/* Flush |pdf_start_link_node|'s created by |append_link| */
1883
ol = res_p->link_list;
1884
while (ol != NULL) {
1885
j = obj_annot_ptr(pdf, ol->info);
1886
/* nodes with |subtype = pdf_link_data_node| were created by |append_link| and
1887
must be flushed here, as they are not linked in any list */
1888
if (subtype(j) == pdf_link_data_node)
1894
/* Write out PDF mark destinations */
1895
write_out_pdf_mark_destinations(pdf);
1896
/* Write out PDF bead rectangle specifications */
1897
print_bead_rectangles(pdf);
1900
/* Write out resources dictionary */
1901
pdf_begin_dict(pdf, res_p->last_resources, 1);
1902
/* Print additional resources */
1903
if (shipping_page) {
1904
if (pdf_page_resources != null)
1905
pdf_print_toks_ln(pdf, pdf_page_resources);
1907
if (pdf_xform_resources != null)
1908
pdf_print_toks_ln(pdf, pdf_xform_resources);
1909
if (obj_xform_resources(pdf, pdf_cur_form) != null) {
1910
pdf_print_toks_ln(pdf, obj_xform_resources(pdf, pdf_cur_form));
1911
delete_token_ref(obj_xform_resources(pdf, pdf_cur_form));
1912
set_obj_xform_resources(pdf, pdf_cur_form, null);
1916
/* Generate font resources */
1917
if ((ol = res_p->font_list) != NULL) {
1918
pdf_puts(pdf, "/Font << ");
1919
while (ol != NULL) {
1920
pdf_puts(pdf, "/F");
1922
pdf_print_int(pdf, ff);
1923
pdf_print_resname_prefix(pdf);
1925
pdf_print_int(pdf, pdf_font_num(ff));
1926
pdf_puts(pdf, " 0 R ");
1929
pdf_puts(pdf, ">>\n");
1930
res_p->text_procset = true;
1933
/* Generate XObject resources */
1934
if ((res_p->xform_list != NULL)
1935
|| (res_p->ximage_list != NULL)) {
1936
pdf_puts(pdf, "/XObject << ");
1937
if ((ol = res_p->xform_list) != NULL) {
1938
while (ol != NULL) {
1939
pdf_printf(pdf, "/Fm");
1940
pdf_print_int(pdf, obj_info(pdf, ol->info));
1941
pdf_print_resname_prefix(pdf);
1943
pdf_print_int(pdf, ol->info);
1944
pdf_puts(pdf, " 0 R ");
1948
if ((ol = res_p->ximage_list) != NULL) {
1949
while (ol != null) {
1950
pdf_puts(pdf, "/Im");
1951
pdf_print_int(pdf, obj_data_ptr(pdf, ol->info));
1952
pdf_print_resname_prefix(pdf);
1954
pdf_print_int(pdf, ol->info);
1955
pdf_puts(pdf, " 0 R ");
1956
update_image_procset(obj_data_ptr(pdf, ol->info));
1960
pdf_puts(pdf, ">>\n");
1963
/* Generate ProcSet */
1964
pdf_puts(pdf, "/ProcSet [ /PDF");
1965
if (res_p->text_procset)
1966
pdf_puts(pdf, " /Text");
1967
if (check_image_b(res_p->image_procset))
1968
pdf_puts(pdf, " /ImageB");
1969
if (check_image_c(res_p->image_procset))
1970
pdf_puts(pdf, " /ImageC");
1971
if (check_image_i(res_p->image_procset))
1972
pdf_puts(pdf, " /ImageI");
1973
pdf_puts(pdf, " ]\n");
1977
/* In the end of shipping out a page we reset all the lists holding objects
1978
have been created during the page shipping. */
1980
flush_resource_lists(pdf);
1983
/**********************************************************************/
1985
/* Finishing the PDF output file. */
1987
#define pdf_gen_tounicode int_par(pdf_gen_tounicode_code)
1990
Destinations that have been referenced but don't exists have
1991
|obj_dest_ptr=null|. Leaving them undefined might cause troubles for
1992
PDF browsers, so we need to fix them; they point to the last page.
1995
static void check_nonexisting_destinations(PDF pdf)
1998
for (k = pdf->head_tab[obj_type_dest]; k != 0; k = obj_link(pdf, k)) {
1999
if (obj_dest_ptr(pdf, k) == null) {
2000
pdf_warning("dest", NULL, false, false);
2001
if (obj_info(pdf, k) < 0) {
2003
print(-obj_info(pdf, k));
2007
print_int(obj_info(pdf, k));
2010
(" has been referenced but does not exist, replaced by a fixed one");
2013
pdf_begin_obj(pdf, k, 1);
2015
pdf_print_int(pdf, pdf->last_page);
2016
pdf_puts(pdf, " 0 R /Fit]\n");
2022
static void check_nonexisting_pages(PDF pdf)
2024
struct avl_traverser t;
2026
struct avl_table *page_tree = pdf->obj_tree[obj_type_page];
2027
avl_t_init(&t, page_tree);
2028
/* search from the end backward until the last real page is found */
2029
for (p = avl_t_last(&t, page_tree);
2030
p != NULL && obj_aux(pdf, p->objptr) == 0; p = avl_t_prev(&t)) {
2031
pdf_warning("dest", "Page ", false, false);
2032
print_int(obj_info(pdf, p->objptr));
2033
tprint(" has been referenced but does not exist!");
2040
If the same keys in a dictionary are given several times, then it is not
2041
defined which value is choosen by an application. Therefore the keys
2042
|/Producer| and |/Creator| are only set if the token list
2043
|pdf_info_toks| converted to a string does not contain these key strings.
2046
boolean substr_of_str(char *s, char *t)
2048
if (strstr(t, s) == NULL)
2053
void pdf_print_info(PDF pdf, int luatex_version, str_number luatex_revision)
2054
{ /* print info object */
2055
boolean creator_given, producer_given, creationdate_given, moddate_given,
2059
pdf_new_dict(pdf, obj_type_others, 0, 3); /* keep Info readable unless explicitely forced */
2060
creator_given = false;
2061
producer_given = false;
2062
creationdate_given = false;
2063
moddate_given = false;
2064
trapped_given = false;
2065
if (pdf_info_toks != 0) {
2066
s = tokenlist_to_cstring(pdf_info_toks, true, &len);
2067
creator_given = substr_of_str("/Creator", s);
2068
producer_given = substr_of_str("/Producer", s);
2069
creationdate_given = substr_of_str("/CreationDate", s);
2070
moddate_given = substr_of_str("/ModDate", s);
2071
trapped_given = substr_of_str("/Trapped", s);
2073
if (!producer_given) {
2074
/* Print the Producer key */
2075
pdf_puts(pdf, "/Producer (LuaTeX-");
2076
pdf_print_int(pdf, luatex_version / 100);
2078
pdf_print_int(pdf, luatex_version % 100);
2080
pdf_print(pdf, luatex_revision);
2081
pdf_puts(pdf, ")\n");
2084
if (pdf_info_toks != null) {
2090
delete_token_ref(pdf_info_toks);
2091
pdf_info_toks = null;
2094
pdf_str_entry_ln(pdf, "Creator", "TeX");
2095
if (!creationdate_given) {
2096
print_creation_date(pdf);
2098
if (!moddate_given) {
2099
print_mod_date(pdf);
2101
if (!trapped_given) {
2102
pdf_puts(pdf, "/Trapped /False\n");
2104
pdf_str_entry_ln(pdf, "PTEX.Fullbanner", pdftex_banner);
2108
void build_free_object_list(PDF pdf)
2112
set_obj_fresh(pdf, l); /* null object at begin of list of free objects */
2113
for (k = 1; k <= pdf->sys_obj_ptr; k++) {
2114
if (!is_obj_written(pdf, k)) {
2115
set_obj_link(pdf, l, k);
2119
set_obj_link(pdf, l, 0);
2122
/**********************************************************************/
2125
Now the finish of PDF output file. At this moment all Page objects
2126
are already written completely to PDF output file.
2129
void finish_pdf_file(PDF pdf, int luatex_version, str_number luatex_revision)
2133
int root, outlines, threads, names_tree;
2134
int xref_offset_width;
2135
int callback_id = callback_defined(stop_run_callback);
2137
if (total_pages == 0) {
2138
if (callback_id == 0) {
2139
tprint_nl("No pages of output.");
2140
} else if (callback_id > 0) {
2141
res = run_callback(callback_id, "->");
2146
if (pdf->draftmode == 0) {
2147
pdf_flush(pdf); /* to make sure that the output file name has been already created */
2148
flush_jbig2_page0_objects(pdf); /* flush page 0 objects from JBIG2 images, if any */
2150
check_nonexisting_pages(pdf);
2151
check_nonexisting_destinations(pdf);
2153
/* Output fonts definition */
2154
for (k = 1; k <= max_font_id(); k++) {
2155
if (font_used(k) && (pdf_font_num(k) < 0)) {
2156
i = -pdf_font_num(k);
2157
assert(pdf_font_num(i) > 0);
2158
for (j = font_bc(k); j <= font_ec(k); j++)
2159
if (quick_char_exists(k, j) && pdf_char_marked(k, j))
2160
pdf_mark_char(i, j);
2161
if ((pdf_font_attr(i) == 0) && (pdf_font_attr(k) != 0)) {
2162
set_pdf_font_attr(i, pdf_font_attr(k));
2163
} else if ((pdf_font_attr(k) == 0)
2164
&& (pdf_font_attr(i) != 0)) {
2165
set_pdf_font_attr(k, pdf_font_attr(i));
2166
} else if ((pdf_font_attr(i) != 0)
2167
&& (pdf_font_attr(k) != 0)
2170
(pdf_font_attr(i), pdf_font_attr(k)))) {
2171
pdf_warning("\\pdffontattr", "fonts ", false, false);
2172
print_font_identifier(i);
2174
print_font_identifier(k);
2176
(" have conflicting attributes; I will ignore the attributes assigned to ");
2177
print_font_identifier(i);
2183
pdf->gen_tounicode = pdf_gen_tounicode;
2184
k = pdf->head_tab[obj_type_font];
2186
f = obj_info(pdf, k);
2187
assert(pdf_font_num(f) > 0);
2188
do_pdf_font(pdf, k, f);
2189
k = obj_link(pdf, k);
2191
write_fontstuff(pdf);
2193
pdf->last_pages = output_pages_tree(pdf);
2194
/* Output outlines */
2195
outlines = print_outlines(pdf);
2197
/* Output name tree */
2198
/* The name tree is very similiar to Pages tree so its construction should be
2199
certain from Pages tree construction. For intermediate node |obj_info| will be
2200
the first name and |obj_link| will be the last name in \.{\\Limits} array.
2201
Note that |pdf_dest_names_ptr| will be less than |obj_ptr|, so we test if
2202
|k < pdf_dest_names_ptr| then |k| is index of leaf in |dest_names|; else
2203
|k| will be index in |obj_tab| of some intermediate node.
2205
names_tree = output_name_tree(pdf);
2207
/* Output article threads */
2208
if (pdf->head_tab[obj_type_thread] != 0) {
2209
pdf_new_obj(pdf, obj_type_others, 0, 1);
2210
threads = pdf->obj_ptr;
2212
k = pdf->head_tab[obj_type_thread];
2214
pdf_print_int(pdf, k);
2215
pdf_puts(pdf, " 0 R ");
2216
k = obj_link(pdf, k);
2218
pdf_remove_last_space(pdf);
2219
pdf_puts(pdf, "]\n");
2221
k = pdf->head_tab[obj_type_thread];
2224
k = obj_link(pdf, k);
2230
/* Output the catalog object */
2231
pdf_new_dict(pdf, obj_type_others, 0, 1);
2232
root = pdf->obj_ptr;
2233
pdf_puts(pdf, "/Type /Catalog\n");
2234
pdf_indirect_ln(pdf, "Pages", pdf->last_pages);
2236
pdf_indirect_ln(pdf, "Threads", threads);
2238
pdf_indirect_ln(pdf, "Outlines", outlines);
2239
if (names_tree != 0)
2240
pdf_indirect_ln(pdf, "Names", names_tree);
2241
if (pdf_catalog_toks != null) {
2242
pdf_print_toks_ln(pdf, pdf_catalog_toks);
2243
delete_token_ref(pdf_catalog_toks);
2244
pdf_catalog_toks = null;
2246
if (pdf_catalog_openaction != 0)
2247
pdf_indirect_ln(pdf, "OpenAction", pdf_catalog_openaction);
2250
pdf_print_info(pdf, luatex_version, luatex_revision); /* last candidate for object stream */
2252
if (pdf->os_enable) {
2253
pdf_os_switch(pdf, true);
2254
pdf_os_write_objstream(pdf);
2256
pdf_os_switch(pdf, false);
2257
/* Output the cross-reference stream dictionary */
2258
pdf_new_dict(pdf, obj_type_others, 0, 0);
2259
if ((obj_offset(pdf, pdf->sys_obj_ptr) / 256) > 16777215)
2260
xref_offset_width = 5;
2261
else if (obj_offset(pdf, pdf->sys_obj_ptr) > 16777215)
2262
xref_offset_width = 4;
2263
else if (obj_offset(pdf, pdf->sys_obj_ptr) > 65535)
2264
xref_offset_width = 3;
2266
xref_offset_width = 2;
2267
/* Build a linked list of free objects */
2268
build_free_object_list(pdf);
2269
pdf_puts(pdf, "/Type /XRef\n");
2270
pdf_puts(pdf, "/Index [0 ");
2271
pdf_print_int(pdf, pdf->obj_ptr + 1);
2272
pdf_puts(pdf, "]\n");
2273
pdf_int_entry_ln(pdf, "Size", pdf->obj_ptr + 1);
2274
pdf_puts(pdf, "/W [1 ");
2275
pdf_print_int(pdf, xref_offset_width);
2276
pdf_puts(pdf, " 1]\n");
2277
pdf_indirect_ln(pdf, "Root", root);
2278
pdf_indirect_ln(pdf, "Info", pdf->obj_ptr - 1);
2279
if (pdf_trailer_toks != null) {
2280
pdf_print_toks_ln(pdf, pdf_trailer_toks);
2281
delete_token_ref(pdf_trailer_toks);
2282
pdf_trailer_toks = null;
2284
print_ID(pdf, pdf->file_name);
2286
pdf_begin_stream(pdf);
2287
for (k = 0; k <= pdf->sys_obj_ptr; k++) {
2288
if (!is_obj_written(pdf, k)) { /* a free object */
2290
pdf_out_bytes(pdf, obj_link(pdf, k), xref_offset_width);
2292
} else if (obj_os_idx(pdf, k) == -1) { /* object not in object stream */
2294
pdf_out_bytes(pdf, obj_offset(pdf, k),
2297
} else { /* object in object stream */
2299
pdf_out_bytes(pdf, obj_offset(pdf, k),
2301
pdf_out(pdf, obj_os_idx(pdf, k));
2304
pdf_end_stream(pdf);
2305
/* TODO: generate a debug version of the crossref */
2309
/* Output the |obj_tab| */
2310
/* Build a linked list of free objects */
2311
build_free_object_list(pdf);
2313
pdf_save_offset(pdf);
2314
pdf_puts(pdf, "xref\n");
2315
pdf_puts(pdf, "0 ");
2316
pdf_print_int_ln(pdf, pdf->obj_ptr + 1);
2317
pdf_print_fw_int(pdf, obj_link(pdf, 0), 10);
2318
pdf_puts(pdf, " 65535 f \n");
2319
for (k = 1; k <= pdf->obj_ptr; k++) {
2320
if (!is_obj_written(pdf, k)) {
2321
pdf_print_fw_int(pdf, obj_link(pdf, k), 10);
2322
pdf_puts(pdf, " 00000 f \n");
2324
pdf_print_fw_int(pdf, obj_offset(pdf, k), 10);
2325
pdf_puts(pdf, " 00000 n \n");
2331
/* Output the trailer */
2332
if (!pdf->os_enable) {
2333
pdf_puts(pdf, "trailer\n");
2334
pdf_puts(pdf, "<< ");
2335
pdf_int_entry_ln(pdf, "Size", pdf->sys_obj_ptr + 1);
2336
pdf_indirect_ln(pdf, "Root", root);
2337
pdf_indirect_ln(pdf, "Info", pdf->sys_obj_ptr);
2338
if (pdf_trailer_toks != null) {
2339
pdf_print_toks_ln(pdf, pdf_trailer_toks);
2340
delete_token_ref(pdf_trailer_toks);
2341
pdf_trailer_toks = null;
2343
print_ID(pdf, pdf->file_name);
2344
pdf_puts(pdf, " >>\n");
2346
pdf_puts(pdf, "startxref\n");
2348
pdf_print_int_ln(pdf, obj_offset(pdf, pdf->sys_obj_ptr));
2350
pdf_print_int_ln(pdf, pdf_saved_offset(pdf));
2351
pdf_puts(pdf, "%%EOF\n");
2354
if (callback_id == 0) {
2355
tprint_nl("Output written on ");
2356
tprint(pdf->file_name);
2358
print_int(total_pages);
2360
if (total_pages != 1)
2363
print_int(pdf_offset(pdf));
2365
} else if (callback_id > 0) {
2366
res = run_callback(callback_id, "->");
2370
if (pdf->draftmode == 0)
2371
close_file(pdf->file);
2374
"\\pdfdraftmode enabled, not changing output pdf",
2378
if (callback_id == 0) {
2381
"\nPDF statistics: %d PDF objects out of %d (max. %d)\n",
2382
(int) pdf->obj_ptr, (int) pdf->obj_tab_size,
2383
(int) sup_obj_tab_size);
2384
if (pdf->os_cntr > 0) {
2386
" %d compressed objects within %d object stream%s\n",
2387
(int) ((pdf->os_cntr - 1) * pdf_os_max_objs +
2388
pdf->os_idx + 1), (int) pdf->os_cntr,
2389
(pdf->os_cntr > 1 ? "s" : ""));
2391
fprintf(log_file, " %d named destinations out of %d (max. %d)\n",
2392
(int) pdf->dest_names_ptr, (int) pdf->dest_names_size,
2393
(int) sup_dest_names_size);
2395
" %d words of extra memory for PDF output out of %d (max. %d)\n",
2396
(int) pdf->mem_ptr, (int) pdf->mem_size,
2397
(int) sup_pdf_mem_size);
2402
void scan_pdfcatalog(PDF pdf)
2405
scan_pdf_ext_toks();
2406
pdf_catalog_toks = concat_tokens(pdf_catalog_toks, def_ref);
2407
if (scan_keyword("openaction")) {
2408
if (pdf_catalog_openaction != 0) {
2409
pdf_error("ext1", "duplicate of openaction");
2411
check_o_mode(pdf, "\\pdfcatalog", 1 << OMODE_PDF, true);
2412
p = scan_action(pdf);
2413
pdf_new_obj(pdf, obj_type_others, 0, 1);
2414
pdf_catalog_openaction = pdf->obj_ptr;
2415
write_action(pdf, p);
2417
delete_action_ref(p);