Skip to content

Commit

Permalink
[svg] Use finer-grained fallbacks for SVG 1.2
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Chris Wilson committed Oct 8, 2008
1 parent 0c777a3 commit 565c02a
Show file tree
Hide file tree
Showing 15 changed files with 147 additions and 48 deletions.
9 changes: 6 additions & 3 deletions src/cairo-paginated-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,16 +65,19 @@ 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.
* Will be called at the end of the ANALYZE phase but before the
* 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
Expand Down
47 changes: 17 additions & 30 deletions src/cairo-paginated-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
14 changes: 11 additions & 3 deletions src/cairo-pdf-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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.
*
Expand Down Expand Up @@ -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,
};
8 changes: 8 additions & 0 deletions src/cairo-ps-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
};
34 changes: 25 additions & 9 deletions src/cairo-svg-surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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,

};
4 changes: 2 additions & 2 deletions test/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
Binary file removed test/finer-grained-fallbacks-ps2-argb32-ref.png
Binary file not shown.
Binary file added test/finer-grained-fallbacks-ps2-ref.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/finer-grained-fallbacks-ps2-rgb24-ref.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed test/finer-grained-fallbacks-ps3-argb32-ref.png
Binary file not shown.
Binary file added test/finer-grained-fallbacks-ps3-ref.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/finer-grained-fallbacks-ps3-rgb24-ref.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/finer-grained-fallbacks-ref.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified test/finer-grained-fallbacks-rgb24-ref.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
79 changes: 78 additions & 1 deletion test/finer-grained-fallbacks.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -50,6 +50,19 @@ draw_circle (cairo_t *cr, double x, double y)
cairo_restore (cr);
}

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)
{
Expand All @@ -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
Expand All @@ -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);
Expand All @@ -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;
}

Expand Down

0 comments on commit 565c02a

Please sign in to comment.