[cairo-commit] cairo/src cairo-svg-surface.c,1.2,1.3

Emmanuel Pacaud commit at pdx.freedesktop.org
Mon Dec 19 13:59:37 PST 2005


Committed by: emmanuel

Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv27212/src

Modified Files:
	cairo-svg-surface.c 
Log Message:
2005-12-19  Emmanuel Pacaud <emmanuel.pacaud at free.fr>

	* configure.in: CAIRO_CAN_TEST_SVG_SURFACE depends on librsvg.
	* src/cairo-svg-surface.c: cairo_svg_surface_t owns a xml node, for
	support of svg_surface_composite.
	(_cairo_svg_surface_create_for_document): init xml_node. All surfaces
	except first one are stored in defs node.
	(emit_composite_image_pattern): returns pattern size, and don't call
	emit_transform if is_pattern == TRUE.
	(emit_composite_svg_pattern): do something.
	(emit_composite_pattern): returns pattern size.
	(_cairo_svg_surface_composite): xml_node is stored in
	cairo_svg_surface_t now.
	(emit_surface_pattern): emit surface pattern width here.
	Fix property names.
	(_cairo_svg_path_close_path): don't close path if no current point.
	(_cairo_svg_surface_fill_rectangles): new.
	(_cairo_svg_surface_fill): emit fill rule. xml_node is in surface now.
	(_cairo_svg_surface_composite_trapezoids): xml_node is in surface now.
	(_cairo_svg_surface_stroke): ditto.
	(_cairo_svg_surface_intersect_clip_path): ditto. Emit fill rule.
	* test/.cvsignore: ignore svg2png.
	* test/Makefile.am: build svg2png utility.
	* test/cairo-test.c (create_svg_surface): new.
	(svg_surface_write_to_png): new.
	(cleanup_svg): new.
	(cairo_test_expecting): test SVG backend if CAIRO_HAS_SVG_SURFACE &&
	CAIRO_CAN_TEST_SVG_SURFACE.
	* test/svg2png.c: new.



Index: cairo-svg-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-svg-surface.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- cairo-svg-surface.c	16 Dec 2005 11:02:35 -0000	1.2
+++ cairo-svg-surface.c	19 Dec 2005 21:59:35 -0000	1.3
@@ -66,8 +66,9 @@
 
     xmlDocPtr	xml_doc;
     xmlNodePtr	xml_node_defs;
-    xmlNodePtr  xml_node;
+    xmlNodePtr  xml_node_main;
 
+    unsigned int surface_id;
     unsigned int linear_pattern_id;
     unsigned int radial_pattern_id;
     unsigned int pattern_id;
@@ -78,11 +79,15 @@
 struct cairo_svg_surface {
     cairo_surface_t base;
 
+    unsigned int id;
+
     double width;
     double height;
 
     cairo_svg_document_t *document;
 
+    xmlNodePtr  xml_node;
+
     cairo_bool_t has_clip;
 };
 
@@ -173,6 +178,7 @@
 					double			height)
 {
     cairo_svg_surface_t *surface;
+    char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
 
     surface = malloc (sizeof (cairo_svg_surface_t));
     if (surface == NULL)
@@ -188,6 +194,15 @@
 
     surface->has_clip = FALSE;
 
+    surface->id = document->surface_id++;
+    if (surface->id == 0)
+	surface->xml_node = document->xml_node_main;
+    else {
+	surface->xml_node = xmlNewChild (document->xml_node_defs, NULL, CC2XML ("g"), NULL);
+	snprintf (buffer, sizeof buffer, "surface%d", surface->id);
+	xmlSetProp (surface->xml_node, CC2XML ("id"), C2XML (buffer));
+    }
+
     return &surface->base;
 }
 
@@ -364,7 +379,10 @@
 
 static cairo_int_status_t
 emit_composite_image_pattern (xmlNodePtr node,
-			      cairo_surface_pattern_t *pattern)
+			      cairo_surface_pattern_t *pattern,
+			      double *width,
+			      double *height,
+			      int is_pattern)
 {
     cairo_surface_t *surface = pattern->surface;
     cairo_image_surface_t *image;
@@ -392,10 +410,16 @@
 		
     xmlBufferFree (image_buffer);
 
-    p2u = pattern->base.matrix;
-    cairo_matrix_invert (&p2u);
+    if (!is_pattern) {
+	p2u = pattern->base.matrix;
+	cairo_matrix_invert (&p2u);
+	emit_transform (child, "transform", &p2u);
+    }
 
-    emit_transform (child, "transform", &p2u);
+    if (width != NULL)
+	    *width = image->width;
+    if (height != NULL)
+	    *height = image->height;
 
     _cairo_surface_release_source_image (pattern->surface, image, image_extra);
 
@@ -404,20 +428,37 @@
 
 static cairo_int_status_t
 emit_composite_svg_pattern (xmlNodePtr node, 
-			    cairo_surface_pattern_t *pattern)
+			    cairo_surface_pattern_t *pattern,
+			    double *width, 
+			    double *height)
 {
-    printf ("TODO: _cairo_svg_surface_composite_svg\r\n");
+    cairo_svg_surface_t *surface = (cairo_svg_surface_t *) pattern->surface;
+    xmlNodePtr child;
+    char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
+    
+    child = xmlNewChild (node, NULL, CC2XML("use"), NULL);
+    snprintf (buffer, sizeof buffer, "#surface%d", surface->id);
+    xmlSetProp (child, CC2XML ("xlink:href"), C2XML (buffer));
+
+    if (width != NULL)
+	    *width = surface->width;
+    if (height != NULL)
+	    *height = surface->height;
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
 emit_composite_pattern (xmlNodePtr node, 
-			cairo_surface_pattern_t *pattern)
+			cairo_surface_pattern_t *pattern,
+			double *width,
+			double *height,
+			int is_pattern)
 {
     if (pattern->surface->backend == &cairo_svg_surface_backend)
-	return emit_composite_svg_pattern (node, pattern);
+	return emit_composite_svg_pattern (node, pattern, width, height);
     else
-	return emit_composite_image_pattern (node, pattern);
+	return emit_composite_image_pattern (node, pattern, width, height, is_pattern);
 }
 
 static cairo_int_status_t
@@ -435,7 +476,6 @@
 			      unsigned int	height)
 {
     cairo_svg_surface_t *dst = abstract_dst;
-    cairo_svg_document_t *document = dst->document;
     cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) src_pattern;
 
     if (mask_pattern)
@@ -444,7 +484,7 @@
     if (src_pattern->type != CAIRO_PATTERN_SURFACE)
 	return CAIRO_STATUS_SUCCESS;
 
-    return emit_composite_pattern (document->xml_node, src);
+    return emit_composite_pattern (dst->xml_node, src, NULL, NULL, FALSE);
 }
 
 static void
@@ -529,6 +569,7 @@
     xmlNodePtr child;
     xmlBufferPtr id;
     cairo_matrix_t p2u;
+    double width, height;
     char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
     
     child = xmlNewChild (document->xml_node_defs, NULL, CC2XML ("pattern"), NULL);
@@ -546,14 +587,19 @@
 
     document->pattern_id++;
 
-    emit_composite_pattern (child, pattern);
+    emit_composite_pattern (child, pattern, &width, &height, TRUE);
+
+    _cairo_dtostr (buffer, sizeof buffer, width);
+    xmlSetProp (child, CC2XML ("width"), C2XML (buffer));
+    _cairo_dtostr (buffer, sizeof buffer, height);
+    xmlSetProp (child, CC2XML ("height"), C2XML (buffer));
 
     p2u = pattern->base.matrix;
     cairo_matrix_invert (&p2u);
 
-    emit_transform (child, "gradientTransform", &p2u);
+    emit_transform (child, "patternTransform", &p2u);
 
-    xmlSetProp (child, CC2XML ("gradientUnits"), CC2XML ("userSpaceOnUse"));
+    xmlSetProp (child, CC2XML ("patternUnits"), CC2XML ("userSpaceOnUse"));
 }
 
 static int
@@ -843,7 +889,8 @@
 {
     svg_path_info_t *info = closure;
 
-    xmlBufferCat (info->path, CC2XML ("Z "));
+    if (info->has_current_point)
+	    xmlBufferCat (info->path, CC2XML ("Z "));
 
     info->has_current_point = FALSE;
 
@@ -851,6 +898,42 @@
 }
 
 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,
@@ -873,6 +956,8 @@
     style = xmlBufferCreate ();
     emit_pattern (surface, source, style, 0);
     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,
@@ -882,8 +967,8 @@
 					  _cairo_svg_path_curve_to,
 					  _cairo_svg_path_close_path,
 					  &info);
-    
-    child = xmlNewChild (document->xml_node, NULL, CC2XML ("path"), NULL);
+
+    child = xmlNewChild (surface->xml_node, NULL, CC2XML ("path"), NULL);
     xmlSetProp (child, CC2XML ("d"), xmlBufferContent (info.path));
     xmlSetProp (child, CC2XML ("style"), xmlBufferContent (style));
 
@@ -917,7 +1002,6 @@
 					 int			 num_traps)
 {
     cairo_svg_surface_t *surface = abstract_dst;
-    cairo_svg_document_t *document = surface->document;
     xmlBufferPtr style, path;
     xmlNodePtr child;
     double left_x1, left_x2, right_x1, right_x2;
@@ -968,7 +1052,7 @@
 	xmlBufferCat (path, CC2XML (" Z"));
     }
 
-    child = xmlNewChild (document->xml_node, NULL, CC2XML ("path"), NULL);
+    child = xmlNewChild (surface->xml_node, NULL, CC2XML ("path"), NULL);
 
     xmlSetProp (child, CC2XML ("d"), xmlBufferContent (path));
     xmlSetProp (child, CC2XML ("style"), xmlBufferContent (style));
@@ -998,6 +1082,40 @@
     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)
+{
+    cairo_svg_surface_t *surface = abstract_surface;
+    xmlNodePtr child;
+    xmlBufferPtr style;
+    char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
+
+    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);
+    xmlSetProp (child, CC2XML ("x"), CC2XML ("0"));
+    xmlSetProp (child, CC2XML ("y"), CC2XML ("0"));
+    _cairo_dtostr (buffer, sizeof buffer, surface->width);
+    xmlSetProp (child, CC2XML ("width"), C2XML (buffer));
+    _cairo_dtostr (buffer, sizeof buffer, surface->height);
+    xmlSetProp (child, CC2XML ("height"), C2XML (buffer));
+    xmlSetProp (child, CC2XML ("style"), xmlBufferContent (style));
+
+    xmlBufferFree (style);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+#endif
+
 static cairo_int_status_t
 _cairo_svg_surface_stroke (void			*abstract_dst,
 			   cairo_operator_t      op,
@@ -1084,7 +1202,7 @@
 					  _cairo_svg_path_close_path,
 					  &info);
     
-    child = xmlNewChild (document->xml_node, NULL, CC2XML ("path"), NULL);
+    child = xmlNewChild (surface->xml_node, NULL, CC2XML ("path"), NULL);
 
     xmlSetProp (child, CC2XML ("d"), xmlBufferContent (info.path));
     xmlSetProp (child, CC2XML ("style"), xmlBufferContent (style));
@@ -1152,7 +1270,7 @@
 
     if (path == NULL) {
 	if (surface->has_clip)
-	    document->xml_node = document->xml_node->parent;
+	    surface->xml_node = surface->xml_node->parent;
 	surface->has_clip = FALSE;
 	return CAIRO_STATUS_SUCCESS;
     }
@@ -1164,7 +1282,7 @@
 	info.has_current_point = FALSE;
 	info.path = xmlBufferCreate ();
 
-	group = xmlNewChild (document->xml_node, NULL, CC2XML ("g"), NULL);
+	group = xmlNewChild (surface->xml_node, NULL, CC2XML ("g"), NULL);
 	clip = xmlNewChild (document->xml_node_defs, NULL, CC2XML ("clipPath"), NULL);
 	clip_path = xmlNewChild (clip, NULL, CC2XML ("path"), NULL);
 	
@@ -1177,7 +1295,7 @@
 					      &info);
 	xmlSetProp (clip_path, CC2XML ("d"), xmlBufferContent (info.path));
 	xmlBufferFree (info.path);
-	
+
 	id = xmlBufferCreate ();
 	xmlBufferCat (id, CC2XML ("clip"));
 	snprintf (buffer, sizeof buffer, "%d", document->clip_id);
@@ -1189,12 +1307,15 @@
 	xmlBufferCat (url, xmlBufferContent (id));
 	xmlBufferCat (url, CC2XML (")"));
 	xmlSetProp (group, CC2XML ("clip-path"), C2XML (xmlBufferContent (url)));
+	xmlSetProp (group, CC2XML ("clip-rule"), 
+		    fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? 
+		    CC2XML ("evenodd") : CC2XML ("nonzero"));
 
 	xmlBufferFree (url);
 	xmlBufferFree (id);
 
 	document->clip_id++;
-	document->xml_node = group;
+	surface->xml_node = group;
     } 
 
     return status;
@@ -1220,7 +1341,7 @@
 	NULL, /* release_dest_image */
 	NULL, /* clone_similar */
 	_cairo_svg_surface_composite,
-	NULL, /* fill_rectangle */
+	_cairo_svg_surface_fill_rectangles, 
 	_cairo_svg_surface_composite_trapezoids,
 	NULL, /* copy_page */
 	NULL, /* show_page */
@@ -1233,7 +1354,7 @@
 	NULL, /* mark dirty rectangle */
 	NULL, /* scaled font fini */
 	NULL, /* scaled glyph fini */
-	NULL, /* paint */
+	NULL, /*_cairo_svg_surface_paint,*/
 	NULL, /* mask */
 	_cairo_svg_surface_stroke,
 	_cairo_svg_surface_fill,
@@ -1263,6 +1384,7 @@
     document->x_dpi = CAIRO_SVG_DEFAULT_DPI;
     document->y_dpi = CAIRO_SVG_DEFAULT_DPI;
 
+    document->surface_id = 0;
     document->linear_pattern_id = 0;
     document->radial_pattern_id = 0;
     document->pattern_id = 0;
@@ -1275,7 +1397,7 @@
     xmlDocSetRootElement (doc, node);
 
     document->xml_doc = doc;
-    document->xml_node = node;
+    document->xml_node_main = node;
     document->xml_node_defs = xmlNewChild (node, NULL, CC2XML ("defs"), NULL); 
 
     _cairo_dtostr (buffer, sizeof buffer, width);



More information about the cairo-commit mailing list