Merge branch 'svgprint'

This commit is contained in:
Emmanuel Pacaud 2006-11-18 12:59:12 +01:00
commit 10920c1326
3 changed files with 115 additions and 45 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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;