mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 00:38:06 +02:00
Add a new fill_stroke surface backend method.
This method is for use in vector backends, where fill immediatly followed by stroke command with the same path can be emited in the same backend command. This commit also factorize the detection of such cases in the meta surface backend and automatically call the fill_stroke method on replay.
This commit is contained in:
parent
43d35e0110
commit
ac51fff0db
4 changed files with 169 additions and 7 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1386,6 +1386,65 @@ _cairo_surface_mask (cairo_surface_t *surface,
|
|||
return status;
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
@ -1750,6 +1770,22 @@ _cairo_surface_mask (cairo_surface_t *surface,
|
|||
cairo_pattern_t *source,
|
||||
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,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue