mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-01 10:18:09 +02:00
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.
This commit is contained in:
parent
9e2a2ea0da
commit
170a028bfa
1 changed files with 44 additions and 5 deletions
|
|
@ -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 {
|
||||
|
|
@ -331,6 +333,29 @@ _cairo_svg_surface_finish (void *abstract_surface)
|
|||
return status;
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
@ -528,8 +553,13 @@ emit_composite_svg_pattern (xmlNodePtr node,
|
|||
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 *abstract_surface,
|
|||
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_stream_t *output_stream,
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue