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