[cairo-commit] 4 commits - src/cairoint.h src/cairo-meta-surface.c src/cairo-path-fixed.c src/cairo-surface.c src/cairo-svg-surface.c
Emmanuel Pacaud
emmanuel at kemper.freedesktop.org
Sat Aug 25 11:52:11 PDT 2007
src/cairo-meta-surface.c | 54 ++++++++++++--
src/cairo-path-fixed.c | 27 +++++++
src/cairo-surface.c | 59 +++++++++++++++
src/cairo-svg-surface.c | 176 +++++++++++++++++++++++++++++++++++++++--------
src/cairoint.h | 36 +++++++++
5 files changed, 318 insertions(+), 34 deletions(-)
New commits:
diff-tree 726ed304018915815d232822cd9efb83ee1339bc (from 89881187f22b40b4afd15eed0b2c19edcba2ca09)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date: Sun Jul 29 16:46:21 2007 +0200
[SVG] Don't emit transform property when matrix is identity.
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 6f2323e..cae90d9 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -451,16 +451,15 @@ _cairo_svg_surface_show_page (void *abst
static void
_cairo_svg_surface_emit_transform (cairo_output_stream_t *output,
char const *attribute_str,
- char const *trailer,
cairo_matrix_t *matrix)
{
- _cairo_output_stream_printf (output,
- "%s=\"matrix(%f,%f,%f,%f,%f,%f)\"%s",
- attribute_str,
- matrix->xx, matrix->yx,
- matrix->xy, matrix->yy,
- matrix->x0, matrix->y0,
- trailer);
+ if (!_cairo_matrix_is_identity (matrix))
+ _cairo_output_stream_printf (output,
+ "%s=\"matrix(%f,%f,%f,%f,%f,%f)\"",
+ attribute_str,
+ matrix->xx, matrix->yx,
+ matrix->xy, matrix->yy,
+ matrix->x0, matrix->y0);
}
typedef struct
@@ -616,7 +615,8 @@ _cairo_svg_document_emit_bitmap_glyph_da
}
_cairo_output_stream_printf (document->xml_node_glyphs, "<g");
- _cairo_svg_surface_emit_transform (document->xml_node_glyphs, " transform", ">/n", &image->base.device_transform_inverse);
+ _cairo_svg_surface_emit_transform (document->xml_node_glyphs, " transform", &image->base.device_transform_inverse);
+ _cairo_output_stream_printf (document->xml_node_glyphs, ">/n");
for (y = 0, row = image->data, rows = image->height; rows; row += image->stride, rows--, y++) {
for (x = 0, byte = row, cols = (image->width + 7) / 8; cols; byte++, cols--) {
@@ -917,7 +917,8 @@ _cairo_svg_surface_emit_composite_image_
"width=\"%d\" height=\"%d\"",
pattern_id,
extents.width, extents.height);
- _cairo_svg_surface_emit_transform (output, " patternTransform", ">\n", &p2u);
+ _cairo_svg_surface_emit_transform (output, " patternTransform", &p2u);
+ _cairo_output_stream_printf (output, ">\n");
}
_cairo_output_stream_printf (output,
@@ -925,7 +926,7 @@ _cairo_svg_surface_emit_composite_image_
extents.width, extents.height);
if (pattern_id == invalid_pattern_id)
- _cairo_svg_surface_emit_transform (output, " transform", "", &p2u);
+ _cairo_svg_surface_emit_transform (output, " transform", &p2u);
if (extra_attributes)
_cairo_output_stream_printf (output, " %s", extra_attributes);
@@ -1092,7 +1093,8 @@ _cairo_svg_surface_emit_composite_meta_p
pattern_id,
meta_surface->width_pixels,
meta_surface->height_pixels);
- _cairo_svg_surface_emit_transform (output, " patternTransform", ">\n", &p2u);
+ _cairo_svg_surface_emit_transform (output, " patternTransform", &p2u);
+ _cairo_output_stream_printf (output, ">\n");
}
_cairo_output_stream_printf (output,
@@ -1100,7 +1102,7 @@ _cairo_svg_surface_emit_composite_meta_p
id);
if (pattern_id == invalid_pattern_id)
- _cairo_svg_surface_emit_transform (output, " transform", "", &p2u);
+ _cairo_svg_surface_emit_transform (output, " transform", &p2u);
if (extra_attributes)
_cairo_output_stream_printf (output, " %s", extra_attributes);
@@ -1399,7 +1401,8 @@ _cairo_svg_surface_emit_linear_pattern (
x0, y0, x1, y1);
_cairo_svg_surface_emit_pattern_extend (document->xml_node_defs, &pattern->base.base),
- _cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u);
+ _cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u);
+ _cairo_output_stream_printf (document->xml_node_defs, ">\n");
_cairo_svg_surface_emit_pattern_stops (document->xml_node_defs ,&pattern->base, 0.0, FALSE, FALSE);
@@ -1469,8 +1472,8 @@ _cairo_svg_surface_emit_radial_pattern (
document->radial_pattern_id,
x1, y1,
x1, y1, r1);
-
- _cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u);
+ _cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u);
+ _cairo_output_stream_printf (document->xml_node_defs, ">\n");
if (extend == CAIRO_EXTEND_NONE ||
pattern->base.n_stops < 1)
@@ -1554,7 +1557,8 @@ _cairo_svg_surface_emit_radial_pattern (
_cairo_output_stream_printf (document->xml_node_defs, "spreadMethod=\"repeat\" ");
else
_cairo_svg_surface_emit_pattern_extend (document->xml_node_defs, &pattern->base.base);
- _cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", ">\n", &p2u);
+ _cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u);
+ _cairo_output_stream_printf (document->xml_node_defs, ">\n");
/* To support cairo's EXTEND_NONE, (for which SVG has no similar
* notion), we add transparent color stops on either end of the
@@ -1725,7 +1729,8 @@ _cairo_svg_surface_fill_stroke (void *
status = _cairo_svg_surface_emit_path (surface->xml_node, path, stroke_ctm_inverse);
- _cairo_svg_surface_emit_transform (surface->xml_node, " transform", "/>\n", stroke_ctm);
+ _cairo_svg_surface_emit_transform (surface->xml_node, " transform", stroke_ctm);
+ _cairo_output_stream_printf (surface->xml_node, "/>\n");
return status;
}
@@ -1998,7 +2003,8 @@ _cairo_svg_surface_stroke (void *abstr
status = _cairo_svg_surface_emit_path (surface->xml_node, path, ctm_inverse);
- _cairo_svg_surface_emit_transform (surface->xml_node, " transform", "/>\n", ctm);
+ _cairo_svg_surface_emit_transform (surface->xml_node, " transform", ctm);
+ _cairo_output_stream_printf (surface->xml_node, "/>\n");
return status;
}
diff-tree 89881187f22b40b4afd15eed0b2c19edcba2ca09 (from ac51fff0db73c5917a38af3f610d4751b8fec626)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date: Sun Jul 29 13:33:50 2007 +0200
[SVG] Implement fill_stroke method.
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 7cf58d2..6f2323e 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -1613,6 +1613,123 @@ _cairo_svg_surface_emit_pattern (cairo_s
return CAIRO_STATUS_SUCCESS;
}
+static void
+_cairo_svg_surface_emit_fill_style (cairo_output_stream_t *output,
+ cairo_svg_surface_t *surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_fill_rule_t fill_rule)
+{
+ _cairo_output_stream_printf (output,
+ "fill-rule: %s; ",
+ fill_rule == CAIRO_FILL_RULE_EVEN_ODD ?
+ "evenodd" : "nonzero");
+ _cairo_svg_surface_emit_operator (output, surface, op);
+ _cairo_svg_surface_emit_pattern (surface, source, output, FALSE);
+}
+
+static void
+_cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output,
+ cairo_svg_surface_t *surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_stroke_style_t *stroke_style)
+{
+ const char *line_cap, *line_join;
+ unsigned int i;
+
+ switch (stroke_style->line_cap) {
+ case CAIRO_LINE_CAP_BUTT:
+ line_cap = "butt";
+ break;
+ case CAIRO_LINE_CAP_ROUND:
+ line_cap = "round";
+ break;
+ case CAIRO_LINE_CAP_SQUARE:
+ line_cap = "square";
+ break;
+ default:
+ ASSERT_NOT_REACHED;
+ }
+
+ switch (stroke_style->line_join) {
+ case CAIRO_LINE_JOIN_MITER:
+ line_join = "miter";
+ break;
+ case CAIRO_LINE_JOIN_ROUND:
+ line_join = "round";
+ break;
+ case CAIRO_LINE_JOIN_BEVEL:
+ line_join = "bevel";
+ break;
+ default:
+ ASSERT_NOT_REACHED;
+ }
+
+ _cairo_output_stream_printf (output,
+ "stroke-width: %f; "
+ "stroke-linecap: %s; "
+ "stroke-linejoin: %s; ",
+ stroke_style->line_width,
+ line_cap,
+ line_join);
+
+ _cairo_svg_surface_emit_pattern (surface, source, output, TRUE);
+ _cairo_svg_surface_emit_operator (output, surface, op);
+
+ if (stroke_style->num_dashes > 0) {
+ _cairo_output_stream_printf (output, "stroke-dasharray: ");
+ for (i = 0; i < stroke_style->num_dashes; i++) {
+ _cairo_output_stream_printf (output, "%f",
+ stroke_style->dash[i]);
+ if (i + 1 < stroke_style->num_dashes)
+ _cairo_output_stream_printf (output, ",");
+ else
+ _cairo_output_stream_printf (output, "; ");
+ }
+ if (stroke_style->dash_offset != 0.0) {
+ _cairo_output_stream_printf (output,
+ "stroke-dashoffset: %f; ",
+ stroke_style->dash_offset);
+ }
+ }
+
+ _cairo_output_stream_printf (output,
+ "stroke-miterlimit: %f; ",
+ stroke_style->miter_limit);
+}
+
+static cairo_int_status_t
+_cairo_svg_surface_fill_stroke (void *abstract_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_svg_surface_t *surface = abstract_surface;
+ cairo_status_t status;
+
+ _cairo_output_stream_printf (surface->xml_node, "<path style=\"");
+ _cairo_svg_surface_emit_fill_style (surface->xml_node, surface, fill_op, fill_source, fill_rule);
+ _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, stroke_op, stroke_source, stroke_style);
+ _cairo_output_stream_printf (surface->xml_node, "\" ");
+
+ status = _cairo_svg_surface_emit_path (surface->xml_node, path, stroke_ctm_inverse);
+
+ _cairo_svg_surface_emit_transform (surface->xml_node, " transform", "/>\n", stroke_ctm);
+
+ return status;
+}
+
static cairo_int_status_t
_cairo_svg_surface_fill (void *abstract_surface,
cairo_operator_t op,
@@ -1630,13 +1747,8 @@ _cairo_svg_surface_fill (void *abstrac
assert (_cairo_svg_surface_operation_supported (surface, op, source));
- _cairo_output_stream_printf (surface->xml_node,
- "<path style=\"stroke: none; "
- "fill-rule: %s; ",
- fill_rule == CAIRO_FILL_RULE_EVEN_ODD ?
- "evenodd" : "nonzero");
- _cairo_svg_surface_emit_operator (surface->xml_node, surface, op);
- _cairo_svg_surface_emit_pattern (surface, source, surface->xml_node, FALSE);
+ _cairo_output_stream_printf (surface->xml_node, "<path style=\" stroke:none;");
+ _cairo_svg_surface_emit_fill_style (surface->xml_node, surface, op, source, fill_rule);
_cairo_output_stream_printf (surface->xml_node, "\" ");
status = _cairo_svg_surface_emit_path (surface->xml_node, path, NULL);
@@ -2043,7 +2155,11 @@ static const cairo_surface_backend_t cai
_cairo_svg_surface_mask,
_cairo_svg_surface_stroke,
_cairo_svg_surface_fill,
- _cairo_svg_surface_show_glyphs
+ _cairo_svg_surface_show_glyphs,
+ NULL, /* snapshot */
+ NULL, /* is_similar */
+ NULL, /* reset */
+ _cairo_svg_surface_fill_stroke
};
static cairo_svg_document_t *
diff-tree ac51fff0db73c5917a38af3f610d4751b8fec626 (from 43d35e01106659ac689846a8d5875d235b0d3c9f)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date: Sat Aug 25 20:49:50 2007 +0200
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.
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 35039ad..d8f5064 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -735,14 +735,54 @@ _cairo_meta_surface_replay_internal (cai
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 86c771e..7c8f34b 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -550,3 +550,30 @@ _cairo_path_fixed_device_transform (cair
_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 05d9939..0c5cbbe 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1387,6 +1387,65 @@ _cairo_surface_mask (cairo_surface_t *su
}
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 310fdfd..58f2ea3 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 *su
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,
diff-tree 43d35e01106659ac689846a8d5875d235b0d3c9f (from 3ceaa6e74e4bd3f5935016c3639411b26d7f576f)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date: Sat Jul 28 17:37:24 2007 +0200
[SVG] fix modeline for vim.
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 6be3098..7cf58d2 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -1,4 +1,4 @@
-/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* vim: set sw=4 sts=4: -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
/* cairo - a vector graphics library with display and print output
*
* Copyright © 2004 Red Hat, Inc
More information about the cairo-commit
mailing list