summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cairo-meta-surface.c54
-rw-r--r--src/cairo-path-fixed.c27
-rw-r--r--src/cairo-surface.c59
-rw-r--r--src/cairoint.h36
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,