[cairo-commit] src/cairo-paginated-private.h src/cairo-paginated-surface.c src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-svg-surface.c test/finer-grained-fallbacks.c test/finer-grained-fallbacks-ps2-argb32-ref.png test/finer-grained-fallbacks-ps2-ref.png test/finer-grained-fallbacks-ps2-rgb24-ref.png test/finer-grained-fallbacks-ps3-argb32-ref.png test/finer-grained-fallbacks-ps3-ref.png test/finer-grained-fallbacks-ps3-rgb24-ref.png test/finer-grained-fallbacks-ref.png test/finer-grained-fallbacks-rgb24-ref.png test/Makefile.am
Chris Wilson
ickle at kemper.freedesktop.org
Wed Oct 8 05:19:09 PDT 2008
dev/null |binary
src/cairo-paginated-private.h | 9 +-
src/cairo-paginated-surface.c | 47 +++++---------
src/cairo-pdf-surface.c | 14 +++-
src/cairo-ps-surface.c | 8 ++
src/cairo-svg-surface.c | 34 +++++++---
test/Makefile.am | 4 -
test/finer-grained-fallbacks-ps2-ref.png |binary
test/finer-grained-fallbacks-ps2-rgb24-ref.png |binary
test/finer-grained-fallbacks-ps3-ref.png |binary
test/finer-grained-fallbacks-ps3-rgb24-ref.png |binary
test/finer-grained-fallbacks-ref.png |binary
test/finer-grained-fallbacks-rgb24-ref.png |binary
test/finer-grained-fallbacks.c | 79 ++++++++++++++++++++++++-
14 files changed, 147 insertions(+), 48 deletions(-)
New commits:
commit 565c02a37e2d140a20867081eea9bb5de9999b1c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date: Wed Oct 8 11:06:42 2008 +0100
[svg] Use finer-grained fallbacks for SVG 1.2
The use of fine-grained fallbacks requires the native support of the
SOURCE operator applied to an image on the target surface. SVG 1.2
introduces the "comp-op:src" mode fulfilling this criteria - so we can
enable fine-grained fallbacks for 1.2+.
Update test/fine-grained-fallbacks to exercise this pathway in SVG 1.2 -
as SVG natively supported all the current operations within that test.
This reveals yet another librsvg bug in handling SVG 1.2.
diff --git a/src/cairo-paginated-private.h b/src/cairo-paginated-private.h
index 0c04274..5cb2e48 100644
--- a/src/cairo-paginated-private.h
+++ b/src/cairo-paginated-private.h
@@ -65,7 +65,7 @@ struct _cairo_paginated_surface_backend {
* before the mode is changed to RENDER.
*/
cairo_warn cairo_int_status_t
- (*set_bounding_box) (void *surface,
+ (*set_bounding_box) (void *surface,
cairo_box_t *bbox);
/* Optional. Indicates whether the page requires fallback images.
@@ -73,8 +73,11 @@ struct _cairo_paginated_surface_backend {
* mode is changed to RENDER.
*/
cairo_warn cairo_int_status_t
- (*set_fallback_images_required)(void *surface,
- cairo_bool_t fallbacks_required);
+ (*set_fallback_images_required) (void *surface,
+ cairo_bool_t fallbacks_required);
+
+ cairo_bool_t
+ (*supports_fine_grained_fallbacks) (void *surface);
};
/* A #cairo_paginated_surface_t provides a very convenient wrapper that
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index e4e84d5..131d289 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -329,36 +329,23 @@ _paint_page (cairo_paginated_surface_t *surface)
/* Finer grained fallbacks are currently only supported for some
* surface types */
- switch (surface->target->type) {
- case CAIRO_SURFACE_TYPE_PDF:
- case CAIRO_SURFACE_TYPE_PS:
- case CAIRO_SURFACE_TYPE_WIN32_PRINTING:
- has_supported = _cairo_analysis_surface_has_supported (analysis);
- has_page_fallback = FALSE;
- has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis);
- break;
-
- case CAIRO_SURFACE_TYPE_IMAGE:
- case CAIRO_SURFACE_TYPE_XLIB:
- case CAIRO_SURFACE_TYPE_XCB:
- case CAIRO_SURFACE_TYPE_GLITZ:
- case CAIRO_SURFACE_TYPE_QUARTZ:
- case CAIRO_SURFACE_TYPE_QUARTZ_IMAGE:
- case CAIRO_SURFACE_TYPE_WIN32:
- case CAIRO_SURFACE_TYPE_BEOS:
- case CAIRO_SURFACE_TYPE_DIRECTFB:
- case CAIRO_SURFACE_TYPE_SVG:
- case CAIRO_SURFACE_TYPE_OS2:
- default:
- if (_cairo_analysis_surface_has_unsupported (analysis)) {
- has_supported = FALSE;
- has_page_fallback = TRUE;
- } else {
- has_supported = TRUE;
- has_page_fallback = FALSE;
- }
- has_finegrained_fallback = FALSE;
- break;
+ if (surface->backend->supports_fine_grained_fallbacks != NULL &&
+ surface->backend->supports_fine_grained_fallbacks (surface->target))
+ {
+ has_supported = _cairo_analysis_surface_has_supported (analysis);
+ has_page_fallback = FALSE;
+ has_finegrained_fallback = _cairo_analysis_surface_has_unsupported (analysis);
+ }
+ else
+ {
+ if (_cairo_analysis_surface_has_unsupported (analysis)) {
+ has_supported = FALSE;
+ has_page_fallback = TRUE;
+ } else {
+ has_supported = TRUE;
+ has_page_fallback = FALSE;
+ }
+ has_finegrained_fallback = FALSE;
}
if (has_supported) {
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 16abab3..e073eb4 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1277,8 +1277,8 @@ _cairo_pdf_surface_start_page (void *abstract_surface)
}
static cairo_int_status_t
-_cairo_pdf_surface_has_fallback_images (void *abstract_surface,
- cairo_bool_t has_fallbacks)
+_cairo_pdf_surface_has_fallback_images (void *abstract_surface,
+ cairo_bool_t has_fallbacks)
{
cairo_status_t status;
cairo_pdf_surface_t *surface = abstract_surface;
@@ -1291,6 +1291,12 @@ _cairo_pdf_surface_has_fallback_images (void *abstract_surface,
return CAIRO_STATUS_SUCCESS;
}
+static cairo_bool_t
+_cairo_pdf_surface_supports_fine_grained_fallbacks (void *abstract_surface)
+{
+ return TRUE;
+}
+
/* Emit alpha channel from the image into the given data, providing
* an id that can be used to reference the resulting SMask object.
*
@@ -4981,9 +4987,11 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
_cairo_pdf_surface_show_text_glyphs,
};
-static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = {
+static const cairo_paginated_surface_backend_t
+cairo_pdf_surface_paginated_backend = {
_cairo_pdf_surface_start_page,
_cairo_pdf_surface_set_paginated_mode,
NULL, /* set_bounding_box */
_cairo_pdf_surface_has_fallback_images,
+ _cairo_pdf_surface_supports_fine_grained_fallbacks,
};
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index bef876c..b107a54 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -3284,6 +3284,12 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface,
return _cairo_output_stream_get_status (surface->stream);
}
+static cairo_bool_t
+_cairo_ps_surface_supports_fine_grained_fallbacks (void *abstract_surface)
+{
+ return TRUE;
+}
+
static const cairo_surface_backend_t cairo_ps_surface_backend = {
CAIRO_SURFACE_TYPE_PS,
_cairo_ps_surface_create_similar,
@@ -3322,4 +3328,6 @@ static const cairo_paginated_surface_backend_t cairo_ps_surface_paginated_backen
_cairo_ps_surface_start_page,
_cairo_ps_surface_set_paginated_mode,
_cairo_ps_surface_set_bounding_box,
+ NULL, /* _cairo_ps_surface_has_fallback_images, */
+ _cairo_ps_surface_supports_fine_grained_fallbacks,
};
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 8095aa4..19af873 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -2022,11 +2022,8 @@ _cairo_svg_surface_paint (void *abstract_surface,
* above always return FALSE. In order to make it work, we need a way
* to know if there's an active clipping path.
* Optimization of CLEAR works because of a test in paginated surface,
- * and an optimiszation in meta surface. */
- if (surface->clip_level == 0 &&
- (op == CAIRO_OPERATOR_CLEAR ||
- op == CAIRO_OPERATOR_SOURCE))
- {
+ * and an optimization in meta surface. */
+ if (surface->clip_level == 0 && op == CAIRO_OPERATOR_CLEAR) {
status = _cairo_output_stream_destroy (surface->xml_node);
if (status) {
surface->xml_node = NULL;
@@ -2054,7 +2051,8 @@ _cairo_svg_surface_paint (void *abstract_surface,
}
}
- return _cairo_svg_surface_emit_paint (surface->xml_node, surface, op, source, 0, NULL);
+ return _cairo_svg_surface_emit_paint (surface->xml_node,
+ surface, op, source, 0, NULL);
}
static cairo_int_status_t
@@ -2551,15 +2549,33 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
}
static void
-_cairo_svg_surface_set_paginated_mode (void *abstract_surface,
- cairo_paginated_mode_t paginated_mode)
+_cairo_svg_surface_set_paginated_mode (void *abstract_surface,
+ cairo_paginated_mode_t paginated_mode)
{
cairo_svg_surface_t *surface = abstract_surface;
surface->paginated_mode = paginated_mode;
}
+static cairo_bool_t
+_cairo_svg_surface_supports_fine_grained_fallbacks (void *abstract_surface)
+{
+ cairo_svg_surface_t *surface = abstract_surface;
+ cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
+
+ if (surface->document->svg_version >= CAIRO_SVG_VERSION_1_2) {
+ status = _cairo_svg_surface_analyze_operator (surface,
+ CAIRO_OPERATOR_SOURCE);
+ }
+
+ return status == CAIRO_STATUS_SUCCESS;
+}
+
static const cairo_paginated_surface_backend_t cairo_svg_surface_paginated_backend = {
NULL /*_cairo_svg_surface_start_page*/,
- _cairo_svg_surface_set_paginated_mode
+ _cairo_svg_surface_set_paginated_mode,
+ NULL, /* _cairo_svg_surface_set_bounding_box */
+ NULL, /* _cairo_svg_surface_set_fallback_images_required */
+ _cairo_svg_surface_supports_fine_grained_fallbacks,
+
};
diff --git a/test/Makefile.am b/test/Makefile.am
index a33ca41..eb961ac 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -478,9 +478,9 @@ REFERENCE_IMAGES = \
filter-nearest-offset-svg12-ref.png \
finer-grained-fallbacks-ref.png \
finer-grained-fallbacks-rgb24-ref.png \
- finer-grained-fallbacks-ps2-argb32-ref.png \
- finer-grained-fallbacks-ps3-argb32-ref.png \
+ finer-grained-fallbacks-ps2-ref.png \
finer-grained-fallbacks-ps2-rgb24-ref.png \
+ finer-grained-fallbacks-ps3-ref.png \
finer-grained-fallbacks-ps3-rgb24-ref.png \
font-matrix-translation-ps2-argb32-ref.png \
font-matrix-translation-ps3-argb32-ref.png \
diff --git a/test/finer-grained-fallbacks-ps2-argb32-ref.png b/test/finer-grained-fallbacks-ps2-argb32-ref.png
deleted file mode 100644
index 402f01b..0000000
Binary files a/test/finer-grained-fallbacks-ps2-argb32-ref.png and /dev/null differ
diff --git a/test/finer-grained-fallbacks-ps2-ref.png b/test/finer-grained-fallbacks-ps2-ref.png
new file mode 100644
index 0000000..1744100
Binary files /dev/null and b/test/finer-grained-fallbacks-ps2-ref.png differ
diff --git a/test/finer-grained-fallbacks-ps2-rgb24-ref.png b/test/finer-grained-fallbacks-ps2-rgb24-ref.png
index e821344..de48286 100644
Binary files a/test/finer-grained-fallbacks-ps2-rgb24-ref.png and b/test/finer-grained-fallbacks-ps2-rgb24-ref.png differ
diff --git a/test/finer-grained-fallbacks-ps3-argb32-ref.png b/test/finer-grained-fallbacks-ps3-argb32-ref.png
deleted file mode 100644
index 402f01b..0000000
Binary files a/test/finer-grained-fallbacks-ps3-argb32-ref.png and /dev/null differ
diff --git a/test/finer-grained-fallbacks-ps3-ref.png b/test/finer-grained-fallbacks-ps3-ref.png
new file mode 100644
index 0000000..1744100
Binary files /dev/null and b/test/finer-grained-fallbacks-ps3-ref.png differ
diff --git a/test/finer-grained-fallbacks-ps3-rgb24-ref.png b/test/finer-grained-fallbacks-ps3-rgb24-ref.png
index e821344..de48286 100644
Binary files a/test/finer-grained-fallbacks-ps3-rgb24-ref.png and b/test/finer-grained-fallbacks-ps3-rgb24-ref.png differ
diff --git a/test/finer-grained-fallbacks-ref.png b/test/finer-grained-fallbacks-ref.png
index 7dce860..c7eb113 100644
Binary files a/test/finer-grained-fallbacks-ref.png and b/test/finer-grained-fallbacks-ref.png differ
diff --git a/test/finer-grained-fallbacks-rgb24-ref.png b/test/finer-grained-fallbacks-rgb24-ref.png
index 7328482..3b8e9c3 100644
Binary files a/test/finer-grained-fallbacks-rgb24-ref.png and b/test/finer-grained-fallbacks-rgb24-ref.png differ
diff --git a/test/finer-grained-fallbacks.c b/test/finer-grained-fallbacks.c
index f7cd5f3..65bceb4 100644
--- a/test/finer-grained-fallbacks.c
+++ b/test/finer-grained-fallbacks.c
@@ -31,7 +31,7 @@ static cairo_test_draw_function_t draw;
#define CIRCLE_SIZE 10
#define PAD 2
#define WIDTH (CIRCLE_SIZE*6.5 + PAD)
-#define HEIGHT (CIRCLE_SIZE*3.5 + PAD)
+#define HEIGHT (CIRCLE_SIZE*7.0 + PAD)
static const cairo_test_t test = {
"finer-grained-fallbacks",
@@ -51,6 +51,19 @@ draw_circle (cairo_t *cr, double x, double y)
}
static void
+draw_image_circle (cairo_t *cr, cairo_surface_t *source, double x, double y)
+{
+ cairo_save (cr);
+
+ cairo_set_source_surface (cr, source, x, y);
+ cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REFLECT);
+ cairo_rectangle (cr, x, y, CIRCLE_SIZE, CIRCLE_SIZE);
+ cairo_fill (cr);
+
+ cairo_restore (cr);
+}
+
+static void
draw_circles (cairo_t *cr)
{
draw_circle (cr, 0, -CIRCLE_SIZE*0.1);
@@ -61,6 +74,17 @@ draw_circles (cairo_t *cr)
draw_circle (cr, CIRCLE_SIZE*6, 0);
}
+static void
+draw_image_circles (cairo_t *cr, cairo_surface_t *source)
+{
+ draw_image_circle (cr, source, 0, -CIRCLE_SIZE*0.1);
+ draw_image_circle (cr, source, CIRCLE_SIZE*0.4, CIRCLE_SIZE*0.25);
+
+ draw_image_circle (cr, source, CIRCLE_SIZE*2, 0);
+ draw_image_circle (cr, source, CIRCLE_SIZE*4, 0);
+ draw_image_circle (cr, source, CIRCLE_SIZE*6, 0);
+}
+
/* For each of circle and fallback_circle we draw:
* - two overlapping
* - one isolated
@@ -74,12 +98,40 @@ draw_circles (cairo_t *cr)
*
* Fallback circles are drawn in red. CAIRO_OPERATOR_ADD is used to
* ensure they will be emitted as a fallback image in PS/PDF.
+ *
+ * In order to trigger a fallback for SVG, we need to use a surface with
+ * REFLECT.
*/
+static cairo_surface_t *
+surface_create (cairo_t *target)
+{
+ cairo_surface_t *surface;
+ cairo_t *cr;
+
+ surface = cairo_surface_create_similar (cairo_get_target (target),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ CIRCLE_SIZE, CIRCLE_SIZE);
+ cr = cairo_create (surface);
+ cairo_surface_destroy (surface);
+
+ cairo_set_source_rgb (cr, 1.0, 0.0, 0.0);
+ draw_circle (cr, CIRCLE_SIZE/2, CIRCLE_SIZE/2);
+
+ surface = cairo_surface_reference (cairo_get_target (cr));
+ cairo_destroy (cr);
+
+ return surface;
+}
+
static cairo_test_status_t
draw (cairo_t *cr, int width, int height)
{
+ cairo_surface_t *surface;
+
cairo_translate (cr, PAD, PAD);
+ cairo_save (cr);
+
/* Draw overlapping circle and fallback circle */
cairo_set_source_rgb (cr, 0.0, 1.0, 0.0);
cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
@@ -101,6 +153,31 @@ draw (cairo_t *cr, int width, int height)
cairo_translate (cr, 0, CIRCLE_SIZE*2);
draw_circles (cr);
+ cairo_restore (cr);
+ cairo_translate (cr, 0, CIRCLE_SIZE * 3.5);
+
+ /* Draw using fallback surface */
+ surface = surface_create (cr);
+
+ cairo_set_source_rgb (cr, 0.0, 1.0, 0.0);
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ draw_circle (cr, CIRCLE_SIZE*0.5, CIRCLE_SIZE*1.5);
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
+ draw_image_circle (cr, surface, CIRCLE_SIZE/4, CIRCLE_SIZE + CIRCLE_SIZE/4);
+
+ /* Draw circles */
+ cairo_set_source_rgb (cr, 0.0, 1.0, 0.0);
+ cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
+ cairo_translate (cr, CIRCLE_SIZE*2.5, CIRCLE_SIZE*0.6);
+ draw_circles (cr);
+
+ cairo_set_operator (cr, CAIRO_OPERATOR_ADD);
+ cairo_translate (cr, -CIRCLE_SIZE/2, CIRCLE_SIZE*1.5);
+ draw_image_circles (cr, surface);
+
+ cairo_surface_destroy (surface);
+
return CAIRO_TEST_SUCCESS;
}
More information about the cairo-commit
mailing list