Hi, while having a look at https://bugs.kde.org/show_bug.cgi?id=302334 i
realized we were filling the siblings of a form field wrong, we were doing it
at the widget level instead of at the field level.
This patch fixes this and makes the pdf work correctly in Okular.
Interestingly the pdf already works on evince even though evince is not using
the getSiblings method, i guess the glib frontend may be exporting the
child/parent structure and using that for their radio decision.
Anyone against commiting this to both 0.20 and master?
Cheers,
Albert
diff --git a/poppler/Form.cc b/poppler/Form.cc
index 99d7bbb..7a4bc84 100644
--- a/poppler/Form.cc
+++ b/poppler/Form.cc
@@ -165,8 +165,6 @@ FormWidgetButton::FormWidgetButton (PDFDoc *docA, Object *aobj, unsigned num, Re
type = formButton;
parent = static_cast<FormFieldButton*>(field);
onStr = NULL;
- siblingsID = NULL;
- numSiblingsID = 0;
Object obj1, obj2;
@@ -199,8 +197,6 @@ char *FormWidgetButton::getOnStr() {
FormWidgetButton::~FormWidgetButton ()
{
- if (siblingsID)
- gfree(siblingsID);
delete onStr;
}
@@ -234,12 +230,6 @@ GBool FormWidgetButton::getState ()
return onStr ? parent->getState(onStr->getCString()) : gFalse;
}
-void FormWidgetButton::setNumSiblingsID (int i)
-{
- numSiblingsID = i;
- siblingsID = (unsigned*)greallocn(siblingsID, numSiblingsID, sizeof(unsigned));
-}
-
FormWidgetText::FormWidgetText (PDFDoc *docA, Object *aobj, unsigned num, Ref ref, FormField *p) :
FormWidget(docA, aobj, num, ref, p)
@@ -777,6 +767,8 @@ FormFieldButton::FormFieldButton(PDFDoc *docA, Object *aobj, const Ref& ref, For
Dict* dict = obj.getDict();
active_child = -1;
noAllOff = false;
+ siblings = NULL;
+ numSiblings = 0;
appearanceState.initNull();
Object obj1;
@@ -827,20 +819,31 @@ void FormFieldButton::print(int indent)
}
#endif
+void FormFieldButton::setNumSiblings (int num)
+{
+ numSiblings = num;
+ siblings = (FormFieldButton**)greallocn(siblings, numSiblings, sizeof(FormFieldButton*));
+}
+
void FormFieldButton::fillChildrenSiblingsID()
{
if (!terminal) {
for(int i=0; i<numChildren; i++) {
- children[i]->fillChildrenSiblingsID();
- }
- } else {
- for(int i=0; i<numChildren; i++) {
- FormWidgetButton *btn = static_cast<FormWidgetButton*>(widgets[i]);
- btn->setNumSiblingsID(numChildren-1);
- for(int j=0, counter=0; j<numChildren; j++) {
- if (i == j) continue;
- btn->setSiblingsID(counter, widgets[j]->getID());
- counter++;
+ FormFieldButton *child = dynamic_cast<FormFieldButton*>(children[i]);
+ if (child != NULL) {
+ // Fill the siblings of this node childs
+ child->setNumSiblings(numChildren-1);
+ for(int j=0, counter=0; j<numChildren; j++) {
+ FormFieldButton *otherChild = dynamic_cast<FormFieldButton*>(children[j]);
+ if (i == j) continue;
+ if (child == otherChild) continue;
+ child->setSibling(counter, otherChild);
+ counter++;
+ }
+
+ // now call ourselves on the child
+ // to fill its children data
+ child->fillChildrenSiblingsID();
}
}
}
@@ -933,6 +936,8 @@ void FormFieldButton::updateState(char *state) {
FormFieldButton::~FormFieldButton()
{
appearanceState.free();
+ if (siblings)
+ gfree(siblings);
}
//------------------------------------------------------------------------
diff --git a/poppler/Form.h b/poppler/Form.h
index fa3c718..51babb2 100644
--- a/poppler/Form.h
+++ b/poppler/Form.h
@@ -155,17 +155,7 @@ public:
char* getOnStr();
void setAppearanceState(const char *state);
- void setNumSiblingsID (int i);
- void setSiblingsID (int i, unsigned id) { siblingsID[i] = id; }
-
- //For radio buttons, return the IDs of the other radio buttons in the same group
- unsigned* getSiblingsID () const { return siblingsID; }
- int getNumSiblingsID () const { return numSiblingsID; }
-
protected:
- unsigned* siblingsID; // IDs of dependent buttons (each button of a radio field has all the others buttons
- // of the same field in this array)
- int numSiblingsID;
GooString *onStr;
FormFieldButton *parent;
};
@@ -281,6 +271,7 @@ public:
GooString *getFullyQualifiedName();
FormWidget* findWidgetByRef (Ref aref);
+ int getNumWidgets() { return terminal ? numChildren : 0; }
FormWidget *getWidget(int i) { return terminal ? widgets[i] : NULL; }
// only implemented in FormFieldButton
@@ -345,6 +336,13 @@ public:
char *getAppearanceState() { return appearanceState.isName() ? appearanceState.getName() : NULL; }
void fillChildrenSiblingsID ();
+
+ void setNumSiblings (int num);
+ void setSibling (int i, FormFieldButton *id) { siblings[i] = id; }
+
+ //For radio buttons, return the fields of the other radio buttons in the same group
+ FormFieldButton* getSibling (int i) const { return siblings[i]; }
+ int getNumSiblings () const { return numSiblings; }
#ifdef DEBUG_FORMS
void print(int indent = 0);
@@ -354,6 +352,10 @@ public:
protected:
void updateState(char *state);
+ FormFieldButton** siblings; // IDs of dependent buttons (each button of a radio field has all the others buttons
+ // of the same field in this array)
+ int numSiblings;
+
FormButtonType btype;
int size;
int active_child; //only used for combo box
diff --git a/qt4/src/poppler-form.cc b/qt4/src/poppler-form.cc
index 82309ff..f072356 100644
--- a/qt4/src/poppler-form.cc
+++ b/qt4/src/poppler-form.cc
@@ -226,13 +226,20 @@ void FormFieldButton::setState( bool state )
QList<int> FormFieldButton::siblings() const
{
FormWidgetButton* fwb = static_cast<FormWidgetButton*>(m_formData->fm);
+ ::FormFieldButton* ffb = static_cast< ::FormFieldButton* >(fwb->getField());
if (fwb->getButtonType() == formButtonPush)
return QList<int>();
QList<int> ret;
- unsigned *sibls = fwb->getSiblingsID();
- for (int i = 0; i < fwb->getNumSiblingsID(); ++i)
- ret.append(sibls[i]);
+ for (int i = 0; i < ffb->getNumSiblings(); ++i)
+ {
+ ::FormFieldButton* sibling = static_cast< ::FormFieldButton* >(ffb->getSibling(i));
+ for (int j = 0; j < sibling->getNumWidgets(); ++j)
+ {
+ FormWidget *w = sibling->getWidget(j);
+ if (w) ret.append(w->getID());
+ }
+ }
return ret;
}
_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler