[poppler] poppler/Annot.cc poppler/Annot.h poppler/Catalog.cc poppler/Form.cc poppler/Form.h

Carlos Garcia Campos carlosgc at kemper.freedesktop.org
Wed Mar 9 08:39:58 PST 2011


 poppler/Annot.cc   |   42 ++++++++++++--------
 poppler/Annot.h    |    2 
 poppler/Catalog.cc |    2 
 poppler/Form.cc    |  107 ++++++++++++++++++++++++-----------------------------
 poppler/Form.h     |   23 +++++------
 5 files changed, 89 insertions(+), 87 deletions(-)

New commits:
commit d59561212253302d4dcb23392bb8306b8e5c68d1
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Wed Mar 9 17:35:28 2011 +0100

    forms: Make FormWidget use a real widget annotation instead of duplicating code
    
    When creating annotations, if it's a widget annotation, look first
    whether it has already been created by a FormWidget and reuse it instead
    of duplicating it.

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index ef1aa64..b8acbab 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -2664,7 +2664,14 @@ void AnnotTextMarkup::draw(Gfx *gfx, GBool printing) {
 AnnotWidget::AnnotWidget(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj) :
     Annot(xrefA, dict, catalog, obj) {
   type = typeWidget;
-  widget = NULL;
+  field = NULL;
+  initialize(xrefA, catalog, dict);
+}
+
+AnnotWidget::AnnotWidget(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj, FormField *fieldA) :
+    Annot(xrefA, dict, catalog, obj) {
+  type = typeWidget;
+  field = fieldA;
   initialize(xrefA, catalog, dict);
 }
 
@@ -2686,13 +2693,11 @@ void AnnotWidget::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
   Object obj1;
 
   if ((form = catalog->getForm ())) {
-    widget = form->findWidgetByRef (ref);
-
     // check if field apperances need to be regenerated
     // Only text or choice fields needs to have appearance regenerated
     // see section 8.6.2 "Variable Text" of PDFReference
     regen = gFalse;
-    if (widget != NULL && (widget->getType () == formText || widget->getType () == formChoice)) {
+    if (field != NULL && (field->getType () == formText || field->getType () == formChoice)) {
       regen = form->getNeedAppearances ();
     }
   }
@@ -3651,7 +3656,7 @@ void AnnotWidget::drawBorder() {
 
 void AnnotWidget::drawFormFieldButton(GfxResources *resources, GooString *da) {
   Object obj1;
-  Dict *annot = widget->getObj()->getDict();
+  Dict *annot = annotObj.getDict();
   GooString *caption = NULL;
   if (appearCharacs)
     caption = appearCharacs->getNormalCaption();
@@ -3736,22 +3741,19 @@ void AnnotWidget::drawFormFieldChoice(GfxResources *resources, GooString *da) {
 
 void AnnotWidget::generateFieldAppearance() {
   Object appearDict, obj1, obj2;
-  Dict *fieldDict;
   Dict *annot;
   GfxResources *resources;
   MemStream *appearStream;
   GooString *da;
   GBool modified;
 
-  if (widget == NULL || !widget->getField () || !widget->getField ()->getObj ()->isDict ())
+  if (field == NULL)
     return;
 
-  field = widget->getField();
-  fieldDict = field->getObj()->getDict();
-  annot = widget->getObj ()->getDict ();
+  annot = annotObj.getDict ();
 
   // do not regenerate appearence if widget has not changed
-  modified = widget->isModified ();
+  modified = field->isModified ();
 
   // only regenerate when it doesn't have an AP or
   // it already has an AP but widget has been modified
@@ -3827,7 +3829,7 @@ void AnnotWidget::generateFieldAppearance() {
 
   appearStream->setNeedFree(gTrue);
 
-  if (widget->isModified()) {
+  if (field->isModified()) {
     //create a new object that will contains the new appearance
     
     //if we already have a N entry in our AP dict, reuse it
@@ -5133,7 +5135,7 @@ void Annots::appendAnnot(Annot *annot) {
 }
 
 Annot *Annots::createAnnot(XRef *xref, Dict* dict, Catalog *catalog, Object *obj) {
-  Annot *annot;
+  Annot *annot = NULL;
   Object obj1;
 
   if (dict->lookup("Subtype", &obj1)->isName()) {
@@ -5176,7 +5178,17 @@ Annot *Annots::createAnnot(XRef *xref, Dict* dict, Catalog *catalog, Object *obj
     } else if(!strcmp(typeName, "Movie")) {
       annot = new AnnotMovie(xref, dict, catalog, obj);
     } else if(!strcmp(typeName, "Widget")) {
-      annot = new AnnotWidget(xref, dict, catalog, obj);
+      // Find the annot in forms
+      if (obj->isRef()) {
+        Form *form = catalog->getForm();
+        FormWidget *widget = form->findWidgetByRef(obj->getRef());
+        if (widget) {
+          annot = widget->getWidgetAnnotation();
+          annot->incRefCnt();
+        }
+      }
+      if (!annot)
+        annot = new AnnotWidget(xref, dict, catalog, obj);
     } else if(!strcmp(typeName, "Screen")) {
       annot = new AnnotScreen(xref, dict, catalog, obj);
     } else if(!strcmp(typeName, "PrinterMark")) {
@@ -5203,8 +5215,6 @@ Annot *Annots::createAnnot(XRef *xref, Dict* dict, Catalog *catalog, Object *obj
     } else {
       annot = new Annot(xref, dict, catalog, obj);
     }
-  } else {
-    annot = NULL;
   }
   obj1.free();
 
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 3126e53..055fa21 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -1131,6 +1131,7 @@ public:
   };
 
   AnnotWidget(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj);
+  AnnotWidget(XRef *xrefA, Dict *dict, Catalog *catalog, Object *obj, FormField *fieldA);
   virtual ~AnnotWidget();
 
   virtual void draw(Gfx *gfx, GBool printing);
@@ -1163,7 +1164,6 @@ private:
   void writeString(GooString *str, GooString *appearBuf);
 
   Form *form;
-  FormWidget *widget;                     // FormWidget object for this annotation
   FormField *field;                       // FormField object for this annotation
   AnnotWidgetHighlightMode mode;          // H  (Default I)
   AnnotAppearanceCharacs *appearCharacs;  // MK
diff --git a/poppler/Catalog.cc b/poppler/Catalog.cc
index 297cac5..d489b10 100644
--- a/poppler/Catalog.cc
+++ b/poppler/Catalog.cc
@@ -111,7 +111,7 @@ Catalog::Catalog(XRef *xrefA) {
 
   // perform form-related loading after all widgets have been loaded
   if (getForm())
-    getForm()->postWidgetsLoad();
+    getForm()->postWidgetsLoad(this);
 
   catDict.free();
   return;
diff --git a/poppler/Form.cc b/poppler/Form.cc
index 2af8d3d..bc816d1 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -63,70 +63,46 @@ char* pdfDocEncodingToUTF16 (GooString* orig, int* length)
 
 FormWidget::FormWidget(XRef *xrefA, Object *aobj, unsigned num, Ref aref, FormField *fieldA) 
 {
-  Object obj1, obj2;
   ref = aref;
-  double t;
   ID = 0;
-  fontSize = 0.0;
   childNum = num;
   xref = xrefA;
   aobj->copy(&obj);
   type = formUndef;
   field = fieldA;
-  Dict *dict = obj.getDict();
-
-  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();
-  //swap coords if needed
-  if (x1 > x2) {
-    t = x1;
-    x1 = x2;
-    x2 = t;
-  }
-  if (y1 > y2) {
-    t = y1;
-    y1 = y2;
-    y2 = t;
-  }
-  
-  err1:
-    obj2.free();  
-  err2:
-    obj1.free();
+  widget = NULL;
 }
 
 FormWidget::~FormWidget()
 {
+  if (widget)
+    widget->decRefCnt();
   obj.free ();
 }
 
+void FormWidget::createWidgetAnnotation(Catalog *catalog) {
+  if (widget)
+    return;
+
+  Object obj1;
+  obj1.initRef(ref.num, ref.gen);
+  widget = new AnnotWidget(xref, obj.getDict(), catalog, &obj1, field);
+  obj1.free();
+}
+
+GBool FormWidget::inRect(double x, double y) const {
+  return widget ? widget->inRect(x, y) : gFalse;
+}
+
+void FormWidget::getRect(double *x1, double *y1, double *x2, double *y2) const {
+  if (widget)
+    widget->getRect(x1, y1, x2, y2);
+}
+
+double FormWidget::getFontSize() const {
+  return widget ? widget->getFontSize() : 0.;
+}
+
 bool FormWidget::isReadOnly() const
 {
   return field->isReadOnly();
@@ -631,12 +607,22 @@ FormField::~FormField()
 
 void FormField::fillChildrenSiblingsID()
 {
-  if(terminal) return;
-  for (int i=0; i<numChildren; i++) {
+  if (terminal)
+    return;
+  for (int i = 0; i < numChildren; i++) {
     children[i]->fillChildrenSiblingsID();
   }
 }
 
+void FormField::createWidgetAnnotations(Catalog *catalog) {
+  if (terminal) {
+    for (int i = 0; i < numChildren; i++)
+      widgets[i]->createWidgetAnnotation(catalog);
+  } else {
+    for (int i = 0; i < numChildren; i++)
+      children[i]->createWidgetAnnotations(catalog);
+  }
+}
 
 void FormField::_createWidget (Object *obj, Ref aref)
 {
@@ -1336,11 +1322,16 @@ FormField *Form::createFieldFromDict (Object* obj, XRef *xrefA, const Ref& pref,
     return field;
 }
 
-void Form::postWidgetsLoad ()
+void Form::postWidgetsLoad (Catalog *catalog)
 {
- for(int i=0; i<numFields; i++) {
-   rootFields[i]->fillChildrenSiblingsID(); 
- }
+  // We create the widget annotations associated to
+  // every form widget here, because the AnnotWidget constructor
+  // needs the form object that gets from the catalog. When constructing
+  // a FormWidget the Catalog is still creating the form object
+  for (int i = 0; i < numFields; i++) {
+    rootFields[i]->fillChildrenSiblingsID();
+    rootFields[i]->createWidgetAnnotations(catalog);
+  }
 }
 
 FormWidget* Form::findWidgetByRef (Ref aref)
@@ -1370,6 +1361,9 @@ FormPageWidgets::FormPageWidgets (Annots *annots, unsigned int page, Form *form)
     for (int i = 0; i < size; ++i) {
       Annot *annot = annots->getAnnot(i);
 
+      if (annot->getType() != Annot::typeWidget)
+        continue;
+
       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 
@@ -1385,7 +1379,6 @@ FormPageWidgets::FormPageWidgets (Annots *annots, unsigned int page, Form *form)
       if (tmp) {
         // We've found a corresponding form field, link it
         tmp->setID(FormWidget::encodeID(page, numWidgets));
-        tmp->setFontSize(annot->getFontSize());
         widgets[numWidgets++] = tmp;
       }
     }
diff --git a/poppler/Form.h b/poppler/Form.h
index b5b4edd..f7bf33e 100644
--- a/poppler/Form.h
+++ b/poppler/Form.h
@@ -27,6 +27,7 @@ class GooString;
 class Array;
 class Dict;
 class Annot;
+class AnnotWidget;
 class Annots;
 class Catalog;
 class LinkAction;
@@ -70,12 +71,10 @@ public:
   virtual ~FormWidget();
 
   // Check if point is inside the field bounding rect
-  GBool inRect(double x, double y)
-    { return x1 <= x && x <= x2 && y1 <= y && y <= y2; }
+  GBool inRect(double x, double y) const;
 
   // Get the field bounding rect
-  void getRect(double *xa1, double *ya1, double *xa2, double *ya2)
-    { *xa1 = x1; *ya1 = y1; *xa2 = x2; *ya2 = y2; }
+  void getRect(double *x1, double *y1, double *x2, double *y2) const;
 
   unsigned getID () { return ID; }
   void setID (unsigned int i) { ID=i; }
@@ -89,8 +88,7 @@ public:
   void setChildNum (unsigned i) { childNum = i; }
   unsigned getChildNum () { return childNum; }
 
-  void setFontSize(double f) { fontSize = f; }
-  double getFontSize () { return fontSize; }
+  double getFontSize() const;
 
   GooString *getPartialName() const;
   GooString *getAlternateUiName() const;
@@ -108,11 +106,15 @@ public:
   // decode id and retrieve pageNum and fieldNum
   static void decodeID (unsigned id, unsigned* pageNum, unsigned* fieldNum);
 
+  void createWidgetAnnotation(Catalog *catalog);
+  AnnotWidget *getWidgetAnnotation() const { return widget; }
+
 protected:
   FormWidget(XRef *xrefA, Object *aobj, unsigned num, Ref aref, FormField *fieldA);
 
   void updateField (const char *key, Object *value);
 
+  AnnotWidget *widget;
   FormField* field;
   FormFieldType type;
   Object obj;
@@ -131,11 +133,6 @@ protected:
   (decoding) pageNum = id >> 4*sizeof(unsigned); fieldNum = (id << 4*sizeof(unsigned)) >> 4*sizeof(unsigned);
   */
   unsigned ID; 
-
-  double x1, y1;                // lower left corner
-  double x2, y2;                // upper right corner
-  double fontSize; //font size if this widget has text
-
 };
 
 //------------------------------------------------------------------------
@@ -285,6 +282,8 @@ public:
   // only implemented in FormFieldButton
   virtual void fillChildrenSiblingsID ();
 
+  void createWidgetAnnotations(Catalog *catalog);
+
 
  protected:
   void _createWidget (Object *obj, Ref aref);
@@ -486,7 +485,7 @@ public:
 
   FormWidget* findWidgetByRef (Ref aref);
 
-  void postWidgetsLoad();
+  void postWidgetsLoad(Catalog *catalog);
 private:
   FormField** rootFields;
   int numFields;


More information about the poppler mailing list