[poppler] poppler/CairoOutputDev.cc poppler/CairoOutputDev.h

Carlos Garcia Campos carlosgc at kemper.freedesktop.org
Mon Aug 22 06:09:02 PDT 2011


 poppler/CairoOutputDev.cc |   52 +++++++++++++++++++++++++++++++++++++++++++++-
 poppler/CairoOutputDev.h  |   17 +++++++++++++--
 2 files changed, 66 insertions(+), 3 deletions(-)

New commits:
commit 3a574f13fa22b7c31eda0d0437f4094a5a39ff34
Author: Adrian Johnson <ajohnson at redneon.com>
Date:   Fri Aug 19 23:23:24 2011 +0930

    cairo: fix stroke patterns
    
    Since cairo still does not yet have cairo_stroke_to_path(), this
    implements a workaround for stroke patterns. In clipToStrokePath, the
    stroke path and stroke parameters are saved. In tilingPatternFill and
    fill (used to draw shading patterns) if a stroke path clip has been
    saved, the current pattern is stroked instead of filled using the
    saved stroke.
    Fixes bug #11719.

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 08c28ec..cdca10d 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -133,6 +133,7 @@ CairoOutputDev::CairoOutputDev() {
   stroke_opacity = 1.0;
   fill_opacity = 1.0;
   textClipPath = NULL;
+  strokePathClip = NULL;
   haveCSPattern = gFalse;
   cairo = NULL;
   currentFont = NULL;
@@ -673,6 +674,8 @@ void CairoOutputDev::fill(GfxState *state) {
   if (mask) {
     cairo_clip (cairo);
     cairo_mask (cairo, mask);
+  } else if (strokePathClip) {
+    fillToStrokePathClip();
   } else {
     cairo_fill (cairo);
   }
@@ -713,6 +716,7 @@ GBool CairoOutputDev::tilingPatternFill(GfxState *state, Catalog *cat, Object *s
   double xMin, yMin, xMax, yMax;
   double width, height;
   int surface_width, surface_height;
+  StrokePathClip *strokePathTmp;
 
   width = bbox[2] - bbox[0];
   height = bbox[3] - bbox[1];
@@ -736,9 +740,12 @@ GBool CairoOutputDev::tilingPatternFill(GfxState *state, Catalog *cat, Object *s
 
   box.x1 = bbox[0]; box.y1 = bbox[1];
   box.x2 = bbox[2]; box.y2 = bbox[3];
+  strokePathTmp = strokePathClip;
+  strokePathClip = NULL;
   gfx = new Gfx(xref, this, resDict, catalog, &box, NULL);
   gfx->display(str);
   delete gfx;
+  strokePathClip = strokePathTmp;
 
   pattern = cairo_pattern_create_for_surface (cairo_get_target (cairo));
   cairo_destroy (cairo);
@@ -756,7 +763,11 @@ GBool CairoOutputDev::tilingPatternFill(GfxState *state, Catalog *cat, Object *s
   cairo_transform (cairo, &matrix);
   cairo_set_source (cairo, pattern);
   cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
-  cairo_fill (cairo);
+  if (strokePathClip) {
+    fillToStrokePathClip();
+  } else {
+    cairo_fill (cairo);
+  }
 
   cairo_pattern_destroy (pattern);
 
@@ -987,6 +998,45 @@ void CairoOutputDev::eoClip(GfxState *state) {
 
 void CairoOutputDev::clipToStrokePath(GfxState *state) {
   LOG(printf("clip-to-stroke-path\n"));
+  strokePathClip = (StrokePathClip*)gmalloc (sizeof(*strokePathClip));
+  doPath (cairo, state, state->getPath());
+  strokePathClip->path = cairo_copy_path (cairo);
+  cairo_get_matrix (cairo, &strokePathClip->ctm);
+  strokePathClip->line_width = cairo_get_line_width (cairo);
+  strokePathClip->dash_count = cairo_get_dash_count (cairo);
+  if (strokePathClip->dash_count) {
+    strokePathClip->dashes = (double*) gmallocn (sizeof(double), strokePathClip->dash_count);
+    cairo_get_dash (cairo, strokePathClip->dashes, &strokePathClip->dash_offset);
+  } else {
+    strokePathClip->dashes = NULL;
+  }
+  strokePathClip->cap = cairo_get_line_cap (cairo);
+  strokePathClip->join = cairo_get_line_join (cairo);
+  strokePathClip->miter = cairo_get_miter_limit (cairo);
+}
+
+void CairoOutputDev::fillToStrokePathClip() {
+  cairo_save (cairo);
+
+  cairo_set_matrix (cairo, &strokePathClip->ctm);
+  cairo_set_line_width (cairo, strokePathClip->line_width);
+  strokePathClip->dash_count = cairo_get_dash_count (cairo);
+  cairo_set_dash (cairo, strokePathClip->dashes, strokePathClip->dash_count, strokePathClip->dash_offset);
+  cairo_set_line_cap (cairo, strokePathClip->cap);
+  cairo_set_line_join (cairo, strokePathClip->join);
+  cairo_set_miter_limit (cairo, strokePathClip->miter);
+
+  cairo_new_path (cairo);
+  cairo_append_path (cairo, strokePathClip->path);
+  cairo_stroke (cairo);
+
+  cairo_restore (cairo);
+
+  cairo_path_destroy (strokePathClip->path);
+  if (strokePathClip->dashes)
+    gfree (strokePathClip->dashes);
+  gfree (strokePathClip);
+  strokePathClip = NULL;
 }
 
 void CairoOutputDev::beginString(GfxState *state, GooString *s)
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index 67f7810..b8c0703 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -281,13 +281,26 @@ protected:
 				     GBool interpolate);
   GBool getStreamData (Stream *str, char **buffer, int *length);
   void setMimeData(Stream *str, Object *ref, cairo_surface_t *image);
-  
+  void fillToStrokePathClip();
+
   GfxRGB fill_color, stroke_color;
   cairo_pattern_t *fill_pattern, *stroke_pattern;
   double fill_opacity;
   double stroke_opacity;
   CairoFont *currentFont;
-  
+
+  struct StrokePathClip {
+    cairo_path_t *path;
+    cairo_matrix_t ctm;
+    double line_width;
+    double *dashes;
+    int dash_count;
+    double dash_offset;
+    cairo_line_cap_t cap;
+    cairo_line_join_t join;
+    double miter;
+  } *strokePathClip;
+
   XRef *xref;			// xref table for current document
   Catalog *catalog;
 


More information about the poppler mailing list