beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / pdf / pdfgen.w
blob5882d0b6f72b5407261bf9d7ceda09e0e3cf428e
1 % pdfgen.w
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/>.
20 @ @c
21 #include "ptexlib.h"
23 @ @c
24 #include <kpathsea/c-dir.h>
25 #include <kpathsea/c-ctype.h>
26 #include "lua/luatex-api.h"
27 #include "md5.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
40 int output_mode_used;
41 int output_mode_option;
42 int output_mode_value;
43 int draft_mode_option;
44 int draft_mode_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 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)
59 strbuf_s *b;
60 b = xtalloc(1, strbuf_s);
61 b->size = size;
62 b->limit = limit;
63 if (size > 0)
64 b->p = b->data = xtalloc(b->size, unsigned char);
65 else
66 b->p = b->data = NULL; /* for other alloc */
67 return b;
70 @ Check that |n| bytes more fit into buffer; increase it if required.
73 static void strbuf_room(strbuf_s * b, size_t n)
75 unsigned int a;
76 size_t l = (size_t) (b->p - b->data);
77 if (n > b->limit - l)
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)
82 b->size = n + l;
83 else if (b->size < b->limit - a)
84 b->size = b->size + a;
85 else
86 b->size = b->limit;
87 b->data = xreallocarray(b->data, unsigned char, (unsigned) b->size);
88 b->p = b->data + l;
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)
114 strbuf_room(b, 1);
115 *b->p++ = c;
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));
124 strbuf_seek(b, 0);
127 @ Free all dynamically allocated buffer structures.
130 void strbuf_free(strbuf_s * b)
132 xfree(b->data);
133 xfree(b);
136 @ |init_pdf_struct()| is called early, only once, from maincontrol.w
139 PDF init_pdf_struct(PDF pdf)
141 os_struct *os;
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);
156 os->cur_objstm = 0;
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.
179 pdf->mem_ptr = 1;
181 pdf->pstruct = NULL;
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;
195 pdf->gamma = 65536;
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;
201 pdf->draftmode = 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();
214 return pdf;
217 @ We use |pdf_get_mem| to allocate memory in |mem|.
220 int pdf_get_mem(PDF pdf, int s)
222 int a;
223 int ret;
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;
232 } else {
233 pdf->mem_size = sup_pdf_mem_size;
235 pdf->mem = xreallocarray(pdf->mem, int, (unsigned) pdf->mem_size);
237 ret = pdf->mem_ptr;
238 pdf->mem_ptr = pdf->mem_ptr + s;
239 return ret;
242 @ there are defined in |luatex-api.h|, so we need |luatex-api.c|:
245 output_mode get_o_mode(void)
247 output_mode o_mode;
248 if (int_par(output_mode_code) > 0) {
249 o_mode = OMODE_PDF;
250 } else
251 o_mode = OMODE_DVI;
252 return o_mode;
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}
269 header is written.
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 };
277 char msg[256];
278 (void) snprintf(msg, 255, "LuaTeX error (illegal pdfminorversion %d)", (int) pdf_minor_version);
279 tex_error(msg, hlp);
280 pdf->minor_version = 4;
281 } else {
282 pdf->minor_version = pdf_minor_version;
284 } else {
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;
297 @ @c
298 #define ZIP_BUF_SIZE 32768
300 #define check_err(f, fn) \
301 if (f != Z_OK) \
302 formatted_error("pdf backend","zlib %s() failed (error code %d)", fn, f)
304 @ @c
305 static void write_zip(PDF pdf)
307 int flush, err = Z_OK;
308 uInt zip_len;
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) {
313 if (s == NULL) {
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);
320 } else
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);
327 while (true) {
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;
335 if (finish) {
336 if (err == Z_STREAM_END) {
337 xfflush(pdf->file);
338 pdf->zip_write_state = NO_ZIP;
339 break;
341 flush = Z_FINISH;
342 } else {
343 if (s->avail_in == 0)
344 break;
345 flush = Z_NO_FLUSH;
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;
354 @ @c
355 void zip_free(PDF pdf)
357 if (pdf->zipbuf != NULL) {
358 check_err(deflateEnd(pdf->c_stream), "deflateEnd");
359 xfree(pdf->zipbuf);
361 xfree(pdf->c_stream);
364 @ @c
365 static void write_nozip(PDF pdf)
367 strbuf_s *buf = pdf->buf;
368 size_t l = strbuf_offset(buf);
369 if (l == 0)
370 return;
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) {
387 case PDFOUT_BUF:
388 if (pdf->draftmode == 0) {
389 switch (pdf->zip_write_state) {
390 case NO_ZIP:
391 write_nozip(pdf);
392 break;
393 case ZIP_WRITING:
394 case ZIP_FINISH:
395 write_zip(pdf);
396 break;
397 default:
398 normal_error("pdf backend", "bad zip state");
400 } else
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)");
405 break;
406 case OBJSTM_BUF:
407 break;
408 default:
409 normal_error("pdf backend", "bad buffer state");
413 @ @c
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 */
419 else
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);
433 else
434 pdf_buffer_select(pdf, PDFOUT_BUF);
435 switch (os->curbuf) {
436 case PDFOUT_BUF:
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 */
439 break;
440 case OBJSTM_BUF:
441 if (os->cur_objstm == 0) {
442 os->cur_objstm =
443 (unsigned int) pdf_create_obj(pdf, obj_type_objstm, 0);
444 os->idx = 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;
452 break;
453 default:
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)
468 return;
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);
474 else
475 pdf_flush(pdf);
476 } else {
477 strbuf_room(buf, (size_t) n);
481 @ @c
482 void pdf_out_block(PDF pdf, const char *s, size_t n)
484 size_t l;
485 strbuf_s *buf = pdf->buf;
486 do {
487 l = n;
488 if (l > buf->size)
489 l = buf->size;
490 pdf_room(pdf, (int) l);
491 (void) memcpy(buf->p, s, l);
492 buf->p += l;
493 s += l;
494 n -= l;
495 } while (n > 0);
498 @ @c
499 __attribute__ ((format(printf, 2, 3)))
500 void pdf_printf(PDF pdf, const char *fmt, ...)
502 va_list args;
503 va_start(args, 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);
509 va_end(args);
512 @ print out a string to PDF buffer
515 void pdf_print(PDF pdf, str_number s)
517 const char *ss;
518 size_t l;
519 if (s >= STRING_OFFSET) {
520 ss = (const char *) str_string(s);
521 l = str_length(s);
522 pdf_out_block(pdf, ss, l);
523 } else {
524 pdf_out(pdf, s);
528 @ print out a integer to PDF buffer
531 void pdf_print_int(PDF pdf, longinteger n)
533 char s[24];
534 int w;
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);
540 @ @c
542 void print_pdffloat(PDF pdf, pdffloat f)
544 char a[24];
545 int e = f.e, i, l;
546 int64_t m = f.m;
547 if (m < 0) {
548 pdf_out(pdf, '-');
549 m *= -1;
551 l = m / ten_pow[e];
552 pdf_print_int(pdf, l);
553 l = m % ten_pow[e];
554 if (l != 0) {
555 pdf_out(pdf, '.');
556 snprintf(a, 23, "%d", l + ten_pow[e]);
557 for (i = e; i > 0; i--) {
558 if (a[i] != '0')
559 break;
560 a[i] = '\0';
562 pdf_puts(pdf, (a + 1));
567 void print_pdffloat(PDF pdf, pdffloat f)
569 int64_t m = f.m;
570 if (m == 0) {
571 pdf_out(pdf, '0');
572 } else {
573 int e = f.e;
574 if (e == 0) {
575 /* division by ten_pow[0] == 1 */
576 if (m == 1) {
577 pdf_out(pdf, '1');
578 } else {
579 char a[24];
580 snprintf(a, 23, "%" LONGINTEGER_PRI "i", m);
581 pdf_puts(pdf, a);
583 } else {
584 int t = ten_pow[e] ;
585 if (t == m) {
586 pdf_out(pdf, '1');
587 } else {
588 int i, l, w;
589 char a[24];
590 if (m < 0) {
591 pdf_out(pdf, '-');
592 m *= -1;
594 l = m / t;
595 w = snprintf(a, 23, "%i", l);
596 pdf_out_block(pdf, (const char *) a, (size_t) w);
597 l = m % t;
598 if (l != 0) {
599 pdf_out(pdf, '.');
600 snprintf(a, 23, "%d", l + t);
601 for (i = e; i > 0; i--) {
602 if (a[i] != '0')
603 break;
604 a[i] = '\0';
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 */
620 if (l < 0) {
621 pdf_puts(pdf, "()");
622 return;
624 /* the next is not really safe, the string could be "(a)xx(b)" */
625 if ((s[0] == '(') && (s[l] == ')')) {
626 pdf_puts(pdf, s);
627 return;
629 if ((s[0] != '<') || (s[l] != '>') || odd((l + 1))) {
630 pdf_out(pdf, '(');
631 pdf_puts(pdf, s);
632 pdf_out(pdf, ')');
633 return;
635 s++;
636 while (is_hex_char((unsigned char)*s))
637 s++;
638 if (s != orig + l) {
639 pdf_out(pdf, '(');
640 pdf_puts(pdf, orig);
641 pdf_out(pdf, ')');
642 return;
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);
654 pdf_flush(pdf);
655 if (pdf->stream_deflate) {
656 pdf->zip_write_state = ZIP_WRITING;
658 pdf->stream_writing = true;
659 pdf->stream_length = 0;
660 pdf->last_byte = 0;
663 @ end a stream
666 void pdf_end_stream(PDF pdf)
668 os_struct *os = pdf->os;
669 switch (os->curbuf) {
670 case PDFOUT_BUF:
671 if (pdf->zip_write_state == ZIP_WRITING)
672 pdf->zip_write_state = ZIP_FINISH;
673 pdf_flush(pdf); /* sets pdf->last_byte */
674 break;
675 case OBJSTM_BUF:
676 normal_error("pdf backend", "bad buffer in end stream, case 1");
677 break;
678 default:
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
695 accurary.
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
711 int ten_pow[10] = {
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;
723 unsigned t, u, v;
724 if (x < 0) {
725 positive = !positive;
726 x = -(x);
728 if (n < 0) {
729 positive = !positive;
730 n = -(n);
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)
736 arith_error = true;
737 else
738 u = 0100000 * (u / d) + (v / d);
739 v = v % d;
740 if (2 * v >= d)
741 u++;
742 if (positive)
743 return (scaled) u;
744 else
745 return (-(scaled) u);
748 @ @c
749 void pdf_add_bp(PDF pdf, scaled s)
751 pdffloat a;
752 pdfstructure *p = pdf->pstruct;
753 a.m = i64round(s * p->k1);
754 a.e = pdf->decimal_digits;
755 if (pdf->cave > 0)
756 pdf_out(pdf, ' ');
757 print_pdffloat(pdf, a);
758 pdf->cave = 1;
761 @* handling page resources.
764 typedef struct {
765 int obj_type;
766 pdf_object_list *list;
767 } pr_entry;
769 @ @c
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;
774 (void) p;
775 if (a > b)
776 return 1;
777 if (a < b)
778 return -1;
779 return 0;
782 @ @c
783 void addto_page_resources(PDF pdf, pdf_obj_type t, int k)
785 pdf_resource_struct *re;
786 pr_entry *pr, tmp;
787 void **pp;
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");
795 tmp.obj_type = t;
796 pr = (pr_entry *) avl_find(re->resources_tree, &tmp);
797 if (pr == NULL) {
798 pr = xtalloc(1, pr_entry);
799 pr->obj_type = t;
800 pr->list = NULL;
801 pp = avl_probe(re->resources_tree, pr);
802 if (pp == NULL)
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);
807 item->link = NULL;
808 item->info = k;
809 pr->list = item;
810 if (obj_type(pdf, k) == (int)t)
811 set_obj_scheduled(pdf, k); /* k is an object number */
812 } else {
813 for (p = pr->list; p->info != k && p->link != NULL; p = p->link);
814 if (p->info != k) {
815 item = xtalloc(1, pdf_object_list);
816 item->link = NULL;
817 item->info = k;
818 p->link = item;
819 if (obj_type(pdf, k) == (int)t)
820 set_obj_scheduled(pdf, k);
825 @ @c
826 pdf_object_list *get_page_resources_list(PDF pdf, pdf_obj_type t)
828 pdf_resource_struct *re = pdf->page_resources;
829 pr_entry *pr, tmp;
830 if (re == NULL || re->resources_tree == NULL)
831 return NULL;
832 tmp.obj_type = t;
833 pr = (pr_entry *) avl_find(re->resources_tree, &tmp);
834 if (pr == NULL)
835 return NULL;
836 return pr->list;
839 @ @c
840 static void reset_page_resources(PDF pdf)
842 pdf_resource_struct *re = pdf->page_resources;
843 pr_entry *p;
844 struct avl_traverser t;
845 pdf_object_list *l1, *l2;
846 if (re == NULL || re->resources_tree == NULL)
847 return;
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) {
852 l2 = l1->link;
853 free(l1);
855 p->list = NULL; /* but the AVL tree remains */
860 @ @c
861 static void destroy_pg_res_tree(void *pa, void *param)
863 (void) param;
864 xfree(pa);
867 @ @c
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];
886 int k = 10;
887 do {
888 k--;
889 digits[k] = (unsigned char) ('0' + (n % 10));
890 n /= 10;
891 } while (k != 0);
892 if (n!=0)
893 /* the absolute value of $n$ is greater than 9999999999 */
894 normal_error("pdf backend", "offset exceeds 10 bytes, try enabling object compression.");
895 digits[10]='\0';
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)
903 int k;
904 unsigned char bytes[8]; /* digits in a number being output */
905 k = (int) w;
906 do {
907 k--;
908 bytes[k] = (unsigned char) (n % 256);
909 n /= 256;
910 } while (k != 0);
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);
920 pdf_out(pdf, '\n');
923 @ @c
924 void pdf_print_toks(PDF pdf, halfword p)
926 int len = 0;
927 char *s = tokenlist_to_cstring(p, true, &len);
928 if (len > 0) {
929 if (pdf->cave > 0)
930 pdf_out(pdf, ' ');
931 pdf_puts(pdf, s);
932 pdf->cave = 1;
934 xfree(s);
937 @ prints a rect spec
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);
956 pdf_end_array(pdf);
959 @ @c
960 static void init_pdf_outputparameters(PDF pdf)
962 int pk_mode;
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;
977 } else {
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);
992 xfree(s);
993 } else {
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)
1009 char *fn;
1010 if (pdf->file_name != NULL)
1011 return;
1012 if (job_name == 0)
1013 open_log_file();
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;
1022 @ @c
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);
1030 pdf_out(pdf, '%');
1031 pdf_out(pdf, 'P' + 128);
1032 pdf_out(pdf, 'T' + 128);
1033 pdf_out(pdf, 'E' + 128);
1034 pdf_out(pdf, 'X' + 128);
1035 pdf_out(pdf, '\n');
1038 @ @c
1039 void ensure_output_state(PDF pdf, output_state s)
1041 if (pdf->o_state < s) {
1042 if (s > ST_INITIAL)
1043 ensure_output_state(pdf, s - 1);
1044 switch (s - 1) {
1045 case ST_INITIAL:
1046 fix_o_mode();
1047 break;
1048 case ST_OMODE_FIX:
1049 switch (output_mode_used) {
1050 case OMODE_DVI:
1051 ensure_output_file_open(pdf, ".dvi");
1052 break;
1053 case OMODE_PDF:
1054 ensure_output_file_open(pdf, ".pdf");
1055 break;
1056 default:
1057 normal_error("pdf backend","weird output state");
1059 break;
1060 case ST_FILE_OPEN:
1061 switch (output_mode_used) {
1062 case OMODE_DVI:
1063 ensure_dvi_header_written(pdf);
1064 break;
1065 case OMODE_PDF:
1066 ensure_pdf_header_written(pdf);
1067 break;
1068 default:
1069 normal_error("pdf backend","weird output state");
1071 break;
1072 case ST_HEADER_WRITTEN:
1073 break;
1074 case ST_FILE_CLOSED:
1075 break;
1076 default:
1077 normal_error("pdf backend","weird output state");
1079 pdf->o_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 */
1098 return;
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);
1103 pdf_out(pdf, ' ');
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 */
1106 pdf_out(pdf, '\n');
1107 j = 0;
1108 } else {
1109 pdf_out(pdf, ' ');
1110 j++;
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);
1120 pdf_end_dict(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);
1127 pdf_end_obj(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, "<<");
1137 pdf->cave = 0;
1140 @ end a PDF dictionary
1143 void pdf_end_dict(PDF pdf)
1145 pdf_puts(pdf, ">>");
1146 pdf->cave = 0;
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)
1181 if (val == NULL)
1182 return;
1183 pdf_add_name(pdf, key);
1184 if (pdf->cave > 0)
1185 pdf_out(pdf, ' ');
1186 pdf->cave = 0;
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)
1204 if (pdf->cave > 0)
1205 pdf_out(pdf, ' ');
1206 pdf_puts(pdf, "null");
1207 pdf->cave = 1;
1210 void pdf_add_bool(PDF pdf, int i)
1212 if (pdf->cave > 0)
1213 pdf_out(pdf, ' ');
1214 if (i == 0)
1215 pdf_puts(pdf, "false");
1216 else
1217 pdf_puts(pdf, "true");
1218 pdf->cave = 1;
1221 void pdf_add_int(PDF pdf, int i)
1223 if (pdf->cave > 0)
1224 pdf_out(pdf, ' ');
1225 pdf_print_int(pdf, i);
1226 pdf->cave = 1;
1229 void pdf_add_longint(PDF pdf, longinteger n)
1231 if (pdf->cave > 0)
1232 pdf_out(pdf, ' ');
1233 pdf_print_int(pdf, n);
1234 pdf->cave = 1;
1237 void pdf_add_string(PDF pdf, const char *s)
1239 if (pdf->cave > 0)
1240 pdf_out(pdf, ' ');
1241 pdf_print_str(pdf, s);
1242 pdf->cave = 1;
1245 void pdf_add_name(PDF pdf, const char *name)
1247 pdf_out(pdf, '/');
1248 pdf_puts(pdf, name);
1249 pdf->cave = 1;
1252 void pdf_add_ref(PDF pdf, int num)
1254 if (pdf->cave > 0)
1255 pdf_out(pdf, ' ');
1256 pdf_print_int(pdf, num);
1257 pdf_puts(pdf, " 0 R");
1258 pdf->cave = 1;
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 */
1271 pdf->cave = 1;
1272 if (pdf->compress_level > 0) {
1273 pdf_dict_add_name(pdf, "Filter", "FlateDecode");
1274 pdf->stream_deflate = true;
1278 @ begin a PDF array
1281 void pdf_begin_array(PDF pdf)
1283 pdf_out(pdf, '[');
1284 pdf->cave = 0;
1287 @ end a PDF array
1290 void pdf_end_array(PDF pdf)
1292 pdf_out(pdf, ']');
1293 pdf->cave = 0;
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) {
1305 case PDFOUT_BUF:
1306 pdf_printf(pdf, "%d 0 obj\n", (int) i);
1307 break;
1308 case OBJSTM_BUF:
1309 if (pdf->compress_level == 0)
1310 pdf_printf(pdf, "%% %d 0 obj\n", (int) i); /* debugging help */
1311 break;
1312 default:
1313 normal_error("pdf backend","weird begin object");
1315 pdf->cave = 0;
1318 @ end a PDF object
1321 void pdf_end_obj(PDF pdf)
1323 os_struct *os = pdf->os;
1324 switch (os->curbuf) {
1325 case PDFOUT_BUF:
1326 pdf_puts(pdf, "\nendobj\n"); /* end a PDF object */
1327 break;
1328 case OBJSTM_BUF:
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);
1333 else
1334 pdf_out(pdf, '\n'); /* Adobe Reader seems to need this */
1335 break;
1336 default:
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
1345 characters!
1348 char *convertStringToPDFString(const char *in, int len)
1350 static char pstrbuf[MAX_PSTRING_LEN];
1351 char *out = pstrbuf;
1352 int i, j, k;
1353 char buf[5];
1354 j = 0;
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));
1361 out[j++] = buf[0];
1362 out[j++] = buf[1];
1363 out[j++] = buf[2];
1364 out[j++] = buf[3];
1365 } else if ((in[i] == '(') || (in[i] == ')')) {
1366 /* escape paranthesis */
1367 out[j++] = '\\';
1368 out[j++] = in[i];
1369 } else if (in[i] == '\\') {
1370 /* escape backslash */
1371 out[j++] = '\\';
1372 out[j++] = '\\';
1373 } else {
1374 /* copy char :-) */
1375 out[j++] = in[i];
1378 out[j] = '\0';
1379 return pstrbuf;
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)
1388 int i, k;
1389 char buf[3];
1390 int j = 0;
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));
1394 out[j++] = buf[0];
1395 out[j++] = buf[1];
1397 out[j] = '\0';
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
1416 current time
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)
1431 time_t t;
1432 size_t size;
1433 char time_str[32];
1434 md5_state_t state;
1435 md5_byte_t digest[16];
1436 char id[64];
1437 char pwd[4096];
1438 /* start md5 */
1439 md5_init(&state);
1440 /* get the time */
1441 t = time(NULL);
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));
1447 #ifdef WIN32
1449 char *p;
1450 for (p = pwd; *p; p++) {
1451 if (*p == '\\')
1452 *p = '/';
1453 else if (IS_KANJI(p))
1454 p++;
1457 #endif
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));
1462 /* finish md5 */
1463 md5_finish(&state, digest);
1464 /* write the IDs */
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);
1469 pdf_end_array(pdf);
1472 @ Print the /CreationDate entry.
1474 PDF Reference, third edition says about the expected date format:
1476 3.8.2 Dates
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')
1484 where
1486 YYYY is the year
1487 MM is the month
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.
1514 Solaris 2.5).
1517 #define TIME_STR_SIZE 30 /* minimum size for |time_str| is 24: |"D:YYYYmmddHHMMSS+HH'MM'"| */
1519 static void makepdftime(PDF pdf)
1521 struct tm lt, gmt;
1522 size_t size;
1523 int i, off, off_hours, off_mins;
1524 time_t t = pdf->start_time;
1525 char *time_str = pdf->start_time_str;
1526 /* get the time */
1527 lt = *localtime(&t);
1528 size = strftime(time_str, TIME_STR_SIZE, "D:%Y%m%d%H%M%S", &lt);
1529 /* expected format: "YYYYmmddHHMMSS" */
1530 if (size == 0) {
1531 /* unexpected, contents of |time_str| is undefined */
1532 time_str[0] = '\0';
1533 return;
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') {
1540 time_str[14] = '5';
1541 time_str[15] = '9';
1542 /* for safety */
1543 time_str[16] = '\0';
1545 /* get the time zone offset */
1546 gmt = *gmtime(&t);
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;
1554 if (off == 0) {
1555 time_str[size++] = 'Z';
1556 time_str[size] = 0;
1557 } else {
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;
1566 @ @c
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);
1572 makepdftime(pdf);
1576 @ @c
1577 char *getcreationdate(PDF pdf)
1579 init_start_time(pdf);
1580 return pdf->start_time_str;
1583 @ @c
1584 void remove_pdffile(PDF pdf)
1586 if (pdf != NULL) {
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 */
1600 output_mode o_mode;
1601 const char *m = NULL;
1602 if (lua_only) {
1603 normal_error("lua only","no backend present, needed for what you asked for");
1604 return ;
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();
1612 else
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 */
1616 switch (o_mode) {
1617 case OMODE_DVI:
1618 m = "DVI";
1619 break;
1620 case OMODE_PDF:
1621 m = "PDF";
1622 break;
1623 default:
1624 normal_error("pdf backend","weird output state");
1626 if (strict)
1627 formatted_error("pdf backend", "%s not allowed in %s mode (outputmode = %d)",s, m, (int) int_par(output_mode_code));
1628 else
1629 formatted_warning("pdf backend", "%s not allowed in %s mode (outputmode = %d)",s, m, (int) int_par(output_mode_code));
1630 } else if (strict)
1631 ensure_output_state(pdf, ST_HEADER_WRITTEN);
1634 @ @c
1635 void set_job_id(PDF pdf, int year, int month, int day, int time)
1637 char *name_string, *format_string, *s;
1638 size_t slen;
1639 int i;
1640 if (pdf->job_id_string != NULL)
1641 return;
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);
1650 xfree(s);
1651 xfree(name_string);
1652 xfree(format_string);
1655 @ @c
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 */
1660 short i;
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];
1666 crc /= base;
1668 prefix[6] = '\0';
1669 return prefix;
1672 @ @c
1673 #define mag int_par(mag_code)
1675 void pdf_begin_page(PDF pdf)
1677 pdffloat f;
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);
1696 } else {
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);
1722 pdf_end_array(pdf);
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);
1732 pdf_end_array(pdf);
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);
1737 pdf_end_dict(pdf);
1738 pdf_begin_stream(pdf);
1739 if (global_shipping_mode == SHIPPING_PAGE) {
1740 /* Adjust transformation matrix for the magnification ratio */
1741 if (mag != 1000) {
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);
1757 @ @c
1758 void print_pdf_table_string(PDF pdf, const char *s)
1760 size_t len;
1761 const char *ls;
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);
1768 if (len > 0) {
1769 if (pdf->cave == 1)
1770 pdf_out(pdf, ' ');
1771 pdf_out_block(pdf, ls, len);
1772 pdf->cave = 1;
1775 lua_pop(Luas, 2);
1778 @ @c
1779 const char *get_pdf_table_string(const char *s)
1781 const_lstring ls;
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
1792 lua_pop(Luas, 2);
1793 return ls.s;
1795 lua_pop(Luas, 2);
1796 return NULL ;
1799 @ @c
1800 void pdf_end_page(PDF pdf)
1802 char s[64], *p;
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);
1819 pdf_end_obj(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);
1837 pdf_end_array(pdf);
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);
1857 pdf_end_dict(pdf);
1858 pdf_end_obj(pdf);
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;
1872 pdf_end_array(pdf);
1873 pdf_end_obj(pdf);
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;
1882 pdf_end_array(pdf);
1883 pdf_end_obj(pdf);
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);
1891 ol = ol->link;
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;
1914 ol = ol->link;
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);
1921 ol = ol->link;
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);
1934 pdf_end_dict(pdf);
1935 pdf_end_obj(pdf);
1937 ol = ol->link;
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));
1954 pdf_end_dict(pdf);
1955 pdf_end_obj(pdf);
1956 ol = ol->link;
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)
1967 flush_node(j);
1968 ol = ol->link;
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");
1985 } else {
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) {
2005 p = s;
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);
2010 ol = ol->link;
2012 pdf_end_dict(pdf);
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) {
2022 p = s;
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);
2027 ol = ol->link;
2029 while (ol1 != null) {
2030 p = s;
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)]);
2036 ol1 = ol1->link;
2038 pdf_end_dict(pdf);
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");
2053 pdf_end_array(pdf);
2054 pdf_end_dict(pdf);
2055 pdf_end_obj(pdf);
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)
2067 int k;
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);
2073 } else {
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");
2081 pdf_end_array(pdf);
2082 pdf_end_obj(pdf);
2087 @ @c
2088 static void check_nonexisting_pages(PDF pdf)
2090 struct avl_traverser t;
2091 oentry *p;
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)
2109 return false;
2110 return true;
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;
2121 char *s = NULL;
2122 const char *p = NULL;
2123 int k, len = 0;
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) {
2144 if (len > 0) {
2145 pdf_out(pdf, '\n');
2146 pdf_puts(pdf, s);
2147 pdf_out(pdf, '\n');
2148 xfree(s);
2150 delete_token_ref(pdf_info_toks);
2151 pdf_info_toks = null;
2153 if (p && strlen(p) > 0) {
2154 pdf_out(pdf, '\n');
2155 pdf_puts(pdf, p); /* no free, pointer */
2156 pdf_out(pdf, '\n');
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);
2163 pdf_out(pdf, '.');
2164 pdf_print_int(pdf, luatexversion % 100);
2165 pdf_out(pdf, '.');
2166 pdf_print(pdf, luatexrevision);
2167 pdf_out(pdf, ')');
2169 if (!creator_given)
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);
2183 pdf_end_dict(pdf);
2184 pdf_end_obj(pdf);
2185 return k;
2188 static void build_free_object_list(PDF pdf)
2190 int k;
2191 int l = 0;
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);
2196 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)
2208 int i, j, k;
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, "->");
2219 if (pdf->gone > 0)
2220 normal_error("pdf backend","dangling objects discarded, no output file produced.");
2221 } else {
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];
2247 while (k != 0) {
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
2264 intermediate node.
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];
2274 while (k != 0) {
2275 pdf_add_ref(pdf, k);
2276 k = obj_link(pdf, k);
2278 pdf_end_array(pdf);
2279 pdf_end_obj(pdf);
2280 k = pdf->head_tab[obj_type_thread];
2281 while (k != 0) {
2282 out_thread(pdf, k);
2283 k = obj_link(pdf, k);
2285 } else {
2286 threads = 0;
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);
2294 if (threads != 0)
2295 pdf_dict_add_ref(pdf, "Threads", threads);
2296 if (outlines != 0)
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);
2308 pdf_end_dict(pdf);
2309 pdf_end_obj(pdf);
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);
2316 pdf_flush(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;
2327 else
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);
2337 pdf_end_array(pdf);
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);
2344 pdf_end_array(pdf);
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");
2353 print_ID(pdf);
2354 pdf_dict_add_streaminfo(pdf);
2355 pdf_end_dict(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 */
2359 pdf_out(pdf, 0);
2360 pdf_out_bytes(pdf, obj_link(pdf, k), xref_offset_width);
2361 pdf_out(pdf, 255);
2362 } else if (obj_os_idx(pdf, k) == PDF_OS_MAX_OBJS) { /* object not in object stream */
2363 pdf_out(pdf, 1);
2364 pdf_out_bytes(pdf, obj_offset(pdf, k),
2365 xref_offset_width);
2366 pdf_out(pdf, 0);
2367 } else { /* object in object stream */
2368 pdf_out(pdf, 2);
2369 pdf_out_bytes(pdf, obj_offset(pdf, k),
2370 xref_offset_width);
2371 pdf_out(pdf, obj_os_idx(pdf, k));
2374 pdf_end_stream(pdf);
2375 pdf_end_obj(pdf);
2376 pdf_flush(pdf);
2377 } else {
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");
2390 } else {
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;
2408 print_ID(pdf);
2409 pdf_end_dict(pdf);
2410 pdf_out(pdf, '\n');
2412 pdf_puts(pdf, "startxref\n");
2413 pdf->cave = 0;
2414 if (pdf->os_enable)
2415 pdf_add_longint(pdf, (longinteger) obj_offset(pdf, xref_stm));
2416 else
2417 pdf_add_longint(pdf, (longinteger) pdf->save_offset);
2418 pdf_puts(pdf, "\n%%EOF\n");
2419 pdf_flush(pdf);
2420 if (callback_id == 0) {
2421 tprint_nl("Output written on ");
2422 tprint(pdf->file_name);
2423 tprint(" (");
2424 print_int(total_pages);
2425 tprint(" page");
2426 if (total_pages != 1)
2427 print_char('s');
2428 tprint(", ");
2429 print_int(pdf_offset(pdf));
2430 tprint(" bytes).");
2431 print_ln();
2432 } else if (callback_id > 0) {
2433 run_callback(callback_id, "->");
2435 } else {
2436 if (callback_id > 0) {
2437 run_callback(callback_id, "->");
2440 libpdffinish(pdf);
2441 if (pdf->draftmode == 0)
2442 close_file(pdf->file);
2443 else
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);
2466 @ @c
2467 void scan_pdfcatalog(PDF pdf)
2469 halfword p;
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");
2475 } else {
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);
2481 pdf_end_obj(pdf);
2482 delete_action_ref(p);