mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-02-15 06:50:31 +01:00
[cairo-svg-surface] Review error propagation.
Ensure that the error status is propagated and all local resources are freed on the error path.
This commit is contained in:
parent
853b29c56f
commit
bd2245f8b8
1 changed files with 271 additions and 103 deletions
|
|
@ -124,7 +124,7 @@ _cairo_svg_document_create (cairo_output_stream_t *stream,
|
|||
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 (cairo_svg_document_t *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 (cairo_svg_document_t *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 (cairo_svg_document_t *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_internal (cairo_output_stream_t *stream,
|
|||
{
|
||||
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_surface_t *surface)
|
|||
{
|
||||
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 *abstract_surface)
|
|||
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 *abstract_surface)
|
|||
{
|
||||
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_output_stream_t *output,
|
|||
_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_data (cairo_svg_document_t *document,
|
|||
"<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_data (cairo_svg_document_t *document,
|
|||
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_svg_document_t *document,
|
|||
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 (cairo_scaled_font_subset_t *font_subset,
|
|||
{
|
||||
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 (cairo_svg_document_t *document)
|
|||
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 *abstract_surface)
|
|||
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 *abstract_surface)
|
|||
}
|
||||
_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_surface_t *surface,
|
|||
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_pattern (cairo_output_stream_t *outp
|
|||
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 (cairo_svg_document_t *document,
|
|||
}
|
||||
}
|
||||
|
||||
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 (cairo_svg_document_t *document,
|
|||
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 (cairo_svg_document_t *document,
|
|||
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 (cairo_svg_document_t *document,
|
|||
|
||||
*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 (cairo_svg_document_t *document,
|
|||
|
||||
/* 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_pattern (cairo_output_stream_t *output,
|
|||
|
||||
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_svg_surface_t *surface,
|
|||
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 (cairo_svg_surface_t *surface,
|
|||
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 (cairo_output_stream_t *output,
|
|||
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 (cairo_output_stream_t *output,
|
|||
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 (cairo_output_stream_t *output,
|
|||
|
||||
if (reverse_stops || emulate_reflect)
|
||||
free (stops);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1380,8 +1454,8 @@ _cairo_svg_surface_emit_linear_pattern (cairo_svg_surface_t *surface,
|
|||
|
||||
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_t *surface,
|
|||
_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 (cairo_svg_surface_t *surface,
|
|||
|
||||
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 (cairo_svg_surface_t *surface,
|
|||
"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_svg_surface_t *surface, cairo_pattern_t *
|
|||
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 (cairo_output_stream_t *output,
|
|||
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 (cairo_output_stream_t *output,
|
|||
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 (cairo_output_stream_t *output,
|
|||
_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 *abstract_surface,
|
|||
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 *abstract_surface,
|
|||
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_output_stream_t *output,
|
|||
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_output_stream_t *output,
|
|||
"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_output_stream_t *output,
|
|||
|
||||
_cairo_output_stream_printf (output, "/>\n");
|
||||
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -1844,10 +1950,17 @@ _cairo_svg_surface_paint (void *abstract_surface,
|
|||
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 *abstract_surface,
|
|||
}
|
||||
}
|
||||
|
||||
_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 *abstract_surface,
|
|||
* 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 *abstract_surface,
|
|||
|
||||
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 *abstract_dst,
|
|||
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 *abstract_surface,
|
|||
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 *abstract_surface,
|
|||
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 (void *dst,
|
|||
" <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 (void *dst,
|
|||
document->clip_id++;
|
||||
surface->clip_level++;
|
||||
|
||||
return status;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -2111,6 +2249,10 @@ _cairo_svg_document_create (cairo_output_stream_t *output_stream,
|
|||
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_stream_t *output_stream,
|
|||
|
||||
/* 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_stream_t *output_stream,
|
|||
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_stream_t *output_stream,
|
|||
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_document_t *document)
|
|||
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_document_t *document)
|
|||
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_document_t *document)
|
|||
_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_document_t *document)
|
|||
_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 (document->owner != NULL) {
|
||||
cairo_svg_surface_t *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");
|
||||
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_document_t *document)
|
|||
|
||||
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);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue