[poppler] 3 commits - poppler/Annot.cc poppler/Annot.h

Albert Astals Cid aacid at kemper.freedesktop.org
Mon Apr 23 13:08:26 PDT 2012


 poppler/Annot.cc |  104 +++++++++++++++++++++++++++++++++++++++++++++++--------
 poppler/Annot.h  |    6 +++
 2 files changed, 95 insertions(+), 15 deletions(-)

New commits:
commit 26fd142a3608283fd41e07b54067a51a9db76e93
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Sat Apr 21 18:16:46 2012 +0200

    Preserve z-index after annotation removal

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index b3bc97d..24ef57d 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -6446,7 +6446,7 @@ void Annots::appendAnnot(Annot *annot) {
 
 GBool Annots::removeAnnot(Annot *annot) {
   int idx = -1;
-  // Search annot and remove it by swapping with last element
+  // Search annot and determine its index
   for (int i = 0; idx == -1 && i < nAnnots; i++) {
     if (annots[i] == annot) {
       idx = i;
@@ -6455,7 +6455,8 @@ GBool Annots::removeAnnot(Annot *annot) {
   if (idx == -1) {
     return gFalse;
   } else {
-    annots[idx] = annots[--nAnnots];
+    --nAnnots;
+    memmove( annots + idx, annots + idx + 1, sizeof(annots[0]) * (nAnnots - idx) );
     annot->decRefCnt();
     return gTrue;
   }
commit 7b10014c1fe9ef1cba57fd6b01c63129ac31386a
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Sat Apr 21 17:53:22 2012 +0200

    Do not remove appearance stream if it's shared with other annotations

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 06d08d5..b3bc97d 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -774,6 +774,7 @@ AnnotIconFit::AnnotIconFit(Dict* dict) {
 
 AnnotAppearance::AnnotAppearance(PDFDoc *docA, Object *dict) {
   assert(dict->isDict());
+  doc = docA;
   xref = docA->getXRef();
   dict->copy(&appearDict);
 }
@@ -841,19 +842,88 @@ int AnnotAppearance::getNumStates() {
   return res;
 }
 
+// Test if stateObj (a Ref or a Dict) points to the specified stream
+GBool AnnotAppearance::referencesStream(Object *stateObj, Ref refToStream) {
+  if (stateObj->isRef()) {
+    Ref r = stateObj->getRef();
+    if (r.num == refToStream.num && r.gen == refToStream.gen) {
+      return gTrue;
+    }
+  } else if (stateObj->isDict()) { // Test each value
+    const int size = stateObj->dictGetLength();
+    for (int i = 0; i < size; ++i) {
+      Object obj1;
+      stateObj->dictGetValNF(i, &obj1);
+      if (obj1.isRef()) {
+        Ref r = obj1.getRef();
+        if (r.num == refToStream.num && r.gen == refToStream.gen) {
+          return gTrue;
+        }
+      }
+      obj1.free();
+    }
+  }
+  return gFalse; // Not found
+}
+
+// Test if this AnnotAppearance references the specified stream
+GBool AnnotAppearance::referencesStream(Ref refToStream) {
+  Object obj1;
+  GBool found;
+
+  // Scan each state's ref/subdictionary
+  appearDict.dictLookupNF("N", &obj1);
+  found = referencesStream(&obj1, refToStream);
+  obj1.free();
+  if (found)
+    return gTrue;
+
+  appearDict.dictLookupNF("R", &obj1);
+  found = referencesStream(&obj1, refToStream);
+  obj1.free();
+  if (found)
+    return gTrue;
+
+  appearDict.dictLookupNF("D", &obj1);
+  found = referencesStream(&obj1, refToStream);
+  obj1.free();
+  return found;
+}
+
+// If this is the only annotation in the document that references the
+// specified appearance stream, remove the appearance stream
+void AnnotAppearance::removeStream(Ref refToStream) {
+  const int lastpage = doc->getNumPages();
+  for (int pg = 1; pg <= lastpage; ++pg) { // Scan all annotations in the document
+    Page *page = doc->getPage(pg);
+    if (!page) {
+      error(errSyntaxError, -1, "Failed check for shared annotation stream at page {0:d}", pg);
+      continue;
+    }
+    Annots *annots = page->getAnnots();
+    for (int i = 0; i < annots->getNumAnnots(); ++i) {
+      AnnotAppearance *annotAp = annots->getAnnot(i)->getAppearStreams();
+      if (annotAp && annotAp != this && annotAp->referencesStream(refToStream)) {
+        return; // Another annotation points to the stream -> Don't delete it
+      }
+    }
+  }
+
+  // TODO: stream resources (e.g. font), AP name tree
+  xref->removeIndirectObject(refToStream);
+}
+
 // Removes stream if obj is a Ref, or removes pointed streams if obj is a Dict
 void AnnotAppearance::removeStateStreams(Object *obj1) {
-  // TODO: Remove XObject resources, check for XObjects shared by multiple
-  //       annotations, delete streams from name table (if any)
   if (obj1->isRef()) {
-    xref->removeIndirectObject(obj1->getRef());
+    removeStream(obj1->getRef());
   } else if (obj1->isDict()) {
     const int size = obj1->dictGetLength();
     for (int i = 0; i < size; ++i) {
       Object obj2;
       obj1->dictGetValNF(i, &obj2);
       if (obj2.isRef()) {
-        xref->removeIndirectObject(obj2.getRef());
+        removeStream(obj2.getRef());
       }
       obj2.free();
     }
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 98e4d70..04a1301 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -382,10 +382,16 @@ public:
   // reset parent annotation's AP and AS after this call.
   void removeAllStreams();
 
+  // Test if this AnnotAppearance references the specified stream
+  GBool referencesStream(Ref targetStreamRef);
+
 private:
+  static GBool referencesStream(Object *stateObj, Ref targetStreamRef);
+  void removeStream(Ref refToStream);
   void removeStateStreams(Object *state);
 
 protected:
+  PDFDoc *doc;
   XRef *xref;                   // the xref table for this PDF file
   Object appearDict;            // Annotation's AP
 };
commit 7684c325929493ad9de01a891de0aef197e176dd
Author: Fabio D'Urso <fabiodurso at hotmail.it>
Date:   Sat Apr 21 20:26:49 2012 +0200

    AnnotText: Always force 24x24 size with custom stamps, not only on first rendering

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 130b9bb..06d08d5 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -2248,8 +2248,6 @@ void AnnotText::draw(Gfx *gfx, GBool printing) {
   if (!isVisible (printing))
     return;
 
-  double rectx2 = rect->x2;
-  double recty2 = rect->y2;
   if (appearance.isNull()) {
     ca = opacity;
 
@@ -2280,9 +2278,11 @@ void AnnotText::draw(Gfx *gfx, GBool printing) {
       appearBuf->append (ANNOT_TEXT_AP_CIRCLE);
     appearBuf->append ("Q\n");
 
+    // Force 24x24 rectangle
+    PDFRectangle fixedRect(rect->x1, rect->y1, rect->x1 + 24, rect->y1 + 24);
+    appearBBox = new AnnotAppearanceBBox(&fixedRect);
     double bbox[4];
-    bbox[0] = bbox[1] = 0;
-    bbox[2] = bbox[3] = 24;
+    appearBBox->getBBoxRect(bbox);
     if (ca == 1) {
       createForm(bbox, gFalse, NULL, &appearance);
     } else {
@@ -2296,15 +2296,18 @@ void AnnotText::draw(Gfx *gfx, GBool printing) {
       createForm(bbox, gFalse, &resDict, &appearance);
     }
     delete appearBuf;
-
-    rectx2 = rect->x1 + 24;
-    recty2 = rect->y1 + 24;
   }
 
   // draw the appearance stream
   appearance.fetch(xref, &obj);
-  gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
-		 rect->x1, rect->y1, rectx2, recty2);
+  if (appearBBox) {
+    gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
+                   appearBBox->getPageXMin(), appearBBox->getPageYMin(),
+                   appearBBox->getPageXMax(), appearBBox->getPageYMax());
+  } else {
+    gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
+                   rect->x1, rect->y1, rect->x2, rect->y2);
+  }
   obj.free();
 }
 


More information about the poppler mailing list