195
static void deletePdfDocument(PdfDocument *);
197
// Called when an image has been written and its resources in image_tab are
198
// freed and it's not referenced anymore.
200
void unrefPdfDocument(char *file_path)
202
PdfDocument *pdf_doc = findPdfDocument(file_path);
195
//**********************************************************************
196
// keep the ObjMap struct small, as these are accumulated until the end
199
Ref in; // object num/gen in orig. PDF file
200
int out_num; // object num after embedding (gen == 0)
203
// AVL sort ObjMap into ObjMapTree by object number and generation
205
static int CompObjMap(const void *pa, const void *pb, void * /*p */ )
207
const Ref *a = &(((const ObjMap *) pa)->in);
208
const Ref *b = &(((const ObjMap *) pb)->in);
213
if (a->gen == b->gen) // most likely gen == 0 anyway
220
static ObjMap *findObjMap(PdfDocument * pdf_doc, Ref in)
222
ObjMap *obj_map, tmp;
203
223
assert(pdf_doc != NULL);
204
assert(pdf_doc->occurences > 0); // aim for point landing
205
pdf_doc->occurences--;
207
fprintf(stderr, "\nluatex Debug: Decrementing %s (%d)\n",
208
pdf_doc->file_path, pdf_doc->occurences);
210
if (pdf_doc->occurences == 0) {
212
fprintf(stderr, "\nluatex Debug: Deleting %s\n", pdf_doc->file_path);
214
void *a = avl_delete(PdfDocumentTree, pdf_doc);
215
assert((PdfDocument *) a == pdf_doc);
216
deletePdfDocument(pdf_doc);
224
if (pdf_doc->ObjMapTree == NULL)
227
obj_map = (ObjMap *) avl_find(pdf_doc->ObjMapTree, &tmp);
231
static void addObjMap(PdfDocument * pdf_doc, Ref in, int out_num)
233
ObjMap *obj_map = NULL;
234
assert(findObjMap(pdf_doc, in) == NULL);
235
if (pdf_doc->ObjMapTree == NULL)
236
pdf_doc->ObjMapTree = avl_create(CompObjMap, NULL, &avl_xallocator);
237
obj_map = new ObjMap;
239
obj_map->out_num = out_num;
240
void **aa = avl_probe(pdf_doc->ObjMapTree, obj_map);
220
244
//**********************************************************************
222
246
// Replacement for
223
247
// Object *initDict(Dict *dict1){ initObj(objDict); dict = dict1; return this; }
225
static void initDictFromDict(PdfObject & obj, Dict * dict)
249
static void initDictFromDict(PdfDocument * pdf_doc, PdfObject & obj,
252
obj->initDict(pdf_doc->xref);
228
253
for (int i = 0, l = dict->getLength(); i < l; i++) {
230
255
obj->dictAdd(copyString(dict->getKey(i)), dict->getValNF(i, &obj1));
234
static int addEncoding(GfxFont * gfont)
237
n = new UsedEncoding;
238
n->next = encodingList;
241
n->enc_objnum = pdf_new_objnum();
242
return n->enc_objnum;
245
#define addFont(ref, fd, enc_objnum) \
246
addInObj(objFont, ref, fd, enc_objnum)
248
// addFontDesc is only used to avoid writing the original FontDescriptor
249
// from the PDF file.
251
#define addFontDesc(ref, fd) \
252
addInObj(objFontDesc, ref, fd, 0)
254
#define addOther(ref) \
255
addInObj(objOther, ref, NULL, 0)
257
static int addInObj(InObjType type, Ref ref, fd_entry * fd, integer e)
259
InObj *p, *q, *n = new InObj;
261
pdftex_fail("PDF inclusion: invalid reference");
259
static int addInObj(PDF pdf, PdfDocument * pdf_doc, Ref ref)
264
pdftex_fail("PDF inclusion: reference to invalid object"
265
" (is the included pdf broken?)");
267
if ((obj_map = findObjMap(pdf_doc, ref)) != NULL)
268
return obj_map->out_num;
268
if (inObjList == NULL)
272
n->num = pdf_new_objnum(pdf);
273
addObjMap(pdf_doc, ref, n->num);
274
if (pdf_doc->inObjList == NULL)
275
pdf_doc->inObjList = n;
271
for (p = inObjList; p != NULL; p = p->next) {
272
if (p->ref.num == ref.num && p->ref.gen == ref.gen) {
278
277
// it is important to add new objects at the end of the list,
279
278
// because new objects are being added while the list is being
280
279
// written out by writeRefs().
280
for (p = pdf_doc->inObjList; p != NULL; p = p->next)
283
if (type == objFontDesc)
284
n->num = get_fd_objnum(fd);
286
n->num = pdf_new_objnum();
290
static void copyName(char *s)
287
static void copyName(PDF pdf, char *s)
293
290
for (; *s != 0; s++) {
294
291
if (isdigit(*s) || isupper(*s) || islower(*s) || *s == '_' ||
295
292
*s == '.' || *s == '-' || *s == '+')
298
pdf_printf("#%.2X", *s & 0xFF);
295
pdf_printf(pdf, "#%.2X", *s & 0xFF);
302
static int getNewObjectNumber(Ref ref)
299
static int getNewObjectNumber(PdfDocument * pdf_doc, Ref ref)
305
if (inObjList == 0) {
306
pdftex_fail("No objects copied yet");
308
for (p = inObjList; p != 0; p = p->next) {
309
if (p->ref.num == ref.num && p->ref.gen == ref.gen) {
313
pdftex_fail("Object not yet copied: %i %i", ref.num, ref.gen);
302
if ((obj_map = findObjMap(pdf_doc, ref)) != NULL)
303
return obj_map->out_num;
304
pdftex_fail("Object not yet copied: %i %i", ref.num, ref.gen);
317
static void copyObject(Object *);
308
static void copyObject(PDF, PdfDocument *, Object *);
319
static void copyDictEntry(Object * obj, int i)
310
static void copyDictEntry(PDF pdf, PdfDocument * pdf_doc, Object * obj, int i)
322
copyName(obj->dictGetKey(i));
313
copyName(pdf, obj->dictGetKey(i));
324
315
obj->dictGetValNF(i, &obj1);
316
copyObject(pdf, pdf_doc, &obj1);
329
static void copyDict(Object * obj)
320
static void copyDict(PDF pdf, PdfDocument * pdf_doc, Object * obj)
332
323
if (!obj->isDict())
333
324
pdftex_fail("PDF inclusion: invalid dict type <%s>",
334
325
obj->getTypeName());
335
326
for (i = 0, l = obj->dictGetLength(); i < l; ++i)
336
copyDictEntry(obj, i);
339
static void copyFontDict(Object * obj, InObj * r)
344
pdftex_fail("PDF inclusion: invalid dict type <%s>",
347
assert(r->type == objFont); // FontDescriptor is in fd_tree
348
for (i = 0, l = obj->dictGetLength(); i < l; ++i) {
349
key = obj->dictGetKey(i);
350
if (strncmp("FontDescriptor", key, strlen("FontDescriptor")) == 0
351
|| strncmp("BaseFont", key, strlen("BaseFont")) == 0
352
|| strncmp("Encoding", key, strlen("Encoding")) == 0)
353
continue; // skip original values
354
copyDictEntry(obj, i);
356
// write new FontDescriptor, BaseFont, and Encoding
357
pdf_printf("/FontDescriptor %d 0 R\n", (int) get_fd_objnum(r->fd));
358
pdf_printf("/BaseFont %d 0 R\n", (int) get_fn_objnum(r->fd));
359
pdf_printf("/Encoding %d 0 R\n", (int) r->enc_objnum);
363
static void copyStream(Stream * str)
327
copyDictEntry(pdf, pdf_doc, obj, i);
330
static void copyStream(PDF pdf, Stream * str)
367
334
while ((c = str->getChar()) != EOF) {
373
static void copyProcSet(Object * obj)
378
pdftex_fail("PDF inclusion: invalid ProcSet array type <%s>",
380
pdf_puts("/ProcSet [ ");
381
for (i = 0, l = obj->arrayGetLength(); i < l; ++i) {
382
obj->arrayGetNF(i, &procset);
383
if (!procset->isName())
384
pdftex_fail("PDF inclusion: invalid ProcSet entry type <%s>",
385
procset->getTypeName());
386
copyName(procset->getName());
392
#define REPLACE_TYPE1C true
394
static void copyFont(char *tag, Object * fontRef)
396
PdfObject fontdict, subtype, basefont, fontdescRef, fontdesc, charset,
397
fontfile, ffsubtype, stemV;
401
// Check whether the font has already been embedded before analysing it.
403
Ref ref = fontRef->getRef();
404
for (p = inObjList; p; p = p->next) {
405
if (p->ref.num == ref.num && p->ref.gen == ref.gen) {
407
pdf_printf(" %d 0 R ", (int) p->num);
411
// Only handle included Type1 (and Type1C) fonts; anything else will be copied.
412
// Type1C fonts are replaced by Type1 fonts, if REPLACE_TYPE1C is true.
413
if (!fixed_inclusion_copy_font && fontRef->fetch(xref, &fontdict)->isDict()
414
&& fontdict->dictLookup("Subtype", &subtype)->isName()
415
&& !strcmp(subtype->getName(), "Type1")
416
&& fontdict->dictLookup("BaseFont", &basefont)->isName()
417
&& fontdict->dictLookupNF("FontDescriptor", &fontdescRef)->isRef()
418
&& fontdescRef->fetch(xref, &fontdesc)->isDict()
419
&& (fontdesc->dictLookup("FontFile", &fontfile)->isStream()
421
&& fontdesc->dictLookup("FontFile3", &fontfile)->isStream()
422
&& fontfile->streamGetDict()->lookup("Subtype",
423
&ffsubtype)->isName()
424
&& !strcmp(ffsubtype->getName(), "Type1C")))
425
&& (fontmap = lookup_fontmap(basefont->getName())) != NULL) {
426
// copy the value of /StemV
427
fontdesc->dictLookup("StemV", &stemV);
428
fd = epdf_create_fontdescriptor(fontmap, stemV->getInt());
429
if (fontdesc->dictLookup("CharSet", &charset) &&
430
charset->isString() && is_subsetable(fontmap))
431
epdf_mark_glyphs(fd, charset->getString()->getCString());
433
embed_whole_font(fd);
434
addFontDesc(fontdescRef->getRef(), fd);
436
gfont = GfxFont::makeFont(xref, tag, fontRef->getRef(),
437
fontdict->getDict());
438
pdf_printf(" %d 0 R ", addFont(fontRef->getRef(), fd,
439
addEncoding(gfont)));
447
static void copyFontResources(Object * obj)
452
pdftex_fail("PDF inclusion: invalid font resources dict type <%s>",
454
pdf_puts("/Font << ");
455
for (i = 0, l = obj->dictGetLength(); i < l; ++i) {
456
obj->dictGetValNF(i, &fontRef);
457
if (fontRef->isRef())
458
copyFont(obj->dictGetKey(i), &fontRef);
460
pdftex_fail("PDF inclusion: invalid font in reference type <%s>",
461
fontRef->getTypeName());
466
static void copyOtherResources(Object * obj, char *key)
468
// copies all other resources (write_epdf handles Fonts and ProcSets),
469
// but gives a warning if an object is not a dictionary.
472
//FIXME: Write the message only to the log file
473
pdftex_warn("PDF inclusion: invalid other resource which is no dict"
474
" (key '%s', type <%s>); copying it anyway.",
475
key, obj->getTypeName());
340
static void copyOtherResources(PDF pdf, PdfDocument * pdf_doc, Object * obj,
345
copyObject(pdf, pdf_doc, obj);
481
348
// Function onverts double to string; very small and very large numbers
536
403
return (char *) buf;
539
static void copyObject(Object * obj)
406
static void copyObject(PDF pdf, PdfDocument * pdf_doc, Object * obj)
546
412
if (obj->isBool()) {
547
pdf_printf("%s", obj->getBool()? "true" : "false");
413
pdf_printf(pdf, "%s", obj->getBool()? "true" : "false");
548
414
} else if (obj->isInt()) {
549
pdf_printf("%i", obj->getInt());
415
pdf_printf(pdf, "%i", obj->getInt());
550
416
} else if (obj->isReal()) {
551
pdf_printf("%s", convertNumToPDF(obj->getReal()));
417
pdf_printf(pdf, "%s", convertNumToPDF(obj->getReal()));
552
418
} else if (obj->isNum()) {
553
pdf_printf("%s", convertNumToPDF(obj->getNum()));
419
pdf_printf(pdf, "%s", convertNumToPDF(obj->getNum()));
554
420
} else if (obj->isString()) {
555
421
s = obj->getString();
556
422
p = s->getCString();
557
423
l = s->getLength();
558
424
if (strlen(p) == (unsigned int) l) {
560
426
for (; *p != 0; p++) {
561
427
c = (unsigned char) *p;
562
428
if (c == '(' || c == ')' || c == '\\')
563
pdf_printf("\\%c", c);
429
pdf_printf(pdf, "\\%c", c);
564
430
else if (c < 0x20 || c > 0x7F)
565
pdf_printf("\\%03o", c);
431
pdf_printf(pdf, "\\%03o", c);
572
438
for (i = 0; i < l; i++) {
573
439
c = s->getChar(i) & 0xFF;
574
pdf_printf("%.2x", c);
440
pdf_printf(pdf, "%.2x", c);
578
444
} else if (obj->isName()) {
579
copyName(obj->getName());
445
copyName(pdf, obj->getName());
580
446
} else if (obj->isNull()) {
447
pdf_puts(pdf, "null");
582
448
} else if (obj->isArray()) {
584
450
for (i = 0, l = obj->arrayGetLength(); i < l; ++i) {
585
451
obj->arrayGetNF(i, &obj1);
586
452
if (!obj1->isName())
454
copyObject(pdf, pdf_doc, &obj1);
591
457
} else if (obj->isDict()) {
458
pdf_puts(pdf, "<<\n");
459
copyDict(pdf, pdf_doc, obj);
595
461
} else if (obj->isStream()) {
596
initDictFromDict(obj1, obj->streamGetDict());
462
initDictFromDict(pdf_doc, obj1, obj->streamGetDict());
597
463
obj->streamGetDict()->incRef();
601
pdf_puts("stream\n");
602
copyStream(obj->getStream()->getUndecodedStream());
603
if (pdf_last_byte != '\n')
605
pdf_puts("endstream"); // can't simply write pdf_end_stream()
464
pdf_puts(pdf, "<<\n");
465
copyDict(pdf, pdf_doc, &obj1);
466
pdf_puts(pdf, ">>\n");
467
pdf_puts(pdf, "stream\n");
468
copyStream(pdf, obj->getStream()->getUndecodedStream());
469
if (pdf->last_byte != '\n')
471
pdf_puts(pdf, "endstream"); // can't simply write pdf_end_stream()
606
472
} else if (obj->isRef()) {
610
("PDF inclusion: reference to invalid object"
611
" (is the included pdf broken?)");
613
pdf_printf("%d 0 R", addOther(ref));
473
pdf_printf(pdf, "%d 0 R", addInObj(pdf, pdf_doc, obj->getRef()));
615
475
pdftex_fail("PDF inclusion: type <%s> cannot be copied",
616
476
obj->getTypeName());
620
static void writeRefs()
623
for (r = inObjList; r != NULL; r = r->next) {
627
xref->fetch(r->ref.num, r->ref.gen, &obj1);
628
if (r->type == objFont) {
629
assert(!obj1.isStream());
630
zpdf_begin_obj(r->num, 2); // \pdfobjcompresslevel = 2 is for this
631
copyFontDict(&obj1, r);
634
} else if (r->type != objFontDesc) { // /FontDescriptor is written via write_fontdescriptor()
636
zpdf_begin_obj(r->num, 0);
638
zpdf_begin_obj(r->num, 2); // \pdfobjcompresslevel = 2 is for this
648
static void writeEncodings()
651
char *glyphNames[256], *s;
653
for (r = encodingList; r != NULL; r = r->next) {
654
for (i = 0; i < 256; i++) {
655
if (r->font->isCIDFont()) {
657
("PDF inclusion: CID fonts are not supported"
658
" (try to disable font replacement to fix this)");
660
if ((s = ((Gfx8BitFont *) r->font)->getCharName(i)) != NULL)
663
glyphNames[i] = notdef;
665
epdf_write_enc(glyphNames, r->enc_objnum);
667
for (r = encodingList; r != NULL; r = n) {
480
static void writeRefs(PDF pdf, PdfDocument * pdf_doc)
483
for (r = pdf_doc->inObjList; r != NULL;) {
485
pdf_doc->xref->fetch(r->ref.num, r->ref.gen, &obj1);
487
pdf_begin_obj(pdf, r->num, 0);
489
pdf_begin_obj(pdf, r->num, 2); // \pdfobjcompresslevel = 2 is for this
490
copyObject(pdf, pdf_doc, &obj1);
496
pdf_doc->inObjList = r = n;
674
// get the pagebox according to the pagebox_spec
500
// get the pagebox coordinates according to the pagebox_spec
676
static PDFRectangle *get_pagebox(Page * page, integer pagebox_spec)
502
static PDFRectangle *get_pagebox(Page * page, int pagebox_spec)
678
if (pagebox_spec == pdf_box_spec_media)
504
switch (pagebox_spec) {
505
case PDF_BOX_SPEC_MEDIA:
679
506
return page->getMediaBox();
680
else if (pagebox_spec == pdf_box_spec_crop)
508
case PDF_BOX_SPEC_CROP:
681
509
return page->getCropBox();
682
else if (pagebox_spec == pdf_box_spec_bleed)
511
case PDF_BOX_SPEC_BLEED:
683
512
return page->getBleedBox();
684
else if (pagebox_spec == pdf_box_spec_trim)
514
case PDF_BOX_SPEC_TRIM:
685
515
return page->getTrimBox();
686
else if (pagebox_spec == pdf_box_spec_art)
517
case PDF_BOX_SPEC_ART:
687
518
return page->getArtBox();
689
521
pdftex_fail("PDF inclusion: unknown value of pagebox spec (%i)",
690
522
(int) pagebox_spec);
691
524
return page->getMediaBox(); // to make the compiler happy
527
#define PDF_CHECKSUM_SIZE 32
528
char *get_file_checksum(char *a)
532
if (stat(a, &finfo) == 0) {
533
off_t size = finfo.st_size;
534
time_t mtime = finfo.st_mtime;
535
ck = (char *) malloc(PDF_CHECKSUM_SIZE);
537
pdftex_fail("PDF inclusion: out of memory while processing '%s'",
539
snprintf(ck, PDF_CHECKSUM_SIZE, "%llu_%llu", (unsigned long long) size,
540
(unsigned long long) mtime);
542
pdftex_fail("PDF inclusion: could not stat() file '%s'", a);
694
547
// Reads various information about the PDF and sets it up for later inclusion.
695
548
// This will fail if the PDF version of the PDF is higher than
696
549
// minor_pdf_version_wanted or page_name is given and can not be found.
801
664
"/Rotate parameter in PDF file not multiple of 90 degrees.");
803
666
if (page->getGroup() != NULL) {
804
initDictFromDict(lastGroup, page->getGroup());
667
initDictFromDict(pdf_doc, lastGroup, page->getGroup());
805
668
if (lastGroup->dictGetLength() > 0) {
806
669
groupIsIndirect = lastGroup->isRef();
807
670
if (groupIsIndirect) {
808
671
// FIXME: Here we already copy the object. It would be
809
672
// better to do this only after write_epdf, otherwise we
810
// may copy ununsed /Group objects
811
copyObject(&lastGroup);
673
// may copy unused /Group objects
674
copyObject(pdf, pdf_doc, &lastGroup);
812
675
epdf_lastGroupObjectNum =
813
getNewObjectNumber(lastGroup->getRef());
676
getNewObjectNumber(pdf_doc, lastGroup->getRef());
815
679
// make the group an indirect object; copying is done later
816
680
// by write_additional_epdf_objects after write_epdf
817
epdf_lastGroupObjectNum = pdf_new_objnum();
681
epdf_lastGroupObjectNum = pdf_new_objnum(pdf);
822
685
epdf_lastGroupObjectNum = 0;
687
if (readtype == IMG_CLOSEINBETWEEN)
688
unrefPdfDocument(img_filepath(idict));
827
691
// Writes the current epf_doc.
828
692
// Here the included PDF is copied, so most errors that can happen during PDF
829
693
// inclusion will arise here.
831
static void write_epdf1(image_dict * idict)
695
static void write_epdf1(PDF pdf, image_dict * idict)
834
698
PdfObject contents, obj1, obj2;
835
699
PdfObject metadata, pieceinfo, separationInfo;
701
char *key, *checksum;
840
PdfDocument *pdf_doc = (PdfDocument *) findPdfDocument(img_filepath(idict));
841
assert(pdf_doc != NULL);
842
xref = pdf_doc->xref;
843
inObjList = pdf_doc->inObjList;
704
PdfDocument *pdf_doc;
705
assert(idict != NULL);
706
// calculate a checksum string
707
checksum = get_file_checksum(img_filepath(idict));
709
pdf_doc = refPdfDocument(img_filepath(idict));
710
if (strncmp(pdf_doc->checksum, checksum, PDF_CHECKSUM_SIZE) != 0) {
711
pdftex_fail("PDF inclusion: file has changed '%s'",
712
img_filename(idict));
715
pdf_doc->xref = pdf_doc->doc->getXRef();
716
(void) pdf_doc->doc->getCatalog()->getPage(img_pagenum(idict));
845
717
page = pdf_doc->doc->getCatalog()->getPage(img_pagenum(idict));
846
718
PDFRectangle *pagebox;
848
720
// write the Page header
849
pdf_puts("/Type /XObject\n/Subtype /Form\n");
721
pdf_puts(pdf, "/Type /XObject\n/Subtype /Form\n");
850
722
if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
851
pdf_printf("%s\n", img_attr(idict));
852
pdf_puts("/FormType 1\n");
723
pdf_printf(pdf, "%s\n", img_attr(idict));
724
pdf_puts(pdf, "/FormType 1\n");
854
726
// write additional information
855
pdf_printf("/%s.FileName (%s)\n", pdfkeyprefix,
727
pdf_printf(pdf, "/%s.FileName (%s)\n", pdfkeyprefix,
856
728
convertStringToPDFString(pdf_doc->file_path,
857
729
strlen(pdf_doc->file_path)));
858
pdf_printf("/%s.PageNumber %i\n", pdfkeyprefix, (int) img_pagenum(idict));
730
pdf_printf(pdf, "/%s.PageNumber %i\n", pdfkeyprefix,
731
(int) img_pagenum(idict));
859
732
pdf_doc->doc->getDocInfoNF(&info);
860
733
if (info.isRef()) {
861
734
// the info dict must be indirect (PDF Ref p. 61)
862
pdf_printf("/%s.InfoDict ", pdfkeyprefix);
863
pdf_printf("%d 0 R\n", addOther(info.getRef()));
735
pdf_printf(pdf, "/%s.InfoDict ", pdfkeyprefix);
736
pdf_printf(pdf, "%d 0 R\n", addInObj(pdf, pdf_doc, info.getRef()));
865
738
if (img_is_bbox(idict)) {
866
739
bbox[0] = int2bp(img_bbox(idict)[0]);
878
751
sprintf(s, "/BBox [%.8f %.8f %.8f %.8f]\n", bbox[0], bbox[1], bbox[2],
880
pdf_puts(stripzeros(s));
753
pdf_puts(pdf, stripzeros(s));
881
754
// The /Matrix calculation is replaced by transforms in out_img().
883
756
// write the page Group if it's there
884
757
if (epdf_lastGroupObjectNum > 0) {
885
758
if (page->getGroup() != NULL) {
886
initDictFromDict(lastGroup, page->getGroup());
759
initDictFromDict(pdf_doc, lastGroup, page->getGroup());
887
760
if (lastGroup->dictGetLength() > 0) {
761
pdf_puts(pdf, "/Group ");
889
762
groupIsIndirect = lastGroup->isRef();
890
pdf_printf("%d 0 R", (int) epdf_lastGroupObjectNum);
763
pdf_printf(pdf, "%d 0 R", (int) epdf_lastGroupObjectNum);
895
768
// write the page Metadata if it's there
896
769
if (page->getMetadata() != NULL) {
897
770
metadata->initStream(page->getMetadata());
898
pdf_puts("/Metadata ");
899
copyObject(&metadata);
771
pdf_puts(pdf, "/Metadata ");
772
copyObject(pdf, pdf_doc, &metadata);
902
775
// write the page PieceInfo if it's there
903
776
if (page->getPieceInfo() != NULL) {
904
initDictFromDict(pieceinfo, page->getPieceInfo());
777
initDictFromDict(pdf_doc, pieceinfo, page->getPieceInfo());
905
778
if (pieceinfo->dictGetLength() > 0) {
906
pdf_puts("/PieceInfo ");
907
copyObject(&pieceinfo);
779
pdf_puts(pdf, "/PieceInfo ");
780
copyObject(pdf, pdf_doc, &pieceinfo);
911
784
// copy LastModified (needed when PieceInfo is there)
912
785
if (page->getLastModified() != NULL) {
913
pdf_printf("/LastModified (%s)\n",
786
pdf_printf(pdf, "/LastModified (%s)\n",
914
787
page->getLastModified()->getCString());
916
789
// write the page SeparationInfo if it's there
917
790
if (page->getSeparationInfo() != NULL) {
918
initDictFromDict(separationInfo, page->getSeparationInfo());
791
initDictFromDict(pdf_doc, separationInfo, page->getSeparationInfo());
919
792
if (separationInfo->dictGetLength() > 0) {
920
pdf_puts("/SeparationInfo ");
921
copyObject(&separationInfo);
793
pdf_puts(pdf, "/SeparationInfo ");
794
copyObject(pdf, pdf_doc, &separationInfo);
925
798
// write the Resources dictionary
961
829
// Variant B: copy stream without recompressing
963
contents->streamGetDict()->lookup("F", &obj1);
831
contents->streamGetDict()->lookup((char *) "F", &obj1);
964
832
if (!obj1->isNull()) {
965
833
pdftex_fail("PDF inclusion: Unsupported external stream");
967
contents->streamGetDict()->lookup("Length", &obj1);
835
contents->streamGetDict()->lookup((char *) "Length", &obj1);
968
836
assert(!obj1->isNull());
969
pdf_puts("/Length ");
972
contents->streamGetDict()->lookup("Filter", &obj1);
837
pdf_puts(pdf, "/Length ");
838
copyObject(pdf, pdf_doc, &obj1);
840
contents->streamGetDict()->lookup((char *) "Filter", &obj1);
973
841
if (!obj1->isNull()) {
974
pdf_puts("/Filter ");
977
contents->streamGetDict()->lookup("DecodeParms", &obj1);
842
pdf_puts(pdf, "/Filter ");
843
copyObject(pdf, pdf_doc, &obj1);
845
contents->streamGetDict()->lookup((char *) "DecodeParms", &obj1);
978
846
if (!obj1->isNull()) {
979
pdf_puts("/DecodeParms ");
847
pdf_puts(pdf, "/DecodeParms ");
848
copyObject(pdf, pdf_doc, &obj1);
984
pdf_puts(">>\nstream\n");
985
copyStream(contents->getStream()->getBaseStream());
852
pdf_puts(pdf, ">>\nstream\n");
853
copyStream(pdf, contents->getStream()->getBaseStream());
987
855
} else if (contents->isArray()) {
856
pdf_begin_stream(pdf);
989
857
for (i = 0, l = contents->arrayGetLength(); i < l; ++i) {
990
858
Object contentsobj;
991
copyStream((contents->arrayGet(i, &contentsobj))->getStream());
859
copyStream(pdf, (contents->arrayGet(i, &contentsobj))->getStream());
992
860
contentsobj.free();
995
863
} else { // the contents are optional, but we need to include an empty stream
864
pdf_begin_stream(pdf);
999
867
// write out all indirect objects
1001
// write out all used encodings (and delete list)
1004
pdf_doc->inObjList = inObjList;
1005
assert(xref == pdf_doc->xref); // xref should be unchanged
868
writeRefs(pdf, pdf_doc);
1008
void write_epdf(image_dict * idict)
871
// this relay function is needed to keep some destructor quiet (???)
873
void write_epdf(PDF pdf, image_dict * idict)
1010
assert(idict != NULL);
875
write_epdf1(pdf, idict);
1012
876
unrefPdfDocument(img_filepath(idict));
1015
879
//**********************************************************************
1016
880
// Deallocate a PdfDocument with all its resources
1018
static void deletePdfDocument(PdfDocument * pdf_doc)
882
static void deletePdfDocumentPdfDoc(PdfDocument * pdf_doc)
1020
885
assert(pdf_doc != NULL);
1021
// free PdfDocument's resources
886
// this may be probably needed for an emergency destroyPdfDocument()
1023
887
for (r = pdf_doc->inObjList; r != NULL; r = n) {
1027
891
delete pdf_doc->doc;
1028
xfree(pdf_doc->file_path);
1032
static void destroyPdfDocument(void *pa, void *pb)
895
static void destroyPdfDocument(void *pa, void * /*pb */ )
1034
897
PdfDocument *pdf_doc = (PdfDocument *) pa;
1035
deletePdfDocument(pdf_doc);
898
deletePdfDocumentPdfDoc(pdf_doc);
899
// TODO: delete rest of pdf_doc
902
// Called when an image has been written and its resources in image_tab are
903
// freed and it's not referenced anymore.
905
void unrefPdfDocument(char *file_path)
907
PdfDocument *pdf_doc = findPdfDocument(file_path);
908
assert(pdf_doc != NULL);
909
assert(pdf_doc->occurences > 0); // aim for point landing
910
pdf_doc->occurences--;
912
fprintf(stderr, "\nluatex Debug: Decrementing %s (%d)\n",
913
pdf_doc->file_path, pdf_doc->occurences);
915
if (pdf_doc->occurences == 0) {
917
fprintf(stderr, "\nluatex Debug: Deleting %s\n", pdf_doc->file_path);
919
assert(pdf_doc->inObjList == NULL); // should be eaten up already
920
deletePdfDocumentPdfDoc(pdf_doc);
1038
924
// Called when PDF embedding system is finalized.