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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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 <[email protected]> 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; } _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
