[cairo-commit] src/cairo-svg-surface.c

Emmanuel Pacaud emmanuel at kemper.freedesktop.org
Mon Apr 17 14:30:10 PDT 2006


 src/cairo-svg-surface.c |   49 +++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 44 insertions(+), 5 deletions(-)

New commits:
diff-tree 170a028bfa00286324d8598d831e570d868a26f1 (from 9e2a2ea0da93065c46a6d6249f98a319ee6158dd)
Author: Emmanuel Pacaud <emmanuel.pacaud at free.fr>
Date:   Mon Apr 17 23:26:30 2006 +0200

    SVG: Fix mask and try to support CAIRO_CONTENT_ALPHA.
    
    Cairo and SVG differ in their implementation of mask. Cairo only uses alpha channel where SVG uses all channels. So, before using a surface for masking, we use a filter that sets RGB channels to 1.0.
    
    Support for CAIRO_CONTENT_ALPHA is similar and use the same filter when a SVG alpha surface is composited.

diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index da38a1e..447abf8 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -75,6 +75,8 @@ struct cairo_svg_document {
     unsigned int filter_id;
     unsigned int clip_id;
     unsigned int mask_id;
+
+    cairo_bool_t alpha_filter;
 };
 
 struct cairo_svg_surface {
@@ -332,6 +334,29 @@ _cairo_svg_surface_finish (void *abstrac
 }
 
 static void
+emit_alpha_filter (cairo_svg_document_t *document)
+{
+    if (!document->alpha_filter) {
+	xmlNodePtr node;
+	xmlNodePtr child;
+
+	node = xmlNewChild (document->xml_node_defs, NULL,
+			    CC2XML ("filter"), NULL);
+	xmlSetProp (node, CC2XML ("id"), CC2XML ("alpha"));
+	xmlSetProp (node, CC2XML ("filterUnits"), CC2XML ("objectBoundingBox"));
+	xmlSetProp (node, CC2XML ("x"), CC2XML ("0%"));
+	xmlSetProp (node, CC2XML ("y"), CC2XML ("0%"));
+	xmlSetProp (node, CC2XML ("width"), CC2XML ("100%"));
+	xmlSetProp (node, CC2XML ("height"), CC2XML ("100%"));
+	child = xmlNewChild (node, NULL, CC2XML ("feColorMatrix"), NULL);
+	xmlSetProp (child, CC2XML("type"), CC2XML ("matrix"));
+	xmlSetProp (child, CC2XML("in"), CC2XML ("SourceGraphic"));
+	xmlSetProp (child, CC2XML("values"), CC2XML ("0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0")); 
+	document->alpha_filter = TRUE;
+    }
+}
+
+static void
 emit_transform (xmlNodePtr node, 
 		char const *attribute_str, 
 		cairo_matrix_t *matrix)
@@ -528,8 +553,13 @@ emit_composite_svg_pattern (xmlNodePtr n
     xmlNodePtr child;
     char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
 
-    if (surface->modified)
-	    xmlAddChild (document->xml_node_defs, xmlCopyNode (surface->xml_root_node, 1));
+    if (surface->modified) {
+	    if (surface->content == CAIRO_CONTENT_ALPHA) 
+		emit_alpha_filter (document);
+	    child = xmlAddChild (document->xml_node_defs, xmlCopyNode (surface->xml_root_node, 1));
+	    if (surface->content == CAIRO_CONTENT_ALPHA) 
+		    xmlSetProp (child, CC2XML ("filter"), CC2XML("url(#alpha)"));
+    }
     
     child = xmlNewChild (node, NULL, CC2XML("use"), NULL);
     snprintf (buffer, sizeof buffer, "#surface%d", 
@@ -1033,7 +1063,8 @@ emit_paint (xmlNodePtr node,
     xmlBufferPtr style;
     char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
 
-    if (source->type == CAIRO_PATTERN_TYPE_SURFACE)
+    if (source->type == CAIRO_PATTERN_TYPE_SURFACE && 
+	source->extend == CAIRO_EXTEND_NONE)
 	return emit_composite_pattern (node, 
 				       (cairo_surface_pattern_t *) source, 
 				       NULL, NULL, FALSE);
@@ -1112,10 +1143,16 @@ _cairo_svg_surface_mask (void		    *abst
     xmlNodePtr child, mask_node;
     char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
 
-    mask_node = xmlNewChild (document->xml_node_defs, NULL, CC2XML ("mask"), NULL);
+    emit_alpha_filter (document);
+
+    mask_node = xmlNewNode (NULL, CC2XML ("mask"));
     snprintf (buffer, sizeof buffer, "mask%d", document->mask_id);
     xmlSetProp (mask_node, CC2XML ("id"), C2XML (buffer));
-    emit_paint (mask_node, surface, op, mask);
+    child = xmlNewChild (mask_node, NULL, CC2XML ("g"), NULL);
+    xmlSetProp (child, CC2XML ("filter"), CC2XML ("url(#alpha)"));
+    emit_paint (child, surface, op, mask);
+
+    xmlAddChild (document->xml_node_defs, mask_node);
 
     child = emit_paint (surface->xml_node, surface, op, source);
 
@@ -1416,6 +1453,8 @@ _cairo_svg_document_create (cairo_output
     xmlSetProp (node, CC2XML ("xmlns:xlink"), CC2XML ("http://www.w3.org/1999/xlink"));
     xmlSetProp (node, CC2XML ("version"), CC2XML ("1.2"));
 
+    document->alpha_filter = FALSE;
+
     return document;
 }
 


More information about the cairo-commit mailing list