[poppler] 2 commits - poppler/Annot.cc poppler/Annot.h poppler/Form.cc

Carlos Garcia Campos carlosgc at kemper.freedesktop.org
Wed Mar 9 11:22:59 PST 2011


 poppler/Annot.cc |  122 ++++++++++++++++++++++---------------------------------
 poppler/Annot.h  |    3 -
 poppler/Form.cc  |    7 +--
 3 files changed, 54 insertions(+), 78 deletions(-)

New commits:
commit 59fb0489bfabfd8acccafdcd0361ce005664962a
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Wed Mar 9 20:19:24 2011 +0100

    annots: Check whether we need to create an appearance stream in AnnotWidget::draw()
    
    And never modify the AP entry since it breaks check and radio buttons
    that doesn't have an appearance for the Off state.

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 881b9d5..036f15a 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -2726,19 +2726,7 @@ AnnotWidget::~AnnotWidget() {
 void AnnotWidget::initialize(XRef *xrefA, Catalog *catalog, Dict *dict) {
   Object obj1;
 
-  if ((form = catalog->getForm ())) {
-    // 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 (field != NULL && (field->getType () == formText || field->getType () == formChoice)) {
-      regen = form->getNeedAppearances ();
-    }
-  }
-
-  // If field doesn't have an AP we'll have to generate it
-  if (appearance.isNone () || appearance.isNull ())
-    regen = gTrue;
+  form = catalog->getForm();
 
   if(dict->lookup("H", &obj1)->isName()) {
     const char *modeName = obj1.getName();
@@ -3770,25 +3758,9 @@ void AnnotWidget::drawFormFieldChoice(GfxResources *resources, GooString *da) {
 
 void AnnotWidget::generateFieldAppearance() {
   Object appearDict, obj1, obj2;
-  Dict *annot;
   GfxResources *resources;
   MemStream *appearStream;
   GooString *da;
-  GBool modified;
-
-  if (field == NULL)
-    return;
-
-  annot = annotObj.getDict ();
-
-  // do not regenerate appearence if widget has not changed
-  modified = field->isModified ();
-
-  // only regenerate when it doesn't have an AP or
-  // it already has an AP but widget has been modified
-  if (!regen && !modified) {
-    return;
-  }
 
   appearBuf = new GooString ();
 
@@ -3857,42 +3829,6 @@ void AnnotWidget::generateFieldAppearance() {
   delete appearBuf;
 
   appearStream->setNeedFree(gTrue);
-
-  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
-    if (annot->lookup("AP", &obj1)->isDict() &&
-        obj1.dictLookupNF("N", &obj2)->isRef()) {
-      appRef = obj2.getRef();
-    }
-
-    obj2.free();
-    obj1.free();
-
-    // this annot doesn't have an AP yet, create one
-    if (appRef.num == 0)
-      appRef = xref->addIndirectObject(&appearance);
-    else // since we reuse the already existing AP, we have to notify the xref about this update
-      xref->setModifiedObject(&appearance, appRef);
-
-    // update object's AP and AS
-    Object apObj;
-    apObj.initDict(xref);
-
-    Object oaRef;
-    oaRef.initRef(appRef.num, appRef.gen);
-
-    apObj.dictSet("N", &oaRef);
-    annot->set("AP", &apObj);
-    Dict* d = new Dict(annot);
-    d->decRef();
-    Object dictObj;
-    dictObj.initDict(d);
-
-    xref->setModifiedObject(&dictObj, ref);
-    dictObj.free();
-  }
 }
 
 
@@ -3903,7 +3839,18 @@ void AnnotWidget::draw(Gfx *gfx, GBool printing) {
     return;
 
   addDingbatsResource = gFalse;
-  generateFieldAppearance ();
+
+  // Only construct the appearance stream when
+  // - annot doesn't have an AP or
+  // - it's a field containing text (text and choices) and
+  // - NeedAppearances is true or
+  // - widget has been modified or
+  if (field) {
+    if (appearance.isNull() ||
+        (((field->getType() == formText || field->getType() == formChoice)) &&
+         ((form && form->getNeedAppearances()) || field->isModified())))
+      generateFieldAppearance();
+  }
 
   // draw the appearance stream
   appearance.fetch(xref, &obj);
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 8cd3aa8..93f82bf 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -1174,7 +1174,6 @@ private:
   // inherited  from Annot
   // AnnotBorderBS border;                // BS
   Dict *parent;                           // Parent
-  GBool regen;
   GBool addDingbatsResource;
 };
 
commit f3b00ef51ceef6d9b7a1aa7e0f19249abf8ca6f3
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Wed Mar 9 18:19:12 2011 +0100

    annots: Add Annot::setAppearanceState() and use it from FormWidget
    
    This method not only updates the current appearance state, but also the
    appearance stream corresponding to the new state.

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index b8acbab..881b9d5 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -1078,6 +1078,40 @@ void Annot::setPage(Ref *pageRef, int pageIndex)
   page = pageIndex;
 }
 
+void Annot::setAppearanceState(char *state) {
+  if (!state)
+    return;
+
+  if (appearState && appearState->cmp(state) == 0)
+    return;
+
+  delete appearState;
+  appearState = new GooString(state);
+
+  Object obj1;
+  obj1.initName(state);
+  update ("AS", &obj1);
+
+  // The appearance state determines the current appearance stream
+  Object obj2;
+  if (annotObj.dictLookup("AP", &obj2)->isDict()) {
+    Object obj3;
+
+    if (obj2.dictLookup("N", &obj3)->isDict()) {
+      Object obj4;
+
+      appearance.free();
+      if (obj3.dictLookupNF(state, &obj4)->isRef())
+        obj4.copy(&appearance);
+      else
+        appearance.initNull();
+      obj4.free();
+    }
+    obj3.free();
+  }
+  obj2.free();
+}
+
 double Annot::getXMin() {
   return rect->x1;
 }
@@ -3655,8 +3689,6 @@ void AnnotWidget::drawBorder() {
 }
 
 void AnnotWidget::drawFormFieldButton(GfxResources *resources, GooString *da) {
-  Object obj1;
-  Dict *annot = annotObj.getDict();
   GooString *caption = NULL;
   if (appearCharacs)
     caption = appearCharacs->getNormalCaption();
@@ -3665,7 +3697,7 @@ void AnnotWidget::drawFormFieldButton(GfxResources *resources, GooString *da) {
   case formButtonRadio: {
     //~ Acrobat doesn't draw a caption if there is no AP dict (?)
     char *buttonState = static_cast<FormFieldButton *>(field)->getAppearanceState();
-    if (buttonState && annot->lookup("AS", &obj1)->isName(buttonState) &&
+    if (buttonState && appearState && appearState->cmp(buttonState) == 0 &&
         strcmp (buttonState, "Off") != 0) {
       if (caption) {
         drawText(caption, da, resources, gFalse, 0, fieldQuadCenter,
@@ -3680,7 +3712,6 @@ void AnnotWidget::drawFormFieldButton(GfxResources *resources, GooString *da) {
         }
       }
     }
-    obj1.free();
   }
     break;
   case formButtonPush:
@@ -3688,8 +3719,7 @@ void AnnotWidget::drawFormFieldButton(GfxResources *resources, GooString *da) {
       drawText(caption, da, resources, gFalse, 0, fieldQuadCenter, gFalse, gFalse);
     break;
   case formButtonCheck:
-    if (annot->lookup("AS", &obj1)->isName() &&
-        strcmp(obj1.getName(), "Off") != 0) {
+    if (appearState && appearState->cmp("Off") != 0) {
       if (!caption) {
         GooString checkMark("3");
         drawText(&checkMark, da, resources, gFalse, 0, fieldQuadCenter, gFalse, gTrue);
@@ -3697,7 +3727,6 @@ void AnnotWidget::drawFormFieldButton(GfxResources *resources, GooString *da) {
         drawText(caption, da, resources, gFalse, 0, fieldQuadCenter, gFalse, gTrue);
       }
     }
-    obj1.free();
     break;
   }
 }
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 055fa21..8cd3aa8 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -483,6 +483,8 @@ public:
 
   void setPage(Ref *pageRef, int pageIndex);
 
+  void setAppearanceState(char *state);
+
   // getters
   XRef *getXRef() const { return xref; }
   GBool getHasRef() const { return hasRef; }
diff --git a/poppler/Form.cc b/poppler/Form.cc
index bc816d1..c2525f0 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -223,10 +223,9 @@ FormButtonType FormWidgetButton::getButtonType () const
 }
 
 void FormWidgetButton::setAppearanceState(char *state) {
-  Object obj1;
-  obj1.initName(state);
-  obj.getDict()->set("AS", &obj1);
-  xref->setModifiedObject(&obj, ref);
+  if (!widget)
+    return;
+  widget->setAppearanceState(state);
 }
 
 void FormWidgetButton::setState (GBool astate, GBool calledByParent)


More information about the poppler mailing list