[cairo-commit] src/cairo-svg-surface.c
Chris Wilson
ickle at kemper.freedesktop.org
Thu Oct 4 16:45:10 PDT 2007
src/cairo-svg-surface.c | 376 ++++++++++++++++++++++++++++++++++--------------
1 file changed, 272 insertions(+), 104 deletions(-)
New commits:
diff-tree bd2245f8b87d85f5ea61200838c10de70e776cf5 (from 853b29c56fdb50c627b27fc3a767300c7551dba0)
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Fri Oct 5 00:45:00 2007 +0100
[cairo-svg-surface] Review error propagation.
Ensure that the error status is propagated and all local resources
are freed on the error path.
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index cc909f5..6ec33d7 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -124,7 +124,7 @@ _cairo_svg_document_create (cairo_output
double height,
cairo_svg_version_t version);
-static void
+static cairo_status_t
_cairo_svg_document_destroy (cairo_svg_document_t *document);
static cairo_status_t
@@ -331,6 +331,8 @@ _cairo_svg_surface_create_for_document (
double height)
{
cairo_svg_surface_t *surface;
+ cairo_surface_t *paginated;
+ cairo_status_t status;
surface = malloc (sizeof (cairo_svg_surface_t));
if (surface == NULL) {
@@ -353,6 +355,9 @@ _cairo_svg_surface_create_for_document (
surface->is_base_clip_emitted = FALSE;
surface->xml_node = _cairo_memory_stream_create ();
+ if (_cairo_output_stream_get_status (surface->xml_node))
+ goto CLEANUP_DOCUMENT;
+
_cairo_array_init (&surface->page_set, sizeof (cairo_svg_page_t));
if (content == CAIRO_CONTENT_COLOR) {
@@ -361,16 +366,31 @@ _cairo_svg_surface_create_for_document (
"style=\"opacity: 1; stroke: none; "
"fill: rgb(0,0,0);\"/>\n",
width, height);
+ if (_cairo_output_stream_get_status (surface->xml_node))
+ goto CLEANUP_STREAM;
}
surface->paginated_mode = CAIRO_PAGINATED_MODE_ANALYZE;
surface->force_fallbacks = FALSE;
surface->content = content;
- return _cairo_paginated_surface_create (&surface->base,
- surface->content,
- surface->width, surface->height,
- &cairo_svg_surface_paginated_backend);
+ paginated = _cairo_paginated_surface_create (&surface->base,
+ surface->content,
+ surface->width,
+ surface->height,
+ &cairo_svg_surface_paginated_backend);
+ if (! paginated->status)
+ return paginated;
+
+ /* ignore status as we are on the error path */
+CLEANUP_STREAM:
+ status = _cairo_output_stream_destroy (surface->xml_node);
+CLEANUP_DOCUMENT:
+ status = _cairo_svg_document_destroy (document);
+
+ free (surface);
+ _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
}
static cairo_surface_t *
@@ -381,18 +401,27 @@ _cairo_svg_surface_create_for_stream_int
{
cairo_svg_document_t *document;
cairo_surface_t *surface;
+ cairo_status_t status;
document = _cairo_svg_document_create (stream, width, height, version);
if (document == NULL) {
+ /* consume the output stream on behalf of caller */
+ status = _cairo_output_stream_destroy (stream);
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
return (cairo_surface_t *) &_cairo_surface_nil;
}
surface = _cairo_svg_surface_create_for_document (document, CAIRO_CONTENT_COLOR_ALPHA,
width, height);
+ if (surface->status) {
+ status = _cairo_svg_document_destroy (document);
+ return (cairo_surface_t *) &_cairo_surface_nil;
+ }
document->owner = surface;
- _cairo_svg_document_destroy (document);
+ status = _cairo_svg_document_destroy (document);
+ /* the ref count should be 2 at this point */
+ assert (status == CAIRO_STATUS_SUCCESS);
return surface;
}
@@ -402,20 +431,29 @@ _cairo_svg_surface_store_page (cairo_svg
{
unsigned int i;
cairo_svg_page_t page;
+ cairo_output_stream_t *stream;
+
+ stream = _cairo_memory_stream_create ();
+ if (stream->status)
+ return NULL;
page.surface_id = surface->id;
page.clip_level = surface->clip_level;
page.xml_node = surface->xml_node;
- surface->xml_node = _cairo_memory_stream_create ();
+ if (_cairo_array_append (&surface->page_set, &page) != CAIRO_STATUS_SUCCESS)
+ {
+ cairo_status_t status = _cairo_output_stream_destroy (stream);
+ return NULL;
+ (void) status;
+ }
+
+ surface->xml_node = stream;
surface->clip_level = 0;
for (i = 0; i < page.clip_level; i++)
_cairo_output_stream_printf (page.xml_node, "</g>\n");
- if (_cairo_array_append (&surface->page_set, &page) != CAIRO_STATUS_SUCCESS)
- return NULL;
-
return _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1);
}
@@ -426,6 +464,8 @@ _cairo_svg_surface_copy_page (void *abst
cairo_svg_page_t *page;
page = _cairo_svg_surface_store_page (surface);
+ if (page == NULL)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
_cairo_memory_stream_copy (page->xml_node, surface->xml_node);
surface->clip_level = page->clip_level;
@@ -438,7 +478,8 @@ _cairo_svg_surface_show_page (void *abst
{
cairo_svg_surface_t *surface = abstract_surface;
- _cairo_svg_surface_store_page (surface);
+ if (_cairo_svg_surface_store_page (surface) == NULL)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
return CAIRO_STATUS_SUCCESS;
}
@@ -549,6 +590,8 @@ _cairo_svg_surface_emit_path (cairo_outp
_cairo_svg_path_curve_to,
_cairo_svg_path_close_path,
&info);
+ if (status)
+ return status;
_cairo_output_stream_printf (output, "\"");
@@ -575,6 +618,8 @@ _cairo_svg_document_emit_outline_glyph_d
"<path style=\"stroke: none;\" ");
status = _cairo_svg_surface_emit_path (document->xml_node_glyphs, scaled_glyph->path, NULL);
+ if (status)
+ return status;
_cairo_output_stream_printf (document->xml_node_glyphs,
"/>\n");
@@ -633,7 +678,7 @@ _cairo_svg_document_emit_bitmap_glyph_da
return CAIRO_STATUS_SUCCESS;
}
-static void
+static cairo_status_t
_cairo_svg_document_emit_glyph (cairo_svg_document_t *document,
cairo_scaled_font_t *scaled_font,
unsigned long scaled_font_glyph_index,
@@ -654,8 +699,12 @@ _cairo_svg_document_emit_glyph (cairo_sv
status = _cairo_svg_document_emit_bitmap_glyph_data (document,
scaled_font,
scaled_font_glyph_index);
+ if (status)
+ return status;
_cairo_output_stream_printf (document->xml_node_glyphs, "</symbol>\n");
+
+ return CAIRO_STATUS_SUCCESS;
}
static void
@@ -664,12 +713,15 @@ _cairo_svg_document_emit_font_subset (ca
{
cairo_svg_document_t *document = closure;
unsigned int i;
+ cairo_status_t status;
for (i = 0; i < font_subset->num_glyphs; i++) {
- _cairo_svg_document_emit_glyph (document,
- font_subset->scaled_font,
- font_subset->glyphs[i],
- font_subset->font_id, i);
+ status = _cairo_svg_document_emit_glyph (document,
+ font_subset->scaled_font,
+ font_subset->glyphs[i],
+ font_subset->font_id, i);
+ if (status)
+ break;
}
}
@@ -681,13 +733,11 @@ _cairo_svg_document_emit_font_subsets (c
status = _cairo_scaled_font_subsets_foreach_scaled (document->font_subsets,
_cairo_svg_document_emit_font_subset,
document);
- if (status)
- return status;
_cairo_scaled_font_subsets_destroy (document->font_subsets);
document->font_subsets = NULL;
- return CAIRO_STATUS_SUCCESS;
+ return status;
}
static cairo_bool_t cairo_svg_force_fallbacks = FALSE;
@@ -743,9 +793,11 @@ _cairo_svg_surface_finish (void *abstrac
else
status = CAIRO_STATUS_SUCCESS;
- status2 = _cairo_output_stream_destroy (surface->xml_node);
- if (status == CAIRO_STATUS_SUCCESS)
- status = status2;
+ if (surface->xml_node != NULL) {
+ status2 = _cairo_output_stream_destroy (surface->xml_node);
+ if (status == CAIRO_STATUS_SUCCESS)
+ status = status2;
+ }
for (i = 0; i < surface->page_set.num_elements; i++) {
page = _cairo_array_index (&surface->page_set, i);
@@ -755,7 +807,9 @@ _cairo_svg_surface_finish (void *abstrac
}
_cairo_array_fini (&surface->page_set);
- _cairo_svg_document_destroy (document);
+ status2 = _cairo_svg_document_destroy (document);
+ if (status == CAIRO_STATUS_SUCCESS)
+ status = status2;
return status;
}
@@ -869,10 +923,10 @@ _cairo_surface_base64_encode (cairo_surf
info.src[i] = '\x0';
info.trailing = 3 - info.in_mem;
info.in_mem = 3;
- base64_write_func (&info, NULL, 0);
+ status = base64_write_func (&info, NULL, 0);
}
- return CAIRO_STATUS_SUCCESS;
+ return status;
}
static cairo_status_t
@@ -896,14 +950,13 @@ _cairo_svg_surface_emit_composite_image_
return status;
status = _cairo_surface_get_extents (surface, &extents);
-
if (status)
return status;
p2u = pattern->base.matrix;
status = cairo_matrix_invert (&p2u);
- if (status)
- return status;
+ /* cairo_pattern_set_matrix ensures the matrix is invertible */
+ assert (status == CAIRO_STATUS_SUCCESS);
if (pattern_id != invalid_pattern_id) {
_cairo_output_stream_printf (output,
@@ -970,25 +1023,32 @@ _cairo_svg_surface_emit_meta_surface (ca
}
}
- meta = (cairo_meta_surface_t *) _cairo_surface_snapshot ((cairo_surface_t *)surface);
+ meta = (cairo_meta_surface_t *) _cairo_surface_snapshot (&surface->base);
paginated_surface = _cairo_svg_surface_create_for_document (document,
meta->content,
meta->width_pixels,
meta->height_pixels);
+ if (paginated_surface->status) {
+ cairo_surface_destroy (&meta->base);
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+
svg_surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (paginated_surface);
cairo_surface_set_fallback_resolution (paginated_surface,
document->owner->x_fallback_resolution,
document->owner->y_fallback_resolution);
- status = _cairo_meta_surface_replay ((cairo_surface_t *)meta, paginated_surface);
+ status = _cairo_meta_surface_replay (&meta->base, paginated_surface);
if (status) {
cairo_surface_destroy (&meta->base);
+ cairo_surface_destroy (paginated_surface);
return status;
}
status = cairo_surface_show_page (paginated_surface);
if (status) {
cairo_surface_destroy (&meta->base);
+ cairo_surface_destroy (paginated_surface);
return status;
}
@@ -997,6 +1057,7 @@ _cairo_svg_surface_emit_meta_surface (ca
status = _cairo_array_append (&document->meta_snapshots, &new_snapshot);
if (status) {
cairo_surface_destroy (&meta->base);
+ cairo_surface_destroy (paginated_surface);
return status;
}
@@ -1030,8 +1091,12 @@ _cairo_svg_surface_emit_meta_surface (ca
contents = svg_surface->xml_node;
page_set = &svg_surface->page_set;
- if (_cairo_memory_stream_length (contents) > 0)
- _cairo_svg_surface_store_page (svg_surface);
+ if (_cairo_memory_stream_length (contents) > 0) {
+ if (_cairo_svg_surface_store_page (svg_surface) == NULL) {
+ cairo_surface_destroy (paginated_surface);
+ return CAIRO_STATUS_NO_MEMORY;
+ }
+ }
if (page_set->num_elements > 0) {
cairo_svg_page_t *page;
@@ -1044,6 +1109,7 @@ _cairo_svg_surface_emit_meta_surface (ca
*id = new_snapshot.id;
+ status = cairo_surface_status (paginated_surface);
cairo_surface_destroy (paginated_surface);
/* FIXME: cairo_paginated_surface doesn't take a ref to the
@@ -1053,7 +1119,7 @@ _cairo_svg_surface_emit_meta_surface (ca
/* cairo_surface_destroy (svg_surface); */
- return CAIRO_STATUS_SUCCESS;
+ return status;
}
static cairo_status_t
@@ -1071,8 +1137,8 @@ _cairo_svg_surface_emit_composite_meta_p
p2u = pattern->base.matrix;
status = cairo_matrix_invert (&p2u);
- if (status)
- return status;
+ /* cairo_pattern_set_matrix ensures the matrix is invertible */
+ assert (status == CAIRO_STATUS_SUCCESS);
meta_surface = (cairo_meta_surface_t *) pattern->surface;
@@ -1174,11 +1240,15 @@ _cairo_svg_surface_emit_surface_pattern
cairo_bool_t is_stroke)
{
cairo_svg_document_t *document = surface->document;
+ cairo_status_t status;
int pattern_id;
pattern_id = document->pattern_id++;
- _cairo_svg_surface_emit_composite_pattern (document->xml_node_defs, surface, pattern,
- pattern_id, NULL);
+ status = _cairo_svg_surface_emit_composite_pattern (document->xml_node_defs,
+ surface, pattern,
+ pattern_id, NULL);
+ if (status)
+ return status;
_cairo_output_stream_printf (style,
"%s: url(#pattern%d);",
@@ -1188,7 +1258,7 @@ _cairo_svg_surface_emit_surface_pattern
return CAIRO_STATUS_SUCCESS;
}
-static void
+static cairo_status_t
_cairo_svg_surface_emit_pattern_stops (cairo_output_stream_t *output,
cairo_gradient_pattern_t const *pattern,
double start_offset,
@@ -1201,7 +1271,7 @@ _cairo_svg_surface_emit_pattern_stops (c
unsigned int i;
if (pattern->n_stops < 1)
- return;
+ return CAIRO_STATUS_SUCCESS;
if (pattern->n_stops == 1) {
_cairo_output_stream_printf (output,
@@ -1213,12 +1283,14 @@ _cairo_svg_surface_emit_pattern_stops (c
pattern->stops[0].color.green * 100.0,
pattern->stops[0].color.blue * 100.0,
pattern->stops[0].color.alpha);
- return;
+ return CAIRO_STATUS_SUCCESS;
}
if (emulate_reflect || reverse_stops) {
n_stops = emulate_reflect ? pattern->n_stops * 2 - 2: pattern->n_stops;
stops = _cairo_malloc_ab (n_stops, sizeof (cairo_gradient_stop_t));
+ if (stops == NULL)
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
for (i = 0; i < pattern->n_stops; i++) {
if (reverse_stops) {
@@ -1348,6 +1420,8 @@ _cairo_svg_surface_emit_pattern_stops (c
if (reverse_stops || emulate_reflect)
free (stops);
+
+ return CAIRO_STATUS_SUCCESS;
}
static void
@@ -1380,8 +1454,8 @@ _cairo_svg_surface_emit_linear_pattern (
p2u = pattern->base.base.matrix;
status = cairo_matrix_invert (&p2u);
- if (status)
- return status;
+ /* cairo_pattern_set_matrix ensures the matrix is invertible */
+ assert (status == CAIRO_STATUS_SUCCESS);
x0 = _cairo_fixed_to_double (pattern->p1.x);
y0 = _cairo_fixed_to_double (pattern->p1.y);
@@ -1399,7 +1473,11 @@ _cairo_svg_surface_emit_linear_pattern (
_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u);
_cairo_output_stream_printf (document->xml_node_defs, ">\n");
- _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs ,&pattern->base, 0.0, FALSE, FALSE);
+ status = _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs,
+ &pattern->base, 0.0,
+ FALSE, FALSE);
+ if (status)
+ return status;
_cairo_output_stream_printf (document->xml_node_defs,
"</linearGradient>\n");
@@ -1455,8 +1533,8 @@ _cairo_svg_surface_emit_radial_pattern (
p2u = pattern->base.base.matrix;
status = cairo_matrix_invert (&p2u);
- if (status)
- return status;
+ /* cairo_pattern_set_matrix ensures the matrix is invertible */
+ assert (status == CAIRO_STATUS_SUCCESS);
if (pattern->r1 == pattern->r2) {
_cairo_output_stream_printf (document->xml_node_defs,
@@ -1570,8 +1648,13 @@ _cairo_svg_surface_emit_radial_pattern (
"stop-opacity: 0;\"/>\n",
r0 / r1);
}
- _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs, &pattern->base, offset,
- reverse_stops, emulate_reflect);
+ status = _cairo_svg_surface_emit_pattern_stops (document->xml_node_defs,
+ &pattern->base, offset,
+ reverse_stops,
+ emulate_reflect);
+ if (status)
+ return status;
+
if (pattern->base.base.extend == CAIRO_EXTEND_NONE)
_cairo_output_stream_printf (document->xml_node_defs,
"<stop offset=\"1.0\" style=\""
@@ -1609,10 +1692,10 @@ _cairo_svg_surface_emit_pattern (cairo_s
case CAIRO_PATTERN_TYPE_RADIAL:
return _cairo_svg_surface_emit_radial_pattern (surface, (cairo_radial_pattern_t *) pattern, output, is_stroke);
}
- return CAIRO_STATUS_SUCCESS;
+ return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
}
-static void
+static cairo_status_t
_cairo_svg_surface_emit_fill_style (cairo_output_stream_t *output,
cairo_svg_surface_t *surface,
cairo_operator_t op,
@@ -1624,16 +1707,17 @@ _cairo_svg_surface_emit_fill_style (cair
fill_rule == CAIRO_FILL_RULE_EVEN_ODD ?
"evenodd" : "nonzero");
_cairo_svg_surface_emit_operator (output, surface, op);
- _cairo_svg_surface_emit_pattern (surface, source, output, FALSE);
+ return _cairo_svg_surface_emit_pattern (surface, source, output, FALSE);
}
-static void
+static cairo_status_t
_cairo_svg_surface_emit_stroke_style (cairo_output_stream_t *output,
cairo_svg_surface_t *surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_stroke_style_t *stroke_style)
{
+ cairo_status_t status;
const char *line_cap, *line_join;
unsigned int i;
@@ -1673,7 +1757,10 @@ _cairo_svg_surface_emit_stroke_style (ca
line_cap,
line_join);
- _cairo_svg_surface_emit_pattern (surface, source, output, TRUE);
+ status = _cairo_svg_surface_emit_pattern (surface, source, output, TRUE);
+ if (status)
+ return status;
+
_cairo_svg_surface_emit_operator (output, surface, op);
if (stroke_style->num_dashes > 0) {
@@ -1696,6 +1783,8 @@ _cairo_svg_surface_emit_stroke_style (ca
_cairo_output_stream_printf (output,
"stroke-miterlimit: %f; ",
stroke_style->miter_limit);
+
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@@ -1718,16 +1807,24 @@ _cairo_svg_surface_fill_stroke (void *
cairo_status_t status;
_cairo_output_stream_printf (surface->xml_node, "<path style=\"");
- _cairo_svg_surface_emit_fill_style (surface->xml_node, surface, fill_op, fill_source, fill_rule);
- _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, stroke_op, stroke_source, stroke_style);
+ status = _cairo_svg_surface_emit_fill_style (surface->xml_node, surface, fill_op, fill_source, fill_rule);
+ if (status)
+ return status;
+
+ status = _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, stroke_op, stroke_source, stroke_style);
+ if (status)
+ return status;
+
_cairo_output_stream_printf (surface->xml_node, "\" ");
status = _cairo_svg_surface_emit_path (surface->xml_node, path, stroke_ctm_inverse);
+ if (status)
+ return status;
_cairo_svg_surface_emit_transform (surface->xml_node, " transform", stroke_ctm);
_cairo_output_stream_printf (surface->xml_node, "/>\n");
- return status;
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@@ -1748,14 +1845,19 @@ _cairo_svg_surface_fill (void *abstrac
assert (_cairo_svg_surface_operation_supported (surface, op, source));
_cairo_output_stream_printf (surface->xml_node, "<path style=\" stroke:none;");
- _cairo_svg_surface_emit_fill_style (surface->xml_node, surface, op, source, fill_rule);
+ status = _cairo_svg_surface_emit_fill_style (surface->xml_node, surface, op, source, fill_rule);
+ if (status)
+ return status;
+
_cairo_output_stream_printf (surface->xml_node, "\" ");
status = _cairo_svg_surface_emit_path (surface->xml_node, path, NULL);
+ if (status)
+ return status;
_cairo_output_stream_printf (surface->xml_node, "/>\n");
- return status;
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@@ -1784,6 +1886,8 @@ _cairo_svg_surface_emit_paint (cairo_out
cairo_pattern_t *source,
const char *extra_attributes)
{
+ cairo_status_t status;
+
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
source->extend == CAIRO_EXTEND_NONE)
return _cairo_svg_surface_emit_composite_pattern (output,
@@ -1798,7 +1902,10 @@ _cairo_svg_surface_emit_paint (cairo_out
"style=\"",
surface->width, surface->height);
_cairo_svg_surface_emit_operator (output, surface, op);
- _cairo_svg_surface_emit_pattern (surface, source, output, FALSE);
+ status = _cairo_svg_surface_emit_pattern (surface, source, output, FALSE);
+ if (status)
+ return status;
+
_cairo_output_stream_printf (output, " stroke: none;\"");
if (extra_attributes)
@@ -1806,7 +1913,6 @@ _cairo_svg_surface_emit_paint (cairo_out
_cairo_output_stream_printf (output, "/>\n");
-
return CAIRO_STATUS_SUCCESS;
}
@@ -1844,10 +1950,17 @@ _cairo_svg_surface_paint (void *abs
op == CAIRO_OPERATOR_SOURCE))
{
status = _cairo_output_stream_destroy (surface->xml_node);
- if (status)
+ if (status) {
+ surface->xml_node = NULL;
return status;
+ }
surface->xml_node = _cairo_memory_stream_create ();
+ status = _cairo_output_stream_get_status (surface->xml_node);
+ if (status) {
+ surface->xml_node = NULL;
+ return status;
+ }
if (op == CAIRO_OPERATOR_CLEAR) {
if (surface->content == CAIRO_CONTENT_COLOR) {
@@ -1863,9 +1976,7 @@ _cairo_svg_surface_paint (void *abs
}
}
- _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, NULL);
-
- return CAIRO_STATUS_SUCCESS;
+ return _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, NULL);
}
static cairo_int_status_t
@@ -1891,11 +2002,21 @@ _cairo_svg_surface_mask (void *abst
* document->xml_node_defs so we need to write the mask element to
* a temporary stream and then copy that to xml_node_defs. */
mask_stream = _cairo_memory_stream_create ();
+ status = _cairo_output_stream_get_status (mask_stream);
+ if (status)
+ return status;
+
_cairo_output_stream_printf (mask_stream,
"<mask id=\"mask%d\">\n"
" <g filter=\"url(#alpha)\">\n",
document->mask_id);
- _cairo_svg_surface_emit_paint (mask_stream, surface, op, mask, NULL);
+ status = _cairo_svg_surface_emit_paint (mask_stream, surface, op, mask, NULL);
+ if (status) {
+ cairo_status_t ignore = _cairo_output_stream_destroy (mask_stream);
+ return status;
+ (void) ignore;
+ }
+
_cairo_output_stream_printf (mask_stream,
" </g>\n"
"</mask>\n");
@@ -1907,7 +2028,9 @@ _cairo_svg_surface_mask (void *abst
snprintf (buffer, sizeof buffer, "mask=\"url(#mask%d);\"",
document->mask_id);
- _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, buffer);
+ status = _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, buffer);
+ if (status)
+ return status;
document->mask_id++;
@@ -1934,15 +2057,17 @@ _cairo_svg_surface_stroke (void *abstr
assert (_cairo_svg_surface_operation_supported (surface, op, source));
_cairo_output_stream_printf (surface->xml_node, "<path style=\"fill: none; ");
- _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, op, source, stroke_style);
+ status = _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, op, source, stroke_style);
_cairo_output_stream_printf (surface->xml_node, "\" ");
status = _cairo_svg_surface_emit_path (surface->xml_node, path, ctm_inverse);
+ if (status)
+ return status;
_cairo_svg_surface_emit_transform (surface->xml_node, " transform", ctm);
_cairo_output_stream_printf (surface->xml_node, "/>\n");
- return status;
+ return CAIRO_STATUS_SUCCESS;
}
static cairo_int_status_t
@@ -1975,19 +2100,28 @@ _cairo_svg_surface_show_glyphs (void *
goto FALLBACK;
_cairo_output_stream_printf (surface->xml_node, "<g style=\"");
- _cairo_svg_surface_emit_pattern (surface, pattern, surface->xml_node, FALSE);
+ status = _cairo_svg_surface_emit_pattern (surface, pattern,
+ surface->xml_node, FALSE);
+ if (status)
+ return status;
+
_cairo_output_stream_printf (surface->xml_node, "\">\n");
for (i = 0; i < num_glyphs; i++) {
status = _cairo_scaled_font_subsets_map_glyph (document->font_subsets,
scaled_font, glyphs[i].index,
&subset_glyph);
- if (status) {
+ if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+ _cairo_output_stream_printf (surface->xml_node, "</g>\n");
+
glyphs += i;
num_glyphs -= i;
goto FALLBACK;
}
+ if (status)
+ return status;
+
_cairo_output_stream_printf (surface->xml_node,
" <use xlink:href=\"#glyph%d-%d\" "
"x=\"%f\" y=\"%f\"/>\n",
@@ -2001,13 +2135,14 @@ _cairo_svg_surface_show_glyphs (void *
return CAIRO_STATUS_SUCCESS;
FALLBACK:
-
_cairo_path_fixed_init (&path);
status = _cairo_scaled_font_glyph_path (scaled_font,(cairo_glyph_t *) glyphs, num_glyphs, &path);
- if (status)
- return status;
+ if (status) {
+ _cairo_path_fixed_fini (&path);
+ return status;
+ }
status = _cairo_svg_surface_fill (abstract_surface, op, pattern,
&path, CAIRO_FILL_RULE_WINDING, 0.0, CAIRO_ANTIALIAS_SUBPIXEL);
@@ -2042,6 +2177,9 @@ _cairo_svg_surface_intersect_clip_path (
" <path ",
document->clip_id);
status = _cairo_svg_surface_emit_path (document->xml_node_defs, path, NULL);
+ if (status)
+ return status;
+
_cairo_output_stream_printf (document->xml_node_defs,
"/>\n"
"</clipPath>\n");
@@ -2056,7 +2194,7 @@ _cairo_svg_surface_intersect_clip_path (
document->clip_id++;
surface->clip_level++;
- return status;
+ return CAIRO_STATUS_SUCCESS;
}
static void
@@ -2111,6 +2249,10 @@ _cairo_svg_document_create (cairo_output
cairo_svg_version_t version)
{
cairo_svg_document_t *document;
+ cairo_status_t status;
+
+ if (output_stream->status)
+ return NULL;
document = malloc (sizeof (cairo_svg_document_t));
if (document == NULL) {
@@ -2120,10 +2262,8 @@ _cairo_svg_document_create (cairo_output
/* The use of defs for font glyphs imposes no per-subset limit. */
document->font_subsets = _cairo_scaled_font_subsets_create_scaled ();
- if (document->font_subsets == NULL) {
- free (document);
- return NULL;
- }
+ if (document->font_subsets == NULL)
+ goto CLEANUP_DOCUMENT;
document->output_stream = output_stream;
document->refcount = 1;
@@ -2141,7 +2281,12 @@ _cairo_svg_document_create (cairo_output
document->mask_id = 0;
document->xml_node_defs = _cairo_memory_stream_create ();
+ if (_cairo_output_stream_get_status (document->xml_node_defs))
+ goto CLEANUP_FONT_SUBSETS;
+
document->xml_node_glyphs = _cairo_memory_stream_create ();
+ if (_cairo_output_stream_get_status (document->xml_node_glyphs))
+ goto CLEANUP_NODE_DEFS;
document->alpha_filter = FALSE;
@@ -2151,6 +2296,14 @@ _cairo_svg_document_create (cairo_output
document->svg_version = version;
return document;
+
+ CLEANUP_NODE_DEFS:
+ status = _cairo_output_stream_destroy (document->xml_node_defs);
+ CLEANUP_FONT_SUBSETS:
+ _cairo_scaled_font_subsets_destroy (document->font_subsets);
+ CLEANUP_DOCUMENT:
+ free (document);
+ return NULL;
}
static cairo_svg_document_t *
@@ -2161,16 +2314,20 @@ _cairo_svg_document_reference (cairo_svg
return document;
}
-static void
+static cairo_status_t
_cairo_svg_document_destroy (cairo_svg_document_t *document)
{
+ cairo_status_t status;
+
document->refcount--;
if (document->refcount > 0)
- return;
+ return CAIRO_STATUS_SUCCESS;
- _cairo_svg_document_finish (document);
+ status = _cairo_svg_document_finish (document);
free (document);
+
+ return status;
}
static cairo_status_t
@@ -2179,7 +2336,6 @@ _cairo_svg_document_finish (cairo_svg_do
cairo_status_t status, status2;
cairo_output_stream_t *output = document->output_stream;
cairo_meta_snapshot_t *snapshot;
- cairo_svg_surface_t *surface;
cairo_svg_page_t *page;
unsigned int i;
@@ -2197,8 +2353,6 @@ _cairo_svg_document_finish (cairo_svg_do
_cairo_svg_internal_version_strings [document->svg_version]);
status = _cairo_svg_document_emit_font_subsets (document);
- if (status)
- return status;
if (_cairo_memory_stream_length (document->xml_node_glyphs) > 0 ||
_cairo_memory_stream_length (document->xml_node_defs) > 0) {
@@ -2212,35 +2366,46 @@ _cairo_svg_document_finish (cairo_svg_do
_cairo_output_stream_printf (output, "</defs>\n");
}
- surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (document->owner);
- if (_cairo_memory_stream_length (surface->xml_node) > 0)
- _cairo_svg_surface_store_page (surface);
-
- if (surface->page_set.num_elements > 1 &&
- _cairo_svg_version_has_page_set_support (document->svg_version)) {
- _cairo_output_stream_printf (output, "<pageSet>\n");
- for (i = 0; i < surface->page_set.num_elements; i++) {
- page = _cairo_array_index (&surface->page_set, i);
- _cairo_output_stream_printf (output, "<page>\n");
+ if (document->owner != NULL) {
+ cairo_svg_surface_t *surface;
+
+ surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (document->owner);
+ if (surface->xml_node != NULL &&
+ _cairo_memory_stream_length (surface->xml_node) > 0) {
+ if (_cairo_svg_surface_store_page (surface) == NULL) {
+ if (status == CAIRO_STATUS_SUCCESS)
+ status = CAIRO_STATUS_NO_MEMORY;
+ }
+ }
+
+ if (surface->page_set.num_elements > 1 &&
+ _cairo_svg_version_has_page_set_support (document->svg_version)) {
+ _cairo_output_stream_printf (output, "<pageSet>\n");
+ for (i = 0; i < surface->page_set.num_elements; i++) {
+ page = _cairo_array_index (&surface->page_set, i);
+ _cairo_output_stream_printf (output, "<page>\n");
+ _cairo_output_stream_printf (output,
+ "<g id=\"surface%d\">\n",
+ page->surface_id);
+ _cairo_memory_stream_copy (page->xml_node, output);
+ _cairo_output_stream_printf (output, "</g>\n</page>\n");
+ }
+ _cairo_output_stream_printf (output, "</pageSet>\n");
+ } else if (surface->page_set.num_elements > 0) {
+ page = _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1);
_cairo_output_stream_printf (output,
"<g id=\"surface%d\">\n",
page->surface_id);
_cairo_memory_stream_copy (page->xml_node, output);
- _cairo_output_stream_printf (output, "</g>\n</page>\n");
+ _cairo_output_stream_printf (output, "</g>\n");
}
- _cairo_output_stream_printf (output, "</pageSet>\n");
- } else if (surface->page_set.num_elements > 0) {
- page = _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1);
- _cairo_output_stream_printf (output,
- "<g id=\"surface%d\">\n",
- page->surface_id);
- _cairo_memory_stream_copy (page->xml_node, output);
- _cairo_output_stream_printf (output, "</g>\n");
}
_cairo_output_stream_printf (output, "</svg>\n");
- status = _cairo_output_stream_destroy (document->xml_node_glyphs);
+ status2 = _cairo_output_stream_destroy (document->xml_node_glyphs);
+ if (status == CAIRO_STATUS_SUCCESS)
+ status = status2;
status2 = _cairo_output_stream_destroy (document->xml_node_defs);
if (status == CAIRO_STATUS_SUCCESS)
@@ -2252,7 +2417,10 @@ _cairo_svg_document_finish (cairo_svg_do
for (i = 0; i < document->meta_snapshots.num_elements; i++) {
snapshot = _cairo_array_index (&document->meta_snapshots, i);
- cairo_surface_destroy ((cairo_surface_t *) snapshot->meta);
+ status2 = cairo_surface_status (&snapshot->meta->base);
+ cairo_surface_destroy (&snapshot->meta->base);
+ if (status == CAIRO_STATUS_SUCCESS)
+ status = status2;
}
_cairo_array_fini (&document->meta_snapshots);
More information about the cairo-commit
mailing list