From 4ffd3ef9b6c72d518961ffad59d9ee46825765ab Mon Sep 17 00:00:00 2001 From: Jason Crain Date: Sun, 28 Feb 2016 16:18:05 -0600 Subject: [PATCH] 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 --- poppler/CairoOutputDev.cc | 38 ++++++++++++++++++++++++++++++-------- poppler/CairoOutputDev.h | 1 + 2 files changed, 31 insertions(+), 8 deletions(-) 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 -- 2.7.0