1% pdftoepdf.w 2% 3% Copyright 1996-2006 Han The Thanh <thanh@@pdftex.org> 4% Copyright 2006-2012 Taco Hoekwater <taco@@luatex.org> 5% 6% This file is part of LuaTeX. 7% 8% LuaTeX is free software; you can redistribute it and/or modify it under 9% the terms of the GNU General Public License as published by the Free 10% Software Foundation; either version 2 of the License, or (at your 11% option) any later version. 12% 13% LuaTeX is distributed in the hope that it will be useful, but WITHOUT 14% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 15% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16% License for more details. 17% 18% You should have received a copy of the GNU General Public License along 19% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. 20 21@ @c 22 23 24// define DEBUG 25#define __STDC_FORMAT_MACROS /* for PRId64 etc. */ 26 27#include "image/epdf.h" 28 29// This file is mostly C and not very much C++; it's just used to interface 30// the functions of xpdf, which happens to be written in C++. 31 32static GBool isInit = gFalse; 33 34//********************************************************************** 35// Maintain AVL tree of all PDF files for embedding 36 37static avl_table *PdfDocumentTree = NULL; 38 39// AVL sort PdfDocument into PdfDocumentTree by file_path 40 41static int CompPdfDocument(const void *pa, const void *pb, void * /*p */ ) 42{ 43 return strcmp(((const PdfDocument *) pa)->file_path, 44 ((const PdfDocument *) pb)->file_path); 45} 46 47// Returns pointer to PdfDocument structure for PDF file. 48 49static PdfDocument *findPdfDocument(char *file_path) 50{ 51 PdfDocument *pdf_doc, tmp; 52 assert(file_path != NULL); 53 if (PdfDocumentTree == NULL) 54 return NULL; 55 tmp.file_path = file_path; 56 pdf_doc = (PdfDocument *) avl_find(PdfDocumentTree, &tmp); 57 return pdf_doc; 58} 59 60#define PDF_CHECKSUM_SIZE 32 61 62static char *get_file_checksum(char *a, file_error_mode fe) 63{ 64 struct stat finfo; 65 char *ck = NULL; 66 if (stat(a, &finfo) == 0) { 67 off_t size = finfo.st_size; 68 time_t mtime = finfo.st_mtime; 69 ck = (char *) malloc(PDF_CHECKSUM_SIZE); 70 if (ck == NULL) 71 luatex_fail("PDF inclusion: out of memory while processing '%s'", 72 a); 73 snprintf(ck, PDF_CHECKSUM_SIZE, "%" PRIu64 "_%" PRIu64, (uint64_t) size, 74 (uint64_t) mtime); 75 } else { 76 switch (fe) { 77 case FE_FAIL: 78 luatex_fail("PDF inclusion: could not stat() file '%s'", a); 79 break; 80 case FE_RETURN_NULL: 81 if (ck != NULL) 82 free(ck); 83 ck = NULL; 84 break; 85 default: 86 assert(0); 87 } 88 } 89 return ck; 90} 91 92// Returns pointer to PdfDocument structure for PDF file. 93// Creates a new PdfDocument structure if it doesn't exist yet. 94// When fe = FE_RETURN_NULL, the function returns NULL in error case. 95 96PdfDocument *refPdfDocument(char *file_path, file_error_mode fe) 97{ 98 char *checksum; 99 PdfDocument *pdf_doc; 100 PDFDoc *doc = NULL; 101 GooString *docName = NULL; 102 int new_flag = 0; 103 if ((checksum = get_file_checksum(file_path, fe)) == NULL) { 104 assert(fe == FE_RETURN_NULL); 105 return (PdfDocument *) NULL; 106 } 107 assert(checksum != NULL); 108 if ((pdf_doc = findPdfDocument(file_path)) == NULL) { 109#ifdef DEBUG 110 fprintf(stderr, "\nDEBUG: New PdfDocument %s\n", file_path); 111#endif 112 new_flag = 1; 113 pdf_doc = new PdfDocument; 114 pdf_doc->file_path = xstrdup(file_path); 115 pdf_doc->checksum = checksum; 116 pdf_doc->doc = NULL; 117 pdf_doc->inObjList = NULL; 118 pdf_doc->ObjMapTree = NULL; 119 pdf_doc->occurences = 0; // 0 = unreferenced 120 pdf_doc->pc = 0; 121 } else { 122#ifdef DEBUG 123 fprintf(stderr, "\nDEBUG: Found PdfDocument %s (%d)\n", 124 pdf_doc->file_path, pdf_doc->occurences); 125#endif 126 assert(pdf_doc->checksum != NULL); 127 if (strncmp(pdf_doc->checksum, checksum, PDF_CHECKSUM_SIZE) != 0) { 128 luatex_fail("PDF inclusion: file has changed '%s'", file_path); 129 } 130 free(checksum); 131 } 132 assert(pdf_doc != NULL); 133 if (pdf_doc->doc == NULL) { 134#ifdef DEBUG 135 fprintf(stderr, "\nDEBUG: New PDFDoc %s (%d)\n", 136 pdf_doc->file_path, pdf_doc->occurences); 137#endif 138 docName = new GooString(file_path); 139 doc = new PDFDoc(docName); // takes ownership of docName 140 pdf_doc->pc++; 141 142 if (!doc->isOk() || !doc->okToPrint()) { 143 switch (fe) { 144 case FE_FAIL: 145 luatex_fail("xpdf: reading PDF image failed"); 146 break; 147 case FE_RETURN_NULL: 148 delete doc; 149 // delete docName; 150 if (new_flag == 1) { 151 if (pdf_doc->file_path != NULL) 152 free(pdf_doc->file_path); 153 if (pdf_doc->checksum != NULL) 154 free(pdf_doc->checksum); 155 delete pdf_doc; 156 } 157 return (PdfDocument *) NULL; 158 break; 159 default: 160 assert(0); 161 } 162 } 163 pdf_doc->doc = doc; 164 } 165 // PDF file could be opened without problems, checksum ok. 166 if (PdfDocumentTree == NULL) 167 PdfDocumentTree = avl_create(CompPdfDocument, NULL, &avl_xallocator); 168 if ((PdfDocument *) avl_find(PdfDocumentTree, pdf_doc) == NULL) { 169 void **aa = avl_probe(PdfDocumentTree, pdf_doc); 170 assert(aa != NULL); 171 } 172 pdf_doc->occurences++; 173#ifdef DEBUG 174 fprintf(stderr, "\nDEBUG: Incrementing %s (%d)\n", 175 pdf_doc->file_path, pdf_doc->occurences); 176#endif 177 return pdf_doc; 178} 179 180//********************************************************************** 181// AVL sort ObjMap into ObjMapTree by object number and generation 182 183// keep the ObjMap struct small, as these are accumulated until the end 184 185struct ObjMap { 186 Ref in; // object num/gen in orig. PDF file 187 int out_num; // object num after embedding (gen == 0) 188}; 189 190static int CompObjMap(const void *pa, const void *pb, void * /*p */ ) 191{ 192 const Ref *a = &(((const ObjMap *) pa)->in); 193 const Ref *b = &(((const ObjMap *) pb)->in); 194 if (a->num > b->num) 195 return 1; 196 if (a->num < b->num) 197 return -1; 198 if (a->gen == b->gen) // most likely gen == 0 anyway 199 return 0; 200 if (a->gen < b->gen) 201 return -1; 202 return 1; 203} 204 205static ObjMap *findObjMap(PdfDocument * pdf_doc, Ref in) 206{ 207 ObjMap *obj_map, tmp; 208 assert(pdf_doc != NULL); 209 if (pdf_doc->ObjMapTree == NULL) 210 return NULL; 211 tmp.in = in; 212 obj_map = (ObjMap *) avl_find(pdf_doc->ObjMapTree, &tmp); 213 return obj_map; 214} 215 216static void addObjMap(PdfDocument * pdf_doc, Ref in, int out_num) 217{ 218 ObjMap *obj_map = NULL; 219 assert(findObjMap(pdf_doc, in) == NULL); 220 if (pdf_doc->ObjMapTree == NULL) 221 pdf_doc->ObjMapTree = avl_create(CompObjMap, NULL, &avl_xallocator); 222 obj_map = new ObjMap; 223 obj_map->in = in; 224 obj_map->out_num = out_num; 225 void **aa = avl_probe(pdf_doc->ObjMapTree, obj_map); 226 assert(aa != NULL); 227} 228 229// When copying the Resources of the selected page, all objects are 230// copied recursively top-down. The findObjMap() function checks if an 231// object has already been copied; if so, instead of copying just the 232// new object number will be referenced. The ObjMapTree guarantees, 233// that during the entire LuaTeX run any object from any embedded PDF 234// file will end up max. once in the output PDF file. Indirect objects 235// are not fetched during copying, but get a new object number from 236// LuaTeX and then will be appended into a linked list. 237 238static int addInObj(PDF pdf, PdfDocument * pdf_doc, Ref ref) 239{ 240 ObjMap *obj_map; 241 InObj *p, *q, *n; 242 if (ref.num == 0) { 243 luatex_fail("PDF inclusion: reference to invalid object" 244 " (is the included pdf broken?)"); 245 } 246 if ((obj_map = findObjMap(pdf_doc, ref)) != NULL) 247 return obj_map->out_num; 248 n = new InObj; 249 n->ref = ref; 250 n->next = NULL; 251 n->num = pdf_create_obj(pdf, obj_type_others, 0); 252 addObjMap(pdf_doc, ref, n->num); 253 if (pdf_doc->inObjList == NULL) 254 pdf_doc->inObjList = n; 255 else { 256 // it is important to add new objects at the end of the list, 257 // because new objects are being added while the list is being 258 // written out by writeRefs(). 259 for (p = pdf_doc->inObjList; p != NULL; p = p->next) 260 q = p; 261 q->next = n; 262 } 263 return n->num; 264} 265 266//********************************************************************** 267// Function converts double to pdffloat; very small and very large numbers 268// are NOT converted to scientific notation. 269// n must be a number or real conforming to the implementation limits 270// of PDF as specified in appendix C.1 of the PDF Ref. 271// These are: 272// maximum value of ints is +2^32 273// maximum value of reals is +2^15 274// smalles values of reals is 1/(2^16) 275 276static pdffloat conv_double_to_pdffloat(double n) 277{ 278 pdffloat a; 279 a.e = 6; 280 a.m = i64round(n * ten_pow[a.e]); 281 return a; 282} 283 284static void copyObject(PDF, PdfDocument *, Object *); 285 286void copyReal(PDF pdf, double d) 287{ 288 if (pdf->cave) 289 pdf_out(pdf, ' '); 290 print_pdffloat(pdf, conv_double_to_pdffloat(d)); 291 pdf->cave = true; 292} 293 294static void copyString(PDF pdf, GooString * string) 295{ 296 char *p; 297 unsigned char c; 298 size_t i, l; 299 p = string->getCString(); 300 l = (size_t) string->getLength(); 301 if (pdf->cave) 302 pdf_out(pdf, ' '); 303 if (strlen(p) == l) { 304 pdf_out(pdf, '('); 305 for (; *p != 0; p++) { 306 c = (unsigned char) *p; 307 if (c == '(' || c == ')' || c == '\\') 308 pdf_printf(pdf, "\\%c", c); 309 else if (c < 0x20 || c > 0x7F) 310 pdf_printf(pdf, "\\%03o", (int) c); 311 else 312 pdf_out(pdf, c); 313 } 314 pdf_out(pdf, ')'); 315 } else { 316 pdf_out(pdf, '<'); 317 for (i = 0; i < l; i++) { 318 c = (unsigned char) string->getChar(i); 319 pdf_printf(pdf, "%.2x", (int) c); 320 } 321 pdf_out(pdf, '>'); 322 } 323 pdf->cave = true; 324} 325 326static void copyName(PDF pdf, char *s) 327{ 328 pdf_out(pdf, '/'); 329 for (; *s != 0; s++) { 330 if (isdigit(*s) || isupper(*s) || islower(*s) || *s == '_' || 331 *s == '.' || *s == '-' || *s == '+') 332 pdf_out(pdf, *s); 333 else 334 pdf_printf(pdf, "#%.2X", *s & 0xFF); 335 } 336 pdf->cave = true; 337} 338 339static void copyArray(PDF pdf, PdfDocument * pdf_doc, Array * array) 340{ 341 int i, l; 342 Object obj1; 343 pdf_begin_array(pdf); 344 for (i = 0, l = array->getLength(); i < l; ++i) { 345 array->getNF(i, &obj1); 346 copyObject(pdf, pdf_doc, &obj1); 347 obj1.free(); 348 } 349 pdf_end_array(pdf); 350} 351 352static void copyDict(PDF pdf, PdfDocument * pdf_doc, Dict * dict) 353{ 354 int i, l; 355 Object obj1; 356 pdf_begin_dict(pdf); 357 for (i = 0, l = dict->getLength(); i < l; ++i) { 358 copyName(pdf, dict->getKey(i)); 359 dict->getValNF(i, &obj1); 360 copyObject(pdf, pdf_doc, &obj1); 361 obj1.free(); 362 } 363 pdf_end_dict(pdf); 364} 365 366static void copyStreamStream(PDF pdf, Stream * str) 367{ 368 int c, i, len = 1024; 369 str->reset(); 370 i = len; 371 while ((c = str->getChar()) != EOF) { 372 if (i == len) { 373 pdf_room(pdf, len); 374 i = 0; 375 } 376 pdf_quick_out(pdf, c); 377 i++; 378 } 379} 380 381static void copyStream(PDF pdf, PdfDocument * pdf_doc, Stream * stream) 382{ 383 copyDict(pdf, pdf_doc, stream->getDict()); 384 pdf_begin_stream(pdf); 385 assert(pdf->zip_write_state == NO_ZIP); 386 copyStreamStream(pdf, stream->getUndecodedStream()); 387 pdf_end_stream(pdf); 388} 389 390static void copyObject(PDF pdf, PdfDocument * pdf_doc, Object * obj) 391{ 392 switch (obj->getType()) { 393 case objBool: 394 pdf_add_bool(pdf, (int) obj->getBool()); 395 break; 396 case objInt: 397 pdf_add_int(pdf, obj->getInt()); 398 break; 399 case objReal: 400 copyReal(pdf, obj->getReal()); 401 break; 402 // not needed: 403 // case objNum: 404 // GBool isNum() { return type == objInt || type == objReal; } 405 case objString: 406 copyString(pdf, obj->getString()); 407 break; 408 case objName: 409 copyName(pdf, obj->getName()); 410 break; 411 case objNull: 412 pdf_add_null(pdf); 413 break; 414 case objArray: 415 copyArray(pdf, pdf_doc, obj->getArray()); 416 break; 417 case objDict: 418 copyDict(pdf, pdf_doc, obj->getDict()); 419 break; 420 case objStream: 421 copyStream(pdf, pdf_doc, obj->getStream()); 422 break; 423 case objRef: 424 pdf_add_ref(pdf, addInObj(pdf, pdf_doc, obj->getRef())); 425 break; 426 case objCmd: 427 case objError: 428 case objEOF: 429 case objNone: 430 luatex_fail("PDF inclusion: type <%s> cannot be copied", 431 obj->getTypeName()); 432 break; 433 default: 434 assert(0); // xpdf doesn't have any other types 435 } 436} 437 438//********************************************************************** 439 440static void writeRefs(PDF pdf, PdfDocument * pdf_doc) 441{ 442 InObj *r, *n; 443 Object obj1; 444 XRef *xref; 445 PDFDoc *doc = pdf_doc->doc; 446 xref = doc->getXRef(); 447 for (r = pdf_doc->inObjList; r != NULL;) { 448 xref->fetch(r->ref.num, r->ref.gen, &obj1); 449 if (obj1.isStream()) 450 pdf_begin_obj(pdf, r->num, OBJSTM_NEVER); 451 else 452 pdf_begin_obj(pdf, r->num, 2); // \pdfobjcompresslevel = 2 is for this 453 copyObject(pdf, pdf_doc, &obj1); 454 obj1.free(); 455 pdf_end_obj(pdf); 456 n = r->next; 457 delete r; 458 pdf_doc->inObjList = r = n; 459 } 460} 461 462// get the pagebox coordinates according to the pagebox_spec 463 464static PDFRectangle *get_pagebox(Page * page, int pagebox_spec) 465{ 466 switch (pagebox_spec) { 467 case PDF_BOX_SPEC_MEDIA: 468 return page->getMediaBox(); 469 break; 470 case PDF_BOX_SPEC_CROP: 471 return page->getCropBox(); 472 break; 473 case PDF_BOX_SPEC_BLEED: 474 return page->getBleedBox(); 475 break; 476 case PDF_BOX_SPEC_TRIM: 477 return page->getTrimBox(); 478 break; 479 case PDF_BOX_SPEC_ART: 480 return page->getArtBox(); 481 break; 482 default: 483 luatex_fail("PDF inclusion: unknown value of pagebox spec (%i)", 484 (int) pagebox_spec); 485 } 486 return page->getMediaBox(); // to make the compiler happy 487} 488 489// Reads various information about the PDF and sets it up for later inclusion. 490// This will fail if the PDF version of the PDF is higher than 491// minor_pdf_version_wanted or page_name is given and can not be found. 492// It makes no sense to give page_name _and_ page_num. 493// Returns the page number. 494 495void 496read_pdf_info(image_dict * idict, int minor_pdf_version_wanted, 497 int pdf_inclusion_errorlevel, img_readtype_e readtype) 498{ 499 PdfDocument *pdf_doc; 500 PDFDoc *doc; 501 Catalog *catalog; 502 Page *page; 503 int rotate; 504 PDFRectangle *pagebox; 505 int pdf_major_version_found, pdf_minor_version_found; 506 float xsize, ysize, xorig, yorig; 507 assert(idict != NULL); 508 assert(img_type(idict) == IMG_TYPE_PDF); 509 assert(readtype == IMG_CLOSEINBETWEEN); // only this is implemented 510 // initialize 511 if (isInit == gFalse) { 512 globalParams = new GlobalParams(); 513 globalParams->setErrQuiet(gFalse); 514 isInit = gTrue; 515 } 516 // open PDF file 517 pdf_doc = refPdfDocument(img_filepath(idict), FE_FAIL); 518 doc = pdf_doc->doc; 519 catalog = doc->getCatalog(); 520 // check PDF version 521 // this works only for PDF 1.x -- but since any versions of PDF newer 522 // than 1.x will not be backwards compatible to PDF 1.x, pdfTeX will 523 // then have to changed drastically anyway. 524 pdf_major_version_found = doc->getPDFMajorVersion(); 525 pdf_minor_version_found = doc->getPDFMinorVersion(); 526 if ((pdf_major_version_found > 1) 527 || (pdf_minor_version_found > minor_pdf_version_wanted)) { 528 const char *msg = 529 "PDF inclusion: found PDF version <%d.%d>, but at most version <1.%d> allowed"; 530 if (pdf_inclusion_errorlevel > 0) { 531 luatex_fail(msg, pdf_major_version_found, pdf_minor_version_found, 532 minor_pdf_version_wanted); 533 } else { 534 luatex_warn(msg, pdf_major_version_found, pdf_minor_version_found, 535 minor_pdf_version_wanted); 536 } 537 } 538 img_totalpages(idict) = catalog->getNumPages(); 539 if (img_pagename(idict)) { 540 // get page by name 541 GooString name(img_pagename(idict)); 542 LinkDest *link = doc->findDest(&name); 543 if (link == NULL || !link->isOk()) 544 luatex_fail("PDF inclusion: invalid destination <%s>", 545 img_pagename(idict)); 546 Ref ref = link->getPageRef(); 547 img_pagenum(idict) = catalog->findPage(ref.num, ref.gen); 548 if (img_pagenum(idict) == 0) 549 luatex_fail("PDF inclusion: destination is not a page <%s>", 550 img_pagename(idict)); 551 delete link; 552 } else { 553 // get page by number 554 if (img_pagenum(idict) <= 0 555 || img_pagenum(idict) > img_totalpages(idict)) 556 luatex_fail("PDF inclusion: required page <%i> does not exist", 557 (int) img_pagenum(idict)); 558 } 559 // get the required page 560 page = catalog->getPage(img_pagenum(idict)); 561 562 // get the pagebox coordinates (media, crop,...) to use. 563 pagebox = get_pagebox(page, img_pagebox(idict)); 564 if (pagebox->x2 > pagebox->x1) { 565 xorig = pagebox->x1; 566 xsize = pagebox->x2 - pagebox->x1; 567 } else { 568 xorig = pagebox->x2; 569 xsize = pagebox->x1 - pagebox->x2; 570 } 571 if (pagebox->y2 > pagebox->y1) { 572 yorig = pagebox->y1; 573 ysize = pagebox->y2 - pagebox->y1; 574 } else { 575 yorig = pagebox->y2; 576 ysize = pagebox->y1 - pagebox->y2; 577 } 578 // The following 4 parameters are raw. Do _not_ modify by /Rotate! 579 img_xsize(idict) = bp2sp(xsize); 580 img_ysize(idict) = bp2sp(ysize); 581 img_xorig(idict) = bp2sp(xorig); 582 img_yorig(idict) = bp2sp(yorig); 583 584 // Handle /Rotate parameter. Only multiples of 90 deg. are allowed 585 // (PDF Ref. v1.3, p. 78). 586 rotate = page->getRotate(); 587 switch (((rotate % 360) + 360) % 360) { // handles also neg. angles 588 case 0: 589 img_rotation(idict) = 0; 590 break; 591 case 90: 592 img_rotation(idict) = 3; // PDF counts clockwise! 593 break; 594 case 180: 595 img_rotation(idict) = 2; 596 break; 597 case 270: 598 img_rotation(idict) = 1; 599 break; 600 default: 601 luatex_warn 602 ("PDF inclusion: " 603 "/Rotate parameter in PDF file not multiple of 90 degrees."); 604 } 605 606 // currently unused info whether PDF contains a /Group 607 if (page->getGroup() != NULL) 608 img_set_group(idict); 609 610 if (readtype == IMG_CLOSEINBETWEEN) 611 unrefPdfDocument(img_filepath(idict)); 612} 613 614//********************************************************************** 615// Writes the current epf_doc. 616// Here the included PDF is copied, so most errors that can happen 617// during PDF inclusion will arise here. 618 619void write_epdf(PDF pdf, image_dict * idict) 620{ 621 PdfDocument *pdf_doc; 622 PDFDoc *doc; 623 Catalog *catalog; 624 Page *page; 625 Ref *pageref; 626 Dict *pageDict; 627 Object obj1, contents, pageobj, pagesobj1, pagesobj2, *op1, *op2, *optmp; 628 PDFRectangle *pagebox; 629 int i, l; 630 double bbox[4]; 631 char s[256]; 632 const char *pagedictkeys[] = 633 { "Group", "LastModified", "Metadata", "PieceInfo", "Resources", 634 "SeparationInfo", NULL 635 }; 636 assert(idict != NULL); 637 638 // open PDF file 639 pdf_doc = refPdfDocument(img_filepath(idict), FE_FAIL); 640 doc = pdf_doc->doc; 641 catalog = doc->getCatalog(); 642 page = catalog->getPage(img_pagenum(idict)); 643 pageref = catalog->getPageRef(img_pagenum(idict)); 644 assert(pageref != NULL); // was checked already in read_pdf_info() 645 doc->getXRef()->fetch(pageref->num, pageref->gen, &pageobj); 646 pageDict = pageobj.getDict(); 647 648 // write the Page header 649 pdf_begin_obj(pdf, img_objnum(idict), OBJSTM_NEVER); 650 pdf_begin_dict(pdf); 651 pdf_dict_add_name(pdf, "Type", "XObject"); 652 pdf_dict_add_name(pdf, "Subtype", "Form"); 653 654 if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0) 655 pdf_printf(pdf, "\n%s\n", img_attr(idict)); 656 pdf_dict_add_int(pdf, "FormType", 1); 657 658 // write additional information 659 pdf_dict_add_img_filename(pdf, idict); 660 snprintf(s, 30, "%s.PageNumber", pdfkeyprefix); 661 pdf_dict_add_int(pdf, s, (int) img_pagenum(idict)); 662 doc->getDocInfoNF(&obj1); 663 if (obj1.isRef()) { 664 // the info dict must be indirect (PDF Ref p. 61) 665 snprintf(s, 30, "%s.InfoDict", pdfkeyprefix); 666 pdf_dict_add_ref(pdf, s, addInObj(pdf, pdf_doc, obj1.getRef())); 667 } 668 obj1.free(); 669 if (img_is_bbox(idict)) { 670 bbox[0] = sp2bp(img_bbox(idict)[0]); 671 bbox[1] = sp2bp(img_bbox(idict)[1]); 672 bbox[2] = sp2bp(img_bbox(idict)[2]); 673 bbox[3] = sp2bp(img_bbox(idict)[3]); 674 } else { 675 // get the pagebox coordinates (media, crop,...) to use. 676 pagebox = get_pagebox(page, img_pagebox(idict)); 677 bbox[0] = pagebox->x1; 678 bbox[1] = pagebox->y1; 679 bbox[2] = pagebox->x2; 680 bbox[3] = pagebox->y2; 681 } 682 pdf_add_name(pdf, "BBox"); 683 pdf_begin_array(pdf); 684 copyReal(pdf, bbox[0]); 685 copyReal(pdf, bbox[1]); 686 copyReal(pdf, bbox[2]); 687 copyReal(pdf, bbox[3]); 688 pdf_end_array(pdf); 689 // The /Matrix calculation is replaced by transforms in out_img(). 690 691 // Now all relevant parts of the Page dictionary are copied: 692 693 // Metadata validity check (as a stream it must be indirect) 694 pageDict->lookupNF((char *) "Metadata", &obj1); 695 if (!obj1.isNull() && !obj1.isRef()) 696 luatex_warn("PDF inclusion: /Metadata must be indirect object"); 697 obj1.free(); 698 699 // copy selected items in Page dictionary 700 for (i = 0; pagedictkeys[i] != NULL; i++) { 701 pageDict->lookupNF((char *) pagedictkeys[i], &obj1); 702 if (!obj1.isNull()) { 703 pdf_add_name(pdf, pagedictkeys[i]); 704 copyObject(pdf, pdf_doc, &obj1); // preserves indirection 705 } 706 obj1.free(); 707 } 708 709 // If there are no Resources in the Page dict of the embedded page, 710 // try to inherit the Resources from the Pages tree of the embedded 711 // PDF file, climbing up the tree until the Resources are found. 712 // (This fixes a problem with Scribus 1.3.3.14.) 713 pageDict->lookupNF((char *) "Resources", &obj1); 714 if (obj1.isNull()) { 715 op1 = &pagesobj1; 716 op2 = &pagesobj2; 717 pageDict->lookup((char *) "Parent", op1); 718 while (op1->isDict()) { 719 obj1.free(); 720 op1->dictLookupNF((char *) "Resources", &obj1); 721 if (!obj1.isNull()) { 722 pdf_add_name(pdf, (const char *) "Resources"); 723 copyObject(pdf, pdf_doc, &obj1); 724 break; 725 } 726 op1->dictLookup((char *) "Parent", op2); 727 optmp = op1; 728 op1 = op2; 729 op2 = optmp; 730 op2->free(); 731 }; 732 if (!op1->isDict()) 733 luatex_warn("PDF inclusion: Page /Resources missing."); 734 op1->free(); 735 } 736 obj1.free(); 737 738 // write the Page contents 739 page->getContents(&contents); 740 if (contents.isStream()) { 741 // Variant A: get stream and recompress under control 742 // of \pdfcompresslevel 743 // 744 // pdf_begin_stream(); 745 // copyStreamStream(contents->getStream()); 746 // pdf_end_stream(); 747 748 // Variant B: copy stream without recompressing 749 // 750 contents.streamGetDict()->lookup((char *) "F", &obj1); 751 if (!obj1.isNull()) { 752 luatex_fail("PDF inclusion: Unsupported external stream"); 753 } 754 obj1.free(); 755 contents.streamGetDict()->lookup((char *) "Length", &obj1); 756 assert(!obj1.isNull()); 757 pdf_add_name(pdf, (const char *) "Length"); 758 copyObject(pdf, pdf_doc, &obj1); 759 obj1.free(); 760 contents.streamGetDict()->lookup((char *) "Filter", &obj1); 761 if (!obj1.isNull()) { 762 pdf_add_name(pdf, (const char *) "Filter"); 763 copyObject(pdf, pdf_doc, &obj1); 764 obj1.free(); 765 contents.streamGetDict()->lookup((char *) "DecodeParms", &obj1); 766 if (!obj1.isNull()) { 767 pdf_add_name(pdf, (const char *) "DecodeParms"); 768 copyObject(pdf, pdf_doc, &obj1); 769 } 770 } 771 obj1.free(); 772 pdf_end_dict(pdf); 773 pdf_begin_stream(pdf); 774 copyStreamStream(pdf, contents.getStream()->getUndecodedStream()); 775 pdf_end_stream(pdf); 776 pdf_end_obj(pdf); 777 } else if (contents.isArray()) { 778 pdf_dict_add_streaminfo(pdf); 779 pdf_end_dict(pdf); 780 pdf_begin_stream(pdf); 781 for (i = 0, l = contents.arrayGetLength(); i < l; ++i) { 782 copyStreamStream(pdf, (contents.arrayGet(i, &obj1))->getStream()); 783 obj1.free(); 784 if (i < (l - 1)) { 785 // put a space between streams to be on the safe side (streams 786 // should have a trailing space here, but one never knows) 787 pdf_out(pdf, ' '); 788 } 789 } 790 pdf_end_stream(pdf); 791 pdf_end_obj(pdf); 792 } else { // the contents are optional, but we need to include an empty stream 793 pdf_dict_add_streaminfo(pdf); 794 pdf_end_dict(pdf); 795 pdf_begin_stream(pdf); 796 pdf_end_stream(pdf); 797 pdf_end_obj(pdf); 798 } 799 // write out all indirect objects 800 writeRefs(pdf, pdf_doc); 801 contents.free(); 802 pageobj.free(); 803 // unrefPdfDocument() must come after contents.free() and pageobj.free()! 804 // TH: The next line makes repeated pdf inclusion unacceptably slow 805#if 0 806 unrefPdfDocument(img_filepath(idict)); 807#endif 808} 809 810//********************************************************************** 811// Deallocate a PdfDocument with all its resources 812 813static void deletePdfDocumentPdfDoc(PdfDocument * pdf_doc) 814{ 815 InObj *r, *n; 816 assert(pdf_doc != NULL); 817 // this may be probably needed for an emergency destroyPdfDocument() 818 for (r = pdf_doc->inObjList; r != NULL; r = n) { 819 n = r->next; 820 delete r; 821 } 822#ifdef DEBUG 823 fprintf(stderr, "\nDEBUG: Deleting PDFDoc %s\n", pdf_doc->file_path); 824#endif 825 delete pdf_doc->doc; 826 pdf_doc->doc = NULL; 827 pdf_doc->pc++; 828} 829 830static void destroyPdfDocument(void *pa, void * /*pb */ ) 831{ 832 PdfDocument *pdf_doc = (PdfDocument *) pa; 833 deletePdfDocumentPdfDoc(pdf_doc); 834 // TODO: delete rest of pdf_doc 835} 836 837// Called when an image has been written and its resources in image_tab are 838// freed and it's not referenced anymore. 839 840void unrefPdfDocument(char *file_path) 841{ 842 PdfDocument *pdf_doc = findPdfDocument(file_path); 843 assert(pdf_doc != NULL); 844 assert(pdf_doc->occurences != 0); // aim for point landing 845 pdf_doc->occurences--; 846#ifdef DEBUG 847 fprintf(stderr, "\nDEBUG: Decrementing %s (%d)\n", 848 pdf_doc->file_path, pdf_doc->occurences); 849#endif 850 if (pdf_doc->occurences == 0) { 851 assert(pdf_doc->inObjList == NULL); // should be eaten up already 852 deletePdfDocumentPdfDoc(pdf_doc); 853 } 854} 855 856// Called when PDF embedding system is finalized. 857// Now deallocate all remaining PdfDocuments. 858 859void epdf_free() 860{ 861 if (PdfDocumentTree != NULL) 862 avl_destroy(PdfDocumentTree, destroyPdfDocument); 863 PdfDocumentTree = NULL; 864 if (isInit == gTrue) 865 delete globalParams; 866 isInit = gFalse; 867} 868