1% pdfgen.w 2% 3% Copyright 2009-2013 Taco Hoekwater <taco@@luatex.org> 4% 5% This file is part of LuaTeX. 6% 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. 11% 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. 16% 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/>. 19 20@ @c 21 22 23#include "ptexlib.h" 24 25@ @c 26#include <kpathsea/c-dir.h> 27#include <kpathsea/c-ctype.h> 28#include "lua/luatex-api.h" 29#include "md5.h" 30 31#define is_hex_char isxdigit 32 33#define check_nprintf(size_get, size_want) \ 34 if ((unsigned)(size_get) >= (unsigned)(size_want)) \ 35 luatex_fail ("snprintf failed: file %s, line %d", __FILE__, __LINE__); 36 37PDF static_pdf = NULL; 38 39@ commandline interface 40@c 41int pdf_output_option; 42int pdf_output_value; 43int pdf_draftmode_option; 44int pdf_draftmode_value; 45 46halfword pdf_info_toks; /* additional keys of Info dictionary */ 47halfword pdf_catalog_toks; /* additional keys of Catalog dictionary */ 48halfword pdf_catalog_openaction; 49halfword pdf_names_toks; /* additional keys of Names dictionary */ 50halfword pdf_trailer_toks; /* additional keys of Trailer dictionary */ 51shipping_mode_e global_shipping_mode = NOT_SHIPPING; /* set to |shipping_mode| when |ship_out| starts */ 52 53@ Create a new buffer |strbuf_s| of size |size| and maximum allowed size |limit|. 54Initialize it and set |p| to begin of data. 55@c 56strbuf_s *new_strbuf(size_t size, size_t limit) 57{ 58 strbuf_s *b; 59 assert(limit >= size); 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; 68} 69 70@ Check that |n| bytes more fit into buffer; increase it if required. 71@c 72static void strbuf_room(strbuf_s * b, size_t n) 73{ 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; 88 } 89} 90 91@ Seek to position |offset| within buffer. Position must be valid. 92@c 93void strbuf_seek(strbuf_s * b, off_t offset) 94{ 95 assert(offset >= 0 && offset < (off_t) b->size); 96 b->p = b->data + offset; 97} 98 99@ Get the current buffer fill level, the number of characters. 100@c 101size_t strbuf_offset(strbuf_s * b) 102{ 103 return (size_t) (b->p - b->data); 104} 105 106@ Put one character into buffer. Make room before if needed. 107@c 108void strbuf_putchar(strbuf_s * b, unsigned char c) 109{ 110 if ((size_t) (b->p - b->data + 1) > b->size) 111 strbuf_room(b, 1); 112 *b->p++ = c; 113} 114 115@ Dump filled buffer part to PDF. 116@c 117void strbuf_flush(PDF pdf, strbuf_s * b) 118{ 119 pdf_out_block(pdf, (const char *) b->data, strbuf_offset(b)); 120 strbuf_seek(b, 0); 121} 122 123@ Free all dynamically allocated buffer structures. 124@c 125void strbuf_free(strbuf_s * b) 126{ 127 xfree(b->data); 128 xfree(b); 129} 130 131@ |init_pdf_struct()| is called early, only once, from maincontrol.w 132@c 133PDF init_pdf_struct(PDF pdf) 134{ 135 os_struct *os; 136 assert(pdf == NULL); 137 pdf = xtalloc(1, pdf_output_file); 138 memset(pdf, 0, sizeof(pdf_output_file)); 139 pdf->job_name = makecstring(job_name); 140 141 pdf->o_mode = OMODE_NONE; /* will be set by |fix_o_mode()| */ 142 pdf->o_state = ST_INITIAL; 143 144 /* init PDF and object stream writing */ 145 pdf->os = os = xtalloc(1, os_struct); 146 memset(pdf->os, 0, sizeof(os_struct)); 147 os->buf[PDFOUT_BUF] = new_strbuf(inf_pdfout_buf_size, sup_pdfout_buf_size); 148 os->buf[OBJSTM_BUF] = new_strbuf(inf_objstm_buf_size, sup_objstm_buf_size); 149 os->buf[LUASTM_BUF] = new_strbuf(0, 0); 150 os->obj = xtalloc(PDF_OS_MAX_OBJS, os_obj_data); 151 os->cur_objstm = 0; 152 os->trigger_luastm = false; 153 154 os->curbuf = PDFOUT_BUF; 155 pdf->buf = os->buf[os->curbuf]; 156 157 /* Later ttf_seek_outbuf(TABDIR_OFF + n * 4 * TTF_ULONG_SIZE) */ 158 /* in ttf_init_font will need 236 bytes, so we start with 256 bytes as in pdftex. */ 159 pdf->fb = new_strbuf(256, 100000000); 160 161 pdf->stream_deflate = false; 162 pdf->stream_writing = false; 163 164 /* Sometimes it is neccesary to allocate memory for PDF output that cannot 165 be deallocated then, so we use |mem| for this purpose. */ 166 pdf->mem_size = inf_pdf_mem_size; /* allocated size of |mem| array */ 167 pdf->mem = xtalloc(pdf->mem_size, int); 168 pdf->mem_ptr = 1; /* the first word is not used so we can use zero as a value for testing 169 whether a pointer to |mem| is valid */ 170 pdf->pstruct = NULL; 171 172 pdf->posstruct = xtalloc(1, posstructure); 173 pdf->posstruct->pos.h = 0; 174 pdf->posstruct->pos.v = 0; 175 pdf->posstruct->dir = dir_TLT; 176 177 pdf->obj_tab_size = (unsigned) inf_obj_tab_size; /* allocated size of |obj_tab| array */ 178 pdf->obj_tab = xtalloc(pdf->obj_tab_size + 1, obj_entry); 179 memset(pdf->obj_tab, 0, sizeof(obj_entry)); 180 181 pdf->minor_version = -1; /* unset */ 182 pdf->decimal_digits = 4; 183 pdf->gamma = 65536; 184 pdf->image_gamma = 65536; 185 pdf->image_hicolor = 1; 186 pdf->image_apply_gamma = 0; 187 pdf->objcompresslevel = 0; 188 pdf->compress_level = 0; 189 pdf->draftmode = 0; 190 pdf->inclusion_copy_font = 1; 191 pdf->replace_font = 0; 192 pdf->pk_resolution = 0; 193 pdf->pk_scale_factor = 0; 194 195 init_dest_names(pdf); 196 pdf->page_resources = NULL; 197 198 init_pdf_pagecalculations(pdf); 199 pdf->pdflua_ref = new_pdflua(); 200 201 pdf->vfstruct = new_vfstruct(); 202 203 return pdf; 204} 205 206@ We use |pdf_get_mem| to allocate memory in |mem|. 207 208@c 209int pdf_get_mem(PDF pdf, int s) 210{ /* allocate |s| words in |mem| */ 211 int a; 212 int ret; 213 if (s > sup_pdf_mem_size - pdf->mem_ptr) 214 overflow("PDF memory size (pdf_mem_size)", (unsigned) pdf->mem_size); 215 if (pdf->mem_ptr + s > pdf->mem_size) { 216 a = pdf->mem_size >> 2; 217 if (pdf->mem_ptr + s > pdf->mem_size + a) { 218 pdf->mem_size = pdf->mem_ptr + s; 219 } else if (pdf->mem_size < sup_pdf_mem_size - a) { 220 pdf->mem_size = pdf->mem_size + a; 221 } else { 222 pdf->mem_size = sup_pdf_mem_size; 223 } 224 pdf->mem = xreallocarray(pdf->mem, int, (unsigned) pdf->mem_size); 225 } 226 ret = pdf->mem_ptr; 227 pdf->mem_ptr = pdf->mem_ptr + s; 228 return ret; 229} 230 231@ |get_o_mode| translates from |pdf_output| to |o_mode|. 232 233@c 234static output_mode get_o_mode(void) 235{ 236 output_mode o_mode; 237 if (pdf_output > 0) { 238 /* ls-hh: for the moment disabled ... incomplete old experiment */ 239 /* 240 if (pdf_output == 2009) 241 o_mode = OMODE_LUA; 242 else 243 */ 244 o_mode = OMODE_PDF; 245 } else 246 o_mode = OMODE_DVI; 247 return o_mode; 248} 249 250@ |fix_o_mode| freezes |pdf->o_mode| as soon as anything goes through 251the backend, be it \.{PDF}, \.{DVI}, or \.{Lua}. 252 253@c 254void fix_o_mode(PDF pdf) 255{ 256 output_mode o_mode = get_o_mode(); 257 if (pdf->o_mode == OMODE_NONE) 258 pdf->o_mode = o_mode; 259 else if (pdf->o_mode != o_mode) 260 pdf_error("setup", "\\pdfoutput can only be changed before anything is written to the output"); 261} 262 263@ This ensures that |pdfminorversion| is set only before any bytes have 264been written to the generated \.{PDF} file. Here also all variables for 265\.{PDF} output are initialized, the \.{PDF} file is opened by |ensure_pdf_open|, 266and the \.{PDF} header is written. 267 268@c 269void fix_pdf_minorversion(PDF pdf) 270{ 271 if (pdf->minor_version < 0) { /* unset */ 272 if ((pdf_minor_version < 0) || (pdf_minor_version > 9)) { 273 const char *hlp[] = { "The pdfminorversion must be between 0 and 9.", "I changed this to 4.", NULL }; 274 char msg[256]; 275 (void) snprintf(msg, 255, "LuaTeX error (illegal pdfminorversion %d)", (int) pdf_minor_version); 276 tex_error(msg, hlp); 277 pdf_minor_version = 4; 278 } 279 pdf->minor_version = pdf_minor_version; 280 } else { 281 /* Check that variables for \.{PDF} output are unchanged */ 282 if (pdf->minor_version != pdf_minor_version) 283 pdf_error("setup", "\\pdfminorversion cannot be changed after data is written to the PDF file"); 284 if (pdf->draftmode != pdf_draftmode) 285 pdf_error("setup", "\\pdfdraftmode cannot be changed after data is written to the PDF file"); 286 } 287 if (pdf->draftmode != 0) { 288 pdf->compress_level = 0; /* re-fix it, might have been changed inbetween */ 289 pdf->objcompresslevel = 0; 290 } 291} 292 293@ @c 294#define ZIP_BUF_SIZE 32768 295 296#define check_err(f, fn) \ 297 if (f != Z_OK) \ 298 luatex_fail("zlib: %s() failed (error code %d)", fn, f) 299 300@ @c 301static void write_zip(PDF pdf) 302{ 303 int flush, err = Z_OK; 304 uInt zip_len; 305 strbuf_s *buf = pdf->buf; 306 z_stream *s = pdf->c_stream; 307 boolean finish = pdf->zip_write_state == ZIP_FINISH; 308 assert(pdf->compress_level > 0); 309 /* This was just to suppress the filename report in |luatex_fail| 310 but zlib errors are rare enough (especially now that the 311 compress level is fixed) that I don't care about the slightly 312 ugly error message that could result. 313 */ 314#if 0 315 cur_file_name = NULL; 316#endif 317 if (pdf->stream_length == 0) { 318 if (s == NULL) { 319 s = pdf->c_stream = xtalloc(1, z_stream); 320 s->zalloc = (alloc_func) 0; 321 s->zfree = (free_func) 0; 322 s->opaque = (voidpf) 0; 323 check_err(deflateInit(s, pdf->compress_level), "deflateInit"); 324 assert(pdf->zipbuf == NULL); 325 pdf->zipbuf = xtalloc(ZIP_BUF_SIZE, char); 326 } else 327 check_err(deflateReset(s), "deflateReset"); 328 s->next_out = (Bytef *) pdf->zipbuf; 329 s->avail_out = ZIP_BUF_SIZE; 330 } 331 assert(s != NULL); 332 assert(pdf->zipbuf != NULL); 333 s->next_in = buf->data; 334 s->avail_in = (uInt) (buf->p - buf->data); 335 while (true) { 336 if (s->avail_out == 0 || (finish && s->avail_out < ZIP_BUF_SIZE)) { 337 zip_len = ZIP_BUF_SIZE - s->avail_out; 338 pdf->gone += (off_t) xfwrite(pdf->zipbuf, 1, zip_len, pdf->file); 339 pdf->last_byte = pdf->zipbuf[zip_len - 1]; 340 s->next_out = (Bytef *) pdf->zipbuf; 341 s->avail_out = ZIP_BUF_SIZE; 342 } 343 if (finish) { 344 if (err == Z_STREAM_END) { 345 assert(s->avail_in == 0); 346 assert(s->avail_out == ZIP_BUF_SIZE); 347 xfflush(pdf->file); 348 pdf->zip_write_state = NO_ZIP; 349 break; 350 } 351 flush = Z_FINISH; 352 } else { 353 if (s->avail_in == 0) 354 break; 355 flush = Z_NO_FLUSH; 356 } 357 err = deflate(s, flush); 358 if (err != Z_OK && err != Z_STREAM_END) 359 luatex_fail("zlib: deflate() failed (error code %d)", err); 360 } 361 pdf->stream_length = (off_t) s->total_out; 362} 363 364@ @c 365void zip_free(PDF pdf) 366{ 367 if (pdf->zipbuf != NULL) { 368 check_err(deflateEnd(pdf->c_stream), "deflateEnd"); 369 xfree(pdf->zipbuf); 370 } 371 xfree(pdf->c_stream); 372} 373 374@ @c 375static void write_nozip(PDF pdf) 376{ 377 strbuf_s *buf = pdf->buf; 378 size_t l = strbuf_offset(buf); 379 if (l == 0) 380 return; 381 pdf->stream_length = pdf_offset(pdf) - pdf->save_offset; 382 pdf->gone += 383 (off_t) xfwrite((char *) buf->data, sizeof(char), l, pdf->file); 384 pdf->last_byte = *(buf->p - 1); 385} 386 387@ The PDF buffer is flushed by calling |pdf_flush|, which checks the 388variable |zip_write_state| and will compress the buffer before flushing if 389neccesary. We call |pdf_begin_stream| to begin a stream and |pdf_end_stream| 390to finish it. The stream contents will be compressed if compression is turn on. 391 392@c 393void pdf_flush(PDF pdf) 394{ /* flush out the |pdf->buf| */ 395 os_struct *os = pdf->os; 396 off_t saved_pdf_gone = pdf->gone; 397 assert(pdf->buf == os->buf[os->curbuf]); 398 switch (os->curbuf) { 399 case PDFOUT_BUF: 400 if (pdf->draftmode == 0) { 401 switch (pdf->zip_write_state) { 402 case NO_ZIP: 403 write_nozip(pdf); 404 break; 405 case ZIP_WRITING: 406 case ZIP_FINISH: 407 write_zip(pdf); 408 break; 409 default: 410 assert(0); 411 } 412 } else 413 pdf->zip_write_state = NO_ZIP; 414 strbuf_seek(pdf->buf, 0); 415 if (saved_pdf_gone > pdf->gone) 416 pdf_error("file size", "File size exceeds architectural limits (pdf_gone wraps around)"); 417 break; 418 case LUASTM_BUF: 419 luaL_addsize(&(os->b), strbuf_offset(pdf->buf)); 420 pdf->buf->p = pdf->buf->data = (unsigned char *) luaL_prepbuffer(&(os->b)); /* for next stream piece */ 421 break; 422 case OBJSTM_BUF: 423 break; 424 default: 425 assert(0); 426 } 427} 428 429@ @c 430static void pdf_buffer_select(PDF pdf, buffer_e buf) 431{ 432 os_struct *os = pdf->os; 433 if (pdf->os_enable && buf == OBJSTM_BUF) 434 os->curbuf = OBJSTM_BUF; /* switch to object stream */ 435 else 436 os->curbuf = PDFOUT_BUF; /* switch to PDF stream */ 437 pdf->buf = os->buf[pdf->os->curbuf]; 438} 439 440@ create new \.{/ObjStm} object if required, and set up cross reference info 441 442@c 443static void pdf_prepare_obj(PDF pdf, int k, int pdf_os_threshold) 444{ 445 os_struct *os = pdf->os; 446 strbuf_s *obuf = os->buf[OBJSTM_BUF]; 447 assert(os->curbuf != LUASTM_BUF); 448 assert(pdf_os_threshold >= OBJSTM_ALWAYS); 449 if (pdf->objcompresslevel >= pdf_os_threshold) 450 pdf_buffer_select(pdf, OBJSTM_BUF); 451 else 452 pdf_buffer_select(pdf, PDFOUT_BUF); 453 assert(pdf->buf == os->buf[os->curbuf]); 454 switch (os->curbuf) { 455 case PDFOUT_BUF: 456 obj_offset(pdf, k) = pdf_offset(pdf); 457 obj_os_idx(pdf, k) = PDF_OS_MAX_OBJS; /* mark it as not included in any ObjStm */ 458 break; 459 case LUASTM_BUF: 460 assert(0); 461 break; 462 case OBJSTM_BUF: 463 if (os->cur_objstm == 0) { 464 os->cur_objstm = 465 (unsigned int) pdf_create_obj(pdf, obj_type_objstm, 0); 466 os->idx = 0; 467 obuf->p = obuf->data; /* start fresh object stream */ 468 os->ostm_ctr++; /* only for statistics */ 469 } 470 assert(os->idx < PDF_OS_MAX_OBJS); /* for marking below */ 471 obj_os_idx(pdf, k) = (int) os->idx; 472 obj_os_objnum(pdf, k) = (int) os->cur_objstm; 473 os->obj[os->idx].num = k; 474 os->obj[os->idx].off = obuf->p - obuf->data; 475 break; 476 default: 477 assert(0); 478 } 479} 480 481@* Low-level buffer checkers. 482 483@ Set the active buffer pointer. 484Make sure that there are at least |n| bytes free in that buffer, 485flush if needed. 486@c 487void pdf_room(PDF pdf, int n) 488{ 489 os_struct *os = pdf->os; 490 strbuf_s *buf = pdf->buf; 491 if ((size_t) (n + buf->p - buf->data) <= buf->size) 492 return; 493 assert(buf == os->buf[os->curbuf]); 494 switch (os->curbuf) { 495 case PDFOUT_BUF: 496 if ((size_t) n > buf->size) 497 overflow("PDF output buffer", (unsigned) buf->size); 498 if ((size_t) (n + buf->p - buf->data) < buf->limit) 499 strbuf_room(buf, (size_t) n); /* grow it if possible */ 500 else 501 pdf_flush(pdf); 502 break; 503 case LUASTM_BUF: 504 if ((size_t) n > buf->size) 505 overflow("PDF output buffer", (unsigned) buf->size); 506 pdf_flush(pdf); 507 break; 508 case OBJSTM_BUF: 509 strbuf_room(buf, (size_t) n); /* just grow it */ 510 break; 511 default: 512 assert(0); 513 } 514} 515 516@ @c 517void pdf_out_block(PDF pdf, const char *s, size_t n) 518{ 519 size_t l; 520 strbuf_s *buf = pdf->buf; 521 do { 522 l = n; 523 if (l > buf->size) 524 l = buf->size; 525 pdf_room(pdf, (int) l); 526 (void) memcpy(buf->p, s, l); 527 buf->p += l; 528 s += l; 529 n -= l; 530 } while (n > 0); 531} 532 533@ @c 534__attribute__ ((format(printf, 2, 3))) 535void pdf_printf(PDF pdf, const char *fmt, ...) 536{ 537 va_list args; 538 va_start(args, fmt); 539 if (pdf->printf_buf == NULL) { 540 pdf->printf_buf = xtalloc(PRINTF_BUF_SIZE, char); 541 } 542 (void) vsnprintf(pdf->printf_buf, PRINTF_BUF_SIZE, fmt, args); 543 pdf_puts(pdf, pdf->printf_buf); 544 va_end(args); 545} 546 547@ print out a string to PDF buffer 548@c 549void pdf_print(PDF pdf, str_number s) 550{ 551 const char *ss; 552 size_t l; 553 if (s >= STRING_OFFSET) { 554 ss = (const char *) str_string(s); 555 l = str_length(s); 556 pdf_out_block(pdf, ss, l); 557 } else { 558 assert(s < 256); 559 pdf_out(pdf, s); 560 } 561} 562 563@ print out a integer to PDF buffer 564@c 565void pdf_print_int(PDF pdf, longinteger n) 566{ 567 char s[24]; 568 int w; 569 w = snprintf(s, 23, "%" LONGINTEGER_PRI "d", (LONGINTEGER_TYPE) n); 570 check_nprintf(w, 23); 571 pdf_out_block(pdf, (const char *) s, (size_t) w); 572} 573 574@ @c 575void print_pdffloat(PDF pdf, pdffloat f) 576{ 577 char a[24]; 578 int e = f.e, i, j, l; 579 int64_t m = f.m; 580 if (m < 0) { 581 pdf_out(pdf, '-'); 582 m *= -1; 583 } 584 l = m / ten_pow[e]; 585 pdf_print_int(pdf, l); 586 l = m % ten_pow[e]; 587 if (l != 0) { 588 pdf_out(pdf, '.'); 589 j = snprintf(a, 23, "%d", l + ten_pow[e]); 590 assert(j < 23); 591 for (i = e; i > 0; i--) { 592 if (a[i] != '0') 593 break; 594 a[i] = '\0'; 595 } 596 pdf_puts(pdf, (a + 1)); 597 } 598} 599 600@ print out |s| as string in PDF output 601@c 602void pdf_print_str(PDF pdf, const char *s) 603{ 604 const char *orig = s; 605 int l = (int) strlen(s) - 1; /* last string index */ 606 if (l < 0) { 607 pdf_puts(pdf, "()"); 608 return; 609 } 610 /* the next is not really safe, the string could be "(a)xx(b)" */ 611 if ((s[0] == '(') && (s[l] == ')')) { 612 pdf_puts(pdf, s); 613 return; 614 } 615 if ((s[0] != '<') || (s[l] != '>') || odd((l + 1))) { 616 pdf_out(pdf, '('); 617 pdf_puts(pdf, s); 618 pdf_out(pdf, ')'); 619 return; 620 } 621 s++; 622 while (is_hex_char((unsigned char)*s)) 623 s++; 624 if (s != orig + l) { 625 pdf_out(pdf, '('); 626 pdf_puts(pdf, orig); 627 pdf_out(pdf, ')'); 628 return; 629 } 630 pdf_puts(pdf, orig); /* it was a hex string after all */ 631} 632 633@ begin a stream (needs to have a stream dictionary also) 634@c 635void pdf_begin_stream(PDF pdf) 636{ 637 os_struct *os = pdf->os; 638 strbuf_s *lbuf = os->buf[LUASTM_BUF]; 639 assert(os->curbuf == PDFOUT_BUF); 640 assert(pdf->buf == os->buf[os->curbuf]); 641 assert(pdf->zip_write_state == NO_ZIP); 642 pdf_puts(pdf, "\nstream\n"); 643 pdf_save_offset(pdf); 644 pdf_flush(pdf); 645 646 if (callback_defined(pdf_stream_filter_callback)) { 647 /*if (os->trigger_luastm) {*/ 648 os->trigger_luastm = false; /* this was just a trigger */ 649 luaL_buffinit(Luas, &(os->b)); 650 lbuf->p = lbuf->data = (unsigned char *) luaL_prepbuffer(&(os->b)); 651 lbuf->size = lbuf->limit = LUAL_BUFFERSIZE; 652 os->curbuf = LUASTM_BUF; 653 pdf->buf = os->buf[os->curbuf]; 654 } 655 if (pdf->stream_deflate) { 656 assert(pdf->compress_level > 0); 657 pdf->zip_write_state = ZIP_WRITING; 658 } 659 pdf->stream_writing = true; 660 pdf->stream_length = 0; 661 pdf->last_byte = 0; 662} 663 664@ end a stream 665@c 666void pdf_end_stream(PDF pdf) 667{ 668 typedef struct strbuf_const_s_ { 669 unsigned const char *data; /* a PDF stream buffer */ 670 unsigned const char *p; /* pointer to the next character in the PDF stream buffer */ 671 size_t size; /* currently allocated size of the PDF stream buffer, grows dynamically */ 672 size_t limit; /* maximum allowed PDF stream buffer size */ 673 } strbuf_const_s; 674 675 676 os_struct *os = pdf->os; 677 /* Old code, */ 678 /* strbuf_s *lbuf = os->buf[LUASTM_BUF]; */ 679 strbuf_const_s *lbuf = (strbuf_const_s * )os->buf[LUASTM_BUF]; 680 const_lstring ls; 681 int callback_id ; 682 assert(pdf->buf == os->buf[os->curbuf]); 683 switch (os->curbuf) { 684 case PDFOUT_BUF: 685 if (pdf->zip_write_state == ZIP_WRITING) 686 pdf->zip_write_state = ZIP_FINISH; 687 pdf_flush(pdf); /* sets pdf->last_byte */ 688 break; 689 case LUASTM_BUF: 690 luaL_addsize(&(os->b), strbuf_offset(os->buf[LUASTM_BUF])); 691 luaL_pushresult(&(os->b)); 692 /* now the complete page stream is on the Lua stack */ 693 /* TODO: pagestream filter callback here */ 694 695 callback_id = callback_defined(pdf_stream_filter_callback); 696 if (callback_id > 0) { 697 run_callback(callback_id, "S->S"); 698 } 699 700 ls.s = lua_tolstring(Luas, -1, &ls.l); 701 /* lbuf->data = (unsigned char *) ls.s; */ 702 lbuf->data = (unsigned const char *) ls.s; 703 lbuf->p = lbuf->data + ls.l; 704 os->curbuf = LUASTM_BUF; 705 pdf->buf = os->buf[os->curbuf]; 706 if (pdf->zip_write_state == ZIP_WRITING) { 707 pdf->zip_write_state = ZIP_FINISH; 708 write_zip(pdf); 709 } else 710 write_nozip(pdf); 711 lua_pop(Luas, 1); 712 os->curbuf = PDFOUT_BUF; 713 pdf->buf = os->buf[os->curbuf]; 714 assert(pdf->buf->data == pdf->buf->p); 715 break; 716 case OBJSTM_BUF: 717 assert(0); 718 break; 719 default: 720 assert(0); 721 } 722 assert(pdf->zip_write_state == NO_ZIP); 723 assert(os->curbuf == PDFOUT_BUF); 724 assert(pdf->buf == os->buf[os->curbuf]); 725 pdf->stream_deflate = false; 726 pdf->stream_writing = false; 727 pdf_out(pdf, '\n'); /* doesn't really belong to the stream */ 728 pdf_puts(pdf, "endstream"); 729 /* write stream /Length */ 730 if (pdf->seek_write_length && pdf->draftmode == 0) { 731 xfseeko(pdf->file, (off_t)pdf->stream_length_offset, SEEK_SET, 732 pdf->job_name); 733 fprintf(pdf->file, "%" LONGINTEGER_PRI "i", (LONGINTEGER_TYPE) pdf->stream_length); 734 xfseeko(pdf->file, 0, SEEK_END, pdf->job_name); 735 } 736 pdf->seek_write_length = false; 737} 738 739@ To print |scaled| value to PDF output we need some subroutines to ensure 740accurary. 741 742@c 743#define max_integer 0x7FFFFFFF /* $2^{31}-1$ */ 744 745/* scaled value corresponds to 100in, exact, 473628672 */ 746scaled one_hundred_inch = 7227 * 65536; 747 748/* scaled value corresponds to 1in (rounded to 4736287) */ 749scaled one_inch = (7227 * 65536 + 50) / 100; 750 751/* scaled value corresponds to 1truein (rounded!) */ 752scaled one_true_inch = (7227 * 65536 + 50) / 100; 753 754/* scaled value corresponds to 100bp */ 755scaled one_hundred_bp = (7227 * 65536) / 72; 756 757/* scaled value corresponds to 1bp (rounded to 65782) */ 758/* changed on 20110411 to be exactly 65781, as in tex itself, 759 because this value is also used for \pdfpxdimen */ 760scaled one_bp = 65781; 761 762/* $10^0..10^9$ */ 763int ten_pow[10] = { 764 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 765}; 766 767 768@ The function |divide_scaled| divides |s| by |m| using |dd| decimal 769digits of precision. It is defined in C because it is a good candidate 770for optimizations that are not possible in pascal. 771 772@c 773scaled round_xn_over_d(scaled x, int n, unsigned int d) 774{ 775 boolean positive = true; /* was |x>=0|, |n>=0| ? */ 776 unsigned t, u, v; /* intermediate quantities */ 777 if (x < 0) { 778 positive = !positive; 779 x = -(x); 780 } 781 if (n < 0) { 782 positive = !positive; 783 n = -(n); 784 } 785 t = (unsigned) ((x % 0100000) * n); 786 u = (unsigned) (((unsigned) (x) / 0100000) * (unsigned) n + (t / 0100000)); 787 v = (u % d) * 0100000 + (t % 0100000); 788 if (u / d >= 0100000) 789 arith_error = true; 790 else 791 u = 0100000 * (u / d) + (v / d); 792 v = v % d; 793 if (2 * v >= d) 794 u++; 795 if (positive) 796 return (scaled) u; 797 else 798 return (-(scaled) u); 799} 800 801 802@ @c 803void pdf_add_bp(PDF pdf, scaled s) 804{ /* print scaled as |bp| */ 805 pdffloat a; 806 pdfstructure *p = pdf->pstruct; 807 assert(p != NULL); 808 a.m = i64round(s * p->k1); 809 a.e = pdf->decimal_digits; 810 if (pdf->cave > 0) 811 pdf_out(pdf, ' '); 812 print_pdffloat(pdf, a); 813 pdf->cave = 1; 814} 815 816void pdf_add_mag_bp(PDF pdf, scaled s) 817{ /* take |mag| into account */ 818 pdffloat a; 819 pdfstructure *p = pdf->pstruct; 820 prepare_mag(); 821 if (int_par(mag_code) != 1000) 822 a.m = i64round(s * (double) int_par(mag_code) / 1000.0 * p->k1); 823 else 824 a.m = i64round(s * p->k1); 825 a.e = pdf->decimal_digits; 826 if (pdf->cave > 0) 827 pdf_out(pdf, ' '); 828 print_pdffloat(pdf, a); 829 pdf->cave = 1; 830} 831 832@* handling page resources. 833 834@c 835typedef struct { 836 int obj_type; 837 pdf_object_list *list; 838} pr_entry; 839 840@ @c 841static int comp_page_resources(const void *pa, const void *pb, void *p) 842{ 843 int a, b; 844 (void) p; 845 a = ((const pr_entry *) pa)->obj_type; 846 b = ((const pr_entry *) pb)->obj_type; 847 if (a > b) 848 return 1; 849 if (a < b) 850 return -1; 851 return 0; 852} 853 854@ @c 855void addto_page_resources(PDF pdf, pdf_obj_type t, int k) 856{ 857 pdf_resource_struct *re; 858 pr_entry *pr, tmp; 859 void **pp; 860 pdf_object_list *p, *item = NULL; 861 assert(pdf != NULL); 862 re = pdf->page_resources; 863 assert(re != NULL); 864 assert(t <= PDF_OBJ_TYPE_MAX); 865 if (re->resources_tree == NULL) { 866 re->resources_tree = 867 avl_create(comp_page_resources, NULL, &avl_xallocator); 868 if (re->resources_tree == NULL) 869 luatex_fail 870 ("addto_page_resources(): avl_create() page_resource_tree failed"); 871 } 872 tmp.obj_type = t; 873 pr = (pr_entry *) avl_find(re->resources_tree, &tmp); 874 if (pr == NULL) { 875 pr = xtalloc(1, pr_entry); 876 pr->obj_type = t; 877 pr->list = NULL; 878 pp = avl_probe(re->resources_tree, pr); 879 if (pp == NULL) 880 luatex_fail 881 ("addto_page_resources(): avl_probe() out of memory in insertion"); 882 } 883 if (pr->list == NULL) { 884 item = xtalloc(1, pdf_object_list); 885 item->link = NULL; 886 item->info = k; 887 pr->list = item; 888 if (obj_type(pdf, k) == (int)t) 889 set_obj_scheduled(pdf, k); /* k is an object number */ 890 } else { 891 for (p = pr->list; p->info != k && p->link != NULL; p = p->link); 892 if (p->info != k) { 893 item = xtalloc(1, pdf_object_list); 894 item->link = NULL; 895 item->info = k; 896 p->link = item; 897 if (obj_type(pdf, k) == (int)t) 898 set_obj_scheduled(pdf, k); 899 } 900 } 901} 902 903@ @c 904pdf_object_list *get_page_resources_list(PDF pdf, pdf_obj_type t) 905{ 906 pdf_resource_struct *re = pdf->page_resources; 907 pr_entry *pr, tmp; 908 if (re == NULL || re->resources_tree == NULL) 909 return NULL; 910 tmp.obj_type = t; 911 pr = (pr_entry *) avl_find(re->resources_tree, &tmp); 912 if (pr == NULL) 913 return NULL; 914 return pr->list; 915} 916 917@ @c 918static void reset_page_resources(PDF pdf) 919{ 920 pdf_resource_struct *re = pdf->page_resources; 921 pr_entry *p; 922 struct avl_traverser t; 923 pdf_object_list *l1, *l2; 924 if (re == NULL || re->resources_tree == NULL) 925 return; 926 avl_t_init(&t, re->resources_tree); 927 for (p = avl_t_first(&t, re->resources_tree); p != NULL; p = avl_t_next(&t)) { 928 if (p->list != NULL) { 929 for (l1 = p->list; l1 != NULL; l1 = l2) { 930 l2 = l1->link; 931 free(l1); 932 } 933 p->list = NULL; /* but the AVL tree remains */ 934 } 935 } 936} 937 938@ @c 939static void destroy_pg_res_tree(void *pa, void *param) 940{ 941 (void) param; 942 xfree(pa); 943} 944 945@ @c 946static void destroy_page_resources_tree(PDF pdf) 947{ 948 pdf_resource_struct *re = pdf->page_resources; 949 reset_page_resources(pdf); 950 if (re->resources_tree != NULL) 951 avl_destroy(re->resources_tree, destroy_pg_res_tree); 952 re->resources_tree = NULL; 953} 954 955@* Subroutines to print out various PDF objects. 956 957@ print out an integer |n| with fixed width |w|; used for outputting cross-reference table 958@c 959static void pdf_print_fw_int(PDF pdf, longinteger n, size_t w) 960{ 961 int k; /* $0\le k\le23$ */ 962 unsigned char digits[24]; 963 k = (int) w; 964 do { 965 k--; 966 digits[k] = (unsigned char) ('0' + (n % 10)); 967 n /= 10; 968 } while (k != 0); 969 pdf_out_block(pdf, (const char *) digits, w); 970} 971 972@ print out an integer |n| as a fixed number |w| of bytes; used for outputting \.{/XRef} cross-reference stream 973@c 974static void pdf_out_bytes(PDF pdf, longinteger n, size_t w) 975{ 976 int k; 977 unsigned char bytes[8]; /* digits in a number being output */ 978 k = (int) w; 979 do { 980 k--; 981 bytes[k] = (unsigned char) (n % 256); 982 n /= 256; 983 } while (k != 0); 984 pdf_out_block(pdf, (const char *) bytes, w); 985} 986 987@ print out |s| as string in PDF output 988@c 989void pdf_print_str_ln(PDF pdf, const char *s) 990{ 991 pdf_print_str(pdf, s); 992 pdf_out(pdf, '\n'); 993} 994 995@ @c 996void pdf_print_toks(PDF pdf, halfword p) 997{ 998 int len = 0; 999 char *s = tokenlist_to_cstring(p, true, &len); 1000 if (len > 0) { 1001 if (pdf->cave > 0) 1002 pdf_out(pdf, ' '); 1003 pdf_puts(pdf, s); 1004 pdf->cave = 1; 1005 } 1006 xfree(s); 1007} 1008 1009@ prints a rect spec 1010@c 1011void pdf_add_rect_spec(PDF pdf, halfword r) 1012{ 1013 pdf_add_mag_bp(pdf, pdf_ann_left(r)); 1014 pdf_add_mag_bp(pdf, pdf_ann_bottom(r)); 1015 pdf_add_mag_bp(pdf, pdf_ann_right(r)); 1016 pdf_add_mag_bp(pdf, pdf_ann_top(r)); 1017} 1018 1019@ output a rectangle specification to PDF file 1020@c 1021void pdf_rectangle(PDF pdf, halfword r) 1022{ 1023 prepare_mag(); 1024 pdf_add_name(pdf, "Rect"); 1025 pdf_begin_array(pdf); 1026 pdf_add_rect_spec(pdf, r); 1027 pdf_end_array(pdf); 1028} 1029 1030@ @c 1031static void init_pdf_outputparameters(PDF pdf) 1032{ 1033 assert(pdf->o_mode == OMODE_PDF); 1034 pdf->draftmode = fix_int(pdf_draftmode, 0, 1); 1035 pdf->compress_level = fix_int(pdf_compress_level, 0, 9); 1036 pdf->decimal_digits = fix_int(pdf_decimal_digits, 0, 4); 1037 pdf->gamma = fix_int(pdf_gamma, 0, 1000000); 1038 pdf->image_gamma = fix_int(pdf_image_gamma, 0, 1000000); 1039 pdf->image_hicolor = fix_int(pdf_image_hicolor, 0, 1); 1040 pdf->image_apply_gamma = fix_int(pdf_image_apply_gamma, 0, 1); 1041 pdf->objcompresslevel = fix_int(pdf_objcompresslevel, 0, MAX_OBJ_COMPRESS_LEVEL); 1042 pdf->inclusion_copy_font = fix_int(pdf_inclusion_copy_font, 0, 1); 1043 pdf->replace_font = fix_int(pdf_replace_font, 0, 1); 1044 pdf->pk_resolution = fix_int(pdf_pk_resolution, 72, 8000); 1045 if ((pdf->minor_version >= 5) && (pdf->objcompresslevel > 0)) { 1046 pdf->os_enable = true; 1047 } else { 1048 if (pdf->objcompresslevel > 0) { 1049 pdf_warning("Object streams", 1050 "\\pdfobjcompresslevel > 0 requires \\pdfminorversion > 4. Object streams disabled now.", 1051 true, true); 1052 pdf->objcompresslevel = 0; 1053 } 1054 pdf->os_enable = false; 1055 } 1056 if (pdf->pk_resolution == 0) /* if not set from format file or by user */ 1057 pdf->pk_resolution = pk_dpi; /* take it from \.{texmf.cnf} */ 1058 pdf->pk_scale_factor = 1059 divide_scaled(72, pdf->pk_resolution, 5 + pdf->decimal_digits); 1060 if (!callback_defined(read_pk_file_callback)) { 1061 if (pdf_pk_mode != null) { 1062 char *s = tokenlist_to_cstring(pdf_pk_mode, true, NULL); 1063 kpse_init_prog("PDFTEX", (unsigned) pdf->pk_resolution, s, nil); 1064 xfree(s); 1065 } else { 1066 kpse_init_prog("PDFTEX", (unsigned) pdf->pk_resolution, nil, nil); 1067 } 1068 if (!kpse_var_value("MKTEXPK")) 1069 kpse_set_program_enabled(kpse_pk_format, 1, kpse_src_cmdline); 1070 } 1071 set_job_id(pdf, int_par(year_code), 1072 int_par(month_code), int_par(day_code), int_par(time_code)); 1073 if ((pdf_unique_resname > 0) && (pdf->resname_prefix == NULL)) 1074 pdf->resname_prefix = get_resname_prefix(pdf); 1075} 1076 1077@ Checks that we have a name for the generated PDF file and that it's open. 1078 1079@c 1080static void ensure_output_file_open(PDF pdf, const char *ext) 1081{ 1082 char *fn; 1083 if (pdf->file_name != NULL) 1084 return; 1085 if (job_name == 0) 1086 open_log_file(); 1087 fn = pack_job_name(ext); 1088 if (pdf->draftmode == 0 || pdf->o_mode == OMODE_DVI) { 1089 while (!lua_b_open_out(&pdf->file, fn)) 1090 fn = prompt_file_name("file name for output", ext); 1091 } 1092 pdf->file_name = fn; 1093} 1094 1095@ @c 1096static void ensure_pdf_header_written(PDF pdf) 1097{ 1098 assert(pdf->o_state == ST_FILE_OPEN); 1099 assert(pdf->o_mode == OMODE_PDF); 1100 /* Initialize variables for \.{PDF} output */ 1101 fix_pdf_minorversion(pdf); 1102 init_pdf_outputparameters(pdf); 1103 /* Write \.{PDF} header */ 1104 pdf_printf(pdf, "%%PDF-1.%d\n", pdf->minor_version); 1105 pdf_out(pdf, '%'); 1106 pdf_out(pdf, 'P' + 128); 1107 pdf_out(pdf, 'T' + 128); 1108 pdf_out(pdf, 'E' + 128); 1109 pdf_out(pdf, 'X' + 128); 1110 pdf_out(pdf, '\n'); 1111} 1112 1113@ @c 1114void ensure_output_state(PDF pdf, output_state s) 1115{ 1116 if (pdf->o_state < s) { 1117 if (s > ST_INITIAL) 1118 ensure_output_state(pdf, s - 1); 1119 switch (s - 1) { 1120 case ST_INITIAL: 1121 fix_o_mode(pdf); 1122 break; 1123 case ST_OMODE_FIX: 1124 switch (pdf->o_mode) { 1125 case OMODE_DVI: 1126 ensure_output_file_open(pdf, ".dvi"); 1127 break; 1128 case OMODE_PDF: 1129 ensure_output_file_open(pdf, ".pdf"); 1130 break; 1131 case OMODE_LUA: 1132 break; 1133 default: 1134 assert(0); 1135 } 1136 break; 1137 case ST_FILE_OPEN: 1138 switch (pdf->o_mode) { 1139 case OMODE_DVI: 1140 ensure_dvi_header_written(pdf); 1141 break; 1142 case OMODE_PDF: 1143 ensure_pdf_header_written(pdf); 1144 break; 1145 case OMODE_LUA: 1146 break; 1147 default: 1148 assert(0); 1149 } 1150 break; 1151 case ST_HEADER_WRITTEN: 1152 break; 1153 case ST_FILE_CLOSED: 1154 break; 1155 default: 1156 assert(0); 1157 } 1158 pdf->o_state++; 1159 } 1160} 1161 1162@ Write out an accumulated object stream. 1163 1164First the object number and byte offset pairs are generated 1165and appended to the ready buffered object stream. 1166By this the value of \.{/First} can be calculated. 1167Then a new \.{/ObjStm} object is generated, and everything is 1168copied to the PDF output buffer, where also compression is done. 1169When calling this procedure, |pdf_os_mode| must be |true|. 1170 1171@c 1172static void pdf_os_write_objstream(PDF pdf) 1173{ 1174 os_struct *os = pdf->os; 1175 unsigned int i, j, n1, n2; /* n1, n2: ObjStm buffer may be reallocated! */ 1176 strbuf_s *obuf = os->buf[OBJSTM_BUF]; 1177 if (os->cur_objstm == 0) /* no object stream started */ 1178 return; 1179 assert(pdf->buf == obuf); /* yes, pdf_out() still goes into ObjStm */ 1180 assert(os->idx > 0); /* yes, there are objects for the ObjStm */ 1181 n1 = (unsigned int) strbuf_offset(obuf); /* remember end of collected object stream contents */ 1182 /* this is needed here to calculate /First for the ObjStm dict */ 1183 for (i = 0, j = 0; i < os->idx; i++) { /* add object-number/byte-offset list to buffer */ 1184 pdf_print_int(pdf, (int) os->obj[i].num); 1185 pdf_out(pdf, ' '); 1186 pdf_print_int(pdf, (int) os->obj[i].off); 1187 if (j == 9 || i == os->idx - 1) { /* print out in groups of ten for better readability */ 1188 pdf_out(pdf, '\n'); 1189 j = 0; 1190 } else { 1191 pdf_out(pdf, ' '); 1192 j++; 1193 } 1194 } 1195 n2 = (unsigned int) strbuf_offset(obuf); /* remember current buffer end */ 1196 pdf_begin_obj(pdf, (int) os->cur_objstm, OBJSTM_NEVER); /* switch to PDF stream writing */ 1197 pdf_begin_dict(pdf); 1198 pdf_dict_add_name(pdf, "Type", "ObjStm"); 1199 pdf_dict_add_int(pdf, "N", (int) os->idx); /* number of objects in ObjStm */ 1200 pdf_dict_add_int(pdf, "First", (int) (n2 - n1)); 1201 pdf_dict_add_streaminfo(pdf); 1202 pdf_end_dict(pdf); 1203 pdf_begin_stream(pdf); 1204 /* write object-number/byte-offset list */ 1205 pdf_out_block(pdf, (const char *) (obuf->data + n1), (size_t) (n2 - n1)); 1206 /* write collected object stream contents */ 1207 pdf_out_block(pdf, (const char *) obuf->data, (size_t) n1); 1208 pdf_end_stream(pdf); 1209 pdf_end_obj(pdf); 1210 os->cur_objstm = 0; /* to force object stream generation next time */ 1211} 1212 1213@ begin a PDF dictionary 1214@c 1215void pdf_begin_dict(PDF pdf) 1216{ 1217 pdf_puts(pdf, "<<"); 1218 pdf->cave = 0; 1219} 1220 1221@ end a PDF dictionary 1222@c 1223void pdf_end_dict(PDF pdf) 1224{ 1225 pdf_puts(pdf, ">>"); 1226 pdf->cave = 0; 1227} 1228 1229@ add integer object to dict 1230@c 1231void pdf_dict_add_bool(PDF pdf, const char *key, int i) 1232{ 1233 pdf_add_name(pdf, key); 1234 pdf_add_bool(pdf, i); 1235} 1236 1237@ add integer object to dict 1238@c 1239void pdf_dict_add_int(PDF pdf, const char *key, int i) 1240{ 1241 pdf_add_name(pdf, key); 1242 pdf_add_int(pdf, i); 1243} 1244 1245@ add name object to dict 1246@c 1247void pdf_dict_add_name(PDF pdf, const char *key, const char *val) 1248{ 1249 pdf_add_name(pdf, key); 1250 pdf_add_name(pdf, val); 1251} 1252 1253@ add string object to dict 1254@c 1255void pdf_dict_add_string(PDF pdf, const char *key, const char *val) 1256{ 1257 if (val == NULL) 1258 return; 1259 pdf_add_name(pdf, key); 1260 if (pdf->cave > 0) 1261 pdf_out(pdf, ' '); 1262 pdf->cave = 0; 1263 pdf_print_str(pdf, val); 1264} 1265 1266@ add name reference to dict 1267@c 1268void pdf_dict_add_ref(PDF pdf, const char *key, int num) 1269{ 1270 pdf_add_name(pdf, key); 1271 pdf_add_ref(pdf, num); 1272} 1273 1274@ add objects of different types 1275@c 1276void pdf_add_null(PDF pdf) 1277{ 1278 if (pdf->cave > 0) 1279 pdf_out(pdf, ' '); 1280 pdf_puts(pdf, "null"); 1281 pdf->cave = 1; 1282} 1283 1284void pdf_add_bool(PDF pdf, int i) 1285{ 1286 if (pdf->cave > 0) 1287 pdf_out(pdf, ' '); 1288 if (i == 0) 1289 pdf_puts(pdf, "false"); 1290 else 1291 pdf_puts(pdf, "true"); 1292 pdf->cave = 1; 1293} 1294 1295void pdf_add_int(PDF pdf, int i) 1296{ 1297 if (pdf->cave > 0) 1298 pdf_out(pdf, ' '); 1299 pdf_print_int(pdf, i); 1300 pdf->cave = 1; 1301} 1302 1303void pdf_add_longint(PDF pdf, longinteger n) 1304{ 1305 if (pdf->cave > 0) 1306 pdf_out(pdf, ' '); 1307 pdf_print_int(pdf, n); 1308 pdf->cave = 1; 1309} 1310 1311void pdf_add_string(PDF pdf, const char *s) 1312{ 1313 if (pdf->cave > 0) 1314 pdf_out(pdf, ' '); 1315 pdf_print_str(pdf, s); 1316 pdf->cave = 1; 1317} 1318 1319void pdf_add_name(PDF pdf, const char *name) 1320{ 1321 pdf_out(pdf, '/'); 1322 pdf_puts(pdf, name); 1323 pdf->cave = 1; 1324} 1325 1326void pdf_add_ref(PDF pdf, int num) 1327{ 1328 if (pdf->cave > 0) 1329 pdf_out(pdf, ' '); 1330 pdf_print_int(pdf, num); 1331 pdf_puts(pdf, " 0 R"); 1332 pdf->cave = 1; 1333} 1334 1335@ add stream length and filter entries to a stream dictionary, 1336remember file position for seek 1337@c 1338void pdf_dict_add_streaminfo(PDF pdf) 1339{ 1340 assert(pdf->buf == pdf->os->buf[PDFOUT_BUF]); 1341 pdf_add_name(pdf, "Length"); 1342 pdf->stream_length_offset = pdf_offset(pdf) + 1; 1343 pdf->seek_write_length = true; /* fill in length at |pdf_end_stream| call */ 1344 pdf_puts(pdf, " x "); /* space for 10 decimal digits */ 1345 pdf->cave = 1; 1346 if (pdf->compress_level > 0) { 1347 pdf_dict_add_name(pdf, "Filter", "FlateDecode"); 1348 pdf->stream_deflate = true; 1349 } 1350} 1351 1352@ begin a PDF array 1353@c 1354void pdf_begin_array(PDF pdf) 1355{ 1356 pdf_out(pdf, '['); 1357 pdf->cave = 0; 1358} 1359 1360@ end a PDF array 1361@c 1362void pdf_end_array(PDF pdf) 1363{ 1364 pdf_out(pdf, ']'); 1365 pdf->cave = 0; 1366} 1367 1368@ begin a PDF object 1369@c 1370void pdf_begin_obj(PDF pdf, int i, int pdf_os_threshold) 1371{ 1372 os_struct *os = pdf->os; 1373 ensure_output_state(pdf, ST_HEADER_WRITTEN); 1374 pdf_prepare_obj(pdf, i, pdf_os_threshold); 1375 assert(pdf->buf == os->buf[os->curbuf]); 1376 switch (os->curbuf) { 1377 case PDFOUT_BUF: 1378 pdf_printf(pdf, "%d 0 obj\n", (int) i); 1379 break; 1380 case LUASTM_BUF: 1381 assert(0); 1382 break; 1383 case OBJSTM_BUF: 1384 if (pdf->compress_level == 0) 1385 pdf_printf(pdf, "%% %d 0 obj\n", (int) i); /* debugging help */ 1386 break; 1387 default: 1388 assert(0); 1389 } 1390 pdf->cave = 0; 1391} 1392 1393@ end a PDF object 1394@c 1395void pdf_end_obj(PDF pdf) 1396{ 1397 os_struct *os = pdf->os; 1398 assert(pdf->buf == os->buf[os->curbuf]); 1399 switch (os->curbuf) { 1400 case PDFOUT_BUF: 1401 pdf_puts(pdf, "\nendobj\n"); /* end a PDF object */ 1402 break; 1403 case LUASTM_BUF: 1404 assert(0); 1405 break; 1406 case OBJSTM_BUF: 1407 os->idx++; /* = number of objects collected so far in ObjStm */ 1408 os->o_ctr++; /* only for statistics */ 1409 if (os->idx == PDF_OS_MAX_OBJS) 1410 pdf_os_write_objstream(pdf); 1411 else 1412 pdf_out(pdf, '\n'); /* Adobe Reader seems to need this */ 1413 break; 1414 default: 1415 assert(0); 1416 } 1417} 1418 1419@ Converts any string given in in in an allowed PDF string which can be 1420 handled by printf et.al.: \.{\\} is escaped to \.{\\\\}, parenthesis are escaped and 1421 control characters are octal encoded. 1422 This assumes that the string does not contain any already escaped 1423 characters! 1424 1425@c 1426char *convertStringToPDFString(const char *in, int len) 1427{ 1428 static char pstrbuf[MAX_PSTRING_LEN]; 1429 char *out = pstrbuf; 1430 int i, j, k; 1431 char buf[5]; 1432 j = 0; 1433 for (i = 0; i < len; i++) { 1434 check_buf((unsigned) j + sizeof(buf), MAX_PSTRING_LEN); 1435 if (((unsigned char) in[i] < '!') || ((unsigned char) in[i] > '~')) { 1436 /* convert control characters into oct */ 1437 k = snprintf(buf, sizeof(buf), "\\%03o", (unsigned int) (unsigned char) in[i]); 1438 check_nprintf(k, sizeof(buf)); 1439 out[j++] = buf[0]; 1440 out[j++] = buf[1]; 1441 out[j++] = buf[2]; 1442 out[j++] = buf[3]; 1443 } else if ((in[i] == '(') || (in[i] == ')')) { 1444 /* escape paranthesis */ 1445 out[j++] = '\\'; 1446 out[j++] = in[i]; 1447 } else if (in[i] == '\\') { 1448 /* escape backslash */ 1449 out[j++] = '\\'; 1450 out[j++] = '\\'; 1451 } else { 1452 /* copy char :-) */ 1453 out[j++] = in[i]; 1454 } 1455 } 1456 out[j] = '\0'; 1457 return pstrbuf; 1458} 1459 1460@ Converts any string given in in in an allowed PDF string which is 1461 hexadecimal encoded; 1462 |sizeof(out)| should be at least $|lin|*2+1$. 1463 1464@c 1465static void convertStringToHexString(const char *in, char *out, int lin) 1466{ 1467 int i, j, k; 1468 char buf[3]; 1469 j = 0; 1470 for (i = 0; i < lin; i++) { 1471 k = snprintf(buf, sizeof(buf), "%02X", (unsigned int) (unsigned char) in[i]); 1472 check_nprintf(k, sizeof(buf)); 1473 out[j++] = buf[0]; 1474 out[j++] = buf[1]; 1475 } 1476 out[j] = '\0'; 1477} 1478 1479@ Compute the ID string as per PDF1.4 9.3: 1480\medskip 1481{\obeylines\obeyspaces 1482 File identifers are defined by the optional ID entry in a PDF file's 1483 trailer dictionary (see Section 3.4.4, "File Trailer"; see also 1484 implementation note 105 in Appendix H). The value of this entry is an 1485 array of two strings. The first string is a permanent identifier based 1486 on the contents of the file at the time it was originally created, and 1487 does not change when the file is incrementally updated. The second 1488 string is a changing identifier based on the file's contents at the 1489 time it was last updated. When a file is first written, both 1490 identifiers are set to the same value. If both identifiers match when a 1491 file reference is resolved, it is very likely that the correct file has 1492 been found; if only the first identifier matches, then a different 1493 version of the correct file has been found. 1494 To help ensure the uniqueness of file identifiers, it is recommend 1495 that they be computed using a message digest algorithm such as MD5 1496 (described in Internet RFC 1321, The MD5 Message-Digest Algorithm; see 1497 the Bibliography), using the following information (see implementation 1498 note 106 in Appendix H): 1499 - The current time 1500 - A string representation of the file's location, usually a pathname 1501 - The size of the file in bytes 1502 - The values of all entries in the file's document information 1503 dictionary (see Section 9.2.1, Document Information Dictionary ) 1504} 1505\medskip 1506 This stipulates only that the two IDs must be identical when the file is 1507 created and that they should be reasonably unique. Since it's difficult 1508 to get the file size at this point in the execution of pdfTeX and 1509 scanning the info dict is also difficult, we start with a simpler 1510 implementation using just the first two items. 1511 1512@c 1513static void print_ID(PDF pdf) 1514{ 1515 time_t t; 1516 size_t size; 1517 char time_str[32]; 1518 md5_state_t state; 1519 md5_byte_t digest[16]; 1520 char id[64]; 1521 char pwd[4096]; 1522 /* start md5 */ 1523 md5_init(&state); 1524 /* get the time */ 1525 t = time(NULL); 1526 size = strftime(time_str, sizeof(time_str), "%Y%m%dT%H%M%SZ", gmtime(&t)); 1527 md5_append(&state, (const md5_byte_t *) time_str, (int) size); 1528 /* get the file name */ 1529 if (getcwd(pwd, sizeof(pwd)) == NULL) 1530 luatex_fail("getcwd() failed (%s), (path too long?)", strerror(errno)); 1531#ifdef WIN32 1532 { 1533 char *p; 1534 for (p = pwd; *p; p++) { 1535 if (*p == '\\') 1536 *p = '/'; 1537 else if (IS_KANJI(p)) 1538 p++; 1539 } 1540 } 1541#endif 1542 md5_append(&state, (const md5_byte_t *) pwd, (int) strlen(pwd)); 1543 md5_append(&state, (const md5_byte_t *) "/", 1); 1544 md5_append(&state, (const md5_byte_t *) pdf->file_name, 1545 (int) strlen(pdf->file_name)); 1546 /* finish md5 */ 1547 md5_finish(&state, digest); 1548 /* write the IDs */ 1549 convertStringToHexString((char *) digest, id, 16); 1550 pdf_add_name(pdf, "ID"); 1551 pdf_begin_array(pdf); 1552 pdf_printf(pdf, "<%s> <%s>", id, id); 1553 pdf_end_array(pdf); 1554} 1555 1556@ Print the /CreationDate entry. 1557 1558 PDF Reference, third edition says about the expected date format: 1559\medskip 1560{\obeylines\obeyspaces 1561 3.8.2 Dates 1562 1563 PDF defines a standard date format, which closely follows that of 1564 the international standard ASN.1 (Abstract Syntax Notation One), 1565 defined in ISO/IEC 8824 (see the Bibliography). A date is a string 1566 of the form 1567 1568 (D:YYYYMMDDHHmmSSOHH'mm') 1569 1570 where 1571 1572 YYYY is the year 1573 MM is the month 1574 DD is the day (01-31) 1575 HH is the hour (00-23) 1576 mm is the minute (00-59) 1577 SS is the second (00-59) 1578 O is the relationship of local time to Universal Time (UT), 1579 denoted by one of the characters +, -, or Z (see below) 1580 HH followed by ' is the absolute value of the offset from UT 1581 in hours (00-23) 1582 mm followed by ' is the absolute value of the offset from UT 1583 in minutes (00-59) 1584 1585 The apostrophe character (') after HH and mm is part of the syntax. 1586 All fields after the year are optional. (The prefix D:, although also 1587 optional, is strongly recommended.) The default values for MM and DD 1588 are both 01; all other numerical fields default to zero values. A plus 1589 sign (+) as the value of the O field signifies that local time is 1590 later than UT, a minus sign (-) that local time is earlier than UT, 1591 and the letter Z that local time is equal to UT. If no UT information 1592 is specified, the relationship of the specified time to UT is 1593 considered to be unknown. Whether or not the time zone is known, the 1594 rest of the date should be specified in local time. 1595 1596 For example, December 23, 1998, at 7:52 PM, U.S. Pacific Standard 1597 Time, is represented by the string 1598 1599 D:199812231952-08'00' 1600} 1601 1602 The main difficulty is get the time zone offset. |strftime()| does this in ISO 1603 C99 (e.g. newer glibc) with \%z, but we have to work with other systems (e.g. 1604 Solaris 2.5). 1605 1606@c 1607#define TIME_STR_SIZE 30 /* minimum size for |time_str| is 24: |"D:YYYYmmddHHMMSS+HH'MM'"| */ 1608 1609static void makepdftime(PDF pdf) 1610{ 1611 struct tm lt, gmt; 1612 size_t size; 1613 int i, off, off_hours, off_mins; 1614 time_t t = pdf->start_time; 1615 char *time_str = pdf->start_time_str; 1616 1617 /* get the time */ 1618 lt = *localtime(&t); 1619 size = strftime(time_str, TIME_STR_SIZE, "D:%Y%m%d%H%M%S", <); 1620 /* expected format: "YYYYmmddHHMMSS" */ 1621 if (size == 0) { 1622 /* unexpected, contents of |time_str| is undefined */ 1623 time_str[0] = '\0'; 1624 return; 1625 } 1626 1627 /* correction for seconds: \%S can be in range 00..61, 1628 the PDF reference expects 00..59, 1629 therefore we map "60" and "61" to "59" */ 1630 if (time_str[14] == '6') { 1631 time_str[14] = '5'; 1632 time_str[15] = '9'; 1633 time_str[16] = '\0'; /* for safety */ 1634 } 1635 1636 /* get the time zone offset */ 1637 gmt = *gmtime(&t); 1638 1639 /* this calculation method was found in exim's tod.c */ 1640 off = 60 * (lt.tm_hour - gmt.tm_hour) + lt.tm_min - gmt.tm_min; 1641 if (lt.tm_year != gmt.tm_year) { 1642 off += (lt.tm_year > gmt.tm_year) ? 1440 : -1440; 1643 } else if (lt.tm_yday != gmt.tm_yday) { 1644 off += (lt.tm_yday > gmt.tm_yday) ? 1440 : -1440; 1645 } 1646 1647 if (off == 0) { 1648 time_str[size++] = 'Z'; 1649 time_str[size] = 0; 1650 } else { 1651 off_hours = off / 60; 1652 off_mins = abs(off - off_hours * 60); 1653 i = snprintf(&time_str[size], 9, "%+03d'%02d'", off_hours, off_mins); 1654 check_nprintf(i, 9); 1655 } 1656 pdf->start_time = t; 1657} 1658 1659@ @c 1660void init_start_time(PDF pdf) 1661{ 1662 assert(pdf); 1663 if (pdf->start_time == 0) { 1664 pdf->start_time = time((time_t *) NULL); 1665 pdf->start_time_str = xtalloc(TIME_STR_SIZE, char); 1666 makepdftime(pdf); 1667 } 1668} 1669 1670@ @c 1671char *getcreationdate(PDF pdf) 1672{ 1673 assert(pdf); 1674 init_start_time(pdf); 1675 return pdf->start_time_str; 1676} 1677 1678@ @c 1679void remove_pdffile(PDF pdf) 1680{ 1681 if (pdf != NULL) { 1682 if (!kpathsea_debug && pdf->file_name && (pdf->draftmode != 0)) { 1683 xfclose(pdf->file, pdf->file_name); 1684 remove(pdf->file_name); 1685 } 1686 } 1687} 1688 1689@ @c 1690void pdf_error(const char *t, const char *p) 1691{ 1692 normalize_selector(); 1693 print_err("LuaTeX error"); 1694 if (t != NULL) { 1695 tprint(" ("); 1696 tprint(t); 1697 tprint(")"); 1698 } 1699 tprint(": "); 1700 if (p != NULL) 1701 tprint(p); 1702 succumb(); 1703} 1704 1705@ @c 1706void pdf_warning(const char *t, const char *p, boolean prepend_nl, 1707 boolean append_nl) 1708{ 1709 if (prepend_nl) 1710 print_ln(); 1711 tprint("LuaTeX warning"); 1712 if (t != NULL) { 1713 tprint(" ("); 1714 tprint(t); 1715 tprint(")"); 1716 } 1717 tprint(": "); 1718 if (p != NULL) 1719 tprint(p); 1720 if (append_nl) 1721 print_ln(); 1722 if (history == spotless) 1723 history = warning_issued; 1724} 1725 1726@ Use |check_o_mode()| in the backend-specific "Implement..." chunks 1727 1728@c 1729void check_o_mode(PDF pdf, const char *s, int o_mode_bitpattern, boolean strict) 1730{ 1731 1732 char warn_string[100]; 1733 output_mode o_mode; 1734 const char *m = NULL; 1735 1736 /* in warn mode (strict == false): 1737 only check, don't do |fix_o_mode()| here! |pdf->o_mode| is left 1738 in possibly wrong state until real output, ok. 1739 */ 1740 1741 if (pdf->o_mode == OMODE_NONE) 1742 o_mode = get_o_mode(); 1743 else 1744 o_mode = pdf->o_mode; 1745 if (!((1 << o_mode) & o_mode_bitpattern)) { /* warning or error */ 1746 switch (o_mode) { 1747 case OMODE_DVI: 1748 m = "DVI"; 1749 break; 1750 case OMODE_PDF: 1751 m = "PDF"; 1752 break; 1753 case OMODE_LUA: 1754 m = "Lua"; 1755 break; 1756 default: 1757 assert(0); 1758 } 1759 snprintf(warn_string, 99, "not allowed in %s mode (\\pdfpoutput = %d)", 1760 m, (int) pdf_output); 1761 if (strict) 1762 pdf_error(s, warn_string); 1763 else 1764 pdf_warning(s, warn_string, true, true); 1765 } else if (strict) 1766 ensure_output_state(pdf, ST_HEADER_WRITTEN); 1767} 1768 1769@ @c 1770void set_job_id(PDF pdf, int year, int month, int day, int time) 1771{ 1772 char *name_string, *format_string, *s; 1773 size_t slen; 1774 int i; 1775 1776 if (pdf->job_id_string != NULL) 1777 return; 1778 1779 name_string = makecstring(job_name); 1780 format_string = makecstring(format_ident); 1781 slen = SMALL_BUF_SIZE + 1782 strlen(name_string) + strlen(format_string) + strlen(luatex_banner); 1783 s = xtalloc(slen, char); 1784 /* The Web2c version string starts with a space. */ 1785 i = snprintf(s, slen, 1786 "%.4d/%.2d/%.2d %.2d:%.2d %s %s %s", 1787 year, month, day, time / 60, time % 60, 1788 name_string, format_string, luatex_banner); 1789 check_nprintf(i, slen); 1790 pdf->job_id_string = xstrdup(s); 1791 xfree(s); 1792 xfree(name_string); 1793 xfree(format_string); 1794} 1795 1796@ @c 1797char *get_resname_prefix(PDF pdf) 1798{ 1799 static char name_str[] = 1800 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; 1801 static char prefix[7]; /* make a tag of 6 chars long */ 1802 unsigned long crc; 1803 short i; 1804 size_t base = strlen(name_str); 1805 crc = crc32(0L, Z_NULL, 0); 1806 crc = 1807 crc32(crc, (Bytef *) pdf->job_id_string, 1808 (uInt) strlen(pdf->job_id_string)); 1809 for (i = 0; i < 6; i++) { 1810 prefix[i] = name_str[crc % base]; 1811 crc /= base; 1812 } 1813 prefix[6] = '\0'; 1814 return prefix; 1815} 1816 1817@ @c 1818#define mag int_par(mag_code) 1819 1820#define pdf_xform_attr equiv(pdf_xform_attr_loc) 1821#define pdf_xform_resources equiv(pdf_xform_resources_loc) 1822 1823void pdf_begin_page(PDF pdf) 1824{ 1825 pdffloat f; 1826 scaled form_margin = 0; /* was one_bp until SVN4066 */ 1827 ensure_output_state(pdf, ST_HEADER_WRITTEN); 1828 init_pdf_pagecalculations(pdf); 1829 if (pdf->page_resources == NULL) { 1830 pdf->page_resources = xtalloc(1, pdf_resource_struct); 1831 pdf->page_resources->resources_tree = NULL; 1832 } 1833 pdf->page_resources->last_resources = 1834 pdf_create_obj(pdf, obj_type_others, 0); 1835 reset_page_resources(pdf); 1836 1837 if (global_shipping_mode == SHIPPING_PAGE) { 1838 pdf->last_page = pdf_get_obj(pdf, obj_type_page, total_pages + 1, 0); 1839 set_obj_aux(pdf, pdf->last_page, 1); /* mark that this page has been created */ 1840 pdf->last_stream = pdf_create_obj(pdf, obj_type_pagestream, 0); 1841 pdf_begin_obj(pdf, pdf->last_stream, OBJSTM_NEVER); 1842 pdf->last_thread = null; 1843 pdf_begin_dict(pdf); 1844 pdflua_begin_page(pdf); 1845 } else { 1846 assert(global_shipping_mode == SHIPPING_FORM); 1847 pdf_begin_obj(pdf, pdf_cur_form, OBJSTM_NEVER); 1848 pdf->last_stream = pdf_cur_form; 1849 1850 /* Write out Form stream header */ 1851 pdf_begin_dict(pdf); 1852 pdf_dict_add_name(pdf, "Type", "XObject"); 1853 pdf_dict_add_name(pdf, "Subtype", "Form"); 1854 if (pdf_xform_attr != null) 1855 pdf_print_toks(pdf, pdf_xform_attr); 1856 if (obj_xform_attr(pdf, pdf_cur_form) != null) { 1857 pdf_print_toks(pdf, obj_xform_attr(pdf, pdf_cur_form)); 1858 delete_token_ref(obj_xform_attr(pdf, pdf_cur_form)); 1859 set_obj_xform_attr(pdf, pdf_cur_form, null); 1860 } 1861 pdf_add_name(pdf, "BBox"); 1862 pdf_begin_array(pdf); 1863 pdf_add_bp(pdf, -form_margin); 1864 pdf_add_bp(pdf, -form_margin); 1865 pdf_add_bp(pdf, pdf->page_size.h + form_margin); 1866 pdf_add_bp(pdf, pdf->page_size.v + form_margin); 1867 pdf_end_array(pdf); 1868 pdf_dict_add_int(pdf, "FormType", 1); 1869 pdf_add_name(pdf, "Matrix"); 1870 pdf_begin_array(pdf); 1871 pdf_add_int(pdf, 1); 1872 pdf_add_int(pdf, 0); 1873 pdf_add_int(pdf, 0); 1874 pdf_add_int(pdf, 1); 1875 pdf_add_int(pdf, 0); 1876 pdf_add_int(pdf, 0); 1877 pdf_end_array(pdf); 1878 pdf_dict_add_ref(pdf, "Resources", pdf->page_resources->last_resources); 1879 } 1880 /* Start stream of page/form contents */ 1881 pdf_dict_add_streaminfo(pdf); 1882 pdf_end_dict(pdf); 1883 pdf->os->trigger_luastm = false; /* if it's true, the page stream goes through Lua */ 1884 pdf_begin_stream(pdf); 1885 if (global_shipping_mode == SHIPPING_PAGE) { 1886 /* Adjust transformation matrix for the magnification ratio */ 1887 if (mag != 1000) { 1888 setpdffloat(f, mag, 3); 1889 print_pdffloat(pdf, f); 1890 pdf_puts(pdf, " 0 0 "); 1891 print_pdffloat(pdf, f); 1892 pdf_puts(pdf, " 0 0 cm\n"); 1893 } 1894 } 1895 pos_stack_used = 0; /* start with empty stack */ 1896 1897 if (global_shipping_mode == SHIPPING_PAGE) { 1898 colorstackpagestart(); 1899 } 1900 if (global_shipping_mode == SHIPPING_PAGE) 1901 pdf_out_colorstack_startpage(pdf); 1902} 1903 1904@ @c 1905void print_pdf_table_string(PDF pdf, const char *s) 1906{ 1907 size_t len; 1908 const char *ls; 1909 lua_rawgeti(Luas, LUA_REGISTRYINDEX, lua_key_index(pdf_data)); 1910 lua_rawget(Luas, LUA_REGISTRYINDEX); 1911 lua_pushstring(Luas, s); /* s t ... */ 1912 lua_rawget(Luas, -2); /* s? t ... */ 1913 if (lua_isstring(Luas, -1)) { /* s t ... */ 1914 ls = lua_tolstring(Luas, -1, &len); 1915 if (len > 0) { 1916 if (pdf->cave == 1) 1917 pdf_out(pdf, ' '); 1918 pdf_out_block(pdf, ls, len); 1919 pdf->cave = 1; 1920 } 1921 } 1922 lua_pop(Luas, 2); /* ... */ 1923} 1924 1925@ @c 1926const char *get_pdf_table_string(const char *s) 1927{ 1928 const_lstring ls; 1929 lua_rawgeti(Luas, LUA_REGISTRYINDEX, lua_key_index(pdf_data)); 1930 lua_rawget(Luas, LUA_REGISTRYINDEX); 1931 lua_pushstring(Luas, s); /* s t ... */ 1932 lua_rawget(Luas, -2); /* s? t ... */ 1933 if (lua_isstring(Luas, -1)) { /* s t ... */ 1934 ls.s = lua_tolstring(Luas, -1, &ls.l); 1935 /* s is supposed to be anchored (e.g in the registry) 1936 so it's not garbage collected */ 1937 lua_pop(Luas, 2); /* ... */ 1938 return ls.s; 1939 } 1940 lua_pop(Luas, 2); /* ... */ 1941 return NULL ; 1942} 1943 1944@ @c 1945#define pdf_page_attr equiv(pdf_page_attr_loc) 1946#define pdf_page_resources equiv(pdf_page_resources_loc) 1947 1948void pdf_end_page(PDF pdf) 1949{ 1950 char s[64], *p; 1951 int j, annots = 0, beads = 0, callback_id; 1952 pdf_resource_struct *res_p = pdf->page_resources; 1953 pdf_resource_struct local_page_resources; 1954 pdf_object_list *annot_list, *bead_list, *link_list, *ol, *ol1; 1955 scaledpos save_cur_page_size; /* to save |pdf->page_size| during flushing pending forms */ 1956 shipping_mode_e save_shipping_mode; 1957 int procset = PROCSET_PDF; 1958 1959 /* Finish stream of page/form contents */ 1960 pdf_goto_pagemode(pdf); 1961 if (pos_stack_used > 0) { 1962 luatex_fail("%u unmatched \\pdfsave after %s shipout", 1963 (unsigned int) pos_stack_used, 1964 ((global_shipping_mode == 1965 SHIPPING_PAGE) ? "page" : "form")); 1966 } 1967 pdf_end_stream(pdf); 1968 pdf_end_obj(pdf); 1969 1970 /* hh-ls : new call back finish_pdfpage_callback */ 1971 callback_id = callback_defined(finish_pdfpage_callback); 1972 if (callback_id > 0) 1973 run_callback(callback_id, "b->",(global_shipping_mode == SHIPPING_PAGE)); 1974 1975 if (global_shipping_mode == SHIPPING_PAGE) { 1976 1977 pdf->last_pages = pdf_do_page_divert(pdf, pdf->last_page, 0); 1978 1979 /* Write out /Page object */ 1980 pdf_begin_obj(pdf, pdf->last_page, OBJSTM_ALWAYS); 1981 pdf_begin_dict(pdf); 1982 pdf_dict_add_name(pdf, "Type", "Page"); 1983 pdf_dict_add_ref(pdf, "Contents", pdf->last_stream); 1984 pdf_dict_add_ref(pdf, "Resources", res_p->last_resources); 1985 pdf_add_name(pdf, "MediaBox"); 1986 pdf_begin_array(pdf); 1987 pdf_add_int(pdf, 0); 1988 pdf_add_int(pdf, 0); 1989 pdf_add_mag_bp(pdf, pdf->page_size.h); 1990 pdf_add_mag_bp(pdf, pdf->page_size.v); 1991 pdf_end_array(pdf); 1992 if (pdf_page_attr != null) 1993 pdf_print_toks(pdf, pdf_page_attr); 1994 print_pdf_table_string(pdf, "pageattributes"); 1995 pdf_dict_add_ref(pdf, "Parent", pdf->last_pages); 1996 if (pdf->img_page_group_val != 0) { 1997 assert(pdf->img_page_group_val > 0); 1998 pdf_dict_add_ref(pdf, "Group", pdf->img_page_group_val); 1999 } 2000 annot_list = get_page_resources_list(pdf, obj_type_annot); 2001 link_list = get_page_resources_list(pdf, obj_type_link); 2002 if (annot_list != NULL || link_list != NULL) { 2003 annots = pdf_create_obj(pdf, obj_type_annots, 0); 2004 pdf_dict_add_ref(pdf, "Annots", annots); 2005 } 2006 bead_list = get_page_resources_list(pdf, obj_type_bead); 2007 if (bead_list != NULL) { 2008 beads = pdf_create_obj(pdf, obj_type_beads, 0); 2009 pdf_dict_add_ref(pdf, "B", beads); 2010 } 2011 pdf_end_dict(pdf); 2012 pdf_end_obj(pdf); 2013 pdflua_end_page(pdf, annots, beads); 2014 2015 pdf->img_page_group_val = 0; 2016 2017 /* Generate array of annotations or beads in page */ 2018 if (annot_list != NULL || link_list != NULL) { 2019 pdf_begin_obj(pdf, annots, OBJSTM_ALWAYS); 2020 pdf_begin_array(pdf); 2021 while (annot_list != NULL) { 2022 assert(annot_list->info > 0); 2023 pdf_add_ref(pdf, annot_list->info); 2024 annot_list = annot_list->link; 2025 } 2026 while (link_list != NULL) { 2027 pdf_add_ref(pdf, link_list->info); 2028 link_list = link_list->link; 2029 } 2030 pdf_end_array(pdf); 2031 pdf_end_obj(pdf); 2032 } 2033 if (bead_list != NULL) { 2034 pdf_begin_obj(pdf, beads, OBJSTM_ALWAYS); 2035 pdf_begin_array(pdf); 2036 while (bead_list != NULL) { 2037 pdf_add_ref(pdf, bead_list->info); 2038 bead_list = bead_list->link; 2039 } 2040 pdf_end_array(pdf); 2041 pdf_end_obj(pdf); 2042 } 2043 } 2044 2045 /* Write out resource lists */ 2046 /* Write out pending raw objects */ 2047 ol = get_page_resources_list(pdf, obj_type_obj); 2048 while (ol != NULL) { 2049 if (!is_obj_written(pdf, ol->info)) 2050 pdf_write_obj(pdf, ol->info); 2051 ol = ol->link; 2052 } 2053 2054 /* Write out pending forms */ 2055 /* When flushing pending forms we need to save and restore resource lists 2056 which are also used by page shipping. 2057 Saving and restoring |pdf->page_size| is needed for proper 2058 writing out pending PDF marks. */ 2059 ol = get_page_resources_list(pdf, obj_type_xform); 2060 while (ol != NULL) { 2061 if (!is_obj_written(pdf, ol->info)) { 2062 pdf_cur_form = ol->info; 2063 save_cur_page_size = pdf->page_size; 2064 save_shipping_mode = global_shipping_mode; 2065 pdf->page_resources = &local_page_resources; 2066 local_page_resources.resources_tree = NULL; 2067 ship_out(pdf, obj_xform_box(pdf, pdf_cur_form), SHIPPING_FORM); 2068 /* Restore page size and page resources */ 2069 pdf->page_size = save_cur_page_size; 2070 global_shipping_mode = save_shipping_mode; 2071 destroy_page_resources_tree(pdf); 2072 pdf->page_resources = res_p; 2073 } 2074 ol = ol->link; 2075 } 2076 2077 /* Write out pending images */ 2078 ol = get_page_resources_list(pdf, obj_type_ximage); 2079 while (ol != NULL) { 2080 if (!is_obj_written(pdf, ol->info)) 2081 pdf_write_image(pdf, ol->info); 2082 ol = ol->link; 2083 } 2084 2085 if (global_shipping_mode == SHIPPING_PAGE) { 2086 /* Write out pending PDF marks */ 2087 /* Write out PDF annotations */ 2088 ol = get_page_resources_list(pdf, obj_type_annot); 2089 while (ol != NULL) { 2090 if (ol->info > 0 && obj_type(pdf, ol->info) == obj_type_annot) { 2091 j = obj_annot_ptr(pdf, ol->info); /* |j| points to |pdf_annot_node| */ 2092 pdf_begin_obj(pdf, ol->info, OBJSTM_ALWAYS); 2093 pdf_begin_dict(pdf); 2094 pdf_dict_add_name(pdf, "Type", "Annot"); 2095 pdf_print_toks(pdf, pdf_annot_data(j)); 2096 pdf_rectangle(pdf, j); 2097 pdf_end_dict(pdf); 2098 pdf_end_obj(pdf); 2099 } 2100 ol = ol->link; 2101 } 2102 2103 /* Write out PDF link annotations */ 2104 if ((ol = get_page_resources_list(pdf, obj_type_link)) != NULL) { 2105 while (ol != NULL) { 2106 j = obj_annot_ptr(pdf, ol->info); 2107 pdf_begin_obj(pdf, ol->info, OBJSTM_ALWAYS); 2108 pdf_begin_dict(pdf); 2109 pdf_dict_add_name(pdf, "Type", "Annot"); 2110 if (pdf_action_type(pdf_link_action(j)) != pdf_action_user) 2111 pdf_dict_add_name(pdf, "Subtype", "Link"); 2112 if (pdf_link_attr(j) != null) 2113 pdf_print_toks(pdf, pdf_link_attr(j)); 2114 pdf_rectangle(pdf, j); 2115 if (pdf_action_type(pdf_link_action(j)) != pdf_action_user) 2116 pdf_puts(pdf, "/A "); 2117 write_action(pdf, pdf_link_action(j)); 2118 pdf_end_dict(pdf); 2119 pdf_end_obj(pdf); 2120 ol = ol->link; 2121 } 2122 /* Flush |pdf_start_link_node|'s created by |append_link| */ 2123 ol = get_page_resources_list(pdf, obj_type_link); 2124 while (ol != NULL) { 2125 j = obj_annot_ptr(pdf, ol->info); 2126 /* nodes with |subtype = pdf_link_data_node| were created by |append_link| and 2127 must be flushed here, as they are not linked in any list */ 2128 if (subtype(j) == pdf_link_data_node) 2129 flush_node(j); 2130 ol = ol->link; 2131 } 2132 } 2133 2134 /* Write out PDF mark destinations */ 2135 write_out_pdf_mark_destinations(pdf); 2136 /* Write out PDF bead rectangle specifications */ 2137 print_bead_rectangles(pdf); 2138 2139 } 2140 /* Write out resources dictionary */ 2141 pdf_begin_obj(pdf, res_p->last_resources, OBJSTM_ALWAYS); 2142 pdf_begin_dict(pdf); 2143 /* Print additional resources */ 2144 if (global_shipping_mode == SHIPPING_PAGE) { 2145 if (pdf_page_resources != null) 2146 pdf_print_toks(pdf, pdf_page_resources); 2147 print_pdf_table_string(pdf, "pageresources"); 2148 } else { 2149 if (pdf_xform_resources != null) 2150 pdf_print_toks(pdf, pdf_xform_resources); 2151 if (obj_xform_resources(pdf, pdf_cur_form) != null) { 2152 pdf_print_toks(pdf, obj_xform_resources(pdf, pdf_cur_form)); 2153 delete_token_ref(obj_xform_resources(pdf, pdf_cur_form)); 2154 set_obj_xform_resources(pdf, pdf_cur_form, null); 2155 } 2156 } 2157 2158 /* Generate font resources */ 2159 if ((ol = get_page_resources_list(pdf, obj_type_font)) != NULL) { 2160 pdf_add_name(pdf, "Font"); 2161 pdf_begin_dict(pdf); 2162 while (ol != NULL) { 2163 assert(ol->info > 0); /* always base font: an object number */ 2164 p = s; 2165 p += snprintf(p, 20, "F%i", obj_info(pdf, ol->info)); 2166 if (pdf->resname_prefix != NULL) 2167 p += snprintf(p, 20, "%s", pdf->resname_prefix); 2168 pdf_dict_add_ref(pdf, s, ol->info); 2169 ol = ol->link; 2170 } 2171 pdf_end_dict(pdf); 2172 procset |= PROCSET_TEXT; 2173 } 2174 2175 /* Generate XObject resources */ 2176 ol = get_page_resources_list(pdf, obj_type_xform); 2177 ol1 = get_page_resources_list(pdf, obj_type_ximage); 2178 if (ol != NULL || ol1 != NULL) { 2179 pdf_add_name(pdf, "XObject"); 2180 pdf_begin_dict(pdf); 2181 while (ol != NULL) { 2182 p = s; 2183 p += snprintf(p, 20, "Fm%i", obj_info(pdf, ol->info)); 2184 if (pdf->resname_prefix != NULL) 2185 p += snprintf(p, 20, "%s", pdf->resname_prefix); 2186 pdf_dict_add_ref(pdf, s, ol->info); 2187 ol = ol->link; 2188 } 2189 while (ol1 != null) { 2190 p = s; 2191 p += snprintf(p, 20, "Im%i", obj_info(pdf, ol1->info)); 2192 if (pdf->resname_prefix != NULL) 2193 p += snprintf(p, 20, "%s", pdf->resname_prefix); 2194 pdf_dict_add_ref(pdf, s, ol1->info); 2195 procset |= img_procset(idict_array[obj_data_ptr(pdf, ol1->info)]); 2196 ol1 = ol1->link; 2197 } 2198 pdf_end_dict(pdf); 2199 } 2200 2201 /* Generate ProcSet */ 2202 pdf_add_name(pdf, "ProcSet"); 2203 pdf_begin_array(pdf); 2204 if ((procset & PROCSET_PDF) != 0) 2205 pdf_add_name(pdf, "PDF"); 2206 if ((procset & PROCSET_TEXT) != 0) 2207 pdf_add_name(pdf, "Text"); 2208 if ((procset & PROCSET_IMAGE_B) != 0) 2209 pdf_add_name(pdf, "ImageB"); 2210 if ((procset & PROCSET_IMAGE_C) != 0) 2211 pdf_add_name(pdf, "ImageC"); 2212 if ((procset & PROCSET_IMAGE_I) != 0) 2213 pdf_add_name(pdf, "ImageI"); 2214 pdf_end_array(pdf); 2215 pdf_end_dict(pdf); 2216 pdf_end_obj(pdf); 2217} 2218 2219@* Finishing the PDF output file. 2220 2221@ Destinations that have been referenced but don't exists have 2222|obj_dest_ptr=null|. Leaving them undefined might cause troubles for 2223PDF browsers, so we need to fix them; they point to the last page. 2224 2225@c 2226static void check_nonexisting_destinations(PDF pdf) 2227{ 2228 int k; 2229 for (k = pdf->head_tab[obj_type_dest]; k != 0; k = obj_link(pdf, k)) { 2230 if (obj_dest_ptr(pdf, k) == null) { 2231 pdf_warning("dest", NULL, false, false); 2232 if (obj_info(pdf, k) < 0) { 2233 tprint("name{"); 2234 print(-obj_info(pdf, k)); 2235 tprint("}"); 2236 } else { 2237 tprint("num"); 2238 print_int(obj_info(pdf, k)); 2239 } 2240 tprint 2241 (" has been referenced but does not exist, replaced by a fixed one"); 2242 print_ln(); 2243 print_ln(); 2244 2245 pdf_begin_obj(pdf, k, OBJSTM_ALWAYS); 2246 pdf_begin_array(pdf); 2247 pdf_add_ref(pdf, pdf->last_page); 2248 pdf_add_name(pdf, "Fit"); 2249 pdf_end_array(pdf); 2250 pdf_end_obj(pdf); 2251 } 2252 } 2253} 2254 2255@ @c 2256static void check_nonexisting_pages(PDF pdf) 2257{ 2258 struct avl_traverser t; 2259 oentry *p; 2260 struct avl_table *page_tree = pdf->obj_tree[obj_type_page]; 2261 avl_t_init(&t, page_tree); 2262 /* search from the end backward until the last real page is found */ 2263 for (p = avl_t_last(&t, page_tree); 2264 p != NULL && obj_aux(pdf, p->objptr) == 0; p = avl_t_prev(&t)) { 2265 pdf_warning("dest", "Page ", false, false); 2266 print_int(obj_info(pdf, p->objptr)); 2267 tprint(" has been referenced but does not exist!"); 2268 print_ln(); 2269 print_ln(); 2270 } 2271} 2272 2273@ If the same keys in a dictionary are given several times, then it is not 2274defined which value is choosen by an application. Therefore the keys 2275|/Producer| and |/Creator| are only set if the token list 2276|pdf_info_toks| converted to a string does not contain these key strings. 2277 2278@c 2279static boolean substr_of_str(const char *s, const char *t) 2280{ 2281 if (strstr(t, s) == NULL) 2282 return false; 2283 return true; 2284} 2285 2286static int pdf_print_info(PDF pdf, int luatexversion, 2287 str_number luatexrevision) 2288{ /* print info object */ 2289 boolean creator_given, producer_given, creationdate_given, moddate_given, 2290 trapped_given; 2291 char *s = NULL; 2292 const char *p = NULL; 2293 int k, len = 0; 2294 k = pdf_create_obj(pdf, obj_type_info, 0); 2295 pdf_begin_obj(pdf, k, 3); /* keep Info readable unless explicitely forced */ 2296 creator_given = false; 2297 producer_given = false; 2298 creationdate_given = false; 2299 moddate_given = false; 2300 trapped_given = false; 2301 pdf_begin_dict(pdf); 2302 if (pdf_info_toks != 0) { 2303 s = tokenlist_to_cstring(pdf_info_toks, true, &len); 2304 creator_given = substr_of_str("/Creator", s); 2305 producer_given = substr_of_str("/Producer", s); 2306 creationdate_given = substr_of_str("/CreationDate", s); 2307 moddate_given = substr_of_str("/ModDate", s); 2308 trapped_given = substr_of_str("/Trapped", s); 2309 } 2310 p = get_pdf_table_string("info"); 2311 if (p && strlen(p) > 0) { 2312 creator_given = creator_given || substr_of_str("/Creator", p); 2313 producer_given = producer_given || substr_of_str("/Producer", p); 2314 creationdate_given = creationdate_given || substr_of_str("/CreationDate", p); 2315 moddate_given = moddate_given || substr_of_str("/ModDate", p); 2316 trapped_given = trapped_given || substr_of_str("/Trapped", p); 2317 } 2318 if (pdf_info_toks != null) { 2319 if (len > 0) { 2320 pdf_out(pdf, '\n'); 2321 pdf_puts(pdf, s); 2322 pdf_out(pdf, '\n'); 2323 xfree(s); 2324 } 2325 delete_token_ref(pdf_info_toks); 2326 pdf_info_toks = null; 2327 } 2328 if (p && strlen(p) > 0) { 2329 pdf_out(pdf, '\n'); 2330 pdf_puts(pdf, p); /* no free, pointer */ 2331 pdf_out(pdf, '\n'); 2332 } 2333 if (!producer_given) { 2334 /* Print the Producer key */ 2335 pdf_add_name(pdf, "Producer"); 2336 pdf_puts(pdf, " (LuaTeX-"); 2337 pdf_print_int(pdf, luatexversion / 100); 2338 pdf_out(pdf, '.'); 2339 pdf_print_int(pdf, luatexversion % 100); 2340 pdf_out(pdf, '.'); 2341 pdf_print(pdf, luatexrevision); 2342 pdf_out(pdf, ')'); 2343 } 2344 if (!creator_given) 2345 pdf_dict_add_string(pdf, "Creator", "TeX"); 2346 if (!creationdate_given) { 2347 init_start_time(pdf); 2348 pdf_dict_add_string(pdf, "CreationDate", pdf->start_time_str); 2349 } 2350 if (!moddate_given) { 2351 init_start_time(pdf); 2352 pdf_dict_add_string(pdf, "ModDate", pdf->start_time_str); 2353 } 2354 if (!trapped_given) { 2355 pdf_dict_add_name(pdf, "Trapped", "False"); 2356 } 2357 pdf_dict_add_string(pdf, "PTEX.Fullbanner", luatex_banner); 2358 pdf_end_dict(pdf); 2359 pdf_end_obj(pdf); 2360 return k; 2361} 2362 2363static void build_free_object_list(PDF pdf) 2364{ 2365 int k, l; 2366 l = 0; 2367 set_obj_fresh(pdf, l); /* null object at begin of list of free objects */ 2368 for (k = 1; k <= pdf->obj_ptr; k++) { 2369 if (!is_obj_written(pdf, k)) { 2370 set_obj_link(pdf, l, k); 2371 l = k; 2372 } 2373 } 2374 set_obj_link(pdf, l, 0); 2375} 2376 2377@ Now the finish of PDF output file. At this moment all Page objects 2378are already written completely to PDF output file. 2379 2380@c 2381void finish_pdf_file(PDF pdf, int luatexversion, str_number luatexrevision) 2382{ 2383 int i, j, k; 2384 int root, info, xref_stm = 0, outlines, threads, names_tree; 2385 size_t xref_offset_width; 2386 int callback_id = callback_defined(stop_run_callback); 2387 int callback_id1 = callback_defined(finish_pdffile_callback); 2388 2389 if (total_pages == 0) { 2390 if (callback_id == 0) { 2391 tprint_nl("No pages of output."); 2392 print_ln(); 2393 } else if (callback_id > 0) { 2394 run_callback(callback_id, "->"); 2395 } 2396 if (pdf->gone > 0) 2397 garbage_warning(); 2398 } else { 2399 if (pdf->draftmode == 0) { 2400 pdf_flush(pdf); /* to make sure that the output file name has been already created */ 2401 flush_jbig2_page0_objects(pdf); /* flush page 0 objects from JBIG2 images, if any */ 2402 if (callback_id1 > 0) 2403 run_callback(callback_id1, "->"); 2404 2405 check_nonexisting_pages(pdf); 2406 check_nonexisting_destinations(pdf); 2407 2408 /* Output fonts definition */ 2409 for (k = 1; k <= max_font_id(); k++) { 2410 if (font_used(k) && (pdf_font_num(k) < 0)) { 2411 i = -pdf_font_num(k); 2412 assert(pdf_font_num(i) > 0); 2413 for (j = font_bc(k); j <= font_ec(k); j++) 2414 if (quick_char_exists(k, j) && pdf_char_marked(k, j)) 2415 pdf_mark_char(i, j); 2416 if ((pdf_font_attr(i) == 0) && (pdf_font_attr(k) != 0)) { 2417 set_pdf_font_attr(i, pdf_font_attr(k)); 2418 } else if ((pdf_font_attr(k) == 0) 2419 && (pdf_font_attr(i) != 0)) { 2420 set_pdf_font_attr(k, pdf_font_attr(i)); 2421 } else if ((pdf_font_attr(i) != 0) 2422 && (pdf_font_attr(k) != 0) 2423 && 2424 (!str_eq_str 2425 (pdf_font_attr(i), pdf_font_attr(k)))) { 2426 pdf_warning("\\pdffontattr", "fonts ", false, false); 2427 print_font_identifier(i); 2428 tprint(" and "); 2429 print_font_identifier(k); 2430 tprint 2431 (" have conflicting attributes; I will ignore the attributes assigned to "); 2432 print_font_identifier(i); 2433 print_ln(); 2434 print_ln(); 2435 } 2436 } 2437 } 2438 pdf->gen_tounicode = pdf_gen_tounicode; 2439 k = pdf->head_tab[obj_type_font]; 2440 while (k != 0) { 2441 int f = obj_info(pdf, k); 2442 assert(pdf_font_num(f) > 0); 2443 assert(pdf_font_num(f) == k); 2444 do_pdf_font(pdf, f); 2445 k = obj_link(pdf, k); 2446 } 2447 write_fontstuff(pdf); 2448 2449 pdf->last_pages = output_pages_tree(pdf); 2450 pdflua_output_pages_tree(pdf); 2451 /* Output outlines */ 2452 outlines = print_outlines(pdf); 2453 2454 /* Output name tree */ 2455 /* The name tree is very similiar to Pages tree so its construction should be 2456 certain from Pages tree construction. For intermediate node |obj_info| will be 2457 the first name and |obj_link| will be the last name in \.{\\Limits} array. 2458 Note that |pdf_dest_names_ptr| will be less than |obj_ptr|, so we test if 2459 |k < pdf_dest_names_ptr| then |k| is index of leaf in |dest_names|; else 2460 |k| will be index in |obj_tab| of some intermediate node. 2461 */ 2462 names_tree = output_name_tree(pdf); 2463 2464 /* Output article threads */ 2465 if (pdf->head_tab[obj_type_thread] != 0) { 2466 threads = pdf_create_obj(pdf, obj_type_others, 0); 2467 pdf_begin_obj(pdf, threads, OBJSTM_ALWAYS); 2468 pdf_begin_array(pdf); 2469 k = pdf->head_tab[obj_type_thread]; 2470 while (k != 0) { 2471 pdf_add_ref(pdf, k); 2472 k = obj_link(pdf, k); 2473 } 2474 pdf_end_array(pdf); 2475 pdf_end_obj(pdf); 2476 k = pdf->head_tab[obj_type_thread]; 2477 while (k != 0) { 2478 out_thread(pdf, k); 2479 k = obj_link(pdf, k); 2480 } 2481 } else { 2482 threads = 0; 2483 } 2484 2485 /* Output the /Catalog object */ 2486 root = pdf_create_obj(pdf, obj_type_catalog, 0); 2487 pdf_begin_obj(pdf, root, OBJSTM_ALWAYS); 2488 pdf_begin_dict(pdf); 2489 pdf_dict_add_name(pdf, "Type", "Catalog"); 2490 pdf_dict_add_ref(pdf, "Pages", pdf->last_pages); 2491 if (threads != 0) 2492 pdf_dict_add_ref(pdf, "Threads", threads); 2493 if (outlines != 0) 2494 pdf_dict_add_ref(pdf, "Outlines", outlines); 2495 if (names_tree != 0) 2496 pdf_dict_add_ref(pdf, "Names", names_tree); 2497 if (pdf_catalog_toks != null) { 2498 pdf_print_toks(pdf, pdf_catalog_toks); 2499 delete_token_ref(pdf_catalog_toks); 2500 pdf_catalog_toks = null; 2501 } 2502 print_pdf_table_string(pdf, "catalog"); 2503 if (pdf_catalog_openaction != 0) 2504 pdf_dict_add_ref(pdf, "OpenAction", pdf_catalog_openaction); 2505 pdf_end_dict(pdf); 2506 pdf_end_obj(pdf); 2507 2508 /* last candidate for object stream */ 2509 info = pdf_print_info(pdf, luatexversion, luatexrevision); /* final object for pdf->os_enable == false */ 2510 2511 if (pdf->os_enable) { 2512 pdf_buffer_select(pdf, OBJSTM_BUF); 2513 pdf_os_write_objstream(pdf); 2514 pdf_flush(pdf); 2515 pdf_buffer_select(pdf, PDFOUT_BUF); 2516 /* Output the cross-reference stream dictionary */ 2517 xref_stm = pdf_create_obj(pdf, obj_type_others, 0); 2518 pdf_begin_obj(pdf, xref_stm, OBJSTM_NEVER); /* final object for pdf->os_enable == true */ 2519 if ((obj_offset(pdf, pdf->obj_ptr) / 256) > 16777215) 2520 xref_offset_width = 5; 2521 else if (obj_offset(pdf, pdf->obj_ptr) > 16777215) 2522 xref_offset_width = 4; 2523 else if (obj_offset(pdf, pdf->obj_ptr) > 65535) 2524 xref_offset_width = 3; 2525 else 2526 xref_offset_width = 2; 2527 /* Build a linked list of free objects */ 2528 build_free_object_list(pdf); 2529 pdf_begin_dict(pdf); 2530 pdf_dict_add_name(pdf, "Type", "XRef"); 2531 pdf_add_name(pdf, "Index"); 2532 pdf_begin_array(pdf); 2533 pdf_add_int(pdf, 0); 2534 pdf_add_int(pdf, pdf->obj_ptr + 1); 2535 pdf_end_array(pdf); 2536 pdf_dict_add_int(pdf, "Size", pdf->obj_ptr + 1); 2537 pdf_add_name(pdf, "W"); 2538 pdf_begin_array(pdf); 2539 pdf_add_int(pdf, 1); 2540 pdf_add_int(pdf, (int) xref_offset_width); 2541 pdf_add_int(pdf, 1); 2542 pdf_end_array(pdf); 2543 pdf_dict_add_ref(pdf, "Root", root); 2544 pdf_dict_add_ref(pdf, "Info", info); 2545 if (pdf_trailer_toks != null) { 2546 pdf_print_toks(pdf, pdf_trailer_toks); 2547 delete_token_ref(pdf_trailer_toks); 2548 pdf_trailer_toks = null; 2549 } 2550 print_pdf_table_string(pdf, "trailer"); 2551 print_ID(pdf); 2552 pdf_dict_add_streaminfo(pdf); 2553 pdf_end_dict(pdf); 2554 pdf_begin_stream(pdf); 2555 for (k = 0; k <= pdf->obj_ptr; k++) { 2556 if (!is_obj_written(pdf, k)) { /* a free object */ 2557 pdf_out(pdf, 0); 2558 pdf_out_bytes(pdf, obj_link(pdf, k), xref_offset_width); 2559 pdf_out(pdf, 255); 2560 } else if (obj_os_idx(pdf, k) == PDF_OS_MAX_OBJS) { /* object not in object stream */ 2561 pdf_out(pdf, 1); 2562 pdf_out_bytes(pdf, obj_offset(pdf, k), 2563 xref_offset_width); 2564 pdf_out(pdf, 0); 2565 } else { /* object in object stream */ 2566 pdf_out(pdf, 2); 2567 pdf_out_bytes(pdf, obj_offset(pdf, k), 2568 xref_offset_width); 2569 pdf_out(pdf, obj_os_idx(pdf, k)); 2570 } 2571 } 2572 pdf_end_stream(pdf); 2573 pdf_end_obj(pdf); 2574 /* TODO: generate a debug version of the crossref */ 2575 2576 pdf_flush(pdf); 2577 } else { 2578 /* Output the |obj_tab| */ 2579 /* Build a linked list of free objects */ 2580 build_free_object_list(pdf); 2581 2582 pdf_save_offset(pdf); 2583 pdf_puts(pdf, "xref\n"); 2584 pdf_puts(pdf, "0 "); 2585 pdf_print_int_ln(pdf, pdf->obj_ptr + 1); 2586 pdf_print_fw_int(pdf, obj_link(pdf, 0), 10); 2587 pdf_puts(pdf, " 65535 f \n"); 2588 for (k = 1; k <= pdf->obj_ptr; k++) { 2589 if (!is_obj_written(pdf, k)) { 2590 pdf_print_fw_int(pdf, obj_link(pdf, k), 10); 2591 pdf_puts(pdf, " 00000 f \n"); 2592 } else { 2593 pdf_print_fw_int(pdf, obj_offset(pdf, k), 10); 2594 pdf_puts(pdf, " 00000 n \n"); 2595 } 2596 } 2597 2598 } 2599 2600 /* Output the trailer */ 2601 if (!pdf->os_enable) { 2602 pdf_puts(pdf, "trailer\n"); 2603 pdf_begin_dict(pdf); 2604 pdf_dict_add_int(pdf, "Size", pdf->obj_ptr + 1); 2605 pdf_dict_add_ref(pdf, "Root", root); 2606 pdf_dict_add_ref(pdf, "Info", info); 2607 if (pdf_trailer_toks != null) { 2608 pdf_print_toks(pdf, pdf_trailer_toks); 2609 delete_token_ref(pdf_trailer_toks); 2610 pdf_trailer_toks = null; 2611 } 2612 print_ID(pdf); 2613 pdf_end_dict(pdf); 2614 pdf_out(pdf, '\n'); 2615 } 2616 pdf_puts(pdf, "startxref\n"); 2617 pdf->cave = 0; 2618 if (pdf->os_enable) 2619 pdf_add_longint(pdf, (longinteger) obj_offset(pdf, xref_stm)); 2620 else 2621 pdf_add_longint(pdf, (longinteger) pdf->save_offset); 2622 pdf_puts(pdf, "\n%%EOF\n"); 2623 2624 pdf_flush(pdf); 2625 2626 if (callback_id == 0) { 2627 tprint_nl("Output written on "); 2628 tprint(pdf->file_name); 2629 tprint(" ("); 2630 print_int(total_pages); 2631 tprint(" page"); 2632 if (total_pages != 1) 2633 print_char('s'); 2634 tprint(", "); 2635 print_int(pdf_offset(pdf)); 2636 tprint(" bytes)."); 2637 print_ln(); 2638 } else if (callback_id > 0) { 2639 run_callback(callback_id, "->"); 2640 } 2641 } 2642 libpdffinish(pdf); 2643 if (pdf->draftmode == 0) 2644 close_file(pdf->file); 2645 else 2646 pdf_warning(NULL, 2647 "\\pdfdraftmode enabled, not changing output pdf", 2648 true, true); 2649 } 2650 2651 if (callback_id == 0) { 2652 if (log_opened_global) { 2653 fprintf(log_file, 2654 "\nPDF statistics: %d PDF objects out of %d (max. %d)\n", 2655 (int) pdf->obj_ptr, (int) pdf->obj_tab_size, 2656 (int) sup_obj_tab_size); 2657 if (pdf->os->ostm_ctr > 0) { 2658 fprintf(log_file, 2659 " %d compressed objects within %d object stream%s\n", 2660 (int) pdf->os->o_ctr, (int) pdf->os->ostm_ctr, 2661 (pdf->os->ostm_ctr > 1 ? "s" : "")); 2662 } 2663 fprintf(log_file, " %d named destinations out of %d (max. %d)\n", 2664 (int) pdf->dest_names_ptr, (int) pdf->dest_names_size, 2665 (int) sup_dest_names_size); 2666 fprintf(log_file, 2667 " %d words of extra memory for PDF output out of %d (max. %d)\n", 2668 (int) pdf->mem_ptr, (int) pdf->mem_size, 2669 (int) sup_pdf_mem_size); 2670 } 2671 } 2672} 2673 2674@ @c 2675void scan_pdfcatalog(PDF pdf) 2676{ 2677 halfword p; 2678 scan_pdf_ext_toks(); 2679 pdf_catalog_toks = concat_tokens(pdf_catalog_toks, def_ref); 2680 if (scan_keyword("openaction")) { 2681 if (pdf_catalog_openaction != 0) { 2682 pdf_error("ext1", "duplicate of openaction"); 2683 } else { 2684 check_o_mode(pdf, "\\pdfcatalog", 1 << OMODE_PDF, true); 2685 p = scan_action(pdf); 2686 pdf_catalog_openaction = pdf_create_obj(pdf, obj_type_others, 0); 2687 pdf_begin_obj(pdf, pdf_catalog_openaction, OBJSTM_ALWAYS); 2688 write_action(pdf, p); 2689 pdf_end_obj(pdf); 2690 delete_action_ref(p); 2691 } 2692 } 2693} 2694