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

Carlos Garcia Campos carlosgc at kemper.freedesktop.org
Sat Apr 2 10:03:23 UTC 2016


 poppler/CairoOutputDev.cc |   38 ++++++++++++++++++++++++++++++--------
 poppler/CairoOutputDev.h  |    1 +
 2 files changed, 31 insertions(+), 8 deletions(-)

New commits:
commit 7d8dfb09d2b9d69d4e80838ce58fdbd091bce7ec
Author: Jason Crain <jason at aquaticape.us>
Date:   Sun Feb 28 16:18:05 2016 -0600

    cairo: fix fillToStrokePathClip crash and rendering
    
    The cairo backend can crash if the dash pattern changes between calling
    clipToStrokePathClip and fillToStrokePathClip because fillToStrokePathClip
    calls cairo_set_dash with the saved dash pattern but the current dash count.
    
    Fixes the crash by removing the call to cairo_get_dash_count in
    fillToStrokePathClip.  Makes strokePathClip reference counted because when
    drawing tiling patterns it may need to be kept around for more than one drawing
    operation.  Uses fillToStrokePathClip in a few more places to fix rendering.
    
    bug #62905

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index d0d6cb4..eab1ccc 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -278,6 +278,9 @@ void CairoOutputDev::saveState(GfxState *state) {
   ms->mask_matrix = mask_matrix;
   ms->next = maskStack;
   maskStack = ms;
+
+  if (strokePathClip)
+    strokePathClip->ref_count++;
 }
 
 void CairoOutputDev::restoreState(GfxState *state) {
@@ -305,6 +308,14 @@ void CairoOutputDev::restoreState(GfxState *state) {
     maskStack = ms->next;
     delete ms;
   }
+
+  if (strokePathClip && --strokePathClip->ref_count == 0) {
+    delete strokePathClip->path;
+    if (strokePathClip->dashes)
+      gfree (strokePathClip->dashes);
+    gfree (strokePathClip);
+    strokePathClip = NULL;
+  }
 }
 
 void CairoOutputDev::updateAll(GfxState *state) {
@@ -780,7 +791,14 @@ void CairoOutputDev::stroke(GfxState *state) {
   align_stroke_coords = gFalse;
   cairo_set_source (cairo, stroke_pattern);
   LOG(printf ("stroke\n"));
-  cairo_stroke (cairo);
+  if (strokePathClip) {
+    cairo_push_group (cairo);
+    cairo_stroke (cairo);
+    cairo_pop_group_to_source (cairo);
+    fillToStrokePathClip (state);
+  } else {
+    cairo_stroke (cairo);
+  }
   if (cairo_shape) {
     doPath (cairo_shape, state, state->getPath());
     cairo_stroke (cairo_shape);
@@ -803,6 +821,11 @@ void CairoOutputDev::fill(GfxState *state) {
   if (mask) {
     cairo_save (cairo);
     cairo_clip (cairo);
+    if (strokePathClip) {
+      cairo_push_group (cairo);
+      fillToStrokePathClip (state);
+      cairo_pop_group_to_source (cairo);
+    }
     cairo_set_matrix (cairo, &mask_matrix);
     cairo_mask (cairo, mask);
     cairo_restore (cairo);
@@ -1296,6 +1319,7 @@ void CairoOutputDev::clipToStrokePath(GfxState *state) {
   strokePathClip->cap = cairo_get_line_cap (cairo);
   strokePathClip->join = cairo_get_line_join (cairo);
   strokePathClip->miter = cairo_get_miter_limit (cairo);
+  strokePathClip->ref_count = 1;
 }
 
 void CairoOutputDev::fillToStrokePathClip(GfxState *state) {
@@ -1303,7 +1327,6 @@ void CairoOutputDev::fillToStrokePathClip(GfxState *state) {
 
   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);
@@ -1312,12 +1335,6 @@ void CairoOutputDev::fillToStrokePathClip(GfxState *state) {
   cairo_stroke (cairo);
 
   cairo_restore (cairo);
-
-  delete strokePathClip->path;
-  if (strokePathClip->dashes)
-    gfree (strokePathClip->dashes);
-  gfree (strokePathClip);
-  strokePathClip = NULL;
 }
 
 void CairoOutputDev::beginString(GfxState *state, GooString *s)
@@ -2425,6 +2442,11 @@ void CairoOutputDev::drawImageMaskPrescaled(GfxState *state, Object *ref, Stream
 
     cairo_rectangle (cairo, 0., 0., scaledWidth, scaledHeight);
     cairo_clip (cairo);
+    if (strokePathClip) {
+      cairo_push_group (cairo);
+      fillToStrokePathClip (state);
+      cairo_pop_group_to_source (cairo);
+    }
     cairo_mask (cairo, pattern);
 
     //cairo_get_matrix(cairo, &matrix);
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index c146ce0..0f88778 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -308,6 +308,7 @@ protected:
     cairo_line_cap_t cap;
     cairo_line_join_t join;
     double miter;
+    int ref_count;
   } *strokePathClip;
 
   PDFDoc *doc;			// the current document


More information about the poppler mailing list