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,

Attachment: 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

Reply via email to