[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