From 389000fddd1cd69dc5b51d29137de5df2d57f5c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hans-Ulrich=20J=C3=BCttner?= Date: Wed, 6 Sep 2017 11:03:52 +0200 Subject: [PATCH] Added methods to get and set the font size of text fields Fixes bug #101692 --- poppler/Annot.cc | 23 +++---------- poppler/Form.cc | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ poppler/Form.h | 16 +++++++++ qt5/src/poppler-form.cc | 12 ++++++- qt5/src/poppler-form.h | 10 ++++++ 5 files changed, 133 insertions(+), 20 deletions(-) diff --git a/poppler/Annot.cc b/poppler/Annot.cc index bda5a90..470943f 100644 --- a/poppler/Annot.cc +++ b/poppler/Annot.cc @@ -2839,29 +2839,14 @@ void AnnotFreeText::parseAppearanceString(GooString *da, double &fontsize, Annot fontcolor = NULL; if (da) { GooList * daToks = new GooList(); - int j, i = 0; + int i = FormFieldText::tokenizeDA(da, daToks, "Tf"); - // Tokenize - while (i < da->getLength()) { - while (i < da->getLength() && Lexer::isSpace(da->getChar(i))) { - ++i; - } - if (i < da->getLength()) { - for (j = i + 1; j < da->getLength() && !Lexer::isSpace(da->getChar(j)); ++j) { - } - daToks->append(new GooString(da, i, j - i)); - i = j; - } + if (i >= 1) { + fontsize = gatof(( (GooString *)daToks->get(i-1) )->getCString()); + // TODO: Font name } - // Scan backwards: we are looking for the last set value for (i = daToks->getLength()-1; i >= 0; --i) { - if (fontsize == -1) { - if (!((GooString *)daToks->get(i))->cmp("Tf") && i >= 2) { - // TODO: Font name - fontsize = gatof(( (GooString *)daToks->get(i-1) )->getCString()); - } - } if (fontcolor == NULL) { if (!((GooString *)daToks->get(i))->cmp("g") && i >= 1) { fontcolor = new AnnotColor(gatof(( (GooString *)daToks->get(i-1) )->getCString())); diff --git a/poppler/Form.cc b/poppler/Form.cc index 0f4718e..15c31e6 100644 --- a/poppler/Form.cc +++ b/poppler/Form.cc @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "goo/gmem.h" #include "goo/GooString.h" @@ -49,6 +50,7 @@ #include "PDFDocEncoding.h" #include "Annot.h" #include "Link.h" +#include "Lexer.h" //return a newly allocated char* containing an UTF16BE string of size length char* pdfDocEncodingToUTF16 (GooString* orig, int* length) @@ -312,6 +314,16 @@ int FormWidgetText::getMaxLen () const return parent()->getMaxLen (); } +double FormWidgetText::getTextFontSize() +{ + return parent()->getTextFontSize(); +} + +void FormWidgetText::setTextFontSize(int fontSize) +{ + parent()->setTextFontSize(fontSize); +} + void FormWidgetText::setContent(GooString* new_content) { parent()->setContentCopy(new_content); @@ -1185,6 +1197,86 @@ FormFieldText::~FormFieldText() delete content; } +double FormFieldText::getTextFontSize() +{ + GooList* daToks = new GooList(); + int idx = parseDA(daToks); + double fontSize = -1; + if (idx >= 0) { + char* p = nullptr; + fontSize = strtod(static_cast(daToks->get(idx))->getCString(), &p); + if (!p || *p) + fontSize = -1; + } + deleteGooList(daToks, GooString); + return fontSize; +} + +void FormFieldText::setTextFontSize(int fontSize) +{ + if (fontSize > 0 && obj.isDict()) { + GooList* daToks = new GooList(); + int idx = parseDA(daToks); + if (idx == -1) { + error(errSyntaxError, -1, "FormFieldText:: invalid DA object\n"); + return; + } + if (defaultAppearance) + delete defaultAppearance; + defaultAppearance = new GooString; + for (int i = 0; i < daToks->getLength(); ++i) { + if (i > 0) + defaultAppearance->append(' '); + if (i == idx) { + defaultAppearance->appendf("{0:d}", fontSize); + } else { + defaultAppearance->append(static_cast(daToks->get(i))); + } + } + deleteGooList(daToks, GooString); + obj.dictSet("DA", Object(defaultAppearance->copy())); + xref->setModifiedObject(&obj, ref); + updateChildrenAppearance(); + } +} + +int FormFieldText::tokenizeDA(GooString* da, GooList* daToks, const char* searchTok) +{ + int idx = -1; + if(da && daToks) { + int i = 0; + int j = 0; + while (i < da->getLength()) { + while (i < da->getLength() && Lexer::isSpace(da->getChar(i))) { + ++i; + } + if (i < da->getLength()) { + for (j = i + 1; j < da->getLength() && !Lexer::isSpace(da->getChar(j)); ++j) { + } + GooString* tok = new GooString(da, i, j - i); + if (searchTok && !tok->cmp(searchTok)) + idx = daToks->getLength(); + daToks->append(tok); + i = j; + } + } + } + return idx; +} + +int FormFieldText::parseDA(GooList* daToks) +{ + int idx = -1; + if (obj.isDict()) { + Object objDA(obj.dictLookup("DA")); + if (objDA.isString()) { + GooString* da = objDA.getString(); + idx = tokenizeDA(da, daToks, "Tf") - 1; + } + } + return idx; +} + //------------------------------------------------------------------------ // FormFieldChoice diff --git a/poppler/Form.h b/poppler/Form.h index 8498752..8e72334 100644 --- a/poppler/Form.h +++ b/poppler/Form.h @@ -25,6 +25,7 @@ #pragma interface #endif +#include "goo/GooList.h" #include "Object.h" #include "Annot.h" @@ -206,6 +207,11 @@ public: bool isComb () const; bool isRichText () const; int getMaxLen () const; + //return the font size of the field's text + double getTextFontSize(); + //set the font size of the field's text (currently only integer values) + void setTextFontSize(int fontSize); + protected: FormFieldText *parent() const; }; @@ -421,10 +427,20 @@ public: int getMaxLen () const { return maxLen; } + //return the font size of the field's text + double getTextFontSize(); + //set the font size of the field's text (currently only integer values) + void setTextFontSize(int fontSize); + #ifdef DEBUG_FORMS void print(int indent = 0); #endif + + static int tokenizeDA(GooString* daString, GooList* daToks, const char* searchTok); + protected: + int parseDA(GooList* daToks); + GooString* content; bool multiline; bool password; diff --git a/qt5/src/poppler-form.cc b/qt5/src/poppler-form.cc index 02c3a5d..f6607b2 100644 --- a/qt5/src/poppler-form.cc +++ b/qt5/src/poppler-form.cc @@ -186,7 +186,6 @@ Link *FormField::additionalAction(AdditionalActionType type) const return action; } - FormFieldButton::FormFieldButton(DocumentData *doc, ::Page *p, ::FormWidgetButton *w) : FormField(*new FormFieldData(doc, p, w)) { @@ -348,6 +347,17 @@ bool FormFieldText::canBeSpellChecked() const return !fwt->noSpellCheck(); } +double FormFieldText::getFontSize() const +{ + FormWidgetText* fwt = static_cast(m_formData->fm); + return fwt->getTextFontSize(); +} + +void FormFieldText::setFontSize(int fontSize) +{ + FormWidgetText* fwt = static_cast(m_formData->fm); + fwt->setTextFontSize(fontSize); +} FormFieldChoice::FormFieldChoice(DocumentData *doc, ::Page *p, ::FormWidgetChoice *w) : FormField(*new FormFieldData(doc, p, w)) diff --git a/qt5/src/poppler-form.h b/qt5/src/poppler-form.h index dbe1f56..a5cc037 100644 --- a/qt5/src/poppler-form.h +++ b/qt5/src/poppler-form.h @@ -277,6 +277,16 @@ namespace Poppler { */ bool canBeSpellChecked() const; + /** + The font size of the text in the form field + */ + double getFontSize() const; + + /** + Set the font size of the text in the form field (currently only as integer) + */ + void setFontSize(int fontSize); + private: Q_DISABLE_COPY(FormFieldText) }; -- 1.9.1