summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmmanuel Pacaud <emmanuel.pacaud@free.fr>2006-11-18 12:59:12 +0100
committerEmmanuel Pacaud <emmanuel.pacaud@free.fr>2006-11-18 12:59:12 +0100
commit10920c1326362b4fadfa01019223647c23351127 (patch)
tree84e16bee2ba44c634b2d4c249df1792aafce7693
parent1ed3811338a03068b7ce60f83fdd23fe01fec972 (diff)
parent2928f6eb5f5bd207f8f41a628ad95d6552aa8246 (diff)
Merge branch 'svgprint'
-rw-r--r--src/cairo-svg-surface.c127
-rw-r--r--test/fallback-resolution.c33
-rw-r--r--test/pixman-rotate.c2
3 files changed, 116 insertions, 46 deletions
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index d4c60b61..258fe24a 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -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;
+
+ if (_cairo_memory_stream_length (contents) > 0)
+ _cairo_svg_surface_store_page ((cairo_svg_surface_t *) svg_surface);
- for (i = 0; i < ((cairo_svg_surface_t *) svg_surface)->clip_level; i++)
- _cairo_output_stream_printf (document->xml_node_defs, "</g>\n");
+ 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);
-
- for (i = 0; i < surface->clip_level; i++)
+ 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");
+ _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);
diff --git a/test/fallback-resolution.c b/test/fallback-resolution.c
index 25cdcdc4..54487659 100644
--- a/test/fallback-resolution.c
+++ b/test/fallback-resolution.c
@@ -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);
diff --git a/test/pixman-rotate.c b/test/pixman-rotate.c
index 425f883a..ca4d9610 100644
--- a/test/pixman-rotate.c
+++ b/test/pixman-rotate.c
@@ -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;