poppler/Annot.cc | 13 +++++++++ poppler/Annot.h | 1 qt5/src/poppler-form.cc | 58 +++++++++++++++++++++++++++++++++++++++++++ qt5/src/poppler-form.h | 39 +++++++++++++++++++++++++++++ qt5/src/poppler-private.cc | 8 +++++- qt5/src/poppler-private.h | 8 ++++++ qt5/tests/check_forms.cpp | 60 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 185 insertions(+), 2 deletions(-)
New commits: commit 6afe59eb8bcb223d28eef5bb364ebb4d35ed0f59 Author: João Netto <[email protected]> Date: Tue Jun 11 19:06:01 2019 -0300 Implemented support for setIcon by changing appearance Added test for setIcon Made changes to be more inline with API. diff --git a/poppler/Annot.cc b/poppler/Annot.cc index 0bf9864b..005fa96e 100644 --- a/poppler/Annot.cc +++ b/poppler/Annot.cc @@ -3819,6 +3819,17 @@ bool AnnotWidget::setFormAdditionalAction(FormAdditionalActionsType formAddition return true; } +void AnnotWidget::setNewAppearance(Object &&newAppearance) +{ + if (!newAppearance.isNull()) { + appearStreams = std::make_unique<AnnotAppearance>(doc, &newAppearance); + update("AP", std::move(newAppearance)); + } + + if (appearStreams) + appearance = appearStreams->getAppearanceStream(AnnotAppearance::appearNormal, appearState->c_str()); +} + // Grand unified handler for preparing text strings to be drawn into form // fields. Takes as input a text string (in PDFDocEncoding or UTF-16). // Converts some or all of this string to the appropriate encoding for the @@ -4980,7 +4991,7 @@ void AnnotWidget::updateAppearanceStream() void AnnotWidget::draw(Gfx *gfx, bool printing) { if (!isVisible (printing)) return; - + annotLocker(); bool addDingbatsResource = false; diff --git a/poppler/Annot.h b/poppler/Annot.h index 88c165f2..7b374644 100644 --- a/poppler/Annot.h +++ b/poppler/Annot.h @@ -1409,6 +1409,7 @@ public: LinkAction *getAdditionalAction(AdditionalActionsType type); // The caller should delete the result LinkAction *getFormAdditionalAction(FormAdditionalActionsType type); // The caller should delete the result Dict *getParent() { return parent; } + void setNewAppearance(Object &&newAppearance); bool setFormAdditionalAction(FormAdditionalActionsType type, const GooString &js); diff --git a/qt5/src/poppler-form.cc b/qt5/src/poppler-form.cc index ef13e58c..fa9c3312 100644 --- a/qt5/src/poppler-form.cc +++ b/qt5/src/poppler-form.cc @@ -70,6 +70,36 @@ Qt::Alignment formTextAlignment(::FormWidget *fm) namespace Poppler { +FormFieldIcon::FormFieldIcon(FormFieldIconData *data) + : d_ptr(data) +{ +} + +FormFieldIcon::FormFieldIcon(const FormFieldIcon &ffIcon) +{ + d_ptr = new FormFieldIconData; + d_ptr->icon = ffIcon.d_ptr->icon; +} + +FormFieldIcon& FormFieldIcon::operator=(const FormFieldIcon &ffIcon) +{ + if(this != &ffIcon) + { + delete d_ptr; + d_ptr = nullptr; + + d_ptr = new FormFieldIconData; + *d_ptr = *ffIcon.d_ptr; + } + + return *this; +} + +FormFieldIcon::~FormFieldIcon() +{ + delete d_ptr; +} + FormField::FormField(FormFieldData &dd) : m_formData(&dd) { @@ -284,6 +314,34 @@ QString FormFieldButton::caption() const return ret; } +FormFieldIcon FormFieldButton::icon() const +{ + FormWidgetButton* fwb = static_cast<FormWidgetButton*>(m_formData->fm); + if (fwb->getButtonType() == formButtonPush) + { + Dict *dict = m_formData->fm->getObj()->getDict(); + FormFieldIconData *data = new FormFieldIconData; + data->icon = dict; + return FormFieldIcon(data); + } + return FormFieldIcon(nullptr); +} + +void FormFieldButton::setIcon(const FormFieldIcon &icon) +{ + if(FormFieldIconData::getData( icon ) == nullptr) + return; + + FormWidgetButton* fwb = static_cast<FormWidgetButton*>(m_formData->fm); + if (fwb->getButtonType() == formButtonPush) + { + ::AnnotWidget *w = m_formData->fm->getWidgetAnnotation(); + FormFieldIconData *data = FormFieldIconData::getData( icon ); + if(data->icon != nullptr) + w->setNewAppearance(data->icon->lookup("AP")); + } +} + bool FormFieldButton::state() const { FormWidgetButton* fwb = static_cast<FormWidgetButton*>(m_formData->fm); diff --git a/qt5/src/poppler-form.h b/qt5/src/poppler-form.h index a1027625..f4c64589 100644 --- a/qt5/src/poppler-form.h +++ b/qt5/src/poppler-form.h @@ -49,6 +49,30 @@ namespace Poppler { class Link; class FormFieldData; + class FormFieldIconData; + + /** + The class containing the appearance information + + \since 0.78 + */ + + class POPPLER_QT5_EXPORT FormFieldIcon { + + friend class FormFieldIconData; + + public: + + FormFieldIcon(FormFieldIconData *data); + FormFieldIcon(const FormFieldIcon &ffIcon); + ~FormFieldIcon(); + + FormFieldIcon& operator=(const FormFieldIcon &ffIcon); + + private: + + FormFieldIconData *d_ptr; + }; /** The base class representing a form field. @@ -210,6 +234,21 @@ namespace Poppler { QString caption() const; /** + * Gets the icon used by the button + * + * \since 0.78 + */ + FormFieldIcon icon() const; + + /** + * Sets a new icon for the button, it has to be a icon + * returned by FormFieldButton::icon. + * + * \since 0.78 + */ + void setIcon(const FormFieldIcon &icon); + + /** The state of the button. */ bool state() const; diff --git a/qt5/src/poppler-private.cc b/qt5/src/poppler-private.cc index e847ed5e..5a8b6e79 100644 --- a/qt5/src/poppler-private.cc +++ b/qt5/src/poppler-private.cc @@ -28,6 +28,7 @@ */ #include "poppler-private.h" +#include "poppler-form.h" #include <QtCore/QByteArray> #include <QtCore/QDebug> @@ -302,4 +303,9 @@ namespace Debug { } } -} + FormFieldIconData POPPLER_QT5_EXPORT *FormFieldIconData::getData( const FormFieldIcon &f ) + { + return f.d_ptr; + } + +} \ No newline at end of file diff --git a/qt5/src/poppler-private.h b/qt5/src/poppler-private.h index 87956349..4bcd263f 100644 --- a/qt5/src/poppler-private.h +++ b/qt5/src/poppler-private.h @@ -237,6 +237,14 @@ namespace Poppler { ::FormWidget *fm; QRectF box; }; + + class FormFieldIcon; + class FormFieldIconData + { + public: + static FormFieldIconData *getData( const FormFieldIcon &f ); + Dict *icon; + }; } diff --git a/qt5/tests/check_forms.cpp b/qt5/tests/check_forms.cpp index 6c6482df..ec48ce91 100644 --- a/qt5/tests/check_forms.cpp +++ b/qt5/tests/check_forms.cpp @@ -2,6 +2,7 @@ #include <poppler-qt5.h> #include <poppler-form.h> +#include <poppler-private.h> #include <Form.h> class TestForms: public QObject @@ -12,6 +13,7 @@ public: private slots: void testCheckbox();// Test for issue #655 void testCheckboxIssue159();// Test for issue #159 + void testSetIcon();// Test that setIcon will always be valid. }; void TestForms::testCheckbox() @@ -88,5 +90,63 @@ void TestForms::testCheckboxIssue159() QCOMPARE( beerFieldButton->state() , false ); } +void TestForms::testSetIcon() +{ + QScopedPointer< Poppler::Document > document(Poppler::Document::load(TESTDATADIR "/unittestcases/form_set_icon.pdf")); + QVERIFY( document ); + + QScopedPointer< Poppler::Page > page(document->page(0)); + QVERIFY( page ); + + QList<Poppler::FormField*> forms = page->formFields(); + + Poppler::FormFieldButton *anmButton = nullptr; + + // First we are finding the field which will have its icon changed + Q_FOREACH (Poppler::FormField *field, forms) { + + if (field->type() != Poppler::FormField::FormButton) + continue; + + Poppler::FormFieldButton *fieldButton = static_cast<Poppler::FormFieldButton *>(field); + if (field->name() == QStringLiteral("anm0")) + anmButton = fieldButton; + + } + + QVERIFY( anmButton ); + + // Then we set the Icon on this field, for every other field + // And verify if it has a valid icon + Q_FOREACH (Poppler::FormField *field, forms) { + + if (field->type() != Poppler::FormField::FormButton) + continue; + + Poppler::FormFieldButton *fieldButton = static_cast<Poppler::FormFieldButton *>(field); + if (field->name() == QStringLiteral("anm0")) + continue; + + Poppler::FormFieldIcon newIcon = fieldButton->icon(); + + anmButton->setIcon( newIcon ); + + Poppler::FormFieldIcon anmIcon = anmButton->icon(); + + QVERIFY( Poppler::FormFieldIconData::getData( anmIcon ) ); + QVERIFY( Poppler::FormFieldIconData::getData( anmIcon )->icon ); + + QCOMPARE( Poppler::FormFieldIconData::getData( anmIcon )->icon->lookupNF("AP").dictLookupNF("N").getRef().num, + Poppler::FormFieldIconData::getData( newIcon )->icon->lookupNF("AP").dictLookupNF("N").getRef().num); + } + + // Just making sure that setting a invalid icon will still produce a valid icon. + anmButton->setIcon( nullptr ); + Poppler::FormFieldIcon anmIcon = anmButton->icon(); + + QVERIFY( Poppler::FormFieldIconData::getData( anmIcon ) ); + QVERIFY( Poppler::FormFieldIconData::getData( anmIcon )->icon ); +} + QTEST_GUILESS_MAIN(TestForms) #include "check_forms.moc" _______________________________________________ poppler mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/poppler
