The attached patches contain many improvements in Annot rendering (and thus
printing).
0001 is a bug fix, to make it possible to hide annotations when printing.
0002 fixes the existing AnnotGemetry::draw method.
0003, 0004, and 0007 implement Annot*::draw methods from scratch.
0005 adds leading line support when drawing AnnotLines.
0006 adds support for typeSquiggly and fixes some bugs that prevented other
types from being drawn.
Note on 0007: AnnotFreeText is a box with text inside. This patch only
implements basic functionality:
- it can't print the full range of Unicode characters (in fact it converts to
WinAnsi before printing)
- font is hardcoded. Note that the font resource dict is not written when
outputting to PS. This fact results in a invalid font reference in the Tf
command. However, font is substituted and a warning is issued in all ps viewers
I have at hand
I'll try to fix 0007 to output font res dict tomorrow, but I feel that even at
this stage this basic implementation can be useful.
The other patches are final
From 610f32756d4ddbd295562de768f91b7ef4ba0431 Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Sat, 24 Mar 2012 23:13:48 +0100
Subject: [PATCH 1/7] Fix: annotDisplayDecideCbk was not propagated
---
poppler/OutputDev.h | 5 ++++-
poppler/PSOutputDev.cc | 10 +++++++---
poppler/PSOutputDev.h | 4 +++-
poppler/Page.cc | 3 ++-
4 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h
index 7e51b9d..a51d2e8 100644
--- a/poppler/OutputDev.h
+++ b/poppler/OutputDev.h
@@ -39,6 +39,7 @@
#include "CharTypes.h"
#include "Object.h"
+class Annot;
class Dict;
class GooHash;
class GooString;
@@ -124,7 +125,9 @@ public:
int sliceX, int sliceY, int sliceW, int sliceH,
GBool printing,
GBool (* abortCheckCbk)(void *data) = NULL,
- void * abortCheckCbkData = NULL)
+ void * abortCheckCbkData = NULL,
+ GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
+ void *annotDisplayDecideCbkData = NULL)
{ return gTrue; }
// Start a page.
diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index 8fa8410..54d1ea8 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -3033,7 +3033,9 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
int sliceW, int sliceH,
GBool printing,
GBool (*abortCheckCbk)(void *data),
- void *abortCheckCbkData) {
+ void *abortCheckCbkData,
+ GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data),
+ void *annotDisplayDecideCbkData) {
PreScanOutputDev *scan;
GBool rasterize;
#if HAVE_SPLASH
@@ -3065,7 +3067,8 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
scan = new PreScanOutputDev(doc);
page->displaySlice(scan, 72, 72, rotateA, useMediaBox, crop,
sliceX, sliceY, sliceW, sliceH,
- printing, abortCheckCbk, abortCheckCbkData);
+ printing, abortCheckCbk, abortCheckCbkData,
+ annotDisplayDecideCbk, annotDisplayDecideCbkData);
rasterize = scan->usesTransparency() || scan->usesPatternImageMask();
delete scan;
}
@@ -3148,7 +3151,8 @@ GBool PSOutputDev::checkPageSlice(Page *page, double /*hDPI*/, double /*vDPI*/,
page->displaySlice(splashOut, hDPI2, vDPI2,
(360 - page->getRotate()) % 360, useMediaBox, crop,
sliceX, stripeY, sliceW, stripeH,
- printing, abortCheckCbk, abortCheckCbkData);
+ printing, abortCheckCbk, abortCheckCbkData,
+ annotDisplayDecideCbk, annotDisplayDecideCbkData);
// draw the rasterized image
bitmap = splashOut->getBitmap();
diff --git a/poppler/PSOutputDev.h b/poppler/PSOutputDev.h
index 82f8dfa..d65556d 100644
--- a/poppler/PSOutputDev.h
+++ b/poppler/PSOutputDev.h
@@ -178,7 +178,9 @@ public:
int sliceX, int sliceY, int sliceW, int sliceH,
GBool printing,
GBool (*abortCheckCbk)(void *data) = NULL,
- void *abortCheckCbkData = NULL);
+ void *abortCheckCbkData = NULL,
+ GBool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = NULL,
+ void *annotDisplayDecideCbkData = NULL);
// Start a page.
virtual void startPage(int pageNum, GfxState *state);
diff --git a/poppler/Page.cc b/poppler/Page.cc
index b9d25ff..afd7bc1 100644
--- a/poppler/Page.cc
+++ b/poppler/Page.cc
@@ -505,7 +505,8 @@ void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
if (!out->checkPageSlice(this, hDPI, vDPI, rotate, useMediaBox, crop,
sliceX, sliceY, sliceW, sliceH,
printing,
- abortCheckCbk, abortCheckCbkData)) {
+ abortCheckCbk, abortCheckCbkData,
+ annotDisplayDecideCbk, annotDisplayDecideCbkData)) {
return;
}
--
1.7.6.5
From eb1e112e2ff5233b9833892abaa26e49e09e9fe5 Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Wed, 21 Mar 2012 21:12:59 +0100
Subject: [PATCH 2/7] 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 58c10ab5bcb238e1c2dcfec312f1c7eb5310aafe Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Wed, 21 Mar 2012 22:33:13 +0100
Subject: [PATCH 3/7] 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 016a9b6ffd75b4dcd97317e34f8b556f077174be Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Wed, 21 Mar 2012 22:48:05 +0100
Subject: [PATCH 4/7] 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 5971a5e2ca1abc701180f573f9b7edf63c6e44c6 Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Thu, 22 Mar 2012 17:33:01 +0100
Subject: [PATCH 5/7] Improvements to AnnotLine::draw
---
poppler/Annot.cc | 29 +++++++++++++++++++++++++----
1 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index 6d42be1..e2b5ca8 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -2851,10 +2851,31 @@ 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 axis, center becomes coord1
+ const double angle = atan2(y2 - y1, x2 - x1);
+ appearBuf->appendf ("{0:.2f} {1:.2f} {2:.2f} {3:.2f} {4:.2f} {5:.2f} cm\n",
+ cos(angle), sin(angle), -sin(angle), cos(angle), x1-rect->x1, y1-rect->y1);
+
+ // Draw main segment TODO: Line ending, caption
+ appearBuf->appendf ("0 {0:.2f} m {1:.2f} {0:.2f} l S\n", leaderLineLength, main_len);
+
+ // Draw leader lines
+ double ll_len = fabs(leaderLineLength) + leaderLineExtension;
+ double sign = leaderLineLength >= 0 ? 1 : -1;
+ if (ll_len != 0) {
+ appearBuf->appendf ("0 0 m 0 {0:.2f} l S\n", sign*ll_len);
+ appearBuf->appendf ("{0:.2f} 0 m {0:.2f} {1:.2f} l S\n", main_len, sign*ll_len);
+ }
+
appearBuf->append ("Q\n");
double bbox[4];
--
1.7.6.5
From 8c08329f097070a713fc26929f4d370c7d8dd5c3 Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Sun, 25 Mar 2012 22:04:11 +0200
Subject: [PATCH 6/7] 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 e2b5ca8..fec112b 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -3044,42 +3044,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);
@@ -3088,16 +3086,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();
@@ -3117,7 +3136,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",
@@ -3127,31 +3146,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 eb71455e35a694cc221cf4432afb29a27264fcac Mon Sep 17 00:00:00 2001
From: Fabio D'Urso <[email protected]>
Date: Fri, 23 Mar 2012 20:54:58 +0100
Subject: [PATCH 7/7] Basic AnnotFreeText rendering (hardcoded font, WinAnsi
characters only)
This patch also moves layoutText and writeString from AnnotWidget to Annot
---
poppler/Annot.cc | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
poppler/Annot.h | 10 +++--
2 files changed, 137 insertions(+), 6 deletions(-)
diff --git a/poppler/Annot.cc b/poppler/Annot.cc
index fec112b..2a7099b 100644
--- a/poppler/Annot.cc
+++ b/poppler/Annot.cc
@@ -2549,6 +2549,135 @@ 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::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, 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\n1 w\n0 G\n0 0 {0:.2f} {1:.2f} re\nb\n", width, height);
+ appearBuf->appendf ("2 0 {0:.2f} {1:.2f} re\nW\nn\n", width-4, height);
+
+ // Set font state
+ appearBuf->appendf ("0 g\nBT\n1 0 0 1 2 {0:.2f} Tm\n", height);
+ appearBuf->appendf ("{0:.2f} TL\n/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\nQ\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;
+ }
+
+ // 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
//------------------------------------------------------------------------
@@ -3287,7 +3416,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)
{
@@ -3481,7 +3610,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..f4591ce 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);
@@ -1242,10 +1248,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
_______________________________________________
poppler mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/poppler