[poppler] Branch 'poppler-0.26' - poppler/PDFDoc.cc poppler/PDFDoc.h utils/pdfunite.cc

Albert Astals Cid aacid at kemper.freedesktop.org
Wed May 7 12:55:33 PDT 2014


 poppler/PDFDoc.cc |  153 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 poppler/PDFDoc.h  |    4 +
 utils/pdfunite.cc |    9 ++-
 3 files changed, 162 insertions(+), 4 deletions(-)

New commits:
commit 0a6c1ff777aa23c7a5654b313b639e66600883b9
Author: Thomas Freitag <Thomas.Freitag at alfa.de>
Date:   Wed May 7 21:54:46 2014 +0200

    Only add annotations of the current page when splitting
    
    Bug #77549

diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc
index 4f3ab31..e427d2b 100644
--- a/poppler/PDFDoc.cc
+++ b/poppler/PDFDoc.cc
@@ -26,7 +26,7 @@
 // Copyright (C) 2010 Ilya Gorenbein <igorenbein at finjan.com>
 // Copyright (C) 2010 Srinivas Adicherla <srinivas.adicherla at geodesic.com>
 // Copyright (C) 2010 Philip Lorenz <lorenzph+freedesktop at gmail.com>
-// Copyright (C) 2011-2013 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2011-2014 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2012, 2013 Fabio D'Urso <fabiodurso at hotmail.it>
 // Copyright (C) 2013 Adrian Johnson <ajohnson at redneon.com>
 // Copyright (C) 2013 Adam Reichold <adamreichold at 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 1e5b808..d8064e9 100644
--- a/poppler/PDFDoc.h
+++ b/poppler/PDFDoc.h
@@ -22,7 +22,7 @@
 // Copyright (C) 2009 Kovid Goyal <kovid at kovidgoyal.net>
 // Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
 // Copyright (C) 2010 Srinivas Adicherla <srinivas.adicherla at geodesic.com>
-// Copyright (C) 2011, 2013 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2011, 2013, 2014 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2012 Fabio D'Urso <fabiodurso at hotmail.it>
 // Copyright (C) 2013 Adrian Johnson <ajohnson at redneon.com>
 // Copyright (C) 2013 Adam Reichold <adamreichold at 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 5f67c0e..b53e497 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 at alfa.de>
+// Copyright (C) 2011-2014 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>
 // Copyright (C) 2012 Albert Astals Cid <aacid at kde.org>
@@ -12,6 +12,7 @@
 // Copyright (C) 2013 Hib Eris <hib at 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;


More information about the poppler mailing list