diff --git a/poppler/Annot.cc b/poppler/Annot.cc index 8c950434..982ad533 100644 --- a/poppler/Annot.cc +++ b/poppler/Annot.cc @@ -1804,48 +1804,60 @@ GBool Annot::isVisible(GBool printing) { if (! optContentConfig->optContentIsVisible(&oc)) return gFalse; } return gTrue; } int Annot::getRotation() const { Page *pageobj = doc->getPage(page); assert(pageobj != nullptr); if (flags & flagNoRotate) { return (360 - pageobj->getRotate()) % 360; } else { return 0; } } void Annot::draw(Gfx *gfx, GBool printing) { - annotLocker(); if (!isVisible (printing)) return; - // draw the appearance stream - Object obj = appearance.fetch(gfx->getXRef()); + annotLocker(); + + Object obj = makeAppearance(gfx->getXRef()); + drawAppearance(gfx, obj, getDrawRect()); +} + +Object Annot::makeAppearance(XRef* xref) { + return appearance.fetch(xref); +} + +void Annot::drawAppearance(Gfx *gfx, Object& obj, const PDFRectangle& drawRect) { gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - rect->x1, rect->y1, rect->x2, rect->y2, getRotation()); + drawRect.x1, drawRect.y1, drawRect.x2, drawRect.y2, getRotation()); +} + +PDFRectangle Annot::getDrawRect() const { + return *rect; } //------------------------------------------------------------------------ // AnnotPopup //------------------------------------------------------------------------ AnnotPopup::AnnotPopup(PDFDoc *docA, PDFRectangle *rect) : Annot(docA, rect) { type = typePopup; annotObj.dictSet ("Subtype", Object(objName, "Popup")); initialize (docA, annotObj.getDict()); } AnnotPopup::AnnotPopup(PDFDoc *docA, Object *dictObject, Object *obj) : Annot(docA, dictObject, obj) { type = typePopup; initialize(docA, dictObject->getDict()); } @@ -2408,47 +2420,43 @@ void AnnotText::setIcon(GooString *new_icon) { "0.729412 0.741176 0.713725 RG 18 6 m 6 18 l S\n" \ "6 6 m 18 18 l S\n" #define ANNOT_TEXT_AP_CIRCLE \ "4.301 23 m 19.699 23 l 21.523 23 23 21.523 23 19.699 c 23 4.301 l 23\n" \ "2.477 21.523 1 19.699 1 c 4.301 1 l 2.477 1 1 2.477 1 4.301 c 1 19.699\n" \ "l 1 21.523 2.477 23 4.301 23 c h\n" \ "4.301 23 m f\n" \ "0.533333 0.541176 0.521569 RG 2.5 w\n" \ "1 J\n" \ "1 j\n" \ "[] 0.0 d\n" \ "4 M 19.5 11.5 m 19.5 7.359 16.141 4 12 4 c 7.859 4 4.5 7.359 4.5 11.5 c 4.5\n" \ "15.641 7.859 19 12 19 c 16.141 19 19.5 15.641 19.5 11.5 c h\n" \ "19.5 11.5 m S\n" \ "0.729412 0.741176 0.713725 RG 19.5 12.5 m 19.5 8.359 16.141 5 12 5 c\n" \ "7.859 5 4.5 8.359 4.5 12.5 c 4.5\n" \ "16.641 7.859 20 12 20 c 16.141 20 19.5 16.641 19.5 12.5 c h\n" \ "19.5 12.5 m S\n" -void AnnotText::draw(Gfx *gfx, GBool printing) { +Object AnnotText::makeAppearance(XRef* xref) { double ca = 1; - if (!isVisible (printing)) - return; - - annotLocker(); if (appearance.isNull()) { ca = opacity; appearBuf = new GooString (); appearBuf->append ("q\n"); if (color) setDrawColor(color, gTrue); else appearBuf->append ("1 1 1 rg\n"); if (!icon->cmp("Note")) appearBuf->append (ANNOT_TEXT_AP_NOTE); else if (!icon->cmp("Comment")) appearBuf->append (ANNOT_TEXT_AP_COMMENT); else if (!icon->cmp("Key")) appearBuf->append (ANNOT_TEXT_AP_KEY); else if (!icon->cmp("Help")) appearBuf->append (ANNOT_TEXT_AP_HELP); else if (!icon->cmp("NewParagraph")) appearBuf->append (ANNOT_TEXT_AP_NEW_PARAGRAPH); @@ -2463,51 +2471,49 @@ void AnnotText::draw(Gfx *gfx, GBool printing) { appearBuf->append ("Q\n"); // Force 24x24 rectangle PDFRectangle fixedRect(rect->x1, rect->y2 - 24, rect->x1 + 24, rect->y2); appearBBox = new AnnotAppearanceBBox(&fixedRect); double bbox[4]; appearBBox->getBBoxRect(bbox); if (ca == 1) { appearance = createForm(bbox, gFalse, nullptr); } else { Object aStream = createForm(bbox, gTrue, nullptr); delete appearBuf; appearBuf = new GooString ("/GS0 gs\n/Fm0 Do"); Dict *resDict = createResourcesDict("Fm0", std::move(aStream), "GS0", ca, nullptr); appearance = createForm(bbox, gFalse, resDict); } delete appearBuf; } - // draw the appearance stream - Object obj = appearance.fetch(gfx->getXRef()); + return appearance.fetch(xref); +} + +PDFRectangle AnnotText::getDrawRect() const { if (appearBBox) { - gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - appearBBox->getPageXMin(), appearBBox->getPageYMin(), - appearBBox->getPageXMax(), appearBBox->getPageYMax(), - getRotation()); - } else { - gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - rect->x1, rect->y1, rect->x2, rect->y2, getRotation()); + return PDFRectangle(appearBBox->getPageXMin(), appearBBox->getPageYMin(), + appearBBox->getPageXMax(), appearBBox->getPageYMax()); } + return *rect; } //------------------------------------------------------------------------ // AnnotLink //------------------------------------------------------------------------ AnnotLink::AnnotLink(PDFDoc *docA, PDFRectangle *rect) : Annot(docA, rect) { type = typeLink; annotObj.dictSet ("Subtype", Object(objName, "Link")); initialize (docA, annotObj.getDict()); } AnnotLink::AnnotLink(PDFDoc *docA, Object *dictObject, Object *obj) : Annot(docA, dictObject, obj) { type = typeLink; initialize (docA, dictObject->getDict()); } AnnotLink::~AnnotLink() { @@ -2563,51 +2569,40 @@ void AnnotLink::initialize(PDFDoc *docA, Dict *dict) { uriAction = NULL; } obj1.free(); */ obj1 = dict->lookup("QuadPoints"); if (obj1.isArray()) { quadrilaterals = new AnnotQuadrilaterals(obj1.getArray(), rect); } else { quadrilaterals = nullptr; } obj1 = dict->lookup("BS"); if (obj1.isDict()) { delete border; border = new AnnotBorderBS(obj1.getDict()); } else if (!border) { border = new AnnotBorderBS(); } } -void AnnotLink::draw(Gfx *gfx, GBool printing) { - if (!isVisible (printing)) - return; - - annotLocker(); - // draw the appearance stream - Object obj = appearance.fetch(gfx->getXRef()); - gfx->drawAnnot(&obj, border, color, - rect->x1, rect->y1, rect->x2, rect->y2, getRotation()); -} - //------------------------------------------------------------------------ // AnnotFreeText //------------------------------------------------------------------------ AnnotFreeText::AnnotFreeText(PDFDoc *docA, PDFRectangle *rect, GooString *da) : AnnotMarkup(docA, rect) { type = typeFreeText; annotObj.dictSet ("Subtype", Object(objName, "FreeText")); annotObj.dictSet("DA", Object(da->copy())); initialize (docA, annotObj.getDict()); } AnnotFreeText::AnnotFreeText(PDFDoc *docA, Object *dictObject, Object *obj) : AnnotMarkup(docA, dictObject, obj) { type = typeFreeText; initialize(docA, dictObject->getDict()); } AnnotFreeText::~AnnotFreeText() { @@ -2940,53 +2935,46 @@ void AnnotFreeText::generateFreeTextAppearance() appearBuf->append ("ET Q\n"); double bbox[4]; bbox[0] = bbox[1] = 0; bbox[2] = rect->x2 - rect->x1; bbox[3] = rect->y2 - rect->y1; if (ca == 1) { appearance = createForm(bbox, gFalse, fontResDict); } else { Object aStream = createForm(bbox, gTrue, fontResDict); delete appearBuf; appearBuf = new GooString ("/GS0 gs\n/Fm0 Do"); Dict *resDict = createResourcesDict("Fm0", std::move(aStream), "GS0", ca, nullptr); appearance = createForm(bbox, gFalse, resDict); } delete appearBuf; } -void AnnotFreeText::draw(Gfx *gfx, GBool printing) { - if (!isVisible (printing)) - return; - - annotLocker(); +Object AnnotFreeText::makeAppearance(XRef* xref) { if (appearance.isNull()) { generateFreeTextAppearance(); } - // draw the appearance stream - Object obj = appearance.fetch(gfx->getXRef()); - gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - rect->x1, rect->y1, rect->x2, rect->y2, getRotation()); + return appearance.fetch(xref); } // Before retrieving the res dict, regenerate the appearance stream if needed, // because AnnotFreeText::draw needs to store font info in the res dict Object AnnotFreeText::getAppearanceResDict() { if (appearance.isNull()) { generateFreeTextAppearance(); } return Annot::getAppearanceResDict(); } //------------------------------------------------------------------------ // AnnotLine //------------------------------------------------------------------------ AnnotLine::AnnotLine(PDFDoc *docA, PDFRectangle *rect) : AnnotMarkup(docA, rect) { type = typeLine; annotObj.dictSet ("Subtype", Object(objName, "Line")); @@ -3378,60 +3366,54 @@ void AnnotLine::generateLineAppearance() appearBBox->extendTo (tx, ty); } appearBuf->append ("Q\n"); double bbox[4]; appearBBox->getBBoxRect(bbox); if (ca == 1) { appearance = createForm(bbox, gFalse, fontResDict); } else { Object aStream = createForm(bbox, gTrue, fontResDict); delete appearBuf; appearBuf = new GooString ("/GS0 gs\n/Fm0 Do"); Dict *resDict = createResourcesDict("Fm0", std::move(aStream), "GS0", ca, nullptr); appearance = createForm(bbox, gFalse, resDict); } delete appearBuf; } -void AnnotLine::draw(Gfx *gfx, GBool printing) { - if (!isVisible (printing)) - return; - - annotLocker(); +Object AnnotLine::makeAppearance(XRef* xref) { if (appearance.isNull()) { generateLineAppearance(); } - // draw the appearance stream - Object obj = appearance.fetch(gfx->getXRef()); + return appearance.fetch(xref); +} + +PDFRectangle AnnotLine::getDrawRect() const { if (appearBBox) { - gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - appearBBox->getPageXMin(), appearBBox->getPageYMin(), - appearBBox->getPageXMax(), appearBBox->getPageYMax(), - getRotation()); - } else { - gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - rect->x1, rect->y1, rect->x2, rect->y2, getRotation()); + return PDFRectangle(appearBBox->getPageXMin(), appearBBox->getPageYMin(), + appearBBox->getPageXMax(), appearBBox->getPageYMax()); } + return *rect; } // Before retrieving the res dict, regenerate the appearance stream if needed, // because AnnotLine::draw may need to store font info in the res dict Object AnnotLine::getAppearanceResDict() { if (appearance.isNull()) { generateLineAppearance(); } return Annot::getAppearanceResDict(); } //------------------------------------------------------------------------ // AnnotTextMarkup //------------------------------------------------------------------------ AnnotTextMarkup::AnnotTextMarkup(PDFDoc *docA, PDFRectangle *rect, AnnotSubtype subType) : AnnotMarkup(docA, rect) { switch (subType) { case typeHighlight: annotObj.dictSet ("Subtype", Object(objName, "Highlight")); break; @@ -3525,48 +3507,44 @@ void AnnotTextMarkup::setQuadrilaterals(AnnotQuadrilaterals *quadPoints) { Array *a = new Array(xref); for (int i = 0; i < quadPoints->getQuadrilateralsLength(); ++i) { a->add(Object(quadPoints->getX1(i))); a->add(Object(quadPoints->getY1(i))); a->add(Object(quadPoints->getX2(i))); a->add(Object(quadPoints->getY2(i))); a->add(Object(quadPoints->getX3(i))); a->add(Object(quadPoints->getY3(i))); a->add(Object(quadPoints->getX4(i))); a->add(Object(quadPoints->getY4(i))); } delete quadrilaterals; quadrilaterals = new AnnotQuadrilaterals(a, rect); annotObj.dictSet ("QuadPoints", Object(a)); invalidateAppearance(); } -void AnnotTextMarkup::draw(Gfx *gfx, GBool printing) { +Object AnnotTextMarkup::makeAppearance(XRef* xref) { double ca = 1; int i; - if (!isVisible (printing)) - return; - - annotLocker(); if (appearance.isNull() || type == typeHighlight) { GBool blendMultiply = gTrue; ca = opacity; appearBuf = new GooString (); appearBuf->append ("q\n"); /* Adjust BBox */ delete appearBBox; appearBBox = new AnnotAppearanceBBox(rect); for (i = 0; i < quadrilaterals->getQuadrilateralsLength(); ++i) { appearBBox->extendTo (quadrilaterals->getX1(i) - rect->x1, quadrilaterals->getY1(i) - rect->y1); appearBBox->extendTo (quadrilaterals->getX2(i) - rect->x1, quadrilaterals->getY2(i) - rect->y1); appearBBox->extendTo (quadrilaterals->getX3(i) - rect->x1, quadrilaterals->getY3(i) - rect->y1); appearBBox->extendTo (quadrilaterals->getX4(i) - rect->x1, quadrilaterals->getY4(i) - rect->y1); } switch (type) { case typeUnderline: if (color) { @@ -3683,78 +3661,81 @@ void AnnotTextMarkup::draw(Gfx *gfx, GBool printing) { bbox[2] = appearBBox->getPageXMax(); bbox[3] = appearBBox->getPageYMax(); aStream = createForm(bbox, gTrue, nullptr); delete appearBuf; appearBuf = new GooString ("/GS0 gs\n/Fm0 Do"); Dict *resDict = createResourcesDict("Fm0", std::move(aStream), "GS0", 1, blendMultiply ? "Multiply" : nullptr); if (ca == 1) { appearance = createForm(bbox, gFalse, resDict); } else { aStream = createForm(bbox, gTrue, resDict); delete appearBuf; appearBuf = new GooString ("/GS0 gs\n/Fm0 Do"); Dict *resDict2 = createResourcesDict("Fm0", std::move(aStream), "GS0", ca, nullptr); appearance = createForm(bbox, gFalse, resDict2); } delete appearBuf; } - // draw the appearance stream - Object obj = appearance.fetch(gfx->getXRef()); + return appearance.fetch(xref); +} + +PDFRectangle AnnotTextMarkup::getDrawRect() const { if (appearBBox) { - gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - appearBBox->getPageXMin(), appearBBox->getPageYMin(), - appearBBox->getPageXMax(), appearBBox->getPageYMax(), - getRotation()); - } else { - gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - rect->x1, rect->y1, rect->x2, rect->y2, getRotation()); + return PDFRectangle(appearBBox->getPageXMin(), appearBBox->getPageYMin(), + appearBBox->getPageXMax(), appearBBox->getPageYMax()); } + return *rect; } //------------------------------------------------------------------------ // AnnotWidget //------------------------------------------------------------------------ AnnotWidget::AnnotWidget(PDFDoc *docA, Object *dictObject, Object *obj) : Annot(docA, dictObject, obj) { type = typeWidget; field = nullptr; + fontResourceDict = nullptr; initialize(docA, dictObject->getDict()); } AnnotWidget::AnnotWidget(PDFDoc *docA, Object *dictObject, Object *obj, FormField *fieldA) : Annot(docA, dictObject, obj) { type = typeWidget; field = fieldA; + fontResourceDict = nullptr; initialize(docA, dictObject->getDict()); } AnnotWidget::~AnnotWidget() { if (appearCharacs) delete appearCharacs; if (action) delete action; + if (fontResourceDict) + delete fontResourceDict; + if (parent) delete parent; } void AnnotWidget::initialize(PDFDoc *docA, Dict *dict) { Object obj1; form = doc->getCatalog()->getForm(); obj1 = dict->lookup("H"); if (obj1.isName()) { const char *modeName = obj1.getName(); if(!strcmp(modeName, "N")) { mode = highlightModeNone; } else if(!strcmp(modeName, "O")) { mode = highlightModeOutline; } else if(!strcmp(modeName, "P") || !strcmp(modeName, "T")) { mode = highlightModePush; } else { @@ -4916,80 +4897,86 @@ void AnnotWidget::updateAppearanceStream() // create a new AP dictionary containing the new appearance stream. // Otherwise, just update the stream we had created previously. if (updatedAppearanceStream.num == -1) { // Write the appearance stream updatedAppearanceStream = xref->addIndirectObject(&obj1); // Write the AP dictionary obj1 = Object(new Dict(xref)); obj1.dictAdd(copyString("N"), Object(updatedAppearanceStream.num, updatedAppearanceStream.gen)); // Update our internal pointers to the appearance dictionary appearStreams = new AnnotAppearance(doc, &obj1); update("AP", std::move(obj1)); } else { // Replace the existing appearance stream xref->setModifiedObject(&obj1, updatedAppearanceStream); } } -void AnnotWidget::draw(Gfx *gfx, GBool printing) { - if (!isVisible (printing)) - return; - - annotLocker(); +Object AnnotWidget::makeAppearance(XRef* xref) { addDingbatsResource = gFalse; // Only construct the appearance stream when // - annot doesn't have an AP or // - NeedAppearances is true if (field) { - if (appearance.isNull() || (form && form->getNeedAppearances())) + if (appearance.isNull() || (form && form->getNeedAppearances())) { generateFieldAppearance(); + } } - // draw the appearance stream - Object obj = appearance.fetch(gfx->getXRef()); - if (addDingbatsResource) { + if (addDingbatsResource && !fontResourceDict) { + // May be requested by AnnotWidget::drawText. // We are forcing ZaDb but the font does not exist // so create a fake one - Dict *fontDict = new Dict(gfx->getXRef()); + Dict *fontDict = new Dict(xref); fontDict->add(copyString("BaseFont"), Object(objName, "ZapfDingbats")); fontDict->add(copyString("Subtype"), Object(objName, "Type1")); - Dict *fontsDict = new Dict(gfx->getXRef()); + Dict *fontsDict = new Dict(xref); fontsDict->add(copyString("ZaDb"), Object(fontDict)); - Dict *dict = new Dict(gfx->getXRef()); - dict->add(copyString("Font"), Object(fontsDict)); - gfx->pushResources(dict); - delete dict; + fontResourceDict = new Dict(xref); + fontResourceDict->add(copyString("Font"), Object(fontsDict)); + } else if (!addDingbatsResource && fontResourceDict) { + // Appearance has changed, fake font not required any longer. Cleanup. + delete fontResourceDict; + fontResourceDict = nullptr; } - gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - rect->x1, rect->y1, rect->x2, rect->y2, getRotation()); - if (addDingbatsResource) { + + return appearance.fetch(xref); +} + +void AnnotWidget::drawAppearance(Gfx *gfx, Object& obj, const PDFRectangle& drawRect) { + if (fontResourceDict != nullptr) { + gfx->pushResources(fontResourceDict); + } + + Annot::drawAppearance(gfx, obj, drawRect); + + if (fontResourceDict != nullptr) { gfx->popResources(); } } - //------------------------------------------------------------------------ // AnnotMovie //------------------------------------------------------------------------ AnnotMovie::AnnotMovie(PDFDoc *docA, PDFRectangle *rect, Movie *movieA) : Annot(docA, rect) { type = typeMovie; annotObj.dictSet ("Subtype", Object(objName, "Movie")); movie = movieA->copy(); // TODO: create movie dict from movieA initialize(docA, annotObj.getDict()); } AnnotMovie::AnnotMovie(PDFDoc *docA, Object *dictObject, Object *obj) : Annot(docA, dictObject, obj) { type = typeMovie; initialize(docA, dictObject->getDict()); } @@ -5011,117 +4998,110 @@ void AnnotMovie::initialize(PDFDoc *docA, Dict* dict) { Object movieDict = dict->lookup("Movie"); if (movieDict.isDict()) { Object obj2 = dict->lookup("A"); if (obj2.isDict()) movie = new Movie (&movieDict, &obj2); else movie = new Movie (&movieDict); if (!movie->isOk()) { delete movie; movie = nullptr; ok = gFalse; } } else { error(errSyntaxError, -1, "Bad Annot Movie"); movie = nullptr; ok = gFalse; } } -void AnnotMovie::draw(Gfx *gfx, GBool printing) { - if (!isVisible (printing)) - return; - - annotLocker(); +Object AnnotMovie::makeAppearance(XRef* xref) { if (appearance.isNull() && movie->getShowPoster()) { int width, height; Object poster = movie->getPoster(); movie->getAspect(&width, &height); if (width != -1 && height != -1 && !poster.isNone()) { appearBuf = new GooString (); appearBuf->append ("q\n"); appearBuf->appendf ("{0:d} 0 0 {1:d} 0 0 cm\n", width, height); appearBuf->append ("/MImg Do\n"); appearBuf->append ("Q\n"); - Dict *imgDict = new Dict(gfx->getXRef()); + Dict *imgDict = new Dict(xref); imgDict->set("MImg", std::move(poster)); - Dict *resDict = new Dict(gfx->getXRef()); + Dict *resDict = new Dict(xref); resDict->set("XObject", Object(imgDict)); - Dict *formDict = new Dict(gfx->getXRef()); + Dict *formDict = new Dict(xref); formDict->set("Length", Object(appearBuf->getLength())); formDict->set("Subtype", Object(objName, "Form")); formDict->set("Name", Object(objName, "FRM")); - Array *bboxArray = new Array(gfx->getXRef()); + Array *bboxArray = new Array(xref); bboxArray->add(Object(0)); bboxArray->add(Object(0)); bboxArray->add(Object(width)); bboxArray->add(Object(height)); formDict->set("BBox", Object(bboxArray)); - Array *matrix = new Array(gfx->getXRef()); + Array *matrix = new Array(xref); matrix->add(Object(1)); matrix->add(Object(0)); matrix->add(Object(0)); matrix->add(Object(1)); matrix->add(Object(-width / 2)); matrix->add(Object(-height / 2)); formDict->set("Matrix", Object(matrix)); formDict->set("Resources", Object(resDict)); MemStream *mStream = new MemStream(copyString(appearBuf->getCString()), 0, appearBuf->getLength(), Object(formDict)); mStream->setNeedFree(gTrue); delete appearBuf; - Dict *dict = new Dict(gfx->getXRef()); + Dict *dict = new Dict(xref); dict->set("FRM", Object(static_cast(mStream))); - Dict *resDict2 = new Dict(gfx->getXRef()); + Dict *resDict2 = new Dict(xref); resDict2->set("XObject", Object(dict)); appearBuf = new GooString (); appearBuf->append ("q\n"); appearBuf->appendf ("0 0 {0:d} {1:d} re W n\n", width, height); appearBuf->append ("q\n"); appearBuf->appendf ("0 0 {0:d} {1:d} re W n\n", width, height); appearBuf->appendf ("1 0 0 1 {0:d} {1:d} cm\n", width / 2, height / 2); appearBuf->append ("/FRM Do\n"); appearBuf->append ("Q\n"); appearBuf->append ("Q\n"); double bbox[4]; bbox[0] = bbox[1] = 0; bbox[2] = width; bbox[3] = height; appearance = createForm(bbox, gFalse, resDict2); delete appearBuf; } } - // draw the appearance stream - Object obj = appearance.fetch(gfx->getXRef()); - gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - rect->x1, rect->y1, rect->x2, rect->y2, getRotation()); + return appearance.fetch(xref); } //------------------------------------------------------------------------ // AnnotScreen //------------------------------------------------------------------------ AnnotScreen::AnnotScreen(PDFDoc *docA, PDFRectangle *rect) : Annot(docA, rect) { type = typeScreen; annotObj.dictSet ("Subtype", Object(objName, "Screen")); initialize(docA, annotObj.getDict()); } AnnotScreen::AnnotScreen(PDFDoc *docA, Object *dictObject, Object *obj) : Annot(docA, dictObject, obj) { type = typeScreen; initialize(docA, dictObject->getDict()); } AnnotScreen::~AnnotScreen() { @@ -5300,47 +5280,43 @@ void AnnotGeometry::setType(AnnotSubtype new_type) { } type = new_type; update("Subtype", Object(objName, typeName)); invalidateAppearance(); } void AnnotGeometry::setInteriorColor(AnnotColor *new_color) { delete interiorColor; if (new_color) { Object obj1 = new_color->writeToObject(xref); update ("IC", std::move(obj1)); interiorColor = new_color; } else { interiorColor = nullptr; } invalidateAppearance(); } -void AnnotGeometry::draw(Gfx *gfx, GBool printing) { +Object AnnotGeometry::makeAppearance(XRef* xref) { double ca = 1; - if (!isVisible (printing)) - return; - - annotLocker(); if (appearance.isNull()) { ca = opacity; appearBuf = new GooString (); appearBuf->append ("q\n"); if (color) setDrawColor(color, gFalse); double borderWidth = border->getWidth(); setLineStyleForBorder(border); if (interiorColor) setDrawColor(interiorColor, gTrue); if (type == typeSquare) { appearBuf->appendf ("{0:.2f} {1:.2f} {2:.2f} {3:.2f} re\n", borderWidth / 2.0, borderWidth / 2.0, (rect->x2 - rect->x1) - borderWidth, (rect->y2 - rect->y1) - borderWidth); } else { @@ -5398,44 +5374,41 @@ void AnnotGeometry::draw(Gfx *gfx, GBool printing) { appearBuf->append ("Q\n"); double bbox[4]; bbox[0] = bbox[1] = 0; bbox[2] = rect->x2 - rect->x1; bbox[3] = rect->y2 - rect->y1; if (ca == 1) { appearance = createForm(bbox, gFalse, nullptr); } else { Object aStream = createForm(bbox, gTrue, nullptr); delete appearBuf; appearBuf = new GooString ("/GS0 gs\n/Fm0 Do"); Dict *resDict = createResourcesDict("Fm0", std::move(aStream), "GS0", ca, nullptr); appearance = createForm(bbox, gFalse, resDict); } delete appearBuf; } - // draw the appearance stream - Object obj = appearance.fetch(gfx->getXRef()); - gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - rect->x1, rect->y1, rect->x2, rect->y2, getRotation()); + return appearance.fetch(xref); } //------------------------------------------------------------------------ // AnnotPolygon //------------------------------------------------------------------------ AnnotPolygon::AnnotPolygon(PDFDoc *docA, PDFRectangle *rect, AnnotSubtype subType) : AnnotMarkup(docA, rect) { switch (subType) { case typePolygon: annotObj.dictSet ("Subtype", Object(objName, "Polygon")); break; case typePolyLine: annotObj.dictSet ("Subtype", Object(objName, "PolyLine")); break; default: assert (0 && "Invalid subtype for AnnotGeometry\n"); } // Store dummy path with one null vertex only Array *a = new Array(doc->getXRef()); @@ -5596,47 +5569,43 @@ void AnnotPolygon::setInteriorColor(AnnotColor *new_color) { interiorColor = new_color; } else { interiorColor = nullptr; } invalidateAppearance(); } void AnnotPolygon::setIntent(AnnotPolygonIntent new_intent) { const char *intentName; intent = new_intent; if (new_intent == polygonCloud) intentName = "PolygonCloud"; else if (new_intent == polylineDimension) intentName = "PolyLineDimension"; else // polygonDimension intentName = "PolygonDimension"; update ("IT", Object(objName, intentName)); } -void AnnotPolygon::draw(Gfx *gfx, GBool printing) { +Object AnnotPolygon::makeAppearance(XRef* xref) { double ca = 1; - if (!isVisible (printing)) - return; - - annotLocker(); if (appearance.isNull()) { appearBBox = new AnnotAppearanceBBox(rect); ca = opacity; appearBuf = new GooString (); appearBuf->append ("q\n"); if (color) { setDrawColor(color, gFalse); } setLineStyleForBorder(border); appearBBox->setBorderWidth(std::max(1., border->getWidth())); if (interiorColor) { setDrawColor(interiorColor, gTrue); } if (vertices->getCoordsLength() != 0) { appearBuf->appendf ("{0:.2f} {1:.2f} m\n", vertices->getX(0) - rect->x1, vertices->getY(0) - rect->y1); @@ -5658,51 +5627,49 @@ void AnnotPolygon::draw(Gfx *gfx, GBool printing) { } } appearBuf->append ("Q\n"); double bbox[4]; appearBBox->getBBoxRect(bbox); if (ca == 1) { appearance = createForm(bbox, gFalse, nullptr); } else { Object aStream = createForm(bbox, gTrue, nullptr); delete appearBuf; appearBuf = new GooString ("/GS0 gs\n/Fm0 Do"); Dict *resDict = createResourcesDict("Fm0", std::move(aStream), "GS0", ca, nullptr); appearance = createForm(bbox, gFalse, resDict); } delete appearBuf; } - // draw the appearance stream - Object obj = appearance.fetch(gfx->getXRef()); + return appearance.fetch(xref); +} + +PDFRectangle AnnotPolygon::getDrawRect() const { if (appearBBox) { - gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - appearBBox->getPageXMin(), appearBBox->getPageYMin(), - appearBBox->getPageXMax(), appearBBox->getPageYMax(), - getRotation()); - } else { - gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - rect->x1, rect->y1, rect->x2, rect->y2, getRotation()); + return PDFRectangle(appearBBox->getPageXMin(), appearBBox->getPageYMin(), + appearBBox->getPageXMax(), appearBBox->getPageYMax()); } + return *rect; } //------------------------------------------------------------------------ // AnnotCaret //------------------------------------------------------------------------ AnnotCaret::AnnotCaret(PDFDoc *docA, PDFRectangle *rect) : AnnotMarkup(docA, rect) { type = typeCaret; annotObj.dictSet ("Subtype", Object(objName, "Caret")); initialize(docA, annotObj.getDict()); } AnnotCaret::AnnotCaret(PDFDoc *docA, Object *dictObject, Object *obj) : AnnotMarkup(docA, dictObject, obj) { type = typeCaret; initialize(docA, dictObject->getDict()); } AnnotCaret::~AnnotCaret() { @@ -5814,47 +5781,43 @@ void AnnotInk::parseInkList(Array *array) { void AnnotInk::freeInkList() { if (inkList) { for (int i = 0; i < inkListLength; ++i) delete inkList[i]; gfree(inkList); } } void AnnotInk::setInkList(AnnotPath **paths, int n_paths) { freeInkList(); Array *a = new Array(xref); writeInkList(paths, n_paths, a); parseInkList(a); annotObj.dictSet ("InkList", Object(a)); invalidateAppearance(); } -void AnnotInk::draw(Gfx *gfx, GBool printing) { +Object AnnotInk::makeAppearance(XRef* xref) { double ca = 1; - if (!isVisible (printing)) - return; - - annotLocker(); if (appearance.isNull()) { appearBBox = new AnnotAppearanceBBox(rect); ca = opacity; appearBuf = new GooString (); appearBuf->append ("q\n"); if (color) { setDrawColor(color, gFalse); } setLineStyleForBorder(border); appearBBox->setBorderWidth(std::max(1., border->getWidth())); for (int i = 0; i < inkListLength; ++i) { const AnnotPath * path = inkList[i]; if (path && path->getCoordsLength() != 0) { appearBuf->appendf ("{0:.2f} {1:.2f} m\n", path->getX(0) - rect->x1, path->getY(0) - rect->y1); appearBBox->extendTo (path->getX(0) - rect->x1, path->getY(0) - rect->y1); @@ -5867,51 +5830,49 @@ void AnnotInk::draw(Gfx *gfx, GBool printing) { } } appearBuf->append ("Q\n"); double bbox[4]; appearBBox->getBBoxRect(bbox); if (ca == 1) { appearance = createForm(bbox, gFalse, nullptr); } else { Object aStream = createForm(bbox, gTrue, nullptr); delete appearBuf; appearBuf = new GooString ("/GS0 gs\n/Fm0 Do"); Dict *resDict = createResourcesDict("Fm0", std::move(aStream), "GS0", ca, nullptr); appearance = createForm(bbox, gFalse, resDict); } delete appearBuf; } - // draw the appearance stream - Object obj = appearance.fetch(gfx->getXRef()); + return appearance.fetch(xref); +} + +PDFRectangle AnnotInk::getDrawRect() const { if (appearBBox) { - gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - appearBBox->getPageXMin(), appearBBox->getPageYMin(), - appearBBox->getPageXMax(), appearBBox->getPageYMax(), - getRotation()); - } else { - gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - rect->x1, rect->y1, rect->x2, rect->y2, getRotation()); + return PDFRectangle(appearBBox->getPageXMin(), appearBBox->getPageYMin(), + appearBBox->getPageXMax(), appearBBox->getPageYMax()); } + return *rect; } //------------------------------------------------------------------------ // AnnotFileAttachment //------------------------------------------------------------------------ AnnotFileAttachment::AnnotFileAttachment(PDFDoc *docA, PDFRectangle *rect, GooString *filename) : AnnotMarkup(docA, rect) { type = typeFileAttachment; annotObj.dictSet("Subtype", Object(objName, "FileAttachment")); annotObj.dictSet("FS", Object(filename->copy())); initialize(docA, annotObj.getDict()); } AnnotFileAttachment::AnnotFileAttachment(PDFDoc *docA, Object *dictObject, Object *obj) : AnnotMarkup(docA, dictObject, obj) { type = typeFileAttachment; initialize(docA, dictObject->getDict()); } @@ -6034,87 +5995,80 @@ void AnnotFileAttachment::initialize(PDFDoc *docA, Dict* dict) { "0.533333 0.541176 0.521569 RG 1 w\n" \ "0 j\n" \ "11.949 13.184 m 16.191 8.941 l S\n" \ "0.729412 0.741176 0.713725 RG 11.949 14.184 m 16.191 9.941 l S\n" \ "0.533333 0.541176 0.521569 RG 14.07 6.82 m 9.828 11.062 l S\n" \ "0.729412 0.741176 0.713725 RG 14.07 7.82 m 9.828 12.062 l S\n" \ "0.533333 0.541176 0.521569 RG 6.93 15.141 m 8 20 14.27 20.5 16 20.5 c\n" \ "18.094 20.504 19.5 20 19.5 18 c 19.5 16.699 20.91 16.418 22.5 16.5 c S\n" \ "0.729412 0.741176 0.713725 RG 0.999781 w\n" \ "1 j\n" \ "q 1 0 0 -1 0 24 cm\n" \ "8.492 7.707 m 8.492 8.535 7.82 9.207 6.992 9.207 c 6.164 9.207 5.492\n" \ "8.535 5.492 7.707 c 5.492 6.879 6.164 6.207 6.992 6.207 c 7.82 6.207\n" \ "8.492 6.879 8.492 7.707 c h\n" \ "8.492 7.707 m S Q\n" \ "1 w\n" \ "0 j\n" \ "6.93 16.141 m 8 21 14.27 21.5 16 21.5 c 18.094 21.504 19.5 21 19.5 19 c\n" \ "19.5 17.699 20.91 17.418 22.5 17.5 c S\n" -void AnnotFileAttachment::draw(Gfx *gfx, GBool printing) { +Object AnnotFileAttachment::makeAppearance(XRef* xref) { double ca = 1; - if (!isVisible (printing)) - return; - - annotLocker(); if (appearance.isNull()) { ca = opacity; appearBuf = new GooString (); appearBuf->append ("q\n"); if (color) setDrawColor(color, gTrue); else appearBuf->append ("1 1 1 rg\n"); if (!name->cmp("PushPin")) appearBuf->append (ANNOT_FILE_ATTACHMENT_AP_PUSHPIN); else if (!name->cmp("Paperclip")) appearBuf->append (ANNOT_FILE_ATTACHMENT_AP_PAPERCLIP); else if (!name->cmp("Graph")) appearBuf->append (ANNOT_FILE_ATTACHMENT_AP_GRAPH); else if (!name->cmp("Tag")) appearBuf->append (ANNOT_FILE_ATTACHMENT_AP_TAG); appearBuf->append ("Q\n"); double bbox[4]; bbox[0] = bbox[1] = 0; bbox[2] = bbox[3] = 24; if (ca == 1) { appearance = createForm (bbox, gFalse, nullptr); } else { Object aStream = createForm (bbox, gTrue, nullptr); delete appearBuf; appearBuf = new GooString ("/GS0 gs\n/Fm0 Do"); Dict *resDict = createResourcesDict("Fm0", std::move(aStream), "GS0", ca, nullptr); appearance = createForm(bbox, gFalse, resDict); } delete appearBuf; } - // draw the appearance stream - Object obj = appearance.fetch(gfx->getXRef()); - gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - rect->x1, rect->y1, rect->x2, rect->y2, getRotation()); + return appearance.fetch(xref); } //------------------------------------------------------------------------ // AnnotSound //------------------------------------------------------------------------ AnnotSound::AnnotSound(PDFDoc *docA, PDFRectangle *rect, Sound *soundA) : AnnotMarkup(docA, rect) { type = typeSound; annotObj.dictSet ("Subtype", Object(objName, "Sound")); annotObj.dictSet ("Sound", soundA->getObject()->copy()); initialize(docA, annotObj.getDict()); } AnnotSound::AnnotSound(PDFDoc *docA, Object *dictObject, Object *obj) : AnnotMarkup(docA, dictObject, obj) { type = typeSound; initialize(docA, dictObject->getDict()); } @@ -6188,84 +6142,76 @@ void AnnotSound::initialize(PDFDoc *docA, Dict* dict) { "17.5 14.5 m 17.5 11.973 l 17.5 8.941 15.047 6.5 12 6.5 c 8.953 6.5 6.5\n" \ "8.941 6.5 11.973 c 6.5 14.5 l S\n" \ "2 w\n" \ "0 J\n" \ "12 6.52 m 12 3 l S\n" \ "1 J\n" \ "8 3 m 16 3 l S\n" \ "0.729412 0.741176 0.713725 RG 12 21 m 12 21 l 13.656 21 15 19.656 15 18 c\n" \ "15 14 l 15 12.344 13.656 11 12 11 c 12 11 l 10.344 11 9 12.344 9 14 c\n" \ "9 18 l 9 19.656 10.344 21 12 21 c h\n" \ "12 21 m S\n" \ "1 w\n" \ "17.5 15.5 m 17.5 12.973 l 17.5 9.941 15.047 7.5 12 7.5 c 8.953 7.5 6.5\n" \ "9.941 6.5 12.973 c 6.5 15.5 l S\n" \ "2 w\n" \ "0 J\n" \ "12 7.52 m 12 4 l S\n" \ "1 J\n" \ "8 4 m 16 4 l S\n" -void AnnotSound::draw(Gfx *gfx, GBool printing) { - Object obj; +Object AnnotSound::makeAppearance(XRef* xref) { double ca = 1; - if (!isVisible (printing)) - return; - - annotLocker(); if (appearance.isNull()) { ca = opacity; appearBuf = new GooString (); appearBuf->append ("q\n"); if (color) setDrawColor(color, gTrue); else appearBuf->append ("1 1 1 rg\n"); if (!name->cmp("Speaker")) appearBuf->append (ANNOT_SOUND_AP_SPEAKER); else if (!name->cmp("Mic")) appearBuf->append (ANNOT_SOUND_AP_MIC); appearBuf->append ("Q\n"); double bbox[4]; bbox[0] = bbox[1] = 0; bbox[2] = bbox[3] = 24; if (ca == 1) { appearance = createForm(bbox, gFalse, nullptr); } else { Object aStream = createForm(bbox, gTrue, nullptr); delete appearBuf; appearBuf = new GooString ("/GS0 gs\n/Fm0 Do"); Dict *resDict = createResourcesDict("Fm0", std::move(aStream), "GS0", ca, nullptr); appearance = createForm(bbox, gFalse, resDict); } delete appearBuf; } - // draw the appearance stream - obj = appearance.fetch(gfx->getXRef()); - gfx->drawAnnot(&obj, (AnnotBorder *)nullptr, color, - rect->x1, rect->y1, rect->x2, rect->y2, getRotation()); + return appearance.fetch(xref); } //------------------------------------------------------------------------ // Annot3D //------------------------------------------------------------------------ Annot3D::Annot3D(PDFDoc *docA, PDFRectangle *rect) : Annot(docA, rect) { type = type3D; annotObj.dictSet ("Subtype", Object(objName, "3D")); initialize(docA, annotObj.getDict()); } Annot3D::Annot3D(PDFDoc *docA, Object *dictObject, Object *obj) : Annot(docA, dictObject, obj) { type = type3D; initialize(docA, dictObject->getDict()); } diff --git a/poppler/Annot.h b/poppler/Annot.h index e061a8c5..dd737841 100644 --- a/poppler/Annot.h +++ b/poppler/Annot.h @@ -560,41 +560,42 @@ public: actionPageClosing, ///< Performed when the page containing the annotation is closed actionPageVisible, ///< Performed when the page containing the annotation becomes visible actionPageInvisible ///< Performed when the page containing the annotation becomes invisible }; enum FormAdditionalActionsType { actionFieldModified, ///< Performed when the when the user modifies the field actionFormatField, ///< Performed before the field is formatted to display its value actionValidateField, ///< Performed when the field value changes actionCalculateField, ///< Performed when the field needs to be recalculated }; Annot(PDFDoc *docA, PDFRectangle *rectA); Annot(PDFDoc *docA, Object *dictObject); Annot(PDFDoc *docA, Object *dictObject, Object *obj); GBool isOk() { return ok; } void incRefCnt(); void decRefCnt(); - virtual void draw(Gfx *gfx, GBool printing); + void draw(Gfx *gfx, GBool printing); + // Get the resource dict of the appearance stream virtual Object getAppearanceResDict(); GBool match(Ref *refA) { return ref.num == refA->num && ref.gen == refA->gen; } double getXMin(); double getYMin(); double getXMax(); double getYMax(); double getFontSize() { return fontSize; } void setRect(PDFRectangle *rect); void setRect(double x1, double y1, double x2, double y2); // Sets the annot contents to new_content // new_content should never be NULL virtual void setContents(GooString *new_content); void setName(GooString *new_name); @@ -627,40 +628,44 @@ public: AnnotBorder *getBorder() const { return border; } AnnotColor *getColor() const { return color; } int getTreeKey() const { return treeKey; } int getId() { return ref.num; } // Check if point is inside the annot rectangle. GBool inRect(double x, double y) const; private: void readArrayNum(Object *pdfArray, int key, double *value); // write vStr[i:j[ in appearBuf void initialize (PDFDoc *docA, Dict *dict); void setPage (int new_page, GBool updateP); // Called by Page::addAnnot and Annots ctor protected: virtual ~Annot(); virtual void removeReferencedObjects(); // Called by Page::removeAnnot + virtual Object makeAppearance(XRef* xref); + virtual PDFRectangle getDrawRect() const; + virtual void drawAppearance(Gfx *gfx, Object& obj, const PDFRectangle& drawRect); + void setDrawColor(AnnotColor *color, GBool fill); void setLineStyleForBorder(AnnotBorder *border); 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 layoutText(GooString *text, GooString *outBuf, int *i, GfxFont *font, double *width, double widthLimit, int *charCount, GBool noReencode); void writeString(GooString *str, GooString *appearBuf); Object createForm(double *bbox, GBool transparencyGroup, Dict *resDict); Dict *createResourcesDict(const char *formName, Object &&formStream, const char *stateName, double opacity, const char *blendMode); GBool isVisible(GBool printing); int getRotation() const; // Updates the field key of the annotation dictionary // and sets M to the current time void update(const char *key, Object &&value); // Delete appearance streams and reset appearance state @@ -784,81 +789,82 @@ private: class AnnotText: public AnnotMarkup { public: enum AnnotTextState { stateUnknown, // Marked state model stateMarked, // Marked stateUnmarked, // Unmarked // Review state model stateAccepted, // Accepted stateRejected, // Rejected stateCancelled, // Cancelled stateCompleted, // Completed stateNone // None }; AnnotText(PDFDoc *docA, PDFRectangle *rect); AnnotText(PDFDoc *docA, Object *dictObject, Object *obj); ~AnnotText(); - void draw(Gfx *gfx, GBool printing) override; - // getters GBool getOpen() const { return open; } GooString *getIcon() const { return icon; } AnnotTextState getState() const { return state; } void setOpen(GBool openA); void setIcon(GooString *new_icon); private: void initialize(PDFDoc *docA, Dict *dict); + Object makeAppearance(XRef* xref) override; + PDFRectangle getDrawRect() const override; + GBool open; // Open (Default false) GooString *icon; // Name (Default Note) AnnotTextState state; // State (Default Umarked if // StateModel Marked // None if StareModel Review) }; //------------------------------------------------------------------------ // AnnotMovie //------------------------------------------------------------------------ class AnnotMovie: public Annot { public: AnnotMovie(PDFDoc *docA, PDFRectangle *rect, Movie *movieA); AnnotMovie(PDFDoc *docA, Object *dictObject, Object *obj); ~AnnotMovie(); - void draw(Gfx *gfx, GBool printing) override; - GooString* getTitle() { return title; } Movie* getMovie() { return movie; } private: void initialize(PDFDoc *docA, Dict *dict); + Object makeAppearance(XRef* xref) override; + GooString* title; // T Movie* movie; // Movie + A }; //------------------------------------------------------------------------ // AnnotScreen //------------------------------------------------------------------------ class AnnotScreen: public Annot { public: AnnotScreen(PDFDoc *docA, PDFRectangle *rect); AnnotScreen(PDFDoc *docA, Object *dictObject, Object *obj); ~AnnotScreen(); GooString* getTitle() { return title; } AnnotAppearanceCharacs *getAppearCharacs() { return appearCharacs; } LinkAction* getAction() { return action; } // The caller should now delete the result @@ -877,103 +883,104 @@ class AnnotScreen: public Annot { }; //------------------------------------------------------------------------ // AnnotLink //------------------------------------------------------------------------ class AnnotLink: public Annot { public: enum AnnotLinkEffect { effectNone, // N effectInvert, // I effectOutline, // O effectPush // P }; AnnotLink(PDFDoc *docA, PDFRectangle *rect); AnnotLink(PDFDoc *docA, Object *dictObject, Object *obj); ~AnnotLink(); - void draw(Gfx *gfx, GBool printing) override; - // getters LinkAction *getAction() const { return action; } AnnotLinkEffect getLinkEffect() const { return linkEffect; } Dict *getUriAction() const { return uriAction; } AnnotQuadrilaterals *getQuadrilaterals() const { return quadrilaterals; } protected: void initialize(PDFDoc *docA, Dict *dict); LinkAction *action; // A, Dest AnnotLinkEffect linkEffect; // H (Default I) Dict *uriAction; // PA AnnotQuadrilaterals *quadrilaterals; // QuadPoints }; //------------------------------------------------------------------------ // AnnotFreeText //------------------------------------------------------------------------ class AnnotFreeText: public AnnotMarkup { public: enum AnnotFreeTextQuadding { quaddingLeftJustified, // 0 quaddingCentered, // 1 quaddingRightJustified // 2 }; enum AnnotFreeTextIntent { intentFreeText, // FreeText intentFreeTextCallout, // FreeTextCallout intentFreeTextTypeWriter // FreeTextTypeWriter }; AnnotFreeText(PDFDoc *docA, PDFRectangle *rect, GooString *da); AnnotFreeText(PDFDoc *docA, Object *dictObject, Object *obj); ~AnnotFreeText(); - void draw(Gfx *gfx, GBool printing) override; Object getAppearanceResDict() override; void setContents(GooString *new_content) override; void setAppearanceString(GooString *new_string); void setQuadding(AnnotFreeTextQuadding new_quadding); void setStyleString(GooString *new_string); void setCalloutLine(AnnotCalloutLine *line); void setIntent(AnnotFreeTextIntent new_intent); // getters GooString *getAppearanceString() const { return appearanceString; } AnnotFreeTextQuadding getQuadding() const { return quadding; } // return rc GooString *getStyleString() const { return styleString; } AnnotCalloutLine *getCalloutLine() const { return calloutLine; } AnnotFreeTextIntent getIntent() const { return intent; } AnnotBorderEffect *getBorderEffect() const { return borderEffect; } PDFRectangle *getRectangle() const { return rectangle; } AnnotLineEndingStyle getEndStyle() const { return endStyle; } +private: + + Object makeAppearance(XRef* xref) override; + protected: void initialize(PDFDoc *docA, Dict *dict); static void parseAppearanceString(GooString *da, double &fontsize, AnnotColor* &fontcolor); void generateFreeTextAppearance(); // required GooString *appearanceString; // DA // optional AnnotFreeTextQuadding quadding; // Q (Default 0) // RC GooString *styleString; // DS AnnotCalloutLine *calloutLine; // CL AnnotFreeTextIntent intent; // IT AnnotBorderEffect *borderEffect; // BE PDFRectangle *rectangle; // RD // inherited from Annot // AnnotBorderBS border; // BS AnnotLineEndingStyle endStyle; // LE (Default None) @@ -983,115 +990,122 @@ protected: // AnnotLine //------------------------------------------------------------------------ class AnnotLine: public AnnotMarkup { public: enum AnnotLineIntent { intentLineArrow, // LineArrow intentLineDimension // LineDimension }; enum AnnotLineCaptionPos { captionPosInline, // Inline captionPosTop // Top }; AnnotLine(PDFDoc *docA, PDFRectangle *rect); AnnotLine(PDFDoc *docA, Object *dictObject, Object *obj); ~AnnotLine(); - void draw(Gfx *gfx, GBool printing) override; Object getAppearanceResDict() override; void setContents(GooString *new_content) override; void setVertices(double x1, double y1, double x2, double y2); void setStartEndStyle(AnnotLineEndingStyle start, AnnotLineEndingStyle end); void setInteriorColor(AnnotColor *new_color); void setLeaderLineLength(double len); void setLeaderLineExtension(double len); void setCaption(bool new_cap); void setIntent(AnnotLineIntent new_intent); // getters AnnotLineEndingStyle getStartStyle() const { return startStyle; } AnnotLineEndingStyle getEndStyle() const { return endStyle; } AnnotColor *getInteriorColor() const { return interiorColor; } double getLeaderLineLength() const { return leaderLineLength; } double getLeaderLineExtension() const { return leaderLineExtension; } bool getCaption() const { return caption; } AnnotLineIntent getIntent() const { return intent; } double getLeaderLineOffset() const { return leaderLineOffset; } AnnotLineCaptionPos getCaptionPos() const { return captionPos; } Dict *getMeasure() const { return measure; } double getCaptionTextHorizontal() const { return captionTextHorizontal; } double getCaptionTextVertical() const { return captionTextVertical; } double getX1() const { return coord1->getX(); } double getY1() const { return coord1->getY(); } double getX2() const { return coord2->getX(); } double getY2() const { return coord2->getY(); } +private: + + Object makeAppearance(XRef* xref) override; + PDFRectangle getDrawRect() const override; + protected: void initialize(PDFDoc *docA, Dict *dict); void generateLineAppearance(); // required AnnotCoord *coord1, *coord2; // optional // inherited from Annot // AnnotBorderBS border; // BS AnnotLineEndingStyle startStyle; // LE (Default [/None /None]) AnnotLineEndingStyle endStyle; // AnnotColor *interiorColor; // IC double leaderLineLength; // LL (Default 0) double leaderLineExtension; // LLE (Default 0) bool caption; // Cap (Default false) AnnotLineIntent intent; // IT double leaderLineOffset; // LLO AnnotLineCaptionPos captionPos; // CP (Default Inline) Dict *measure; // Measure double captionTextHorizontal; // CO (Default [0, 0]) double captionTextVertical; // }; //------------------------------------------------------------------------ // AnnotTextMarkup //------------------------------------------------------------------------ class AnnotTextMarkup: public AnnotMarkup { public: AnnotTextMarkup(PDFDoc *docA, PDFRectangle *rect, AnnotSubtype subType); AnnotTextMarkup(PDFDoc *docA, Object *dictObject, Object *obj); ~AnnotTextMarkup(); - void draw(Gfx *gfx, GBool printing) override; - // typeHighlight, typeUnderline, typeSquiggly or typeStrikeOut void setType(AnnotSubtype new_type); void setQuadrilaterals(AnnotQuadrilaterals *quadPoints); AnnotQuadrilaterals *getQuadrilaterals() const { return quadrilaterals; } +private: + + Object makeAppearance(XRef* xref) override; + PDFRectangle getDrawRect() const override; + protected: void initialize(PDFDoc *docA, Dict *dict); AnnotQuadrilaterals *quadrilaterals; // QuadPoints }; //------------------------------------------------------------------------ // AnnotStamp //------------------------------------------------------------------------ class AnnotStamp: public AnnotMarkup { public: AnnotStamp(PDFDoc *docA, PDFRectangle *rect); AnnotStamp(PDFDoc *docA, Object *dictObject, Object *obj); ~AnnotStamp(); void setIcon(GooString *new_icon); @@ -1099,96 +1113,97 @@ public: GooString *getIcon() const { return icon; } private: void initialize(PDFDoc *docA, Dict *dict); GooString *icon; // Name (Default Draft) }; //------------------------------------------------------------------------ // AnnotGeometry //------------------------------------------------------------------------ class AnnotGeometry: public AnnotMarkup { public: AnnotGeometry(PDFDoc *docA, PDFRectangle *rect, AnnotSubtype subType); AnnotGeometry(PDFDoc *docA, Object *dictObject, Object *obj); ~AnnotGeometry(); - void draw(Gfx *gfx, GBool printing) override; - void setType(AnnotSubtype new_type); // typeSquare or typeCircle void setInteriorColor(AnnotColor *new_color); // getters AnnotColor *getInteriorColor() const { return interiorColor; } AnnotBorderEffect *getBorderEffect() const { return borderEffect; } PDFRectangle *getGeometryRect() const { return geometryRect; } private: void initialize(PDFDoc *docA, Dict *dict); + Object makeAppearance(XRef* xref) override; + AnnotColor *interiorColor; // IC AnnotBorderEffect *borderEffect; // BE PDFRectangle *geometryRect; // RD (combined with Rect) }; //------------------------------------------------------------------------ // AnnotPolygon //------------------------------------------------------------------------ class AnnotPolygon: public AnnotMarkup { public: enum AnnotPolygonIntent { polygonCloud, // PolygonCloud polylineDimension, // PolyLineDimension polygonDimension // PolygonDimension }; AnnotPolygon(PDFDoc *docA, PDFRectangle *rect, AnnotSubtype subType); AnnotPolygon(PDFDoc *docA, Object *dictObject, Object *obj); ~AnnotPolygon(); - void draw(Gfx *gfx, GBool printing) override; - void setType(AnnotSubtype new_type); // typePolygon or typePolyLine void setVertices(AnnotPath *path); void setStartEndStyle(AnnotLineEndingStyle start, AnnotLineEndingStyle end); void setInteriorColor(AnnotColor *new_color); void setIntent(AnnotPolygonIntent new_intent); // getters AnnotPath *getVertices() const { return vertices; } AnnotLineEndingStyle getStartStyle() const { return startStyle; } AnnotLineEndingStyle getEndStyle() const { return endStyle; } AnnotColor *getInteriorColor() const { return interiorColor; } AnnotBorderEffect *getBorderEffect() const { return borderEffect; } AnnotPolygonIntent getIntent() const { return intent; } private: void initialize(PDFDoc *docA, Dict *dict); + Object makeAppearance(XRef* xref) override; + PDFRectangle getDrawRect() const override; + // required AnnotPath *vertices; // Vertices // optional AnnotLineEndingStyle startStyle; // LE (Default [/None /None]) AnnotLineEndingStyle endStyle; // // inherited from Annot // AnnotBorderBS border; // BS AnnotColor *interiorColor; // IC AnnotBorderEffect *borderEffect; // BE AnnotPolygonIntent intent; // IT // Measure }; //------------------------------------------------------------------------ // AnnotCaret //------------------------------------------------------------------------ class AnnotCaret: public AnnotMarkup { public: @@ -1210,176 +1225,179 @@ public: private: void initialize(PDFDoc *docA, Dict *dict); AnnotCaretSymbol symbol; // Sy (Default None) PDFRectangle *caretRect; // RD (combined with Rect) }; //------------------------------------------------------------------------ // AnnotInk //------------------------------------------------------------------------ class AnnotInk: public AnnotMarkup { public: AnnotInk(PDFDoc *docA, PDFRectangle *rect); AnnotInk(PDFDoc *docA, Object *dictObject, Object *obj); ~AnnotInk(); - void draw(Gfx *gfx, GBool printing) override; - void setInkList(AnnotPath **paths, int n_paths); // getters AnnotPath **getInkList() const { return inkList; } int getInkListLength() const { return inkListLength; } private: void initialize(PDFDoc *docA, Dict *dict); void writeInkList(AnnotPath **paths, int n_paths, Array *dest_array); void parseInkList(Array *src_array); void freeInkList(); + Object makeAppearance(XRef* xref) override; + PDFRectangle getDrawRect() const override; + // required AnnotPath **inkList; // InkList int inkListLength; // optional // inherited from Annot // AnnotBorderBS border; // BS }; //------------------------------------------------------------------------ // AnnotFileAttachment //------------------------------------------------------------------------ class AnnotFileAttachment: public AnnotMarkup { public: AnnotFileAttachment(PDFDoc *docA, PDFRectangle *rect, GooString *filename); AnnotFileAttachment(PDFDoc *docA, Object *dictObject, Object *obj); ~AnnotFileAttachment(); - void draw(Gfx *gfx, GBool printing) override; - // getters Object *getFile() { return &file; } GooString *getName() const { return name; } private: void initialize(PDFDoc *docA, Dict *dict); + Object makeAppearance(XRef* xref) override; + // required Object file; // FS // optional GooString *name; // Name }; //------------------------------------------------------------------------ // AnnotSound //------------------------------------------------------------------------ class AnnotSound: public AnnotMarkup { public: AnnotSound(PDFDoc *docA, PDFRectangle *rect, Sound *soundA); AnnotSound(PDFDoc *docA, Object *dictObject, Object *obj); ~AnnotSound(); - void draw(Gfx *gfx, GBool printing) override; - // getters Sound *getSound() { return sound; } GooString *getName() const { return name; } private: void initialize(PDFDoc *docA, Dict *dict); + Object makeAppearance(XRef* xref) override; + // required Sound *sound; // Sound // optional GooString *name; // Name }; //------------------------------------------------------------------------ // AnnotWidget //------------------------------------------------------------------------ class AnnotWidget: public Annot { public: enum AnnotWidgetHighlightMode { highlightModeNone, // N highlightModeInvert, // I highlightModeOutline, // O highlightModePush // P,T }; AnnotWidget(PDFDoc *docA, Object *dictObject, Object *obj); AnnotWidget(PDFDoc *docA, Object *dictObject, Object *obj, FormField *fieldA); ~AnnotWidget(); - void draw(Gfx *gfx, GBool printing) override; - void drawBorder(); void drawFormFieldButton(GfxResources *resources, GooString *da); void drawFormFieldText(GfxResources *resources, GooString *da); void drawFormFieldChoice(GfxResources *resources, GooString *da); void generateFieldAppearance (); void updateAppearanceStream (); AnnotWidgetHighlightMode getMode() { return mode; } AnnotAppearanceCharacs *getAppearCharacs() { return appearCharacs; } LinkAction *getAction() { return action; } // The caller should not delete the result LinkAction *getAdditionalAction(AdditionalActionsType type); // The caller should delete the result LinkAction *getFormAdditionalAction(FormAdditionalActionsType type); // The caller should delete the result Dict *getParent() { return parent; } private: void initialize(PDFDoc *docA, Dict *dict); void drawText(GooString *text, GooString *da, GfxResources *resources, GBool multiline, int comb, int quadding, GBool txField, GBool forceZapfDingbats, GBool password=false); void drawListBox(FormFieldChoice *fieldChoice, GooString *da, GfxResources *resources, int quadding); + Object makeAppearance(XRef* xref) override; + void drawAppearance(Gfx *gfx, Object& obj, const PDFRectangle& drawRect) override; + Form *form; FormField *field; // FormField object for this annotation AnnotWidgetHighlightMode mode; // H (Default I) AnnotAppearanceCharacs *appearCharacs; // MK LinkAction *action; // A Object additionalActions; // AA // inherited from Annot // AnnotBorderBS border; // BS Dict *parent; // Parent GBool addDingbatsResource; Ref updatedAppearanceStream; // {-1,-1} if updateAppearanceStream has never been called + Dict *fontResourceDict; // a fake resource, required if drawText is called with forceZapfDingbats = true }; //------------------------------------------------------------------------ // Annot3D //------------------------------------------------------------------------ class Annot3D: public Annot { class Activation { public: enum ActivationATrigger { aTriggerUnknown, aTriggerPageOpened, // PO aTriggerPageVisible, // PV aTriggerUserAction // XA }; enum ActivationAState { aStateUnknown, aStateEnabled, // I aStateDisabled // L