I've just finished the bbox part. Since I also changed the AnnotLine patch, 
I'm reposting all the final patches yet to be committed.

NOTES ON BBOX CHECKING:
> Since we're so close to release I'd just disable clipping for generated
> appearances for now. After all, we never export the generated appearance,
> therefore it won't cause incompatibilities with other readers.
Unfortunately this workaround only worked for non-transparent annots, 
therefore I had to implement proper bbox adjustment for generated appearances 
that potentially draw out of the bbox (AnnotLine, AnnotPolygon, AnnotInk 
and AnnotTextMarkup).

The bbox is recalculated in *::draw, but the result is stored different 
object than rect, so that the rect can't change out of user control.
In particular, I initialize the new bounding box as the rect, and grow it if 
necessary. These changes are in 0008 and 0009.
Note: In 0009 I removed a check that forced AnnotTextMarkup's quadrilaterals 
within the rect at initialization time. Now it behaves like acroread.

> * = Actually, AnnotLine already changes rect from draw (as workaround for
> pdf_commenting_new), but I don't feel comfortable with this approach.
This workaround is not needed any more. Patch 0008 removes it.
From 6b5b4370fd8b828386c78f20301a1ed876914e76 Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Wed, 21 Mar 2012 21:12:59 +0100
Subject: [PATCH 1/9] Do not fill AnnotGeometry with transparent color

Previously it was filled with black.
---
 poppler/Annot.cc |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index caa13c5..6e8b355 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -4812,7 +4812,7 @@ void AnnotGeometry::draw(Gfx *gfx, GBool printing) {
 
       }
 
-      if (interiorColor)
+      if (interiorColor && interiorColor->getSpace() != AnnotColor::colorTransparent)
         appearBuf->append ("b\n");
       else
         appearBuf->append ("S\n");
-- 
1.7.6.5

From 7aa361c98d0d3695c392965b2ac23cdca4b37127 Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Wed, 21 Mar 2012 22:33:13 +0100
Subject: [PATCH 2/9] AnnotPolygon rendering

---
 poppler/Annot.cc |   87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 poppler/Annot.h  |    2 +
 2 files changed, 89 insertions(+), 0 deletions(-)

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 6e8b355..2868efd 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -5041,6 +5041,93 @@ void AnnotPolygon::setIntent(AnnotPolygonIntent new_intent) {
   update ("IT", &obj1);
 }
 
+void AnnotPolygon::draw(Gfx *gfx, GBool printing) {
+  Object obj;
+  double ca = 1;
+
+  if (!isVisible (printing))
+    return;
+
+  if (appearance.isNull()) {
+    ca = opacity;
+
+    appearBuf = new GooString ();
+    appearBuf->append ("q\n");
+
+    if (color) {
+      setColor(color, gFalse);
+    }
+
+    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());
+    }
+
+    if (interiorColor) {
+      setColor(interiorColor, gTrue);
+    }
+
+    if (vertices->getCoordsLength() != 0) {
+      appearBuf->appendf ("{0:.2f} {1:.2f} m\n", vertices->getX(0) - rect->x1, vertices->getY(0) - rect->y1);
+
+      for (int i = 1; i < vertices->getCoordsLength(); ++i) {
+        appearBuf->appendf ("{0:.2f} {1:.2f} l\n", vertices->getX(i) - rect->x1, vertices->getY(i) - rect->y1);
+      }
+
+      if (type == typePolygon) {
+        if (interiorColor && interiorColor->getSpace() != AnnotColor::colorTransparent) {
+          appearBuf->append ("b\n");
+        } else {
+          appearBuf->append ("s\n");
+        }
+      } else {
+        appearBuf->append ("S\n");
+      }
+    }
+
+    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) {
+      createForm(bbox, gFalse, NULL, &appearance);
+    } else {
+      Object aStream, resDict;
+
+      createForm(bbox, gTrue, NULL, &aStream);
+      delete appearBuf;
+
+      appearBuf = new GooString ("/GS0 gs\n/Fm0 Do");
+      createResourcesDict("Fm0", &aStream, "GS0", ca, NULL, &resDict);
+      createForm(bbox, gFalse, &resDict, &appearance);
+    }
+    delete appearBuf;
+  }
+
+  // draw the appearance stream
+  appearance.fetch(xref, &obj);
+  gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
+                 rect->x1, rect->y1, rect->x2, rect->y2);
+  obj.free();
+}
+
 //------------------------------------------------------------------------
 // AnnotCaret
 //------------------------------------------------------------------------
diff --git a/poppler/Annot.h b/poppler/Annot.h
index b196e51..299eaa7 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -1045,6 +1045,8 @@ public:
   AnnotPolygon(PDFDoc *docA, Dict *dict, Object *obj);
   ~AnnotPolygon();
 
+  virtual void draw(Gfx *gfx, GBool printing);
+
   void setType(AnnotSubtype new_type); // typePolygon or typePolyLine
   void setVertices(AnnotPath *path);
   void setStartEndStyle(AnnotLineEndingStyle start, AnnotLineEndingStyle end);
-- 
1.7.6.5

From 3ff0a845443eaa0e69d6659e13168c77f8d9e8b0 Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Wed, 21 Mar 2012 22:48:05 +0100
Subject: [PATCH 3/9] AnnotInk rendering

---
 poppler/Annot.cc |   62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 poppler/Annot.h  |    2 +
 2 files changed, 64 insertions(+), 0 deletions(-)

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 2868efd..6d42be1 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -5270,6 +5270,68 @@ void AnnotInk::setInkList(AnnotPath **paths, int n_paths) {
   annotObj.dictSet ("InkList", &obj1);
 }
 
+void AnnotInk::draw(Gfx *gfx, GBool printing) {
+  Object obj;
+  double ca = 1;
+
+  if (!isVisible (printing))
+    return;
+
+  if (appearance.isNull()) {
+    ca = opacity;
+
+    appearBuf = new GooString ();
+    appearBuf->append ("q\n");
+
+    if (color) {
+      setColor(color, gFalse);
+    }
+
+    if (border) {
+      appearBuf->appendf("{0:.2f} w\n", border->getWidth());
+    }
+
+    for (int i = 0; i < inkListLength; ++i) {
+      const AnnotPath * path = inkList[i];
+      if (path->getCoordsLength() != 0) {
+        appearBuf->appendf ("{0:.2f} {1:.2f} m\n", path->getX(0) - rect->x1, path->getY(0) - rect->y1);
+
+        for (int j = 1; j < path->getCoordsLength(); ++j) {
+          appearBuf->appendf ("{0:.2f} {1:.2f} l\n", path->getX(j) - rect->x1, path->getY(j) - rect->y1);
+        }
+
+        appearBuf->append ("S\n");
+      }
+    }
+
+    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) {
+      createForm(bbox, gFalse, NULL, &appearance);
+    } else {
+      Object aStream, resDict;
+
+      createForm(bbox, gTrue, NULL, &aStream);
+      delete appearBuf;
+
+      appearBuf = new GooString ("/GS0 gs\n/Fm0 Do");
+      createResourcesDict("Fm0", &aStream, "GS0", ca, NULL, &resDict);
+      createForm(bbox, gFalse, &resDict, &appearance);
+    }
+    delete appearBuf;
+  }
+
+  // draw the appearance stream
+  appearance.fetch(xref, &obj);
+  gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
+                 rect->x1, rect->y1, rect->x2, rect->y2);
+  obj.free();
+}
+
 //------------------------------------------------------------------------
 // AnnotFileAttachment
 //------------------------------------------------------------------------
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 299eaa7..a01361f 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -1120,6 +1120,8 @@ public:
   AnnotInk(PDFDoc *docA, Dict *dict, Object *obj);
   ~AnnotInk();
 
+  virtual void draw(Gfx *gfx, GBool printing);
+
   void setInkList(AnnotPath **paths, int n_paths);
 
   // getters
-- 
1.7.6.5

From 82da7a52608b06484d652dc5e8d9e4b4797d222d Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Thu, 22 Mar 2012 17:33:01 +0100
Subject: [PATCH 4/9] Improvements to AnnotLine::draw

---
 poppler/Annot.cc |   50 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 6d42be1..9ed22bf 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -2851,10 +2851,52 @@ void AnnotLine::draw(Gfx *gfx, GBool printing) {
       }
       appearBuf->appendf("{0:.2f} w\n", border->getWidth());
     }
-    appearBuf->appendf ("{0:.2f} {1:.2f} m\n", coord1->getX() - rect->x1, coord1->getY() - rect->y1);
-    appearBuf->appendf ("{0:.2f} {1:.2f} l\n", coord2->getX() - rect->x1, coord2->getY() - rect->y1);
-    // TODO: Line ending, caption, leader lines
-    appearBuf->append ("S\n");
+
+    const double x1 = coord1->getX();
+    const double y1 = coord1->getY();
+    const double x2 = coord2->getX();
+    const double y2 = coord2->getY();
+
+    // Main segment length
+    const double main_len = sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
+
+    // Main segment becomes positive x direction, coord1 becomes (0,0)
+    Matrix matr;
+    const double angle = atan2(y2 - y1, x2 - x1);
+    matr.m[0] = matr.m[3] = cos(angle);
+    matr.m[1] = sin(angle);
+    matr.m[2] = -matr.m[1];
+    matr.m[4] = x1-rect->x1;
+    matr.m[5] = y1-rect->y1;
+
+    double tx, ty;
+
+    // Draw main segment
+    matr.transform (0, leaderLineLength, &tx, &ty);
+    appearBuf->appendf ("{0:.2f} {1:.2f} m\n", tx, ty);
+
+    matr.transform (main_len, leaderLineLength, &tx, &ty);
+    appearBuf->appendf ("{0:.2f} {1:.2f} l S\n", tx, ty);
+
+    // TODO: Line ending, caption
+
+    // Draw leader lines
+    double ll_len = fabs(leaderLineLength) + leaderLineExtension;
+    double sign = leaderLineLength >= 0 ? 1 : -1;
+    if (ll_len != 0) {
+      matr.transform (0, 0, &tx, &ty);
+      appearBuf->appendf ("{0:.2f} {1:.2f} m\n", tx, ty);
+
+      matr.transform (0, sign*ll_len, &tx, &ty);
+      appearBuf->appendf ("{0:.2f} {1:.2f} l S\n", tx, ty);
+
+      matr.transform (main_len, 0, &tx, &ty);
+      appearBuf->appendf ("{0:.2f} {1:.2f} m\n", tx, ty);
+
+      matr.transform (main_len, sign*ll_len, &tx, &ty);
+      appearBuf->appendf ("{0:.2f} {1:.2f} l S\n", tx, ty);
+    }
+
     appearBuf->append ("Q\n");
 
     double bbox[4];
-- 
1.7.6.5

From 5e2249abe9ded6e0a670b2b449131b6177bd3770 Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Sun, 25 Mar 2012 22:04:11 +0200
Subject: [PATCH 5/9] AnnotTextMarkup rendering improvements

1) FIX: Wrong coords in typeUnderline and typeStrikeout
2) Implementation of typeSquiggly
3) FIX: Form creation is common to all markup types
---
 poppler/Annot.cc |   92 +++++++++++++++++++++++++++++++++---------------------
 1 files changed, 56 insertions(+), 36 deletions(-)

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 9ed22bf..9013eed 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -3065,42 +3065,40 @@ void AnnotTextMarkup::draw(Gfx *gfx, GBool printing) {
     return;
 
   if (appearance.isNull() || type == typeHighlight) {
+    GBool blendMultiply = gTrue;
     ca = opacity;
 
     appearBuf = new GooString ();
+    appearBuf->append ("q\n");
 
     switch (type) {
     case typeUnderline:
       if (color) {
         setColor(color, gFalse);
-	setColor(color, gTrue);
       }
+      appearBuf->append ("[] 0 d 1 w\n");
 
       for (i = 0; i < quadrilaterals->getQuadrilateralsLength(); ++i) {
         double x1, x2, y3;
-	double x, y;
 
 	x1 = quadrilaterals->getX1(i);
 	x2 = quadrilaterals->getX2(i);
 	y3 = quadrilaterals->getY3(i);
 
-	x = x1 - rect->x1;
-	y = y3 - rect->y1;
-	appearBuf->append ("[]0 d 2 w\n");
-	appearBuf->appendf ("{0:.2f} {1:.2f} m\n", x, y);
-	appearBuf->appendf ("{0:.2f} {1:.2f} l\n", x + (x2 - x1), y);
+	appearBuf->appendf ("{0:.2f} {1:.2f} m\n", x1, y3);
+	appearBuf->appendf ("{0:.2f} {1:.2f} l\n", x2, y3);
 	appearBuf->append ("S\n");
       }
       break;
     case typeStrikeOut:
       if (color) {
         setColor(color, gFalse);
-	setColor(color, gTrue);
       }
+      blendMultiply = gFalse;
+      appearBuf->append ("[] 0 d 1 w\n");
 
       for (i = 0; i < quadrilaterals->getQuadrilateralsLength(); ++i) {
         double x1, y1, x2, y3;
-	double x, y;
 	double h2;
 
 	x1 = quadrilaterals->getX1(i);
@@ -3109,16 +3107,37 @@ void AnnotTextMarkup::draw(Gfx *gfx, GBool printing) {
 	y3 = quadrilaterals->getY3(i);
 	h2 = (y1 - y3) / 2.0;
 
-	x = x1 - rect->x1;
-	y = (y3 - rect->y1) + h2;
-	appearBuf->append ("[]0 d 2 w\n");
-	appearBuf->appendf ("{0:.2f} {1:.2f} m\n", x, y);
-	appearBuf->appendf ("{0:.2f} {1:.2f} l\n", x + (x2 - x1), y);
+	appearBuf->appendf ("{0:.2f} {1:.2f} m\n", x1, y3+h2);
+	appearBuf->appendf ("{0:.2f} {1:.2f} l\n", x2, y3+h2);
 	appearBuf->append ("S\n");
       }
       break;
     case typeSquiggly:
-      // TODO
+      if (color) {
+        setColor(color, gFalse);
+      }
+      appearBuf->append ("[] 0 d 1 w\n");
+
+      for (i = 0; i < quadrilaterals->getQuadrilateralsLength(); ++i) {
+        double x1, y1, x2, y3;
+        double h6;
+
+        x1 = quadrilaterals->getX1(i);
+        y1 = quadrilaterals->getY1(i);
+        x2 = quadrilaterals->getX2(i);
+        y3 = quadrilaterals->getY3(i);
+        h6 = (y1 - y3) / 6.0;
+
+        appearBuf->appendf ("{0:.2f} {1:.2f} m\n", x1, y3+h6);
+        bool down = false;
+        do {
+          down = !down; // Zigzag line
+          x1 += 2;
+          appearBuf->appendf ("{0:.2f} {1:.2f} l\n", x1, y3 + (down ? 0 : h6));
+        } while (x1 < x2);
+        appearBuf->append ("S\n");
+      }
+      break;
     default:
     case typeHighlight:
       appearance.free();
@@ -3138,7 +3157,7 @@ void AnnotTextMarkup::draw(Gfx *gfx, GBool printing) {
 	y3 = quadrilaterals->getY3(i);
 	x4 = quadrilaterals->getX4(i);
 	y4 = quadrilaterals->getY4(i);
-	h4 = abs(y1 - y3) / 4.0;
+	h4 = fabs(y1 - y3) / 4.0;
 
 	appearBuf->appendf ("{0:.2f} {1:.2f} m\n", x3, y3);
 	appearBuf->appendf ("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
@@ -3148,31 +3167,32 @@ void AnnotTextMarkup::draw(Gfx *gfx, GBool printing) {
 			    x2 + h4, y2 - h4, x4 + h4, y4 + h4, x4, y4);
 	appearBuf->append ("f\n");
       }
+      break;
+    }
+    appearBuf->append ("Q\n");
 
-      Object aStream, resDict;
-      double bbox[4];
-      bbox[0] = rect->x1;
-      bbox[1] = rect->y1;
-      bbox[2] = rect->x2;
-      bbox[3] = rect->y2;
-      createForm(bbox, gTrue, NULL, &aStream);
+    Object aStream, resDict;
+    double bbox[4];
+    bbox[0] = rect->x1;
+    bbox[1] = rect->y1;
+    bbox[2] = rect->x2;
+    bbox[3] = rect->y2;
+    createForm(bbox, gTrue, NULL, &aStream);
+    delete appearBuf;
+
+    appearBuf = new GooString ("/GS0 gs\n/Fm0 Do");
+    createResourcesDict("Fm0", &aStream, "GS0", 1, blendMultiply ? "Multiply" : NULL, &resDict);
+    if (ca == 1) {
+      createForm(bbox, gFalse, &resDict, &appearance);
+    } else {
+      createForm(bbox, gTrue, &resDict, &aStream);
       delete appearBuf;
 
       appearBuf = new GooString ("/GS0 gs\n/Fm0 Do");
-      createResourcesDict("Fm0", &aStream, "GS0", 1, "Multiply", &resDict);
-      if (ca == 1) {
-        createForm(bbox, gFalse, &resDict, &appearance);
-      } else {
-        createForm(bbox, gTrue, &resDict, &aStream);
-	delete appearBuf;
-
-	appearBuf = new GooString ("/GS0 gs\n/Fm0 Do");
-	createResourcesDict("Fm0", &aStream, "GS0", ca, NULL, &resDict);
-	createForm(bbox, gFalse, &resDict, &appearance);
-      }
-      delete appearBuf;
-      break;
+      createResourcesDict("Fm0", &aStream, "GS0", ca, NULL, &resDict);
+      createForm(bbox, gFalse, &resDict, &appearance);
     }
+    delete appearBuf;
   }
 
   // draw the appearance stream
-- 
1.7.6.5

From 49ab9216511c2964e5a5cadce3c66674fd902b79 Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Fri, 23 Mar 2012 20:54:58 +0100
Subject: [PATCH 6/9] Basic AnnotFreeText rendering (hardcoded font, WinAnsi
 characters only)

This patch also moves layoutText and writeString from AnnotWidget to Annot
---
 poppler/Annot.cc |  137 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 poppler/Annot.h  |   11 +++--
 2 files changed, 142 insertions(+), 6 deletions(-)

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 9013eed..e1fd5d8 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -2549,6 +2549,139 @@ void AnnotFreeText::setIntent(AnnotFreeTextIntent new_intent) {
   update ("IT", &obj1);
 }
 
+static GfxFont * createAnnotDrawFont(XRef * xref, Object *fontResDict)
+{
+  Ref dummyRef = { -1, -1 };
+
+  Object baseFontObj, subtypeObj, encodingObj;
+  baseFontObj.initName("Helvetica");
+  subtypeObj.initName("Type0");
+  encodingObj.initName("WinAnsiEncoding");
+
+  Object fontDictObj;
+  Dict *fontDict = new Dict(xref);
+  fontDict->decRef();
+  fontDict->add(copyString("BaseFont"), &baseFontObj);
+  fontDict->add(copyString("Subtype"), &subtypeObj);
+  fontDict->add(copyString("Encoding"), &encodingObj);
+  fontDictObj.initDict(fontDict);
+
+  Object fontsDictObj;
+  Dict *fontsDict = new Dict(xref);
+  fontsDict->decRef();
+  fontsDict->add(copyString("AnnotDrawFont"), &fontDictObj);
+  fontsDictObj.initDict(fontsDict);
+
+  Dict *dict = new Dict(xref);
+  dict->add(copyString("Font"), &fontsDictObj);
+
+  fontResDict->initDict(dict);
+  return GfxFont::makeFont(xref, "AnnotDrawFont", dummyRef, fontDict);
+}
+
+void AnnotFreeText::generateFreeTextAppearance()
+{
+  double ca = opacity;
+
+  appearBuf = new GooString ();
+  appearBuf->append ("q\n");
+  if (color) {
+    setColor(color, gTrue);
+  }
+
+  // Main segment length
+  const double width = rect->x2 - rect->x1;
+  const double height = rect->y2 - rect->y1;
+
+  // Parse text size from appearance string (TODO: other properties)
+  double fontsize = 0;
+  GooString * da = appearanceString;
+  if (da) {
+    GooList * daToks = new GooList();
+    int j, i = 0;
+    while (i < da->getLength()) {
+      while (i < da->getLength() && Lexer::isSpace(da->getChar(i))) {
+        ++i;
+      }
+      if (i < da->getLength()) {
+        for (j = i + 1; j < da->getLength() && !Lexer::isSpace(da->getChar(j)); ++j) {
+        }
+        daToks->append(new GooString(da, i, j - i));
+        i = j;
+      }
+    }
+    for (i = 2; i < daToks->getLength(); ++i) {
+      if (!((GooString *)daToks->get(i))->cmp("Tf")) {
+        GooString * tok = (GooString *)daToks->get(i - 1);
+        fontsize = gatof(tok->getCString());
+        break;
+      }
+    }
+    deleteGooList(daToks, GooString);
+  }
+  if (fontsize <= 0) {
+    fontsize = 10; // Default value
+  }
+
+  // Draw box and setup clipping
+  appearBuf->appendf ("[] 0 d 1 w 0 G 0 0 {0:.2f} {1:.2f} re b\n", width, height);
+  appearBuf->appendf ("2 0 {0:.2f} {1:.2f} re W n\n", width-4, height);
+
+  // Set font state
+  appearBuf->appendf ("0 g BT 1 0 0 1 2 {0:.2f} Tm\n", height);
+  appearBuf->appendf ("{0:.2f} TL /AnnotDrawFont {0:.2f} Tf\n", fontsize);
+
+  Object fontResDict;
+  GfxFont *font = createAnnotDrawFont(xref, &fontResDict);
+
+  int i = 0;
+  while (i < contents->getLength()) {
+    GooString out;
+    layoutText(contents, &out, &i, font, NULL, 0, NULL, gFalse);
+    writeString(&out, appearBuf);
+    appearBuf->append("'\n");
+  }
+
+  font->decRefCnt();
+  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) {
+    createForm(bbox, gFalse, &fontResDict, &appearance);
+  } else {
+    Object aStream, resDict;
+
+    createForm(bbox, gTrue, &fontResDict, &aStream);
+    delete appearBuf;
+
+    appearBuf = new GooString ("/GS0 gs\n/Fm0 Do");
+    createResourcesDict("Fm0", &aStream, "GS0", ca, NULL, &resDict);
+    createForm(bbox, gFalse, &resDict, &appearance);
+  }
+  delete appearBuf;
+}
+
+void AnnotFreeText::draw(Gfx *gfx, GBool printing) {
+  Object obj;
+
+  if (!isVisible (printing))
+    return;
+
+  if (appearance.isNull()) {
+    generateFreeTextAppearance();
+  }
+
+  // draw the appearance stream
+  appearance.fetch(xref, &obj);
+  gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
+                 rect->x1, rect->y1, rect->x2, rect->y2);
+  obj.free();
+}
+
 //------------------------------------------------------------------------
 // AnnotLine
 //------------------------------------------------------------------------
@@ -3308,7 +3441,7 @@ void AnnotWidget::initialize(PDFDoc *docA, Dict *dict) {
 // TODO: Handle surrogate pairs in UTF-16.
 //       Should be able to generate output for any CID-keyed font.
 //       Doesn't handle vertical fonts--should it?
-void AnnotWidget::layoutText(GooString *text, GooString *outBuf, int *i,
+void Annot::layoutText(GooString *text, GooString *outBuf, int *i,
                              GfxFont *font, double *width, double widthLimit,
                              int *charCount, GBool noReencode)
 {
@@ -3502,7 +3635,7 @@ void AnnotWidget::layoutText(GooString *text, GooString *outBuf, int *i,
 
 // Copy the given string to appearBuf, adding parentheses around it and
 // escaping characters as appropriate.
-void AnnotWidget::writeString(GooString *str, GooString *appearBuf)
+void Annot::writeString(GooString *str, GooString *appearBuf)
 {
   char c;
   int i;
diff --git a/poppler/Annot.h b/poppler/Annot.h
index a01361f..5f0d4c4 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -563,6 +563,10 @@ protected:
   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);
   void createForm(double *bbox, GBool transparencyGroup, Object *resDict, Object *aStream);
   void createResourcesDict(const char *formName, Object *formStream, const char *stateName,
 			   double opacity, const char *blendMode, Object *resDict);
@@ -837,6 +841,8 @@ public:
   AnnotFreeText(PDFDoc *docA, Dict *dict, Object *obj);
   ~AnnotFreeText();
 
+  virtual void draw(Gfx *gfx, GBool printing);
+
   void setAppearanceString(GooString *new_string);
   void setQuadding(AnnotFreeTextQuadding new_quadding);
   void setStyleString(GooString *new_string);
@@ -857,6 +863,7 @@ public:
 protected:
 
   void initialize(PDFDoc *docA, Dict *dict);
+  void generateFreeTextAppearance();
 
   // required
   GooString *appearanceString;      // DA
@@ -1242,10 +1249,6 @@ private:
 		GBool password=false);
   void drawListBox(FormFieldChoice *fieldChoice,
 		   GooString *da, GfxResources *resources, int quadding);
-  void layoutText(GooString *text, GooString *outBuf, int *i, GfxFont *font,
-		  double *width, double widthLimit, int *charCount,
-		  GBool noReencode);
-  void writeString(GooString *str, GooString *appearBuf);
 
   Form *form;
   FormField *field;                       // FormField object for this annotation
-- 
1.7.6.5

From eba4b851c21f0bbef29263ffeb625ca5d58c21e6 Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Thu, 29 Mar 2012 19:07:05 +0200
Subject: [PATCH 7/9] Do not recreate Annots when writing to PS, Export
 poppler-generated Annot appearance resource dict

1) With previous code each Annot object was reconstructed from the pdf object when
writing to PS, leading to the fact that writeDocSetup couldn't see the
generated appearance.
This patch makes writeDocSetup use the same Annots object returned by
Page::getAnnots.

2) This patch also enables each Annot subtype to control the exported
resources. AnnotFreeText uses this new method to export font information.

3) Comment fixed in Page.h: Page::getAnnots does *not* give away ownership, in
fact the returned object is destroyed by ~Page.
---
 poppler/Annot.cc       |   28 ++++++++++++++++++++++++++++
 poppler/Annot.h        |    5 +++--
 poppler/FontInfo.cc    |   11 ++++-------
 poppler/PSOutputDev.cc |   12 +++---------
 poppler/Page.h         |    2 +-
 5 files changed, 39 insertions(+), 19 deletions(-)

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index e1fd5d8..60419b2 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -1552,6 +1552,25 @@ void Annot::createResourcesDict(const char *formName, Object *formStream,
   resDict->dictSet("XObject", &formDict);
 }
 
+Object *Annot::getAppearanceResDict(Object *dest) {
+  Object obj1, obj2;
+
+  dest->initNull(); // Default value
+
+  // Fetch appearance's resource dict (if any)
+  appearance.fetch(xref, &obj1);
+  if (obj1.isStream()) {
+    obj1.streamGetDict()->lookup("Resources", &obj2);
+    if (obj2.isDict()) {
+      obj2.copy(dest);
+    }
+    obj2.free();
+  }
+  obj1.free();
+
+  return dest;
+}
+
 GBool Annot::isVisible(GBool printing) {
   // check the flags
   if ((flags & flagHidden) ||
@@ -2682,6 +2701,15 @@ void AnnotFreeText::draw(Gfx *gfx, GBool printing) {
   obj.free();
 }
 
+// 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(Object *dest) {
+  if (appearance.isNull()) {
+    generateFreeTextAppearance();
+  }
+  return Annot::getAppearanceResDict(dest);
+}
+
 //------------------------------------------------------------------------
 // AnnotLine
 //------------------------------------------------------------------------
diff --git a/poppler/Annot.h b/poppler/Annot.h
index 5f0d4c4..cfa2365 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -492,8 +492,8 @@ public:
   void decRefCnt();
 
   virtual void draw(Gfx *gfx, GBool printing);
-  // Get appearance object.
-  Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); }
+  // Get the resource dict of the appearance stream
+  virtual Object *getAppearanceResDict(Object *dest);
 
   GBool match(Ref *refA)
     { return ref.num == refA->num && ref.gen == refA->gen; }
@@ -842,6 +842,7 @@ public:
   ~AnnotFreeText();
 
   virtual void draw(Gfx *gfx, GBool printing);
+  virtual Object *getAppearanceResDict(Object *dest);
 
   void setAppearanceString(GooString *new_string);
   void setQuadding(AnnotFreeTextQuadding new_quadding);
diff --git a/poppler/FontInfo.cc b/poppler/FontInfo.cc
index 2a90c1e..4f30f05 100644
--- a/poppler/FontInfo.cc
+++ b/poppler/FontInfo.cc
@@ -11,6 +11,7 @@
 // Copyright (C) 2010, 2012 Adrian Johnson <[email protected]>
 // Copyright (C) 2010 Thomas Freitag <[email protected]>
 // Copyright (C) 2011 Carlos Garcia Campos <[email protected]>
+// Copyright (C) 2012 Fabio D'Urso <[email protected]>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -53,7 +54,7 @@ GooList *FontInfoScanner::scan(int nPages) {
   Page *page;
   Dict *resDict;
   Annots *annots;
-  Object obj1, obj2;
+  Object obj1;
   int lastPage;
 
   if (currentPage > doc->getNumPages()) {
@@ -76,12 +77,8 @@ GooList *FontInfoScanner::scan(int nPages) {
     }
     annots = page->getAnnots();
     for (int i = 0; i < annots->getNumAnnots(); ++i) {
-      if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) {
-	obj1.streamGetDict()->lookup("Resources", &obj2);
-	if (obj2.isDict()) {
-	  scanFonts(obj2.getDict(), result);
-	}
-	obj2.free();
+      if (annots->getAnnot(i)->getAppearanceResDict(&obj1)->isDict()) {
+        scanFonts(obj1.getDict(), result);
       }
       obj1.free();
     }
diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index 232c750..157b4b7 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -1553,19 +1553,13 @@ void PSOutputDev::writeDocSetup(PDFDoc *doc, Catalog *catalog,
     if ((resDict = page->getResourceDict())) {
       setupResources(resDict);
     }
-    annots = new Annots(doc, page->getAnnots(&obj1));
-    obj1.free();
+    annots = page->getAnnots();
     for (i = 0; i < annots->getNumAnnots(); ++i) {
-      if (annots->getAnnot(i)->getAppearance(&obj1)->isStream()) {
-	obj1.streamGetDict()->lookup("Resources", &obj2);
-	if (obj2.isDict()) {
-	  setupResources(obj2.getDict());
-	}
-	obj2.free();
+      if (annots->getAnnot(i)->getAppearanceResDict(&obj1)->isDict()) {
+        setupResources(obj1.getDict());
       }
       obj1.free();
     }
-    delete annots;
   }
   if ((acroForm = catalog->getAcroForm()) && acroForm->isDict()) {
     if (acroForm->dictLookup("DR", &obj1)->isDict()) {
diff --git a/poppler/Page.h b/poppler/Page.h
index a1722a4..9dea41c 100644
--- a/poppler/Page.h
+++ b/poppler/Page.h
@@ -178,7 +178,7 @@ public:
   // Return a list of links.
   Links *getLinks();
 
-  // Return a list of annots. Ownership is transferred to the caller.
+  // Return a list of annots. It will be valid until the page is destroyed
   Annots *getAnnots();
 
   // Get contents.
-- 
1.7.6.5

From 1e55c715d8fbdfe49f8f1b789754733c240b25b6 Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Sat, 7 Apr 2012 00:30:54 +0200
Subject: [PATCH 8/9] Do not trust the rect of AnnotLine, AnnotPolygon and
 AnnotInk when drawing

---
 poppler/Annot.cc |  126 +++++++++++++++++++++++++++++++++++++++++++-----------
 poppler/Annot.h  |   27 ++++++++++++
 2 files changed, 128 insertions(+), 25 deletions(-)

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 60419b2..a2ced1f 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -965,6 +965,59 @@ AnnotAppearanceCharacs::~AnnotAppearanceCharacs() {
 }
 
 //------------------------------------------------------------------------
+// AnnotAppearanceBBox
+//------------------------------------------------------------------------
+
+AnnotAppearanceBBox::AnnotAppearanceBBox(PDFRectangle *rect) {
+  origX = rect->x1;
+  origY = rect->y1;
+  borderWidth = 0;
+
+  // Initially set the same size as rect
+  minX = 0;
+  minY = 0;
+  maxX = rect->x2 - rect->x1;
+  maxY = rect->y2 - rect->y1;
+}
+
+void AnnotAppearanceBBox::extendTo(double x, double y) {
+  if (x < minX) {
+    minX = x;
+  } else if (x > maxX) {
+    maxX = x;
+  }
+  if (y < minY) {
+    minY = y;
+  } else if (y > maxY) {
+    maxY = y;
+  }
+}
+
+void AnnotAppearanceBBox::getBBoxRect(double bbox[4]) const {
+  Object obj2;
+  bbox[0] = minX - borderWidth;
+  bbox[1] = minY - borderWidth;
+  bbox[2] = maxX + borderWidth;
+  bbox[3] = maxY + borderWidth;
+}
+
+double AnnotAppearanceBBox::getPageXMin() const {
+  return origX + minX - borderWidth;
+}
+
+double AnnotAppearanceBBox::getPageYMin() const {
+  return origY + minY - borderWidth;
+}
+
+double AnnotAppearanceBBox::getPageXMax() const {
+  return origX + maxX + borderWidth;
+}
+
+double AnnotAppearanceBBox::getPageYMax() const {
+  return origY + maxY + borderWidth;
+}
+
+//------------------------------------------------------------------------
 // Annot
 //------------------------------------------------------------------------
 
@@ -1023,6 +1076,7 @@ void Annot::initialize(PDFDoc *docA, Dict *dict) {
   doc = docA;
   xref = doc->getXRef();
   appearStreams = NULL;
+  appearBBox = NULL;
   appearState = NULL;
   appearBuf = NULL;
   fontSize = 0;
@@ -1315,6 +1369,9 @@ void Annot::setAppearanceState(const char *state) {
   delete appearState;
   appearState = new GooString(state);
 
+  delete appearBBox;
+  appearBBox = NULL;
+
   Object obj1;
   obj1.initName(state);
   update ("AS", &obj1);
@@ -1388,6 +1445,7 @@ Annot::~Annot() {
     delete modified;
 
   delete appearStreams;
+  delete appearBBox;
   appearance.free();
 
   if (appearState)
@@ -2975,17 +3033,8 @@ void AnnotLine::draw(Gfx *gfx, GBool printing) {
   if (!isVisible (printing))
     return;
 
-  /* Some documents like pdf_commenting_new.pdf,
-   * have y1 = y2 but line_width > 0, acroread
-   * renders the lines in such cases even though
-   * the annot bbox is empty. We adjust the bbox here
-   * to avoid having an empty bbox so that lines
-   * are rendered
-   */
-  if (rect->y1 == rect->y2)
-    rect->y2 += border ? border->getWidth() : 1;
-
   if (appearance.isNull()) {
+    appearBBox = new AnnotAppearanceBBox(rect);
     ca = opacity;
 
     appearBuf = new GooString ();
@@ -3011,6 +3060,7 @@ void AnnotLine::draw(Gfx *gfx, GBool printing) {
         break;
       }
       appearBuf->appendf("{0:.2f} w\n", border->getWidth());
+      appearBBox->setBorderWidth(border->getWidth());
     }
 
     const double x1 = coord1->getX();
@@ -3035,9 +3085,11 @@ void AnnotLine::draw(Gfx *gfx, GBool printing) {
     // Draw main segment
     matr.transform (0, leaderLineLength, &tx, &ty);
     appearBuf->appendf ("{0:.2f} {1:.2f} m\n", tx, ty);
+    appearBBox->extendTo (tx, ty);
 
     matr.transform (main_len, leaderLineLength, &tx, &ty);
     appearBuf->appendf ("{0:.2f} {1:.2f} l S\n", tx, ty);
+    appearBBox->extendTo (tx, ty);
 
     // TODO: Line ending, caption
 
@@ -3047,23 +3099,25 @@ void AnnotLine::draw(Gfx *gfx, GBool printing) {
     if (ll_len != 0) {
       matr.transform (0, 0, &tx, &ty);
       appearBuf->appendf ("{0:.2f} {1:.2f} m\n", tx, ty);
+      appearBBox->extendTo (tx, ty);
 
       matr.transform (0, sign*ll_len, &tx, &ty);
       appearBuf->appendf ("{0:.2f} {1:.2f} l S\n", tx, ty);
+      appearBBox->extendTo (tx, ty);
 
       matr.transform (main_len, 0, &tx, &ty);
       appearBuf->appendf ("{0:.2f} {1:.2f} m\n", tx, ty);
+      appearBBox->extendTo (tx, ty);
 
       matr.transform (main_len, sign*ll_len, &tx, &ty);
       appearBuf->appendf ("{0:.2f} {1:.2f} l S\n", tx, ty);
+      appearBBox->extendTo (tx, ty);
     }
 
     appearBuf->append ("Q\n");
 
     double bbox[4];
-    bbox[0] = bbox[1] = 0;
-    bbox[2] = rect->x2 - rect->x1;
-    bbox[3] = rect->y2 - rect->y1;
+    appearBBox->getBBoxRect(bbox);
     if (ca == 1) {
       createForm(bbox, gFalse, NULL, &appearance);
     } else {
@@ -3081,8 +3135,14 @@ void AnnotLine::draw(Gfx *gfx, GBool printing) {
 
   // draw the appearance stream
   appearance.fetch(xref, &obj);
-  gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
-		 rect->x1, rect->y1, rect->x2, rect->y2);
+  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();
 }
 
@@ -5272,6 +5332,7 @@ void AnnotPolygon::draw(Gfx *gfx, GBool printing) {
     return;
 
   if (appearance.isNull()) {
+    appearBBox = new AnnotAppearanceBBox(rect);
     ca = opacity;
 
     appearBuf = new GooString ();
@@ -5299,6 +5360,7 @@ void AnnotPolygon::draw(Gfx *gfx, GBool printing) {
         break;
       }
       appearBuf->appendf("{0:.2f} w\n", border->getWidth());
+      appearBBox->setBorderWidth(border->getWidth());
     }
 
     if (interiorColor) {
@@ -5307,9 +5369,11 @@ void AnnotPolygon::draw(Gfx *gfx, GBool printing) {
 
     if (vertices->getCoordsLength() != 0) {
       appearBuf->appendf ("{0:.2f} {1:.2f} m\n", vertices->getX(0) - rect->x1, vertices->getY(0) - rect->y1);
+      appearBBox->extendTo (vertices->getX(0) - rect->x1, vertices->getY(0) - rect->y1);
 
       for (int i = 1; i < vertices->getCoordsLength(); ++i) {
         appearBuf->appendf ("{0:.2f} {1:.2f} l\n", vertices->getX(i) - rect->x1, vertices->getY(i) - rect->y1);
+        appearBBox->extendTo (vertices->getX(i) - rect->x1, vertices->getY(i) - rect->y1);
       }
 
       if (type == typePolygon) {
@@ -5326,9 +5390,7 @@ void AnnotPolygon::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;
+    appearBBox->getBBoxRect(bbox);
     if (ca == 1) {
       createForm(bbox, gFalse, NULL, &appearance);
     } else {
@@ -5346,8 +5408,14 @@ void AnnotPolygon::draw(Gfx *gfx, GBool printing) {
 
   // draw the appearance stream
   appearance.fetch(xref, &obj);
-  gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
-                 rect->x1, rect->y1, rect->x2, rect->y2);
+  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();
 }
 
@@ -5501,6 +5569,7 @@ void AnnotInk::draw(Gfx *gfx, GBool printing) {
     return;
 
   if (appearance.isNull()) {
+    appearBBox = new AnnotAppearanceBBox(rect);
     ca = opacity;
 
     appearBuf = new GooString ();
@@ -5512,15 +5581,18 @@ void AnnotInk::draw(Gfx *gfx, GBool printing) {
 
     if (border) {
       appearBuf->appendf("{0:.2f} w\n", border->getWidth());
+      appearBBox->setBorderWidth(border->getWidth());
     }
 
     for (int i = 0; i < inkListLength; ++i) {
       const AnnotPath * path = inkList[i];
       if (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);
 
         for (int j = 1; j < path->getCoordsLength(); ++j) {
           appearBuf->appendf ("{0:.2f} {1:.2f} l\n", path->getX(j) - rect->x1, path->getY(j) - rect->y1);
+          appearBBox->extendTo (path->getX(j) - rect->x1, path->getY(j) - rect->y1);
         }
 
         appearBuf->append ("S\n");
@@ -5530,9 +5602,7 @@ void AnnotInk::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;
+    appearBBox->getBBoxRect(bbox);
     if (ca == 1) {
       createForm(bbox, gFalse, NULL, &appearance);
     } else {
@@ -5550,8 +5620,14 @@ void AnnotInk::draw(Gfx *gfx, GBool printing) {
 
   // draw the appearance stream
   appearance.fetch(xref, &obj);
-  gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
-                 rect->x1, rect->y1, rect->x2, rect->y2);
+  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();
 }
 
diff --git a/poppler/Annot.h b/poppler/Annot.h
index cfa2365..2e64ac9 100644
--- a/poppler/Annot.h
+++ b/poppler/Annot.h
@@ -435,6 +435,32 @@ protected:
 };
 
 //------------------------------------------------------------------------
+// AnnotAppearanceBBox
+//------------------------------------------------------------------------
+
+class AnnotAppearanceBBox
+{
+public:
+  AnnotAppearanceBBox(PDFRectangle *init);
+
+  void setBorderWidth(double w) { borderWidth = w; }
+
+  // The following functions operate on coords relative to [origX origY]
+  void extendTo(double x, double y);
+  void getBBoxRect(double bbox[4]) const;
+
+  // Get boundaries in page coordinates
+  double getPageXMin() const;
+  double getPageYMin() const;
+  double getPageXMax() const;
+  double getPageYMax() const;
+
+private:
+  double origX, origY, borderWidth;
+  double minX, minY, maxX, maxY;
+};
+
+//------------------------------------------------------------------------
 // Annot
 //------------------------------------------------------------------------
 
@@ -593,6 +619,7 @@ protected:
   AnnotAppearance *appearStreams;   // AP
   Object appearance;     // a reference to the Form XObject stream
                          //   for the normal appearance
+  AnnotAppearanceBBox *appearBBox;  // BBox of generated appearance
   GooString *appearState;           // AS
   int treeKey;                      // Struct Parent;
   Object oc;                        // OC
-- 
1.7.6.5

From ce9784f73e6fb65158c6e0f86ab004d812374bea Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Sat, 7 Apr 2012 11:28:36 +0200
Subject: [PATCH 9/9] Do not trust the rect of AnnotTextMarkup when drawing

---
 poppler/Annot.cc |   43 +++++++++++++++++++++++++++++--------------
 1 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index a2ced1f..53d71ed 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -93,10 +93,6 @@
 // = (4 * (sqrt(2) - 1) / 3) * r
 #define bezierCircle 0.55228475
 
-// Ensures that x is between the limits set by low and high.
-// If low is greater than high the result is undefined.
-#define CLAMP(x, low, high)  (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
-
 AnnotLineEndingStyle parseAnnotLineEndingStyle(GooString *string) {
   if (string != NULL) {
     if (!string->cmp("Square")) {
@@ -361,10 +357,7 @@ AnnotQuadrilaterals::AnnotQuadrilaterals(Array *array, PDFRectangle *rect) {
       for (int j = 0; j < 8; j++) {
         Object obj;
         if (array->get(i * 8 + j, &obj)->isNum()) {
-          if (j % 2 == 1)
-	    quadArray[j] = CLAMP (obj.getNum(), rect->y1, rect->y2);
-          else
-	    quadArray[j] = CLAMP (obj.getNum(), rect->x1, rect->x2);
+          quadArray[j] = obj.getNum();
         } else {
             correct = gFalse;
 	    obj.free();
@@ -3292,6 +3285,16 @@ void AnnotTextMarkup::draw(Gfx *gfx, GBool printing) {
     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) {
@@ -3366,6 +3369,7 @@ void AnnotTextMarkup::draw(Gfx *gfx, GBool printing) {
       if (color)
         setColor(color, gTrue);
 
+      double biggestBorder = 0;
       for (i = 0; i < quadrilaterals->getQuadrilateralsLength(); ++i) {
         double x1, y1, x2, y2, x3, y3, x4, y4;
 	double h4;
@@ -3380,6 +3384,10 @@ void AnnotTextMarkup::draw(Gfx *gfx, GBool printing) {
 	y4 = quadrilaterals->getY4(i);
 	h4 = fabs(y1 - y3) / 4.0;
 
+	if (h4 > biggestBorder) {
+	  biggestBorder = h4;
+	}
+
 	appearBuf->appendf ("{0:.2f} {1:.2f} m\n", x3, y3);
 	appearBuf->appendf ("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} c\n",
 			    x3 - h4, y3 + h4, x1 - h4, y1 - h4, x1, y1);
@@ -3388,16 +3396,17 @@ void AnnotTextMarkup::draw(Gfx *gfx, GBool printing) {
 			    x2 + h4, y2 - h4, x4 + h4, y4 + h4, x4, y4);
 	appearBuf->append ("f\n");
       }
+      appearBBox->setBorderWidth(biggestBorder);
       break;
     }
     appearBuf->append ("Q\n");
 
     Object aStream, resDict;
     double bbox[4];
-    bbox[0] = rect->x1;
-    bbox[1] = rect->y1;
-    bbox[2] = rect->x2;
-    bbox[3] = rect->y2;
+    bbox[0] = appearBBox->getPageXMin();
+    bbox[1] = appearBBox->getPageYMin();
+    bbox[2] = appearBBox->getPageXMax();
+    bbox[3] = appearBBox->getPageYMax();
     createForm(bbox, gTrue, NULL, &aStream);
     delete appearBuf;
 
@@ -3418,8 +3427,14 @@ void AnnotTextMarkup::draw(Gfx *gfx, GBool printing) {
 
   // draw the appearance stream
   appearance.fetch(xref, &obj);
-  gfx->drawAnnot(&obj, (AnnotBorder *)NULL, color,
-		 rect->x1, rect->y1, rect->x2, rect->y2);
+  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();
 }
 
-- 
1.7.6.5

_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler

Reply via email to