[cairo-commit] cairo/src cairo-svg-surface.c,1.9,1.10
Emmanuel Pacaud
commit at pdx.freedesktop.org
Mon Feb 13 12:41:12 PST 2006
Committed by: emmanuel
Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv14489/src
Modified Files:
cairo-svg-surface.c
Log Message:
2006-02-13 Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Add mask support and switch to SVG 1.2 for compositing operators.
* src/cairo-svg-surface.c (emit_composite_image_pattern): return xml
node instead of cairo status.
(emit_composite_svg_pattern): ditto.
(emit_composite_pattern): ditto.
(emit_operator): use SVG 1.2 operators, since feComposite filter
always composite resulting surface to current canvas.
(_cairo_svg_surface_composite): removed.
(_cairo_svg_surface_fill_rectangles): removed.
(intersect): removed.
(_cairo_svg_surface_composite_trapezoids): removed.
(emit_paint): new.
(_cairo_svg_surface_paint): new.
(_cairo_svg_surface_mask): new.
(_cairo_svg_surface_stroke): emit operator.
Index: cairo-svg-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-svg-surface.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- cairo-svg-surface.c 29 Jan 2006 21:25:10 -0000 1.9
+++ cairo-svg-surface.c 13 Feb 2006 20:41:10 -0000 1.10
@@ -74,6 +74,7 @@
unsigned int pattern_id;
unsigned int filter_id;
unsigned int clip_id;
+ unsigned int mask_id;
};
struct cairo_svg_surface {
@@ -392,7 +393,7 @@
return CAIRO_STATUS_SUCCESS;
}
-static cairo_int_status_t
+static xmlNodePtr
emit_composite_image_pattern (xmlNodePtr node,
cairo_surface_pattern_t *pattern,
double *width,
@@ -410,11 +411,11 @@
status = _cairo_surface_acquire_source_image (surface, &image, &image_extra);
if (status)
- return status;
+ return NULL;
status = _cairo_surface_base64_encode (surface, &image_buffer);
if (status)
- return status;
+ return NULL;
child = xmlNewChild (node, NULL, CC2XML ("image"), NULL);
_cairo_dtostr (buffer, sizeof buffer, image->width);
@@ -438,10 +439,10 @@
_cairo_surface_release_source_image (pattern->surface, image, image_extra);
- return status;
+ return child;
}
-static cairo_int_status_t
+static xmlNodePtr
emit_composite_svg_pattern (xmlNodePtr node,
cairo_surface_pattern_t *pattern,
double *width,
@@ -455,7 +456,7 @@
/* FIXME: self copy is not supported yet */
if (surface->id == 0)
- return CAIRO_STATUS_SUCCESS;
+ return NULL;
child = xmlNewChild (node, NULL, CC2XML("use"), NULL);
snprintf (buffer, sizeof buffer, "#surface%d", surface->id);
@@ -472,10 +473,10 @@
if (height != NULL)
*height = surface->height;
- return CAIRO_STATUS_SUCCESS;
+ return child;
}
-static cairo_int_status_t
+static xmlNodePtr
emit_composite_pattern (xmlNodePtr node,
cairo_surface_pattern_t *pattern,
double *width,
@@ -488,69 +489,27 @@
return emit_composite_image_pattern (node, pattern, width, height, is_pattern);
}
-static cairo_int_status_t
-_cairo_svg_surface_composite (cairo_operator_t op,
- cairo_pattern_t *src_pattern,
- cairo_pattern_t *mask_pattern,
- void *abstract_dst,
- int src_x,
- int src_y,
- int mask_x,
- int mask_y,
- int dst_x,
- int dst_y,
- unsigned int width,
- unsigned int height)
-{
- cairo_svg_surface_t *dst = abstract_dst;
- cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) src_pattern;
-
- if (mask_pattern)
- return CAIRO_STATUS_SUCCESS;
-
- if (src_pattern->type != CAIRO_PATTERN_SURFACE)
- return CAIRO_STATUS_SUCCESS;
-
- return emit_composite_pattern (dst->xml_node, src, NULL, NULL, FALSE);
-}
+/* FIXME: Here we use a SVG 1.2 feature. We should probably have
+ * an API to limit output SVG version, and fallback to image when
+ * necessary. */
static void
-emit_operator (cairo_operator_t op, cairo_svg_surface_t *surface,
- xmlBufferPtr style)
+emit_operator (xmlNodePtr node, cairo_operator_t op)
{
char const *op_str[] = {
- NULL,
- NULL, NULL, "in", "out", "atop",
- NULL, NULL, NULL, NULL, NULL,
- "xor", NULL, NULL };
-
- cairo_svg_document_t *document = surface->document;
- xmlNodePtr child, primitive;
- xmlBufferPtr id;
- char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
-
- if (op_str[op] == NULL)
- return;
-
- child = xmlNewChild (document->xml_node_defs, NULL, CC2XML ("filter"), NULL);
- primitive = xmlNewChild (child, NULL, CC2XML ("feComposite"), NULL);
- xmlSetProp (primitive, CC2XML ("operator"), CC2XML (op_str[op]));
- xmlSetProp (primitive, CC2XML ("in"), CC2XML ("SourceGraphic"));
- xmlSetProp (primitive, CC2XML ("in2"), CC2XML ("BackgroundImage"));
-
- id = xmlBufferCreate ();
- xmlBufferCat (id, CC2XML ("filter"));
- snprintf (buffer, sizeof buffer, "%d", document->filter_id);
- xmlBufferCat (id, C2XML (buffer));
- xmlSetProp (child, CC2XML ("id"), C2XML (xmlBufferContent (id)));
-
- xmlBufferCat (style, CC2XML ("filter: url(#"));
- xmlBufferCat (style, xmlBufferContent (id));
- xmlBufferCat (style, CC2XML (");"));
+ "clear",
+
+ "src", "src-over", "src-in",
+ "src-out", "src-atop",
+
+ "dst", "dst-over", "dst-in",
+ "dst-out", "dst-atop",
+
+ "xor", "plus",
+ "color-dodge" /* FIXME: saturate ? */
+ };
- xmlBufferFree (id);
-
- document->filter_id++;
+ xmlSetProp (node, CC2XML ("comp-op"), C2XML (op_str[op]));
}
static void
@@ -828,7 +787,7 @@
xmlBufferPtr path;
} svg_path_info_t;
- static cairo_status_t
+static cairo_status_t
_cairo_svg_path_move_to (void *closure, cairo_point_t *point)
{
svg_path_info_t *info = closure;
@@ -918,42 +877,6 @@
}
static cairo_int_status_t
-_cairo_svg_surface_fill_rectangles (void *abstract_surface,
- cairo_operator_t op,
- const cairo_color_t *color,
- cairo_rectangle_t *rects,
- int num_rects)
-{
- cairo_svg_surface_t *surface = abstract_surface;
- xmlNodePtr child;
- xmlBufferPtr style;
- char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
- int i;
-
- style = xmlBufferCreate ();
- emit_color (color, style, "fill", "opacity");
- xmlBufferCat (style, " stroke: none;");
- emit_operator (op, surface, style);
-
- for (i = 0; i < num_rects; i++) {
- child = xmlNewChild (surface->xml_node, NULL, CC2XML ("rect"), NULL);
- _cairo_dtostr (buffer, sizeof buffer, rects[i].x);
- xmlSetProp (child, CC2XML ("x"), C2XML (buffer));
- _cairo_dtostr (buffer, sizeof buffer, rects[i].y);
- xmlSetProp (child, CC2XML ("y"), C2XML (buffer));
- _cairo_dtostr (buffer, sizeof buffer, rects[i].width);
- xmlSetProp (child, CC2XML ("width"), C2XML (buffer));
- _cairo_dtostr (buffer, sizeof buffer, rects[i].height);
- xmlSetProp (child, CC2XML ("height"), C2XML (buffer));
- xmlSetProp (child, CC2XML ("style"), xmlBufferContent (style));
- }
-
- xmlBufferFree (style);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
_cairo_svg_surface_fill (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
@@ -978,7 +901,6 @@
xmlBufferCat (style, " stroke: none;");
xmlBufferCat (style, " fill-rule: ");
xmlBufferCat (style, fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? "evenodd;" : "nonzero;");
- emit_operator (op, surface, style);
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
@@ -991,6 +913,7 @@
child = xmlNewChild (surface->xml_node, NULL, CC2XML ("path"), NULL);
xmlSetProp (child, CC2XML ("d"), xmlBufferContent (info.path));
xmlSetProp (child, CC2XML ("style"), xmlBufferContent (style));
+ emit_operator (child, op);
xmlBufferFree (info.path);
xmlBufferFree (style);
@@ -998,91 +921,6 @@
return status;
}
-static double
-intersect (cairo_line_t *line, cairo_fixed_t y)
-{
- return _cairo_fixed_to_double (line->p1.x) +
- _cairo_fixed_to_double (line->p2.x - line->p1.x) *
- _cairo_fixed_to_double (y - line->p1.y) /
- _cairo_fixed_to_double (line->p2.y - line->p1.y);
-}
-
-static cairo_int_status_t
-_cairo_svg_surface_composite_trapezoids (cairo_operator_t op,
- cairo_pattern_t *pattern,
- void *abstract_dst,
- cairo_antialias_t antialias,
- int x_src,
- int y_src,
- int x_dst,
- int y_dst,
- unsigned int width,
- unsigned int height,
- cairo_trapezoid_t *traps,
- int num_traps)
-{
- cairo_svg_surface_t *surface = abstract_dst;
- xmlBufferPtr style, path;
- xmlNodePtr child;
- double left_x1, left_x2, right_x1, right_x2;
- char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
- int i;
-
- style = xmlBufferCreate ();
- emit_pattern (surface, pattern, style, 0);
- xmlBufferCat (style, "stroke: none;");
-
- path = xmlBufferCreate ();
-
- for (i = 0; i < num_traps; i++) {
-
- left_x1 = intersect (&traps[i].left, traps[i].top);
- left_x2 = intersect (&traps[i].left, traps[i].bottom);
- right_x1 = intersect (&traps[i].right, traps[i].top);
- right_x2 = intersect (&traps[i].right, traps[i].bottom);
-
- xmlBufferCat (path, CC2XML ("M "));
- _cairo_dtostr (buffer, sizeof buffer, left_x1);
- xmlBufferCat (path, CC2XML (buffer));
- xmlBufferCat (path, CC2XML (" "));
- _cairo_dtostr (buffer, sizeof buffer,
- _cairo_fixed_to_double (traps[i].top));
- xmlBufferCat (path, CC2XML (buffer));
- xmlBufferCat (path, CC2XML (" L "));
- _cairo_dtostr (buffer, sizeof buffer, left_x2);
- xmlBufferCat (path, CC2XML (buffer));
- xmlBufferCat (path, CC2XML (" "));
- _cairo_dtostr (buffer, sizeof buffer,
- _cairo_fixed_to_double (traps[i].bottom));
- xmlBufferCat (path, CC2XML (buffer));
- xmlBufferCat (path, CC2XML (" L "));
- _cairo_dtostr (buffer, sizeof buffer, right_x2);
- xmlBufferCat (path, CC2XML (buffer));
- xmlBufferCat (path, CC2XML (" "));
- _cairo_dtostr (buffer, sizeof buffer,
- _cairo_fixed_to_double (traps[i].bottom));
- xmlBufferCat (path, CC2XML (buffer));
- xmlBufferCat (path, CC2XML (" L "));
- _cairo_dtostr (buffer, sizeof buffer, right_x1);
- xmlBufferCat (path, CC2XML (buffer));
- xmlBufferCat (path, CC2XML (" "));
- _cairo_dtostr (buffer, sizeof buffer,
- _cairo_fixed_to_double (traps[i].top));
- xmlBufferCat (path, CC2XML (buffer));
- xmlBufferCat (path, CC2XML (" Z"));
- }
-
- child = xmlNewChild (surface->xml_node, NULL, CC2XML ("path"), NULL);
-
- xmlSetProp (child, CC2XML ("d"), xmlBufferContent (path));
- xmlSetProp (child, CC2XML ("style"), xmlBufferContent (style));
-
- xmlBufferFree (path);
- xmlBufferFree (style);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
static cairo_int_status_t
_cairo_svg_surface_get_extents (void *abstract_surface,
cairo_rectangle_t *rectangle)
@@ -1102,26 +940,26 @@
return CAIRO_STATUS_SUCCESS;
}
- /* First attempt of paint implementation, but obviously I didn't
- * understand how it's supposed to work */
-
-#if 0
-static cairo_int_status_t
-_cairo_svg_surface_paint (void *abstract_surface,
- cairo_operator_t op,
- cairo_pattern_t *source)
+static xmlNodePtr
+emit_paint (xmlNodePtr node,
+ cairo_svg_surface_t *surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source)
{
- cairo_svg_surface_t *surface = abstract_surface;
xmlNodePtr child;
xmlBufferPtr style;
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
+ if (source->type == CAIRO_PATTERN_SURFACE)
+ return emit_composite_pattern (node,
+ (cairo_surface_pattern_t *) source,
+ NULL, NULL, FALSE);
+
style = xmlBufferCreate ();
emit_pattern (surface, source, style, 0);
xmlBufferCat (style, " stroke: none;");
- emit_operator (op, surface, style);
- child = xmlNewChild (surface->xml_node, NULL, CC2XML ("rect"), NULL);
+ child = xmlNewChild (node, NULL, CC2XML ("rect"), NULL);
xmlSetProp (child, CC2XML ("x"), CC2XML ("0"));
xmlSetProp (child, CC2XML ("y"), CC2XML ("0"));
_cairo_dtostr (buffer, sizeof buffer, surface->width);
@@ -1129,12 +967,51 @@
_cairo_dtostr (buffer, sizeof buffer, surface->height);
xmlSetProp (child, CC2XML ("height"), C2XML (buffer));
xmlSetProp (child, CC2XML ("style"), xmlBufferContent (style));
+ emit_operator (child, op);
xmlBufferFree (style);
+ return child;
+}
+
+static cairo_int_status_t
+_cairo_svg_surface_paint (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source)
+{
+ cairo_svg_surface_t *surface = abstract_surface;
+
+ emit_paint (surface->xml_node, surface, op, source);
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_int_status_t
+_cairo_svg_surface_mask (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_pattern_t *mask)
+{
+ cairo_svg_surface_t *surface = abstract_surface;
+ cairo_svg_document_t *document = surface->document;
+ xmlNodePtr child, mask_node;
+ char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
+
+ mask_node = xmlNewChild (document->xml_node_defs, NULL, CC2XML ("mask"), NULL);
+ snprintf (buffer, sizeof buffer, "mask%d", document->mask_id);
+ xmlSetProp (mask_node, CC2XML ("id"), C2XML (buffer));
+ emit_paint (mask_node, surface, op, mask);
+
+ child = emit_paint (surface->xml_node, surface, op, source);
+
+ if (child) {
+ snprintf (buffer, sizeof buffer, "url(#mask%d)", document->mask_id);
+ xmlSetProp (child, CC2XML ("mask"), C2XML (buffer));
+ }
+
+ document->mask_id++;
+
return CAIRO_STATUS_SUCCESS;
}
-#endif
static cairo_int_status_t
_cairo_svg_surface_stroke (void *abstract_dst,
@@ -1231,9 +1108,9 @@
&info);
child = xmlNewChild (surface->xml_node, NULL, CC2XML ("path"), NULL);
-
xmlSetProp (child, CC2XML ("d"), xmlBufferContent (info.path));
xmlSetProp (child, CC2XML ("style"), xmlBufferContent (style));
+ emit_operator (child, op);
xmlBufferFree (info.path);
xmlBufferFree (style);
@@ -1357,9 +1234,9 @@
NULL, /* acquire_dest_image */
NULL, /* release_dest_image */
NULL, /* clone_similar */
- _cairo_svg_surface_composite,
- _cairo_svg_surface_fill_rectangles,
- _cairo_svg_surface_composite_trapezoids,
+ NULL, /* _cairo_svg_surface_composite, */
+ NULL, /* _cairo_svg_surface_fill_rectangles, */
+ NULL, /* _cairo_svg_surface_composite_trapezoids,*/
NULL, /* copy_page */
NULL, /* show_page */
NULL, /* set_clip_region */
@@ -1371,8 +1248,8 @@
NULL, /* mark dirty rectangle */
NULL, /* scaled font fini */
NULL, /* scaled glyph fini */
- NULL, /*_cairo_svg_surface_paint,*/
- NULL, /* mask */
+ _cairo_svg_surface_paint,
+ _cairo_svg_surface_mask,
_cairo_svg_surface_stroke,
_cairo_svg_surface_fill,
NULL /* show_glyphs */
@@ -1407,6 +1284,7 @@
document->pattern_id = 0;
document->filter_id = 0;
document->clip_id = 0;
+ document->mask_id = 0;
doc = xmlNewDoc (CC2XML ("1.0"));
node = xmlNewNode (NULL, CC2XML ("svg"));
@@ -1423,7 +1301,7 @@
xmlSetProp (node, CC2XML ("height"), CC2XML (buffer));
xmlSetProp (node, CC2XML ("xmlns"), CC2XML ("http://www.w3.org/2000/svg"));
xmlSetProp (node, CC2XML ("xmlns:xlink"), CC2XML ("http://www.w3.org/1999/xlink"));
- xmlSetProp (node, CC2XML ("version"), CC2XML ("1.1"));
+ xmlSetProp (node, CC2XML ("version"), CC2XML ("1.2"));
return document;
}
More information about the cairo-commit
mailing list