summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc')
-rw-r--r--Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc1103
1 files changed, 419 insertions, 684 deletions
diff --git a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc
index 536c6398cd7..8a177163a76 100644
--- a/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc
+++ b/Build/source/texk/web2c/luatexdir/image/pdftoepdf.cc
@@ -1,7 +1,7 @@
/* pdftoepdf.cc
-
+
Copyright 1996-2006 Han The Thanh <thanh@pdftex.org>
- Copyright 2006-2008 Taco Hoekwater <taco@luatex.org>
+ Copyright 2006-2010 Taco Hoekwater <taco@luatex.org>
This file is part of LuaTeX.
@@ -18,46 +18,13 @@
You should have received a copy of the GNU General Public License along
with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */
-#include <stdlib.h>
-#include <math.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#ifdef POPPLER_VERSION
-# define GString GooString
-# include <dirent.h>
-# include <poppler-config.h>
-# include <goo/GooString.h>
-# include <goo/gmem.h>
-# include <goo/gfile.h>
-#else
-# include <aconf.h>
-# include <GString.h>
-# include <gmem.h>
-# include <gfile.h>
-# include <assert.h>
-#endif
-#include "Object.h"
-#include "Stream.h"
-#include "Array.h"
-#include "Dict.h"
-#include "XRef.h"
-#include "Catalog.h"
-#include "Link.h"
-#include "Page.h"
-#include "GfxFont.h"
-#include "PDFDoc.h"
-#include "GlobalParams.h"
-#include "Error.h"
+static const char _svn_version[] =
+ "$Id: pdftoepdf.cc 3431 2010-02-17 20:35:50Z oneiros $ "
+ "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/image/pdftoepdf.cc $";
#include "epdf.h"
-static const char _svn_version[] =
- "$Id: pdftoepdf.cc 2448 2009-06-08 07:43:50Z taco $ "
- "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.40.6/source/texk/web2c/luatexdir/image/pdftoepdf.cc $";
-
-#define one_hundred_bp 6578176 /* 7227 * 65536 / 72 */
+#define one_hundred_bp 6578176 // one_hundred_bp = 7227 * 65536 / 72
// This file is mostly C and not very much C++; it's just used to interface
// the functions of xpdf, which happens to be written in C++.
@@ -67,81 +34,16 @@ static const char _svn_version[] =
#define pdfkeyprefix "PTEX"
-// PdfObject encapsulates the xpdf Object type,
-// and properly frees its resources on destruction.
-// Use obj-> to access members of the Object,
-// and &obj to get a pointer to the object.
-// It is no longer necessary to call Object::free explicitely.
-
-/* *INDENT-OFF* */
-class PdfObject {
- public:
- PdfObject() { // nothing
- }
- ~PdfObject() {
- iObject.free();
- }
- Object *operator->() {
- return &iObject;
- }
- Object *operator&() {
- return &iObject;
- }
- private: // no copying or assigning
- PdfObject(const PdfObject &);
- void operator=(const PdfObject &);
- public:
- Object iObject;
-};
-/* *INDENT-ON* */
-
-// When copying the Resources of the selected page, all objects are copied
-// recusively top-down. Indirect objects however are not fetched during
-// copying, but get a new object number from pdfTeX and then will be
-// appended into a linked list. Duplicates are checked and removed from the
-// list of indirect objects during appending.
-
-enum InObjType { objFont, objFontDesc, objOther };
-
-struct InObj {
- Ref ref; // ref in original PDF
- InObjType type; // object type
- integer num; // new object number in output PDF
- fd_entry *fd; // pointer to /FontDescriptor object structure
- integer enc_objnum; // Encoding for objFont
- int written; // has it been written to output PDF?
- InObj *next; // next entry in list of indirect objects
-};
-
-struct UsedEncoding {
- integer enc_objnum;
- GfxFont *font;
- UsedEncoding *next;
-};
-
-static XRef *xref = NULL;
-static InObj *inObjList = NULL;
-static UsedEncoding *encodingList;
static GBool isInit = gFalse;
-static bool groupIsIndirect;
-static PdfObject lastGroup;
//**********************************************************************
-// Maintain AVL tree of open embedded PDF files
+// Maintain AVL tree of all PDF files for embedding
static avl_table *PdfDocumentTree = NULL;
-struct PdfDocument {
- char *file_path; // full file name including path
- PDFDoc *doc;
- XRef *xref;
- InObj *inObjList;
- int occurences; // number of references to the PdfDocument; it can be deleted when occurences == 0
-};
-
-/* AVL sort PdfDocument into PdfDocumentTree by file_path */
+// AVL sort PdfDocument into PdfDocumentTree by file_path
-static int CompPdfDocument(const void *pa, const void *pb, void *p)
+static int CompPdfDocument(const void *pa, const void *pb, void * /*p */ )
{
return strcmp(((const PdfDocument *) pa)->file_path,
((const PdfDocument *) pb)->file_path);
@@ -154,8 +56,7 @@ static PdfDocument *findPdfDocument(char *file_path)
PdfDocument *pdf_doc, tmp;
assert(file_path != NULL);
if (PdfDocumentTree == NULL)
- PdfDocumentTree = avl_create(CompPdfDocument, NULL, &avl_xallocator);
- assert(PdfDocumentTree != NULL);
+ return NULL;
tmp.file_path = file_path;
pdf_doc = (PdfDocument *) avl_find(PdfDocumentTree, &tmp);
return pdf_doc;
@@ -164,26 +65,35 @@ static PdfDocument *findPdfDocument(char *file_path)
// Returns pointer to PdfDocument structure for PDF file.
// Creates a new structure if it doesn't exist yet.
-static PdfDocument *refPdfDocument(char *file_path)
+char *get_file_checksum(char *a);
+
+PdfDocument *refPdfDocument(char *file_path)
{
PdfDocument *pdf_doc = findPdfDocument(file_path);
if (pdf_doc == NULL) {
+ if (PdfDocumentTree == NULL)
+ PdfDocumentTree =
+ avl_create(CompPdfDocument, NULL, &avl_xallocator);
pdf_doc = new PdfDocument;
pdf_doc->file_path = xstrdup(file_path);
+ pdf_doc->checksum = get_file_checksum(file_path);
void **aa = avl_probe(PdfDocumentTree, pdf_doc);
assert(aa != NULL);
+ pdf_doc->ObjMapTree = NULL;
+ pdf_doc->doc = NULL;
+ }
+ if (pdf_doc->doc == NULL) {
GString *docName = new GString(pdf_doc->file_path);
pdf_doc->doc = new PDFDoc(docName); // takes ownership of docName
if (!pdf_doc->doc->isOk() || !pdf_doc->doc->okToPrint())
pdftex_fail("xpdf: reading PDF image failed");
- pdf_doc->xref = NULL;
pdf_doc->inObjList = NULL;
pdf_doc->occurences = 0; // 0 = unreferenced
+ }
#ifdef DEBUG
- fprintf(stderr, "\nluatex Debug: Creating %s (%d)\n",
- pdf_doc->file_path, pdf_doc->occurences);
+ fprintf(stderr, "\nluatex Debug: Creating %s (%d)\n",
+ pdf_doc->file_path, pdf_doc->occurences);
#endif
- }
pdf_doc->occurences++;
#ifdef DEBUG
fprintf(stderr, "\nluatex Debug: Incrementing %s (%d)\n",
@@ -192,293 +102,94 @@ static PdfDocument *refPdfDocument(char *file_path)
return pdf_doc;
}
-static void deletePdfDocument(PdfDocument *);
+//**********************************************************************
+// AVL sort ObjMap into ObjMapTree by object number and generation
-// Called when an image has been written and its resources in image_tab are
-// freed and it's not referenced anymore.
+// keep the ObjMap struct small, as these are accumulated until the end
-void unrefPdfDocument(char *file_path)
+struct ObjMap {
+ Ref in; // object num/gen in orig. PDF file
+ int out_num; // object num after embedding (gen == 0)
+};
+
+static int CompObjMap(const void *pa, const void *pb, void * /*p */ )
{
- PdfDocument *pdf_doc = findPdfDocument(file_path);
- assert(pdf_doc != NULL);
- assert(pdf_doc->occurences > 0); // aim for point landing
- pdf_doc->occurences--;
-#ifdef DEBUG
- fprintf(stderr, "\nluatex Debug: Decrementing %s (%d)\n",
- pdf_doc->file_path, pdf_doc->occurences);
-#endif
- if (pdf_doc->occurences == 0) {
-#ifdef DEBUG
- fprintf(stderr, "\nluatex Debug: Deleting %s\n", pdf_doc->file_path);
-#endif
- void *a = avl_delete(PdfDocumentTree, pdf_doc);
- assert((PdfDocument *) a == pdf_doc);
- deletePdfDocument(pdf_doc);
- }
+ const Ref *a = &(((const ObjMap *) pa)->in);
+ const Ref *b = &(((const ObjMap *) pb)->in);
+ if (a->num > b->num)
+ return 1;
+ if (a->num < b->num)
+ return -1;
+ if (a->gen == b->gen) // most likely gen == 0 anyway
+ return 0;
+ if (a->gen < b->gen)
+ return -1;
+ return 1;
}
-//**********************************************************************
-
-// Replacement for
-// Object *initDict(Dict *dict1){ initObj(objDict); dict = dict1; return this; }
-
-static void initDictFromDict(PdfObject & obj, Dict * dict)
+static ObjMap *findObjMap(PdfDocument * pdf_doc, Ref in)
{
- obj->initDict(xref);
- for (int i = 0, l = dict->getLength(); i < l; i++) {
- Object obj1;
- obj->dictAdd(copyString(dict->getKey(i)), dict->getValNF(i, &obj1));
- }
+ ObjMap *obj_map, tmp;
+ assert(pdf_doc != NULL);
+ if (pdf_doc->ObjMapTree == NULL)
+ return NULL;
+ tmp.in = in;
+ obj_map = (ObjMap *) avl_find(pdf_doc->ObjMapTree, &tmp);
+ return obj_map;
}
-static int addEncoding(GfxFont * gfont)
+static void addObjMap(PdfDocument * pdf_doc, Ref in, int out_num)
{
- UsedEncoding *n;
- n = new UsedEncoding;
- n->next = encodingList;
- encodingList = n;
- n->font = gfont;
- n->enc_objnum = pdf_new_objnum();
- return n->enc_objnum;
+ ObjMap *obj_map = NULL;
+ assert(findObjMap(pdf_doc, in) == NULL);
+ if (pdf_doc->ObjMapTree == NULL)
+ pdf_doc->ObjMapTree = avl_create(CompObjMap, NULL, &avl_xallocator);
+ obj_map = new ObjMap;
+ obj_map->in = in;
+ obj_map->out_num = out_num;
+ void **aa = avl_probe(pdf_doc->ObjMapTree, obj_map);
+ assert(aa != NULL);
}
-#define addFont(ref, fd, enc_objnum) \
- addInObj(objFont, ref, fd, enc_objnum)
+// When copying the Resources of the selected page, all objects are
+// copied recursively top-down. The findObjMap() function checks if an
+// object has already been copied; if so, instead of copying just the
+// new object number will be referenced. The ObjMapTree guarantees,
+// that during the entire LuaTeX run any object from any embedded PDF
+// file will end up max. once in the output PDF file. Indirect objects
+// are not fetched during copying, but get a new object number from
+// LuaTeX and then will be appended into a linked list.
-// addFontDesc is only used to avoid writing the original FontDescriptor
-// from the PDF file.
-
-#define addFontDesc(ref, fd) \
- addInObj(objFontDesc, ref, fd, 0)
-
-#define addOther(ref) \
- addInObj(objOther, ref, NULL, 0)
-
-static int addInObj(InObjType type, Ref ref, fd_entry * fd, integer e)
+static int addInObj(PDF pdf, PdfDocument * pdf_doc, Ref ref)
{
- InObj *p, *q, *n = new InObj;
- if (ref.num == 0)
- pdftex_fail("PDF inclusion: invalid reference");
+ ObjMap *obj_map;
+ InObj *p, *q, *n;
+ if (ref.num == 0) {
+ pdftex_fail("PDF inclusion: reference to invalid object"
+ " (is the included pdf broken?)");
+ }
+ if ((obj_map = findObjMap(pdf_doc, ref)) != NULL)
+ return obj_map->out_num;
+ n = new InObj;
n->ref = ref;
- n->type = type;
n->next = NULL;
- n->fd = fd;
- n->enc_objnum = e;
- n->written = 0;
- if (inObjList == NULL)
- inObjList = n;
+ n->num = pdf_new_objnum(pdf);
+ addObjMap(pdf_doc, ref, n->num);
+ if (pdf_doc->inObjList == NULL)
+ pdf_doc->inObjList = n;
else {
- for (p = inObjList; p != NULL; p = p->next) {
- if (p->ref.num == ref.num && p->ref.gen == ref.gen) {
- delete n;
- return p->num;
- }
- q = p;
- }
// it is important to add new objects at the end of the list,
// because new objects are being added while the list is being
// written out by writeRefs().
+ for (p = pdf_doc->inObjList; p != NULL; p = p->next)
+ q = p;
q->next = n;
}
- if (type == objFontDesc)
- n->num = get_fd_objnum(fd);
- else
- n->num = pdf_new_objnum();
return n->num;
}
-static void copyName(char *s)
-{
- pdf_puts("/");
- for (; *s != 0; s++) {
- if (isdigit(*s) || isupper(*s) || islower(*s) || *s == '_' ||
- *s == '.' || *s == '-' || *s == '+')
- pdfout(*s);
- else
- pdf_printf("#%.2X", *s & 0xFF);
- }
-}
-
-static int getNewObjectNumber(Ref ref)
-{
- InObj *p;
- if (inObjList == 0) {
- pdftex_fail("No objects copied yet");
- } else {
- for (p = inObjList; p != 0; p = p->next) {
- if (p->ref.num == ref.num && p->ref.gen == ref.gen) {
- return p->num;
- }
- }
- pdftex_fail("Object not yet copied: %i %i", ref.num, ref.gen);
- }
-}
-
-static void copyObject(Object *);
-
-static void copyDictEntry(Object * obj, int i)
-{
- PdfObject obj1;
- copyName(obj->dictGetKey(i));
- pdf_puts(" ");
- obj->dictGetValNF(i, &obj1);
- copyObject(&obj1);
- pdf_puts("\n");
-}
-
-static void copyDict(Object * obj)
-{
- int i, l;
- if (!obj->isDict())
- pdftex_fail("PDF inclusion: invalid dict type <%s>",
- obj->getTypeName());
- for (i = 0, l = obj->dictGetLength(); i < l; ++i)
- copyDictEntry(obj, i);
-}
-
-static void copyFontDict(Object * obj, InObj * r)
-{
- int i, l;
- char *key;
- if (!obj->isDict())
- pdftex_fail("PDF inclusion: invalid dict type <%s>",
- obj->getTypeName());
- pdf_puts("<<\n");
- assert(r->type == objFont); // FontDescriptor is in fd_tree
- for (i = 0, l = obj->dictGetLength(); i < l; ++i) {
- key = obj->dictGetKey(i);
- if (strncmp("FontDescriptor", key, strlen("FontDescriptor")) == 0
- || strncmp("BaseFont", key, strlen("BaseFont")) == 0
- || strncmp("Encoding", key, strlen("Encoding")) == 0)
- continue; // skip original values
- copyDictEntry(obj, i);
- }
- // write new FontDescriptor, BaseFont, and Encoding
- pdf_printf("/FontDescriptor %d 0 R\n", (int) get_fd_objnum(r->fd));
- pdf_printf("/BaseFont %d 0 R\n", (int) get_fn_objnum(r->fd));
- pdf_printf("/Encoding %d 0 R\n", (int) r->enc_objnum);
- pdf_puts(">>");
-}
-
-static void copyStream(Stream * str)
-{
- int c;
- str->reset();
- while ((c = str->getChar()) != EOF) {
- pdfout(c);
- pdf_last_byte = c;
- }
-}
-
-static void copyProcSet(Object * obj)
-{
- int i, l;
- PdfObject procset;
- if (!obj->isArray())
- pdftex_fail("PDF inclusion: invalid ProcSet array type <%s>",
- obj->getTypeName());
- pdf_puts("/ProcSet [ ");
- for (i = 0, l = obj->arrayGetLength(); i < l; ++i) {
- obj->arrayGetNF(i, &procset);
- if (!procset->isName())
- pdftex_fail("PDF inclusion: invalid ProcSet entry type <%s>",
- procset->getTypeName());
- copyName(procset->getName());
- pdf_puts(" ");
- }
- pdf_puts("]\n");
-}
-
-#define REPLACE_TYPE1C true
-
-static void copyFont(char *tag, Object * fontRef)
-{
- PdfObject fontdict, subtype, basefont, fontdescRef, fontdesc, charset,
- fontfile, ffsubtype, stemV;
- GfxFont *gfont;
- fd_entry *fd;
- fm_entry *fontmap;
- // Check whether the font has already been embedded before analysing it.
- InObj *p;
- Ref ref = fontRef->getRef();
- for (p = inObjList; p; p = p->next) {
- if (p->ref.num == ref.num && p->ref.gen == ref.gen) {
- copyName(tag);
- pdf_printf(" %d 0 R ", (int) p->num);
- return;
- }
- }
- // Only handle included Type1 (and Type1C) fonts; anything else will be copied.
- // Type1C fonts are replaced by Type1 fonts, if REPLACE_TYPE1C is true.
- if (!fixed_inclusion_copy_font && fontRef->fetch(xref, &fontdict)->isDict()
- && fontdict->dictLookup("Subtype", &subtype)->isName()
- && !strcmp(subtype->getName(), "Type1")
- && fontdict->dictLookup("BaseFont", &basefont)->isName()
- && fontdict->dictLookupNF("FontDescriptor", &fontdescRef)->isRef()
- && fontdescRef->fetch(xref, &fontdesc)->isDict()
- && (fontdesc->dictLookup("FontFile", &fontfile)->isStream()
- || (REPLACE_TYPE1C
- && fontdesc->dictLookup("FontFile3", &fontfile)->isStream()
- && fontfile->streamGetDict()->lookup("Subtype",
- &ffsubtype)->isName()
- && !strcmp(ffsubtype->getName(), "Type1C")))
- && (fontmap = lookup_fontmap(basefont->getName())) != NULL) {
- // copy the value of /StemV
- fontdesc->dictLookup("StemV", &stemV);
- fd = epdf_create_fontdescriptor(fontmap, stemV->getInt());
- if (fontdesc->dictLookup("CharSet", &charset) &&
- charset->isString() && is_subsetable(fontmap))
- epdf_mark_glyphs(fd, charset->getString()->getCString());
- else
- embed_whole_font(fd);
- addFontDesc(fontdescRef->getRef(), fd);
- copyName(tag);
- gfont = GfxFont::makeFont(xref, tag, fontRef->getRef(),
- fontdict->getDict());
- pdf_printf(" %d 0 R ", addFont(fontRef->getRef(), fd,
- addEncoding(gfont)));
- } else {
- copyName(tag);
- pdf_puts(" ");
- copyObject(fontRef);
- }
-}
-
-static void copyFontResources(Object * obj)
-{
- PdfObject fontRef;
- int i, l;
- if (!obj->isDict())
- pdftex_fail("PDF inclusion: invalid font resources dict type <%s>",
- obj->getTypeName());
- pdf_puts("/Font << ");
- for (i = 0, l = obj->dictGetLength(); i < l; ++i) {
- obj->dictGetValNF(i, &fontRef);
- if (fontRef->isRef())
- copyFont(obj->dictGetKey(i), &fontRef);
- else
- pdftex_fail("PDF inclusion: invalid font in reference type <%s>",
- fontRef->getTypeName());
- }
- pdf_puts(">>\n");
-}
-
-static void copyOtherResources(Object * obj, char *key)
-{
- // copies all other resources (write_epdf handles Fonts and ProcSets),
- // but gives a warning if an object is not a dictionary.
-
- if (!obj->isDict())
- //FIXME: Write the message only to the log file
- pdftex_warn("PDF inclusion: invalid other resource which is no dict"
- " (key '%s', type <%s>); copying it anyway.",
- key, obj->getTypeName());
- copyName(key);
- pdf_puts(" ");
- copyObject(obj);
-}
-
-// Function onverts double to string; very small and very large numbers
+//**********************************************************************
+// Function converts double to string; very small and very large numbers
// are NOT converted to scientific notation.
// n must be a number or real conforming to the implementation limits
// of PDF as specified in appendix C.1 of the PDF Ref.
@@ -536,165 +247,215 @@ static char *convertNumToPDF(double n)
return (char *) buf;
}
-static void copyObject(Object * obj)
+static void copyObject(PDF, PdfDocument *, Object *);
+
+static void copyString(PDF pdf, GString * string)
{
- PdfObject obj1;
- int i, l, c;
- Ref ref;
char *p;
- GString *s;
- if (obj->isBool()) {
- pdf_printf("%s", obj->getBool()? "true" : "false");
- } else if (obj->isInt()) {
- pdf_printf("%i", obj->getInt());
- } else if (obj->isReal()) {
- pdf_printf("%s", convertNumToPDF(obj->getReal()));
- } else if (obj->isNum()) {
- pdf_printf("%s", convertNumToPDF(obj->getNum()));
- } else if (obj->isString()) {
- s = obj->getString();
- p = s->getCString();
- l = s->getLength();
- if (strlen(p) == (unsigned int) l) {
- pdf_puts("(");
- for (; *p != 0; p++) {
- c = (unsigned char) *p;
- if (c == '(' || c == ')' || c == '\\')
- pdf_printf("\\%c", c);
- else if (c < 0x20 || c > 0x7F)
- pdf_printf("\\%03o", c);
- else
- pdfout(c);
- }
- pdf_puts(")");
- } else {
- pdf_puts("<");
- for (i = 0; i < l; i++) {
- c = s->getChar(i) & 0xFF;
- pdf_printf("%.2x", c);
- }
- pdf_puts(">");
- }
- } else if (obj->isName()) {
- copyName(obj->getName());
- } else if (obj->isNull()) {
- pdf_puts("null");
- } else if (obj->isArray()) {
- pdf_puts("[");
- for (i = 0, l = obj->arrayGetLength(); i < l; ++i) {
- obj->arrayGetNF(i, &obj1);
- if (!obj1->isName())
- pdf_puts(" ");
- copyObject(&obj1);
+ unsigned char c;
+ size_t i, l;
+ p = string->getCString();
+ l = (size_t) string->getLength();
+ if (strlen(p) == l) {
+ pdf_puts(pdf, "(");
+ for (; *p != 0; p++) {
+ c = (unsigned char) *p;
+ if (c == '(' || c == ')' || c == '\\')
+ pdf_printf(pdf, "\\%c", c);
+ else if (c < 0x20 || c > 0x7F)
+ pdf_printf(pdf, "\\%03o", (int) c);
+ else
+ pdf_out(pdf, c);
}
- pdf_puts("]");
- } else if (obj->isDict()) {
- pdf_puts("<<\n");
- copyDict(obj);
- pdf_puts(">>");
- } else if (obj->isStream()) {
- initDictFromDict(obj1, obj->streamGetDict());
- obj->streamGetDict()->incRef();
- pdf_puts("<<\n");
- copyDict(&obj1);
- pdf_puts(">>\n");
- pdf_puts("stream\n");
- copyStream(obj->getStream()->getUndecodedStream());
- if (pdf_last_byte != '\n')
- pdf_puts("\n");
- pdf_puts("endstream"); // can't simply write pdf_end_stream()
- } else if (obj->isRef()) {
- ref = obj->getRef();
- if (ref.num == 0) {
- pdftex_fail
- ("PDF inclusion: reference to invalid object"
- " (is the included pdf broken?)");
- } else
- pdf_printf("%d 0 R", addOther(ref));
+ pdf_puts(pdf, ")");
} else {
- pdftex_fail("PDF inclusion: type <%s> cannot be copied",
- obj->getTypeName());
+ pdf_puts(pdf, "<");
+ for (i = 0; i < l; i++) {
+ c = (unsigned char) string->getChar(i);
+ pdf_printf(pdf, "%.2x", (int) c);
+ }
+ pdf_puts(pdf, ">");
}
}
-static void writeRefs()
+static void copyName(PDF pdf, char *s)
{
- InObj *r;
- for (r = inObjList; r != NULL; r = r->next) {
- if (!r->written) {
- Object obj1;
- r->written = 1;
- xref->fetch(r->ref.num, r->ref.gen, &obj1);
- if (r->type == objFont) {
- assert(!obj1.isStream());
- zpdf_begin_obj(r->num, 2); // \pdfobjcompresslevel = 2 is for this
- copyFontDict(&obj1, r);
- pdf_puts("\n");
- pdf_end_obj();
- } else if (r->type != objFontDesc) { // /FontDescriptor is written via write_fontdescriptor()
- if (obj1.isStream())
- zpdf_begin_obj(r->num, 0);
- else
- zpdf_begin_obj(r->num, 2); // \pdfobjcompresslevel = 2 is for this
- copyObject(&obj1);
- pdf_puts("\n");
- pdf_end_obj();
- }
- obj1.free();
- }
+ pdf_puts(pdf, "/");
+ for (; *s != 0; s++) {
+ if (isdigit(*s) || isupper(*s) || islower(*s) || *s == '_' ||
+ *s == '.' || *s == '-' || *s == '+')
+ pdf_out(pdf, *s);
+ else
+ pdf_printf(pdf, "#%.2X", *s & 0xFF);
}
}
-static void writeEncodings()
+static void copyArray(PDF pdf, PdfDocument * pdf_doc, Array * array)
{
- UsedEncoding *r, *n;
- char *glyphNames[256], *s;
- int i;
- for (r = encodingList; r != NULL; r = r->next) {
- for (i = 0; i < 256; i++) {
- if (r->font->isCIDFont()) {
- pdftex_fail
- ("PDF inclusion: CID fonts are not supported"
- " (try to disable font replacement to fix this)");
- }
- if ((s = ((Gfx8BitFont *) r->font)->getCharName(i)) != NULL)
- glyphNames[i] = s;
- else
- glyphNames[i] = notdef;
- }
- epdf_write_enc(glyphNames, r->enc_objnum);
+ int i, l;
+ PdfObject obj1;
+ pdf_puts(pdf, "[");
+ for (i = 0, l = array->getLength(); i < l; ++i) {
+ array->getNF(i, &obj1);
+ if (!obj1->isName())
+ pdf_puts(pdf, " ");
+ copyObject(pdf, pdf_doc, &obj1);
+ }
+ pdf_puts(pdf, "]");
+}
+
+static void copyDict(PDF pdf, PdfDocument * pdf_doc, Dict * dict)
+{
+ int i, l;
+ PdfObject obj1;
+ pdf_puts(pdf, "<<");
+ for (i = 0, l = dict->getLength(); i < l; ++i) {
+ copyName(pdf, dict->getKey(i));
+ pdf_puts(pdf, " ");
+ dict->getValNF(i, &obj1);
+ copyObject(pdf, pdf_doc, &obj1);
+ pdf_puts(pdf, "\n");
+ }
+ pdf_puts(pdf, ">>");
+}
+
+static void copyStreamStream(PDF pdf, Stream * str)
+{
+ int c;
+ str->reset();
+ while ((c = str->getChar()) != EOF) {
+ pdf_out(pdf, c);
+ pdf->last_byte = c;
+ }
+}
+
+static void copyStream(PDF pdf, PdfDocument * pdf_doc, Stream * stream)
+{
+ copyDict(pdf, pdf_doc, stream->getDict());
+ pdf_puts(pdf, "stream\n");
+ copyStreamStream(pdf, stream->getUndecodedStream());
+ if (pdf->last_byte != '\n')
+ pdf_puts(pdf, "\n");
+ pdf_puts(pdf, "endstream"); // can't simply write pdf_end_stream()
+}
+
+static void copyObject(PDF pdf, PdfDocument * pdf_doc, Object * obj)
+{
+ switch (obj->getType()) {
+ case objBool:
+ pdf_printf(pdf, "%s", obj->getBool()? "true" : "false");
+ break;
+ case objInt:
+ pdf_printf(pdf, "%i", obj->getInt());
+ break;
+ case objReal:
+ pdf_printf(pdf, "%s", convertNumToPDF(obj->getReal()));
+ break;
+ // not needed:
+ // GBool isNum() { return type == objInt || type == objReal; }
+ case objString:
+ copyString(pdf, obj->getString());
+ break;
+ case objName:
+ copyName(pdf, obj->getName());
+ break;
+ case objNull:
+ pdf_puts(pdf, "null");
+ break;
+ case objArray:
+ copyArray(pdf, pdf_doc, obj->getArray());
+ break;
+ case objDict:
+ copyDict(pdf, pdf_doc, obj->getDict());
+ break;
+ case objStream:
+ copyStream(pdf, pdf_doc, obj->getStream());
+ break;
+ case objRef:
+ pdf_printf(pdf, "%d 0 R", addInObj(pdf, pdf_doc, obj->getRef()));
+ break;
+ case objCmd:
+ case objError:
+ case objEOF:
+ case objNone:
+ pdftex_fail("PDF inclusion: type <%s> cannot be copied",
+ obj->getTypeName());
+ break;
+ default:
+ assert(0); // xpdf doesn't have any other types
}
- for (r = encodingList; r != NULL; r = n) {
+}
+
+//**********************************************************************
+
+static void writeRefs(PDF pdf, PdfDocument * pdf_doc)
+{
+ InObj *r, *n;
+ XRef *xref;
+ xref = pdf_doc->doc->getXRef();
+ for (r = pdf_doc->inObjList; r != NULL;) {
+ PdfObject obj1;
+ xref->fetch(r->ref.num, r->ref.gen, &obj1);
+ if (obj1->isStream())
+ pdf_begin_obj(pdf, r->num, 0);
+ else
+ pdf_begin_obj(pdf, r->num, 2); // \pdfobjcompresslevel = 2 is for this
+ copyObject(pdf, pdf_doc, &obj1);
+ pdf_puts(pdf, "\n");
+ pdf_end_obj(pdf);
n = r->next;
-#ifdef POPPLER_VERSION
- r->font->decRefCnt();
-#else
- delete r->font;
-#endif
delete r;
+ pdf_doc->inObjList = r = n;
}
}
-// get the pagebox according to the pagebox_spec
+// get the pagebox coordinates according to the pagebox_spec
-static PDFRectangle *get_pagebox(Page * page, integer pagebox_spec)
+static PDFRectangle *get_pagebox(Page * page, int pagebox_spec)
{
- if (pagebox_spec == pdf_box_spec_media)
+ switch (pagebox_spec) {
+ case PDF_BOX_SPEC_MEDIA:
return page->getMediaBox();
- else if (pagebox_spec == pdf_box_spec_crop)
+ break;
+ case PDF_BOX_SPEC_CROP:
return page->getCropBox();
- else if (pagebox_spec == pdf_box_spec_bleed)
+ break;
+ case PDF_BOX_SPEC_BLEED:
return page->getBleedBox();
- else if (pagebox_spec == pdf_box_spec_trim)
+ break;
+ case PDF_BOX_SPEC_TRIM:
return page->getTrimBox();
- else if (pagebox_spec == pdf_box_spec_art)
+ break;
+ case PDF_BOX_SPEC_ART:
return page->getArtBox();
- else
+ break;
+ default:
pdftex_fail("PDF inclusion: unknown value of pagebox spec (%i)",
(int) pagebox_spec);
+ }
return page->getMediaBox(); // to make the compiler happy
}
+#define PDF_CHECKSUM_SIZE 32
+char *get_file_checksum(char *a)
+{
+ struct stat finfo;
+ char *ck = NULL;
+ if (stat(a, &finfo) == 0) {
+ off_t size = finfo.st_size;
+ time_t mtime = finfo.st_mtime;
+ ck = (char *) malloc(PDF_CHECKSUM_SIZE);
+ if (ck == NULL)
+ pdftex_fail("PDF inclusion: out of memory while processing '%s'",
+ a);
+ snprintf(ck, PDF_CHECKSUM_SIZE, "%llu_%llu", (unsigned long long) size,
+ (unsigned long long) mtime);
+ } else {
+ pdftex_fail("PDF inclusion: could not stat() file '%s'", a);
+ }
+ return ck;
+}
+
// Reads various information about the PDF and sets it up for later inclusion.
// This will fail if the PDF version of the PDF is higher than
// minor_pdf_version_wanted or page_name is given and can not be found.
@@ -702,47 +463,37 @@ static PDFRectangle *get_pagebox(Page * page, integer pagebox_spec)
// Returns the page number.
void
-read_pdf_info(image_dict * idict, integer minor_pdf_version_wanted,
- integer pdf_inclusion_errorlevel)
+read_pdf_info(image_dict * idict, int minor_pdf_version_wanted,
+ int pdf_inclusion_errorlevel, img_readtype_e readtype)
{
PdfDocument *pdf_doc;
Page *page;
int rotate;
+ char *checksum;
PDFRectangle *pagebox;
-#ifdef HAVE_GETPDFMAJORVERSION
- int pdf_major_version_found, pdf_minor_version_found;
-#else
- float pdf_version_found, pdf_version_wanted;
-#endif
- float xsize, ysize, xorig, yorig;
+ float pdf_version_found, pdf_version_wanted, xsize, ysize, xorig, yorig;
assert(idict != NULL);
assert(img_type(idict) == IMG_TYPE_PDF);
+ assert(readtype == IMG_CLOSEINBETWEEN); // only this is implemented
// initialize
if (isInit == gFalse) {
globalParams = new GlobalParams();
globalParams->setErrQuiet(gFalse);
isInit = gTrue;
}
+ // calculate a checksum string
+ checksum = get_file_checksum(img_filepath(idict));
// open PDF file
pdf_doc = refPdfDocument(img_filepath(idict));
+ if (strncmp(pdf_doc->checksum, checksum, PDF_CHECKSUM_SIZE) != 0) {
+ pdftex_fail("PDF inclusion: file has changed '%s'",
+ img_filename(idict));
+ }
+ free(checksum);
// check PDF version
// this works only for PDF 1.x -- but since any versions of PDF newer
// than 1.x will not be backwards compatible to PDF 1.x, pdfTeX will
// then have to changed drastically anyway.
-#ifdef HAVE_GETPDFMAJORVERSION
- pdf_major_version_found = pdf_doc->doc->getPDFMajorVersion();
- pdf_minor_version_found = pdf_doc->doc->getPDFMinorVersion();
- if ((pdf_major_version_found > 1)
- || (pdf_minor_version_found > minor_pdf_version_wanted)) {
- const char *msg =
- "PDF inclusion: found PDF version <%d.%d>, but at most version <1.%d> allowed";
- if (pdf_inclusion_errorlevel > 0) {
- pdftex_fail(msg, pdf_major_version_found, pdf_minor_version_found, minor_pdf_version_wanted);
- } else {
- pdftex_warn(msg, pdf_major_version_found, pdf_minor_version_found, minor_pdf_version_wanted);
- }
- }
-#else
pdf_version_found = pdf_doc->doc->getPDFVersion();
pdf_version_wanted = 1 + (minor_pdf_version_wanted * 0.1);
if (pdf_version_found > pdf_version_wanted + 0.01) {
@@ -754,7 +505,6 @@ read_pdf_info(image_dict * idict, integer minor_pdf_version_wanted,
pdftex_warn(msg, pdf_version_found, pdf_version_wanted);
}
}
-#endif
img_totalpages(idict) = pdf_doc->doc->getCatalog()->getNumPages();
if (img_pagename(idict)) {
// get page by name
@@ -777,11 +527,10 @@ read_pdf_info(image_dict * idict, integer minor_pdf_version_wanted,
pdftex_fail("PDF inclusion: required page <%i> does not exist",
(int) img_pagenum(idict));
}
- pdf_doc->xref = pdf_doc->doc->getXRef();
// get the required page
page = pdf_doc->doc->getCatalog()->getPage(img_pagenum(idict));
- // get the pagebox (media, crop...) to use.
+ // get the pagebox coordinates (media, crop,...) to use.
pagebox = get_pagebox(page, img_pagebox(idict));
if (pagebox->x2 > pagebox->x1) {
xorig = pagebox->x1;
@@ -824,67 +573,60 @@ read_pdf_info(image_dict * idict, integer minor_pdf_version_wanted,
("PDF inclusion: "
"/Rotate parameter in PDF file not multiple of 90 degrees.");
}
- if (page->getGroup() != NULL) {
- initDictFromDict(lastGroup, page->getGroup());
- if (lastGroup->dictGetLength() > 0) {
- groupIsIndirect = lastGroup->isRef();
- if (groupIsIndirect) {
- // FIXME: Here we already copy the object. It would be
- // better to do this only after write_epdf, otherwise we
- // may copy ununsed /Group objects
- copyObject(&lastGroup);
- epdf_lastGroupObjectNum =
- getNewObjectNumber(lastGroup->getRef());
- } else {
- // make the group an indirect object; copying is done later
- // by write_additional_epdf_objects after write_epdf
- epdf_lastGroupObjectNum = pdf_new_objnum();
- }
- pdf_puts("\n");
- }
- } else {
- epdf_lastGroupObjectNum = 0;
- }
+ // currently unused info whether PDF contains a /Group
+ if (page->getGroup() != NULL)
+ img_set_group(idict);
+
+ if (readtype == IMG_CLOSEINBETWEEN)
+ unrefPdfDocument(img_filepath(idict));
}
+//**********************************************************************
// Writes the current epf_doc.
-// Here the included PDF is copied, so most errors that can happen during PDF
-// inclusion will arise here.
+// Here the included PDF is copied, so most errors that can happen
+// during PDF inclusion will arise here.
-static void write_epdf1(image_dict * idict)
+static void write_epdf1(PDF pdf, image_dict * idict)
{
+ PdfDocument *pdf_doc;
Page *page;
- PdfObject contents, obj1, obj2;
- PdfObject metadata, pieceinfo, separationInfo;
- Object info;
- char *key;
+ PdfObject info, contents, metadata, obj1;
+ Object *metadataNF, *resourcesNF;
+ char *checksum;
char s[256];
int i, l;
- PdfDocument *pdf_doc = (PdfDocument *) findPdfDocument(img_filepath(idict));
- assert(pdf_doc != NULL);
- xref = pdf_doc->xref;
- inObjList = pdf_doc->inObjList;
- encodingList = NULL;
+ assert(idict != NULL);
+ // calculate a checksum string
+ checksum = get_file_checksum(img_filepath(idict));
+ // open PDF file
+ pdf_doc = refPdfDocument(img_filepath(idict));
+ if (strncmp(pdf_doc->checksum, checksum, PDF_CHECKSUM_SIZE) != 0) {
+ pdftex_fail("PDF inclusion: file has changed '%s'",
+ img_filename(idict));
+ }
+ free(checksum);
+ (void) pdf_doc->doc->getCatalog()->getPage(img_pagenum(idict));
page = pdf_doc->doc->getCatalog()->getPage(img_pagenum(idict));
PDFRectangle *pagebox;
float bbox[4];
// write the Page header
- pdf_puts("/Type /XObject\n/Subtype /Form\n");
+ pdf_puts(pdf, "/Type /XObject\n/Subtype /Form\n");
if (img_attr(idict) != NULL && strlen(img_attr(idict)) > 0)
- pdf_printf("%s\n", img_attr(idict));
- pdf_puts("/FormType 1\n");
+ pdf_printf(pdf, "%s\n", img_attr(idict));
+ pdf_puts(pdf, "/FormType 1\n");
// write additional information
- pdf_printf("/%s.FileName (%s)\n", pdfkeyprefix,
+ pdf_printf(pdf, "/%s.FileName (%s)\n", pdfkeyprefix,
convertStringToPDFString(pdf_doc->file_path,
strlen(pdf_doc->file_path)));
- pdf_printf("/%s.PageNumber %i\n", pdfkeyprefix, (int) img_pagenum(idict));
+ pdf_printf(pdf, "/%s.PageNumber %i\n", pdfkeyprefix,
+ (int) img_pagenum(idict));
pdf_doc->doc->getDocInfoNF(&info);
- if (info.isRef()) {
+ if (info->isRef()) {
// the info dict must be indirect (PDF Ref p. 61)
- pdf_printf("/%s.InfoDict ", pdfkeyprefix);
- pdf_printf("%d 0 R\n", addOther(info.getRef()));
+ pdf_printf(pdf, "/%s.InfoDict ", pdfkeyprefix);
+ pdf_printf(pdf, "%d 0 R\n", addInObj(pdf, pdf_doc, info->getRef()));
}
if (img_is_bbox(idict)) {
bbox[0] = int2bp(img_bbox(idict)[0]);
@@ -892,7 +634,7 @@ static void write_epdf1(image_dict * idict)
bbox[2] = int2bp(img_bbox(idict)[2]);
bbox[3] = int2bp(img_bbox(idict)[3]);
} else {
- // get the pagebox (media, crop...) to use.
+ // get the pagebox coordinates (media, crop,...) to use.
pagebox = get_pagebox(page, img_pagebox(idict));
bbox[0] = pagebox->x1;
bbox[1] = pagebox->y1;
@@ -901,77 +643,57 @@ static void write_epdf1(image_dict * idict)
}
sprintf(s, "/BBox [%.8f %.8f %.8f %.8f]\n", bbox[0], bbox[1], bbox[2],
bbox[3]);
- pdf_puts(stripzeros(s));
+ pdf_puts(pdf, stripzeros(s));
// The /Matrix calculation is replaced by transforms in out_img().
- // write the page Group if it's there
- if (epdf_lastGroupObjectNum > 0) {
- if (page->getGroup() != NULL) {
- initDictFromDict(lastGroup, page->getGroup());
- if (lastGroup->dictGetLength() > 0) {
- pdf_puts("/Group ");
- groupIsIndirect = lastGroup->isRef();
- pdf_printf("%d 0 R", (int) epdf_lastGroupObjectNum);
- pdf_puts("\n");
- }
- }
+ // Now all relevant parts of the /Page dictionary are copied:
+
+ // write the /Resources dictionary
+ if (page->getResourceDict() == NULL) {
+ // Resources can be missing (files without them have been spotted
+ // in the wild); in which case the /Resouces of the /Page will be used.
+ // "This practice is not recommended".
+ pdftex_warn
+ ("PDF inclusion: /Resources missing. 'This practice is not recommended' (PDF Ref.)");
+ } else {
+#if 0 // TEMP, waiting for XPDF patch
+ resourcesNF = page->getResourcesNF();
+ pdf_puts(pdf, "/Resources ");
+ copyObject(pdf, pdf_doc, resourcesNF);
+#endif
}
- // write the page Metadata if it's there
+ // write the page /Metadata if it's there (as a stream it must be indirect)
if (page->getMetadata() != NULL) {
- metadata->initStream(page->getMetadata());
- pdf_puts("/Metadata ");
- copyObject(&metadata);
- pdf_puts("\n");
+#if 0 // TEMP, waiting for XPDF patch
+ metadataNF = page->getMetadataNF(); // *NF = "don't resolve indirects"
+ if (!metadataNF->isRef())
+ pdftex_warn("PDF inclusion: /Metadata must be indirect object");
+ else {
+ pdf_printf(pdf, "/Metadata %d 0 R",
+ addInObj(pdf, pdf_doc, metadataNF->getRef()));
+ }
+#endif
}
- // write the page PieceInfo if it's there
+ // write the page /Group if it's there
+ if (page->getGroup() != NULL) {
+ pdf_puts(pdf, "/Group ");
+ copyDict(pdf, pdf_doc, page->getGroup());
+ }
+ // write the page /PieceInfo if it's there
if (page->getPieceInfo() != NULL) {
- initDictFromDict(pieceinfo, page->getPieceInfo());
- if (pieceinfo->dictGetLength() > 0) {
- pdf_puts("/PieceInfo ");
- copyObject(&pieceinfo);
- pdf_puts("\n");
- }
+ pdf_puts(pdf, "/PieceInfo ");
+ copyDict(pdf, pdf_doc, page->getPieceInfo());
+ }
+ // write the page /SeparationInfo if it's there
+ if (page->getSeparationInfo() != NULL) {
+ pdf_puts(pdf, "/SeparationInfo ");
+ copyDict(pdf, pdf_doc, page->getSeparationInfo());
}
// copy LastModified (needed when PieceInfo is there)
if (page->getLastModified() != NULL) {
- pdf_printf("/LastModified (%s)\n",
+ pdf_printf(pdf, "/LastModified (%s)\n",
page->getLastModified()->getCString());
}
- // write the page SeparationInfo if it's there
- if (page->getSeparationInfo() != NULL) {
- initDictFromDict(separationInfo, page->getSeparationInfo());
- if (separationInfo->dictGetLength() > 0) {
- pdf_puts("/SeparationInfo ");
- copyObject(&separationInfo);
- pdf_puts("\n");
- }
- }
- // write the Resources dictionary
- if (page->getResourceDict() == NULL) {
- // Resources can be missing (files without them have been spotted
- // in the wild); in which case the /Resouces of the /Page will be used.
- // "This practice is not recommended".
- pdftex_warn
- ("PDF inclusion: /Resources missing. 'This practice is not recommended' (PDF Ref)");
- } else {
- initDictFromDict(obj1, page->getResourceDict());
- page->getResourceDict()->incRef();
- if (!obj1->isDict())
- pdftex_fail("PDF inclusion: invalid resources dict type <%s>",
- obj1->getTypeName());
- pdf_puts("/Resources <<\n");
- for (i = 0, l = obj1->dictGetLength(); i < l; ++i) {
- obj1->dictGetVal(i, &obj2);
- key = obj1->dictGetKey(i);
- if (strcmp("Font", key) == 0)
- copyFontResources(&obj2);
- else if (strcmp("ProcSet", key) == 0)
- copyProcSet(&obj2);
- else
- copyOtherResources(&obj2, key);
- }
- pdf_puts(">>\n");
- }
// write the page contents
page->getContents(&contents);
if (contents->isStream()) {
@@ -979,84 +701,108 @@ static void write_epdf1(image_dict * idict)
// of \pdfcompresslevel
//
// pdfbeginstream();
- // copyStream(contents->getStream());
+ // copyStreamStream(contents->getStream());
// pdfendstream();
// Variant B: copy stream without recompressing
//
- contents->streamGetDict()->lookup("F", &obj1);
+ contents->streamGetDict()->lookup((char *) "F", &obj1);
if (!obj1->isNull()) {
pdftex_fail("PDF inclusion: Unsupported external stream");
}
- contents->streamGetDict()->lookup("Length", &obj1);
+ contents->streamGetDict()->lookup((char *) "Length", &obj1);
assert(!obj1->isNull());
- pdf_puts("/Length ");
- copyObject(&obj1);
- pdf_puts("\n");
- contents->streamGetDict()->lookup("Filter", &obj1);
+ pdf_puts(pdf, "/Length ");
+ copyObject(pdf, pdf_doc, &obj1);
+ pdf_puts(pdf, "\n");
+ contents->streamGetDict()->lookup((char *) "Filter", &obj1);
if (!obj1->isNull()) {
- pdf_puts("/Filter ");
- copyObject(&obj1);
- pdf_puts("\n");
- contents->streamGetDict()->lookup("DecodeParms", &obj1);
+ pdf_puts(pdf, "/Filter ");
+ copyObject(pdf, pdf_doc, &obj1);
+ pdf_puts(pdf, "\n");
+ contents->streamGetDict()->lookup((char *) "DecodeParms", &obj1);
if (!obj1->isNull()) {
- pdf_puts("/DecodeParms ");
- copyObject(&obj1);
- pdf_puts("\n");
+ pdf_puts(pdf, "/DecodeParms ");
+ copyObject(pdf, pdf_doc, &obj1);
+ pdf_puts(pdf, "\n");
}
}
- pdf_puts(">>\nstream\n");
- copyStream(contents->getStream()->getBaseStream());
- pdf_end_stream();
+ pdf_puts(pdf, ">>\nstream\n");
+ copyStreamStream(pdf, contents->getStream()->getBaseStream());
+ pdf_end_stream(pdf);
} else if (contents->isArray()) {
- pdf_begin_stream();
+ pdf_begin_stream(pdf);
for (i = 0, l = contents->arrayGetLength(); i < l; ++i) {
- Object contentsobj;
- copyStream((contents->arrayGet(i, &contentsobj))->getStream());
- contentsobj.free();
+ PdfObject contentsobj;
+ copyStreamStream(pdf,
+ (contents->arrayGet(i, &contentsobj))->
+ getStream());
+ if (i < (l - 1)) {
+ // put a space between streams to be on the safe side (streams
+ // should have a trailing space here, but one never knows)
+ pdf_puts(pdf, " ");
+ }
}
- pdf_end_stream();
+ pdf_end_stream(pdf);
} else { // the contents are optional, but we need to include an empty stream
- pdf_begin_stream();
- pdf_end_stream();
+ pdf_begin_stream(pdf);
+ pdf_end_stream(pdf);
}
// write out all indirect objects
- writeRefs();
- // write out all used encodings (and delete list)
- writeEncodings();
- // save object list
- pdf_doc->inObjList = inObjList;
- assert(xref == pdf_doc->xref); // xref should be unchanged
+ writeRefs(pdf, pdf_doc);
}
-void write_epdf(image_dict * idict)
+// this relay function is needed to keep some destructor quiet (???)
+
+void write_epdf(PDF pdf, image_dict * idict)
{
- assert(idict != NULL);
- write_epdf1(idict);
+ write_epdf1(pdf, idict);
unrefPdfDocument(img_filepath(idict));
}
//**********************************************************************
// Deallocate a PdfDocument with all its resources
-static void deletePdfDocument(PdfDocument * pdf_doc)
+static void deletePdfDocumentPdfDoc(PdfDocument * pdf_doc)
{
- assert(pdf_doc != NULL);
- // free PdfDocument's resources
InObj *r, *n;
+ assert(pdf_doc != NULL);
+ // this may be probably needed for an emergency destroyPdfDocument()
for (r = pdf_doc->inObjList; r != NULL; r = n) {
n = r->next;
delete r;
}
delete pdf_doc->doc;
- xfree(pdf_doc->file_path);
- delete pdf_doc;
+ pdf_doc->doc = NULL;
}
-static void destroyPdfDocument(void *pa, void *pb)
+static void destroyPdfDocument(void *pa, void * /*pb */ )
{
PdfDocument *pdf_doc = (PdfDocument *) pa;
- deletePdfDocument(pdf_doc);
+ deletePdfDocumentPdfDoc(pdf_doc);
+ // TODO: delete rest of pdf_doc
+}
+
+// Called when an image has been written and its resources in image_tab are
+// freed and it's not referenced anymore.
+
+void unrefPdfDocument(char *file_path)
+{
+ PdfDocument *pdf_doc = findPdfDocument(file_path);
+ assert(pdf_doc != NULL);
+ assert(pdf_doc->occurences > 0); // aim for point landing
+ pdf_doc->occurences--;
+#ifdef DEBUG
+ fprintf(stderr, "\nluatex Debug: Decrementing %s (%d)\n",
+ pdf_doc->file_path, pdf_doc->occurences);
+#endif
+ if (pdf_doc->occurences == 0) {
+#ifdef DEBUG
+ fprintf(stderr, "\nluatex Debug: Deleting %s\n", pdf_doc->file_path);
+#endif
+ assert(pdf_doc->inObjList == NULL); // should be eaten up already
+ deletePdfDocumentPdfDoc(pdf_doc);
+ }
}
// Called when PDF embedding system is finalized.
@@ -1071,14 +817,3 @@ void epdf_check_mem()
delete globalParams;
isInit = gFalse;
}
-
-// Called after the xobject generated by write_epdf has been finished; used to
-// write out objects that have been made indirect
-void write_additional_epdf_objects(void)
-{
- if ((epdf_lastGroupObjectNum > 0) && !groupIsIndirect) {
- zpdf_begin_obj(epdf_lastGroupObjectNum, 2);
- copyObject(&lastGroup);
- pdf_end_obj();
- }
-}