summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--poppler/PDFDoc.cc153
-rw-r--r--poppler/PDFDoc.h4
-rw-r--r--utils/pdfunite.cc9
3 files changed, 162 insertions, 4 deletions
diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc
index 4f3ab311..e427d2b4 100644
--- a/poppler/PDFDoc.cc
+++ b/poppler/PDFDoc.cc
@@ -26,7 +26,7 @@
// Copyright (C) 2010 Ilya Gorenbein <igorenbein@finjan.com>
// Copyright (C) 2010 Srinivas Adicherla <srinivas.adicherla@geodesic.com>
// Copyright (C) 2010 Philip Lorenz <lorenzph+freedesktop@gmail.com>
-// Copyright (C) 2011-2013 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2011-2014 Thomas Freitag <Thomas.Freitag@alfa.de>
// Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso@hotmail.it>
// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
@@ -686,10 +686,15 @@ int PDFDoc::savePageAs(GooString *name, int pageNo)
infoObj.free();
// get and mark output intents etc.
- Object catObj, pagesObj, resourcesObj;
+ Object catObj, pagesObj, resourcesObj, annotsObj, afObj;
getXRef()->getCatalog(&catObj);
Dict *catDict = catObj.getDict();
catDict->lookup("Pages", &pagesObj);
+ catDict->lookupNF("AcroForm", &afObj);
+ if (!afObj.isNull()) {
+ markAcroForm(&afObj, yRef, countRef, 0, refPage->num, rootNum + 2);
+ afObj.free();
+ }
Dict *pagesDict = pagesObj.getDict();
pagesDict->lookup("Resources", &resourcesObj);
if (resourcesObj.isDict())
@@ -698,6 +703,11 @@ int PDFDoc::savePageAs(GooString *name, int pageNo)
Dict *pageDict = page.getDict();
markPageObjects(pageDict, yRef, countRef, 0);
+ pageDict->lookupNF("Annots", &annotsObj);
+ if (!annotsObj.isNull()) {
+ markAnnotations(&annotsObj, yRef, countRef, 0, refPage->num, rootNum + 2);
+ annotsObj.free();
+ }
yRef->markUnencrypted();
Guint objectsCount = writePageObjects(outStr, yRef, 0);
@@ -1569,6 +1579,9 @@ void PDFDoc::markPageObjects(Dict *pageDict, XRef *xRef, XRef *countRef, Guint n
Object value; pageDict->getValNF(n, &value);
if (strcmp(key, "Parent") != 0 &&
strcmp(key, "Pages") != 0 &&
+ strcmp(key, "AcroForm") != 0 &&
+ strcmp(key, "Annots") != 0 &&
+ strcmp(key, "P") != 0 &&
strcmp(key, "Root") != 0) {
markObject(&value, xRef, countRef, numOffset);
}
@@ -1576,6 +1589,142 @@ void PDFDoc::markPageObjects(Dict *pageDict, XRef *xRef, XRef *countRef, Guint n
}
}
+GBool PDFDoc::markAnnotations(Object *annotsObj, XRef *xRef, XRef *countRef, Guint numOffset, Guint oldPageNum, Guint newPageNum) {
+ Object annots;
+ GBool modified = gFalse;
+ annotsObj->fetch(getXRef(), &annots);
+ if (annots.isArray()) {
+ Array *array = annots.getArray();
+ for (int i=array->getLength() - 1; i >= 0; i--) {
+ Object obj1;
+ if (array->get(i, &obj1)->isDict()) {
+ Object type;
+ Dict *dict = obj1.getDict();
+ dict->lookup("Type", &type);
+ if (type.isName() && strcmp(type.getName(), "Annot") == 0) {
+ Object obj2;
+ if (dict->lookupNF("P", &obj2)->isRef()) {
+ if (obj2.getRef().num == oldPageNum) {
+ Object obj3;
+ array->getNF(i, &obj3);
+ if (obj3.isRef()) {
+ Object *newRef = new Object();
+ newRef->initRef(newPageNum, 0);
+ dict->set("P", newRef);
+ getXRef()->setModifiedObject(&obj1, obj3.getRef());
+ }
+ obj3.free();
+ } else if (obj2.getRef().num == newPageNum) {
+ obj1.free();
+ obj2.free();
+ type.free();
+ continue;
+ } else {
+ array->remove(i);
+ obj1.free();
+ obj2.free();
+ type.free();
+ modified = gTrue;
+ continue;
+ }
+ }
+ obj2.free();
+ }
+ type.free();
+ markPageObjects(dict, xRef, countRef, numOffset);
+ }
+ obj1.free();
+ array->getNF(i, &obj1);
+ if (obj1.isRef()) {
+ if (obj1.getRef().num + (int) numOffset >= xRef->getNumObjects() || xRef->getEntry(obj1.getRef().num + numOffset)->type == xrefEntryFree) {
+ if (getXRef()->getEntry(obj1.getRef().num)->type == xrefEntryFree) {
+ continue; // already marked as free => should be replaced
+ }
+ xRef->add(obj1.getRef().num + numOffset, obj1.getRef().gen, 0, gTrue);
+ if (getXRef()->getEntry(obj1.getRef().num)->type == xrefEntryCompressed) {
+ xRef->getEntry(obj1.getRef().num + numOffset)->type = xrefEntryCompressed;
+ }
+ }
+ if (obj1.getRef().num + (int) numOffset >= countRef->getNumObjects() ||
+ countRef->getEntry(obj1.getRef().num + numOffset)->type == xrefEntryFree)
+ {
+ countRef->add(obj1.getRef().num + numOffset, 1, 0, gTrue);
+ } else {
+ XRefEntry *entry = countRef->getEntry(obj1.getRef().num + numOffset);
+ entry->gen++;
+ }
+ }
+ obj1.free();
+ }
+ }
+ if (annotsObj->isRef()) {
+ if (annotsObj->getRef().num + (int) numOffset >= xRef->getNumObjects() || xRef->getEntry(annotsObj->getRef().num + numOffset)->type == xrefEntryFree) {
+ if (getXRef()->getEntry(annotsObj->getRef().num)->type == xrefEntryFree) {
+ return modified; // already marked as free => should be replaced
+ }
+ xRef->add(annotsObj->getRef().num + numOffset, annotsObj->getRef().gen, 0, gTrue);
+ if (getXRef()->getEntry(annotsObj->getRef().num)->type == xrefEntryCompressed) {
+ xRef->getEntry(annotsObj->getRef().num + numOffset)->type = xrefEntryCompressed;
+ }
+ }
+ if (annotsObj->getRef().num + (int) numOffset >= countRef->getNumObjects() ||
+ countRef->getEntry(annotsObj->getRef().num + numOffset)->type == xrefEntryFree)
+ {
+ countRef->add(annotsObj->getRef().num + numOffset, 1, 0, gTrue);
+ } else {
+ XRefEntry *entry = countRef->getEntry(annotsObj->getRef().num + numOffset);
+ entry->gen++;
+ }
+ getXRef()->setModifiedObject(&annots, annotsObj->getRef());
+ }
+ annots.free();
+ return modified;
+}
+
+void PDFDoc::markAcroForm(Object *afObj, XRef *xRef, XRef *countRef, Guint numOffset, Guint oldPageNum, Guint newPageNum) {
+ Object acroform;
+ GBool modified = gFalse;
+ afObj->fetch(getXRef(), &acroform);
+ if (acroform.isDict()) {
+ Dict *dict = acroform.getDict();
+ for (int i=0; i < dict->getLength(); i++) {
+ if (strcmp(dict->getKey(i), "Fields") == 0) {
+ Object fields;
+ modified = markAnnotations(dict->getValNF(i, &fields), xRef, countRef, numOffset, oldPageNum, newPageNum);
+ fields.free();
+ } else {
+ Object obj;
+ markObject(dict->getValNF(i, &obj), xRef, countRef, numOffset);
+ obj.free();
+ }
+ }
+ }
+ if (afObj->isRef()) {
+ if (afObj->getRef().num + (int) numOffset >= xRef->getNumObjects() || xRef->getEntry(afObj->getRef().num + numOffset)->type == xrefEntryFree) {
+ if (getXRef()->getEntry(afObj->getRef().num)->type == xrefEntryFree) {
+ return; // already marked as free => should be replaced
+ }
+ xRef->add(afObj->getRef().num + numOffset, afObj->getRef().gen, 0, gTrue);
+ if (getXRef()->getEntry(afObj->getRef().num)->type == xrefEntryCompressed) {
+ xRef->getEntry(afObj->getRef().num + numOffset)->type = xrefEntryCompressed;
+ }
+ }
+ if (afObj->getRef().num + (int) numOffset >= countRef->getNumObjects() ||
+ countRef->getEntry(afObj->getRef().num + numOffset)->type == xrefEntryFree)
+ {
+ countRef->add(afObj->getRef().num + numOffset, 1, 0, gTrue);
+ } else {
+ XRefEntry *entry = countRef->getEntry(afObj->getRef().num + numOffset);
+ entry->gen++;
+ }
+ if (modified){
+ getXRef()->setModifiedObject(&acroform, afObj->getRef());
+ }
+ }
+ acroform.free();
+ return;
+}
+
Guint PDFDoc::writePageObjects(OutStream *outStr, XRef *xRef, Guint numOffset, GBool combine)
{
Guint objectsCount = 0; //count the number of objects in the XRef(s)
diff --git a/poppler/PDFDoc.h b/poppler/PDFDoc.h
index 1e5b8088..d8064e9d 100644
--- a/poppler/PDFDoc.h
+++ b/poppler/PDFDoc.h
@@ -22,7 +22,7 @@
// Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
// Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
// Copyright (C) 2010 Srinivas Adicherla <srinivas.adicherla@geodesic.com>
-// Copyright (C) 2011, 2013 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2011, 2013, 2014 Thomas Freitag <Thomas.Freitag@alfa.de>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
// Copyright (C) 2013 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2013 Adam Reichold <adamreichold@myopera.com>
@@ -249,6 +249,8 @@ public:
// rewrite pageDict with MediaBox, CropBox and new page CTM
void replacePageDict(int pageNo, int rotate, PDFRectangle *mediaBox, PDFRectangle *cropBox, Object *pageCTM);
void markPageObjects(Dict *pageDict, XRef *xRef, XRef *countRef, Guint numOffset);
+ GBool markAnnotations(Object *annots, XRef *xRef, XRef *countRef, Guint numOffset, Guint oldPageNum, Guint newPageNum);
+ void markAcroForm(Object *acrpForm, XRef *xRef, XRef *countRef, Guint numOffset, Guint oldPageNum, Guint newPageNum);
// write all objects used by pageDict to outStr
Guint writePageObjects(OutStream *outStr, XRef *xRef, Guint numOffset, GBool combine = gFalse);
static void writeObject (Object *obj, OutStream* outStr, XRef *xref, Guint numOffset, Guchar *fileKey,
diff --git a/utils/pdfunite.cc b/utils/pdfunite.cc
index 5f67c0ef..b53e4977 100644
--- a/utils/pdfunite.cc
+++ b/utils/pdfunite.cc
@@ -4,7 +4,7 @@
//
// This file is licensed under the GPLv2 or later
//
-// Copyright (C) 2011-2013 Thomas Freitag <Thomas.Freitag@alfa.de>
+// Copyright (C) 2011-2014 Thomas Freitag <Thomas.Freitag@alfa.de>
// Copyright (C) 2012 Arseny Solokha <asolokha@gmx.com>
// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
// Copyright (C) 2012 Albert Astals Cid <aacid@kde.org>
@@ -12,6 +12,7 @@
// Copyright (C) 2013 Hib Eris <hib@hiberis.nl>
//
//========================================================================
+
#include <PDFDoc.h>
#include <GlobalParams.h>
#include "parseargs.h"
@@ -129,6 +130,12 @@ int main (int argc, char *argv[])
pages.push_back(page);
offsets.push_back(numOffset);
docs[i]->markPageObjects(pageDict, yRef, countRef, numOffset);
+ Object annotsObj;
+ pageDict->lookupNF("Annots", &annotsObj);
+ if (!annotsObj.isNull()) {
+ docs[i]->markAnnotations(&annotsObj, yRef, countRef, numOffset, refPage->num, refPage->num);
+ annotsObj.free();
+ }
}
objectsCount += docs[i]->writePageObjects(outStr, yRef, numOffset, gTrue);
numOffset = yRef->getNumObjects() + 1;