[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