fix getsup (HH)
[luatex.git] / source / texk / web2c / luatexdir / pdf / pdfgen.w
blob023f7fd65a380424953eba8bb737cf9816278196
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 check_nprintf(size_get, size_want) \
30 if ((unsigned)(size_get) >= (unsigned)(size_want)) \
31 formatted_error("pdf backend","snprintf() failed in file %s at line %d", __FILE__, __LINE__);
33 PDF static_pdf = NULL;
35 @ commandline interface
38 int output_mode_used;
39 int output_mode_option;
40 int output_mode_value;
41 int draft_mode_option;
42 int draft_mode_value;
44 halfword pdf_info_toks; /* additional keys of Info dictionary */
45 halfword pdf_catalog_toks; /* additional keys of Catalog dictionary */
46 halfword pdf_catalog_openaction;
47 halfword pdf_names_toks; /* additional keys of Names dictionary */
48 halfword pdf_trailer_toks; /* additional keys of Trailer dictionary */
49 shipping_mode_e global_shipping_mode = NOT_SHIPPING; /* set to |shipping_mode| when |ship_out| starts */
52 @ Create a new buffer |strbuf_s| of size |size| and maximum allowed size |limit|.
53 Initialize it and set |p| to begin of data.
56 strbuf_s *new_strbuf(size_t size, size_t limit)
58 strbuf_s *b;
59 b = xtalloc(1, strbuf_s);
60 b->size = size;
61 b->limit = limit;
62 if (size > 0)
63 b->p = b->data = xtalloc(b->size, unsigned char);
64 else
65 b->p = b->data = NULL; /* for other alloc */
66 return b;
69 @ Check that |n| bytes more fit into buffer; increase it if required.
72 static void strbuf_room(strbuf_s * b, size_t n)
74 unsigned int a;
75 size_t l = (size_t) (b->p - b->data);
76 if (n > b->limit - l)
77 overflow("PDF buffer", (unsigned) b->size);
78 if (n + l > b->size) {
79 a = (unsigned int) (b->size >> 2);
80 if (n + l > b->size + a)
81 b->size = n + l;
82 else if (b->size < b->limit - a)
83 b->size = b->size + a;
84 else
85 b->size = b->limit;
86 b->data = xreallocarray(b->data, unsigned char, (unsigned) b->size);
87 b->p = b->data + l;
91 @ Seek to position |offset| within buffer. Position must be valid.
94 void strbuf_seek(strbuf_s * b, off_t offset)
96 b->p = b->data + offset;
99 @ Get the current buffer fill level, the number of characters.
102 size_t strbuf_offset(strbuf_s * b)
104 return (size_t) (b->p - b->data);
107 @ Put one character into buffer. Make room before if needed.
110 void strbuf_putchar(strbuf_s * b, unsigned char c)
112 if ((size_t) (b->p - b->data + 1) > b->size)
113 strbuf_room(b, 1);
114 *b->p++ = c;
117 @ Dump filled buffer part to PDF.
120 void strbuf_flush(PDF pdf, strbuf_s * b)
122 pdf_out_block(pdf, (const char *) b->data, strbuf_offset(b));
123 strbuf_seek(b, 0);
126 @ Free all dynamically allocated buffer structures.
129 void strbuf_free(strbuf_s * b)
131 xfree(b->data);
132 xfree(b);
135 @ |init_pdf_struct()| is called early, only once, from maincontrol.w
138 PDF init_pdf_struct(PDF pdf)
140 os_struct *os;
141 pdf = xtalloc(1, pdf_output_file);
142 memset(pdf, 0, sizeof(pdf_output_file));
143 pdf->job_name = makecstring(job_name);
145 output_mode_used = OMODE_NONE; /* will be set by |fix_o_mode()| */
146 pdf->o_mode = output_mode_used; /* used by synctex, we need to use output_mode_used there */
147 pdf->o_state = ST_INITIAL;
149 /* init PDF and object stream writing */
150 pdf->os = os = xtalloc(1, os_struct);
151 memset(pdf->os, 0, sizeof(os_struct));
152 os->buf[PDFOUT_BUF] = new_strbuf(inf_pdfout_buf_size, sup_pdfout_buf_size);
153 os->buf[OBJSTM_BUF] = new_strbuf(inf_objstm_buf_size, sup_objstm_buf_size);
154 os->obj = xtalloc(PDF_OS_MAX_OBJS, os_obj_data);
155 os->cur_objstm = 0;
157 os->curbuf = PDFOUT_BUF;
158 pdf->buf = os->buf[os->curbuf];
160 Later ttf_seek_outbuf(TABDIR_OFF + n * 4 * TTF_ULONG_SIZE); in ttf_init_font
161 we need 236 bytes, so we start with 256 bytes as in pdftex.
163 pdf->fb = new_strbuf(256, 100000000);
165 pdf->stream_deflate = false;
166 pdf->stream_writing = false;
169 Sometimes it is neccesary to allocate memory for PDF output that cannot be
170 deallocated then, so we use |mem| for this purpose.
172 pdf->mem_size = inf_pdf_mem_size;
173 pdf->mem = xtalloc(pdf->mem_size, int);
175 The first word is not used so we can use zero as a value for testing
176 whether a pointer to |mem| is valid.
178 pdf->mem_ptr = 1;
180 pdf->pstruct = NULL;
182 pdf->posstruct = xtalloc(1, posstructure);
183 pdf->posstruct->pos.h = 0;
184 pdf->posstruct->pos.v = 0;
185 pdf->posstruct->dir = dir_TLT;
187 /* allocated size of |obj_tab| array */
188 pdf->obj_tab_size = (unsigned) inf_obj_tab_size;
189 pdf->obj_tab = xtalloc(pdf->obj_tab_size + 1, obj_entry);
190 memset(pdf->obj_tab, 0, sizeof(obj_entry));
192 pdf->minor_version = -1;
193 pdf->decimal_digits = 4;
194 pdf->gamma = 65536;
195 pdf->image_gamma = 65536;
196 pdf->image_hicolor = 1;
197 pdf->image_apply_gamma = 0;
198 pdf->objcompresslevel = 0;
199 pdf->compress_level = 0;
200 pdf->draftmode = 0;
201 pdf->inclusion_copy_font = 1;
202 pdf->pk_resolution = 0;
203 pdf->pk_fixed_dpi = 0;
204 pdf->pk_scale_factor = 0;
206 init_dest_names(pdf);
207 pdf->page_resources = NULL;
209 init_pdf_pagecalculations(pdf);
211 pdf->vfstruct = new_vfstruct();
213 return pdf;
216 @ We use |pdf_get_mem| to allocate memory in |mem|.
219 int pdf_get_mem(PDF pdf, int s)
221 int a;
222 int ret;
223 if (s > sup_pdf_mem_size - pdf->mem_ptr)
224 overflow("pdf memory size (pdf_mem_size)", (unsigned) pdf->mem_size);
225 if (pdf->mem_ptr + s > pdf->mem_size) {
226 a = pdf->mem_size >> 2;
227 if (pdf->mem_ptr + s > pdf->mem_size + a) {
228 pdf->mem_size = pdf->mem_ptr + s;
229 } else if (pdf->mem_size < sup_pdf_mem_size - a) {
230 pdf->mem_size = pdf->mem_size + a;
231 } else {
232 pdf->mem_size = sup_pdf_mem_size;
234 pdf->mem = xreallocarray(pdf->mem, int, (unsigned) pdf->mem_size);
236 ret = pdf->mem_ptr;
237 pdf->mem_ptr = pdf->mem_ptr + s;
238 return ret;
241 @ there are defined in |luatex-api.h|, so we need |luatex-api.c|:
244 output_mode get_o_mode(void)
246 output_mode o_mode;
247 if (output_mode_par > 0) {
248 o_mode = OMODE_PDF;
249 } else
250 o_mode = OMODE_DVI;
251 return o_mode;
254 void fix_o_mode(void)
256 output_mode o_mode = get_o_mode();
257 if (output_mode_used == OMODE_NONE) {
258 output_mode_used = o_mode;
259 static_pdf->o_mode = output_mode_used; /* used by synctex, we need to use output_mode_used there */
260 } else if (output_mode_used != o_mode) {
261 normal_error("pdf backend", "\\outputmode can only be changed before anything is written to the output");
265 @ This ensures that |pdfminorversion| is set only before any bytes have been
266 written to the generated \.{PDF} file. Here also all variables for \.{PDF} output
267 are initialized, the \.{PDF} file is opened by |ensure_pdf_open|, and the \.{PDF}
268 header is written.
271 void fix_pdf_minorversion(PDF pdf)
273 if (pdf->minor_version < 0) { /* unset */
274 if ((pdf_minor_version < 0) || (pdf_minor_version > 9)) {
275 const char *hlp[] = { "The pdfminorversion must be between 0 and 9.", "I changed this to 4.", NULL };
276 char msg[256];
277 (void) snprintf(msg, 255, "LuaTeX error (illegal pdfminorversion %d)", (int) pdf_minor_version);
278 tex_error(msg, hlp);
279 pdf->minor_version = 4;
280 } else {
281 pdf->minor_version = pdf_minor_version;
283 } else {
284 /* Check that variables for \.{PDF} output are unchanged */
285 if (pdf->minor_version != pdf_minor_version)
286 normal_error("pdf backend", "minorversion cannot be changed after data is written to the PDF file");
290 static void fix_pdf_draftmode(PDF pdf)
292 if (pdf->draftmode != draft_mode_par)
293 normal_error("pdf backend", "draftmode cannot be changed after data is written to the PDF file");
294 if (pdf->draftmode != 0) {
295 pdf->compress_level = 0; /* re-fix it, might have been changed inbetween */
296 pdf->objcompresslevel = 0;
300 @ @c
301 #define ZIP_BUF_SIZE 32768
303 #define check_err(f, fn) \
304 if (f != Z_OK) \
305 formatted_error("pdf backend","zlib %s() failed (error code %d)", fn, f)
307 @ @c
308 static void write_zip(PDF pdf)
310 int flush, err = Z_OK;
311 uInt zip_len;
312 strbuf_s *buf = pdf->buf;
313 z_stream *s = pdf->c_stream;
314 boolean finish = pdf->zip_write_state == ZIP_FINISH;
315 if (pdf->stream_length == 0) {
316 if (s == NULL) {
317 s = pdf->c_stream = xtalloc(1, z_stream);
318 s->zalloc = (alloc_func) 0;
319 s->zfree = (free_func) 0;
320 s->opaque = (voidpf) 0;
321 check_err(deflateInit(s, pdf->compress_level), "deflateInit");
322 pdf->zipbuf = xtalloc(ZIP_BUF_SIZE, char);
323 } else
324 check_err(deflateReset(s), "deflateReset");
325 s->next_out = (Bytef *) pdf->zipbuf;
326 s->avail_out = ZIP_BUF_SIZE;
328 s->next_in = buf->data;
329 s->avail_in = (uInt) (buf->p - buf->data);
330 while (true) {
331 if (s->avail_out == 0 || (finish && s->avail_out < ZIP_BUF_SIZE)) {
332 zip_len = ZIP_BUF_SIZE - s->avail_out;
333 pdf->gone += (off_t) xfwrite(pdf->zipbuf, 1, zip_len, pdf->file);
334 pdf->last_byte = pdf->zipbuf[zip_len - 1];
335 s->next_out = (Bytef *) pdf->zipbuf;
336 s->avail_out = ZIP_BUF_SIZE;
338 if (finish) {
339 if (err == Z_STREAM_END) {
340 xfflush(pdf->file);
341 pdf->zip_write_state = NO_ZIP;
342 break;
344 flush = Z_FINISH;
345 } else {
346 if (s->avail_in == 0)
347 break;
348 flush = Z_NO_FLUSH;
350 err = deflate(s, flush);
351 if (err != Z_OK && err != Z_STREAM_END)
352 formatted_error("pdf backend","zlib deflate() failed (error code %d)", err);
354 pdf->stream_length = (off_t) s->total_out;
357 @ @c
358 void zip_free(PDF pdf)
360 if (pdf->zipbuf != NULL) {
361 check_err(deflateEnd(pdf->c_stream), "deflateEnd");
362 xfree(pdf->zipbuf);
364 xfree(pdf->c_stream);
367 @ @c
368 static void write_nozip(PDF pdf)
370 strbuf_s *buf = pdf->buf;
371 size_t l = strbuf_offset(buf);
372 if (l == 0)
373 return;
374 pdf->stream_length = pdf_offset(pdf) - pdf->save_offset;
375 pdf->gone += (off_t) xfwrite((char *) buf->data, sizeof(char), l, pdf->file);
376 pdf->last_byte = *(buf->p - 1);
379 @ The PDF buffer is flushed by calling |pdf_flush|, which checks the
380 variable |zip_write_state| and will compress the buffer before flushing if
381 neccesary. We call |pdf_begin_stream| to begin a stream and |pdf_end_stream|
382 to finish it. The stream contents will be compressed if compression is turn on.
385 void pdf_flush(PDF pdf)
387 os_struct *os = pdf->os;
388 off_t saved_pdf_gone = pdf->gone;
389 switch (os->curbuf) {
390 case PDFOUT_BUF:
391 if (pdf->draftmode == 0) {
392 switch (pdf->zip_write_state) {
393 case NO_ZIP:
394 write_nozip(pdf);
395 break;
396 case ZIP_WRITING:
397 case ZIP_FINISH:
398 write_zip(pdf);
399 break;
400 default:
401 normal_error("pdf backend", "bad zip state");
403 } else
404 pdf->zip_write_state = NO_ZIP;
405 strbuf_seek(pdf->buf, 0);
406 if (saved_pdf_gone > pdf->gone)
407 normal_error("pdf backend", "file size exceeds architectural limits (pdf_gone wraps around)");
408 break;
409 case OBJSTM_BUF:
410 break;
411 default:
412 normal_error("pdf backend", "bad buffer state");
416 @ @c
417 static void pdf_buffer_select(PDF pdf, buffer_e buf)
419 os_struct *os = pdf->os;
420 if (pdf->os_enable && buf == OBJSTM_BUF)
421 os->curbuf = OBJSTM_BUF; /* switch to object stream */
422 else
423 os->curbuf = PDFOUT_BUF; /* switch to PDF stream */
424 pdf->buf = os->buf[pdf->os->curbuf];
427 @ create new \.{/ObjStm} object if required, and set up cross reference info
430 static void pdf_prepare_obj(PDF pdf, int k, int pdf_os_threshold)
432 os_struct *os = pdf->os;
433 strbuf_s *obuf = os->buf[OBJSTM_BUF];
434 if (pdf->objcompresslevel >= pdf_os_threshold)
435 pdf_buffer_select(pdf, OBJSTM_BUF);
436 else
437 pdf_buffer_select(pdf, PDFOUT_BUF);
438 switch (os->curbuf) {
439 case PDFOUT_BUF:
440 obj_offset(pdf, k) = pdf_offset(pdf);
441 obj_os_idx(pdf, k) = PDF_OS_MAX_OBJS; /* mark it as not included in any ObjStm */
442 break;
443 case OBJSTM_BUF:
444 if (os->cur_objstm == 0) {
445 os->cur_objstm =
446 (unsigned int) pdf_create_obj(pdf, obj_type_objstm, 0);
447 os->idx = 0;
448 obuf->p = obuf->data; /* start fresh object stream */
449 os->ostm_ctr++; /* only for statistics */
451 obj_os_idx(pdf, k) = (int) os->idx;
452 obj_os_objnum(pdf, k) = (int) os->cur_objstm;
453 os->obj[os->idx].num = k;
454 os->obj[os->idx].off = obuf->p - obuf->data;
455 break;
456 default:
457 normal_error("pdf backend", "bad object state");
461 @* Low-level buffer checkers.
463 @ Set the active buffer pointer. Make sure that there are at least |n| bytes free
464 in that buffer, flush if needed.
467 inline void pdf_room(PDF pdf, int n)
469 strbuf_s *buf = pdf->buf;
470 if ((size_t) (n + buf->p - buf->data) <= buf->size)
471 return;
472 if (pdf->os->curbuf == PDFOUT_BUF) {
473 if ((size_t) n > buf->size)
474 overflow("PDF output buffer", (unsigned) buf->size);
475 if ((size_t) (n + buf->p - buf->data) < buf->limit)
476 strbuf_room(buf, (size_t) n);
477 else
478 pdf_flush(pdf);
479 } else {
480 strbuf_room(buf, (size_t) n);
484 @ @c
485 void pdf_out_block(PDF pdf, const char *s, size_t n)
487 size_t l;
488 strbuf_s *buf = pdf->buf;
489 do {
490 l = n;
491 if (l > buf->size)
492 l = buf->size;
493 pdf_room(pdf, (int) l);
494 (void) memcpy(buf->p, s, l);
495 buf->p += l;
496 s += l;
497 n -= l;
498 } while (n > 0);
501 @ @c
502 __attribute__ ((format(printf, 2, 3)))
503 void pdf_printf(PDF pdf, const char *fmt, ...)
505 va_list args;
506 va_start(args, fmt);
507 if (pdf->printf_buf == NULL) {
508 pdf->printf_buf = xtalloc(PRINTF_BUF_SIZE, char);
510 (void) vsnprintf(pdf->printf_buf, PRINTF_BUF_SIZE, fmt, args);
511 pdf_puts(pdf, pdf->printf_buf);
512 va_end(args);
515 @ print out a string to PDF buffer
518 void pdf_print(PDF pdf, str_number s)
520 const char *ss;
521 size_t l;
522 if (s >= STRING_OFFSET) {
523 ss = (const char *) str_string(s);
524 l = str_length(s);
525 pdf_out_block(pdf, ss, l);
526 } else {
527 pdf_out(pdf, s);
531 @ print out a integer to PDF buffer
534 void pdf_print_int(PDF pdf, longinteger n)
536 char s[24];
537 int w;
538 w = snprintf(s, 23, "%" LONGINTEGER_PRI "d", (LONGINTEGER_TYPE) n);
539 check_nprintf(w, 23);
540 pdf_out_block(pdf, (const char *) s, (size_t) w);
543 @ @c
545 void print_pdffloat(PDF pdf, pdffloat f)
547 char a[24];
548 int e = f.e, i, l;
549 int64_t m = f.m;
550 if (m < 0) {
551 pdf_out(pdf, '-');
552 m *= -1;
554 l = m / ten_pow[e];
555 pdf_print_int(pdf, l);
556 l = m % ten_pow[e];
557 if (l != 0) {
558 pdf_out(pdf, '.');
559 snprintf(a, 23, "%d", l + ten_pow[e]);
560 for (i = e; i > 0; i--) {
561 if (a[i] != '0')
562 break;
563 a[i] = '\0';
565 pdf_puts(pdf, (a + 1));
570 void print_pdffloat(PDF pdf, pdffloat f)
572 int64_t m = f.m;
573 if (m == 0) {
574 pdf_out(pdf, '0');
575 } else {
576 int e = f.e;
577 if (e == 0) {
578 /* division by ten_pow[0] == 1 */
579 if (m == 1) {
580 pdf_out(pdf, '1');
581 } else {
582 char a[24];
583 snprintf(a, 23, "%" LONGINTEGER_PRI "i", (LONGINTEGER_TYPE) m);
584 pdf_puts(pdf, a);
586 } else {
587 int t = ten_pow[e] ;
588 if (t == m) {
589 pdf_out(pdf, '1');
590 } else {
591 int i, l, w;
592 char a[24];
593 if (m < 0) {
594 pdf_out(pdf, '-');
595 m *= -1;
597 l = m / t;
598 w = snprintf(a, 23, "%i", l);
599 pdf_out_block(pdf, (const char *) a, (size_t) w);
600 l = m % t;
601 if (l != 0) {
602 pdf_out(pdf, '.');
603 snprintf(a, 23, "%d", l + t);
604 for (i = e; i > 0; i--) {
605 if (a[i] != '0')
606 break;
607 a[i] = '\0';
609 pdf_puts(pdf, (a + 1));
616 @ print out |s| as string in PDF output
619 void pdf_print_str(PDF pdf, const char *s)
621 const char *orig = s;
622 int l = (int) strlen(s) - 1; /* last string index */
623 if (l < 0) {
624 pdf_puts(pdf, "()");
625 return;
627 /* the next is not really safe, the string could be "(a)xx(b)" */
628 if ((s[0] == '(') && (s[l] == ')')) {
629 pdf_puts(pdf, s);
630 return;
632 if ((s[0] != '<') || (s[l] != '>') || odd((l + 1))) {
633 pdf_out(pdf, '(');
634 pdf_puts(pdf, s);
635 pdf_out(pdf, ')');
636 return;
638 s++;
639 while (isxdigit((unsigned char)*s))
640 s++;
641 if (s != orig + l) {
642 pdf_out(pdf, '(');
643 pdf_puts(pdf, orig);
644 pdf_out(pdf, ')');
645 return;
647 pdf_puts(pdf, orig); /* it was a hex string after all */
650 @ begin a stream (needs to have a stream dictionary also)
653 void pdf_begin_stream(PDF pdf)
655 pdf_puts(pdf, "\nstream\n");
656 pdf_save_offset(pdf);
657 pdf_flush(pdf);
658 if (pdf->stream_deflate) {
659 pdf->zip_write_state = ZIP_WRITING;
661 pdf->stream_writing = true;
662 pdf->stream_length = 0;
663 pdf->last_byte = 0;
666 @ end a stream
669 void pdf_end_stream(PDF pdf)
671 os_struct *os = pdf->os;
672 switch (os->curbuf) {
673 case PDFOUT_BUF:
674 if (pdf->zip_write_state == ZIP_WRITING)
675 pdf->zip_write_state = ZIP_FINISH;
676 pdf_flush(pdf); /* sets pdf->last_byte */
677 break;
678 case OBJSTM_BUF:
679 normal_error("pdf backend", "bad buffer in end stream, case 1");
680 break;
681 default:
682 normal_error("pdf backend", "bad buffer in end stream, case 2");
684 pdf->stream_deflate = false;
685 pdf->stream_writing = false;
686 pdf_out(pdf, '\n'); /* doesn't really belong to the stream */
687 pdf_puts(pdf, "endstream");
688 /* write stream /Length */
689 if (pdf->seek_write_length && pdf->draftmode == 0) {
690 xfseeko(pdf->file, (off_t)pdf->stream_length_offset, SEEK_SET, pdf->job_name);
691 fprintf(pdf->file, "%" LONGINTEGER_PRI "i", (LONGINTEGER_TYPE) pdf->stream_length);
692 xfseeko(pdf->file, 0, SEEK_END, pdf->job_name);
694 pdf->seek_write_length = false;
697 @ To print |scaled| value to PDF output we need some subroutines to ensure
698 accurary.
701 #define max_integer 0x7FFFFFFF /* $2^{31}-1$ */
703 scaled one_hundred_inch = 7227 * 65536; /* scaled value corresponds to 100in, exact, 473628672 */
704 scaled one_inch = (7227 * 65536 + 50) / 100; /* scaled value corresponds to 1in (rounded to 4736287) */
705 scaled one_true_inch = (7227 * 65536 + 50) / 100; /* scaled value corresponds to 1truein (rounded!) */
706 scaled one_hundred_bp = (7227 * 65536) / 72; /* scaled value corresponds to 100bp */
707 scaled one_bp = 65781; /* scaled value corresponds to 1bp (rounded to 65782) */
710 one_bp is changed on 20110411 to be exactly 65781, as in tex itself, because this value
711 is also used for \pdfpxdimen
714 int ten_pow[10] = {
715 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 /* $10^0..10^9$ */
718 @ The function |divide_scaled| divides |s| by |m| using |dd| decimal
719 digits of precision. It is defined in C because it is a good candidate
720 for optimizations that are not possible in pascal.
723 scaled round_xn_over_d(scaled x, int n, unsigned int d)
725 boolean positive = true;
726 unsigned t, u, v;
727 if (x < 0) {
728 positive = !positive;
729 x = -(x);
731 if (n < 0) {
732 positive = !positive;
733 n = -(n);
735 t = (unsigned) ((x % 0100000) * n);
736 u = (unsigned) (((unsigned) (x) / 0100000) * (unsigned) n + (t / 0100000));
737 v = (u % d) * 0100000 + (t % 0100000);
738 if (u / d >= 0100000)
739 arith_error = true;
740 else
741 u = 0100000 * (u / d) + (v / d);
742 v = v % d;
743 if (2 * v >= d)
744 u++;
745 if (positive)
746 return (scaled) u;
747 else
748 return (-(scaled) u);
751 @ @c
752 void pdf_add_bp(PDF pdf, scaled s)
754 pdffloat a;
755 pdfstructure *p = pdf->pstruct;
756 a.m = i64round(s * p->k1);
757 a.e = pdf->decimal_digits;
758 if (pdf->cave > 0)
759 pdf_out(pdf, ' ');
760 print_pdffloat(pdf, a);
761 pdf->cave = 1;
764 @* handling page resources.
767 typedef struct {
768 int obj_type;
769 pdf_object_list *list;
770 } pr_entry;
772 @ @c
773 static int comp_page_resources(const void *pa, const void *pb, void *p)
775 int a = ((const pr_entry *) pa)->obj_type;
776 int b = ((const pr_entry *) pb)->obj_type;
777 (void) p;
778 if (a > b)
779 return 1;
780 if (a < b)
781 return -1;
782 return 0;
785 @ @c
786 void addto_page_resources(PDF pdf, pdf_obj_type t, int k)
788 pdf_resource_struct *re;
789 pr_entry *pr, tmp;
790 void **pp;
791 pdf_object_list *p, *item = NULL;
792 re = pdf->page_resources;
793 if (re->resources_tree == NULL) {
794 re->resources_tree = avl_create(comp_page_resources, NULL, &avl_xallocator);
795 if (re->resources_tree == NULL)
796 formatted_error("pdf backend","addto_page_resources(): avl_create() page_resource_tree failed");
798 tmp.obj_type = t;
799 pr = (pr_entry *) avl_find(re->resources_tree, &tmp);
800 if (pr == NULL) {
801 pr = xtalloc(1, pr_entry);
802 pr->obj_type = t;
803 pr->list = NULL;
804 pp = avl_probe(re->resources_tree, pr);
805 if (pp == NULL)
806 formatted_error("pdf backend","addto_page_resources(): avl_probe() out of memory in insertion");
808 if (pr->list == NULL) {
809 item = xtalloc(1, pdf_object_list);
810 item->link = NULL;
811 item->info = k;
812 pr->list = item;
813 if (obj_type(pdf, k) == (int)t)
814 set_obj_scheduled(pdf, k); /* k is an object number */
815 } else {
816 for (p = pr->list; p->info != k && p->link != NULL; p = p->link);
817 if (p->info != k) {
818 item = xtalloc(1, pdf_object_list);
819 item->link = NULL;
820 item->info = k;
821 p->link = item;
822 if (obj_type(pdf, k) == (int)t)
823 set_obj_scheduled(pdf, k);
828 @ @c
829 pdf_object_list *get_page_resources_list(PDF pdf, pdf_obj_type t)
831 pdf_resource_struct *re = pdf->page_resources;
832 pr_entry *pr, tmp;
833 if (re == NULL || re->resources_tree == NULL)
834 return NULL;
835 tmp.obj_type = t;
836 pr = (pr_entry *) avl_find(re->resources_tree, &tmp);
837 if (pr == NULL)
838 return NULL;
839 return pr->list;
842 @ @c
843 static void reset_page_resources(PDF pdf)
845 pdf_resource_struct *re = pdf->page_resources;
846 pr_entry *p;
847 struct avl_traverser t;
848 pdf_object_list *l1, *l2;
849 if (re == NULL || re->resources_tree == NULL)
850 return;
851 avl_t_init(&t, re->resources_tree);
852 for (p = avl_t_first(&t, re->resources_tree); p != NULL; p = avl_t_next(&t)) {
853 if (p->list != NULL) {
854 for (l1 = p->list; l1 != NULL; l1 = l2) {
855 l2 = l1->link;
856 free(l1);
858 p->list = NULL; /* but the AVL tree remains */
863 @ @c
864 static void destroy_pg_res_tree(void *pa, void *param)
866 (void) param;
867 xfree(pa);
870 @ @c
871 static void destroy_page_resources_tree(PDF pdf)
873 pdf_resource_struct *re = pdf->page_resources;
874 reset_page_resources(pdf);
875 if (re->resources_tree != NULL)
876 avl_destroy(re->resources_tree, destroy_pg_res_tree);
877 re->resources_tree = NULL;
880 @* Subroutines to print out various PDF objects.
882 @ print out an integer |n| with fixed width |w|; used for outputting cross-reference table. The
883 specification says that an offset must take 10 bytes.
885 static void pdf_print_fw_int(PDF pdf, longinteger n)
887 unsigned char digits[11];
889 int k = 10;
890 do {
891 k--;
892 digits[k] = (unsigned char) ('0' + (n % 10));
893 n /= 10;
894 } while (k != 0);
895 if (n!=0)
896 /* the absolute value of $n$ is greater than 9999999999 */
897 normal_error("pdf backend", "offset exceeds 10 bytes, try enabling object compression.");
898 digits[10]='\0';
899 pdf_puts(pdf, (const char *) digits);
902 @ print out an integer |n| as a fixed number |w| of bytes; used for outputting \.{/XRef} cross-reference stream
904 static void pdf_out_bytes(PDF pdf, longinteger n, size_t w)
906 int k;
907 unsigned char bytes[8]; /* digits in a number being output */
908 k = (int) w;
909 do {
910 k--;
911 bytes[k] = (unsigned char) (n % 256);
912 n /= 256;
913 } while (k != 0);
914 pdf_out_block(pdf, (const char *) bytes, w);
917 @ print out |s| as string in PDF output
920 void pdf_print_str_ln(PDF pdf, const char *s)
922 pdf_print_str(pdf, s);
923 pdf_out(pdf, '\n');
926 @ @c
927 void pdf_print_toks(PDF pdf, halfword p)
929 int len = 0;
930 char *s = tokenlist_to_cstring(p, true, &len);
931 if (len > 0) {
932 if (pdf->cave > 0)
933 pdf_out(pdf, ' ');
934 pdf_puts(pdf, s);
935 pdf->cave = 1;
937 xfree(s);
940 @ prints a rect spec
943 void pdf_add_rect_spec(PDF pdf, halfword r)
945 pdf_add_bp(pdf, pdf_ann_left(r));
946 pdf_add_bp(pdf, pdf_ann_bottom(r));
947 pdf_add_bp(pdf, pdf_ann_right(r));
948 pdf_add_bp(pdf, pdf_ann_top(r));
951 @ output a rectangle specification to PDF file
954 void pdf_rectangle(PDF pdf, halfword r)
956 pdf_add_name(pdf, "Rect");
957 pdf_begin_array(pdf);
958 pdf_add_rect_spec(pdf, r);
959 pdf_end_array(pdf);
962 @ @c
963 static void init_pdf_outputparameters(PDF pdf)
965 int pk_mode;
966 pdf->draftmode = fix_int(draft_mode_par, 0, 1);
967 pdf->compress_level = fix_int(pdf_compress_level, 0, 9);
968 pdf->decimal_digits = fix_int(pdf_decimal_digits, 3, 5);
969 pdf->gamma = fix_int(pdf_gamma, 0, 1000000);
970 pdf->image_gamma = fix_int(pdf_image_gamma, 0, 1000000);
971 pdf->image_hicolor = fix_int(pdf_image_hicolor, 0, 1);
972 pdf->image_apply_gamma = fix_int(pdf_image_apply_gamma, 0, 1);
973 pdf->objcompresslevel = fix_int(pdf_obj_compress_level, 0, MAX_OBJ_COMPRESS_LEVEL);
974 pdf->inclusion_copy_font = fix_int(pdf_inclusion_copy_font, 0, 1);
975 pdf->pk_resolution = fix_int(pdf_pk_resolution, 72, 8000);
976 pdf->pk_fixed_dpi = fix_int(pdf_pk_fixed_dpi, 0, 1);
977 if ((pdf->minor_version >= 5) && (pdf->objcompresslevel > 0)) {
978 pdf->os_enable = true;
979 } else {
980 if (pdf->objcompresslevel > 0) {
981 normal_warning("pdf backend","objcompresslevel > 0 requires minorversion > 4");
982 pdf->objcompresslevel = 0;
984 pdf->os_enable = false;
986 if (pdf->pk_resolution == 0) /* if not set from format file or by user */
987 pdf->pk_resolution = pk_dpi; /* take it from \.{texmf.cnf} */
988 pdf->pk_scale_factor = divide_scaled(72, pdf->pk_resolution, pk_decimal_digits(pdf,5));
989 if (!callback_defined(read_pk_file_callback)) {
990 pk_mode = pdf_pk_mode; /* lookup once */
991 if (pk_mode != null) {
992 char *s = tokenlist_to_cstring(pk_mode, true, NULL);
993 /* This will become LUATEX in 1.0. */
994 kpse_init_prog("PDFTEX", (unsigned) pdf->pk_resolution, s, nil);
995 xfree(s);
996 } else {
997 /* This will become LUATEX in 1.0. */
998 kpse_init_prog("PDFTEX", (unsigned) pdf->pk_resolution, nil, nil);
1000 if (!kpse_var_value("MKTEXPK"))
1001 kpse_set_program_enabled(kpse_pk_format, 1, kpse_src_cmdline);
1003 set_job_id(pdf, year_par, month_par, day_par, time_par);
1004 if ((pdf_unique_resname > 0) && (pdf->resname_prefix == NULL))
1005 pdf->resname_prefix = get_resname_prefix(pdf);
1008 @ Checks that we have a name for the generated PDF file and that it's open.
1011 static void ensure_output_file_open(PDF pdf, const char *ext)
1013 char *fn;
1014 if (pdf->file_name != NULL)
1015 return;
1016 if (job_name == 0)
1017 open_log_file();
1018 fn = pack_job_name(ext);
1019 if (pdf->draftmode == 0 || output_mode_used == OMODE_DVI) {
1020 while (!lua_b_open_out(&pdf->file, fn))
1021 fn = prompt_file_name("file name for output", ext);
1023 pdf->file_name = fn;
1026 @ @c
1027 static void ensure_pdf_header_written(PDF pdf)
1029 /* Initialize variables for \.{PDF} output */
1030 fix_pdf_minorversion(pdf);
1031 init_pdf_outputparameters(pdf);
1032 fix_pdf_draftmode(pdf);
1033 /* Write \.{PDF} header */
1034 pdf_printf(pdf, "%%PDF-1.%d\n", pdf->minor_version);
1035 /* The next blob will be removed 1.0. */
1036 pdf_out(pdf, '%');
1037 pdf_out(pdf, 'P' + 128);
1038 pdf_out(pdf, 'T' + 128);
1039 pdf_out(pdf, 'E' + 128);
1040 pdf_out(pdf, 'X' + 128);
1041 pdf_out(pdf, '\n');
1044 @ @c
1045 void ensure_output_state(PDF pdf, output_state s)
1047 if (pdf->o_state < s) {
1048 if (s > ST_INITIAL)
1049 ensure_output_state(pdf, s - 1);
1050 switch (s - 1) {
1051 case ST_INITIAL:
1052 fix_o_mode();
1053 break;
1054 case ST_OMODE_FIX:
1055 switch (output_mode_used) {
1056 case OMODE_DVI:
1057 ensure_output_file_open(pdf, ".dvi");
1058 break;
1059 case OMODE_PDF:
1060 ensure_output_file_open(pdf, ".pdf");
1061 break;
1062 default:
1063 normal_error("pdf backend","weird output state");
1065 break;
1066 case ST_FILE_OPEN:
1067 switch (output_mode_used) {
1068 case OMODE_DVI:
1069 ensure_dvi_header_written(pdf);
1070 break;
1071 case OMODE_PDF:
1072 ensure_pdf_header_written(pdf);
1073 break;
1074 default:
1075 normal_error("pdf backend","weird output state");
1077 break;
1078 case ST_HEADER_WRITTEN:
1079 break;
1080 case ST_FILE_CLOSED:
1081 break;
1082 default:
1083 normal_error("pdf backend","weird output state");
1085 pdf->o_state++;
1089 @ Write out an accumulated object stream.
1091 First the object number and byte offset pairs are generated and appended to the
1092 ready buffered object stream. By this the value of \.{/First} can be calculated.
1093 Then a new \.{/ObjStm} object is generated, and everything is copied to the PDF
1094 output buffer, where also compression is done. When calling this procedure,
1095 |pdf_os_mode| must be |true|.
1098 static void pdf_os_write_objstream(PDF pdf)
1100 os_struct *os = pdf->os;
1101 unsigned int i, j, n1, n2; /* n1, n2: ObjStm buffer may be reallocated! */
1102 strbuf_s *obuf = os->buf[OBJSTM_BUF];
1103 if (os->cur_objstm == 0) /* no object stream started */
1104 return;
1105 n1 = (unsigned int) strbuf_offset(obuf); /* remember end of collected object stream contents */
1106 /* this is needed here to calculate /First for the ObjStm dict */
1107 for (i = 0, j = 0; i < os->idx; i++) { /* add object-number/byte-offset list to buffer */
1108 pdf_print_int(pdf, (int) os->obj[i].num);
1109 pdf_out(pdf, ' ');
1110 pdf_print_int(pdf, (int) os->obj[i].off);
1111 if (j == 9 || i == os->idx - 1) { /* print out in groups of ten for better readability */
1112 pdf_out(pdf, '\n');
1113 j = 0;
1114 } else {
1115 pdf_out(pdf, ' ');
1116 j++;
1119 n2 = (unsigned int) strbuf_offset(obuf); /* remember current buffer end */
1120 pdf_begin_obj(pdf, (int) os->cur_objstm, OBJSTM_NEVER); /* switch to PDF stream writing */
1121 pdf_begin_dict(pdf);
1122 pdf_dict_add_name(pdf, "Type", "ObjStm");
1123 pdf_dict_add_int(pdf, "N", (int) os->idx); /* number of objects in ObjStm */
1124 pdf_dict_add_int(pdf, "First", (int) (n2 - n1));
1125 pdf_dict_add_streaminfo(pdf);
1126 pdf_end_dict(pdf);
1127 pdf_begin_stream(pdf);
1128 /* write object-number/byte-offset list */
1129 pdf_out_block(pdf, (const char *) (obuf->data + n1), (size_t) (n2 - n1));
1130 /* write collected object stream contents */
1131 pdf_out_block(pdf, (const char *) obuf->data, (size_t) n1);
1132 pdf_end_stream(pdf);
1133 pdf_end_obj(pdf);
1134 os->cur_objstm = 0; /* to force object stream generation next time */
1137 @ begin a PDF dictionary
1140 void pdf_begin_dict(PDF pdf)
1142 pdf_puts(pdf, "<<");
1143 pdf->cave = 0;
1146 @ end a PDF dictionary
1149 void pdf_end_dict(PDF pdf)
1151 pdf_puts(pdf, ">>");
1152 pdf->cave = 0;
1155 @ add integer object to dict
1158 void pdf_dict_add_bool(PDF pdf, const char *key, int i)
1160 pdf_add_name(pdf, key);
1161 pdf_add_bool(pdf, i);
1164 @ add integer object to dict
1167 void pdf_dict_add_int(PDF pdf, const char *key, int i)
1169 pdf_add_name(pdf, key);
1170 pdf_add_int(pdf, i);
1173 @ add name object to dict
1176 void pdf_dict_add_name(PDF pdf, const char *key, const char *val)
1178 pdf_add_name(pdf, key);
1179 pdf_add_name(pdf, val);
1182 @ add string object to dict
1185 void pdf_dict_add_string(PDF pdf, const char *key, const char *val)
1187 if (val == NULL)
1188 return;
1189 pdf_add_name(pdf, key);
1190 if (pdf->cave > 0)
1191 pdf_out(pdf, ' ');
1192 pdf->cave = 0;
1193 pdf_print_str(pdf, val);
1196 @ add name reference to dict
1199 void pdf_dict_add_ref(PDF pdf, const char *key, int num)
1201 pdf_add_name(pdf, key);
1202 pdf_add_ref(pdf, num);
1205 @ add objects of different types
1208 void pdf_add_null(PDF pdf)
1210 if (pdf->cave > 0)
1211 pdf_out(pdf, ' ');
1212 pdf_puts(pdf, "null");
1213 pdf->cave = 1;
1216 void pdf_add_bool(PDF pdf, int i)
1218 if (pdf->cave > 0)
1219 pdf_out(pdf, ' ');
1220 if (i == 0)
1221 pdf_puts(pdf, "false");
1222 else
1223 pdf_puts(pdf, "true");
1224 pdf->cave = 1;
1227 void pdf_add_int(PDF pdf, int i)
1229 if (pdf->cave > 0)
1230 pdf_out(pdf, ' ');
1231 pdf_print_int(pdf, i);
1232 pdf->cave = 1;
1235 void pdf_add_longint(PDF pdf, longinteger n)
1237 if (pdf->cave > 0)
1238 pdf_out(pdf, ' ');
1239 pdf_print_int(pdf, n);
1240 pdf->cave = 1;
1243 void pdf_add_string(PDF pdf, const char *s)
1245 if (pdf->cave > 0)
1246 pdf_out(pdf, ' ');
1247 pdf_print_str(pdf, s);
1248 pdf->cave = 1;
1251 void pdf_add_name(PDF pdf, const char *name)
1253 pdf_out(pdf, '/');
1254 pdf_puts(pdf, name);
1255 pdf->cave = 1;
1258 void pdf_add_ref(PDF pdf, int num)
1260 if (pdf->cave > 0)
1261 pdf_out(pdf, ' ');
1262 pdf_print_int(pdf, num);
1263 pdf_puts(pdf, " 0 R");
1264 pdf->cave = 1;
1267 @ add stream length and filter entries to a stream dictionary,
1268 remember file position for seek
1271 void pdf_dict_add_streaminfo(PDF pdf)
1273 pdf_add_name(pdf, "Length");
1274 pdf->stream_length_offset = pdf_offset(pdf) + 1;
1275 pdf->seek_write_length = true; /* fill in length at |pdf_end_stream| call */
1276 pdf_puts(pdf, " x "); /* space for 10 decimal digits */
1277 pdf->cave = 1;
1278 if (pdf->compress_level > 0) {
1279 pdf_dict_add_name(pdf, "Filter", "FlateDecode");
1280 pdf->stream_deflate = true;
1284 @ begin a PDF array
1287 void pdf_begin_array(PDF pdf)
1289 pdf_out(pdf, '[');
1290 pdf->cave = 0;
1293 @ end a PDF array
1296 void pdf_end_array(PDF pdf)
1298 pdf_out(pdf, ']');
1299 pdf->cave = 0;
1302 @ begin a PDF object
1305 void pdf_begin_obj(PDF pdf, int i, int pdf_os_threshold)
1307 os_struct *os = pdf->os;
1308 ensure_output_state(pdf, ST_HEADER_WRITTEN);
1309 pdf_prepare_obj(pdf, i, pdf_os_threshold);
1310 switch (os->curbuf) {
1311 case PDFOUT_BUF:
1312 pdf_printf(pdf, "%d 0 obj\n", (int) i);
1313 break;
1314 case OBJSTM_BUF:
1315 if (pdf->compress_level == 0)
1316 pdf_printf(pdf, "%% %d 0 obj\n", (int) i); /* debugging help */
1317 break;
1318 default:
1319 normal_error("pdf backend","weird begin object");
1321 pdf->cave = 0;
1324 @ end a PDF object
1327 void pdf_end_obj(PDF pdf)
1329 os_struct *os = pdf->os;
1330 switch (os->curbuf) {
1331 case PDFOUT_BUF:
1332 pdf_puts(pdf, "\nendobj\n"); /* end a PDF object */
1333 break;
1334 case OBJSTM_BUF:
1335 os->idx++; /* = number of objects collected so far in ObjStm */
1336 os->o_ctr++; /* only for statistics */
1337 if (os->idx == PDF_OS_MAX_OBJS)
1338 pdf_os_write_objstream(pdf);
1339 else
1340 pdf_out(pdf, '\n'); /* Adobe Reader seems to need this */
1341 break;
1342 default:
1343 normal_error("pdf backend","weird end object");
1347 @ Converts any string given in in in an allowed PDF string which can be
1348 handled by printf et.al.: \.{\\} is escaped to \.{\\\\}, parenthesis are escaped and
1349 control characters are octal encoded.
1350 This assumes that the string does not contain any already escaped
1351 characters!
1354 char *convertStringToPDFString(const char *in, int len)
1356 static char pstrbuf[MAX_PSTRING_LEN];
1357 char *out = pstrbuf;
1358 int i, j, k;
1359 char buf[5];
1360 j = 0;
1361 for (i = 0; i < len; i++) {
1362 check_buf((unsigned) j + sizeof(buf), MAX_PSTRING_LEN);
1363 if (((unsigned char) in[i] < '!') || ((unsigned char) in[i] > '~')) {
1364 /* convert control characters into oct */
1365 k = snprintf(buf, sizeof(buf), "\\%03o", (unsigned int) (unsigned char) in[i]);
1366 check_nprintf(k, sizeof(buf));
1367 out[j++] = buf[0];
1368 out[j++] = buf[1];
1369 out[j++] = buf[2];
1370 out[j++] = buf[3];
1371 } else if ((in[i] == '(') || (in[i] == ')')) {
1372 /* escape paranthesis */
1373 out[j++] = '\\';
1374 out[j++] = in[i];
1375 } else if (in[i] == '\\') {
1376 /* escape backslash */
1377 out[j++] = '\\';
1378 out[j++] = '\\';
1379 } else {
1380 /* copy char :-) */
1381 out[j++] = in[i];
1384 out[j] = '\0';
1385 return pstrbuf;
1388 @ Converts any string given in in in an allowed PDF string which is hexadecimal
1389 encoded; |sizeof(out)| should be at least $|lin|*2+1$.
1392 static void convertStringToHexString(const char *in, char *out, int lin)
1394 int i, k;
1395 char buf[3];
1396 int j = 0;
1397 for (i = 0; i < lin; i++) {
1398 k = snprintf(buf, sizeof(buf), "%02X", (unsigned int) (unsigned char) in[i]);
1399 check_nprintf(k, sizeof(buf));
1400 out[j++] = buf[0];
1401 out[j++] = buf[1];
1403 out[j] = '\0';
1406 @ Compute the ID string as per PDF1.4 9.3:
1408 File identifers are defined by the optional ID entry in a PDF file's trailer
1409 dictionary (see Section 3.4.4, "File Trailer"; see also implementation note 105
1410 in Appendix H). The value of this entry is an array of two strings. The first
1411 string is a permanent identifier based on the contents of the file at the time it
1412 was originally created, and does not change when the file is incrementally
1413 updated. The second string is a changing identifier based on the file's contents
1414 at the time it was last updated. When a file is first written, both identifiers
1415 are set to the same value. If both identifiers match when a file reference is
1416 resolved, it is very likely that the correct file has been found; if only the
1417 first identifier matches, then a different version of the correct file has been
1418 found. To help ensure the uniqueness of file identifiers, it is recommend that
1419 they be computed using a message digest algorithm such as MD5 (described in
1420 Internet RFC 1321, The MD5 Message-Digest Algorithm; see the Bibliography), using
1421 the following information (see implementation note 106 in Appendix H): - The
1422 current time
1424 - A string representation of the file's location, usually a pathname
1425 - The size of the file in bytes
1426 - The values of all entries in the file's document information
1427 dictionary (see Section 9.2.1, Document Information Dictionary )
1429 This stipulates only that the two IDs must be identical when the file is created
1430 and that they should be reasonably unique. Since it's difficult to get the file
1431 size at this point in the execution of pdfTeX and scanning the info dict is also
1432 difficult, we start with a simpler implementation using just the first two items.
1438 A user supplied trailerid had better be an array! So maybe we need to check
1439 for [] and error otherwise.
1442 static void print_ID(PDF pdf)
1444 if ((pdf_suppress_optional_info & 512) == 0) {
1445 const char *p = NULL;
1446 pdf_add_name(pdf, "ID");
1447 p = get_pdf_table_string("trailerid");
1448 if (p && strlen(p) > 0) {
1449 pdf_puts(pdf,p);
1450 } else if (pdf_trailer_id != 0) {
1451 /* user provided one */
1452 pdf_print_toks(pdf, pdf_trailer_id);
1453 } else {
1454 /* system provided one */
1455 time_t t;
1456 size_t size;
1457 char time_str[32];
1458 md5_state_t state;
1459 md5_byte_t digest[16];
1460 char id[64];
1461 char pwd[4096];
1462 /* start md5 */
1463 md5_init(&state);
1464 /* get the time */
1465 t = pdf->start_time;
1466 size = strftime(time_str, sizeof(time_str), "%Y%m%dT%H%M%SZ", gmtime(&t));
1467 md5_append(&state, (const md5_byte_t *) time_str, (int) size);
1468 /* get the file name */
1469 if (getcwd(pwd, sizeof(pwd)) == NULL) {
1470 formatted_error("pdf backend","getcwd() failed (%s), (path too long?)", strerror(errno));
1472 #ifdef WIN32
1474 char *p;
1475 for (p = pwd; *p; p++) {
1476 if (*p == '\\')
1477 *p = '/';
1478 else if (IS_KANJI(p))
1479 p++;
1482 #endif
1483 md5_append(&state, (const md5_byte_t *) pwd, (int) strlen(pwd));
1484 md5_append(&state, (const md5_byte_t *) "/", 1);
1485 md5_append(&state, (const md5_byte_t *) pdf->file_name, (int) strlen(pdf->file_name));
1486 /* finish md5 */
1487 md5_finish(&state, digest);
1488 /* write the IDs */
1489 convertStringToHexString((char *) digest, id, 16);
1490 pdf_begin_array(pdf);
1491 pdf_printf(pdf, "<%s> <%s>", id, id);
1492 pdf_end_array(pdf);
1497 @ Print the /CreationDate entry.
1499 PDF Reference, third edition says about the expected date format:
1501 3.8.2 Dates
1503 PDF defines a standard date format, which closely follows that of the
1504 international standard ASN.1 (Abstract Syntax Notation One), defined in ISO/IEC
1505 8824 (see the Bibliography). A date is a string of the form
1507 (D:YYYYMMDDHHmmSSOHH'mm')
1509 where
1511 YYYY is the year
1512 MM is the month
1513 DD is the day (01-31)
1514 HH is the hour (00-23)
1515 mm is the minute (00-59)
1516 SS is the second (00-59)
1517 O is the relationship of local time to Universal Time (UT), denoted by one
1518 of the characters +, -, or Z (see below)
1519 HH followed by ' is the absolute value of the offset from UT in hours (00-23)
1520 mm followed by ' is the absolute value of the offset from UT in minutes (00-59)
1522 The apostrophe character (') after HH and mm is part of the syntax. All fields
1523 after the year are optional. (The prefix D:, although also optional, is strongly
1524 recommended.) The default values for MM and DD are both 01; all other numerical
1525 fields default to zero values. A plus sign (+) as the value of the O field
1526 signifies that local time is later than UT, a minus sign (-) that local time is
1527 earlier than UT, and the letter Z that local time is equal to UT. If no UT
1528 information is specified, the relationship of the specified time to UT is
1529 considered to be unknown. Whether or not the time zone is known, the rest of the
1530 date should be specified in local time.
1532 For example, December 23, 1998, at 7:52 PM, U.S. Pacific Standard Time, is
1533 represented by the string
1535 D:199812231952-08'00'
1537 The main difficulty is get the time zone offset. |strftime()| does this in ISO
1538 C99 (e.g. newer glibc) with \%z, but we have to work with other systems (e.g.
1539 Solaris 2.5).
1542 #define TIME_STR_SIZE 30 /* minimum size for |time_str| is 24: |"D:YYYYmmddHHMMSS+HH'MM'"| */
1544 static void makepdftime(PDF pdf)
1546 struct tm lt, gmt;
1547 size_t size;
1548 int i, off, off_hours, off_mins;
1549 time_t t = pdf->start_time;
1550 char *time_str = pdf->start_time_str;
1551 /* get the time */
1552 if (utc_option) {
1553 lt = *gmtime(&t);
1554 } else {
1555 lt = *localtime(&t);
1557 size = strftime(time_str, TIME_STR_SIZE, "D:%Y%m%d%H%M%S", &lt);
1558 /* expected format: "YYYYmmddHHMMSS" */
1559 if (size == 0) {
1560 /* unexpected, contents of |time_str| is undefined */
1561 time_str[0] = '\0';
1562 return;
1565 correction for seconds: \%S can be in range 00..61, the PDF reference
1566 expects 00..59, therefore we map "60" and "61" to "59"
1568 if (time_str[14] == '6') {
1569 time_str[14] = '5';
1570 time_str[15] = '9';
1571 /* for safety */
1572 time_str[16] = '\0';
1574 /* get the time zone offset */
1575 gmt = *gmtime(&t);
1576 /* this calculation method was found in exim's tod.c */
1577 off = 60 * (lt.tm_hour - gmt.tm_hour) + lt.tm_min - gmt.tm_min;
1578 if (lt.tm_year != gmt.tm_year) {
1579 off += (lt.tm_year > gmt.tm_year) ? 1440 : -1440;
1580 } else if (lt.tm_yday != gmt.tm_yday) {
1581 off += (lt.tm_yday > gmt.tm_yday) ? 1440 : -1440;
1583 if (off == 0) {
1584 time_str[size++] = 'Z';
1585 time_str[size] = 0;
1586 } else {
1587 off_hours = off / 60;
1588 off_mins = abs(off - off_hours * 60);
1589 i = snprintf(&time_str[size], 9, "%+03d'%02d'", off_hours, off_mins);
1590 check_nprintf(i, 9);
1592 pdf->start_time = t;
1595 @ @c
1596 void initialize_start_time(PDF pdf)
1598 if (pdf->start_time == 0) {
1599 pdf->start_time = get_start_time();
1600 pdf->start_time_str = xtalloc(TIME_STR_SIZE, char);
1601 makepdftime(pdf);
1605 @ @c
1606 char *getcreationdate(PDF pdf)
1608 initialize_start_time(pdf);
1609 return pdf->start_time_str;
1612 @ @c
1613 void remove_pdffile(PDF pdf)
1615 if (pdf != NULL) {
1616 if (!kpathsea_debug && pdf->file_name && (pdf->draftmode == 0)) {
1617 xfclose(pdf->file, pdf->file_name);
1618 remove(pdf->file_name);
1623 @ Use |check_o_mode()| in the backend-specific "Implement..." chunks
1626 void check_o_mode(PDF pdf, const char *s, int o_mode_bitpattern, boolean strict) /* s ignored now */
1629 output_mode o_mode;
1630 const char *m = NULL;
1631 if (lua_only) {
1632 normal_error("lua only","no backend present, needed for what you asked for");
1633 return ;
1636 in warn mode (strict == false): only check, don't do |fix_o_mode()| here! |output_mode_used|
1637 is left in possibly wrong state until real output, ok.
1639 if (output_mode_used == OMODE_NONE)
1640 o_mode = get_o_mode();
1641 else
1642 o_mode = output_mode_used;
1643 pdf->o_mode = output_mode_used; /* used by synctex, we need to use output_mode_used there */
1644 if (!((1 << o_mode) & o_mode_bitpattern)) { /* warning or error */
1645 switch (o_mode) {
1646 case OMODE_DVI:
1647 m = "DVI";
1648 break;
1649 case OMODE_PDF:
1650 m = "PDF";
1651 break;
1652 default:
1653 normal_error("pdf backend","weird output state");
1655 if (strict)
1656 formatted_error("pdf backend", "%s not allowed in %s mode (outputmode = %d)",s, m, (int) output_mode_par);
1657 else
1658 formatted_warning("pdf backend", "%s not allowed in %s mode (outputmode = %d)",s, m, (int) output_mode_par);
1659 } else if (strict)
1660 ensure_output_state(pdf, ST_HEADER_WRITTEN);
1663 @ @c
1664 void set_job_id(PDF pdf, int year, int month, int day, int time)
1666 char *name_string, *format_string, *s;
1667 size_t slen;
1668 int i;
1669 if (pdf->job_id_string != NULL)
1670 return;
1671 name_string = makecstring(job_name);
1672 format_string = makecstring(format_ident);
1673 slen = SMALL_BUF_SIZE + strlen(name_string) + strlen(format_string) + strlen(luatex_banner);
1674 s = xtalloc(slen, char);
1675 /* The Web2c version string starts with a space. */
1676 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);
1677 check_nprintf(i, slen);
1678 pdf->job_id_string = xstrdup(s);
1679 xfree(s);
1680 xfree(name_string);
1681 xfree(format_string);
1684 @ @c
1685 char *get_resname_prefix(PDF pdf)
1687 static char name_str[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
1688 static char prefix[7]; /* make a tag of 6 chars long */
1689 short i;
1690 size_t base = strlen(name_str);
1691 unsigned long crc = crc32(0L, Z_NULL, 0);
1692 crc = crc32(crc, (Bytef *) pdf->job_id_string, (uInt) strlen(pdf->job_id_string));
1693 for (i = 0; i < 6; i++) {
1694 prefix[i] = name_str[crc % base];
1695 crc /= base;
1697 prefix[6] = '\0';
1698 return prefix;
1701 @ @c
1702 void pdf_begin_page(PDF pdf)
1704 int xform_attributes;
1705 int xform_type = 0;
1706 scaled form_margin = pdf_xform_margin; /* was one_bp until SVN4066 */
1707 ensure_output_state(pdf, ST_HEADER_WRITTEN);
1708 init_pdf_pagecalculations(pdf);
1709 if (pdf->page_resources == NULL) {
1710 pdf->page_resources = xtalloc(1, pdf_resource_struct);
1711 pdf->page_resources->resources_tree = NULL;
1713 pdf->page_resources->last_resources = pdf_create_obj(pdf, obj_type_others, 0);
1714 reset_page_resources(pdf);
1716 if (global_shipping_mode == SHIPPING_PAGE) {
1717 pdf->last_page = pdf_get_obj(pdf, obj_type_page, total_pages + 1, 0);
1718 set_obj_aux(pdf, pdf->last_page, 1); /* mark that this page has been created */
1719 pdf->last_stream = pdf_create_obj(pdf, obj_type_pagestream, 0);
1720 pdf_begin_obj(pdf, pdf->last_stream, OBJSTM_NEVER);
1721 pdf->last_thread = null;
1722 pdf_begin_dict(pdf);
1723 } else {
1724 xform_type = obj_xform_type(pdf, pdf_cur_form) ;
1725 pdf_begin_obj(pdf, pdf_cur_form, OBJSTM_NEVER);
1726 pdf->last_stream = pdf_cur_form;
1727 /* Write out Form stream header */
1728 pdf_begin_dict(pdf);
1729 if (xform_type == 0) {
1730 pdf_dict_add_name(pdf, "Type", "XObject");
1731 pdf_dict_add_name(pdf, "Subtype", "Form");
1732 pdf_dict_add_int(pdf, "FormType", 1);
1734 xform_attributes = pdf_xform_attr; /* lookup once */
1735 if (xform_attributes != null)
1736 pdf_print_toks(pdf, xform_attributes);
1737 if (obj_xform_attr(pdf, pdf_cur_form) != null) {
1738 pdf_print_toks(pdf, obj_xform_attr(pdf, pdf_cur_form));
1739 delete_token_ref(obj_xform_attr(pdf, pdf_cur_form));
1740 set_obj_xform_attr(pdf, pdf_cur_form, null);
1742 if (obj_xform_attr_str(pdf, pdf_cur_form) != null) {
1743 lua_pdf_literal(pdf, obj_xform_attr_str(pdf, pdf_cur_form));
1744 luaL_unref(Luas, LUA_REGISTRYINDEX, obj_xform_attr_str(pdf, pdf_cur_form));
1745 set_obj_xform_attr_str(pdf, pdf_cur_form, null);
1747 if (xform_type == 0 || xform_type == 1 || xform_type == 3) {
1748 pdf_add_name(pdf, "BBox");
1749 pdf_begin_array(pdf);
1750 pdf_add_bp(pdf, -form_margin);
1751 pdf_add_bp(pdf, -form_margin);
1752 pdf_add_bp(pdf, pdf->page_size.h + form_margin);
1753 pdf_add_bp(pdf, pdf->page_size.v + form_margin);
1754 pdf_end_array(pdf);
1756 if (xform_type == 0 || xform_type == 2 || xform_type == 3) {
1757 pdf_add_name(pdf, "Matrix");
1758 pdf_begin_array(pdf);
1759 pdf_add_int(pdf, 1);
1760 pdf_add_int(pdf, 0);
1761 pdf_add_int(pdf, 0);
1762 pdf_add_int(pdf, 1);
1763 pdf_add_int(pdf, 0);
1764 pdf_add_int(pdf, 0);
1765 pdf_end_array(pdf);
1767 pdf_dict_add_ref(pdf, "Resources", pdf->page_resources->last_resources);
1769 /* Start stream of page/form contents */
1770 pdf_dict_add_streaminfo(pdf);
1771 pdf_end_dict(pdf);
1772 pdf_begin_stream(pdf);
1773 pos_stack_used = 0; /* start with empty stack */
1774 if (global_shipping_mode == SHIPPING_PAGE) {
1775 colorstackpagestart();
1777 if (global_shipping_mode == SHIPPING_PAGE)
1778 pdf_out_colorstack_startpage(pdf);
1781 @ @c
1782 void print_pdf_table_string(PDF pdf, const char *s)
1784 size_t len;
1785 const char *ls;
1786 lua_rawgeti(Luas, LUA_REGISTRYINDEX, lua_key_index(pdf_data));
1787 lua_rawget(Luas, LUA_REGISTRYINDEX);
1788 lua_pushstring(Luas, s); /* s t ... */
1789 lua_rawget(Luas, -2); /* s? t ... */
1790 if (lua_type(Luas, -1) == LUA_TSTRING) { /* s t ... */
1791 ls = lua_tolstring(Luas, -1, &len);
1792 if (len > 0) {
1793 if (pdf->cave == 1)
1794 pdf_out(pdf, ' ');
1795 pdf_out_block(pdf, ls, len);
1796 pdf->cave = 1;
1799 lua_pop(Luas, 2);
1802 @ @c
1803 const char *get_pdf_table_string(const char *s)
1805 const_lstring ls;
1806 lua_rawgeti(Luas, LUA_REGISTRYINDEX, lua_key_index(pdf_data));
1807 lua_rawget(Luas, LUA_REGISTRYINDEX);
1808 lua_pushstring(Luas, s); /* s t ... */
1809 lua_rawget(Luas, -2); /* s? t ... */
1810 if (lua_type(Luas, -1) == LUA_TSTRING) { /* s t ... */
1811 ls.s = lua_tolstring(Luas, -1, &ls.l);
1813 s is supposed to be anchored (e.g in the registry)
1814 so it's not garbage collected
1816 lua_pop(Luas, 2);
1817 return ls.s;
1819 lua_pop(Luas, 2);
1820 return NULL ;
1823 @ @c
1824 void pdf_end_page(PDF pdf)
1826 char s[64], *p;
1827 int j, annots = 0, beads = 0, callback_id;
1828 pdf_resource_struct *res_p = pdf->page_resources;
1829 pdf_resource_struct local_page_resources;
1830 pdf_object_list *annot_list, *bead_list, *link_list, *ol, *ol1;
1831 scaledpos save_cur_page_size; /* to save |pdf->page_size| during flushing pending forms */
1832 shipping_mode_e save_shipping_mode;
1833 int xform_resources;
1834 int page_resources, page_attributes;
1835 int procset = PROCSET_PDF;
1836 /* Finish stream of page/form contents */
1837 pdf_goto_pagemode(pdf);
1838 if (pos_stack_used > 0) {
1839 formatted_error("pdf backend","%u unmatched 'save' after %s shipout", (unsigned int) pos_stack_used,
1840 ((global_shipping_mode == SHIPPING_PAGE) ? "page" : "form"));
1842 pdf_end_stream(pdf);
1843 pdf_end_obj(pdf);
1844 callback_id = callback_defined(finish_pdfpage_callback);
1845 if (callback_id > 0)
1846 run_callback(callback_id, "b->",(global_shipping_mode == SHIPPING_PAGE));
1847 if (global_shipping_mode == SHIPPING_PAGE) {
1848 pdf->last_pages = pdf_do_page_divert(pdf, pdf->last_page, 0);
1849 /* Write out /Page object */
1850 pdf_begin_obj(pdf, pdf->last_page, OBJSTM_ALWAYS);
1851 pdf_begin_dict(pdf);
1852 pdf_dict_add_name(pdf, "Type", "Page");
1853 pdf_dict_add_ref(pdf, "Contents", pdf->last_stream);
1854 pdf_dict_add_ref(pdf, "Resources", res_p->last_resources);
1855 pdf_add_name(pdf, "MediaBox");
1856 pdf_begin_array(pdf);
1857 pdf_add_int(pdf, 0);
1858 pdf_add_int(pdf, 0);
1859 pdf_add_bp(pdf, pdf->page_size.h);
1860 pdf_add_bp(pdf, pdf->page_size.v);
1861 pdf_end_array(pdf);
1862 page_attributes = pdf_page_attr ; /* lookup once */
1863 if (page_attributes != null)
1864 pdf_print_toks(pdf, page_attributes);
1865 print_pdf_table_string(pdf, "pageattributes");
1866 pdf_dict_add_ref(pdf, "Parent", pdf->last_pages);
1867 if (pdf->img_page_group_val != 0) {
1868 pdf_dict_add_ref(pdf, "Group", pdf->img_page_group_val);
1870 annot_list = get_page_resources_list(pdf, obj_type_annot);
1871 link_list = get_page_resources_list(pdf, obj_type_link);
1872 if (annot_list != NULL || link_list != NULL) {
1873 annots = pdf_create_obj(pdf, obj_type_annots, 0);
1874 pdf_dict_add_ref(pdf, "Annots", annots);
1876 bead_list = get_page_resources_list(pdf, obj_type_bead);
1877 if (bead_list != NULL) {
1878 beads = pdf_create_obj(pdf, obj_type_beads, 0);
1879 pdf_dict_add_ref(pdf, "B", beads);
1881 pdf_end_dict(pdf);
1882 pdf_end_obj(pdf);
1883 pdf->img_page_group_val = 0;
1884 /* Generate array of annotations or beads in page */
1885 if (annot_list != NULL || link_list != NULL) {
1886 pdf_begin_obj(pdf, annots, OBJSTM_ALWAYS);
1887 pdf_begin_array(pdf);
1888 while (annot_list != NULL) {
1889 pdf_add_ref(pdf, annot_list->info);
1890 annot_list = annot_list->link;
1892 while (link_list != NULL) {
1893 pdf_add_ref(pdf, link_list->info);
1894 link_list = link_list->link;
1896 pdf_end_array(pdf);
1897 pdf_end_obj(pdf);
1899 if (bead_list != NULL) {
1900 pdf_begin_obj(pdf, beads, OBJSTM_ALWAYS);
1901 pdf_begin_array(pdf);
1902 while (bead_list != NULL) {
1903 pdf_add_ref(pdf, bead_list->info);
1904 bead_list = bead_list->link;
1906 pdf_end_array(pdf);
1907 pdf_end_obj(pdf);
1910 /* Write out resource lists and pending raw objects */
1911 ol = get_page_resources_list(pdf, obj_type_obj);
1912 while (ol != NULL) {
1913 if (!is_obj_written(pdf, ol->info))
1914 pdf_write_obj(pdf, ol->info);
1915 ol = ol->link;
1919 When flushing pending forms we need to save and restore resource lists
1920 which are also used by page shipping. Saving and restoring
1921 |pdf->page_size| is needed for proper writing out pending PDF marks.
1923 ol = get_page_resources_list(pdf, obj_type_xform);
1924 while (ol != NULL) {
1925 if (!is_obj_written(pdf, ol->info)) {
1926 pdf_cur_form = ol->info;
1927 save_cur_page_size = pdf->page_size;
1928 save_shipping_mode = global_shipping_mode;
1929 pdf->page_resources = &local_page_resources;
1930 local_page_resources.resources_tree = NULL;
1931 ship_out(pdf, obj_xform_box(pdf, pdf_cur_form), SHIPPING_FORM);
1932 /* Restore page size and page resources */
1933 pdf->page_size = save_cur_page_size;
1934 global_shipping_mode = save_shipping_mode;
1935 destroy_page_resources_tree(pdf);
1936 pdf->page_resources = res_p;
1938 ol = ol->link;
1940 /* Write out pending images */
1941 ol = get_page_resources_list(pdf, obj_type_ximage);
1942 while (ol != NULL) {
1943 if (!is_obj_written(pdf, ol->info))
1944 pdf_write_image(pdf, ol->info);
1945 ol = ol->link;
1947 if (global_shipping_mode == SHIPPING_PAGE) {
1948 /* Write out pending PDF marks and annotations */
1949 ol = get_page_resources_list(pdf, obj_type_annot);
1950 while (ol != NULL) {
1951 if (ol->info > 0 && obj_type(pdf, ol->info) == obj_type_annot) {
1952 j = obj_annot_ptr(pdf, ol->info); /* |j| points to |pdf_annot_node| */
1953 pdf_begin_obj(pdf, ol->info, OBJSTM_ALWAYS);
1954 pdf_begin_dict(pdf);
1955 pdf_dict_add_name(pdf, "Type", "Annot");
1956 pdf_print_toks(pdf, pdf_annot_data(j));
1957 pdf_rectangle(pdf, j);
1958 pdf_end_dict(pdf);
1959 pdf_end_obj(pdf);
1961 ol = ol->link;
1963 /* Write out PDF link annotations */
1964 if ((ol = get_page_resources_list(pdf, obj_type_link)) != NULL) {
1965 while (ol != NULL) {
1966 j = obj_annot_ptr(pdf, ol->info);
1967 pdf_begin_obj(pdf, ol->info, OBJSTM_ALWAYS);
1968 pdf_begin_dict(pdf);
1969 pdf_dict_add_name(pdf, "Type", "Annot");
1970 if (pdf_action_type(pdf_link_action(j)) != pdf_action_user)
1971 pdf_dict_add_name(pdf, "Subtype", "Link");
1972 if (pdf_link_attr(j) != null)
1973 pdf_print_toks(pdf, pdf_link_attr(j));
1974 pdf_rectangle(pdf, j);
1975 if (pdf_action_type(pdf_link_action(j)) != pdf_action_user)
1976 pdf_puts(pdf, "/A ");
1977 write_action(pdf, pdf_link_action(j));
1978 pdf_end_dict(pdf);
1979 pdf_end_obj(pdf);
1980 ol = ol->link;
1982 /* Flush |pdf_start_link_node|'s created by |append_link| */
1983 ol = get_page_resources_list(pdf, obj_type_link);
1984 while (ol != NULL) {
1985 j = obj_annot_ptr(pdf, ol->info);
1987 nodes with |subtype = pdf_link_data_node| were created by |append_link| and
1988 must be flushed here, as they are not linked in any list
1990 if (subtype(j) == pdf_link_data_node)
1991 flush_node(j);
1992 ol = ol->link;
1995 /* Write out PDF mark destinations */
1996 write_out_pdf_mark_destinations(pdf);
1997 /* Write out PDF bead rectangle specifications */
1998 print_bead_rectangles(pdf);
2000 /* Write out resources dictionary */
2001 pdf_begin_obj(pdf, res_p->last_resources, OBJSTM_ALWAYS);
2002 pdf_begin_dict(pdf);
2003 /* Print additional resources */
2004 if (global_shipping_mode == SHIPPING_PAGE) {
2005 page_resources = pdf_page_resources; /* lookup once */
2006 if (page_resources != null)
2007 pdf_print_toks(pdf, page_resources);
2008 print_pdf_table_string(pdf, "pageresources");
2009 } else {
2010 xform_resources = pdf_xform_resources; /* lookup once */
2011 if (xform_resources != null)
2012 pdf_print_toks(pdf, xform_resources);
2013 if (obj_xform_resources(pdf, pdf_cur_form) != null) {
2014 pdf_print_toks(pdf, obj_xform_resources(pdf, pdf_cur_form));
2015 delete_token_ref(obj_xform_resources(pdf, pdf_cur_form));
2016 set_obj_xform_resources(pdf, pdf_cur_form, null);
2018 if (obj_xform_resources_str(pdf, pdf_cur_form) != null) {
2019 lua_pdf_literal(pdf, obj_xform_resources_str(pdf, pdf_cur_form));
2020 luaL_unref(Luas, LUA_REGISTRYINDEX, obj_xform_resources_str(pdf, pdf_cur_form));
2021 set_obj_xform_resources_str(pdf, pdf_cur_form, null);
2024 /* Generate font resources */
2025 if ((ol = get_page_resources_list(pdf, obj_type_font)) != NULL) {
2026 pdf_add_name(pdf, "Font");
2027 pdf_begin_dict(pdf);
2028 while (ol != NULL) {
2029 p = s;
2030 p += snprintf(p, 20, "F%i", obj_info(pdf, ol->info));
2031 if (pdf->resname_prefix != NULL)
2032 p += snprintf(p, 20, "%s", pdf->resname_prefix);
2033 pdf_dict_add_ref(pdf, s, ol->info);
2034 ol = ol->link;
2036 pdf_end_dict(pdf);
2037 procset |= PROCSET_TEXT;
2039 /* Generate XObject resources */
2040 ol = get_page_resources_list(pdf, obj_type_xform);
2041 ol1 = get_page_resources_list(pdf, obj_type_ximage);
2042 if (ol != NULL || ol1 != NULL) {
2043 pdf_add_name(pdf, "XObject");
2044 pdf_begin_dict(pdf);
2045 while (ol != NULL) {
2046 p = s;
2047 p += snprintf(p, 20, "Fm%i", obj_info(pdf, ol->info));
2048 if (pdf->resname_prefix != NULL)
2049 p += snprintf(p, 20, "%s", pdf->resname_prefix);
2050 pdf_dict_add_ref(pdf, s, ol->info);
2051 ol = ol->link;
2053 while (ol1 != null) {
2054 p = s;
2055 p += snprintf(p, 20, "Im%i", obj_info(pdf, ol1->info));
2056 if (pdf->resname_prefix != NULL)
2057 p += snprintf(p, 20, "%s", pdf->resname_prefix);
2058 pdf_dict_add_ref(pdf, s, ol1->info);
2059 procset |= img_procset(idict_array[obj_data_ptr(pdf, ol1->info)]);
2060 ol1 = ol1->link;
2062 pdf_end_dict(pdf);
2064 /* Generate ProcSet */
2065 pdf_add_name(pdf, "ProcSet");
2066 pdf_begin_array(pdf);
2067 if ((procset & PROCSET_PDF) != 0)
2068 pdf_add_name(pdf, "PDF");
2069 if ((procset & PROCSET_TEXT) != 0)
2070 pdf_add_name(pdf, "Text");
2071 if ((procset & PROCSET_IMAGE_B) != 0)
2072 pdf_add_name(pdf, "ImageB");
2073 if ((procset & PROCSET_IMAGE_C) != 0)
2074 pdf_add_name(pdf, "ImageC");
2075 if ((procset & PROCSET_IMAGE_I) != 0)
2076 pdf_add_name(pdf, "ImageI");
2077 pdf_end_array(pdf);
2078 pdf_end_dict(pdf);
2079 pdf_end_obj(pdf);
2082 @* Finishing the PDF output file.
2084 @ Destinations that have been referenced but don't exists have
2085 |obj_dest_ptr=null|. Leaving them undefined might cause troubles for PDF
2086 browsers, so we need to fix them; they point to the last page.
2089 static void check_nonexisting_destinations(PDF pdf)
2091 int k;
2092 for (k = pdf->head_tab[obj_type_dest]; k != 0; k = obj_link(pdf, k)) {
2093 if (obj_dest_ptr(pdf, k) == null) {
2094 if (obj_info(pdf, k) < 0) {
2095 char *ss = makecstring(-obj_info(pdf, k));
2096 formatted_warning("pdf backend", "unreferenced destination with name '%s'",ss);
2097 } else {
2098 formatted_warning("pdf backend", "unreferenced destination with num '%d'",obj_info(pdf,k));
2101 pdf_begin_obj(pdf, k, OBJSTM_ALWAYS);
2102 pdf_begin_array(pdf);
2103 pdf_add_ref(pdf, pdf->last_page);
2104 pdf_add_name(pdf, "Fit");
2105 pdf_end_array(pdf);
2106 pdf_end_obj(pdf);
2111 @ @c
2112 static void check_nonexisting_pages(PDF pdf)
2114 struct avl_traverser t;
2115 oentry *p;
2116 struct avl_table *page_tree = pdf->obj_tree[obj_type_page];
2117 avl_t_init(&t, page_tree);
2118 /* search from the end backward until the last real page is found */
2119 for (p = avl_t_last(&t, page_tree); p != NULL && obj_aux(pdf, p->objptr) == 0; p = avl_t_prev(&t)) {
2120 formatted_warning("pdf backend", "page %d has been referenced but does not exist",obj_info(pdf, p->objptr));
2124 @ If the same keys in a dictionary are given several times, then it is not
2125 defined which value is choosen by an application. Therefore the keys |/Producer|
2126 and |/Creator| are only set if the token list |pdf_info_toks| converted to a
2127 string does not contain these key strings.
2130 static boolean substr_of_str(const char *s, const char *t)
2132 if (strstr(t, s) == NULL)
2133 return false;
2134 return true;
2137 static int pdf_print_info(PDF pdf, int luatexversion,
2138 str_number luatexrevision)
2139 { /* print info object */
2140 boolean creator_given = false;
2141 boolean producer_given = false;
2142 boolean creationdate_given = false;
2143 boolean moddate_given = false;
2144 boolean trapped_given = false;
2145 char *s = NULL;
2146 const char *p = NULL;
2147 int k, len = 0;
2148 k = pdf_create_obj(pdf, obj_type_info, 0);
2149 pdf_begin_obj(pdf, k, 3); /* keep Info readable unless explicitely forced */
2150 pdf_begin_dict(pdf);
2151 if (pdf_info_toks != 0) {
2152 s = tokenlist_to_cstring(pdf_info_toks, true, &len);
2153 creator_given = substr_of_str("/Creator", s);
2154 producer_given = substr_of_str("/Producer", s);
2155 creationdate_given = substr_of_str("/CreationDate", s);
2156 moddate_given = substr_of_str("/ModDate", s);
2157 trapped_given = substr_of_str("/Trapped", s);
2159 p = get_pdf_table_string("info");
2160 if (p && strlen(p) > 0) {
2161 creator_given = creator_given || substr_of_str("/Creator", p);
2162 producer_given = producer_given || substr_of_str("/Producer", p);
2163 creationdate_given = creationdate_given || substr_of_str("/CreationDate", p);
2164 moddate_given = moddate_given || substr_of_str("/ModDate", p);
2165 trapped_given = trapped_given || substr_of_str("/Trapped", p);
2167 if (pdf_info_toks != null) {
2168 if (len > 0) {
2169 pdf_out(pdf, '\n');
2170 pdf_puts(pdf, s);
2171 pdf_out(pdf, '\n');
2172 xfree(s);
2174 delete_token_ref(pdf_info_toks);
2175 pdf_info_toks = null;
2177 if (p && strlen(p) > 0) {
2178 pdf_out(pdf, '\n');
2179 pdf_puts(pdf, p); /* no free, pointer */
2180 pdf_out(pdf, '\n');
2182 if ((pdf_suppress_optional_info & 128) == 0 && !producer_given) {
2183 pdf_add_name(pdf, "Producer");
2184 pdf_puts(pdf, " (LuaTeX-");
2185 pdf_print_int(pdf, luatexversion / 100);
2186 pdf_out(pdf, '.');
2187 pdf_print_int(pdf, luatexversion % 100);
2188 pdf_out(pdf, '.');
2189 pdf_print(pdf, luatexrevision);
2190 pdf_out(pdf, ')');
2192 if ((pdf_suppress_optional_info & 16) == 0 && !creator_given) {
2193 pdf_dict_add_string(pdf, "Creator", "TeX");
2195 if ((pdf_suppress_optional_info & 32) == 0 && !creationdate_given) {
2196 initialize_start_time(pdf);
2197 pdf_dict_add_string(pdf, "CreationDate", pdf->start_time_str);
2199 if ((pdf_suppress_optional_info & 64) == 0 && !moddate_given) {
2200 initialize_start_time(pdf);
2201 pdf_dict_add_string(pdf, "ModDate", pdf->start_time_str);
2203 if ((pdf_suppress_optional_info & 256) == 0 && !trapped_given) {
2204 pdf_dict_add_name(pdf, "Trapped", "False");
2206 if ((pdf_suppress_optional_info & 1) == 0) {
2207 pdf_dict_add_string(pdf, "PTEX.FullBanner", luatex_banner);
2209 pdf_end_dict(pdf);
2210 pdf_end_obj(pdf);
2211 return k;
2214 static void build_free_object_list(PDF pdf)
2216 int k;
2217 int l = 0;
2218 set_obj_fresh(pdf, l); /* null object at begin of list of free objects */
2219 for (k = 1; k <= pdf->obj_ptr; k++) {
2220 if (!is_obj_written(pdf, k)) {
2221 set_obj_link(pdf, l, k);
2222 l = k;
2225 set_obj_link(pdf, l, 0);
2228 @ Now the finish of PDF output file. At this moment all Page objects
2229 are already written completely to PDF output file.
2232 void finish_pdf_file(PDF pdf, int luatexversion, str_number luatexrevision)
2234 int i, j, k;
2235 int root, info, xref_stm = 0, outlines, threads, names_tree;
2236 size_t xref_offset_width;
2237 int callback_id = callback_defined(stop_run_callback);
2238 int callback_id1 = callback_defined(finish_pdffile_callback);
2239 if (total_pages == 0) {
2240 if (callback_id == 0) {
2241 normal_warning("pdf backend","no pages of output.");
2242 } else if (callback_id > 0) {
2243 run_callback(callback_id, "->");
2245 if (pdf->gone > 0)
2246 normal_error("pdf backend","dangling objects discarded, no output file produced.");
2247 } else {
2248 if (pdf->draftmode == 0) {
2249 pdf_flush(pdf); /* to make sure that the output file name has been already created */
2250 flush_jbig2_page0_objects(pdf); /* flush page 0 objects from JBIG2 images, if any */
2251 if (callback_id1 > 0)
2252 run_callback(callback_id1, "->");
2253 check_nonexisting_pages(pdf);
2254 check_nonexisting_destinations(pdf);
2255 /* Output fonts definition */
2256 for (k = 1; k <= max_font_id(); k++) {
2257 if (font_used(k) && (pdf_font_num(k) < 0)) {
2258 i = -pdf_font_num(k);
2259 for (j = font_bc(k); j <= font_ec(k); j++)
2260 if (quick_char_exists(k, j) && pdf_char_marked(k, j))
2261 pdf_mark_char(i, j);
2262 if ((pdf_font_attr(i) == 0) && (pdf_font_attr(k) != 0)) {
2263 set_pdf_font_attr(i, pdf_font_attr(k));
2264 } else if ((pdf_font_attr(k) == 0) && (pdf_font_attr(i) != 0)) {
2265 set_pdf_font_attr(k, pdf_font_attr(i));
2266 } else if ((pdf_font_attr(i) != 0) && (pdf_font_attr(k) != 0) && (!str_eq_str(pdf_font_attr(i), pdf_font_attr(k)))) {
2267 formatted_warning("pdf backend","fontattr of font %d and %d are conflicting, %k is used",i,k,i);
2271 pdf->gen_tounicode = pdf_gen_tounicode;
2272 pdf->omit_cidset = pdf_omit_cidset;
2273 k = pdf->head_tab[obj_type_font];
2274 while (k != 0) {
2275 int f = obj_info(pdf, k);
2276 do_pdf_font(pdf, f);
2277 k = obj_link(pdf, k);
2279 write_fontstuff(pdf);
2280 pdf->last_pages = output_pages_tree(pdf);
2281 /* Output outlines */
2282 outlines = print_outlines(pdf);
2284 Output name tree. The name tree is very similiar to Pages tree so
2285 its construction should be certain from Pages tree construction.
2286 For intermediate node |obj_info| will be the first name and
2287 |obj_link| will be the last name in \.{\\Limits} array. Note that
2288 |pdf_dest_names_ptr| will be less than |obj_ptr|, so we test if
2289 |k < pdf_dest_names_ptr| then |k| is index of leaf in
2290 |dest_names|; else |k| will be index in |obj_tab| of some
2291 intermediate node.
2293 names_tree = output_name_tree(pdf);
2295 /* Output article threads */
2296 if (pdf->head_tab[obj_type_thread] != 0) {
2297 threads = pdf_create_obj(pdf, obj_type_others, 0);
2298 pdf_begin_obj(pdf, threads, OBJSTM_ALWAYS);
2299 pdf_begin_array(pdf);
2300 k = pdf->head_tab[obj_type_thread];
2301 while (k != 0) {
2302 pdf_add_ref(pdf, k);
2303 k = obj_link(pdf, k);
2305 pdf_end_array(pdf);
2306 pdf_end_obj(pdf);
2307 k = pdf->head_tab[obj_type_thread];
2308 while (k != 0) {
2309 out_thread(pdf, k);
2310 k = obj_link(pdf, k);
2312 } else {
2313 threads = 0;
2315 /* Output the /Catalog object */
2316 root = pdf_create_obj(pdf, obj_type_catalog, 0);
2317 pdf_begin_obj(pdf, root, OBJSTM_ALWAYS);
2318 pdf_begin_dict(pdf);
2319 pdf_dict_add_name(pdf, "Type", "Catalog");
2320 pdf_dict_add_ref(pdf, "Pages", pdf->last_pages);
2321 if (threads != 0)
2322 pdf_dict_add_ref(pdf, "Threads", threads);
2323 if (outlines != 0)
2324 pdf_dict_add_ref(pdf, "Outlines", outlines);
2325 if (names_tree != 0)
2326 pdf_dict_add_ref(pdf, "Names", names_tree);
2327 if (pdf_catalog_toks != null) {
2328 pdf_print_toks(pdf, pdf_catalog_toks);
2329 delete_token_ref(pdf_catalog_toks);
2330 pdf_catalog_toks = null;
2332 print_pdf_table_string(pdf, "catalog");
2333 if (pdf_catalog_openaction != 0)
2334 pdf_dict_add_ref(pdf, "OpenAction", pdf_catalog_openaction);
2335 pdf_end_dict(pdf);
2336 pdf_end_obj(pdf);
2337 /* last candidate for object stream */
2338 info = pdf_print_info(pdf, luatexversion, luatexrevision);
2339 /* final object for pdf->os_enable == false */
2340 if (pdf->os_enable) {
2341 pdf_buffer_select(pdf, OBJSTM_BUF);
2342 pdf_os_write_objstream(pdf);
2343 pdf_flush(pdf);
2344 pdf_buffer_select(pdf, PDFOUT_BUF);
2345 /* Output the cross-reference stream dictionary */
2346 xref_stm = pdf_create_obj(pdf, obj_type_others, 0);
2347 pdf_begin_obj(pdf, xref_stm, OBJSTM_NEVER); /* final object for pdf->os_enable == true */
2348 if ((obj_offset(pdf, pdf->obj_ptr) / 256) > 16777215)
2349 xref_offset_width = 5;
2350 else if (obj_offset(pdf, pdf->obj_ptr) > 16777215)
2351 xref_offset_width = 4;
2352 else if (obj_offset(pdf, pdf->obj_ptr) > 65535)
2353 xref_offset_width = 3;
2354 else
2355 xref_offset_width = 2;
2356 /* Build a linked list of free objects */
2357 build_free_object_list(pdf);
2358 pdf_begin_dict(pdf);
2359 pdf_dict_add_name(pdf, "Type", "XRef");
2360 pdf_add_name(pdf, "Index");
2361 pdf_begin_array(pdf);
2362 pdf_add_int(pdf, 0);
2363 pdf_add_int(pdf, pdf->obj_ptr + 1);
2364 pdf_end_array(pdf);
2365 pdf_dict_add_int(pdf, "Size", pdf->obj_ptr + 1);
2366 pdf_add_name(pdf, "W");
2367 pdf_begin_array(pdf);
2368 pdf_add_int(pdf, 1);
2369 pdf_add_int(pdf, (int) xref_offset_width);
2370 pdf_add_int(pdf, 1);
2371 pdf_end_array(pdf);
2372 pdf_dict_add_ref(pdf, "Root", root);
2373 pdf_dict_add_ref(pdf, "Info", info);
2374 if (pdf_trailer_toks != null) {
2375 pdf_print_toks(pdf, pdf_trailer_toks);
2376 delete_token_ref(pdf_trailer_toks);
2377 pdf_trailer_toks = null;
2379 print_pdf_table_string(pdf, "trailer");
2380 print_ID(pdf);
2381 pdf_dict_add_streaminfo(pdf);
2382 pdf_end_dict(pdf);
2383 pdf_begin_stream(pdf);
2384 for (k = 0; k <= pdf->obj_ptr; k++) {
2385 if (!is_obj_written(pdf, k)) { /* a free object */
2386 pdf_out(pdf, 0);
2387 pdf_out_bytes(pdf, obj_link(pdf, k), xref_offset_width);
2388 pdf_out(pdf, 255);
2389 } else if (obj_os_idx(pdf, k) == PDF_OS_MAX_OBJS) { /* object not in object stream */
2390 pdf_out(pdf, 1);
2391 pdf_out_bytes(pdf, obj_offset(pdf, k),
2392 xref_offset_width);
2393 pdf_out(pdf, 0);
2394 } else { /* object in object stream */
2395 pdf_out(pdf, 2);
2396 pdf_out_bytes(pdf, obj_offset(pdf, k),
2397 xref_offset_width);
2398 pdf_out(pdf, obj_os_idx(pdf, k));
2401 pdf_end_stream(pdf);
2402 pdf_end_obj(pdf);
2403 pdf_flush(pdf);
2404 } else {
2405 /* Output the |obj_tab| and build a linked list of free objects */
2406 build_free_object_list(pdf);
2407 pdf_save_offset(pdf);
2408 pdf_puts(pdf, "xref\n");
2409 pdf_puts(pdf, "0 ");
2410 pdf_print_int_ln(pdf, pdf->obj_ptr + 1);
2411 pdf_print_fw_int(pdf, obj_link(pdf, 0));
2412 pdf_puts(pdf, " 65535 f \n");
2413 for (k = 1; k <= pdf->obj_ptr; k++) {
2414 if (!is_obj_written(pdf, k)) {
2415 pdf_print_fw_int(pdf, obj_link(pdf, k));
2416 pdf_puts(pdf, " 00000 f \n");
2417 } else {
2418 pdf_print_fw_int(pdf, obj_offset(pdf, k));
2419 pdf_puts(pdf, " 00000 n \n");
2423 /* Output the trailer */
2424 if (!pdf->os_enable) {
2425 pdf_puts(pdf, "trailer\n");
2426 pdf_begin_dict(pdf);
2427 pdf_dict_add_int(pdf, "Size", pdf->obj_ptr + 1);
2428 pdf_dict_add_ref(pdf, "Root", root);
2429 pdf_dict_add_ref(pdf, "Info", info);
2430 if (pdf_trailer_toks != null) {
2431 pdf_print_toks(pdf, pdf_trailer_toks);
2432 delete_token_ref(pdf_trailer_toks);
2433 pdf_trailer_toks = null;
2435 print_ID(pdf);
2436 pdf_end_dict(pdf);
2437 pdf_out(pdf, '\n');
2439 pdf_puts(pdf, "startxref\n");
2440 pdf->cave = 0;
2441 if (pdf->os_enable)
2442 pdf_add_longint(pdf, (longinteger) obj_offset(pdf, xref_stm));
2443 else
2444 pdf_add_longint(pdf, (longinteger) pdf->save_offset);
2445 pdf_puts(pdf, "\n%%EOF\n");
2446 pdf_flush(pdf);
2447 if (callback_id == 0) {
2448 tprint_nl("Output written on ");
2449 tprint(pdf->file_name);
2450 tprint(" (");
2451 print_int(total_pages);
2452 tprint(" page");
2453 if (total_pages != 1)
2454 print_char('s');
2455 tprint(", ");
2456 print_int(pdf_offset(pdf));
2457 tprint(" bytes).");
2458 print_ln();
2459 } else if (callback_id > 0) {
2460 run_callback(callback_id, "->");
2462 } else {
2463 if (callback_id > 0) {
2464 run_callback(callback_id, "->");
2467 libpdffinish(pdf);
2468 if (pdf->draftmode == 0)
2469 close_file(pdf->file);
2470 else
2471 normal_warning("pdf backend","draftmode enabled, not changing output pdf");
2473 if (callback_id == 0) {
2474 if (log_opened_global) {
2475 fprintf(log_file, "\nPDF statistics: %d PDF objects out of %d (max. %d)\n",
2476 (int) pdf->obj_ptr, (int) pdf->obj_tab_size,
2477 (int) sup_obj_tab_size);
2478 if (pdf->os->ostm_ctr > 0) {
2479 fprintf(log_file, " %d compressed objects within %d object stream%s\n",
2480 (int) pdf->os->o_ctr, (int) pdf->os->ostm_ctr,
2481 (pdf->os->ostm_ctr > 1 ? "s" : ""));
2483 fprintf(log_file, " %d named destinations out of %d (max. %d)\n",
2484 (int) pdf->dest_names_ptr, (int) pdf->dest_names_size,
2485 (int) sup_dest_names_size);
2486 fprintf(log_file, " %d words of extra memory for PDF output out of %d (max. %d)\n",
2487 (int) pdf->mem_ptr, (int) pdf->mem_size,
2488 (int) sup_pdf_mem_size);
2493 @ @c
2494 void scan_pdfcatalog(PDF pdf)
2496 halfword p;
2497 scan_toks(false, true);
2498 pdf_catalog_toks = concat_tokens(pdf_catalog_toks, def_ref);
2499 if (scan_keyword("openaction")) {
2500 if (pdf_catalog_openaction != 0) {
2501 normal_error("pdf backend", "duplicate of openaction");
2502 } else {
2503 check_o_mode(pdf, "catalog", 1 << OMODE_PDF, true);
2504 p = scan_action(pdf);
2505 pdf_catalog_openaction = pdf_create_obj(pdf, obj_type_others, 0);
2506 pdf_begin_obj(pdf, pdf_catalog_openaction, OBJSTM_ALWAYS);
2507 write_action(pdf, p);
2508 pdf_end_obj(pdf);
2509 delete_action_ref(p);