[poppler] glib/poppler-document.cc glib/poppler-page.cc glib/poppler-private.h poppler/Annot.cc poppler/Annot.h poppler/ArthurOutputDev.cc poppler/ArthurOutputDev.h poppler/CairoOutputDev.cc poppler/CairoOutputDev.h poppler/FontInfo.cc poppler/Form.cc poppler/Form.h poppler/Link.cc poppler/Link.h poppler/OutputDev.h poppler/Page.cc poppler/Page.h poppler/PDFDoc.cc poppler/TextOutputDev.cc poppler/TextOutputDev.h qt4/src utils/HtmlOutputDev.cc utils/HtmlOutputDev.h

Carlos Garcia Campos carlosgc at kemper.freedesktop.org
Tue Mar 1 03:33:25 PST 2011


 glib/poppler-document.cc                 |    2 
 glib/poppler-page.cc                     |   29 +++----
 glib/poppler-private.h                   |    1 
 poppler/Annot.cc                         |   79 +++++++++++++------
 poppler/Annot.h                          |   24 ++++--
 poppler/ArthurOutputDev.cc               |    4 -
 poppler/ArthurOutputDev.h                |    3 
 poppler/CairoOutputDev.cc                |    3 
 poppler/CairoOutputDev.h                 |    6 -
 poppler/FontInfo.cc                      |    4 -
 poppler/Form.cc                          |   36 +++------
 poppler/Form.h                           |    5 -
 poppler/Link.cc                          |  124 ++++---------------------------
 poppler/Link.h                           |   43 +---------
 poppler/OutputDev.h                      |    4 -
 poppler/PDFDoc.cc                        |    4 -
 poppler/Page.cc                          |   63 ++++++++-------
 poppler/Page.h                           |   11 +-
 poppler/TextOutputDev.cc                 |    9 +-
 poppler/TextOutputDev.h                  |   10 +-
 qt4/src/poppler-link-extractor-private.h |    2 
 qt4/src/poppler-link-extractor.cc        |    3 
 qt4/src/poppler-page.cc                  |   12 +--
 utils/HtmlOutputDev.cc                   |    7 +
 utils/HtmlOutputDev.h                    |    4 -
 25 files changed, 188 insertions(+), 304 deletions(-)

New commits:
commit 664865a2ddca9c20ac36a41aef52ebf12eab838d
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Tue Mar 1 10:56:40 2011 +0100

    Merge Link and AnnotLink code
    
    Annotations now belong to the Page and are created only once on demand.
    Annots are now ref counted and Links is a list of AnnotLink objects,
    Link object has been removed. The AnnotLink API is mostly the same than
    Link and frontends APIs are not affected.
    Qt4 changes made by Pino Toscano.

diff --git a/glib/poppler-document.cc b/glib/poppler-document.cc
index fd764d8..710a5b3 100644
--- a/glib/poppler-document.cc
+++ b/glib/poppler-document.cc
@@ -2493,7 +2493,7 @@ poppler_document_get_form_field (PopplerDocument *document,
   if (!page)
     return NULL;
 
-  widgets = page->getPageWidgets ();
+  widgets = page->getFormWidgets (document->doc->getCatalog ());
   if (!widgets)
     return NULL;
 
diff --git a/glib/poppler-page.cc b/glib/poppler-page.cc
index 8531bda..d1f1bcf 100644
--- a/glib/poppler-page.cc
+++ b/glib/poppler-page.cc
@@ -76,8 +76,6 @@ poppler_page_finalize (GObject *object)
   g_object_unref (page->document);
   page->document = NULL;
 
-  if (page->annots != NULL)
-    delete page->annots;
   if (page->text != NULL) 
     page->text->decRefCnt();
   /* page->page is owned by the document */
@@ -1139,15 +1137,12 @@ poppler_page_get_link_mapping (PopplerPage *page)
   GList *map_list = NULL;
   gint i;
   Links *links;
-  Object obj;
   double width, height;
   
   g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
   
-  links = new Links (page->page->getAnnots (&obj),
-		     page->document->doc->getCatalog ()->getBaseURI ());
-  obj.free ();
-  
+  links = new Links (page->page->getAnnots (page->document->doc->getCatalog ()));
+
   if (links == NULL)
     return NULL;
   
@@ -1158,7 +1153,7 @@ poppler_page_get_link_mapping (PopplerPage *page)
       PopplerLinkMapping *mapping;
       PopplerRectangle rect;
       LinkAction *link_action;
-      Link *link;
+      AnnotLink *link;
       
       link = links->getLink (i);
       link_action = link->getAction ();
@@ -1250,7 +1245,8 @@ poppler_page_get_form_field_mapping (PopplerPage *page)
   
   g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
 
-  forms = page->page->getPageWidgets ();
+  forms = page->page->getFormWidgets (page->document->doc->getCatalog ());
+
   if (forms == NULL)
     return NULL;
   
@@ -1273,6 +1269,8 @@ poppler_page_get_form_field_mapping (PopplerPage *page)
     
     map_list = g_list_prepend (map_list, mapping);
   }
+
+  delete forms;
   
   return map_list;
 }
@@ -1310,25 +1308,24 @@ poppler_page_get_annot_mapping (PopplerPage *page)
   GList *map_list = NULL;
   double width, height;
   gint i;
+  Annots *annots;
 
   g_return_val_if_fail (POPPLER_IS_PAGE (page), NULL);
 
-  if (!page->annots)
-    page->annots = page->page->getAnnots (page->document->doc->getCatalog ());
-  
-  if (!page->annots)
+  annots = page->page->getAnnots (page->document->doc->getCatalog ());
+  if (!annots)
     return NULL;
 
   poppler_page_get_size (page, &width, &height);
 
-  for (i = 0; i < page->annots->getNumAnnots (); i++) {
+  for (i = 0; i < annots->getNumAnnots (); i++) {
     PopplerAnnotMapping *mapping;
     PopplerRectangle rect;
     Annot *annot;
     PDFRectangle *annot_rect;
     gint rotation = 0;
 
-    annot = page->annots->getAnnot (i);
+    annot = annots->getAnnot (i);
 
     /* Create the mapping */
     mapping = poppler_annot_mapping_new ();
@@ -1432,7 +1429,7 @@ poppler_page_add_annot (PopplerPage  *page,
   g_return_if_fail (POPPLER_IS_PAGE (page));
   g_return_if_fail (POPPLER_IS_ANNOT (annot));
 
-  page->page->addAnnot (annot->annot);
+  page->page->addAnnot (annot->annot, page->document->doc->getCatalog ());
 }
 
 /* PopplerRectangle type */
diff --git a/glib/poppler-private.h b/glib/poppler-private.h
index f939fa5..4e06a0e 100644
--- a/glib/poppler-private.h
+++ b/glib/poppler-private.h
@@ -60,7 +60,6 @@ struct _PopplerPage
   Page *page;
   int index;
   TextPage *text;
-  Annots *annots;
 };
 
 struct _PopplerFormField
diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 1475db3..5a5ba2e 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -46,13 +46,13 @@
 #include "Catalog.h"
 #include "Gfx.h"
 #include "Lexer.h"
+#include "Page.h"
 #include "Annot.h"
 #include "GfxFont.h"
 #include "CharCodeToUnicode.h"
 #include "PDFDocEncoding.h"
 #include "Form.h"
 #include "Error.h"
-#include "Page.h"
 #include "XRef.h"
 #include "Movie.h"
 #include "OptionalContent.h"
@@ -853,6 +853,7 @@ AnnotAppearanceCharacs::~AnnotAppearanceCharacs() {
 Annot::Annot(XRef *xrefA, PDFRectangle *rectA, Catalog *catalog) {
   Object obj1;
 
+  refCnt = 1;
   flags = flagUnknown;
   type = typeUnknown;
 
@@ -875,6 +876,7 @@ Annot::Annot(XRef *xrefA, PDFRectangle *rectA, Catalog *catalog) {
 }
 
 Annot::Annot(XRef *xrefA, Dict *dict, Catalog* catalog) {
+  refCnt = 1;
   hasRef = false;
   flags = flagUnknown;
   type = typeUnknown;
@@ -883,6 +885,7 @@ Annot::Annot(XRef *xrefA, Dict *dict, Catalog* catalog) {
 }
 
 Annot::Annot(XRef *xrefA, Dict *dict, Catalog* catalog, Object *obj) {
+  refCnt = 1;
   if (obj->isRef()) {
     hasRef = gTrue;
     ref = obj->getRef();
@@ -1048,6 +1051,17 @@ void Annot::initialize(XRef *xrefA, Dict *dict, Catalog *catalog) {
   }
 }
 
+void Annot::getRect(double *x1, double *y1, double *x2, double *y2) const {
+  *x1 = rect->x1;
+  *y1 = rect->y1;
+  *x2 = rect->x2;
+  *y2 = rect->y2;
+}
+
+GBool Annot::inRect(double x, double y) const {
+  return rect->contains(x, y);
+}
+
 void Annot::update(const char *key, Object *value) {
   /* Set M to current time */
   delete modified;
@@ -1128,6 +1142,15 @@ void Annot::readArrayNum(Object *pdfArray, int key, double *value) {
   valueObject.free();
 }
 
+void Annot::incRefCnt() {
+  refCnt++;
+}
+
+void Annot::decRefCnt() {
+  if (--refCnt == 0)
+    delete this;
+}
+
 Annot::~Annot() {
   annotObj.free();
   
@@ -1999,11 +2022,7 @@ AnnotLink::AnnotLink(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
 }
 
 AnnotLink::~AnnotLink() {
-  /*
-  if (actionDict)
-    delete actionDict;
-  */
-  dest.free();
+  delete action;
   /*
   if (uriAction)
     delete uriAction;
@@ -2014,15 +2033,21 @@ AnnotLink::~AnnotLink() {
 
 void AnnotLink::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
   Object obj1;
-  /*
-  if (dict->lookup("A", &obj1)->isDict()) {
-    actionDict = NULL;
+
+  action = NULL;
+
+  // look for destination
+  if (!dict->lookup("Dest", &obj1)->isNull()) {
+    action = LinkAction::parseDest(&obj1);
+  // look for action
   } else {
-    actionDict = NULL;
+    obj1.free();
+    if (dict->lookup("A", &obj1)->isDict()) {
+      action = LinkAction::parseAction(&obj1, catalog->getBaseURI());
+    }
   }
   obj1.free();
-  */
-  dict->lookup("Dest", &dest);
+
   if (dict->lookup("H", &obj1)->isName()) {
     GooString *effect = new GooString(obj1.getName());
 
@@ -2750,10 +2775,9 @@ void AnnotWidget::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
   }
   obj1.free();
 
+  action = NULL;
   if(dict->lookup("A", &obj1)->isDict()) {
-    action = NULL;
-  } else {
-    action = NULL;
+    action = LinkAction::parseAction(&obj1, catalog->getBaseURI());
   }
   obj1.free();
 
@@ -5235,7 +5259,6 @@ Annot3D::Activation::Activation(Dict *dict) {
 Annots::Annots(XRef *xref, Catalog *catalog, Object *annotsObj) {
   Annot *annot;
   Object obj1;
-  int size;
   int i;
 
   annots = NULL;
@@ -5251,15 +5274,8 @@ Annots::Annots(XRef *xref, Catalog *catalog, Object *annotsObj) {
       if (annotsObj->arrayGet(i, &obj1)->isDict()) {
         annotsObj->arrayGetNF(i, &obj2);
         annot = createAnnot (xref, obj1.getDict(), catalog, &obj2);
-        if (annot && annot->isOk()) {
-          if (nAnnots >= size) {
-            size += 16;
-            annots = (Annot **)greallocn(annots, size, sizeof(Annot *));
-          }
-          annots[nAnnots++] = annot;
-        } else {
-          delete annot;
-        }
+        appendAnnot(annot);
+        annot->decRefCnt();
       }
       obj2.free();
       obj1.free();
@@ -5267,6 +5283,17 @@ Annots::Annots(XRef *xref, Catalog *catalog, Object *annotsObj) {
   }
 }
 
+void Annots::appendAnnot(Annot *annot) {
+  if (annot && annot->isOk()) {
+    if (nAnnots >= size) {
+      size += 16;
+      annots = (Annot **)greallocn(annots, size, sizeof(Annot *));
+    }
+    annots[nAnnots++] = annot;
+    annot->incRefCnt();
+  }
+}
+
 Annot *Annots::createAnnot(XRef *xref, Dict* dict, Catalog *catalog, Object *obj) {
   Annot *annot;
   Object obj1;
@@ -5364,7 +5391,7 @@ Annots::~Annots() {
   int i;
 
   for (i = 0; i < nAnnots; ++i) {
-    delete annots[i];
+    annots[i]->decRefCnt();
   }
   gfree(annots);
 }
diff --git a/poppler/Annot.h b/poppler/Annot.h
index a392267..8df1c67 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -486,9 +486,11 @@ public:
   Annot(XRef *xrefA, PDFRectangle *rectA, Catalog *catalog);
   Annot(XRef *xrefA, Dict *dict, Catalog *catalog);
   Annot(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
-  virtual ~Annot();
   GBool isOk() { return ok; }
 
+  void incRefCnt();
+  void decRefCnt();
+
   virtual void draw(Gfx *gfx, GBool printing);
   // Get appearance object.
   Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); }
@@ -513,9 +515,11 @@ public:
 
   // getters
   XRef *getXRef() const { return xref; }
+  GBool getHasRef() const { return hasRef; }
   Ref getRef() const { return ref; }
   AnnotSubtype getType() const { return type; }
   PDFRectangle *getRect() const { return rect; }
+  void getRect(double *x1, double *y1, double *x2, double *y2) const;
   GooString *getContents() const { return contents; }
   int getPageNum() const { return page; }
   GooString *getName() const { return name; }
@@ -529,6 +533,9 @@ public:
 
   int getId() { return ref.num; }
 
+  // Check if point is inside the annot rectangle.
+  GBool inRect(double x, double y) const;
+
 private:
   void readArrayNum(Object *pdfArray, int key, double *value);
   // write vStr[i:j[ in appearBuf
@@ -537,6 +544,7 @@ private:
 
 
 protected:
+  virtual ~Annot();
   void setColor(AnnotColor *color, GBool fill);
   void drawCircle(double cx, double cy, double r, GBool fill);
   void drawCircleTopLeft(double cx, double cy, double r);
@@ -550,6 +558,8 @@ protected:
   // and sets M to the current time
   void update(const char *key, Object *value);
 
+  int refCnt;
+
   Object annotObj;
   
   // required data
@@ -774,8 +784,7 @@ public:
   virtual void draw(Gfx *gfx, GBool printing);
 
   // getters
-  Dict *getActionDict() const { return actionDict; }
-  Object *getDest() { return &dest; }
+  LinkAction *getAction() const { return action; }
   AnnotLinkEffect getLinkEffect() const { return linkEffect; }
   Dict *getUriAction() const { return uriAction; }
   AnnotQuadrilaterals *getQuadrilaterals() const { return quadrilaterals; }
@@ -784,8 +793,7 @@ protected:
 
   void initialize(XRef *xrefA, Catalog *catalog, Dict *dict);
 
-  Dict *actionDict;                    // A
-  Object dest;                         // Dest
+  LinkAction *action;                  // A, Dest
   AnnotLinkEffect linkEffect;          // H          (Default I)
   Dict *uriAction;                     // PA
 
@@ -1161,7 +1169,7 @@ public:
 
   AnnotWidgetHighlightMode getMode() { return mode; }
   AnnotAppearanceCharacs *getAppearCharacs() { return appearCharacs; }
-  Dict *getAction() { return action; }
+  LinkAction *getAction() { return action; }
   Dict *getAdditionActions() { return additionActions; }
   Dict *getParent() { return parent; }
 
@@ -1185,7 +1193,7 @@ private:
   FormWidget *widget;                     // FormWidget object for this annotation
   AnnotWidgetHighlightMode mode;          // H  (Default I)
   AnnotAppearanceCharacs *appearCharacs;  // MK
-  Dict *action;                           // A
+  LinkAction *action;                     // A
   Dict *additionActions;                  // AA
   // inherited  from Annot
   // AnnotBorderBS border;                // BS
@@ -1268,6 +1276,7 @@ public:
   // Iterate through list of annotations.
   int getNumAnnots() { return nAnnots; }
   Annot *getAnnot(int i) { return annots[i]; }
+  void appendAnnot(Annot *annot);
 
 private:
   Annot* createAnnot(XRef *xref, Dict* dict, Catalog *catalog, Object *obj);
@@ -1275,6 +1284,7 @@ private:
 
   Annot **annots;
   int nAnnots;
+  int size;
 };
 
 #endif
diff --git a/poppler/ArthurOutputDev.cc b/poppler/ArthurOutputDev.cc
index d065d9b..bfec690 100644
--- a/poppler/ArthurOutputDev.cc
+++ b/poppler/ArthurOutputDev.cc
@@ -140,10 +140,6 @@ void ArthurOutputDev::startPage(int pageNum, GfxState *state)
 void ArthurOutputDev::endPage() {
 }
 
-void ArthurOutputDev::drawLink(Link *link, Catalog *catalog)
-{
-}
-
 void ArthurOutputDev::saveState(GfxState *state)
 {
   m_painter->save();
diff --git a/poppler/ArthurOutputDev.h b/poppler/ArthurOutputDev.h
index fc00c71..984f95e 100644
--- a/poppler/ArthurOutputDev.h
+++ b/poppler/ArthurOutputDev.h
@@ -91,9 +91,6 @@ public:
   // End a page.
   virtual void endPage();
 
-  //----- link borders
-  virtual void drawLink(Link *link, Catalog *catalog);
-
   //----- save/restore graphics state
   virtual void saveState(GfxState *state);
   virtual void restoreState(GfxState *state);
diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 2ee5167..de0663c 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -242,9 +242,6 @@ void CairoOutputDev::endPage() {
   }
 }
 
-void CairoOutputDev::drawLink(Link *link, Catalog *catalog) {
-}
-
 void CairoOutputDev::saveState(GfxState *state) {
   LOG(printf ("save\n"));
   cairo_save (cairo);
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index 9404d6d..8ef2a93 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -128,9 +128,6 @@ public:
   // End a page.
   virtual void endPage();
 
-  //----- link borders
-  virtual void drawLink(Link *link, Catalog *catalog);
-
   //----- save/restore graphics state
   virtual void saveState(GfxState *state);
   virtual void restoreState(GfxState *state);
@@ -386,9 +383,6 @@ public:
   // Does this device need non-text content?
   virtual GBool needNonText() { return gTrue; }
 
-    //----- link borders
-  virtual void drawLink(Link *link, Catalog *catalog) { }
-
   //----- save/restore graphics state
   virtual void saveState(GfxState *state) { }
   virtual void restoreState(GfxState *state) { }
diff --git a/poppler/FontInfo.cc b/poppler/FontInfo.cc
index 6560598..ecf26fb 100644
--- a/poppler/FontInfo.cc
+++ b/poppler/FontInfo.cc
@@ -73,8 +73,7 @@ GooList *FontInfoScanner::scan(int nPages) {
     if ((resDict = page->getResourceDict())) {
       scanFonts(resDict, result);
     }
-    annots = new Annots(doc->getXRef(), doc->getCatalog(), page->getAnnots(&obj1));
-    obj1.free();
+    annots = page->getAnnots(doc->getCatalog());
     for (int i = 0; i < annots->getNumAnnots(); ++i) {
       if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) {
 	obj1.streamGetDict()->lookup("Resources", &obj2);
@@ -85,7 +84,6 @@ GooList *FontInfoScanner::scan(int nPages) {
       }
       obj1.free();
     }
-    delete annots;
   }
 
   currentPage = lastPage;
diff --git a/poppler/Form.cc b/poppler/Form.cc
index 4e1b8e1..15e7e61 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -1360,50 +1360,40 @@ FormWidget* Form::findWidgetByRef (Ref aref)
 // FormPageWidgets
 //------------------------------------------------------------------------
 
-FormPageWidgets::FormPageWidgets (XRef *xrefA, Object* annots, unsigned int page, Form *form)
+FormPageWidgets::FormPageWidgets (Annots *annots, unsigned int page, Form *form)
 {
-  Object obj1;
   numWidgets = 0;
   widgets = NULL;
-  xref = xrefA;
-  if (annots->isArray() && form) {
-    size = annots->arrayGetLength();
+
+  if (annots && annots->getNumAnnots() > 0 && form) {
+    size = annots->getNumAnnots();
     widgets = (FormWidget**)greallocn(widgets, size, sizeof(FormWidget*));
 
     /* For each entry in the page 'Annots' dict, try to find
        a matching form field */
     for (int i = 0; i < size; ++i) {
-      if (!annots->arrayGetNF(i, &obj1)->isRef())  {
+      Annot *annot = annots->getAnnot(i);
+
+      if (!annot->getHasRef()) {
         /* Since all entry in a form field's kid dict needs to be
            indirect references, if this annot isn't indirect, it isn't 
            related to a form field */
-        obj1.free();
         continue;
       }
-      Ref r = obj1.getRef();
+
+      Ref r = annot->getRef();
 
       /* Try to find a form field which either has this Annot in its Kids entry
           or  is merged with this Annot */
       FormWidget* tmp = form->findWidgetByRef(r);
-      if(tmp) {
+      if (tmp) {
         // We've found a corresponding form field, link it
         tmp->setID(FormWidget::encodeID(page, numWidgets));
+        tmp->setFontSize(annot->getFontSize());
         widgets[numWidgets++] = tmp;
-        //create a temporary Annot to get the font size
-        Object obj2;
-        if (annots->arrayGet(i, &obj2)->isDict()) {
-          Annot *ann;
-	  
-          ann = new Annot(xref, obj2.getDict(), NULL);
-          tmp->setFontSize(ann->getFontSize());
-          delete ann;
-        }
-        obj2.free();
-      } 
-      
-      obj1.free();
+      }
     }
-  } 
+  }
 }
 
 FormPageWidgets::~FormPageWidgets()
diff --git a/poppler/Form.h b/poppler/Form.h
index b38b92f..833fa27 100644
--- a/poppler/Form.h
+++ b/poppler/Form.h
@@ -26,6 +26,7 @@ class GooString;
 class Array;
 class Dict;
 class Annot;
+class Annots;
 class Catalog;
 class LinkAction;
 
@@ -477,7 +478,7 @@ private:
 
 class FormPageWidgets {
 public:
-  FormPageWidgets (XRef *xrefA, Object* annots, unsigned int page, Form *form);
+  FormPageWidgets (Annots* annots, unsigned int page, Form *form);
   ~FormPageWidgets();
   
   int getNumWidgets() const { return numWidgets; }
@@ -487,8 +488,6 @@ private:
   FormWidget** widgets;
   int numWidgets;
   int size;
-  unsigned pageNum;
-  XRef* xref;
 };
 
 #endif
diff --git a/poppler/Link.cc b/poppler/Link.cc
index b6d7f2d..d281212 100644
--- a/poppler/Link.cc
+++ b/poppler/Link.cc
@@ -44,6 +44,7 @@
 #include "Sound.h"
 #include "FileSpec.h"
 #include "Rendition.h"
+#include "Annot.h"
 
 //------------------------------------------------------------------------
 // LinkAction
@@ -860,96 +861,10 @@ LinkUnknown::~LinkUnknown() {
 }
 
 //------------------------------------------------------------------------
-// Link
-//------------------------------------------------------------------------
-
-Link::Link(Dict *dict, GooString *baseURI) {
-  Object obj1, obj2;
-  double t;
-
-  action = NULL;
-  ok = gFalse;
-
-  // get rectangle
-  if (!dict->lookup("Rect", &obj1)->isArray()) {
-    error(-1, "Annotation rectangle is wrong type");
-    goto err2;
-  }
-  if (!obj1.arrayGet(0, &obj2)->isNum()) {
-    error(-1, "Bad annotation rectangle");
-    goto err1;
-  }
-  x1 = obj2.getNum();
-  obj2.free();
-  if (!obj1.arrayGet(1, &obj2)->isNum()) {
-    error(-1, "Bad annotation rectangle");
-    goto err1;
-  }
-  y1 = obj2.getNum();
-  obj2.free();
-  if (!obj1.arrayGet(2, &obj2)->isNum()) {
-    error(-1, "Bad annotation rectangle");
-    goto err1;
-  }
-  x2 = obj2.getNum();
-  obj2.free();
-  if (!obj1.arrayGet(3, &obj2)->isNum()) {
-    error(-1, "Bad annotation rectangle");
-    goto err1;
-  }
-  y2 = obj2.getNum();
-  obj2.free();
-  obj1.free();
-  if (x1 > x2) {
-    t = x1;
-    x1 = x2;
-    x2 = t;
-  }
-  if (y1 > y2) {
-    t = y1;
-    y1 = y2;
-    y2 = t;
-  }
-
-  // look for destination
-  if (!dict->lookup("Dest", &obj1)->isNull()) {
-    action = LinkAction::parseDest(&obj1);
-
-  // look for action
-  } else {
-    obj1.free();
-    if (dict->lookup("A", &obj1)->isDict()) {
-      action = LinkAction::parseAction(&obj1, baseURI);
-    }
-  }
-  obj1.free();
-
-  // check for bad action
-  if (action) {
-    ok = gTrue;
-  }
-
-  return;
-
- err1:
-  obj2.free();
- err2:
-  obj1.free();
-}
-
-Link::~Link() {
-  if (action) {
-    delete action;
-  }
-}
-
-//------------------------------------------------------------------------
 // Links
 //------------------------------------------------------------------------
 
-Links::Links(Object *annots, GooString *baseURI) {
-  Link *link;
-  Object obj1, obj2;
+Links::Links(Annots *annots) {
   int size;
   int i;
 
@@ -957,25 +872,21 @@ Links::Links(Object *annots, GooString *baseURI) {
   size = 0;
   numLinks = 0;
 
-  if (annots->isArray()) {
-    for (i = 0; i < annots->arrayGetLength(); ++i) {
-      if (annots->arrayGet(i, &obj1)->isDict()) {
-	if (obj1.dictLookup("Subtype", &obj2)->isName("Link")) {
-	  link = new Link(obj1.getDict(), baseURI);
-	  if (link->isOk()) {
-	    if (numLinks >= size) {
-	      size += 16;
-	      links = (Link **)greallocn(links, size, sizeof(Link *));
-	    }
-	    links[numLinks++] = link;
-	  } else {
-	    delete link;
-	  }
-	}
-	obj2.free();
-      }
-      obj1.free();
+  if (!annots)
+    return;
+
+  for (i = 0; i < annots->getNumAnnots(); ++i) {
+    Annot *annot = annots->getAnnot(i);
+
+    if (annot->getType() != Annot::typeLink)
+      continue;
+
+    if (numLinks >= size) {
+      size += 16;
+      links = (AnnotLink **)greallocn(links, size, sizeof(AnnotLink *));
     }
+    annot->incRefCnt();
+    links[numLinks++] = static_cast<AnnotLink *>(annot);
   }
 }
 
@@ -983,7 +894,8 @@ Links::~Links() {
   int i;
 
   for (i = 0; i < numLinks; ++i)
-    delete links[i];
+    links[i]->decRefCnt();
+
   gfree(links);
 }
 
diff --git a/poppler/Link.h b/poppler/Link.h
index ea10375..a5dbfab 100644
--- a/poppler/Link.h
+++ b/poppler/Link.h
@@ -37,6 +37,8 @@ class Array;
 class Dict;
 class Sound;
 class MediaRendition;
+class AnnotLink;
+class Annots;
 
 //------------------------------------------------------------------------
 // LinkAction
@@ -454,41 +456,6 @@ private:
 };
 
 //------------------------------------------------------------------------
-// Link
-//------------------------------------------------------------------------
-
-class Link {
-public:
-
-  // Construct a link, given its dictionary.
-  Link(Dict *dict, GooString *baseURI);
-
-  // Destructor.
-  ~Link();
-
-  // Was the link created successfully?
-  GBool isOk() { return ok; }
-
-  // Check if point is inside the link rectangle.
-  GBool inRect(double x, double y)
-    { return x1 <= x && x <= x2 && y1 <= y && y <= y2; }
-
-  // Get action.
-  LinkAction *getAction() { return action; }
-
-  // Get the link rectangle.
-  void getRect(double *xa1, double *ya1, double *xa2, double *ya2)
-    { *xa1 = x1; *ya1 = y1; *xa2 = x2; *ya2 = y2; }
-
-private:
-
-  double x1, y1;		// lower left corner
-  double x2, y2;		// upper right corner
-  LinkAction *action;		// action
-  GBool ok;			// is link valid?
-};
-
-//------------------------------------------------------------------------
 // Links
 //------------------------------------------------------------------------
 
@@ -496,14 +463,14 @@ class Links {
 public:
 
   // Extract links from array of annotations.
-  Links(Object *annots, GooString *baseURI);
+  Links(Annots *annots);
 
   // Destructor.
   ~Links();
 
   // Iterate through list of links.
   int getNumLinks() const { return numLinks; }
-  Link *getLink(int i) const { return links[i]; }
+  AnnotLink *getLink(int i) const { return links[i]; }
 
   // If point <x>,<y> is in a link, return the associated action;
   // else return NULL.
@@ -514,7 +481,7 @@ public:
 
 private:
 
-  Link **links;
+  AnnotLink **links;
   int numLinks;
 };
 
diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h
index 65cfa2d..31767d0 100644
--- a/poppler/OutputDev.h
+++ b/poppler/OutputDev.h
@@ -55,7 +55,7 @@ class GfxGouraudTriangleShading;
 class GfxPatchMeshShading;
 class Stream;
 class Links;
-class Link;
+class AnnotLink;
 class Catalog;
 class Page;
 class Function;
@@ -304,7 +304,7 @@ public:
   virtual void clearSoftMask(GfxState * /*state*/) {}
 
   //----- links
-  virtual void processLink(Link * /*link*/, Catalog * /*catalog*/) {}
+  virtual void processLink(AnnotLink * /*link*/, Catalog * /*catalog*/) {}
 
 #if 1 //~tmp: turn off anti-aliasing temporarily
   virtual GBool getVectorAntialias() { return gFalse; }
diff --git a/poppler/PDFDoc.cc b/poppler/PDFDoc.cc
index cb3de02..cf5cde9 100644
--- a/poppler/PDFDoc.cc
+++ b/poppler/PDFDoc.cc
@@ -473,9 +473,7 @@ void PDFDoc::displayPageSlice(OutputDev *out, int page,
 Links *PDFDoc::getLinks(int page) {
   Page *p = getPage(page);
   if (!p) {
-    Object obj;
-    obj.initNull();
-    return new Links (&obj, NULL);
+    return new Links (NULL);
   }
   return p->getLinks(catalog);
 }
diff --git a/poppler/Page.cc b/poppler/Page.cc
index caf233f..5c7edf4 100644
--- a/poppler/Page.cc
+++ b/poppler/Page.cc
@@ -262,7 +262,7 @@ Page::Page(XRef *xrefA, int numA, Dict *pageDict, Ref pageRefA, PageAttrs *attrs
   xref = xrefA;
   num = numA;
   duration = -1;
-  pageWidgets = NULL;
+  annots = NULL;
 
   pageObj.initDict(pageDict);
   pageRef = pageRefA;
@@ -289,18 +289,14 @@ Page::Page(XRef *xrefA, int numA, Dict *pageDict, Ref pageRefA, PageAttrs *attrs
   tmp.free();
 
   // annotations
-  pageDict->lookupNF("Annots", &annots);
-  if (!(annots.isRef() || annots.isArray() || annots.isNull())) {
+  pageDict->lookupNF("Annots", &annotsObj);
+  if (!(annotsObj.isRef() || annotsObj.isArray() || annotsObj.isNull())) {
     error(-1, "Page annotations object (page %d) is wrong type (%s)",
-	  num, annots.getTypeName());
-    annots.free();
+	  num, annotsObj.getTypeName());
+    annotsObj.free();
     goto err2;
   }
 
-  // forms
-  pageWidgets = new FormPageWidgets(xrefA, this->getAnnots(&tmp),num,form);
-  tmp.free();
-
   // contents
   pageDict->lookupNF("Contents", &contents);
   if (!(contents.isRef() || contents.isArray() ||
@@ -331,17 +327,17 @@ Page::Page(XRef *xrefA, int numA, Dict *pageDict, Ref pageRefA, PageAttrs *attrs
 
   trans.initNull();
  err2:
-  annots.initNull();
+  annotsObj.initNull();
  err1:
   contents.initNull();
   ok = gFalse;
 }
 
 Page::~Page() {
-  delete pageWidgets;
   delete attrs;
+  delete annots;
   pageObj.free();
-  annots.free();
+  annotsObj.free();
   contents.free();
   trans.free();
   thumb.free();
@@ -349,20 +345,26 @@ Page::~Page() {
 }
 
 Annots *Page::getAnnots(Catalog *catalog) {
-  Annots *annots;
-  Object obj;
+  if (!annots) {
+    Object obj;
+    annots = new Annots(xref, catalog, getAnnots(&obj));
+    obj.free();
+  }
 
-  annots = new Annots(xref, catalog, getAnnots(&obj));
-  obj.free();
   return annots;
 }
 
-void Page::addAnnot(Annot *annot) {
+void Page::addAnnot(Annot *annot, Catalog *catalog) {
   Object obj1;
   Object tmp;
   Ref annotRef = annot->getRef ();
 
-  if (annots.isNull()) {
+  // Make sure we have annots before adding the new one
+  // even if it's an empty list so that we can safely
+  // call annots->appendAnnot(annot)
+  getAnnots(catalog);
+
+  if (annotsObj.isNull()) {
     Ref annotsRef;
     // page doesn't have annots array,
     // we have to create it
@@ -372,31 +374,32 @@ void Page::addAnnot(Annot *annot) {
     tmp.free();
 
     annotsRef = xref->addIndirectObject (&obj1);
-    annots.initRef(annotsRef.num, annotsRef.gen);
-    pageObj.dictSet ("Annots", &annots);
+    annotsObj.initRef(annotsRef.num, annotsRef.gen);
+    pageObj.dictSet ("Annots", &annotsObj);
     xref->setModifiedObject (&pageObj, pageRef);
   } else {
     getAnnots(&obj1);
     if (obj1.isArray()) {
       obj1.arrayAdd (tmp.initRef (annotRef.num, annotRef.gen));
-      if (annots.isRef())
-        xref->setModifiedObject (&obj1, annots.getRef());
+      if (annotsObj.isRef())
+        xref->setModifiedObject (&obj1, annotsObj.getRef());
       else
         xref->setModifiedObject (&pageObj, pageRef);
     }
     obj1.free();
   }
 
+  annots->appendAnnot(annot);
+
   annot->setPage(&pageRef, num);
 }
 
 Links *Page::getLinks(Catalog *catalog) {
-  Links *links;
-  Object obj;
+  return new Links(getAnnots(catalog));
+}
 
-  links = new Links(getAnnots(&obj), catalog->getBaseURI());
-  obj.free();
-  return links;
+FormPageWidgets *Page::getFormWidgets(Catalog *catalog) {
+  return new FormPageWidgets(getAnnots(catalog), num, catalog->getForm());
 }
 
 void Page::display(OutputDev *out, double hDPI, double vDPI,
@@ -485,9 +488,8 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
   obj.free();
 
   // draw annotations
-  annotList = new Annots(xref, catalog, getAnnots(&obj));
-  obj.free();
-  
+  annotList = getAnnots(catalog);
+
   if (annotList->getNumAnnots() > 0) {
     if (globalParams->getPrintCommands()) {
       printf("***** Annotations\n");
@@ -502,7 +504,6 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
     }
     out->dump();
   }
-  delete annotList;
 
   delete gfx;
 }
diff --git a/poppler/Page.h b/poppler/Page.h
index 9d892b1..6db9049 100644
--- a/poppler/Page.h
+++ b/poppler/Page.h
@@ -55,6 +55,7 @@ public:
   PDFRectangle(double x1A, double y1A, double x2A, double y2A)
     { x1 = x1A; y1 = y1A; x2 = x2A; y2 = y2A; }
   GBool isValid() { return x1 != 0 || y1 != 0 || x2 != 0 || y2 != 0; }
+  GBool contains(double x, double y) { return x1 <= x && x <= x2 && y1 <= y && y <= y2; }
   void clipTo(PDFRectangle *rect);
 };
 
@@ -162,9 +163,9 @@ public:
   Dict *getResourceDict() { return attrs->getResourceDict(); }
 
   // Get annotations array.
-  Object *getAnnots(Object *obj) { return annots.fetch(xref, obj); }
+  Object *getAnnots(Object *obj) { return annotsObj.fetch(xref, obj); }
   // Add a new annotation to the page
-  void addAnnot(Annot *annot);
+  void addAnnot(Annot *annot, Catalog *catalog);
 
   // Return a list of links.
   Links *getLinks(Catalog *catalog);
@@ -183,7 +184,7 @@ public:
   Object *getTrans(Object *obj) { return trans.fetch(xref, obj); }
 
   // Get form.
-  FormPageWidgets *getPageWidgets() { return pageWidgets; }
+  FormPageWidgets *getFormWidgets(Catalog *catalog);
 
   // Get duration, the maximum length of time, in seconds,
   // that the page is displayed before the presentation automatically
@@ -241,9 +242,9 @@ private:
   Ref pageRef;                  // page reference
   int num;			// page number
   PageAttrs *attrs;		// page attributes
-  Object annots;		// annotations array
+  Annots *annots;               // annotations
+  Object annotsObj;		// annotations array
   Object contents;		// page contents
-  FormPageWidgets *pageWidgets; 			// the form for that page
   Object thumb;			// page thumbnail
   Object trans;			// page transition
   Object actions;		// page addiction actions
diff --git a/poppler/TextOutputDev.cc b/poppler/TextOutputDev.cc
index a946ba6..428cdb3 100644
--- a/poppler/TextOutputDev.cc
+++ b/poppler/TextOutputDev.cc
@@ -58,6 +58,7 @@
 #include "Link.h"
 #include "TextOutputDev.h"
 #include "Page.h"
+#include "Annot.h"
 #include "PDFDocEncoding.h"
 
 #ifdef MACOS
@@ -184,12 +185,12 @@ public:
 class TextLink {
 public:
 
-  TextLink(int xMinA, int yMinA, int xMaxA, int yMaxA, Link *linkA)
+  TextLink(int xMinA, int yMinA, int xMaxA, int yMaxA, AnnotLink *linkA)
     { xMin = xMinA; yMin = yMinA; xMax = xMaxA; yMax = yMaxA; link = linkA; }
   ~TextLink() {}
 
   int xMin, yMin, xMax, yMax;
-  Link *link;
+  AnnotLink *link;
 };
 
 //------------------------------------------------------------------------
@@ -2337,7 +2338,7 @@ void TextPage::addUnderline(double x0, double y0, double x1, double y1) {
   underlines->append(new TextUnderline(x0, y0, x1, y1));
 }
 
-void TextPage::addLink(int xMin, int yMin, int xMax, int yMax, Link *link) {
+void TextPage::addLink(int xMin, int yMin, int xMax, int yMax, AnnotLink *link) {
   links->append(new TextLink(xMin, yMin, xMax, yMax, link));
 }
 
@@ -5347,7 +5348,7 @@ void TextOutputDev::eoFill(GfxState *state) {
   fill(state);
 }
 
-void TextOutputDev::processLink(Link *link, Catalog * /*catalog*/) {
+void TextOutputDev::processLink(AnnotLink *link, Catalog * /*catalog*/) {
   double x1, y1, x2, y2;
   int xMin, yMin, xMax, yMax, x, y;
 
diff --git a/poppler/TextOutputDev.h b/poppler/TextOutputDev.h
index 438aee4..5bbcdfb 100644
--- a/poppler/TextOutputDev.h
+++ b/poppler/TextOutputDev.h
@@ -42,7 +42,7 @@ class Gfx;
 class GfxFont;
 class GfxState;
 class UnicodeMap;
-class Link;
+class AnnotLink;
 
 class TextWord;
 class TextPool;
@@ -160,7 +160,7 @@ public:
   GBool getSpaceAfter() { return spaceAfter; }
 #endif
   GBool isUnderlined() { return underlined; }
-  Link *getLink() { return link; }
+  AnnotLink *getLink() { return link; }
   double getEdge(int i) { return edge[i]; }
   double getBaseline () { return base; }
   GBool hasSpaceAfter  () { return spaceAfter; }
@@ -194,7 +194,7 @@ private:
 #endif
 
   GBool underlined;
-  Link *link;
+  AnnotLink *link;
 
   friend class TextPool;
   friend class TextLine;
@@ -510,7 +510,7 @@ public:
   void addUnderline(double x0, double y0, double x1, double y1);
 
   // Add a hyperlink.
-  void addLink(int xMin, int yMin, int xMax, int yMax, Link *link);
+  void addLink(int xMin, int yMin, int xMax, int yMax, AnnotLink *link);
 
   // Coalesce strings that look like parts of the same line.
   void coalesce(GBool physLayout, GBool doHTML);
@@ -727,7 +727,7 @@ public:
   virtual void eoFill(GfxState *state);
 
   //----- link borders
-  virtual void processLink(Link *link, Catalog *catalog);
+  virtual void processLink(AnnotLink *link, Catalog *catalog);
 
   //----- special access
 
diff --git a/qt4/src/poppler-link-extractor-private.h b/qt4/src/poppler-link-extractor-private.h
index 284f33c..234ff6b 100644
--- a/qt4/src/poppler-link-extractor-private.h
+++ b/qt4/src/poppler-link-extractor-private.h
@@ -40,7 +40,7 @@ class LinkExtractorOutputDev : public OutputDev
     virtual GBool upsideDown() { return gFalse; }
     virtual GBool useDrawChar() { return gFalse; }
     virtual GBool interpretType3Chars() { return gFalse; }
-    virtual void processLink(::Link *link, Catalog *catalog);
+    virtual void processLink(::AnnotLink *link, Catalog *catalog);
 
     // our stuff
     QList< Link* > links();
diff --git a/qt4/src/poppler-link-extractor.cc b/qt4/src/poppler-link-extractor.cc
index e9806b5..f10a16a 100644
--- a/qt4/src/poppler-link-extractor.cc
+++ b/qt4/src/poppler-link-extractor.cc
@@ -23,6 +23,7 @@
 #include <Link.h>
 #include <Object.h>
 #include <Page.h>
+#include <Annot.h>
 
 #include "poppler-qt4.h"
 #include "poppler-page-private.h"
@@ -48,7 +49,7 @@ LinkExtractorOutputDev::~LinkExtractorOutputDev()
   qDeleteAll(m_links);
 }
 
-void LinkExtractorOutputDev::processLink(::Link *link, Catalog *catalog)
+void LinkExtractorOutputDev::processLink(::AnnotLink *link, Catalog *catalog)
 {
   if (!link->isOk())
     return;
diff --git a/qt4/src/poppler-page.cc b/qt4/src/poppler-page.cc
index b0821cb..3ca8c07 100644
--- a/qt4/src/poppler-page.cc
+++ b/qt4/src/poppler-page.cc
@@ -558,7 +558,6 @@ QList<Annotation*> Page::annotations() const
     const uint numAnnotations = annots->getNumAnnots();
     if ( numAnnotations == 0 )
     {
-        delete annots;
         return QList<Annotation*>();
     }
 
@@ -907,11 +906,9 @@ QList<Annotation*> Page::annotations() const
                 // TODO
 
                 // reading link action
-                if ( !linkann->getDest()->isNull() )
+                if ( linkann->getAction() )
                 {
-                    ::LinkAction *act = ::LinkAction::parseDest( linkann->getDest() );
-                    Link * popplerLink = m_page->convertLinkActionToLink( act, QRectF() );
-                    delete act;
+                    Link * popplerLink = m_page->convertLinkActionToLink( linkann->getAction(), QRectF() );
                     if ( popplerLink )
                     {
                         l->setLinkDestination( popplerLink );
@@ -1301,7 +1298,6 @@ QList<Annotation*> Page::annotations() const
         }
     }
 
-    delete annots;
     /** 5 - finally RETURN ANNOTATIONS */
     return annotationsMap.values();
 }
@@ -1310,7 +1306,7 @@ QList<FormField*> Page::formFields() const
 {
   QList<FormField*> fields;
   ::Page *p = m_page->page;
-  ::FormPageWidgets * form = p->getPageWidgets();
+  ::FormPageWidgets * form = p->getFormWidgets(m_page->parentDoc->doc->getCatalog());
   int formcount = form->getNumWidgets();
   for (int i = 0; i < formcount; ++i)
   {
@@ -1343,6 +1339,8 @@ QList<FormField*> Page::formFields() const
       fields.append(ff);
   }
 
+  delete form;
+
   return fields;
 }
 
diff --git a/utils/HtmlOutputDev.cc b/utils/HtmlOutputDev.cc
index ede5700..19c1e5f 100644
--- a/utils/HtmlOutputDev.cc
+++ b/utils/HtmlOutputDev.cc
@@ -52,6 +52,7 @@
 #include "Error.h"
 #include "GfxState.h"
 #include "Page.h"
+#include "Annot.h"
 #include "PNGWriter.h"
 #ifdef ENABLE_LIBJPEG
 #include "DCTStream.h"
@@ -1395,10 +1396,10 @@ void HtmlOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
 
 
 
-void HtmlOutputDev::doProcessLink(Link* link){
+void HtmlOutputDev::doProcessLink(AnnotLink* link){
   double _x1,_y1,_x2,_y2;
   int x1,y1,x2,y2;
-  
+
   link->getRect(&_x1,&_y1,&_x2,&_y2);
   cvtUserToDev(_x1,_y1,&x1,&y1);
   
@@ -1411,7 +1412,7 @@ void HtmlOutputDev::doProcessLink(Link* link){
   delete _dest;
 }
 
-GooString* HtmlOutputDev::getLinkDest(Link *link,Catalog* catalog){
+GooString* HtmlOutputDev::getLinkDest(AnnotLink *link,Catalog* catalog){
   char *p;
   switch(link->getAction()->getKind()) 
   {
diff --git a/utils/HtmlOutputDev.h b/utils/HtmlOutputDev.h
index 7afffa5..e6be587 100644
--- a/utils/HtmlOutputDev.h
+++ b/utils/HtmlOutputDev.h
@@ -300,8 +300,8 @@ private:
   // convert encoding into a HTML standard, or encoding->getCString if not
   // recognized
   static char* mapEncodingToHtml(GooString* encoding);
-  void doProcessLink(Link *link);
-  GooString* getLinkDest(Link *link,Catalog *catalog);
+  void doProcessLink(AnnotLink *link);
+  GooString* getLinkDest(AnnotLink *link,Catalog *catalog);
   void dumpMetaVars(FILE *);
   void doFrame(int firstPage);
   GBool newOutlineLevel(FILE *output, Object *node, Catalog* catalog, int level = 1);


More information about the poppler mailing list