From 8821c04f36cb737776cd9077a46f1a9f86ca54e7 Mon Sep 17 00:00:00 2001 From: Albert Astals Cid Date: Wed, 4 Apr 2018 10:20:52 +0200 Subject: Workaround form field text not being drawn on broken files Try drawing with the form appearance instead of the field apparance if drawing with the field appearance fails Bug #103245 --- poppler/Annot.cc | 88 +++++++++++++++++++++++++++++++++++--------------------- poppler/Annot.h | 24 +++++++++------- 2 files changed, 68 insertions(+), 44 deletions(-) diff --git a/poppler/Annot.cc b/poppler/Annot.cc index 629b65b2..c66096e7 100644 --- a/poppler/Annot.cc +++ b/poppler/Annot.cc @@ -4035,7 +4035,7 @@ void AnnotAppearanceBuilder::writeString(const GooString &str) } // Draw the variable text or caption for a field. -void AnnotAppearanceBuilder::drawText(const GooString *text, const GooString *da, const GfxResources *resources, +bool AnnotAppearanceBuilder::drawText(const GooString *text, const GooString *da, const GfxResources *resources, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect, GBool multiline, int comb, int quadding, GBool txField, GBool forceZapfDingbats, @@ -4131,7 +4131,7 @@ void AnnotAppearanceBuilder::drawText(const GooString *text, const GooString *da if (daToks) { deleteGooList(daToks, GooString); } - return; + return false; } // get the border width @@ -4448,10 +4448,12 @@ void AnnotAppearanceBuilder::drawText(const GooString *text, const GooString *da if (fontToFree) { fontToFree->decRefCnt(); } + + return true; } // Draw the variable text or caption for a field. -void AnnotAppearanceBuilder::drawListBox(const FormFieldChoice *fieldChoice, const AnnotBorder *border, const PDFRectangle *rect, +bool AnnotAppearanceBuilder::drawListBox(const FormFieldChoice *fieldChoice, const AnnotBorder *border, const PDFRectangle *rect, const GooString *da, const GfxResources *resources, int quadding) { GooList *daToks; GooString *tok, *convertedText; @@ -4512,7 +4514,7 @@ void AnnotAppearanceBuilder::drawListBox(const FormFieldChoice *fieldChoice, con if (daToks) { deleteGooList(daToks, GooString); } - return; + return false; } convertedText = new GooString; @@ -4531,7 +4533,7 @@ void AnnotAppearanceBuilder::drawListBox(const FormFieldChoice *fieldChoice, con deleteGooList(daToks, GooString); } delete convertedText; - return; + return false; } Annot::layoutText(fieldChoice->getChoice(i), convertedText, &j, font, &w, 0.0, nullptr, gFalse); if (w > wMax) { @@ -4630,6 +4632,8 @@ void AnnotAppearanceBuilder::drawListBox(const FormFieldChoice *fieldChoice, con } delete convertedText; + + return true; } void AnnotAppearanceBuilder::drawFieldBorder(const FormField *field, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect) { @@ -4736,7 +4740,31 @@ void AnnotAppearanceBuilder::drawFieldBorder(const FormField *field, const Annot } } -void AnnotAppearanceBuilder::drawFormFieldButton(const FormFieldButton *field, const GfxResources *resources, const GooString *da, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect, const GooString *appearState, XRef *xref, bool *addedDingbatsResource) { +bool AnnotAppearanceBuilder::drawFormField(const FormField *field, const Form *form, const GfxResources *resources, const GooString *da, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect, const GooString *appearState, XRef *xref, bool *addedDingbatsResource) +{ + // draw the field contents + switch (field->getType()) { + case formButton: + return drawFormFieldButton(static_cast(field), resources, da, border, appearCharacs, rect, appearState, xref, addedDingbatsResource); + break; + case formText: + return drawFormFieldText(static_cast(field), form, resources, da, border, appearCharacs, rect); + case formChoice: + return drawFormFieldChoice(static_cast(field), form, resources, da, border, appearCharacs, rect); + break; + case formSignature: + //~unimp + break; + case formUndef: + default: + error(errSyntaxError, -1, "Unknown field type"); + } + + return false; +} + + +bool AnnotAppearanceBuilder::drawFormFieldButton(const FormFieldButton *field, const GfxResources *resources, const GooString *da, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect, const GooString *appearState, XRef *xref, bool *addedDingbatsResource) { const GooString *caption = nullptr; if (appearCharacs) caption = appearCharacs->getNormalCaption(); @@ -4747,7 +4775,7 @@ void AnnotAppearanceBuilder::drawFormFieldButton(const FormFieldButton *field, c if (appearState && appearState->cmp("Off") != 0 && field->getState(appearState->getCString())) { if (caption) { - drawText(caption, da, resources, border, appearCharacs, rect, gFalse, 0, fieldQuadCenter, gFalse, gTrue, xref, addedDingbatsResource, gFalse); + return drawText(caption, da, resources, border, appearCharacs, rect, gFalse, 0, fieldQuadCenter, gFalse, gTrue, xref, addedDingbatsResource, gFalse); } else if (appearCharacs) { const AnnotColor *aColor = appearCharacs->getBorderColor(); if (aColor) { @@ -4756,28 +4784,31 @@ void AnnotAppearanceBuilder::drawFormFieldButton(const FormFieldButton *field, c setDrawColor(aColor, gTrue); drawCircle(0.5 * dx, 0.5 * dy, 0.2 * (dx < dy ? dx : dy), gTrue); } + return true; } } } break; case formButtonPush: if (caption) - drawText(caption, da, resources, border, appearCharacs, rect, gFalse, 0, fieldQuadCenter, gFalse, gFalse, xref, addedDingbatsResource, gFalse); + return drawText(caption, da, resources, border, appearCharacs, rect, gFalse, 0, fieldQuadCenter, gFalse, gFalse, xref, addedDingbatsResource, gFalse); break; case formButtonCheck: if (appearState && appearState->cmp("Off") != 0) { if (!caption) { GooString checkMark("3"); - drawText(&checkMark, da, resources, border, appearCharacs, rect, gFalse, 0, fieldQuadCenter, gFalse, gTrue, xref, addedDingbatsResource, gFalse); + return drawText(&checkMark, da, resources, border, appearCharacs, rect, gFalse, 0, fieldQuadCenter, gFalse, gTrue, xref, addedDingbatsResource, gFalse); } else { - drawText(caption, da, resources, border, appearCharacs, rect, gFalse, 0, fieldQuadCenter, gFalse, gTrue, xref, addedDingbatsResource, gFalse); + return drawText(caption, da, resources, border, appearCharacs, rect, gFalse, 0, fieldQuadCenter, gFalse, gTrue, xref, addedDingbatsResource, gFalse); } } break; } + + return true; } -void AnnotAppearanceBuilder::drawFormFieldText(const FormFieldText *fieldText, const Form *form, const GfxResources *resources, const GooString *da, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect) { +bool AnnotAppearanceBuilder::drawFormFieldText(const FormFieldText *fieldText, const Form *form, const GfxResources *resources, const GooString *da, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect) { VariableTextQuadding quadding; const GooString *contents; @@ -4789,12 +4820,14 @@ void AnnotAppearanceBuilder::drawFormFieldText(const FormFieldText *fieldText, c if (fieldText->isComb()) comb = fieldText->getMaxLen(); - drawText(contents, da, resources, border, appearCharacs, rect, + return drawText(contents, da, resources, border, appearCharacs, rect, fieldText->isMultiline(), comb, quadding, gTrue, gFalse, nullptr, nullptr, fieldText->isPassword()); } + + return true; } -void AnnotAppearanceBuilder::drawFormFieldChoice(const FormFieldChoice *fieldChoice, const Form *form, const GfxResources *resources, const GooString *da, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect) { +bool AnnotAppearanceBuilder::drawFormFieldChoice(const FormFieldChoice *fieldChoice, const Form *form, const GfxResources *resources, const GooString *da, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect) { const GooString *selected; VariableTextQuadding quadding; @@ -4803,18 +4836,20 @@ void AnnotAppearanceBuilder::drawFormFieldChoice(const FormFieldChoice *fieldCho if (fieldChoice->isCombo()) { selected = fieldChoice->getSelectedChoice(); if (selected) { - drawText(selected, da, resources, border, appearCharacs, rect, gFalse, 0, quadding, gTrue, gFalse, nullptr, nullptr, gFalse); + return drawText(selected, da, resources, border, appearCharacs, rect, gFalse, 0, quadding, gTrue, gFalse, nullptr, nullptr, gFalse); //~ Acrobat draws a popup icon on the right side } // list box } else { - drawListBox(fieldChoice, border, rect, da, resources, quadding); + return drawListBox(fieldChoice, border, rect, da, resources, quadding); } + + return true; } void AnnotWidget::generateFieldAppearance(bool *addedDingbatsResource) { GfxResources *resources; - GooString *da; + const GooString *da; AnnotAppearanceBuilder appearBuilder; @@ -4838,23 +4873,10 @@ void AnnotWidget::generateFieldAppearance(bool *addedDingbatsResource) { resources = form->getDefaultResources(); - // draw the field contents - switch (field->getType()) { - case formButton: - appearBuilder.drawFormFieldButton(static_cast(field), resources, da, border, appearCharacs, rect, appearState, xref, addedDingbatsResource); - break; - case formText: - appearBuilder.drawFormFieldText(static_cast(field), form, resources, da, border, appearCharacs, rect); - break; - case formChoice: - appearBuilder.drawFormFieldChoice(static_cast(field), form, resources, da, border, appearCharacs, rect); - break; - case formSignature: - //~unimp - break; - case formUndef: - default: - error(errSyntaxError, -1, "Unknown field type"); + const bool success = appearBuilder.drawFormField(field, form, resources, da, border, appearCharacs, rect, appearState, xref, addedDingbatsResource); + if (!success && da != form->getDefaultAppearance()) { + da = form->getDefaultAppearance(); + appearBuilder.drawFormField(field, form, resources, da, border, appearCharacs, rect, appearState, xref, addedDingbatsResource); } const GooString *appearBuf = appearBuilder.buffer(); diff --git a/poppler/Annot.h b/poppler/Annot.h index d5944a13..c1acc065 100644 --- a/poppler/Annot.h +++ b/poppler/Annot.h @@ -514,18 +514,8 @@ public: void drawCircle(double cx, double cy, double r, GBool fill); void drawCircleTopLeft(double cx, double cy, double r); void drawCircleBottomRight(double cx, double cy, double r); - void drawText(const GooString *text, const GooString *da, const GfxResources *resources, - const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect, - GBool multiline, int comb, int quadding, - GBool txField, GBool forceZapfDingbats, - XRef *xref, bool *addedDingbatsResource, // xref and addedDingbatsResource both must not be null if forceZapfDingbats is passed - GBool password); - void drawListBox(const FormFieldChoice *fieldChoice, const AnnotBorder *border, const PDFRectangle *rect, - const GooString *da, const GfxResources *resources, int quadding); void drawFieldBorder(const FormField *field, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect); - void drawFormFieldButton(const FormFieldButton *field, const GfxResources *resources, const GooString *da, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect, const GooString *appearState, XRef *xref, bool *addedDingbatsResource); - void drawFormFieldText(const FormFieldText *fieldText, const Form *form, const GfxResources *resources, const GooString *da, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect); - void drawFormFieldChoice(const FormFieldChoice *fieldChoice, const Form *form, const GfxResources *resources, const GooString *da, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect); + bool drawFormField(const FormField *field, const Form *form, const GfxResources *resources, const GooString *da, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect, const GooString *appearState, XRef *xref, bool *addedDingbatsResource); void writeString(const GooString &str); @@ -535,6 +525,18 @@ public: const GooString *buffer() const; private: + bool drawListBox(const FormFieldChoice *fieldChoice, const AnnotBorder *border, const PDFRectangle *rect, + const GooString *da, const GfxResources *resources, int quadding); + bool drawFormFieldButton(const FormFieldButton *field, const GfxResources *resources, const GooString *da, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect, const GooString *appearState, XRef *xref, bool *addedDingbatsResource); + bool drawFormFieldText(const FormFieldText *fieldText, const Form *form, const GfxResources *resources, const GooString *da, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect); + bool drawFormFieldChoice(const FormFieldChoice *fieldChoice, const Form *form, const GfxResources *resources, const GooString *da, const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect); + bool drawText(const GooString *text, const GooString *da, const GfxResources *resources, + const AnnotBorder *border, const AnnotAppearanceCharacs *appearCharacs, const PDFRectangle *rect, + GBool multiline, int comb, int quadding, + GBool txField, GBool forceZapfDingbats, + XRef *xref, bool *addedDingbatsResource, // xref and addedDingbatsResource both must not be null if forceZapfDingbats is passed + GBool password); + GooString *appearBuf; }; -- cgit v1.2.3