poppler/CairoOutputDev.cc | 145 ++++++++++++++++++++++++++++++---------------- poppler/CairoOutputDev.h | 6 - 2 files changed, 98 insertions(+), 53 deletions(-)
New commits: commit 7f0f080277d35f6f2e426ca2a3ff76c2856daeaf Author: Adrian Johnson <[email protected]> Date: Tue Apr 10 00:08:49 2012 +0930 cairo: fix stroke pattern with transparency group Cairo copy path/append path with device offsets is broken. Use GfxPath instead. Bug 48468 diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc index 8ea4129..32f01d3 100644 --- a/poppler/CairoOutputDev.cc +++ b/poppler/CairoOutputDev.cc @@ -776,7 +776,7 @@ void CairoOutputDev::fill(GfxState *state) { cairo_mask (cairo, mask); cairo_restore (cairo); } else if (strokePathClip) { - fillToStrokePathClip(); + fillToStrokePathClip(state); } else { cairo_fill (cairo); } @@ -865,7 +865,7 @@ GBool CairoOutputDev::tilingPatternFill(GfxState *state, Gfx *gfx1, Catalog *cat cairo_set_source (cairo, pattern); cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT); if (strokePathClip) { - fillToStrokePathClip(); + fillToStrokePathClip(state); } else { cairo_fill (cairo); } @@ -1100,8 +1100,7 @@ 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); + strokePathClip->path = state->getPath()->copy(); cairo_get_matrix (cairo, &strokePathClip->ctm); strokePathClip->line_width = cairo_get_line_width (cairo); strokePathClip->dash_count = cairo_get_dash_count (cairo); @@ -1116,7 +1115,7 @@ void CairoOutputDev::clipToStrokePath(GfxState *state) { strokePathClip->miter = cairo_get_miter_limit (cairo); } -void CairoOutputDev::fillToStrokePathClip() { +void CairoOutputDev::fillToStrokePathClip(GfxState *state) { cairo_save (cairo); cairo_set_matrix (cairo, &strokePathClip->ctm); @@ -1126,14 +1125,12 @@ void CairoOutputDev::fillToStrokePathClip() { 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); + doPath (cairo, state, strokePathClip->path); cairo_stroke (cairo); cairo_restore (cairo); - cairo_path_destroy (strokePathClip->path); + delete strokePathClip->path; if (strokePathClip->dashes) gfree (strokePathClip->dashes); gfree (strokePathClip); diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h index f0c1666..ae85433 100644 --- a/poppler/CairoOutputDev.h +++ b/poppler/CairoOutputDev.h @@ -273,7 +273,7 @@ protected: GBool interpolate); GBool getStreamData (Stream *str, char **buffer, int *length); void setMimeData(Stream *str, Object *ref, cairo_surface_t *image); - void fillToStrokePathClip(); + void fillToStrokePathClip(GfxState *state); void alignStrokeCoords(GfxSubpath *subpath, int i, double *x, double *y); GfxRGB fill_color, stroke_color; @@ -286,7 +286,7 @@ protected: CairoFont *currentFont; struct StrokePathClip { - cairo_path_t *path; + GfxPath *path; cairo_matrix_t ctm; double line_width; double *dashes; commit 5ea305c3924cead302092378ab67300c3099afd9 Author: Adrian Johnson <[email protected]> Date: Sun Apr 8 23:11:30 2012 +0930 cairo: only align stroke coords for horizontal and vertical lines Bug 48318 diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc index df2be51..8ea4129 100644 --- a/poppler/CairoOutputDev.cc +++ b/poppler/CairoOutputDev.cc @@ -640,48 +640,90 @@ void CairoOutputDev::updateFont(GfxState *state) { cairo_set_font_matrix (cairo, &matrix); } -void CairoOutputDev::alignStrokeCoords(double *x, double *y) +/* Tolerance in pixels for checking if strokes are horizontal or vertical + * lines in device space */ +#define STROKE_COORD_TOLERANCE 0.5 + +/* Align stroke coordinate i if the point is the start or end of a + * horizontal or vertical line */ +void CairoOutputDev::alignStrokeCoords(GfxSubpath *subpath, int i, double *x, double *y) { - /* see http://www.cairographics.org/FAQ/#sharp_lines */ - cairo_user_to_device (cairo, x, y); - *x = floor(*x) + 0.5; - *y = floor(*y) + 0.5; - cairo_device_to_user (cairo, x, y); + double x1, y1, x2, y2; + GBool align = gFalse; + + x1 = subpath->getX(i); + y1 = subpath->getY(i); + cairo_user_to_device (cairo, &x1, &y1); + + // Does the current coord and prev coord form a horiz or vert line? + if (i > 0 && !subpath->getCurve(i - 1)) { + x2 = subpath->getX(i - 1); + y2 = subpath->getY(i - 1); + cairo_user_to_device (cairo, &x2, &y2); + if (fabs(x2 - x1) < STROKE_COORD_TOLERANCE || fabs(y2 - y1) < STROKE_COORD_TOLERANCE) + align = gTrue; + } + + // Does the current coord and next coord form a horiz or vert line? + if (i < subpath->getNumPoints() - 1 && !subpath->getCurve(i + 1)) { + x2 = subpath->getX(i + 1); + y2 = subpath->getY(i + 1); + cairo_user_to_device (cairo, &x2, &y2); + if (fabs(x2 - x1) < STROKE_COORD_TOLERANCE || fabs(y2 - y1) < STROKE_COORD_TOLERANCE) + align = gTrue; + } + + *x = subpath->getX(i); + *y = subpath->getY(i); + if (align) { + /* see http://www.cairographics.org/FAQ/#sharp_lines */ + cairo_user_to_device (cairo, x, y); + *x = floor(*x) + 0.5; + *y = floor(*y) + 0.5; + cairo_device_to_user (cairo, x, y); + } } +#undef STROKE_COORD_TOLERANCE + void CairoOutputDev::doPath(cairo_t *cairo, GfxState *state, GfxPath *path) { GfxSubpath *subpath; int i, j; + double x, y; cairo_new_path (cairo); for (i = 0; i < path->getNumSubpaths(); ++i) { subpath = path->getSubpath(i); if (subpath->getNumPoints() > 0) { if (align_stroke_coords) { - double x = subpath->getX(0); - double y = subpath->getY(0); - alignStrokeCoords(&x, &y); - cairo_move_to (cairo, x, y); + alignStrokeCoords(subpath, 0, &x, &y); } else { - cairo_move_to (cairo, subpath->getX(0), subpath->getY(0)); + x = subpath->getX(0); + y = subpath->getY(0); } + cairo_move_to (cairo, x, y); j = 1; while (j < subpath->getNumPoints()) { if (subpath->getCurve(j)) { + if (align_stroke_coords) { + alignStrokeCoords(subpath, j + 2, &x, &y); + } else { + x = subpath->getX(j+2); + y = subpath->getY(j+2); + } cairo_curve_to( cairo, subpath->getX(j), subpath->getY(j), subpath->getX(j+1), subpath->getY(j+1), - subpath->getX(j+2), subpath->getY(j+2)); + x, y); j += 3; } else { if (align_stroke_coords) { - double x = subpath->getX(j); - double y = subpath->getY(j); - alignStrokeCoords(&x, &y); - cairo_line_to (cairo, x, y); - } else { - cairo_line_to (cairo, subpath->getX(j), subpath->getY(j)); - } + alignStrokeCoords(subpath, j, &x, &y); + } else { + x = subpath->getX(j); + y = subpath->getY(j); + } + cairo_line_to (cairo, x, y); ++j; } } diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h index 873dd43..f0c1666 100644 --- a/poppler/CairoOutputDev.h +++ b/poppler/CairoOutputDev.h @@ -274,7 +274,7 @@ protected: GBool getStreamData (Stream *str, char **buffer, int *length); void setMimeData(Stream *str, Object *ref, cairo_surface_t *image); void fillToStrokePathClip(); - void alignStrokeCoords(double *x, double *y); + void alignStrokeCoords(GfxSubpath *subpath, int i, double *x, double *y); GfxRGB fill_color, stroke_color; cairo_pattern_t *fill_pattern, *stroke_pattern; commit 8414d8f621b8abb018e80f2255cfb511a1e558d4 Author: Adrian Johnson <[email protected]> Date: Mon Apr 9 12:08:20 2012 +0930 cairo: ensure 0 width lines with stroke_adjust are aligned Previously the code path for 0 width lines ignored the stroke_adjust setting. Rearrange the code so the code path for stroke_adjust == TRUE is performed first (this will also set 0 width lines to 1 pixel wide). diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc index fa29146..df2be51 100644 --- a/poppler/CairoOutputDev.cc +++ b/poppler/CairoOutputDev.cc @@ -417,9 +417,25 @@ void CairoOutputDev::updateMiterLimit(GfxState *state) { void CairoOutputDev::updateLineWidth(GfxState *state) { LOG(printf ("line width: %f\n", state->getLineWidth())); adjusted_stroke_width = gFalse; - if (state->getLineWidth() == 0.0) { - /* find out how big pixels (device unit) are in the x and y directions - * choose the smaller of the two as our line width */ + double width = state->getLineWidth(); + if (stroke_adjust && !printing) { + double x, y; + x = y = width; + + /* find out line width in device units */ + cairo_user_to_device_distance(cairo, &x, &y); + if (fabs(x) <= 1.0 && fabs(y) <= 1.0) { + /* adjust width to at least one device pixel */ + x = y = 1.0; + cairo_device_to_user_distance(cairo, &x, &y); + width = MIN(fabs(x),fabs(y)); + adjusted_stroke_width = gTrue; + } + } else if (width == 0.0) { + /* Cairo does not support 0 line width == 1 device pixel. Find out + * how big pixels (device unit) are in the x and y + * directions. Choose the smaller of the two as our line width. + */ double x = 1.0, y = 1.0; if (printing) { // assume printer pixel size is 1/600 inch @@ -427,25 +443,9 @@ void CairoOutputDev::updateLineWidth(GfxState *state) { y = 72.0/600; } cairo_device_to_user_distance(cairo, &x, &y); - cairo_set_line_width (cairo, MIN(fabs(x),fabs(y))); - } else { - double width = state->getLineWidth(); - if (stroke_adjust && !printing) { - double x, y; - x = y = width; - - /* find out line width in device units */ - cairo_user_to_device_distance(cairo, &x, &y); - if (fabs(x) <= 1.0 && fabs(y) <= 1.0) { - /* adjust width to at least one device pixel */ - x = y = 1.0; - cairo_device_to_user_distance(cairo, &x, &y); - width = MIN(fabs(x),fabs(y)); - adjusted_stroke_width = gTrue; - } - } - cairo_set_line_width (cairo, width); + width = MIN(fabs(x),fabs(y)); } + cairo_set_line_width (cairo, width); if (cairo_shape) cairo_set_line_width (cairo_shape, cairo_get_line_width (cairo)); } commit af1a84eb90656de68bb14f2c4ae4f813c51bc3a3 Author: Adrian Johnson <[email protected]> Date: Mon Apr 9 17:17:29 2012 +0930 cairo: fix paintTransparencyGroup when both mask and fill opacity are required Bug 48453 diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc index 22fdaca..fa29146 100644 --- a/poppler/CairoOutputDev.cc +++ b/poppler/CairoOutputDev.cc @@ -1460,11 +1460,17 @@ void CairoOutputDev::paintTransparencyGroup(GfxState * /*state*/, double * /*bbo if (status) printf("BAD status: %s\n", cairo_status_to_string(status)); } else { + if (fill_opacity < 1.0) { + cairo_push_group(cairo); + } cairo_save(cairo); cairo_set_matrix(cairo, &mask_matrix); cairo_mask(cairo, mask); cairo_restore(cairo); - + if (fill_opacity < 1.0) { + cairo_pop_group_to_source(cairo); + cairo_paint_with_alpha (cairo, fill_opacity); + } cairo_pattern_destroy(mask); mask = NULL; } _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
