On Sunday, May 20, 2012 07:04:45 PM Fabio D'Urso wrote:
> On Sunday, May 20, 2012 12:27:52 PM Carlos Garcia Campos wrote:
> > Why doesn't Page::removeAnnot() also remove the appearances? I've
> > noticed that the qt4 implementation removes the popup and appearances
> > manually. [...]
> > What happens with all other objects referenced by annotations? I guess
> > they are all left in the document, should we remove them too? like the
> > appearances? [...]
> > Maybe we could add a Annot::removeAnnotFromPage (or something like
> > that) so that every annotation can implement it to remove the objects
> > it references and not referenced by others.

The attached patch defines a virtual Annot::removeReferencedObjects method
that each annotation type can reimplement. The base implementation takes
care of removing the appearance stream. The AnnotMarkup implementation
takes care of removing the popup too.

> I have some doubts about setting /P if the annotation has no /P or a wrong
> value, because that would mean that annotations are automatically modified
> as soon as the document is loaded.

This patch implements the following behavior:
 - When parsing existing annotations, /P is ignored and the in-memory
   page field is always set to the page which the annotation was read
   from (without setting or changing the actual /P value).
 - When adding a new annotation to a given page, /P is set accordingly.

Fabio
From e798145619ea6d59eb1b24a6a3680363f54e9c8a Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Mon, 21 May 2012 18:16:06 +0200
Subject: [PATCH] Added Annot::removeReferencedObjects + Always set
 annotations' page field

- Now Page::removeAnnot calls Annot::removeReferencedObjects, which takes care of
  removing referenced objects (such as the annot popup and the appearance streams).
- Previously, Annot's page field was set only if the annotation dictionary
  contained /P
---
 poppler/Annot.cc              |   40 ++++++++++++++++++++++++++++++++++------
 poppler/Annot.h               |   13 +++++++++----
 poppler/Page.cc               |    7 ++++---
 poppler/Page.h                |    2 +-
 qt4/src/poppler-annotation.cc |    8 --------
 5 files changed, 48 insertions(+), 22 deletions(-)

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 8e1e760..9778bd2 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -1185,6 +1185,7 @@ void Annot::initialize(PDFDoc *docA, Dict *dict) {
   }
   obj1.free();
 
+  // Note: This value is overwritten by Annots ctor
   if (dict->lookupNF("P", &obj1)->isRef()) {
     Ref ref = obj1.getRef();
 
@@ -1416,13 +1417,22 @@ void Annot::setColor(AnnotColor *new_color) {
   }
 }
 
-void Annot::setPage(Ref *pageRef, int pageIndex)
-{
+void Annot::setPage(int pageIndex, GBool updateP) {
+  Page *pageobj = doc->getPage(pageIndex);
   Object obj1;
 
-  obj1.initRef(pageRef->num, pageRef->gen);
-  update("P", &obj1);
-  page = pageIndex;
+  if (pageobj) {
+    Ref pageRef = pageobj->getRef();
+    obj1.initRef(pageRef.num, pageRef.gen);
+    page = pageIndex;
+  } else {
+    obj1.initNull();
+    page = 0;
+  }
+
+  if (updateP) {
+    update("P", &obj1);
+  }
 }
 
 void Annot::setAppearanceState(const char *state) {
@@ -1484,6 +1494,11 @@ void Annot::readArrayNum(Object *pdfArray, int key, double *value) {
   valueObject.free();
 }
 
+void Annot::removeReferencedObjects() {
+  // Remove appearance streams (if any)
+  invalidateAppearance();
+}
+
 void Annot::incRefCnt() {
   refCnt++;
 }
@@ -1934,6 +1949,18 @@ void AnnotMarkup::setDate(GooString *new_date) {
   update ("CreationDate", &obj1);
 }
 
+void AnnotMarkup::removeReferencedObjects() {
+  Page *pageobj = doc->getPage(page);
+  assert(pageobj != NULL); // We're called when removing an annot from a page
+
+  // Remove popup
+  if (popup) {
+    pageobj->removeAnnot(popup);
+  }
+
+  Annot::removeReferencedObjects();
+}
+
 //------------------------------------------------------------------------
 // AnnotText
 //------------------------------------------------------------------------
@@ -6400,7 +6427,7 @@ Annot3D::Activation::Activation(Dict *dict) {
 // Annots
 //------------------------------------------------------------------------
 
-Annots::Annots(PDFDoc *docA, Object *annotsObj) {
+Annots::Annots(PDFDoc *docA, int page, Object *annotsObj) {
   Annot *annot;
   Object obj1;
   int i;
@@ -6421,6 +6448,7 @@ Annots::Annots(PDFDoc *docA, Object *annotsObj) {
         annot = createAnnot (obj1.getDict(), &obj2);
         if (annot) {
           if (annot->isOk()) {
+            annot->setPage(page, gFalse); // Don't change /P
             appendAnnot(annot);
           }
           annot->decRefCnt();
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 04a1301..0d20cc7 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -43,6 +43,7 @@ class Gfx;
 class CharCodeToUnicode;
 class GfxFont;
 class GfxResources;
+class Page;
 class PDFDoc;
 class Form;
 class FormWidget;
@@ -471,6 +472,8 @@ private:
 //------------------------------------------------------------------------
 
 class Annot {
+  friend class Annots;
+  friend class Page;
 public:
   enum AnnotFlag {
     flagUnknown        = 0x0000,
@@ -551,8 +554,6 @@ public:
   // new_color. 
   void setColor(AnnotColor *new_color);
 
-  void setPage(Ref *pageRef, int pageIndex);
-
   void setAppearanceState(const char *state);
 
   // Delete appearance streams and reset appearance state
@@ -587,10 +588,12 @@ private:
   // write vStr[i:j[ in appearBuf
 
   void initialize (PDFDoc *docA, Dict *dict);
+  void setPage (int new_page, GBool updateP); // Called by Page::addAnnot and Annots ctor
 
 
 protected:
   virtual ~Annot();
+  virtual void removeReferencedObjects(); // Called by Page::removeAnnot
   void setColor(AnnotColor *color, GBool fill);
   void drawCircle(double cx, double cy, double r, GBool fill);
   void drawCircleTopLeft(double cx, double cy, double r);
@@ -699,6 +702,8 @@ public:
   void setDate(GooString *new_date);
 
 protected:
+  virtual void removeReferencedObjects();
+
   GooString *label;             // T            (Default autor)
   AnnotPopup *popup;            // Popup
   double opacity;               // CA           (Default 1.0)
@@ -1365,8 +1370,8 @@ private:
 class Annots {
 public:
 
-  // Build a list of Annot objects.
-  Annots(PDFDoc *docA, Object *annotsObj);
+  // Build a list of Annot objects and call setPage on them
+  Annots(PDFDoc *docA, int page, Object *annotsObj);
 
   ~Annots();
 
diff --git a/poppler/Page.cc b/poppler/Page.cc
index eccc198..87bc3a4 100644
--- a/poppler/Page.cc
+++ b/poppler/Page.cc
@@ -348,7 +348,7 @@ Page::~Page() {
 Annots *Page::getAnnots() {
   if (!annots) {
     Object obj;
-    annots = new Annots(doc, getAnnots(&obj));
+    annots = new Annots(doc, num, getAnnots(&obj));
     obj.free();
   }
 
@@ -391,8 +391,7 @@ void Page::addAnnot(Annot *annot) {
   }
 
   annots->appendAnnot(annot);
-
-  annot->setPage(&pageRef, num);
+  annot->setPage(num, gTrue);
 }
 
 void Page::removeAnnot(Annot *annot) {
@@ -428,6 +427,8 @@ void Page::removeAnnot(Annot *annot) {
     }
   }
   annArray.free();
+  annot->removeReferencedObjects(); // Note: Might recurse in removeAnnot again
+  annot->setPage(0, gFalse);
 }
 
 Links *Page::getLinks() {
diff --git a/poppler/Page.h b/poppler/Page.h
index e2e666c..78cedc4 100644
--- a/poppler/Page.h
+++ b/poppler/Page.h
@@ -164,6 +164,7 @@ public:
   Dict *getPieceInfo() { return attrs->getPieceInfo(); }
   Dict *getSeparationInfo() { return attrs->getSeparationInfo(); }
   PDFDoc *getDoc() { return doc; }
+  Ref getRef() { return pageRef; }
 
   // Get resource dictionary.
   Dict *getResourceDict() { return attrs->getResourceDict(); }
@@ -173,7 +174,6 @@ public:
   // Add a new annotation to the page
   void addAnnot(Annot *annot);
   // Remove an existing annotation from the page
-  // Note: Caller is responsible for deleting popup and appearance streams too
   void removeAnnot(Annot *annot);
 
   // Return a list of links.
diff --git a/qt4/src/poppler-annotation.cc b/qt4/src/poppler-annotation.cc
index 4d7cd84..59db52d 100644
--- a/qt4/src/poppler-annotation.cc
+++ b/qt4/src/poppler-annotation.cc
@@ -510,14 +510,6 @@ void AnnotationPrivate::removeAnnotationFromPage(::Page *pdfPage, const Annotati
         return;
     }
 
-    // Remove popup window
-    AnnotMarkup *markupann = dynamic_cast<AnnotMarkup*>(ann->d_ptr->pdfAnnot);
-    if (markupann && markupann->getPopup())
-        pdfPage->removeAnnot(markupann->getPopup());
-
-    // Remove appearance streams (if any)
-    ann->d_ptr->pdfAnnot->invalidateAppearance();
-
     // Remove annotation
     pdfPage->removeAnnot(ann->d_ptr->pdfAnnot);
 
-- 
1.7.6.5

_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler

Reply via email to