diff options
-rw-r--r-- | src/cairo-meta-surface.c | 54 | ||||
-rw-r--r-- | src/cairo-path-fixed.c | 27 | ||||
-rw-r--r-- | src/cairo-surface.c | 59 | ||||
-rw-r--r-- | src/cairoint.h | 36 |
4 files changed, 169 insertions, 7 deletions
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c index 35039ad4..d8f5064a 100644 --- a/src/cairo-meta-surface.c +++ b/src/cairo-meta-surface.c @@ -735,14 +735,54 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface, break; } case CAIRO_COMMAND_FILL: - status = _cairo_surface_fill (target, - command->fill.op, - &command->fill.source.base, - dev_path, - command->fill.fill_rule, - command->fill.tolerance, - command->fill.antialias); + { + cairo_command_t *stroke_command; + + stroke_command = (i < num_elements - 1) ? elements[i + 1] : NULL; + + if (stroke_command != NULL && + stroke_command->header.type == CAIRO_COMMAND_STROKE && + _cairo_path_fixed_is_equal (dev_path, _cairo_command_get_path (stroke_command))) { + cairo_matrix_t dev_ctm; + cairo_matrix_t dev_ctm_inverse; + cairo_matrix_t tmp; + + dev_ctm = stroke_command->stroke.ctm; + dev_ctm_inverse = stroke_command->stroke.ctm_inverse; + + if (has_device_transform) { + cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform); + tmp = surface->device_transform; + status = cairo_matrix_invert (&tmp); + assert (status == CAIRO_STATUS_SUCCESS); + cairo_matrix_multiply (&dev_ctm_inverse, &tmp, &dev_ctm_inverse); + } + + status = _cairo_surface_fill_stroke (target, + command->fill.op, + &command->fill.source.base, + command->fill.fill_rule, + command->fill.tolerance, + command->fill.antialias, + dev_path, + stroke_command->stroke.op, + &stroke_command->stroke.source.base, + &stroke_command->stroke.style, + &dev_ctm, + &dev_ctm_inverse, + stroke_command->stroke.tolerance, + stroke_command->stroke.antialias); + i++; + } else + status = _cairo_surface_fill (target, + command->fill.op, + &command->fill.source.base, + dev_path, + command->fill.fill_rule, + command->fill.tolerance, + command->fill.antialias); break; + } case CAIRO_COMMAND_SHOW_GLYPHS: { cairo_glyph_t *glyphs = command->show_glyphs.glyphs; diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c index 86c771ee..7c8f34bd 100644 --- a/src/cairo-path-fixed.c +++ b/src/cairo-path-fixed.c @@ -550,3 +550,30 @@ _cairo_path_fixed_device_transform (cairo_path_fixed_t *path, _cairo_fixed_from_double (device_transform->xx), _cairo_fixed_from_double (device_transform->yy)); } + +cairo_bool_t +_cairo_path_fixed_is_equal (cairo_path_fixed_t *path, + cairo_path_fixed_t *other) +{ + cairo_path_buf_t *path_buf, *other_buf; + + if (path->current_point.x != other->current_point.x || + path->current_point.y != other->current_point.y || + path->has_current_point != other->has_current_point || + path->has_curve_to != other->has_curve_to || + path->last_move_point.x != other->last_move_point.x || + path->last_move_point.y != other->last_move_point.y) + return FALSE; + + other_buf = other->buf_head; + for (path_buf = path->buf_head; path_buf != NULL; path_buf = path_buf->next) { + if (other_buf == NULL || + path_buf->num_ops != other_buf->num_ops || + path_buf->num_points != other_buf->num_points || + memcmp (path_buf->op, other_buf->op, path_buf->num_ops) != 0 || + memcmp (path_buf->points, other_buf->points, path_buf->num_points != 0)) + return FALSE; + other_buf = other_buf->next; + } + return TRUE; +} diff --git a/src/cairo-surface.c b/src/cairo-surface.c index 05d9939f..0c5cbbe6 100644 --- a/src/cairo-surface.c +++ b/src/cairo-surface.c @@ -1387,6 +1387,65 @@ _cairo_surface_mask (cairo_surface_t *surface, } cairo_status_t +_cairo_surface_fill_stroke (cairo_surface_t *surface, + cairo_operator_t fill_op, + cairo_pattern_t *fill_source, + cairo_fill_rule_t fill_rule, + double fill_tolerance, + cairo_antialias_t fill_antialias, + cairo_path_fixed_t *path, + cairo_operator_t stroke_op, + cairo_pattern_t *stroke_source, + cairo_stroke_style_t *stroke_style, + cairo_matrix_t *stroke_ctm, + cairo_matrix_t *stroke_ctm_inverse, + double stroke_tolerance, + cairo_antialias_t stroke_antialias) +{ + cairo_status_t status; + + if (surface->backend->fill_stroke) { + cairo_pattern_union_t dev_stroke_source; + cairo_pattern_union_t dev_fill_source; + cairo_matrix_t dev_ctm = *stroke_ctm; + cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse; + + status = _cairo_surface_copy_pattern_for_destination (stroke_source, surface, &dev_stroke_source.base); + if (status) + return status; + + status = _cairo_surface_copy_pattern_for_destination (fill_source, surface, &dev_fill_source.base); + if (status) { + _cairo_pattern_fini (&dev_stroke_source.base); + return status; + } + + status = surface->backend->fill_stroke (surface, fill_op, &dev_fill_source.base, + fill_rule, fill_tolerance, fill_antialias, + path, stroke_op, &dev_stroke_source.base, stroke_style, + &dev_ctm, &dev_ctm_inverse, stroke_tolerance, + stroke_antialias); + + _cairo_pattern_fini (&dev_stroke_source.base); + _cairo_pattern_fini (&dev_fill_source.base); + + if (status != CAIRO_INT_STATUS_UNSUPPORTED) + return status; + } + + status = _cairo_surface_fill (surface, fill_op, fill_source, path, + fill_rule, fill_tolerance, fill_antialias); + if (status) + return status; + + status = _cairo_surface_stroke (surface, stroke_op, stroke_source, path, + stroke_style, stroke_ctm, stroke_ctm_inverse, + stroke_tolerance, stroke_antialias); + + return status; +} + +cairo_status_t _cairo_surface_stroke (cairo_surface_t *surface, cairo_operator_t op, cairo_pattern_t *source, diff --git a/src/cairoint.h b/src/cairoint.h index 310fdfdb..58f2ea35 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -874,6 +874,22 @@ struct _cairo_surface_backend { cairo_warn cairo_status_t (*reset) (void *surface); + + cairo_warn cairo_int_status_t + (*fill_stroke) (void *surface, + cairo_operator_t fill_op, + cairo_pattern_t *fill_source, + cairo_fill_rule_t fill_rule, + double fill_tolerance, + cairo_antialias_t fill_antialias, + cairo_path_fixed_t *path, + cairo_operator_t stroke_op, + cairo_pattern_t *stroke_source, + cairo_stroke_style_t *stroke_style, + cairo_matrix_t *stroke_ctm, + cairo_matrix_t *stroke_ctm_inverse, + double stroke_tolerance, + cairo_antialias_t stroke_antialias); }; typedef struct _cairo_format_masks { @@ -1469,6 +1485,10 @@ cairo_private cairo_status_t _cairo_path_fixed_init_copy (cairo_path_fixed_t *path, cairo_path_fixed_t *other); +cairo_private cairo_bool_t +_cairo_path_fixed_is_equal (cairo_path_fixed_t *path, + cairo_path_fixed_t *other); + cairo_private cairo_path_fixed_t * _cairo_path_fixed_create (void); @@ -1751,6 +1771,22 @@ _cairo_surface_mask (cairo_surface_t *surface, cairo_pattern_t *mask); cairo_private cairo_status_t +_cairo_surface_fill_stroke (cairo_surface_t *surface, + cairo_operator_t fill_op, + cairo_pattern_t *fill_source, + cairo_fill_rule_t fill_rule, + double fill_tolerance, + cairo_antialias_t fill_antialias, + cairo_path_fixed_t *path, + cairo_operator_t stroke_op, + cairo_pattern_t *stroke_source, + cairo_stroke_style_t *stroke_style, + cairo_matrix_t *stroke_ctm, + cairo_matrix_t *stroke_ctm_inverse, + double stroke_tolerance, + cairo_antialias_t stroke_antialias); + +cairo_private cairo_status_t _cairo_surface_stroke (cairo_surface_t *surface, cairo_operator_t op, cairo_pattern_t *source, |