I've noticed some small issues in the way we handle the border of annots compared to what the spec says and what acroread does. Attached are 4 patches:
[PATCH 1/4] annots: Remove unused AnnotBorderType from AnnotBorder This is simply a cleanup, we have a base class AnnotBorder that allows to create instances of it with the unknown type. It doesn't make much sense and we are not using it at all, so I've removed the AnnotBorderType, and made the constructor protected. [PATCH 2/4] annots: Add helper function Annot::setLineStyleForBorder The code to set the line width and dash was duplicated in several draw() methods, so I've moved it to a helper function. This patch also changes the way we are using it. We were always ignoring the border when the border with was 0, but it doesn't seem to be always correct. The PDF spec says that in both Border and BS entries when the width is 0, no border should be drawn at all. But some annotations like lines, geometry, polygons, etc. don't use the border entry to actually draw a border, but to set the line with and dash for the stroke operations. For example, we were not drawing lines for annots with no border or with a border width = 0, but acroread does, because in this case the border entry is used to set the line with and dash pattern, and the PDF spec also says that a line width of 0 should be drawn as the thinnest line that can be rendered at device resolution: 1 device pixel wide. So, for FreeText annotations where we actually draw a border, we only call Annot::setLineStyleForBorder if we have a border and the width is greater than 0, and in all other cases we always call it when we have a border. Of course, this only affects annotations not having an AP entry. [PATCH 3/4] annots: Use a default border for annots that can have a BS entry According to the PDF spec if neither the Border nor the BS entry is present, the border shall be drawn as a solid line with a width of 1 point. But again, acroread seems to only apply this rule for annotations that can have a BS entry. This patch moves the parsing of the BS entry From the base Annot class to the specific annot classes that can have a BS entry, and it creates a default border object when neither Border nor Bs is present. It also removes the border passed to Gfx::drawAnnot() in AnnotFileAttachment::draw and AnnotSound::draw because acroread ignores the Border entry also for annots that can't have a BS entry. This ensures that we always draw line, geometry, polygon, etc, even if there's no border specified. [PATCH 4/4] annots: Make Annot::setBorder receive an AnnotBorder object Currently we can only set AnnotBorderArray objects to annots. This might have no effect if the annots already has a BS entry, for example, because the BS takes precedence over Border. This patches changes Annot::setBorder to receive an AnnotBorder object, so that you can either pass an AnnotBorderArray or an AnnotBorderBS. Frontends should always use BS when updating an annotation that can have BS entries. The patch also completes the implementation of writeToObject method for array borders and adds an impementation for BS borders too. I've passed my tests with no regressions, but I can't test the qt frontend (that uses setBorder(), for example), so it would be great if someone could test these patches to make sure they don't introduce any regression in qt (it should build in any case). Leonard, please, feel free to correct me if I'm wrong in any of my interpretations of the PDF spec. Regards,
pgpjFzVCQOLSK.pgp
Description: PGP signature
>From 4dd0bb480dc13004912592c6c0fe0db65e6f0bed Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos <[email protected]> Date: Tue, 26 Nov 2013 11:40:57 +0100 Subject: [PATCH 1/4] annots: Remove unused AnnotBorderType from AnnotBorder Also make the AnnotBorder constructor protected to make sure it's not possible to create AnnotBorder instances. --- poppler/Annot.cc | 3 --- poppler/Annot.h | 10 +--------- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/poppler/Annot.cc b/poppler/Annot.cc index 5b83db2..021a49d 100644 --- a/poppler/Annot.cc +++ b/poppler/Annot.cc @@ -520,7 +520,6 @@ AnnotQuadrilaterals::AnnotQuadrilateral::AnnotQuadrilateral(double x1, double y1 // AnnotBorder //------------------------------------------------------------------------ AnnotBorder::AnnotBorder() { - type = typeUnknown; width = 1; dashLength = 0; dash = NULL; @@ -565,7 +564,6 @@ AnnotBorder::~AnnotBorder() { //------------------------------------------------------------------------ AnnotBorderArray::AnnotBorderArray() { - type = typeArray; horizontalCorner = 0; verticalCorner = 0; } @@ -627,7 +625,6 @@ void AnnotBorderArray::writeToObject(XRef *xref, Object *obj1) const { //------------------------------------------------------------------------ AnnotBorderBS::AnnotBorderBS() { - type = typeBS; } AnnotBorderBS::AnnotBorderBS(Dict *dict) { diff --git a/poppler/Annot.h b/poppler/Annot.h index bd3ff80..6efe471 100644 --- a/poppler/Annot.h +++ b/poppler/Annot.h @@ -215,12 +215,6 @@ protected: class AnnotBorder { public: - enum AnnotBorderType { - typeUnknown, - typeArray, - typeBS - }; - enum AnnotBorderStyle { borderSolid, // Solid borderDashed, // Dashed @@ -229,21 +223,19 @@ public: borderUnderlined // Underlined }; - AnnotBorder(); virtual ~AnnotBorder(); virtual void setWidth(double new_width) { width = new_width; } - virtual AnnotBorderType getType() const { return type; } virtual double getWidth() const { return width; } virtual int getDashLength() const { return dashLength; } virtual double *getDash() const { return dash; } virtual AnnotBorderStyle getStyle() const { return style; } protected: + AnnotBorder(); GBool parseDashArray(Object *dashObj); - AnnotBorderType type; double width; static const int DASH_LIMIT = 10; // implementation note 82 in Appendix H. int dashLength; -- 1.8.4.2
>From ca12172060823fdc2212eca6b10c87a2112cd0cc Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos <[email protected]> Date: Tue, 26 Nov 2013 14:07:21 +0100 Subject: [PATCH 2/4] annots: Add helper function Annot::setLineStyleForBorder It sets the line dash and width based on the given AnnotBorder. Use it only when the border width is greater than 0 for FreeText annotations and always for annotations that use the border to set the line width and dash, but don't draw a border. --- poppler/Annot.cc | 110 ++++++++++++++++--------------------------------------- poppler/Annot.h | 1 + 2 files changed, 32 insertions(+), 79 deletions(-) diff --git a/poppler/Annot.cc b/poppler/Annot.cc index 021a49d..0661fd2 100644 --- a/poppler/Annot.cc +++ b/poppler/Annot.cc @@ -1660,6 +1660,26 @@ void Annot::setColor(AnnotColor *color, GBool fill) { } } +void Annot::setLineStyleForBorder(AnnotBorder *border) { + int i, dashLength; + double *dash; + + switch (border->getStyle()) { + case AnnotBorder::borderDashed: + appearBuf->append("["); + dashLength = border->getDashLength(); + dash = border->getDash(); + for (i = 0; i < dashLength; ++i) + appearBuf->appendf(" {0:.2f}", dash[i]); + appearBuf->append(" ] 0 d\n"); + break; + default: + appearBuf->append("[] 0 d\n"); + break; + } + appearBuf->appendf("{0:.2f} w\n", border->getWidth()); +} + // Draw an (approximate) circle of radius <r> centered at (<cx>, <cy>). // If <fill> is true, the circle is filled; otherwise it is stroked. void Annot::drawCircle(double cx, double cy, double r, GBool fill) { @@ -2925,29 +2945,10 @@ void AnnotFreeText::generateFreeTextAppearance() appearBuf = new GooString (); appearBuf->append ("q\n"); - - if (border) { - int i, dashLength; - double *dash; - borderWidth = border->getWidth(); - switch (border->getStyle()) { - case AnnotBorder::borderDashed: - appearBuf->append("["); - dashLength = border->getDashLength(); - dash = border->getDash(); - for (i = 0; i < dashLength; ++i) - appearBuf->appendf(" {0:.2f}", dash[i]); - appearBuf->append(" ] 0 d\n"); - break; - default: - appearBuf->append("[] 0 d\n"); - break; - } - appearBuf->appendf("{0:.2f} w\n", borderWidth); - } else { - borderWidth = 0; // No border - } + borderWidth = border ? border->getWidth() : 0; + if (borderWidth > 0) + setLineStyleForBorder(border); // Box size const double width = rect->x2 - rect->x1; @@ -3331,7 +3332,7 @@ void AnnotLine::setIntent(AnnotLineIntent new_intent) { void AnnotLine::generateLineAppearance() { - double borderWidth, ca = opacity; + double borderWidth = 0, ca = opacity; appearBBox = new AnnotAppearanceBBox(rect); appearBuf = new GooString (); @@ -3341,28 +3342,10 @@ void AnnotLine::generateLineAppearance() } if (border) { - int i, dashLength; - double *dash; - - switch (border->getStyle()) { - case AnnotBorder::borderDashed: - appearBuf->append("["); - dashLength = border->getDashLength(); - dash = border->getDash(); - for (i = 0; i < dashLength; ++i) - appearBuf->appendf(" {0:.2f}", dash[i]); - appearBuf->append(" ] 0 d\n"); - break; - default: - appearBuf->append("[] 0 d\n"); - break; - } + setLineStyleForBorder(border); borderWidth = border->getWidth(); - appearBuf->appendf("{0:.2f} w\n", borderWidth); - appearBBox->setBorderWidth(borderWidth); - } else { - borderWidth = 0; } + appearBBox->setBorderWidth(std::max(1., borderWidth)); const double x1 = coord1->getX(); const double y1 = coord1->getY(); @@ -5508,24 +5491,9 @@ void AnnotGeometry::draw(Gfx *gfx, GBool printing) { setColor(color, gFalse); if (border) { - int i, dashLength; - double *dash; double borderWidth = border->getWidth(); - switch (border->getStyle()) { - case AnnotBorder::borderDashed: - appearBuf->append("["); - dashLength = border->getDashLength(); - dash = border->getDash(); - for (i = 0; i < dashLength; ++i) - appearBuf->appendf(" {0:.2f}", dash[i]); - appearBuf->append(" ] 0 d\n"); - break; - default: - appearBuf->append("[] 0 d\n"); - break; - } - appearBuf->appendf("{0:.2f} w\n", borderWidth); + setLineStyleForBorder(border); if (interiorColor) setColor(interiorColor, gTrue); @@ -5832,24 +5800,8 @@ void AnnotPolygon::draw(Gfx *gfx, GBool printing) { } if (border) { - int i, dashLength; - double *dash; - - switch (border->getStyle()) { - case AnnotBorder::borderDashed: - appearBuf->append("["); - dashLength = border->getDashLength(); - dash = border->getDash(); - for (i = 0; i < dashLength; ++i) - appearBuf->appendf(" {0:.2f}", dash[i]); - appearBuf->append(" ] 0 d\n"); - break; - default: - appearBuf->append("[] 0 d\n"); - break; - } - appearBuf->appendf("{0:.2f} w\n", border->getWidth()); - appearBBox->setBorderWidth(border->getWidth()); + setLineStyleForBorder(border); + appearBBox->setBorderWidth(std::max(1., border->getWidth())); } if (interiorColor) { @@ -6075,8 +6027,8 @@ void AnnotInk::draw(Gfx *gfx, GBool printing) { } if (border) { - appearBuf->appendf("{0:.2f} w\n", border->getWidth()); - appearBBox->setBorderWidth(border->getWidth()); + setLineStyleForBorder(border); + appearBBox->setBorderWidth(std::max(1., border->getWidth())); } for (int i = 0; i < inkListLength; ++i) { diff --git a/poppler/Annot.h b/poppler/Annot.h index 6efe471..38191e5 100644 --- a/poppler/Annot.h +++ b/poppler/Annot.h @@ -612,6 +612,7 @@ protected: virtual ~Annot(); virtual void removeReferencedObjects(); // Called by Page::removeAnnot void setColor(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); -- 1.8.4.2
>From a1b02ed388629975acf7672c1a534f7224694a26 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos <[email protected]> Date: Tue, 26 Nov 2013 14:44:57 +0100 Subject: [PATCH 3/4] annots: Use a default border for annots that can have a BS entry According to the spec if neither the Border nor the BS entry is present, the border shall be drawn as a solid line with a width of 1 point. However, acroread seems to ignore the Border entry for annots that can't have a BS entry. --- poppler/Annot.cc | 231 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 137 insertions(+), 94 deletions(-) diff --git a/poppler/Annot.cc b/poppler/Annot.cc index 0661fd2..7b6da45 100644 --- a/poppler/Annot.cc +++ b/poppler/Annot.cc @@ -1292,18 +1292,14 @@ void Annot::initialize(PDFDoc *docA, Dict *dict) { } //----- parse the border style - if (dict->lookup("BS", &obj1)->isDict()) { - border = new AnnotBorderBS(obj1.getDict()); - } else { - obj1.free(); - - if (dict->lookup("Border", &obj1)->isArray()) - border = new AnnotBorderArray(obj1.getArray()); - else - // Adobe draws no border at all if the last element is of - // the wrong type. - border = NULL; - } + // According to the spec if neither the Border nor the BS entry is present, + // the border shall be drawn as a solid line with a width of 1 point. But acroread + // seems to ignore the Border entry for annots that can't have a BS entry. So, we only + // follow this rule for annots tha can have a BS entry. + if (dict->lookup("Border", &obj1)->isArray()) + border = new AnnotBorderArray(obj1.getArray()); + else + border = NULL; obj1.free(); if (dict->lookup("C", &obj1)->isArray()) { @@ -2620,6 +2616,14 @@ void AnnotLink::initialize(PDFDoc *docA, Dict *dict) { quadrilaterals = NULL; } obj1.free(); + + if (dict->lookup("BS", &obj1)->isDict()) { + delete border; + border = new AnnotBorderBS(obj1.getDict()); + } else if (!border) { + border = new AnnotBorderBS(); + } + obj1.free(); } void AnnotLink::draw(Gfx *gfx, GBool printing) { @@ -2747,6 +2751,14 @@ void AnnotFreeText::initialize(PDFDoc *docA, Dict *dict) { } obj1.free(); + if (dict->lookup("BS", &obj1)->isDict()) { + delete border; + border = new AnnotBorderBS(obj1.getDict()); + } else if (!border) { + border = new AnnotBorderBS(); + } + obj1.free(); + if (dict->lookup("BE", &obj1)->isDict()) { borderEffect = new AnnotBorderEffect(obj1.getDict()); } else { @@ -2946,7 +2958,7 @@ void AnnotFreeText::generateFreeTextAppearance() appearBuf = new GooString (); appearBuf->append ("q\n"); - borderWidth = border ? border->getWidth() : 0; + borderWidth = border->getWidth(); if (borderWidth > 0) setLineStyleForBorder(border); @@ -3234,6 +3246,14 @@ void AnnotLine::initialize(PDFDoc *docA, Dict *dict) { captionTextHorizontal = captionTextVertical = 0; } obj1.free(); + + if (dict->lookup("BS", &obj1)->isDict()) { + delete border; + border = new AnnotBorderBS(obj1.getDict()); + } else if (!border) { + border = new AnnotBorderBS(); + } + obj1.free(); } void AnnotLine::setContents(GooString *new_content) { @@ -3332,7 +3352,7 @@ void AnnotLine::setIntent(AnnotLineIntent new_intent) { void AnnotLine::generateLineAppearance() { - double borderWidth = 0, ca = opacity; + double borderWidth, ca = opacity; appearBBox = new AnnotAppearanceBBox(rect); appearBuf = new GooString (); @@ -3341,10 +3361,8 @@ void AnnotLine::generateLineAppearance() setColor(color, gFalse); } - if (border) { - setLineStyleForBorder(border); - borderWidth = border->getWidth(); - } + setLineStyleForBorder(border); + borderWidth = border->getWidth(); appearBBox->setBorderWidth(std::max(1., borderWidth)); const double x1 = coord1->getX(); @@ -3906,6 +3924,14 @@ void AnnotWidget::initialize(PDFDoc *docA, Dict *dict) { } obj1.free(); + if (dict->lookup("BS", &obj1)->isDict()) { + delete border; + border = new AnnotBorderBS(obj1.getDict()); + } else if (!border) { + border = new AnnotBorderBS(); + } + obj1.free(); + updatedAppearanceStream.num = updatedAppearanceStream.gen = -1; } @@ -4253,7 +4279,7 @@ void AnnotWidget::drawText(GooString *text, GooString *da, GfxResources *resourc } // get the border width - borderWidth = border ? border->getWidth() : 0; + borderWidth = border->getWidth(); // for a password field, replace all characters with asterisks if (password) { @@ -4636,7 +4662,7 @@ void AnnotWidget::drawListBox(FormFieldChoice *fieldChoice, convertedText = new GooString; // get the border width - borderWidth = border ? border->getWidth() : 0; + borderWidth = border->getWidth(); // compute font autosize if (fontSize == 0) { @@ -4951,7 +4977,7 @@ void AnnotWidget::generateFieldAppearance() { } // draw the border - if (appearCharacs && border && border->getWidth() > 0) + if (appearCharacs && border->getWidth() > 0) drawBorder(); da = field->getDefaultAppearance(); @@ -5426,6 +5452,14 @@ void AnnotGeometry::initialize(PDFDoc *docA, Dict* dict) { } obj1.free(); + if (dict->lookup("BS", &obj1)->isDict()) { + delete border; + border = new AnnotBorderBS(obj1.getDict()); + } else if (!border) { + border = new AnnotBorderBS(); + } + obj1.free(); + if (dict->lookup("BE", &obj1)->isDict()) { borderEffect = new AnnotBorderEffect(obj1.getDict()); } else { @@ -5490,73 +5524,70 @@ void AnnotGeometry::draw(Gfx *gfx, GBool printing) { if (color) setColor(color, gFalse); - if (border) { - double borderWidth = border->getWidth(); - - setLineStyleForBorder(border); + double borderWidth = border->getWidth(); + setLineStyleForBorder(border); - if (interiorColor) - setColor(interiorColor, gTrue); + if (interiorColor) + setColor(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 { - double width, height; - double b; - double x1, y1, x2, y2, x3, y3; - - width = rect->x2 - rect->x1; - height = rect->y2 - rect->y1; - b = borderWidth / 2.0; - - x1 = b; - y1 = height / 2.0; - appearBuf->appendf ("{0:.2f} {1:.2f} m\n", x1, y1); - - y1 += height / 4.0; - x2 = width / 4.0; - y2 = height - b; - x3 = width / 2.0; - y3 = y2; - appearBuf->appendf ("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", - x1, y1, x2, y2, x3, y3); - x2 = width - b; - y2 = y1; - x1 = x3 + (width / 4.0); - y1 = y3; - x3 = x2; - y3 = height / 2.0; - appearBuf->appendf ("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", - x1, y1, x2, y2, x3, y3); - - x2 = x1; - y2 = b; - x1 = x3; - y1 = height / 4.0; - x3 = width / 2.0; - y3 = b; - appearBuf->appendf ("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", - x1, y1, x2, y2, x3, y3); - - x2 = b; - y2 = y1; - x1 = width / 4.0; - y1 = b; - x3 = b; - y3 = height / 2.0; - appearBuf->appendf ("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", - x1, y1, x2, y2, x3, y3); + 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 { + double width, height; + double b; + double x1, y1, x2, y2, x3, y3; + + width = rect->x2 - rect->x1; + height = rect->y2 - rect->y1; + b = borderWidth / 2.0; + + x1 = b; + y1 = height / 2.0; + appearBuf->appendf ("{0:.2f} {1:.2f} m\n", x1, y1); + + y1 += height / 4.0; + x2 = width / 4.0; + y2 = height - b; + x3 = width / 2.0; + y3 = y2; + appearBuf->appendf ("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + x1, y1, x2, y2, x3, y3); + x2 = width - b; + y2 = y1; + x1 = x3 + (width / 4.0); + y1 = y3; + x3 = x2; + y3 = height / 2.0; + appearBuf->appendf ("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + x1, y1, x2, y2, x3, y3); + + x2 = x1; + y2 = b; + x1 = x3; + y1 = height / 4.0; + x3 = width / 2.0; + y3 = b; + appearBuf->appendf ("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + x1, y1, x2, y2, x3, y3); + + x2 = b; + y2 = y1; + x1 = width / 4.0; + y1 = b; + x3 = b; + y3 = height / 2.0; + appearBuf->appendf ("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n", + x1, y1, x2, y2, x3, y3); + } - } + if (interiorColor && interiorColor->getSpace() != AnnotColor::colorTransparent) + appearBuf->append ("b\n"); + else + appearBuf->append ("S\n"); - if (interiorColor && interiorColor->getSpace() != AnnotColor::colorTransparent) - appearBuf->append ("b\n"); - else - appearBuf->append ("S\n"); - } appearBuf->append ("Q\n"); double bbox[4]; @@ -5680,6 +5711,14 @@ void AnnotPolygon::initialize(PDFDoc *docA, Dict* dict) { } obj1.free(); + if (dict->lookup("BS", &obj1)->isDict()) { + delete border; + border = new AnnotBorderBS(obj1.getDict()); + } else if (!border) { + border = new AnnotBorderBS(); + } + obj1.free(); + if (dict->lookup("BE", &obj1)->isDict()) { borderEffect = new AnnotBorderEffect(obj1.getDict()); } else { @@ -5799,10 +5838,8 @@ void AnnotPolygon::draw(Gfx *gfx, GBool printing) { setColor(color, gFalse); } - if (border) { - setLineStyleForBorder(border); - appearBBox->setBorderWidth(std::max(1., border->getWidth())); - } + setLineStyleForBorder(border); + appearBBox->setBorderWidth(std::max(1., border->getWidth())); if (interiorColor) { setColor(interiorColor, gTrue); @@ -5959,6 +5996,14 @@ void AnnotInk::initialize(PDFDoc *docA, Dict* dict) { ok = gFalse; } obj1.free(); + + if (dict->lookup("BS", &obj1)->isDict()) { + delete border; + border = new AnnotBorderBS(obj1.getDict()); + } else if (!border) { + border = new AnnotBorderBS(); + } + obj1.free(); } void AnnotInk::writeInkList(AnnotPath **paths, int n_paths, Array *dest_array) { @@ -6026,10 +6071,8 @@ void AnnotInk::draw(Gfx *gfx, GBool printing) { setColor(color, gFalse); } - if (border) { - setLineStyleForBorder(border); - appearBBox->setBorderWidth(std::max(1., border->getWidth())); - } + setLineStyleForBorder(border); + appearBBox->setBorderWidth(std::max(1., border->getWidth())); for (int i = 0; i < inkListLength; ++i) { const AnnotPath * path = inkList[i]; @@ -6290,7 +6333,7 @@ void AnnotFileAttachment::draw(Gfx *gfx, GBool printing) { // draw the appearance stream appearance.fetch(gfx->getXRef(), &obj); - gfx->drawAnnot(&obj, border, color, + gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color, rect->x1, rect->y1, rect->x2, rect->y2, getRotation()); obj.free(); } @@ -6452,7 +6495,7 @@ void AnnotSound::draw(Gfx *gfx, GBool printing) { // draw the appearance stream appearance.fetch(gfx->getXRef(), &obj); - gfx->drawAnnot(&obj, border, color, + gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color, rect->x1, rect->y1, rect->x2, rect->y2, getRotation()); obj.free(); } -- 1.8.4.2
>From caa605971be3d7955a60ad91762871e91de29eaa Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos <[email protected]> Date: Tue, 26 Nov 2013 20:12:22 +0100 Subject: [PATCH 4/4] annots: Make Annot::setBorder receive an AnnotBorder object Instead of receiving AnnotBorderArray. Also implement writeToObject in both AnnotBorderArray and AnnotBorderBS to make sure that Annot::setBorder will work for both cases. --- poppler/Annot.cc | 51 +++++++++++++++++++++++++++++++++++++++++++++------ poppler/Annot.h | 19 +++++++++++++++---- 2 files changed, 60 insertions(+), 10 deletions(-) diff --git a/poppler/Annot.cc b/poppler/Annot.cc index 7b6da45..fa4a74b 100644 --- a/poppler/Annot.cc +++ b/poppler/Annot.cc @@ -614,10 +614,17 @@ void AnnotBorderArray::writeToObject(XRef *xref, Object *obj1) const { Object obj2; obj1->initArray(xref); - obj1->arrayAdd(obj2.initReal( horizontalCorner )); - obj1->arrayAdd(obj2.initReal( verticalCorner )); - obj1->arrayAdd(obj2.initReal( width )); - // TODO: Dash array + obj1->arrayAdd(obj2.initReal(horizontalCorner)); + obj1->arrayAdd(obj2.initReal(verticalCorner)); + obj1->arrayAdd(obj2.initReal(width)); + + if (dashLength > 0) { + Object obj3; + + obj1->arrayAdd(obj3.initArray(xref)); + for (int i = 0; i < dashLength; i++) + obj3.arrayAdd(obj2.initReal(dash[i])); + } } //------------------------------------------------------------------------ @@ -675,6 +682,38 @@ AnnotBorderBS::AnnotBorderBS(Dict *dict) { } } +const char *AnnotBorderBS::getStyleName() const { + switch (style) { + case borderSolid: + return "S"; + case borderDashed: + return "D"; + case borderBeveled: + return "B"; + case borderInset: + return "I"; + case borderUnderlined: + return "U"; + } + + return "S"; +} + +void AnnotBorderBS::writeToObject(XRef *xref, Object *obj1) const { + Object obj2; + + obj1->initDict(xref); + obj1->dictSet("W", obj2.initReal(width)); + obj1->dictSet("S", obj2.initName(getStyleName())); + if (style == borderDashed && dashLength > 0) { + Object obj3; + + obj1->dictSet("D", obj3.initArray(xref)); + for (int i = 0; i < dashLength; i++) + obj3.arrayAdd(obj2.initReal(dash[i])); + } +} + //------------------------------------------------------------------------ // AnnotColor //------------------------------------------------------------------------ @@ -1441,14 +1480,14 @@ void Annot::setFlags(Guint new_flags) { update ("F", &obj1); } -void Annot::setBorder(AnnotBorderArray *new_border) { +void Annot::setBorder(AnnotBorder *new_border) { annotLocker(); delete border; if (new_border) { Object obj1; new_border->writeToObject(xref, &obj1); - update ("Border", &obj1); + update(new_border->getEntryName(), &obj1); border = new_border; } else { border = NULL; diff --git a/poppler/Annot.h b/poppler/Annot.h index 38191e5..050a457 100644 --- a/poppler/Annot.h +++ b/poppler/Annot.h @@ -232,6 +232,9 @@ public: virtual double *getDash() const { return dash; } virtual AnnotBorderStyle getStyle() const { return style; } + virtual void writeToObject(XRef *xref, Object *obj1) const = 0; + virtual const char *getEntryName() const = 0; + protected: AnnotBorder(); GBool parseDashArray(Object *dashObj); @@ -252,15 +255,17 @@ public: AnnotBorderArray(); AnnotBorderArray(Array *array); - void writeToObject(XRef *xref, Object *dest) const; - void setHorizontalCorner(double hc) { horizontalCorner = hc; } void setVerticalCorner(double vc) { verticalCorner = vc; } double getHorizontalCorner() const { return horizontalCorner; } double getVerticalCorner() const { return verticalCorner; } -protected: +private: + virtual void writeToObject(XRef *xref, Object *obj1) const; + + virtual const char *getEntryName() const { return "Border"; } + double horizontalCorner; // (Default 0) double verticalCorner; // (Default 0) // double width; // (Default 1) (inherited from AnnotBorder) @@ -277,6 +282,12 @@ public: AnnotBorderBS(Dict *dict); private: + virtual void writeToObject(XRef *xref, Object *obj1) const; + + virtual const char *getEntryName() const { return "BS"; } + + const char *getStyleName() const; + // double width; // W (Default 1) (inherited from AnnotBorder) // AnnotBorderStyle style; // S (Default S) (inherited from AnnotBorder) // double *dash; // D (Default [3]) (inherited from AnnotBorder) @@ -568,7 +579,7 @@ public: void setModified(GooString *new_date); void setFlags(Guint new_flags); - void setBorder(AnnotBorderArray *new_border); // Takes ownership + void setBorder(AnnotBorder *new_border); // Takes ownership // The annotation takes the ownership of // new_color. -- 1.8.4.2
-- Carlos Garcia Campos PGP key: http://pgp.mit.edu:11371/pks/lookup?op=get&search=0x523E6462
_______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
