[poppler] poppler/PDFDoc.cc utils/pdfunite.cc

Albert Astals Cid aacid at kemper.freedesktop.org
Thu Aug 27 14:02:32 PDT 2015


 poppler/PDFDoc.cc |    1 
 utils/pdfunite.cc |  156 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 154 insertions(+), 3 deletions(-)

New commits:
commit 3e19bec738889ee9140379ac3f871552dbb9bf41
Author: Thomas Freitag <Thomas.Freitag at alfa.de>
Date:   Thu Aug 27 23:01:21 2015 +0200

    pdfunite: Insert embedded files in result pdf
    
    Bug #90066

diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc
index e99af26..46c4544 100644
--- a/poppler/PDFDoc.cc
+++ b/poppler/PDFDoc.cc
@@ -1561,7 +1561,6 @@ void PDFDoc::replacePageDict(int pageNo, int rotate,
 
 void PDFDoc::markPageObjects(Dict *pageDict, XRef *xRef, XRef *countRef, Guint numOffset, int oldRefNum, int newRefNum) 
 {
-  pageDict->remove("Names");
   pageDict->remove("OpenAction");
   pageDict->remove("Outlines");
   pageDict->remove("StructTreeRoot");
diff --git a/utils/pdfunite.cc b/utils/pdfunite.cc
index b35090c..170355d 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-2014 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2011-2015 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, 2014 Albert Astals Cid <aacid at kde.org>
@@ -37,6 +37,132 @@ static const ArgDesc argDesc[] = {
   {NULL}
 };
 
+void doMergeNameTree(PDFDoc *doc, XRef *srcXRef, XRef *countRef, int oldRefNum, int newRefNum, Dict *srcNameTree, Dict *mergeNameTree, int numOffset) {
+  Object mergeNameArray;
+  Object srcNameArray;
+  mergeNameTree->lookup("Names", &mergeNameArray);
+  srcNameTree->lookup("Names", &srcNameArray);
+  if (mergeNameArray.isArray() && srcNameArray.isArray()) {
+    Object *newNameArray = new Object();
+    newNameArray->initArray(srcXRef);
+    int j = 0;
+    for (int i = 0; i < srcNameArray.arrayGetLength() - 1; i += 2) {
+      Object key;
+      Object value;
+      srcNameArray.arrayGetNF(i, &key);
+      srcNameArray.arrayGetNF(i + 1, &value);
+      if (key.isString() && value.isRef()) {
+        while (j < mergeNameArray.arrayGetLength() - 1) {
+          Object mkey;
+          Object mvalue;
+          mergeNameArray.arrayGetNF(j, &mkey);
+          mergeNameArray.arrayGetNF(j + 1, &mvalue);
+          if (mkey.isString() && mvalue.isRef()) {
+            if (mkey.getString()->cmp(key.getString()) < 0) {
+              Object *newKey = new Object();
+	      newKey->initString(new GooString(mkey.getString()->getCString()));
+              newNameArray->arrayAdd(newKey);
+              Object *newValue = new Object();
+              newValue->initRef(mvalue.getRef().num + numOffset, mvalue.getRef().gen);
+              newNameArray->arrayAdd(newValue);
+              delete newKey;
+              delete newValue;
+              j += 2;
+            } else if (mkey.getString()->cmp(key.getString()) == 0) {
+              j += 2;
+            } else {
+              mkey.free();
+              mvalue.free();
+              break;
+            }
+          } else {
+            j += 2;
+          }
+          mkey.free();
+          mvalue.free();
+        }
+        Object *newKey = new Object();
+        newKey->initString(new GooString(key.getString()->getCString()));
+        newNameArray->arrayAdd(newKey);
+        Object *newValue = new Object();
+        newValue->initRef(value.getRef().num, value.getRef().gen);
+        newNameArray->arrayAdd(newValue);
+        delete newKey;
+        delete newValue;
+      }
+      key.free();
+      value.free();
+    }
+    while (j < mergeNameArray.arrayGetLength() - 1) {
+      Object mkey;
+      Object mvalue;
+      mergeNameArray.arrayGetNF(j, &mkey);
+      mergeNameArray.arrayGetNF(j + 1, &mvalue);
+      if (mkey.isString() && mvalue.isRef()) {
+        Object *newKey = new Object();
+        newKey->initString(new GooString(mkey.getString()->getCString()));
+        newNameArray->arrayAdd(newKey);
+        Object *newValue = new Object();
+        newValue->initRef(mvalue.getRef().num + numOffset, mvalue.getRef().gen);
+        newNameArray->arrayAdd(newValue);
+        delete newKey;
+        delete newValue;
+      }
+      j += 2;
+      mkey.free();
+      mvalue.free();
+    }
+    srcNameTree->set("Names", newNameArray);
+    doc->markPageObjects(mergeNameTree, srcXRef, countRef, numOffset, oldRefNum, newRefNum);
+    delete newNameArray;
+  } else if (srcNameArray.isNull() && mergeNameArray.isArray()) {
+    Object *newNameArray = new Object();
+    newNameArray->initArray(srcXRef);
+    for (int i = 0; i < mergeNameArray.arrayGetLength() - 1; i += 2) {
+      Object key;
+      Object value;
+      mergeNameArray.arrayGetNF(i, &key);
+      mergeNameArray.arrayGetNF(i + 1, &value);
+      if (key.isString() && value.isRef()) {
+        Object *newKey = new Object();
+	newKey->initString(new GooString(key.getString()->getCString()));
+        newNameArray->arrayAdd(newKey);
+        Object *newValue = new Object();
+        newValue->initRef(value.getRef().num + numOffset, value.getRef().gen);
+        newNameArray->arrayAdd(newValue);
+        delete newKey;
+        delete newValue;
+      }
+      key.free();
+      value.free();
+    }
+    srcNameTree->add(copyString("Names"), newNameArray);
+    doc->markPageObjects(mergeNameTree, srcXRef, countRef, numOffset, oldRefNum, newRefNum);
+  }
+  mergeNameArray.free();
+  srcNameArray.free();
+}
+
+void doMergeNameDict(PDFDoc *doc, XRef *srcXRef, XRef *countRef, int oldRefNum, int newRefNum, Dict *srcNameDict, Dict *mergeNameDict, int numOffset) {
+  for (int i = 0; i < mergeNameDict->getLength(); i++) {
+    const char *key = mergeNameDict->getKey(i);
+    Object mergeNameTree;
+    Object srcNameTree;
+    mergeNameDict->lookup(key, &mergeNameTree);
+    srcNameDict->lookup(key, &srcNameTree);
+    if (srcNameTree.isDict() && mergeNameTree.isDict()) {
+      doMergeNameTree(doc, srcXRef, countRef, oldRefNum, newRefNum, srcNameTree.getDict(), mergeNameTree.getDict(), numOffset);
+    } else if (srcNameTree.isNull() && mergeNameTree.isDict()) {
+      Object *newNameTree = new Object();
+      newNameTree->initDict(srcXRef);
+      doMergeNameTree(doc, srcXRef, countRef, oldRefNum, newRefNum, newNameTree->getDict(), mergeNameTree.getDict(), numOffset);
+      srcNameDict->add(copyString(key), newNameTree);
+    }
+    srcNameTree.free();
+    mergeNameTree.free();
+  }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 int main (int argc, char *argv[])
 ///////////////////////////////////////////////////////////////////////////
@@ -109,10 +235,11 @@ int main (int argc, char *argv[])
   yRef->add(0, 65535, 0, gFalse);
   PDFDoc::writeHeader(outStr, majorVersion, minorVersion);
 
-  // handle OutputIntents, AcroForm & OCProperties
+  // handle OutputIntents, AcroForm, OCProperties & Names
   Object intents;
   Object afObj;
   Object ocObj;
+  Object names;
   if (docs.size() >= 1) {
     Object catObj;
     docs[0]->getXRef()->getCatalog(&catObj);
@@ -127,6 +254,10 @@ int main (int argc, char *argv[])
     if (!ocObj.isNull() && ocObj.isDict()) {
       docs[0]->markPageObjects(ocObj.getDict(), yRef, countRef, 0, refPage->num, refPage->num);
     }
+    catDict->lookup("Names", &names);
+    if (!names.isNull() && names.isDict()) {
+      docs[0]->markPageObjects(names.getDict(), yRef, countRef, 0, refPage->num, refPage->num);
+    }
     if (intents.isArray() && intents.arrayGetLength() > 0) {
       for (i = 1; i < (int) docs.size(); i++) {
         Object pagecatObj, pageintents;
@@ -216,6 +347,7 @@ int main (int argc, char *argv[])
         Object *newResource = new Object();
         newResource->initDict(resDict);
         pageDict->set("Resources", newResource);
+        delete newResource;
       }
       pages.push_back(page);
       offsets.push_back(numOffset);
@@ -227,6 +359,19 @@ int main (int argc, char *argv[])
         annotsObj.free();
       }
     }
+    Object pageCatObj, pageNames;
+    docs[i]->getXRef()->getCatalog(&pageCatObj);
+    Dict *pageCatDict = pageCatObj.getDict();
+    pageCatDict->lookup("Names", &pageNames);
+    if (!pageNames.isNull() && pageNames.isDict()) {
+      if (!names.isDict()) {
+        names.free();
+        names.initDict(yRef);
+      }
+      doMergeNameDict(docs[i], yRef, countRef, 0, 0, names.getDict(), pageNames.getDict(), numOffset);
+    }
+    pageNames.free();
+    pageCatObj.free();
     objectsCount += docs[i]->writePageObjects(outStr, yRef, numOffset, gTrue);
     numOffset = yRef->getNumObjects() + 1;
   }
@@ -261,6 +406,12 @@ int main (int argc, char *argv[])
     PDFDoc::writeObject(&ocObj, outStr, yRef, 0, NULL, cryptRC4, 0, 0, 0);
     ocObj.free();
   }
+  // insert Names
+  if (!names.isNull() && names.isDict()) {
+    outStr->printf(" /Names ");
+    PDFDoc::writeObject(&names, outStr, yRef, 0, NULL, cryptRC4, 0, 0, 0);
+    names.free();
+  }
   outStr->printf(">>\nendobj\n");
   objectsCount++;
 
@@ -305,6 +456,7 @@ int main (int argc, char *argv[])
   delete trailerDict;
 
   outStr->close();
+  delete outStr;
   fclose(f);
   delete yRef;
   delete countRef;


More information about the poppler mailing list