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

Carlos Garcia Campos carlosgc at kemper.freedesktop.org
Sun Mar 6 09:08:18 PST 2011


 poppler/Annot.cc |  552 ++++++++++++++++++++++++-------------------------------
 poppler/Annot.h  |   12 -
 poppler/Form.cc  |    5 
 poppler/Form.h   |    5 
 4 files changed, 265 insertions(+), 309 deletions(-)

New commits:
commit c198a3f83d8508ddaf84564871d9202ffba8096c
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sun Mar 6 17:52:01 2011 +0100

    annots: Use the field object to get the top index of a form field choice
    
    Instead of parsing the field dictionary again.

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 247a474..d0d9798 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -3367,7 +3367,6 @@ void AnnotWidget::drawText(GooString *text, GooString *da, GfxFontDict *fontDict
 
 // Draw the variable text or caption for a field.
 void AnnotWidget::drawListBox(FormFieldChoice *fieldChoice,
-			      int topIdx,
 			      GooString *da, GfxFontDict *fontDict, int quadding) {
   GooList *daToks;
   GooString *tok, *convertedText;
@@ -3460,7 +3459,7 @@ void AnnotWidget::drawListBox(FormFieldChoice *fieldChoice,
   }
   // draw the text
   y = rect->y2 - rect->y1 - 1.1 * fontSize;
-  for (i = topIdx; i < fieldChoice->getNumChoices(); ++i) {
+  for (i = fieldChoice->getTopIndex(); i < fieldChoice->getNumChoices(); ++i) {
     // setup
     appearBuf->append("q\n");
 
@@ -3740,16 +3739,7 @@ void AnnotWidget::drawFormFieldChoice(GfxFontDict *fontDict, GooString *da) {
     obj1.free();
   // list box
   } else {
-    // get the top index
-    int topIdx;
-    if (fieldDict->lookup("TI", &obj1)->isInt()) {
-      topIdx = obj1.getInt();
-    } else {
-      topIdx = 0;
-    }
-    obj1.free();
-
-    drawListBox(fieldChoice, topIdx, da, fontDict, quadding);
+    drawListBox(fieldChoice, da, fontDict, quadding);
   }
 }
 
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 3e80788..7776119 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -1156,7 +1156,6 @@ private:
 		GBool txField, GBool forceZapfDingbats,
 		GBool password=false);
   void drawListBox(FormFieldChoice *fieldChoice,
-		   int topIdx,
 		   GooString *da, GfxFontDict *fontDict, int quadding);
   void layoutText(GooString *text, GooString *outBuf, int *i, GfxFont *font,
 		  double *width, double widthLimit, int *charCount,
commit 5cf803ec181dbf1112f67b4f4a9c77b88d102e3b
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sun Mar 6 17:47:18 2011 +0100

    forms: Add FormFieldChoice::getTopIndex()

diff --git a/poppler/Form.cc b/poppler/Form.cc
index 9f83063..09848b2 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -1113,6 +1113,7 @@ FormFieldChoice::FormFieldChoice(XRef *xrefA, Object *aobj, const Ref& ref, std:
   numChoices = 0;
   choices = NULL;
   editedChoice = NULL;
+  topIdx = 0;
 
   Dict* dict = obj.getDict();
   Object obj1;
@@ -1134,6 +1135,10 @@ FormFieldChoice::FormFieldChoice(XRef *xrefA, Object *aobj, const Ref& ref, std:
   }
   obj1.free();
 
+  if (dict->lookup("TI", &obj1)->isInt())
+    topIdx = obj1.getInt();
+  obj1.free();
+
 }
 
 FormFieldChoice::~FormFieldChoice()
diff --git a/poppler/Form.h b/poppler/Form.h
index 26fad52..f3938d1 100644
--- a/poppler/Form.h
+++ b/poppler/Form.h
@@ -402,6 +402,8 @@ public:
   bool commitOnSelChange () const { return doCommitOnSelChange; }
   bool isListBox () const { return !combo; }
 
+  int getTopIndex() const { return topIdx; }
+
   /* these functions _must_ only be used by FormWidgetChoice */
   void _setNumChoices (int i) { numChoices = i; }
   void _createChoicesTab ();
@@ -423,7 +425,8 @@ protected:
 
   int numChoices;
   ChoiceOpt* choices;
-  GooString* editedChoice; 
+  GooString* editedChoice;
+  int topIdx; // TI
 };
 
 //------------------------------------------------------------------------
commit 1248f59e2045749ece1f5a5e579b866b8330a752
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sun Mar 6 17:41:33 2011 +0100

    annots: Draw widget background using the existing appearance characteristics
    
    Instead of parsing the appearance characteristics dictionary again

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 58dc458..247a474 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -3754,11 +3754,10 @@ void AnnotWidget::drawFormFieldChoice(GfxFontDict *fontDict, GooString *da) {
 }
 
 void AnnotWidget::generateFieldAppearance() {
-  Object mkObj, ftObj, appearDict, drObj, obj1, obj2, obj3;
+  Object appearDict, drObj, obj1, obj2;
   Dict *fieldDict;
   Dict *annot;
   Dict *acroForm;
-  Dict *mkDict;
   MemStream *appearStream;
   GfxFontDict *fontDict;
   GooString *da;
@@ -3782,22 +3781,15 @@ void AnnotWidget::generateFieldAppearance() {
   }
 
   appearBuf = new GooString ();
-  // get the appearance characteristics (MK) dictionary
-  if (annot->lookup("MK", &mkObj)->isDict()) {
-    mkDict = mkObj.getDict();
-  } else {
-    mkDict = NULL;
-  }
+
   // draw the background
-  if (mkDict) {
-    if (mkDict->lookup("BG", &obj1)->isArray() &&
-        obj1.arrayGetLength() > 0) {
-      AnnotColor aColor = AnnotColor (obj1.getArray());
-      setColor(&aColor, gTrue);
+  if (appearCharacs) {
+    AnnotColor *aColor = appearCharacs->getBackColor();
+    if (aColor) {
+      setColor(aColor, gTrue);
       appearBuf->appendf("0 0 {0:.2f} {1:.2f} re f\n",
-          rect->x2 - rect->x1, rect->y2 - rect->y1);
+                         rect->x2 - rect->x1, rect->y2 - rect->y1);
     }
-    obj1.free();
   }
 
   // draw the border
@@ -3918,7 +3910,6 @@ void AnnotWidget::generateFieldAppearance() {
   if (fontDict) {
     delete fontDict;
   }
-  mkObj.free();
 }
 
 
commit dc249ad4529997001ae1f96dcfd7351766ca8e8d
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sun Mar 6 17:34:33 2011 +0100

    annots: Factor out generateFieldAppearance()
    
    Adding methods to render every form field type and using the field
    object when possible instead of parsing the field dictionary again.

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 3f87080..58dc458 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -3366,8 +3366,8 @@ void AnnotWidget::drawText(GooString *text, GooString *da, GfxFontDict *fontDict
 }
 
 // Draw the variable text or caption for a field.
-void AnnotWidget::drawListBox(GooString **text, GBool *selection,
-			      int nOptions, int topIdx,
+void AnnotWidget::drawListBox(FormFieldChoice *fieldChoice,
+			      int topIdx,
 			      GooString *da, GfxFontDict *fontDict, int quadding) {
   GooList *daToks;
   GooString *tok, *convertedText;
@@ -3439,9 +3439,9 @@ void AnnotWidget::drawListBox(GooString **text, GBool *selection,
   // compute font autosize
   if (fontSize == 0) {
     wMax = 0;
-    for (i = 0; i < nOptions; ++i) {
+    for (i = 0; i < fieldChoice->getNumChoices(); ++i) {
       j = 0;
-      layoutText(text[i], convertedText, &j, font, &w, 0.0, NULL, gFalse);
+      layoutText(fieldChoice->getChoice(i), convertedText, &j, font, &w, 0.0, NULL, gFalse);
       if (w > wMax) {
         wMax = w;
       }
@@ -3460,12 +3460,12 @@ void AnnotWidget::drawListBox(GooString **text, GBool *selection,
   }
   // draw the text
   y = rect->y2 - rect->y1 - 1.1 * fontSize;
-  for (i = topIdx; i < nOptions; ++i) {
+  for (i = topIdx; i < fieldChoice->getNumChoices(); ++i) {
     // setup
     appearBuf->append("q\n");
 
     // draw the background if selected
-    if (selection[i]) {
+    if (fieldChoice->isSelected(i)) {
       appearBuf->append("0 g f\n");
       appearBuf->appendf("{0:.2f} {1:.2f} {2:.2f} {3:.2f} re f\n",
           borderWidth,
@@ -3479,7 +3479,7 @@ void AnnotWidget::drawListBox(GooString **text, GBool *selection,
 
     // compute text width and start position
     j = 0;
-    layoutText(text[i], convertedText, &j, font, &w, 0.0, NULL, gFalse);
+    layoutText(fieldChoice->getChoice(i), convertedText, &j, font, &w, 0.0, NULL, gFalse);
     w *= fontSize;
     switch (quadding) {
       case fieldQuadLeft:
@@ -3517,7 +3517,7 @@ void AnnotWidget::drawListBox(GooString **text, GBool *selection,
     }
 
     // change the text color if selected
-    if (selection[i]) {
+    if (fieldChoice->isSelected(i)) {
       appearBuf->append("1 g\n");
     }
 
@@ -3644,6 +3644,115 @@ void AnnotWidget::drawBorder() {
   }
 }
 
+void AnnotWidget::drawFormFieldButton(GfxFontDict *fontDict, GooString *da) {
+  Object obj1, obj2;
+  Dict *annot = widget->getObj()->getDict();
+  Dict *fieldDict = field->getObj()->getDict();
+  GooString *caption = NULL;
+  if (appearCharacs)
+    caption = appearCharacs->getNormalCaption();
+
+  switch (static_cast<FormFieldButton *>(field)->getButtonType()) {
+  case formButtonRadio:
+    //~ Acrobat doesn't draw a caption if there is no AP dict (?)
+    if (Form::fieldLookup(fieldDict, "V", &obj1)->isName()) {
+      if (annot->lookup("AS", &obj2)->isName(obj1.getName()) &&
+          strcmp (obj1.getName(), "Off") != 0) {
+        if (caption) {
+          drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter,
+                   gFalse, gTrue);
+        } else if (appearCharacs) {
+          AnnotColor *aColor = appearCharacs->getBorderColor();
+          if (aColor) {
+            double dx = rect->x2 - rect->x1;
+            double dy = rect->y2 - rect->y1;
+            setColor(aColor, gTrue);
+            drawCircle(0.5 * dx, 0.5 * dy, 0.2 * (dx < dy ? dx : dy), gTrue);
+          }
+        }
+      }
+      obj2.free();
+    }
+    obj1.free();
+    break;
+  case formButtonPush:
+    if (caption)
+      drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter, gFalse, gFalse);
+    break;
+  case formButtonCheck:
+    if (annot->lookup("AS", &obj1)->isName() &&
+        strcmp(obj1.getName(), "Off") != 0) {
+      if (!caption) {
+        GooString checkMark("3");
+        drawText(&checkMark, da, fontDict, gFalse, 0, fieldQuadCenter, gFalse, gTrue);
+      } else {
+        drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter, gFalse, gTrue);
+      }
+    }
+    obj1.free();
+    break;
+  }
+}
+
+void AnnotWidget::drawFormFieldText(GfxFontDict *fontDict, GooString *da) {
+  Object obj1, obj2;
+  int quadding;
+  Dict *fieldDict = field->getObj()->getDict();
+  FormFieldText *fieldText = static_cast<FormFieldText *>(field);
+
+  if (Form::fieldLookup(fieldDict, "V", &obj1)->isString()) {
+    if (Form::fieldLookup(fieldDict, "Q", &obj2)->isInt())
+      quadding = obj2.getInt();
+    else
+      quadding = fieldQuadLeft;
+    obj2.free();
+
+    int comb = 0;
+    if (fieldText->isComb()) {
+      if (Form::fieldLookup(fieldDict, "MaxLen", &obj2)->isInt())
+        comb = obj2.getInt();
+      obj2.free();
+    }
+    drawText(obj1.getString(), da, fontDict,
+             fieldText->isMultiline(), comb, quadding, gTrue, gFalse, fieldText->isPassword());
+  }
+  obj1.free();
+}
+
+void AnnotWidget::drawFormFieldChoice(GfxFontDict *fontDict, GooString *da) {
+  Object obj1;
+  Dict *fieldDict = field->getObj()->getDict();
+  int quadding;
+  FormFieldChoice *fieldChoice = static_cast<FormFieldChoice *>(field);
+
+  if (Form::fieldLookup(fieldDict, "Q", &obj1)->isInt()) {
+    quadding = obj1.getInt();
+  } else {
+    quadding = fieldQuadLeft;
+  }
+  obj1.free();
+
+  if (fieldChoice->isCombo()) {
+    if (Form::fieldLookup(fieldDict, "V", &obj1)->isString()) {
+      drawText(obj1.getString(), da, fontDict, gFalse, 0, quadding, gTrue, gFalse);
+      //~ Acrobat draws a popup icon on the right side
+    }
+    obj1.free();
+  // list box
+  } else {
+    // get the top index
+    int topIdx;
+    if (fieldDict->lookup("TI", &obj1)->isInt()) {
+      topIdx = obj1.getInt();
+    } else {
+      topIdx = 0;
+    }
+    obj1.free();
+
+    drawListBox(fieldChoice, topIdx, da, fontDict, quadding);
+  }
+}
+
 void AnnotWidget::generateFieldAppearance() {
   Object mkObj, ftObj, appearDict, drObj, obj1, obj2, obj3;
   Dict *fieldDict;
@@ -3652,15 +3761,8 @@ void AnnotWidget::generateFieldAppearance() {
   Dict *mkDict;
   MemStream *appearStream;
   GfxFontDict *fontDict;
-  GBool hasCaption;
-  double w, dx, dy, r;
-  double *dash;
-  GooString *caption, *da;
-  GooString **text;
-  GBool *selection;
-  int dashLength, ff, quadding, comb, nOptions, topIdx, i, j;
+  GooString *da;
   GBool modified;
-  AnnotColor aColor;
 
   if (widget == NULL || !widget->getField () || !widget->getField ()->getObj ()->isDict ())
     return;
@@ -3698,17 +3800,6 @@ void AnnotWidget::generateFieldAppearance() {
     obj1.free();
   }
 
-  // get the field type
-  Form::fieldLookup(fieldDict, "FT", &ftObj);
-
-  // get the field flags (Ff) value
-  if (Form::fieldLookup(fieldDict, "Ff", &obj1)->isInt()) {
-    ff = obj1.getInt();
-  } else {
-    ff = 0;
-  }
-  obj1.free();
-
   // draw the border
   if (appearCharacs && border && border->getWidth() > 0)
     drawBorder();
@@ -3739,159 +3830,21 @@ void AnnotWidget::generateFieldAppearance() {
   obj1.free();
 
   // draw the field contents
-  if (ftObj.isName("Btn")) {
-    caption = NULL;
-    if (mkDict) {
-      if (mkDict->lookup("CA", &obj1)->isString()) {
-        caption = obj1.getString()->copy();
-      }
-      obj1.free();
-    }
-    // radio button
-    if (ff & fieldFlagRadio) {
-      //~ Acrobat doesn't draw a caption if there is no AP dict (?)
-      if (Form::fieldLookup(fieldDict, "V", &obj1)->isName()) {
-        if (annot->lookup("AS", &obj2)->isName(obj1.getName()) &&
-	    strcmp (obj1.getName(), "Off") != 0) {
-          if (caption) {
-            drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter,
-                gFalse, gTrue);
-          } else {
-            if (mkDict) {
-              if (mkDict->lookup("BC", &obj3)->isArray() &&
-                  obj3.arrayGetLength() > 0) {
-                dx = rect->x2 - rect->x1;
-                dy = rect->y2 - rect->y1;
-		aColor = AnnotColor (obj3.getArray());
-                setColor(&aColor, gTrue);
-                drawCircle(0.5 * dx, 0.5 * dy, 0.2 * (dx < dy ? dx : dy),
-                    gTrue);
-              }
-              obj3.free();
-            }
-          }
-        }
-        obj2.free();
-      }
-      obj1.free();
-      // pushbutton
-    } else if (ff & fieldFlagPushbutton) {
-      if (caption) {
-        drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter,
-            gFalse, gFalse);
-      }
-      // checkbox
-    } else {
-      if (annot->lookup("AS", &obj1)->isName() &&
-          strcmp(obj1.getName(), "Off") != 0) {
-        if (!caption) {
-          caption = new GooString("3"); // ZapfDingbats checkmark
-        }
-        drawText(caption, da, fontDict, gFalse, 0, fieldQuadCenter,
-            gFalse, gTrue);
-      }
-      obj1.free();
-    }
-    if (caption) {
-      delete caption;
-    }
-  } else if (ftObj.isName("Tx")) {
-    if (Form::fieldLookup(fieldDict, "V", &obj1)->isString()) {
-      if (Form::fieldLookup(fieldDict, "Q", &obj2)->isInt()) {
-        quadding = obj2.getInt();
-      } else {
-        quadding = fieldQuadLeft;
-      }
-      obj2.free();
-      comb = 0;
-      if (ff & fieldFlagComb) {
-        if (Form::fieldLookup(fieldDict, "MaxLen", &obj2)->isInt()) {
-          comb = obj2.getInt();
-        }
-        obj2.free();
-      }
-      drawText(obj1.getString(), da, fontDict,
-          ff & fieldFlagMultiline, comb, quadding, gTrue, gFalse, ff & fieldFlagPassword);
-    }
-    obj1.free();
-  } else if (ftObj.isName("Ch")) {
-    if (Form::fieldLookup(fieldDict, "Q", &obj1)->isInt()) {
-      quadding = obj1.getInt();
-    } else {
-      quadding = fieldQuadLeft;
-    }
-    obj1.free();
-    // combo box
-    if (ff & fieldFlagCombo) {
-      if (Form::fieldLookup(fieldDict, "V", &obj1)->isString()) {
-        drawText(obj1.getString(), da, fontDict,
-            gFalse, 0, quadding, gTrue, gFalse);
-        //~ Acrobat draws a popup icon on the right side
-      }
-      obj1.free();
-      // list box
-    } else {
-      if (fieldDict->lookup("Opt", &obj1)->isArray()) {
-        nOptions = obj1.arrayGetLength();
-        // get the option text
-        text = (GooString **)gmallocn(nOptions, sizeof(GooString *));
-        for (i = 0; i < nOptions; ++i) {
-          text[i] = NULL;
-          obj1.arrayGet(i, &obj2);
-          if (obj2.isString()) {
-            text[i] = obj2.getString()->copy();
-          } else if (obj2.isArray() && obj2.arrayGetLength() == 2) {
-            if (obj2.arrayGet(1, &obj3)->isString()) {
-              text[i] = obj3.getString()->copy();
-            }
-            obj3.free();
-          }
-          obj2.free();
-          if (!text[i]) {
-            text[i] = new GooString();
-          }
-        }
-        // get the selected option(s)
-        selection = (GBool *)gmallocn(nOptions, sizeof(GBool));
-        //~ need to use the I field in addition to the V field
-	Form::fieldLookup(fieldDict, "V", &obj2);
-        for (i = 0; i < nOptions; ++i) {
-          selection[i] = gFalse;
-          if (obj2.isString()) {
-            if (!obj2.getString()->cmp(text[i])) {
-              selection[i] = gTrue;
-            }
-          } else if (obj2.isArray()) {
-            for (j = 0; j < obj2.arrayGetLength(); ++j) {
-              if (obj2.arrayGet(j, &obj3)->isString() &&
-                  !obj3.getString()->cmp(text[i])) {
-                selection[i] = gTrue;
-              }
-              obj3.free();
-            }
-          }
-        }
-        obj2.free();
-        // get the top index
-        if (fieldDict->lookup("TI", &obj2)->isInt()) {
-          topIdx = obj2.getInt();
-        } else {
-          topIdx = 0;
-        }
-        obj2.free();
-        // draw the text
-        drawListBox(text, selection, nOptions, topIdx, da, fontDict, quadding);
-        for (i = 0; i < nOptions; ++i) {
-          delete text[i];
-        }
-        gfree(text);
-        gfree(selection);
-      }
-      obj1.free();
-    }
-  } else if (ftObj.isName("Sig")) {
+  switch (field->getType()) {
+  case formButton:
+    drawFormFieldButton(fontDict, da);
+    break;
+  case formText:
+    drawFormFieldText(fontDict, da);
+    break;
+  case formChoice:
+    drawFormFieldChoice(fontDict, da);
+    break;
+  case formSignature:
     //~unimp
-  } else {
+    break;
+  case formUndef:
+  default:
     error(-1, "Unknown field type");
   }
 
@@ -3965,7 +3918,6 @@ void AnnotWidget::generateFieldAppearance() {
   if (fontDict) {
     delete fontDict;
   }
-  ftObj.free();
   mkObj.free();
 }
 
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 7984b8e..3e80788 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -44,6 +44,7 @@ class GfxFontDict;
 class Form;
 class FormWidget;
 class FormField;
+class FormFieldChoice;
 class PDFRectangle;
 class Movie;
 class LinkAction;
@@ -1135,6 +1136,9 @@ public:
   virtual void draw(Gfx *gfx, GBool printing);
 
   void drawBorder();
+  void drawFormFieldButton(GfxFontDict *fontDict, GooString *da);
+  void drawFormFieldText(GfxFontDict *fontDict, GooString *da);
+  void drawFormFieldChoice(GfxFontDict *fontDict, GooString *da);
   void generateFieldAppearance ();
 
   AnnotWidgetHighlightMode getMode() { return mode; }
@@ -1151,8 +1155,8 @@ private:
 		GBool multiline, int comb, int quadding,
 		GBool txField, GBool forceZapfDingbats,
 		GBool password=false);
-  void drawListBox(GooString **text, GBool *selection,
-		   int nOptions, int topIdx,
+  void drawListBox(FormFieldChoice *fieldChoice,
+		   int topIdx,
 		   GooString *da, GfxFontDict *fontDict, int quadding);
   void layoutText(GooString *text, GooString *outBuf, int *i, GfxFont *font,
 		  double *width, double widthLimit, int *charCount,
commit f98b3540db731026e0febf1f010548f0f0ef9142
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sun Mar 6 15:57:22 2011 +0100

    annots: Move code to draw the border of an AnnotWidget to a new method
    
    And use the field object instead of parsing the field dictionary again.

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 0026ef7..3f87080 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -3540,9 +3540,113 @@ void AnnotWidget::drawListBox(GooString **text, GBool *selection,
   delete convertedText;
 }
 
+void AnnotWidget::drawBorder() {
+  int dashLength;
+  double *dash;
+  AnnotColor adjustedColor;
+  double w = border->getWidth();
+
+  AnnotColor *aColor = appearCharacs->getBorderColor();
+  if (!aColor)
+    aColor = appearCharacs->getBackColor();
+  if (!aColor)
+    return;
+
+  double dx = rect->x2 - rect->x1;
+  double dy = rect->y2 - rect->y1;
+
+  // radio buttons with no caption have a round border
+  GBool hasCaption = appearCharacs->getNormalCaption() != NULL;
+  if (field->getType() == formButton &&
+      static_cast<FormFieldButton*>(field)->getButtonType() == formButtonRadio && !hasCaption) {
+    double r = 0.5 * (dx < dy ? dx : dy);
+    switch (border->getStyle()) {
+    case AnnotBorder::borderDashed:
+      appearBuf->append("[");
+      dashLength = border->getDashLength();
+      dash = border->getDash();
+      for (int i = 0; i < dashLength; ++i) {
+        appearBuf->appendf(" {0:.2f}", dash[i]);
+      }
+      appearBuf->append("] 0 d\n");
+      // fall through to the solid case
+    case AnnotBorder::borderSolid:
+    case AnnotBorder::borderUnderlined:
+      appearBuf->appendf("{0:.2f} w\n", w);
+      setColor(aColor, gFalse);
+      drawCircle(0.5 * dx, 0.5 * dy, r - 0.5 * w, gFalse);
+      break;
+    case AnnotBorder::borderBeveled:
+    case AnnotBorder::borderInset:
+      appearBuf->appendf("{0:.2f} w\n", 0.5 * w);
+      setColor(aColor, gFalse);
+      drawCircle(0.5 * dx, 0.5 * dy, r - 0.25 * w, gFalse);
+      adjustedColor = AnnotColor(*aColor);
+      adjustedColor.adjustColor(border->getStyle() == AnnotBorder::borderBeveled ? 1 : -1);
+      setColor(&adjustedColor, gFalse);
+      drawCircleTopLeft(0.5 * dx, 0.5 * dy, r - 0.75 * w);
+      adjustedColor = AnnotColor(*aColor);
+      adjustedColor.adjustColor(border->getStyle() == AnnotBorder::borderBeveled ? -1 : 1);
+      setColor(&adjustedColor, gFalse);
+      drawCircleBottomRight(0.5 * dx, 0.5 * dy, r - 0.75 * w);
+      break;
+    }
+  } else {
+    switch (border->getStyle()) {
+    case AnnotBorder::borderDashed:
+      appearBuf->append("[");
+      dashLength = border->getDashLength();
+      dash = border->getDash();
+      for (int i = 0; i < dashLength; ++i) {
+        appearBuf->appendf(" {0:.2f}", dash[i]);
+      }
+      appearBuf->append("] 0 d\n");
+      // fall through to the solid case
+    case AnnotBorder::borderSolid:
+      appearBuf->appendf("{0:.2f} w\n", w);
+      setColor(aColor, gFalse);
+      appearBuf->appendf("{0:.2f} {0:.2f} {1:.2f} {2:.2f} re s\n",
+                         0.5 * w, dx - w, dy - w);
+      break;
+    case AnnotBorder::borderBeveled:
+    case AnnotBorder::borderInset:
+      adjustedColor = AnnotColor(*aColor);
+      adjustedColor.adjustColor(border->getStyle() == AnnotBorder::borderBeveled ? 1 : -1);
+      setColor(&adjustedColor, gTrue);
+      appearBuf->append("0 0 m\n");
+      appearBuf->appendf("0 {0:.2f} l\n", dy);
+      appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx, dy);
+      appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx - w, dy - w);
+      appearBuf->appendf("{0:.2f} {1:.2f} l\n", w, dy - w);
+      appearBuf->appendf("{0:.2f} {0:.2f} l\n", w);
+      appearBuf->append("f\n");
+      adjustedColor = AnnotColor(*aColor);
+      adjustedColor.adjustColor(border->getStyle() == AnnotBorder::borderBeveled ? -1 : 1);
+      setColor(&adjustedColor, gTrue);
+      appearBuf->append("0 0 m\n");
+      appearBuf->appendf("{0:.2f} 0 l\n", dx);
+      appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx, dy);
+      appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx - w, dy - w);
+      appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx - w, w);
+      appearBuf->appendf("{0:.2f} {0:.2f} l\n", w);
+      appearBuf->append("f\n");
+      break;
+    case AnnotBorder::borderUnderlined:
+      appearBuf->appendf("{0:.2f} w\n", w);
+      setColor(aColor, gFalse);
+      appearBuf->appendf("0 0 m {0:.2f} 0 l s\n", dx);
+      break;
+    }
+
+    // clip to the inside of the border
+    appearBuf->appendf("{0:.2f} {0:.2f} {1:.2f} {2:.2f} re W n\n",
+                       w, dx - 2 * w, dy - 2 * w);
+  }
+}
+
 void AnnotWidget::generateFieldAppearance() {
   Object mkObj, ftObj, appearDict, drObj, obj1, obj2, obj3;
-  Dict *field;
+  Dict *fieldDict;
   Dict *annot;
   Dict *acroForm;
   Dict *mkDict;
@@ -3561,7 +3665,8 @@ void AnnotWidget::generateFieldAppearance() {
   if (widget == NULL || !widget->getField () || !widget->getField ()->getObj ()->isDict ())
     return;
 
-  field = widget->getField ()->getObj ()->getDict ();
+  field = widget->getField();
+  fieldDict = field->getObj()->getDict();
   annot = widget->getObj ()->getDict ();
   acroForm = form->getObj ()->getDict ();
   
@@ -3594,10 +3699,10 @@ void AnnotWidget::generateFieldAppearance() {
   }
 
   // get the field type
-  Form::fieldLookup(field, "FT", &ftObj);
+  Form::fieldLookup(fieldDict, "FT", &ftObj);
 
   // get the field flags (Ff) value
-  if (Form::fieldLookup(field, "Ff", &obj1)->isInt()) {
+  if (Form::fieldLookup(fieldDict, "Ff", &obj1)->isInt()) {
     ff = obj1.getInt();
   } else {
     ff = 0;
@@ -3605,113 +3710,8 @@ void AnnotWidget::generateFieldAppearance() {
   obj1.free();
 
   // draw the border
-  if (mkDict && border) {
-    w = border->getWidth();
-    if (w > 0) {
-      mkDict->lookup("BC", &obj1);
-      if (!(obj1.isArray() && obj1.arrayGetLength() > 0)) {
-        mkDict->lookup("BG", &obj1);
-      }
-      if (obj1.isArray() && obj1.arrayGetLength() > 0) {
-        dx = rect->x2 - rect->x1;
-        dy = rect->y2 - rect->y1;
-
-        // radio buttons with no caption have a round border
-        hasCaption = mkDict->lookup("CA", &obj2)->isString();
-        obj2.free();
-        if (ftObj.isName("Btn") && (ff & fieldFlagRadio) && !hasCaption) {
-          r = 0.5 * (dx < dy ? dx : dy);
-          switch (border->getStyle()) {
-            case AnnotBorder::borderDashed:
-              appearBuf->append("[");
-              dashLength = border->getDashLength();
-              dash = border->getDash();
-              for (i = 0; i < dashLength; ++i) {
-                appearBuf->appendf(" {0:.2f}", dash[i]);
-              }
-              appearBuf->append("] 0 d\n");
-              // fall through to the solid case
-            case AnnotBorder::borderSolid:
-            case AnnotBorder::borderUnderlined:
-              appearBuf->appendf("{0:.2f} w\n", w);
-	      aColor = AnnotColor (obj1.getArray());
-              setColor(&aColor, gFalse);
-              drawCircle(0.5 * dx, 0.5 * dy, r - 0.5 * w, gFalse);
-              break;
-            case AnnotBorder::borderBeveled:
-            case AnnotBorder::borderInset:
-              appearBuf->appendf("{0:.2f} w\n", 0.5 * w);
-	      aColor = AnnotColor (obj1.getArray());
-              setColor(&aColor, gFalse);
-              drawCircle(0.5 * dx, 0.5 * dy, r - 0.25 * w, gFalse);
-	      aColor = AnnotColor (obj1.getArray(),
-				   border->getStyle() == AnnotBorder::borderBeveled ? 1 : -1);
-              setColor(&aColor, gFalse);
-              drawCircleTopLeft(0.5 * dx, 0.5 * dy, r - 0.75 * w);
-	      aColor = AnnotColor (obj1.getArray(),
-				   border->getStyle() == AnnotBorder::borderBeveled ? -1 : 1);
-              setColor(&aColor, gFalse);
-              drawCircleBottomRight(0.5 * dx, 0.5 * dy, r - 0.75 * w);
-              break;
-          }
-
-        } else {
-          switch (border->getStyle()) {
-            case AnnotBorder::borderDashed:
-              appearBuf->append("[");
-              dashLength = border->getDashLength();
-              dash = border->getDash();
-              for (i = 0; i < dashLength; ++i) {
-                appearBuf->appendf(" {0:.2f}", dash[i]);
-              }
-              appearBuf->append("] 0 d\n");
-              // fall through to the solid case
-            case AnnotBorder::borderSolid:
-              appearBuf->appendf("{0:.2f} w\n", w);
-	      aColor = AnnotColor (obj1.getArray());
-              setColor(&aColor, gFalse);
-              appearBuf->appendf("{0:.2f} {0:.2f} {1:.2f} {2:.2f} re s\n",
-                  0.5 * w, dx - w, dy - w);
-              break;
-            case AnnotBorder::borderBeveled:
-            case AnnotBorder::borderInset:
-	      aColor = AnnotColor (obj1.getArray(),
-				   border->getStyle() == AnnotBorder::borderBeveled ? 1 : -1);
-	      setColor(&aColor, gTrue);
-              appearBuf->append("0 0 m\n");
-              appearBuf->appendf("0 {0:.2f} l\n", dy);
-              appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx, dy);
-              appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx - w, dy - w);
-              appearBuf->appendf("{0:.2f} {1:.2f} l\n", w, dy - w);
-              appearBuf->appendf("{0:.2f} {0:.2f} l\n", w);
-              appearBuf->append("f\n");
-	      aColor = AnnotColor (obj1.getArray(),
-				   border->getStyle() == AnnotBorder::borderBeveled ? -1 : 1);
-              setColor(&aColor, gTrue);
-              appearBuf->append("0 0 m\n");
-              appearBuf->appendf("{0:.2f} 0 l\n", dx);
-              appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx, dy);
-              appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx - w, dy - w);
-              appearBuf->appendf("{0:.2f} {1:.2f} l\n", dx - w, w);
-              appearBuf->appendf("{0:.2f} {0:.2f} l\n", w);
-              appearBuf->append("f\n");
-              break;
-            case AnnotBorder::borderUnderlined:
-              appearBuf->appendf("{0:.2f} w\n", w);
-	      aColor = AnnotColor (obj1.getArray());
-              setColor(&aColor, gFalse);
-              appearBuf->appendf("0 0 m {0:.2f} 0 l s\n", dx);
-              break;
-          }
-
-          // clip to the inside of the border
-          appearBuf->appendf("{0:.2f} {0:.2f} {1:.2f} {2:.2f} re W n\n",
-              w, dx - 2 * w, dy - 2 * w);
-        }
-      }
-      obj1.free();
-    }
-  }
+  if (appearCharacs && border && border->getWidth() > 0)
+    drawBorder();
 
   // get the resource dictionary
   acroForm->lookup("DR", &drObj);
@@ -3725,7 +3725,7 @@ void AnnotWidget::generateFieldAppearance() {
   obj1.free();
 
   // get the default appearance string
-  if (Form::fieldLookup(field, "DA", &obj1)->isNull()) {
+  if (Form::fieldLookup(fieldDict, "DA", &obj1)->isNull()) {
     obj1.free();
     acroForm->lookup("DA", &obj1);
   }
@@ -3750,7 +3750,7 @@ void AnnotWidget::generateFieldAppearance() {
     // radio button
     if (ff & fieldFlagRadio) {
       //~ Acrobat doesn't draw a caption if there is no AP dict (?)
-      if (Form::fieldLookup(field, "V", &obj1)->isName()) {
+      if (Form::fieldLookup(fieldDict, "V", &obj1)->isName()) {
         if (annot->lookup("AS", &obj2)->isName(obj1.getName()) &&
 	    strcmp (obj1.getName(), "Off") != 0) {
           if (caption) {
@@ -3796,8 +3796,8 @@ void AnnotWidget::generateFieldAppearance() {
       delete caption;
     }
   } else if (ftObj.isName("Tx")) {
-    if (Form::fieldLookup(field, "V", &obj1)->isString()) {
-      if (Form::fieldLookup(field, "Q", &obj2)->isInt()) {
+    if (Form::fieldLookup(fieldDict, "V", &obj1)->isString()) {
+      if (Form::fieldLookup(fieldDict, "Q", &obj2)->isInt()) {
         quadding = obj2.getInt();
       } else {
         quadding = fieldQuadLeft;
@@ -3805,7 +3805,7 @@ void AnnotWidget::generateFieldAppearance() {
       obj2.free();
       comb = 0;
       if (ff & fieldFlagComb) {
-        if (Form::fieldLookup(field, "MaxLen", &obj2)->isInt()) {
+        if (Form::fieldLookup(fieldDict, "MaxLen", &obj2)->isInt()) {
           comb = obj2.getInt();
         }
         obj2.free();
@@ -3815,7 +3815,7 @@ void AnnotWidget::generateFieldAppearance() {
     }
     obj1.free();
   } else if (ftObj.isName("Ch")) {
-    if (Form::fieldLookup(field, "Q", &obj1)->isInt()) {
+    if (Form::fieldLookup(fieldDict, "Q", &obj1)->isInt()) {
       quadding = obj1.getInt();
     } else {
       quadding = fieldQuadLeft;
@@ -3823,7 +3823,7 @@ void AnnotWidget::generateFieldAppearance() {
     obj1.free();
     // combo box
     if (ff & fieldFlagCombo) {
-      if (Form::fieldLookup(field, "V", &obj1)->isString()) {
+      if (Form::fieldLookup(fieldDict, "V", &obj1)->isString()) {
         drawText(obj1.getString(), da, fontDict,
             gFalse, 0, quadding, gTrue, gFalse);
         //~ Acrobat draws a popup icon on the right side
@@ -3831,7 +3831,7 @@ void AnnotWidget::generateFieldAppearance() {
       obj1.free();
       // list box
     } else {
-      if (field->lookup("Opt", &obj1)->isArray()) {
+      if (fieldDict->lookup("Opt", &obj1)->isArray()) {
         nOptions = obj1.arrayGetLength();
         // get the option text
         text = (GooString **)gmallocn(nOptions, sizeof(GooString *));
@@ -3854,7 +3854,7 @@ void AnnotWidget::generateFieldAppearance() {
         // get the selected option(s)
         selection = (GBool *)gmallocn(nOptions, sizeof(GBool));
         //~ need to use the I field in addition to the V field
-	Form::fieldLookup(field, "V", &obj2);
+	Form::fieldLookup(fieldDict, "V", &obj2);
         for (i = 0; i < nOptions; ++i) {
           selection[i] = gFalse;
           if (obj2.isString()) {
@@ -3873,7 +3873,7 @@ void AnnotWidget::generateFieldAppearance() {
         }
         obj2.free();
         // get the top index
-        if (field->lookup("TI", &obj2)->isInt()) {
+        if (fieldDict->lookup("TI", &obj2)->isInt()) {
           topIdx = obj2.getInt();
         } else {
           topIdx = 0;
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 769a64a..7984b8e 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -43,6 +43,7 @@ class GfxFont;
 class GfxFontDict;
 class Form;
 class FormWidget;
+class FormField;
 class PDFRectangle;
 class Movie;
 class LinkAction;
@@ -1133,6 +1134,7 @@ public:
 
   virtual void draw(Gfx *gfx, GBool printing);
 
+  void drawBorder();
   void generateFieldAppearance ();
 
   AnnotWidgetHighlightMode getMode() { return mode; }
@@ -1159,6 +1161,7 @@ private:
 
   Form *form;
   FormWidget *widget;                     // FormWidget object for this annotation
+  FormField *field;                       // FormField object for this annotation
   AnnotWidgetHighlightMode mode;          // H  (Default I)
   AnnotAppearanceCharacs *appearCharacs;  // MK
   LinkAction *action;                     // A
commit 9854f3173f994bbe3f57d33bd1d0e045833859c2
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Sun Mar 6 15:56:06 2011 +0100

    annots: Add AnnotColor::adjustColor() to be able to adjust an existing AnnotColor

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index bcbe50c..0026ef7 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -629,6 +629,13 @@ AnnotColor::AnnotColor(Array *array, int adjust) {
     obj1.free();
   }
 
+  if (adjust != 0)
+    adjustColor(adjust);
+}
+
+void AnnotColor::adjustColor(int adjust) {
+  int i;
+
   if (length == 4) {
     adjust = -adjust;
   }
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 3659abe..769a64a 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -295,6 +295,8 @@ public:
   AnnotColor(double c, double m, double y, double k);
   AnnotColor(Array *array, int adjust = 0);
 
+  void adjustColor(int adjust);
+
   AnnotColorSpace getSpace() const { return (AnnotColorSpace) length; }
   const double *getValues() const { return values; }
 


More information about the poppler mailing list