[poppler] 2 commits - poppler/PDFDoc.cc poppler/PDFDoc.h poppler/XRef.cc poppler/XRef.h utils/pdfunite.cc
Albert Astals Cid
aacid at kemper.freedesktop.org
Thu Apr 26 16:03:56 PDT 2012
poppler/PDFDoc.cc | 96 ++++++++++++++++++++++++++++++++++++++----------------
poppler/PDFDoc.h | 14 ++++++-
poppler/XRef.cc | 76 ++++++++++++++++++++++++++++++++++++------
poppler/XRef.h | 36 +++++++++++++++++++-
utils/pdfunite.cc | 10 +++--
5 files changed, 185 insertions(+), 47 deletions(-)
New commits:
commit b1d5c6c0a20a4a24b42de66db23e0f63d10ca52d
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date: Tue Apr 24 21:00:11 2012 +0200
Output XRef stream when incrementally updating if there's already a XRef stream
diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc
index 9c977a6..2dc1ac8 100644
--- a/poppler/PDFDoc.cc
+++ b/poppler/PDFDoc.cc
@@ -864,8 +864,30 @@ void PDFDoc::saveIncrementalUpdate (OutStream* outStr)
}
Guint uxrefOffset = outStr->getPos();
- writeXRefTableTrailer(uxrefOffset, uxref, gFalse /* do not write unnecessary entries */,
- xref->getNumObjects(), outStr, gTrue /* incremental update */);
+ int numobjects = xref->getNumObjects();
+ const char *fileNameA = fileName ? fileName->getCString() : NULL;
+ Ref rootRef, uxrefStreamRef;
+ rootRef.num = getXRef()->getRootNum();
+ rootRef.gen = getXRef()->getRootGen();
+
+ // Output a xref stream if there is a xref stream already
+ GBool xRefStream = xref->isXRefStream();
+
+ if (xRefStream) {
+ // Append an entry for the xref stream itself
+ uxrefStreamRef.num = numobjects++;
+ uxrefStreamRef.gen = 0;
+ uxref->add(uxrefStreamRef.num, uxrefStreamRef.gen, uxrefOffset, gTrue);
+ }
+
+ Dict *trailerDict = createTrailerDict(numobjects, gTrue, getStartXRef(), &rootRef, getXRef(), fileNameA, uxrefOffset);
+ if (xRefStream) {
+ writeXRefStreamTrailer(trailerDict, uxref, &uxrefStreamRef, uxrefOffset, outStr, getXRef());
+ } else {
+ writeXRefTableTrailer(trailerDict, uxref, gFalse, uxrefOffset, outStr, getXRef());
+ }
+
+ delete trailerDict;
delete uxref;
}
@@ -1203,6 +1225,25 @@ void PDFDoc::writeXRefTableTrailer(Dict *trailerDict, XRef *uxref, GBool writeAl
outStr->printf( "%%%%EOF\r\n");
}
+void PDFDoc::writeXRefStreamTrailer (Dict *trailerDict, XRef *uxref, Ref *uxrefStreamRef, Guint uxrefOffset, OutStream* outStr, XRef *xRef)
+{
+ GooString stmData;
+
+ // Fill stmData and some trailerDict fields
+ uxref->writeStreamToBuffer(&stmData, trailerDict, xRef);
+
+ // Create XRef stream object and write it
+ Object obj1;
+ MemStream *mStream = new MemStream( stmData.getCString(), 0,
+ stmData.getLength(), obj1.initDict(trailerDict) );
+ writeObject(obj1.initStream(mStream), uxrefStreamRef, outStr, xRef, 0);
+ obj1.free();
+
+ outStr->printf( "startxref\r\n");
+ outStr->printf( "%i\r\n", uxrefOffset);
+ outStr->printf( "%%%%EOF\r\n");
+}
+
void PDFDoc::writeXRefTableTrailer(Guint uxrefOffset, XRef *uxref, GBool writeAllEntries,
int uxrefSize, OutStream* outStr, GBool incrUpdate)
{
diff --git a/poppler/XRef.cc b/poppler/XRef.cc
index 3b0d7f8..1574371 100644
--- a/poppler/XRef.cc
+++ b/poppler/XRef.cc
@@ -1240,10 +1240,10 @@ void XRef::removeIndirectObject(Ref r) {
e->updated = true;
}
-void XRef::writeTableToFile(OutStream* outStr, GBool writeAllEntries) {
+void XRef::writeXRef(XRef::XRefWriter *writer, GBool writeAllEntries) {
//create free entries linked-list
if (getEntry(0)->gen != 65535) {
- error(errInternal, -1, "XRef::writeToFile, entry 0 of the XRef is invalid (gen != 65535)\n");
+ error(errInternal, -1, "XRef::writeXRef, entry 0 of the XRef is invalid (gen != 65535)\n");
}
int lastFreeEntry = 0;
for (int i=0; i<size; i++) {
@@ -1254,18 +1254,13 @@ void XRef::writeTableToFile(OutStream* outStr, GBool writeAllEntries) {
}
if (writeAllEntries) {
- //write the new xref
- outStr->printf("xref\r\n");
- outStr->printf("%i %i\r\n", 0, size);
+ writer->startSection(0, size);
for (int i=0; i<size; i++) {
XRefEntry *e = getEntry(i);
-
if(e->gen > 65535) e->gen = 65535; //cap generation number to 65535 (required by PDFReference)
- outStr->printf("%010i %05i %c\r\n", e->offset, e->gen, (e->type==xrefEntryFree)?'f':'n');
+ writer->writeEntry(e->offset, e->gen, e->type);
}
} else {
- //write the new xref
- outStr->printf("xref\r\n");
int i = 0;
while (i < size) {
int j;
@@ -1275,11 +1270,11 @@ void XRef::writeTableToFile(OutStream* outStr, GBool writeAllEntries) {
}
if (j-i != 0)
{
- outStr->printf("%i %i\r\n", i, j-i);
+ writer->startSection(i, j-i);
for (int k=i; k<j; k++) {
XRefEntry *e = getEntry(k);
if(e->gen > 65535) e->gen = 65535; //cap generation number to 65535 (required by PDFReference)
- outStr->printf("%010i %05i %c\r\n", e->offset, e->gen, (e->type==xrefEntryFree)?'f':'n');
+ writer->writeEntry(e->offset, e->gen, e->type);
}
i = j;
}
@@ -1288,6 +1283,65 @@ void XRef::writeTableToFile(OutStream* outStr, GBool writeAllEntries) {
}
}
+XRef::XRefTableWriter::XRefTableWriter(OutStream* outStrA) {
+ outStr = outStrA;
+}
+
+void XRef::XRefTableWriter::startSection(int first, int count) {
+ outStr->printf("%i %i\r\n", first, count);
+}
+
+void XRef::XRefTableWriter::writeEntry(Guint offset, int gen, XRefEntryType type) {
+ outStr->printf("%010i %05i %c\r\n", offset, gen, (type==xrefEntryFree)?'f':'n');
+}
+
+void XRef::writeTableToFile(OutStream* outStr, GBool writeAllEntries) {
+ XRefTableWriter writer(outStr);
+ outStr->printf("xref\r\n");
+ writeXRef(&writer, writeAllEntries);
+}
+
+XRef::XRefStreamWriter::XRefStreamWriter(Object *indexA, GooString *stmBufA) {
+ index = indexA;
+ stmBuf = stmBufA;
+}
+
+void XRef::XRefStreamWriter::startSection(int first, int count) {
+ Object obj;
+ index->arrayAdd( obj.initInt(first) );
+ index->arrayAdd( obj.initInt(count) );
+}
+
+void XRef::XRefStreamWriter::writeEntry(Guint offset, int gen, XRefEntryType type) {
+ char data[7];
+ data[0] = (type==xrefEntryFree) ? 0 : 1;
+ data[1] = (offset >> 24) & 0xff;
+ data[2] = (offset >> 16) & 0xff;
+ data[3] = (offset >> 8) & 0xff;
+ data[4] = offset & 0xff;
+ data[5] = (gen >> 8) & 0xff;
+ data[6] = gen & 0xff;
+ stmBuf->append(data, 7);
+}
+
+void XRef::writeStreamToBuffer(GooString *stmBuf, Dict *xrefDict, XRef *xref) {
+ Object index;
+ index.initArray(xref);
+ stmBuf->clear();
+
+ XRefStreamWriter writer(&index, stmBuf);
+ writeXRef(&writer, gFalse);
+
+ Object obj1, obj2;
+ xrefDict->set("Type", obj1.initName("XRef"));
+ xrefDict->set("Index", &index);
+ obj2.initArray(xref);
+ obj2.arrayAdd( obj1.initInt(1) );
+ obj2.arrayAdd( obj1.initInt(4) );
+ obj2.arrayAdd( obj1.initInt(2) );
+ xrefDict->set("W", &obj2);
+}
+
GBool XRef::parseEntry(Guint offset, XRefEntry *entry)
{
GBool r;
diff --git a/poppler/XRef.h b/poppler/XRef.h
index ab8047c..148a5ce 100644
--- a/poppler/XRef.h
+++ b/poppler/XRef.h
@@ -79,6 +79,9 @@ public:
// Is xref table valid?
GBool isOk() { return ok; }
+ // Is the last XRef section a stream or a table?
+ GBool isXRefStream() { return xRefStream; }
+
// Get the error code (if isOk() returns false).
int getErrorCode() { return errCode; }
@@ -135,7 +138,11 @@ public:
Ref addIndirectObject (Object* o);
void removeIndirectObject(Ref r);
void add(int num, int gen, Guint offs, GBool used);
+
+ // Output XRef table to stream
void writeTableToFile(OutStream* outStr, GBool writeAllEntries);
+ // Output XRef stream contents to GooString and fill trailerDict fields accordingly
+ void writeStreamToBuffer(GooString *stmBuf, Dict *xrefDict, XRef *xref);
private:
@@ -176,6 +183,33 @@ private:
GBool constructXRef(GBool *wasReconstructed);
GBool parseEntry(Guint offset, XRefEntry *entry);
+ class XRefWriter {
+ public:
+ virtual void startSection(int first, int count) = 0;
+ virtual void writeEntry(Guint offset, int gen, XRefEntryType type) = 0;
+ virtual ~XRefWriter() {};
+ };
+
+ class XRefTableWriter: public XRefWriter {
+ public:
+ XRefTableWriter(OutStream* outStrA);
+ void startSection(int first, int count);
+ void writeEntry(Guint offset, int gen, XRefEntryType type);
+ private:
+ OutStream* outStr;
+ };
+
+ class XRefStreamWriter: public XRefWriter {
+ public:
+ XRefStreamWriter(Object *index, GooString *stmBuf);
+ void startSection(int first, int count);
+ void writeEntry(Guint offset, int gen, XRefEntryType type);
+ private:
+ Object *index;
+ GooString *stmBuf;
+ };
+
+ void writeXRef(XRefWriter *writer, GBool writeAllEntries);
};
#endif
commit 2ecf3b2e49a4c35e995d25016b810592260edfeb
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date: Tue Apr 24 18:10:15 2012 +0200
Refactoring of XRef table write support (in preparation for XRef stream write support)
- Trailer dictionary creation now lives in its own function "createTrailerDict"
(that will be used by XRef stream creation too)
- writeXRefTableTrailer (WAS writeTrailer) now takes care of writing the XRef
table too (previously it was demanded to the caller)
diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc
index 898bcbb..9c977a6 100644
--- a/poppler/PDFDoc.cc
+++ b/poppler/PDFDoc.cc
@@ -716,12 +716,14 @@ int PDFDoc::savePageAs(GooString *name, int pageNo)
page.free();
Guint uxrefOffset = outStr->getPos();
- yRef->writeToFile(outStr, gFalse /* do not write unnecessary entries */);
-
Ref ref;
ref.num = rootNum;
ref.gen = 0;
- writeTrailer(uxrefOffset, objectsCount, outStr, gFalse, 0, &ref, getXRef(), name->getCString(), outStr->getPos());
+ Dict *trailerDict = createTrailerDict(objectsCount, gFalse, 0, &ref, getXRef(),
+ name->getCString(), uxrefOffset);
+ writeXRefTableTrailer(trailerDict, yRef, gFalse /* do not write unnecessary entries */,
+ uxrefOffset, outStr, getXRef());
+ delete trailerDict;
outStr->close();
fclose(f);
@@ -862,10 +864,8 @@ void PDFDoc::saveIncrementalUpdate (OutStream* outStr)
}
Guint uxrefOffset = outStr->getPos();
- uxref->writeToFile(outStr, gFalse /* do not write unnecessary entries */);
-
- writeTrailer(uxrefOffset, xref->getNumObjects(), outStr, gTrue);
-
+ writeXRefTableTrailer(uxrefOffset, uxref, gFalse /* do not write unnecessary entries */,
+ xref->getNumObjects(), outStr, gTrue /* incremental update */);
delete uxref;
}
@@ -902,13 +902,9 @@ void PDFDoc::saveCompleteRewrite (OutStream* outStr)
}
}
Guint uxrefOffset = outStr->getPos();
- uxref->writeToFile(outStr, gTrue /* write all entries */);
-
- writeTrailer(uxrefOffset, uxref->getNumObjects(), outStr, gFalse);
-
-
+ writeXRefTableTrailer(uxrefOffset, uxref, gTrue /* write all entries */,
+ uxref->getNumObjects(), outStr, gFalse /* complete rewrite */);
delete uxref;
-
}
void PDFDoc::writeDictionnary (Dict* dict, OutStream* outStr, XRef *xRef, Guint numOffset)
@@ -1109,10 +1105,8 @@ Guint PDFDoc::writeObject (Object* obj, Ref* ref, OutStream* outStr, XRef *xRef,
return offset;
}
-void PDFDoc::writeTrailer(Guint uxrefOffset, int uxrefSize,
- OutStream* outStr, GBool incrUpdate,
- Guint startxRef, Ref *root, XRef *xRef, const char *fileName,
- Guint fileSize)
+Dict *PDFDoc::createTrailerDict(int uxrefSize, GBool incrUpdate, Guint startxRef,
+ Ref *root, XRef *xRef, const char *fileName, Guint fileSize)
{
Dict *trailerDict = new Dict(xRef);
Object obj1;
@@ -1120,7 +1114,6 @@ void PDFDoc::writeTrailer(Guint uxrefOffset, int uxrefSize,
trailerDict->set("Size", &obj1);
obj1.free();
-
//build a new ID, as recommended in the reference, uses:
// - current time
// - file name
@@ -1130,7 +1123,9 @@ void PDFDoc::writeTrailer(Guint uxrefOffset, int uxrefSize,
char buffer[256];
sprintf(buffer, "%i", (int)time(NULL));
message.append(buffer);
- message.append(fileName);
+
+ if (fileName)
+ message.append(fileName);
sprintf(buffer, "%i", fileSize);
message.append(buffer);
@@ -1162,7 +1157,7 @@ void PDFDoc::writeTrailer(Guint uxrefOffset, int uxrefSize,
//only update the second part of the array
xRef->getTrailerDict()->getDict()->lookup("ID", &obj4);
if (!obj4.isArray()) {
- error(errSyntaxWarning, -1, "PDFDoc::writeTrailer original file's ID entry isn't an array. Trying to continue");
+ error(errSyntaxWarning, -1, "PDFDoc::createTrailerDict original file's ID entry isn't an array. Trying to continue");
} else {
//Get the first part of the ID
obj4.arrayGet(0,&obj3);
@@ -1194,24 +1189,25 @@ void PDFDoc::writeTrailer(Guint uxrefOffset, int uxrefSize,
trailerDict->set("Info", &obj5);
}
}
-
+
+ return trailerDict;
+}
+
+void PDFDoc::writeXRefTableTrailer(Dict *trailerDict, XRef *uxref, GBool writeAllEntries, Guint uxrefOffset, OutStream* outStr, XRef *xRef)
+{
+ uxref->writeTableToFile( outStr, writeAllEntries );
outStr->printf( "trailer\r\n");
writeDictionnary(trailerDict, outStr, xRef, 0);
outStr->printf( "\r\nstartxref\r\n");
outStr->printf( "%i\r\n", uxrefOffset);
outStr->printf( "%%%%EOF\r\n");
-
- delete trailerDict;
}
-void PDFDoc::writeTrailer(Guint uxrefOffset, int uxrefSize, OutStream* outStr, GBool incrUpdate)
+void PDFDoc::writeXRefTableTrailer(Guint uxrefOffset, XRef *uxref, GBool writeAllEntries,
+ int uxrefSize, OutStream* outStr, GBool incrUpdate)
{
- const char *fileNameA;
- if (fileName)
- fileNameA = fileName->getCString();
- else
- fileNameA = "streamwithoutfilename.pdf";
- // file size
+ const char *fileNameA = fileName ? fileName->getCString() : NULL;
+ // file size (doesn't include the trailer)
unsigned int fileSize = 0;
int c;
str->reset();
@@ -1222,7 +1218,10 @@ void PDFDoc::writeTrailer(Guint uxrefOffset, int uxrefSize, OutStream* outStr, G
Ref ref;
ref.num = getXRef()->getRootNum();
ref.gen = getXRef()->getRootGen();
- writeTrailer(uxrefOffset, uxrefSize, outStr, incrUpdate, getStartXRef(), &ref, getXRef(), fileNameA, fileSize);
+ Dict * trailerDict = createTrailerDict(uxrefSize, incrUpdate, getStartXRef(), &ref,
+ getXRef(), fileNameA, fileSize);
+ writeXRefTableTrailer(trailerDict, uxref, writeAllEntries, uxrefOffset, outStr, getXRef());
+ delete trailerDict;
}
void PDFDoc::writeHeader(OutStream *outStr, int major, int minor)
diff --git a/poppler/PDFDoc.h b/poppler/PDFDoc.h
index ccb1b22..468f698 100644
--- a/poppler/PDFDoc.h
+++ b/poppler/PDFDoc.h
@@ -23,6 +23,7 @@
// Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
// Copyright (C) 2010 Srinivas Adicherla <srinivas.adicherla at geodesic.com>
// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -244,8 +245,14 @@ public:
Guint writePageObjects(OutStream *outStr, XRef *xRef, Guint numOffset);
static Guint writeObject (Object *obj, Ref *ref, OutStream* outStr, XRef *xref, Guint numOffset);
static void writeHeader(OutStream *outStr, int major, int minor);
- static void writeTrailer (Guint uxrefOffset, int uxrefSize, OutStream* outStr, GBool incrUpdate,
- Guint startxRef, Ref *root, XRef *xRef, const char *fileName, Guint fileSize);
+
+ // Ownership goes to the caller
+ static Dict *createTrailerDict (int uxrefSize, GBool incrUpdate, Guint startxRef,
+ Ref *root, XRef *xRef, const char *fileName, Guint fileSize);
+ static void writeXRefTableTrailer (Dict *trailerDict, XRef *uxref, GBool writeAllEntries,
+ Guint uxrefOffset, OutStream* outStr, XRef *xRef);
+ static void writeXRefStreamTrailer (Dict *trailerDict, XRef *uxref, Ref *uxrefStreamRef,
+ Guint uxrefOffset, OutStream* outStr, XRef *xRef);
private:
// insert referenced objects in XRef
@@ -260,7 +267,8 @@ private:
{ writeDictionnary(dict, outStr, getXRef(), 0); }
static void writeStream (Stream* str, OutStream* outStr);
static void writeRawStream (Stream* str, OutStream* outStr);
- void writeTrailer (Guint uxrefOffset, int uxrefSize, OutStream* outStr, GBool incrUpdate);
+ void writeXRefTableTrailer (Guint uxrefOffset, XRef *uxref, GBool writeAllEntries,
+ int uxrefSize, OutStream* outStr, GBool incrUpdate);
static void writeString (GooString* s, OutStream* outStr);
void saveIncrementalUpdate (OutStream* outStr);
void saveCompleteRewrite (OutStream* outStr);
diff --git a/poppler/XRef.cc b/poppler/XRef.cc
index dfc6d73..3b0d7f8 100644
--- a/poppler/XRef.cc
+++ b/poppler/XRef.cc
@@ -1240,7 +1240,7 @@ void XRef::removeIndirectObject(Ref r) {
e->updated = true;
}
-void XRef::writeToFile(OutStream* outStr, GBool writeAllEntries) {
+void XRef::writeTableToFile(OutStream* outStr, GBool writeAllEntries) {
//create free entries linked-list
if (getEntry(0)->gen != 65535) {
error(errInternal, -1, "XRef::writeToFile, entry 0 of the XRef is invalid (gen != 65535)\n");
diff --git a/poppler/XRef.h b/poppler/XRef.h
index 4cba474..ab8047c 100644
--- a/poppler/XRef.h
+++ b/poppler/XRef.h
@@ -135,7 +135,7 @@ public:
Ref addIndirectObject (Object* o);
void removeIndirectObject(Ref r);
void add(int num, int gen, Guint offs, GBool used);
- void writeToFile(OutStream* outStr, GBool writeAllEntries);
+ void writeTableToFile(OutStream* outStr, GBool writeAllEntries);
private:
diff --git a/utils/pdfunite.cc b/utils/pdfunite.cc
index 93850a4..212f89b 100644
--- a/utils/pdfunite.cc
+++ b/utils/pdfunite.cc
@@ -6,6 +6,7 @@
//
// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2012 Arseny Solokha <asolokha at gmx.com>
+// Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
//
//========================================================================
#include <PDFDoc.h>
@@ -161,13 +162,14 @@ int main (int argc, char *argv[])
objectsCount++;
}
Guint uxrefOffset = outStr->getPos();
- yRef->writeToFile(outStr, gFalse /* do not write unnecessary entries */ );
-
Ref ref;
ref.num = rootNum;
ref.gen = 0;
- PDFDoc::writeTrailer(uxrefOffset, objectsCount, outStr, (GBool) gFalse, 0,
- &ref, yRef, fileName, outStr->getPos());
+ Dict *trailerDict = PDFDoc::createTrailerDict(objectsCount, gFalse, 0, &ref, yRef,
+ fileName, outStr->getPos());
+ PDFDoc::writeXRefTableTrailer(trailerDict, yRef, gFalse /* do not write unnecessary entries */,
+ uxrefOffset, outStr, yRef);
+ delete trailerDict;
outStr->close();
fclose(f);
More information about the poppler
mailing list