Commit 7d8dfb09 authored by Jason Crain's avatar Jason Crain Committed by Carlos Garcia Campos

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
parent 67bc280c
......@@ -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);
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment