mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-21 14:28:10 +02:00
Merge branch 'svgprint'
This commit is contained in:
commit
10920c1326
3 changed files with 115 additions and 45 deletions
|
|
@ -49,6 +49,7 @@
|
|||
|
||||
typedef struct cairo_svg_document cairo_svg_document_t;
|
||||
typedef struct cairo_svg_surface cairo_svg_surface_t;
|
||||
typedef struct cairo_svg_page cairo_svg_page_t;
|
||||
|
||||
static const int invalid_pattern_id = -1;
|
||||
|
||||
|
|
@ -60,6 +61,12 @@ static const cairo_svg_version_t _cairo_svg_versions[] =
|
|||
|
||||
#define CAIRO_SVG_VERSION_LAST ((int)(sizeof (_cairo_svg_versions) / sizeof (_cairo_svg_versions[0])))
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_svg_version_has_page_set_support (cairo_svg_version_t version)
|
||||
{
|
||||
return version > CAIRO_SVG_VERSION_1_1;
|
||||
}
|
||||
|
||||
static const char * _cairo_svg_version_strings[CAIRO_SVG_VERSION_LAST] =
|
||||
{
|
||||
"SVG 1.1",
|
||||
|
|
@ -72,6 +79,13 @@ static const char * _cairo_svg_internal_version_strings[CAIRO_SVG_VERSION_LAST]
|
|||
"1.2"
|
||||
};
|
||||
|
||||
struct cairo_svg_page {
|
||||
unsigned int surface_id;
|
||||
unsigned int clip_id;
|
||||
unsigned int clip_level;
|
||||
cairo_output_stream_t *xml_node;
|
||||
};
|
||||
|
||||
struct cairo_svg_document {
|
||||
cairo_output_stream_t *output_stream;
|
||||
unsigned long refcount;
|
||||
|
|
@ -114,6 +128,7 @@ struct cairo_svg_surface {
|
|||
cairo_svg_document_t *document;
|
||||
|
||||
cairo_output_stream_t *xml_node;
|
||||
cairo_array_t page_set;
|
||||
|
||||
unsigned int clip_level;
|
||||
unsigned int base_clip;
|
||||
|
|
@ -370,6 +385,7 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
|
|||
width, height);
|
||||
|
||||
surface->xml_node = _cairo_memory_stream_create ();
|
||||
_cairo_array_init (&surface->page_set, sizeof (cairo_svg_page_t));
|
||||
|
||||
if (content == CAIRO_CONTENT_COLOR) {
|
||||
_cairo_output_stream_printf (surface->xml_node,
|
||||
|
|
@ -412,6 +428,53 @@ _cairo_svg_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
|||
return surface;
|
||||
}
|
||||
|
||||
static cairo_svg_page_t *
|
||||
_cairo_svg_surface_store_page (cairo_svg_surface_t *surface)
|
||||
{
|
||||
unsigned int i;
|
||||
cairo_svg_page_t page;
|
||||
|
||||
page.xml_node = _cairo_memory_stream_create ();
|
||||
page.surface_id = surface->id;
|
||||
page.clip_id = surface->base_clip;
|
||||
page.clip_level = surface->clip_level;
|
||||
|
||||
page.xml_node = surface->xml_node;
|
||||
surface->xml_node = _cairo_memory_stream_create ();
|
||||
surface->clip_level = 0;
|
||||
|
||||
for (i = 0; i < page.clip_level; i++)
|
||||
_cairo_output_stream_printf (page.xml_node, "</g>\n");
|
||||
|
||||
_cairo_array_append (&surface->page_set, &page);
|
||||
|
||||
return _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_svg_surface_copy_page (void *abstract_surface)
|
||||
{
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
cairo_svg_page_t *page;
|
||||
|
||||
page = _cairo_svg_surface_store_page (surface);
|
||||
|
||||
_cairo_memory_stream_copy (page->xml_node, surface->xml_node);
|
||||
surface->clip_level = page->clip_level;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_svg_surface_show_page (void *abstract_surface)
|
||||
{
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
|
||||
_cairo_svg_surface_store_page (surface);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
emit_transform (cairo_output_stream_t *output,
|
||||
char const *attribute_str,
|
||||
|
|
@ -716,6 +779,8 @@ _cairo_svg_surface_finish (void *abstract_surface)
|
|||
cairo_status_t status;
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
cairo_svg_document_t *document = surface->document;
|
||||
cairo_svg_page_t *page;
|
||||
unsigned int i;
|
||||
|
||||
if (_cairo_paginated_surface_get_target (document->owner) == &surface->base)
|
||||
status = _cairo_svg_document_finish (document);
|
||||
|
|
@ -724,6 +789,12 @@ _cairo_svg_surface_finish (void *abstract_surface)
|
|||
|
||||
_cairo_output_stream_destroy (surface->xml_node);
|
||||
|
||||
for (i = 0; i < surface->page_set.num_elements; i++) {
|
||||
page = _cairo_array_index (&surface->page_set, i);
|
||||
_cairo_output_stream_destroy (page->xml_node);
|
||||
}
|
||||
_cairo_array_fini (&surface->page_set);
|
||||
|
||||
_cairo_svg_document_destroy (document);
|
||||
|
||||
return status;
|
||||
|
|
@ -923,6 +994,7 @@ emit_meta_surface (cairo_svg_document_t *document,
|
|||
cairo_surface_t *paginated_surface;
|
||||
cairo_surface_t *svg_surface;
|
||||
cairo_meta_snapshot_t new_snapshot;
|
||||
cairo_array_t *page_set;
|
||||
|
||||
meta = (cairo_meta_surface_t *) _cairo_surface_snapshot ((cairo_surface_t *)surface);
|
||||
paginated_surface = _cairo_svg_surface_create_for_document (document,
|
||||
|
|
@ -957,10 +1029,17 @@ emit_meta_surface (cairo_svg_document_t *document,
|
|||
}
|
||||
|
||||
contents = ((cairo_svg_surface_t *) svg_surface)->xml_node;
|
||||
_cairo_memory_stream_copy (contents, document->xml_node_defs);
|
||||
page_set = &((cairo_svg_surface_t *) svg_surface)->page_set;
|
||||
|
||||
for (i = 0; i < ((cairo_svg_surface_t *) svg_surface)->clip_level; i++)
|
||||
_cairo_output_stream_printf (document->xml_node_defs, "</g>\n");
|
||||
if (_cairo_memory_stream_length (contents) > 0)
|
||||
_cairo_svg_surface_store_page ((cairo_svg_surface_t *) svg_surface);
|
||||
|
||||
if (page_set->num_elements > 0) {
|
||||
cairo_svg_page_t *page;
|
||||
|
||||
page = _cairo_array_index (page_set, page_set->num_elements - 1);
|
||||
_cairo_memory_stream_copy (page->xml_node, document->xml_node_defs);
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_defs, "</g>\n");
|
||||
|
||||
|
|
@ -1664,8 +1743,8 @@ static const cairo_surface_backend_t cairo_svg_surface_backend = {
|
|||
NULL, /* _cairo_svg_surface_composite, */
|
||||
NULL, /* _cairo_svg_surface_fill_rectangles, */
|
||||
NULL, /* _cairo_svg_surface_composite_trapezoids,*/
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
_cairo_svg_surface_copy_page,
|
||||
_cairo_svg_surface_show_page,
|
||||
NULL, /* set_clip_region */
|
||||
_cairo_svg_surface_intersect_clip_path,
|
||||
_cairo_svg_surface_get_extents,
|
||||
|
|
@ -1759,6 +1838,7 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
|
|||
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;
|
||||
|
||||
if (document->finished)
|
||||
|
|
@ -1788,17 +1868,36 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
|
|||
}
|
||||
|
||||
surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (document->owner);
|
||||
_cairo_output_stream_printf (output,
|
||||
"<g id=\"surface%d\" "
|
||||
"clip-path=\"url(#clip%d)\">\n",
|
||||
surface->id,
|
||||
surface->base_clip);
|
||||
_cairo_memory_stream_copy (surface->xml_node, output);
|
||||
if (_cairo_memory_stream_length (surface->xml_node) > 0)
|
||||
_cairo_svg_surface_store_page (surface);
|
||||
|
||||
for (i = 0; i < surface->clip_level; i++)
|
||||
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\" "
|
||||
"clip-path=\"url(#clip%d)\">\n",
|
||||
page->surface_id,
|
||||
page->clip_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\" "
|
||||
"clip-path=\"url(#clip%d)\">\n",
|
||||
page->surface_id,
|
||||
page->clip_id);
|
||||
_cairo_memory_stream_copy (page->xml_node, output);
|
||||
_cairo_output_stream_printf (output, "</g>\n");
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (output, "</g>\n</svg>\n");
|
||||
_cairo_output_stream_printf (output, "</svg>\n");
|
||||
|
||||
_cairo_output_stream_destroy (document->xml_node_glyphs);
|
||||
_cairo_output_stream_destroy (document->xml_node_defs);
|
||||
|
|
|
|||
|
|
@ -112,7 +112,8 @@ main (void)
|
|||
break;
|
||||
case SVG:
|
||||
surface = cairo_svg_surface_create (backend_filename[backend],
|
||||
SIZE, SIZE * num_pages);
|
||||
SIZE, SIZE);
|
||||
cairo_svg_surface_restrict_to_version (surface, CAIRO_SVG_VERSION_1_2);
|
||||
_cairo_svg_test_force_fallbacks ();
|
||||
break;
|
||||
}
|
||||
|
|
@ -125,35 +126,7 @@ main (void)
|
|||
|
||||
draw_with_ppi (cr, SIZE, SIZE, ppi[page]);
|
||||
|
||||
/* Backend-specific means of "advancing a page" */
|
||||
switch (backend) {
|
||||
case PDF:
|
||||
case PS:
|
||||
cairo_show_page (cr);
|
||||
break;
|
||||
case SVG:
|
||||
/* Since the SVG backend doesn't natively support multiple
|
||||
* pages, we just move further down for each logical
|
||||
* page, then finally do a show_page at the end. */
|
||||
if (page < num_pages - 1) {
|
||||
cairo_translate (cr, 0, SIZE);
|
||||
} else {
|
||||
/* XXX: The goal of this test is to show the
|
||||
* effect of several different fallback
|
||||
* resolutions in a single output document. But
|
||||
* since fallback_resolution only takes effect at
|
||||
* the time of show_page, we only get once for the
|
||||
* SVG backend. I'm just re-setting the first one
|
||||
* here so we actually get legible output.
|
||||
*
|
||||
* To fix this properly we'll need some sort of
|
||||
* multi-page support in the SVG backend I think.
|
||||
*/
|
||||
cairo_surface_set_fallback_resolution (surface, ppi[0], ppi[0]);
|
||||
cairo_show_page (cr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
cairo_show_page (cr);
|
||||
}
|
||||
|
||||
status = cairo_status (cr);
|
||||
|
|
|
|||
|
|
@ -63,8 +63,6 @@ draw (cairo_t *cr, int width, int height)
|
|||
cairo_set_source_surface (cr, stamp, 0, 0);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_show_page (cr);
|
||||
|
||||
cairo_surface_destroy (stamp);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue