poppler/Annot.cc | 104 +++++++++++++++++++++++++++++++++++++++++++++++-------- poppler/Annot.h | 6 +++ 2 files changed, 95 insertions(+), 15 deletions(-)
New commits: commit 26fd142a3608283fd41e07b54067a51a9db76e93 Author: Fabio D'Urso <[email protected]> Date: Sat Apr 21 18:16:46 2012 +0200 Preserve z-index after annotation removal diff --git a/poppler/Annot.cc b/poppler/Annot.cc index b3bc97d..24ef57d 100644 --- a/poppler/Annot.cc +++ b/poppler/Annot.cc @@ -6446,7 +6446,7 @@ void Annots::appendAnnot(Annot *annot) { GBool Annots::removeAnnot(Annot *annot) { int idx = -1; - // Search annot and remove it by swapping with last element + // Search annot and determine its index for (int i = 0; idx == -1 && i < nAnnots; i++) { if (annots[i] == annot) { idx = i; @@ -6455,7 +6455,8 @@ GBool Annots::removeAnnot(Annot *annot) { if (idx == -1) { return gFalse; } else { - annots[idx] = annots[--nAnnots]; + --nAnnots; + memmove( annots + idx, annots + idx + 1, sizeof(annots[0]) * (nAnnots - idx) ); annot->decRefCnt(); return gTrue; } commit 7b10014c1fe9ef1cba57fd6b01c63129ac31386a Author: Fabio D'Urso <[email protected]> Date: Sat Apr 21 17:53:22 2012 +0200 Do not remove appearance stream if it's shared with other annotations diff --git a/poppler/Annot.cc b/poppler/Annot.cc index 06d08d5..b3bc97d 100644 --- a/poppler/Annot.cc +++ b/poppler/Annot.cc @@ -774,6 +774,7 @@ AnnotIconFit::AnnotIconFit(Dict* dict) { AnnotAppearance::AnnotAppearance(PDFDoc *docA, Object *dict) { assert(dict->isDict()); + doc = docA; xref = docA->getXRef(); dict->copy(&appearDict); } @@ -841,19 +842,88 @@ int AnnotAppearance::getNumStates() { return res; } +// Test if stateObj (a Ref or a Dict) points to the specified stream +GBool AnnotAppearance::referencesStream(Object *stateObj, Ref refToStream) { + if (stateObj->isRef()) { + Ref r = stateObj->getRef(); + if (r.num == refToStream.num && r.gen == refToStream.gen) { + return gTrue; + } + } else if (stateObj->isDict()) { // Test each value + const int size = stateObj->dictGetLength(); + for (int i = 0; i < size; ++i) { + Object obj1; + stateObj->dictGetValNF(i, &obj1); + if (obj1.isRef()) { + Ref r = obj1.getRef(); + if (r.num == refToStream.num && r.gen == refToStream.gen) { + return gTrue; + } + } + obj1.free(); + } + } + return gFalse; // Not found +} + +// Test if this AnnotAppearance references the specified stream +GBool AnnotAppearance::referencesStream(Ref refToStream) { + Object obj1; + GBool found; + + // Scan each state's ref/subdictionary + appearDict.dictLookupNF("N", &obj1); + found = referencesStream(&obj1, refToStream); + obj1.free(); + if (found) + return gTrue; + + appearDict.dictLookupNF("R", &obj1); + found = referencesStream(&obj1, refToStream); + obj1.free(); + if (found) + return gTrue; + + appearDict.dictLookupNF("D", &obj1); + found = referencesStream(&obj1, refToStream); + obj1.free(); + return found; +} + +// If this is the only annotation in the document that references the +// specified appearance stream, remove the appearance stream +void AnnotAppearance::removeStream(Ref refToStream) { + const int lastpage = doc->getNumPages(); + for (int pg = 1; pg <= lastpage; ++pg) { // Scan all annotations in the document + Page *page = doc->getPage(pg); + if (!page) { + error(errSyntaxError, -1, "Failed check for shared annotation stream at page {0:d}", pg); + continue; + } + Annots *annots = page->getAnnots(); + for (int i = 0; i < annots->getNumAnnots(); ++i) { + AnnotAppearance *annotAp = annots->getAnnot(i)->getAppearStreams(); + if (annotAp && annotAp != this && annotAp->referencesStream(refToStream)) { + return; // Another annotation points to the stream -> Don't delete it + } + } + } + + // TODO: stream resources (e.g. font), AP name tree + xref->removeIndirectObject(refToStream); +} + // Removes stream if obj is a Ref, or removes pointed streams if obj is a Dict void AnnotAppearance::removeStateStreams(Object *obj1) { - // TODO: Remove XObject resources, check for XObjects shared by multiple - // annotations, delete streams from name table (if any) if (obj1->isRef()) { - xref->removeIndirectObject(obj1->getRef()); + removeStream(obj1->getRef()); } else if (obj1->isDict()) { const int size = obj1->dictGetLength(); for (int i = 0; i < size; ++i) { Object obj2; obj1->dictGetValNF(i, &obj2); if (obj2.isRef()) { - xref->removeIndirectObject(obj2.getRef()); + removeStream(obj2.getRef()); } obj2.free(); } diff --git a/poppler/Annot.h b/poppler/Annot.h index 98e4d70..04a1301 100644 --- a/poppler/Annot.h +++ b/poppler/Annot.h @@ -382,10 +382,16 @@ public: // reset parent annotation's AP and AS after this call. void removeAllStreams(); + // Test if this AnnotAppearance references the specified stream + GBool referencesStream(Ref targetStreamRef); + private: + static GBool referencesStream(Object *stateObj, Ref targetStreamRef); + void removeStream(Ref refToStream); void removeStateStreams(Object *state); protected: + PDFDoc *doc; XRef *xref; // the xref table for this PDF file Object appearDict; // Annotation's AP }; commit 7684c325929493ad9de01a891de0aef197e176dd Author: Fabio D'Urso <[email protected]> Date: Sat Apr 21 20:26:49 2012 +0200 AnnotText: Always force 24x24 size with custom stamps, not only on first rendering diff --git a/poppler/Annot.cc b/poppler/Annot.cc index 130b9bb..06d08d5 100644 --- a/poppler/Annot.cc +++ b/poppler/Annot.cc @@ -2248,8 +2248,6 @@ void AnnotText::draw(Gfx *gfx, GBool printing) { if (!isVisible (printing)) return; - double rectx2 = rect->x2; - double recty2 = rect->y2; if (appearance.isNull()) { ca = opacity; @@ -2280,9 +2278,11 @@ void AnnotText::draw(Gfx *gfx, GBool printing) { appearBuf->append (ANNOT_TEXT_AP_CIRCLE); appearBuf->append ("Q\n"); + // Force 24x24 rectangle + PDFRectangle fixedRect(rect->x1, rect->y1, rect->x1 + 24, rect->y1 + 24); + appearBBox = new AnnotAppearanceBBox(&fixedRect); double bbox[4]; - bbox[0] = bbox[1] = 0; - bbox[2] = bbox[3] = 24; + appearBBox->getBBoxRect(bbox); if (ca == 1) { createForm(bbox, gFalse, NULL, &appearance); } else { @@ -2296,15 +2296,18 @@ void AnnotText::draw(Gfx *gfx, GBool printing) { createForm(bbox, gFalse, &resDict, &appearance); } delete appearBuf; - - rectx2 = rect->x1 + 24; - recty2 = rect->y1 + 24; } // draw the appearance stream appearance.fetch(xref, &obj); - gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color, - rect->x1, rect->y1, rectx2, recty2); + if (appearBBox) { + gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color, + appearBBox->getPageXMin(), appearBBox->getPageYMin(), + appearBBox->getPageXMax(), appearBBox->getPageYMax()); + } else { + gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color, + rect->x1, rect->y1, rect->x2, rect->y2); + } obj.free(); } _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
