diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index e8567bcb5..889086510 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -366,8 +366,8 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document, if (content == CAIRO_CONTENT_COLOR) { _cairo_output_stream_printf (surface->xml_node, "\n", + "style=\"opacity:1;stroke:none;" + "fill:rgb(0,0,0);\"/>\n", width, height); status = _cairo_output_stream_get_status (surface->xml_node); if (status) @@ -631,7 +631,7 @@ _cairo_svg_document_emit_outline_glyph_data (cairo_svg_document_t *document, return status; _cairo_output_stream_printf (document->xml_node_glyphs, - "xml_node_glyphs, scaled_glyph->path, NULL); if (status) @@ -706,8 +706,8 @@ _cairo_svg_document_emit_glyph (cairo_svg_document_t *document, _cairo_output_stream_printf (document->xml_node_glyphs, "\n", - font_id, - subset_glyph_index); + font_id, + subset_glyph_index); status = _cairo_svg_document_emit_outline_glyph_data (document, scaled_font, @@ -967,9 +967,52 @@ _cairo_surface_base64_encode (cairo_surface_t *surface, return status; } +static struct { + char const *str; + cairo_bool_t clip_to_self; +} _cairo_svg_surface_operators[] = { + {"clear", TRUE}, + + {"src", TRUE}, {"src-over", FALSE}, {"src-in", FALSE}, + {"src-out", FALSE}, {"src-atop", FALSE}, + + {"dst", FALSE}, {"dst-over", FALSE}, {"dst-in", FALSE}, + {"dst-out", FALSE}, {"dst-atop", FALSE}, + + {"xor", FALSE}, {"plus", FALSE}, + {"color-dodge", FALSE} /* FIXME: saturate ? */ +}; + +static void +_cairo_svg_surface_emit_operator (cairo_output_stream_t *output, + cairo_svg_surface_t *surface, + cairo_operator_t op) +{ + if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2 && + op != CAIRO_OPERATOR_OVER) { + _cairo_output_stream_printf (output, " comp-op=\"%s\"", _cairo_svg_surface_operators[op].str); + if (_cairo_svg_surface_operators[op].clip_to_self) + _cairo_output_stream_printf (output, " clip-to-self=\"true\""); + } +} + +static void +_cairo_svg_surface_emit_operator_for_style (cairo_output_stream_t *output, + cairo_svg_surface_t *surface, + cairo_operator_t op) +{ + if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2 && + op != CAIRO_OPERATOR_OVER) { + _cairo_output_stream_printf (output, "comp-op:%s;", _cairo_svg_surface_operators[op].str); + if (_cairo_svg_surface_operators[op].clip_to_self) + _cairo_output_stream_printf (output, "clip-to-self:true;"); + } +} + static cairo_status_t _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output, cairo_svg_surface_t *svg_surface, + cairo_operator_t op, cairo_surface_pattern_t *pattern, int pattern_id, const cairo_matrix_t *parent_matrix, @@ -1012,8 +1055,10 @@ _cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output " surface)) { - return _cairo_svg_surface_emit_composite_meta_pattern (output, surface, pattern, + return _cairo_svg_surface_emit_composite_meta_pattern (output, surface, op, pattern, pattern_id, parent_matrix, extra_attributes); } - return _cairo_svg_surface_emit_composite_image_pattern (output, surface, pattern, + return _cairo_svg_surface_emit_composite_image_pattern (output, surface, op, pattern, pattern_id, parent_matrix, extra_attributes); } -static void -_cairo_svg_surface_emit_operator (cairo_output_stream_t *output, - cairo_svg_surface_t *surface, - cairo_operator_t op) -{ - char const *op_str[] = { - "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 ? */ - }; - - if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2) - _cairo_output_stream_printf (output, "comp-op: %s; ", op_str[op]); -} - static cairo_status_t _cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface, cairo_solid_pattern_t *pattern, @@ -1265,8 +1292,8 @@ _cairo_svg_surface_emit_solid_pattern (cairo_svg_surface_t *surface, cairo_bool_t is_stroke) { _cairo_output_stream_printf (style, is_stroke ? - "stroke: rgb(%f%%,%f%%,%f%%); stroke-opacity: %f;": - "fill: rgb(%f%%,%f%%,%f%%); fill-opacity: %f;", + "stroke:rgb(%f%%,%f%%,%f%%);stroke-opacity:%f;": + "fill:rgb(%f%%,%f%%,%f%%);fill-opacity:%f;", pattern->color.red * 100.0, pattern->color.green * 100.0, pattern->color.blue * 100.0, @@ -1288,13 +1315,13 @@ _cairo_svg_surface_emit_surface_pattern (cairo_svg_surface_t *surface, pattern_id = document->pattern_id++; status = _cairo_svg_surface_emit_composite_pattern (document->xml_node_defs, - surface, pattern, + surface, CAIRO_OPERATOR_SOURCE, pattern, pattern_id, parent_matrix, NULL); if (status) return status; _cairo_output_stream_printf (style, - "%s: url(#pattern%d);", + "%s:url(#pattern%d);", is_stroke ? "stroke" : "fill", pattern_id); @@ -1319,8 +1346,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, if (pattern->n_stops == 1) { _cairo_output_stream_printf (output, "\n", + "stop-color:rgb(%f%%,%f%%,%f%%);" + "stop-opacity:%f;\"/>\n", pattern->stops[0].offset, pattern->stops[0].color.red * 100.0, pattern->stops[0].color.green * 100.0, @@ -1366,8 +1393,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, offset = start_offset + (1 - start_offset ) * stops[i].offset; _cairo_output_stream_printf (output, "\n", + "stop-color:rgb(%f%%,%f%%,%f%%);" + "stop-opacity:%f;\"/>\n", offset, stops[i].color.red * 100.0, stops[i].color.green * 100.0, @@ -1418,8 +1445,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, _cairo_output_stream_printf (output, "\n", + "stop-color:rgb(%f%%,%f%%,%f%%);" + "stop-opacity:%f;\"/>\n", offset_color_start.red * 100.0, offset_color_start.green * 100.0, offset_color_start.blue * 100.0, @@ -1427,8 +1454,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, for (i = offset_index; i < n_stops; i++) { _cairo_output_stream_printf (output, "\n", + "stop-color:rgb(%f%%,%f%%,%f%%);" + "stop-opacity:%f;\"/>\n", stops[i].offset + start_offset, stops[i].color.red * 100.0, stops[i].color.green * 100.0, @@ -1438,8 +1465,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, for (i = 0; i < offset_index; i++) { _cairo_output_stream_printf (output, "\n", + "stop-color:rgb(%f%%,%f%%,%f%%);" + "stop-opacity:%f;\"/>\n", 1.0 + stops[i].offset + start_offset, stops[i].color.red * 100.0, stops[i].color.green * 100.0, @@ -1449,8 +1476,8 @@ _cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output, _cairo_output_stream_printf (output, "\n", + "stop-color:rgb(%f%%,%f%%,%f%%);" + "stop-opacity:%f;\"/>\n", offset_color_stop.red * 100.0, offset_color_stop.green * 100.0, offset_color_stop.blue * 100.0, @@ -1524,7 +1551,7 @@ _cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface, "\n"); _cairo_output_stream_printf (style, - "%s: url(#linear%d);", + "%s:url(#linear%d);", is_stroke ? "stroke" : "fill", document->linear_pattern_id); @@ -1595,13 +1622,13 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface, if (extend == CAIRO_EXTEND_NONE || n_stops < 1) _cairo_output_stream_printf (document->xml_node_defs, "\n"); + "stop-color:rgb(0%%,0%%,0%%);" + "stop-opacity:0;\"/>\n"); else { _cairo_output_stream_printf (document->xml_node_defs, "\n", + "stop-color:rgb(%f%%,%f%%,%f%%);" + "stop-opacity %f;\"/>\n", pattern->base.stops[0].color.red * 100.0, pattern->base.stops[0].color.green * 100.0, pattern->base.stops[0].color.blue * 100.0, @@ -1609,8 +1636,8 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface, if (n_stops > 1) _cairo_output_stream_printf (document->xml_node_defs, "\n", + "stop-color:rgb(%f%%,%f%%,%f%%);" + "stop-opacity:%f;\"/>\n", pattern->base.stops[n_stops - 1].color.red * 100.0, pattern->base.stops[n_stops - 1].color.green * 100.0, pattern->base.stops[n_stops - 1].color.blue * 100.0, @@ -1682,13 +1709,13 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface, if (extend == CAIRO_EXTEND_NONE) { _cairo_output_stream_printf (document->xml_node_defs, "\n"); + "stop-color:rgb(0%%,0%%,0%%);" + "stop-opacity:0;\"/>\n"); if (r0 != 0.0) _cairo_output_stream_printf (document->xml_node_defs, "\n", + "stop-color:rgb(0%%,0%%,0%%);" + "stop-opacity:0;\"/>\n", r0 / r1); } status = _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs, @@ -1701,15 +1728,15 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface, if (pattern->base.base.extend == CAIRO_EXTEND_NONE) _cairo_output_stream_printf (document->xml_node_defs, "\n"); + "stop-color:rgb(0%%,0%%,0%%);" + "stop-opacity:0;\"/>\n"); } _cairo_output_stream_printf (document->xml_node_defs, "\n"); _cairo_output_stream_printf (style, - "%s: url(#radial%d);", + "%s:url(#radial%d);", is_stroke ? "stroke" : "fill", document->radial_pattern_id); @@ -1754,10 +1781,10 @@ _cairo_svg_surface_emit_fill_style (cairo_output_stream_t *output, cairo_matrix_t *parent_matrix) { _cairo_output_stream_printf (output, - "fill-rule: %s; ", + "fill-rule:%s;", fill_rule == CAIRO_FILL_RULE_EVEN_ODD ? "evenodd" : "nonzero"); - _cairo_svg_surface_emit_operator (output, surface, op); + _cairo_svg_surface_emit_operator_for_style (output, surface, op); return _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, parent_matrix); } @@ -1802,9 +1829,9 @@ _cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output, } _cairo_output_stream_printf (output, - "stroke-width: %f; " - "stroke-linecap: %s; " - "stroke-linejoin: %s; ", + "stroke-width:%f;" + "stroke-linecap:%s;" + "stroke-linejoin:%s;", stroke_style->line_width, line_cap, line_join); @@ -1813,27 +1840,27 @@ _cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output, if (status) return status; - _cairo_svg_surface_emit_operator (output, surface, op); + _cairo_svg_surface_emit_operator_for_style (output, surface, op); if (stroke_style->num_dashes > 0) { - _cairo_output_stream_printf (output, "stroke-dasharray: "); + _cairo_output_stream_printf (output, "stroke-dasharray:"); for (i = 0; i < stroke_style->num_dashes; i++) { _cairo_output_stream_printf (output, "%f", stroke_style->dash[i]); if (i + 1 < stroke_style->num_dashes) _cairo_output_stream_printf (output, ","); else - _cairo_output_stream_printf (output, "; "); + _cairo_output_stream_printf (output, ";"); } if (stroke_style->dash_offset != 0.0) { _cairo_output_stream_printf (output, - "stroke-dashoffset: %f; ", + "stroke-dashoffset:%f;", stroke_style->dash_offset); } } _cairo_output_stream_printf (output, - "stroke-miterlimit: %f; ", + "stroke-miterlimit:%f;", stroke_style->miter_limit); return CAIRO_STATUS_SUCCESS; @@ -1946,23 +1973,24 @@ _cairo_svg_surface_emit_paint (cairo_output_stream_t *output, if (source->type == CAIRO_PATTERN_TYPE_SURFACE && source->extend == CAIRO_EXTEND_NONE) return _cairo_svg_surface_emit_composite_pattern (output, - surface, - (cairo_surface_pattern_t *) source, - invalid_pattern_id, - mask_source ? &mask_source->matrix :NULL, - extra_attributes); + surface, + op, + (cairo_surface_pattern_t *) source, + invalid_pattern_id, + mask_source ? &mask_source->matrix :NULL, + extra_attributes); _cairo_output_stream_printf (output, "width, surface->height); - _cairo_svg_surface_emit_operator (output, surface, op); + _cairo_svg_surface_emit_operator_for_style (output, surface, op); status = _cairo_svg_surface_emit_pattern (surface, source, output, FALSE, NULL); if (status) return status; - _cairo_output_stream_printf (output, " stroke: none;\""); + _cairo_output_stream_printf (output, "stroke:none;\""); if (extra_attributes) _cairo_output_stream_printf (output, " %s", extra_attributes); @@ -2023,9 +2051,9 @@ _cairo_svg_surface_paint (void *abstract_surface, _cairo_output_stream_printf (surface->xml_node, "\n", + "style=\"opacity:1;" + "stroke:none;" + "fill:rgb(0,0,0);\"/>\n", surface->width, surface->height); } return CAIRO_STATUS_SUCCESS; @@ -2078,7 +2106,7 @@ _cairo_svg_surface_mask (void *abstract_surface, "%s", mask_id, discard_filter ? "" : " \n"); - status = _cairo_svg_surface_emit_paint (mask_stream, surface, op, mask, source, NULL); + status = _cairo_svg_surface_emit_paint (mask_stream, surface, CAIRO_OPERATOR_OVER, mask, source, NULL); if (status) { cairo_status_t ignore = _cairo_output_stream_destroy (mask_stream); return status; @@ -2123,7 +2151,7 @@ _cairo_svg_surface_stroke (void *abstract_dst, assert (_cairo_svg_surface_operation_supported (surface, op, source)); - _cairo_output_stream_printf (surface->xml_node, "xml_node, "xml_node, surface, op, source, stroke_style, ctm_inverse); if (status) @@ -2177,6 +2205,8 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface, if (status) return status; + _cairo_svg_surface_emit_operator_for_style (surface->xml_node, surface, op); + _cairo_output_stream_printf (surface->xml_node, "\">\n"); for (i = 0; i < num_glyphs; i++) {