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