Export meta-surface

The meta-surface is a vital tool to record a trace of drawing commands
in-memory. As such it is used throughout cairo.

The value of such a surface is immediately obvious and should be
applicable for many applications. The first such case is by
cairo-test-trace which wants to record the entire graph of drawing commands
that affect a surface in the event of a failure.
This commit is contained in:
Chris Wilson 2009-07-03 18:26:50 +01:00
parent 2a9903dbbf
commit 6003ab77e1
25 changed files with 296 additions and 156 deletions

27
NEWS
View file

@ -1,3 +1,30 @@
Snapshot 1.9.4 (2009-07-xx)
===========================
API additions:
cairo_meta_surface_create()
cairo_meta_surface_ink_extents()
cairo_meta_surface_replay()
Finally exporting the internal meta-surface so that applications
have a method to record and replay a sequence of drawing commands.
New utilities:
cairo-test-trace
A companion to cairo-perf-trace, this utility replays a trace against
multiple targets in parallel and looks for differences in the output,
and then records any drawing commands that cause a failure.
Future plans:
Further minimisation of the fail trace using "delta debugging".
More control over test/reference targets.
New experimental backends:
QT
Snapshot 1.9.2 (2009-06-12)
===========================
API additions:

View file

@ -234,6 +234,14 @@ enabled_cairo_boilerplate_headers += $(cairo_boilerplate_image_headers)
enabled_cairo_boilerplate_private += $(cairo_boilerplate_image_private)
enabled_cairo_boilerplate_sources += $(cairo_boilerplate_image_sources)
supported_cairo_boilerplate_headers += $(cairo_boilerplate_meta_headers)
all_cairo_boilerplate_headers += $(cairo_boilerplate_meta_headers)
all_cairo_boilerplate_private += $(cairo_boilerplate_meta_private)
all_cairo_boilerplate_sources += $(cairo_boilerplate_meta_sources)
enabled_cairo_boilerplate_headers += $(cairo_boilerplate_meta_headers)
enabled_cairo_boilerplate_private += $(cairo_boilerplate_meta_private)
enabled_cairo_boilerplate_sources += $(cairo_boilerplate_meta_sources)
supported_cairo_boilerplate_headers += $(cairo_boilerplate_user_headers)
all_cairo_boilerplate_headers += $(cairo_boilerplate_user_headers)
all_cairo_boilerplate_private += $(cairo_boilerplate_user_private)

View file

@ -526,7 +526,7 @@ static const cairo_boilerplate_target_t targets[] =
},
{
"win32-printing", "win32", ".ps", NULL,
CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
CAIRO_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
_cairo_boilerplate_win32_printing_create_surface,
NULL, NULL,
_cairo_boilerplate_win32_printing_get_image_surface,
@ -613,7 +613,7 @@ static const cairo_boilerplate_target_t targets[] =
},
{
"ps2", "ps", ".ps", NULL,
CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
CAIRO_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
_cairo_boilerplate_ps2_create_surface,
_cairo_boilerplate_ps_force_fallbacks,
_cairo_boilerplate_ps_finish_surface,
@ -636,7 +636,7 @@ static const cairo_boilerplate_target_t targets[] =
},
{
"ps3", "ps", ".ps", NULL,
CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
CAIRO_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
_cairo_boilerplate_ps3_create_surface,
_cairo_boilerplate_ps_force_fallbacks,
_cairo_boilerplate_ps_finish_surface,
@ -661,7 +661,7 @@ static const cairo_boilerplate_target_t targets[] =
},
{
"pdf", "pdf", ".pdf", NULL,
CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
CAIRO_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
_cairo_boilerplate_pdf_create_surface,
_cairo_boilerplate_pdf_force_fallbacks,
_cairo_boilerplate_pdf_finish_surface,
@ -703,7 +703,7 @@ static const cairo_boilerplate_target_t targets[] =
},
{
"svg11", "svg", NULL, NULL,
CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
CAIRO_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
_cairo_boilerplate_svg11_create_surface,
_cairo_boilerplate_svg_force_fallbacks,
_cairo_boilerplate_svg_finish_surface,
@ -725,7 +725,7 @@ static const cairo_boilerplate_target_t targets[] =
},
{
"svg12", "svg", NULL, NULL,
CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
CAIRO_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
_cairo_boilerplate_svg12_create_surface,
_cairo_boilerplate_svg_force_fallbacks,
_cairo_boilerplate_svg_finish_surface,

View file

@ -69,5 +69,6 @@ ifeq ($(CAIRO_HAS_TEST_SURFACES),1)
@echo "#define CAIRO_HAS_TEST_SURFACES 1" >> src/cairo-features.h
endif
@echo "#define CAIRO_HAS_IMAGE_SURFACE 1" >> src/cairo-features.h
@echo "#define CAIRO_HAS_META_SURFACE 1" >> src/cairo-features.h
@echo "#define CAIRO_HAS_USER_FONT 1" >> src/cairo-features.h
@echo "#endif" >> src/cairo-features.h

View file

@ -361,6 +361,7 @@ AC_DEFUN([CAIRO_REPORT],
echo ""
echo "The following surface backends:"
echo " Image: yes (always builtin)"
echo " Meta: yes (always builtin)"
echo " Xlib: $use_xlib"
echo " Xlib Xrender: $use_xlib_xrender"
echo " Qt: $use_qt"

View file

@ -472,6 +472,10 @@ CAIRO_ENABLE_SURFACE_BACKEND(image, image, always, [
dnl ===========================================================================
CAIRO_ENABLE_SURFACE_BACKEND(meta, meta, always)
dnl ===========================================================================
CAIRO_ENABLE_FONT_BACKEND(user, user, always)
dnl ===========================================================================

View file

@ -68,7 +68,7 @@ const cairo_perf_case_t perf_cases[];
static cairo_bool_t
target_is_measurable (const cairo_boilerplate_target_t *target)
{
switch (target->expected_type) {
switch ((int) target->expected_type) {
case CAIRO_SURFACE_TYPE_IMAGE:
if (strcmp (target->name, "pdf") == 0 ||
strcmp (target->name, "ps") == 0)
@ -102,9 +102,7 @@ target_is_measurable (const cairo_boilerplate_target_t *target)
case CAIRO_SURFACE_TYPE_QT:
#endif
return TRUE;
case CAIRO_SURFACE_TYPE_PDF:
case CAIRO_SURFACE_TYPE_PS:
case CAIRO_SURFACE_TYPE_SVG:
default:
return FALSE;
}

View file

@ -316,6 +316,14 @@ enabled_cairo_headers += $(cairo_image_headers)
enabled_cairo_private += $(cairo_image_private)
enabled_cairo_sources += $(cairo_image_sources)
supported_cairo_headers += $(cairo_meta_headers)
all_cairo_headers += $(cairo_meta_headers)
all_cairo_private += $(cairo_meta_private)
all_cairo_sources += $(cairo_meta_sources)
enabled_cairo_headers += $(cairo_meta_headers)
enabled_cairo_private += $(cairo_meta_private)
enabled_cairo_sources += $(cairo_meta_sources)
supported_cairo_headers += $(cairo_user_headers)
all_cairo_headers += $(cairo_user_headers)
all_cairo_private += $(cairo_user_private)

View file

@ -150,8 +150,9 @@ typedef struct _cairo_meta_surface {
/* A meta-surface is logically unbounded, but when used as a
* source we need to render it to an image, so we need a size at
* which to create that image. */
int width_pixels;
int height_pixels;
double width_pixels;
double height_pixels;
cairo_rectangle_int_t extents;
cairo_array_t commands;
cairo_surface_t *commands_owner;
@ -160,18 +161,13 @@ typedef struct _cairo_meta_surface {
int replay_start_idx;
} cairo_meta_surface_t;
cairo_private cairo_surface_t *
_cairo_meta_surface_create (cairo_content_t content,
int width_pixels,
int height_pixels);
slim_hidden_proto (cairo_meta_surface_create);
slim_hidden_proto (cairo_meta_surface_replay);
cairo_private cairo_int_status_t
_cairo_meta_surface_get_path (cairo_surface_t *surface,
cairo_path_fixed_t *path);
cairo_private cairo_status_t
_cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target);
cairo_private cairo_status_t
_cairo_meta_surface_replay_analyze_meta_pattern (cairo_surface_t *surface,

View file

@ -42,7 +42,9 @@
* level of paint, mask, stroke, fill, and show_text_glyphs). The meta
* surface can then be "replayed" against any target surface with:
*
* _cairo_meta_surface_replay (meta, target);
* <informalexample><programlisting>
* cairo_meta_surface_replay (meta, target);
* </programlisting></informalexample>
*
* after which the results in target will be identical to the results
* that would have been obtained if the original operations applied to
@ -57,6 +59,7 @@
*/
#include "cairoint.h"
#include "cairo-analysis-surface-private.h"
#include "cairo-meta-surface-private.h"
#include "cairo-clip-private.h"
@ -73,13 +76,38 @@ static const cairo_surface_backend_t cairo_meta_surface_backend;
*
* XXX: The naming of "pixels" in the size here is a misnomer. It's
* actually a size in whatever device-space units are desired (again,
* according to the intended replay target). This should likely also
* be changed to use doubles not ints.
* according to the intended replay target).
*/
/**
* cairo_meta_surface_create:
* @content: the content of the meta surface
* @width_pixels: width of the surface, in pixels
* @height_pixels: height of the surface, in pixels
*
* Creates a meta-surface which can be used to record all drawing operations
* at the highest level (that is, the level of paint, mask, stroke, fill
* and show_text_glyphs). The meta surface can then be "replayed" against
* any target surface with:
*
* <informalexample><programlisting>
* cairo_meta_surface_replay (meta, target);
* </programlisting></informalexample>
*
* after which the results in target will be identical to the results
* that would have been obtained if the original operations applied to
* the meta surface had instead been applied to the target surface.
*
* The recording phase of the meta surface is careful to snapshot all
* necessary objects (paths, patterns, etc.), in order to achieve
* accurate replay.
*
* Since 1.10
**/
cairo_surface_t *
_cairo_meta_surface_create (cairo_content_t content,
int width_pixels,
int height_pixels)
cairo_meta_surface_create (cairo_content_t content,
double width_pixels,
double height_pixels)
{
cairo_meta_surface_t *meta;
@ -94,6 +122,29 @@ _cairo_meta_surface_create (cairo_content_t content,
meta->width_pixels = width_pixels;
meta->height_pixels = height_pixels;
/* unbounded -> 'infinite' extents */
if (width_pixels < 0) {
meta->extents.x = CAIRO_RECT_INT_MIN;
meta->extents.width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
} else {
meta->extents.x = 0;
if (ceil (width_pixels) > CAIRO_RECT_INT_MAX)
meta->extents.width = CAIRO_RECT_INT_MAX;
else
meta->extents.width = ceil (width_pixels);
}
if (height_pixels < 0) {
meta->extents.y = CAIRO_RECT_INT_MIN;
meta->extents.height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
} else {
meta->extents.y = 0;
if (ceil (height_pixels) > CAIRO_RECT_INT_MAX)
meta->extents.height = CAIRO_RECT_INT_MAX;
else
meta->extents.height = ceil (height_pixels);
}
_cairo_array_init (&meta->commands, sizeof (cairo_command_t *));
meta->commands_owner = NULL;
@ -102,6 +153,7 @@ _cairo_meta_surface_create (cairo_content_t content,
return &meta->base;
}
slim_hidden_def (cairo_meta_surface_create);
static cairo_surface_t *
_cairo_meta_surface_create_similar (void *abstract_surface,
@ -109,7 +161,7 @@ _cairo_meta_surface_create_similar (void *abstract_surface,
int width,
int height)
{
return _cairo_meta_surface_create (content, width, height);
return cairo_meta_surface_create (content, width, height);
}
static cairo_status_t
@ -193,10 +245,10 @@ _cairo_meta_surface_acquire_source_image (void *abstract_surface,
cairo_surface_t *image;
image = _cairo_image_surface_create_with_content (surface->content,
surface->width_pixels,
surface->height_pixels);
ceil (surface->width_pixels),
ceil (surface->height_pixels));
status = _cairo_meta_surface_replay (&surface->base, image);
status = cairo_meta_surface_replay (&surface->base, image);
if (unlikely (status)) {
cairo_surface_destroy (image);
return status;
@ -216,6 +268,16 @@ _cairo_meta_surface_release_source_image (void *abstract_surface,
cairo_surface_destroy (&image->base);
}
static void
_draw_command_init (cairo_command_header_t *command,
cairo_command_type_t type,
cairo_meta_surface_t *meta)
{
command->type = type;
command->region = CAIRO_META_REGION_ALL;
command->extents = meta->extents;
}
static cairo_int_status_t
_cairo_meta_surface_paint (void *abstract_surface,
cairo_operator_t op,
@ -230,12 +292,7 @@ _cairo_meta_surface_paint (void *abstract_surface,
if (unlikely (command == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
command->header.type = CAIRO_COMMAND_PAINT;
command->header.region = CAIRO_META_REGION_ALL;
command->header.extents.x = 0;
command->header.extents.y = 0;
command->header.extents.width = meta->width_pixels;
command->header.extents.height = meta->height_pixels;
_draw_command_init (&command->header, CAIRO_COMMAND_PAINT, meta);
command->op = op;
status = _cairo_pattern_init_snapshot (&command->source.base, source);
@ -276,12 +333,7 @@ _cairo_meta_surface_mask (void *abstract_surface,
if (unlikely (command == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
command->header.type = CAIRO_COMMAND_MASK;
command->header.region = CAIRO_META_REGION_ALL;
command->header.extents.x = 0;
command->header.extents.y = 0;
command->header.extents.width = meta->width_pixels;
command->header.extents.height = meta->height_pixels;
_draw_command_init (&command->header, CAIRO_COMMAND_MASK, meta);
command->op = op;
status = _cairo_pattern_init_snapshot (&command->source.base, source);
@ -327,12 +379,7 @@ _cairo_meta_surface_stroke (void *abstract_surface,
if (unlikely (command == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
command->header.type = CAIRO_COMMAND_STROKE;
command->header.region = CAIRO_META_REGION_ALL;
command->header.extents.x = 0;
command->header.extents.y = 0;
command->header.extents.width = meta->width_pixels;
command->header.extents.height = meta->height_pixels;
_draw_command_init (&command->header, CAIRO_COMMAND_STROKE, meta);
command->op = op;
status = _cairo_pattern_init_snapshot (&command->source.base, source);
@ -387,12 +434,7 @@ _cairo_meta_surface_fill (void *abstract_surface,
if (unlikely (command == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
command->header.type = CAIRO_COMMAND_FILL;
command->header.region = CAIRO_META_REGION_ALL;
command->header.extents.x = 0;
command->header.extents.y = 0;
command->header.extents.width = meta->width_pixels;
command->header.extents.height = meta->height_pixels;
_draw_command_init (&command->header, CAIRO_COMMAND_FILL, meta);
command->op = op;
status = _cairo_pattern_init_snapshot (&command->source.base, source);
@ -450,12 +492,7 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface,
if (unlikely (command == NULL))
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
command->header.type = CAIRO_COMMAND_SHOW_TEXT_GLYPHS;
command->header.region = CAIRO_META_REGION_ALL;
command->header.extents.x = 0;
command->header.extents.y = 0;
command->header.extents.width = meta->width_pixels;
command->header.extents.height = meta->height_pixels;
_draw_command_init (&command->header, CAIRO_COMMAND_SHOW_TEXT_GLYPHS, meta);
command->op = op;
status = _cairo_pattern_init_snapshot (&command->source.base, source);
@ -601,7 +638,7 @@ _cairo_meta_surface_intersect_clip_path (void *dst,
/* Currently, we're using as the "size" of a meta surface the largest
* surface size against which the meta-surface is expected to be
* replayed, (as passed in to _cairo_meta_surface_create).
* replayed, (as passed in to cairo_meta_surface_create()).
*/
static cairo_int_status_t
_cairo_meta_surface_get_extents (void *abstract_surface,
@ -609,13 +646,13 @@ _cairo_meta_surface_get_extents (void *abstract_surface,
{
cairo_meta_surface_t *surface = abstract_surface;
if (surface->width_pixels == -1 && surface->height_pixels == -1)
if (surface->width_pixels < 0 || surface->height_pixels < 0)
return CAIRO_INT_STATUS_UNSUPPORTED;
rectangle->x = 0;
rectangle->y = 0;
rectangle->width = surface->width_pixels;
rectangle->height = surface->height_pixels;
rectangle->width = ceil (surface->width_pixels);
rectangle->height = ceil (surface->height_pixels);
return CAIRO_STATUS_SUCCESS;
}
@ -635,7 +672,7 @@ _cairo_surface_is_meta (const cairo_surface_t *surface)
}
static const cairo_surface_backend_t cairo_meta_surface_backend = {
CAIRO_INTERNAL_SURFACE_TYPE_META,
CAIRO_SURFACE_TYPE_META,
_cairo_meta_surface_create_similar,
_cairo_meta_surface_finish,
_cairo_meta_surface_acquire_source_image,
@ -1000,15 +1037,30 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
return _cairo_surface_set_error (surface, status);
}
/**
* cairo_meta_surface_replay:
* @surface: the #cairo_meta_surface_t
* @target: a target #cairo_surface_t onto which to replay the operations
* @width_pixels: width of the surface, in pixels
* @height_pixels: height of the surface, in pixels
*
* A meta surface can be "replayed" against any target surface,
* after which the results in target will be identical to the results
* that would have been obtained if the original operations applied to
* the meta surface had instead been applied to the target surface.
*
* Since 1.10
**/
cairo_status_t
_cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target)
cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target)
{
return _cairo_meta_surface_replay_internal (surface,
target,
CAIRO_META_REPLAY,
CAIRO_META_REGION_ALL);
}
slim_hidden_def (cairo_meta_surface_replay);
/* Replay meta to surface. When the return status of each operation is
* one of %CAIRO_STATUS_SUCCESS, %CAIRO_INT_STATUS_UNSUPPORTED, or
@ -1036,3 +1088,59 @@ _cairo_meta_surface_replay_region (cairo_surface_t *surface,
CAIRO_META_REPLAY,
region);
}
/**
* cairo_meta_surface_ink_extents:
* @surface: a #cairo_meta_surface_t
* @x0: the x-coordinate of the top-left of the ink bounding box
* @y0: the y-coordinate of the top-left of the ink bounding box
* @width: the width of the ink bounding box
* @height: the height of the ink bounding box
*
* Measures the extents of the operations stored within the meta-surface.
* This is useful to compute the required size of an image surface (or
* equivalent) into which to replay the full sequence of drawing operaitions.
*
* Since: 1.10
**/
void
cairo_meta_surface_ink_extents (cairo_surface_t *surface,
double *x0,
double *y0,
double *width,
double *height)
{
cairo_surface_t *null_surface;
cairo_surface_t *analysis_surface;
cairo_status_t status;
cairo_box_t bbox;
memset (&bbox, 0, sizeof (bbox));
if (! _cairo_surface_is_meta (surface)) {
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
goto DONE;
}
null_surface = _cairo_null_surface_create (CAIRO_CONTENT_COLOR_ALPHA);
analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1);
cairo_surface_destroy (null_surface);
status = analysis_surface->status;
if (unlikely (status))
goto DONE;
status = cairo_meta_surface_replay (surface, analysis_surface);
_cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
cairo_surface_destroy (analysis_surface);
DONE:
if (x0)
*x0 = _cairo_fixed_to_double (bbox.p1.x);
if (y0)
*y0 = _cairo_fixed_to_double (bbox.p1.y);
if (width)
*width = _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x);
if (height)
*height = _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y);
}

View file

@ -97,7 +97,7 @@ _cairo_paginated_surface_create (cairo_surface_t *target,
surface->backend = backend;
surface->meta = _cairo_meta_surface_create (content, width, height);
surface->meta = cairo_meta_surface_create (content, width, height);
status = cairo_surface_status (surface->meta);
if (unlikely (status))
goto FAIL_CLEANUP_SURFACE;
@ -148,8 +148,8 @@ _cairo_paginated_surface_set_size (cairo_surface_t *surface,
paginated_surface->height = height;
cairo_surface_destroy (paginated_surface->meta);
paginated_surface->meta = _cairo_meta_surface_create (paginated_surface->content,
width, height);
paginated_surface->meta = cairo_meta_surface_create (paginated_surface->content,
width, height);
status = cairo_surface_status (paginated_surface->meta);
if (unlikely (status))
return _cairo_surface_set_error (surface, status);
@ -222,7 +222,7 @@ _cairo_paginated_surface_acquire_source_image (void *abstract_surface,
extents.width,
extents.height);
status = _cairo_meta_surface_replay (surface->meta, image);
status = cairo_meta_surface_replay (surface->meta, image);
if (unlikely (status)) {
cairo_surface_destroy (image);
return status;
@ -266,7 +266,7 @@ _paint_fallback_image (cairo_paginated_surface_t *surface,
* so we have to do the scaling manually. */
cairo_surface_set_device_offset (image, -x*x_scale, -y*y_scale);
status = _cairo_meta_surface_replay (surface->meta, image);
status = cairo_meta_surface_replay (surface->meta, image);
if (unlikely (status))
goto CLEANUP_IMAGE;
@ -481,9 +481,9 @@ _cairo_paginated_surface_show_page (void *abstract_surface)
cairo_surface_destroy (surface->meta);
surface->meta = _cairo_meta_surface_create (surface->content,
surface->width,
surface->height);
surface->meta = cairo_meta_surface_create (surface->content,
surface->width,
surface->height);
status = cairo_surface_status (surface->meta);
if (unlikely (status))
return status;

View file

@ -1475,7 +1475,7 @@ _cairo_pdf_surface_create_similar (void *abstract_surface,
int width,
int height)
{
return _cairo_meta_surface_create (content, width, height);
return cairo_meta_surface_create (content, width, height);
}
static void

View file

@ -1294,7 +1294,7 @@ _cairo_ps_surface_create_similar (void *abstract_surface,
int width,
int height)
{
return _cairo_meta_surface_create (content, width, height);
return cairo_meta_surface_create (content, width, height);
}
static cairo_status_t

View file

@ -840,7 +840,7 @@ _emit_meta_surface_pattern (cairo_script_surface_t *surface,
if (unlikely (status))
return status;
status = _cairo_meta_surface_replay (source, analysis_surface);
status = cairo_meta_surface_replay (source, analysis_surface);
_cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
cairo_surface_destroy (analysis_surface);
if (unlikely (status))
@ -862,7 +862,7 @@ _emit_meta_surface_pattern (cairo_script_surface_t *surface,
_content_to_string (source->content));
target_push (similar);
status = _cairo_meta_surface_replay (source, &similar->base);
status = cairo_meta_surface_replay (source, &similar->base);
if (unlikely (status)) {
cairo_surface_destroy (&similar->base);
return status;
@ -1145,7 +1145,7 @@ _emit_surface_pattern (cairo_script_surface_t *surface,
source = surface_pattern->surface;
switch ((int) source->type) {
case CAIRO_INTERNAL_SURFACE_TYPE_META:
case CAIRO_SURFACE_TYPE_META:
return _emit_meta_surface_pattern (surface, pattern);
case CAIRO_SURFACE_TYPE_SCRIPT:
return _emit_script_surface_pattern (surface, pattern);
@ -2216,8 +2216,8 @@ _emit_scaled_glyph_vector (cairo_script_surface_t *surface,
old_cr = surface->cr;
_cairo_script_implicit_context_init (&surface->cr);
status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
&surface->base);
status = cairo_meta_surface_replay (scaled_glyph->meta_surface,
&surface->base);
surface->cr = old_cr;
_cairo_output_stream_puts (surface->ctx->stream, "} set set\n");

View file

@ -1517,7 +1517,7 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
cairo_surface_set_device_offset (similar, -src_x, -src_y);
status = _cairo_meta_surface_replay (src, similar);
status = cairo_meta_surface_replay (src, similar);
if (unlikely (status)) {
cairo_surface_destroy (similar);
return status;

View file

@ -856,7 +856,7 @@ _cairo_svg_surface_create_similar (void *abstract_src,
int width,
int height)
{
return _cairo_meta_surface_create (content, width, height);
return cairo_meta_surface_create (content, width, height);
}
static cairo_status_t
@ -1217,7 +1217,7 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
document->owner->x_fallback_resolution,
document->owner->y_fallback_resolution);
status = _cairo_meta_surface_replay (&meta->base, paginated_surface);
status = cairo_meta_surface_replay (&meta->base, paginated_surface);
if (unlikely (status)) {
cairo_surface_destroy (&meta->base);
cairo_surface_destroy (paginated_surface);
@ -1334,8 +1334,8 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
"patternUnits=\"userSpaceOnUse\" "
"width=\"%d\" height=\"%d\"",
pattern_id,
meta_surface->width_pixels,
meta_surface->height_pixels);
(int) ceil (meta_surface->width_pixels),
(int) ceil (meta_surface->height_pixels));
_cairo_svg_surface_emit_transform (output, " patternTransform", &p2u, parent_matrix);
_cairo_output_stream_printf (output, ">\n");
}

View file

@ -425,8 +425,8 @@ _cairo_type3_glyph_surface_analyze_glyph (void *abstract_surface,
goto cleanup;
}
status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
&surface->base);
status = cairo_meta_surface_replay (scaled_glyph->meta_surface,
&surface->base);
if (unlikely (status))
goto cleanup;
@ -520,8 +520,8 @@ _cairo_type3_glyph_surface_emit_glyph (void *abstract_surface,
_cairo_type3_glyph_surface_set_stream (surface, mem_stream);
_cairo_output_stream_printf (surface->stream, "q\n");
status = _cairo_meta_surface_replay (scaled_glyph->meta_surface,
&surface->base);
status = cairo_meta_surface_replay (scaled_glyph->meta_surface,
&surface->base);
status2 = _cairo_pdf_operators_flush (&surface->pdf_operators);
if (status == CAIRO_STATUS_SUCCESS)

View file

@ -162,8 +162,7 @@ typedef enum _cairo_int_status {
} cairo_int_status_t;
typedef enum _cairo_internal_surface_type {
CAIRO_INTERNAL_SURFACE_TYPE_META = 0x1000,
CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED = 0x1000,
CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,

View file

@ -85,7 +85,7 @@ _cairo_user_scaled_font_create_meta_context (cairo_user_scaled_font_t *scaled_fo
CAIRO_CONTENT_COLOR_ALPHA :
CAIRO_CONTENT_ALPHA;
meta_surface = _cairo_meta_surface_create (content, -1, -1);
meta_surface = cairo_meta_surface_create (content, -1, -1);
cr = cairo_create (meta_surface);
cairo_surface_destroy (meta_surface);
@ -158,8 +158,7 @@ _cairo_user_scaled_glyph_init (void *abstract_font,
_cairo_analysis_surface_set_ctm (analysis_surface,
&scaled_font->extent_scale);
status = _cairo_meta_surface_replay (meta_surface,
analysis_surface);
status = cairo_meta_surface_replay (meta_surface, analysis_surface);
_cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
cairo_surface_destroy (analysis_surface);
@ -214,7 +213,7 @@ _cairo_user_scaled_glyph_init (void *abstract_font,
cairo_surface_set_device_offset (surface,
- _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
- _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
status = _cairo_meta_surface_replay (meta_surface, surface);
status = cairo_meta_surface_replay (meta_surface, surface);
if (unlikely (status)) {
cairo_surface_destroy(surface);

View file

@ -1607,7 +1607,7 @@ _cairo_win32_printing_surface_create_similar (void *abstract_surface,
int width,
int height)
{
return _cairo_meta_surface_create (content, width, height);
return cairo_meta_surface_create (content, width, height);
}
static cairo_int_status_t

View file

@ -1890,6 +1890,7 @@ cairo_surface_status (cairo_surface_t *surface);
* @CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: The surface is of type quartz_image
* @CAIRO_SURFACE_TYPE_SCRIPT: The surface is of type script, since 1.10
* @CAIRO_SURFACE_TYPE_QT: The surface is of type Qt, since 1.10
* @CAIRO_SURFACE_TYPE_META: The surface is a meta-type, since 1.10
*
* #cairo_surface_type_t is used to describe the type of a given
* surface. The surface types are also known as "backends" or "surface
@ -1930,7 +1931,8 @@ typedef enum _cairo_surface_type {
CAIRO_SURFACE_TYPE_WIN32_PRINTING,
CAIRO_SURFACE_TYPE_QUARTZ_IMAGE,
CAIRO_SURFACE_TYPE_SCRIPT,
CAIRO_SURFACE_TYPE_QT
CAIRO_SURFACE_TYPE_QT,
CAIRO_SURFACE_TYPE_META
} cairo_surface_type_t;
cairo_public cairo_surface_type_t
@ -2108,6 +2110,24 @@ cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func,
#endif
/* Meta-surface functions */
cairo_public cairo_surface_t *
cairo_meta_surface_create (cairo_content_t content,
double width_pixels,
double height_pixels);
cairo_public void
cairo_meta_surface_ink_extents (cairo_surface_t *surface,
double *x0,
double *y0,
double *width,
double *height);
cairo_public cairo_status_t
cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target);
/* Pattern creation functions */
cairo_public cairo_pattern_t *

View file

@ -136,7 +136,7 @@ _test_meta_surface_show_page (void *abstract_surface)
return status;
}
status = _cairo_meta_surface_replay (surface->meta, surface->image);
status = cairo_meta_surface_replay (surface->meta, surface->image);
if (status)
return status;
@ -338,7 +338,7 @@ _cairo_test_meta_surface_create (cairo_content_t content,
_cairo_surface_init (&surface->base, &test_meta_surface_backend,
content);
surface->meta = _cairo_meta_surface_create (content, width, height);
surface->meta = cairo_meta_surface_create (content, width, height);
status = cairo_surface_status (surface->meta);
if (status)
goto FAIL;
@ -356,15 +356,3 @@ _cairo_test_meta_surface_create (cairo_content_t content,
return _cairo_surface_create_in_error (status);
}
slim_hidden_def (_cairo_test_meta_surface_create);
cairo_status_t
_cairo_test_meta_surface_replay (cairo_surface_t *abstract_surface,
cairo_surface_t *target)
{
test_meta_surface_t *surface = (test_meta_surface_t *) abstract_surface;
if (abstract_surface->backend != &test_meta_surface_backend)
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
return _cairo_meta_surface_replay (surface->meta, target);
}

View file

@ -42,12 +42,8 @@ CAIRO_BEGIN_DECLS
cairo_surface_t *
_cairo_test_meta_surface_create (cairo_content_t content,
int width,
int height);
cairo_status_t
_cairo_test_meta_surface_replay (cairo_surface_t *abstract_surface,
cairo_surface_t *target);
int width,
int height);
CAIRO_END_DECLS

View file

@ -64,9 +64,6 @@
#include <cairo-script.h>
#endif
/* XXX give me a real meta surface! */
#include <test-meta-surface.h>
/* For basename */
#ifdef HAVE_LIBGEN_H
#include <libgen.h>
@ -603,9 +600,6 @@ cleanup_recorder (void *arg)
cairo_surface_finish (thread->surface);
cairo_surface_destroy (thread->surface);
if (thread->target->cleanup)
thread->target->cleanup (thread->closure);
close (thread->sk);
free (thread);
}
@ -628,9 +622,7 @@ record (void *arg)
* 2. Runs in the same process, but separate thread.
*/
static pid_t
spawn_recorder (const char *socket_path,
const cairo_boilerplate_target_t *target,
const char *trace)
spawn_recorder (const char *socket_path, const char *trace)
{
test_runner_thread_t *thread;
pthread_t id;
@ -653,18 +645,13 @@ spawn_recorder (const char *socket_path,
}
thread->base = NULL;
thread->target = target;
thread->target = NULL;
thread->contexts = NULL;
thread->context_id = 0;
thread->trace = trace;
thread->surface = target->create_surface (NULL,
target->content,
1, 1,
1, 1,
CAIRO_BOILERPLATE_MODE_TEST,
0,
&thread->closure);
thread->surface = cairo_meta_surface_create (CAIRO_CONTENT_COLOR_ALPHA,
0, 0);
if (thread->surface == NULL) {
cleanup_recorder (thread);
return -1;
@ -853,7 +840,7 @@ static void
write_images (const char *trace, struct slave *slave, int num_slaves)
{
while (num_slaves--) {
if (slave->image != NULL) {
if (slave->image != NULL && ! slave->is_meta) {
char *filename;
xasprintf (&filename, "%s-%s-fail.png",
@ -887,7 +874,7 @@ write_trace (const char *trace, struct slave *slave)
slave->height);
free (filename);
status = _cairo_test_meta_surface_replay (slave->image, script);
status = cairo_meta_surface_replay (slave->image, script);
cairo_surface_destroy (script);
#endif
}
@ -1179,6 +1166,7 @@ target_is_measurable (const cairo_boilerplate_target_t *target)
case CAIRO_SURFACE_TYPE_SCRIPT:
case CAIRO_SURFACE_TYPE_SVG:
case CAIRO_SURFACE_TYPE_WIN32_PRINTING:
case CAIRO_SURFACE_TYPE_META:
default:
return FALSE;
}
@ -1243,8 +1231,9 @@ _test_trace (test_runner_t *test,
struct error_info *error)
{
const char *shm_path = SHM_PATH_XXX;
const cairo_boilerplate_target_t *target, *image, *meta;
const cairo_boilerplate_target_t *target, *image;
struct slave *slaves, *s;
pid_t slave;
char socket_dir[] = "/tmp/cairo-test-trace.XXXXXX";
char *socket_path;
int sk, fd;
@ -1280,29 +1269,22 @@ _test_trace (test_runner_t *test,
#if HAVE_PTHREAD_H
/* set-up a meta-surface to reconstruct errors */
meta = cairo_boilerplate_get_target_by_name ("test-meta",
CAIRO_CONTENT_COLOR_ALPHA);
if (meta != NULL) {
pid_t slave;
slave = spawn_recorder (socket_path, meta, trace);
if (slave < 0) {
fprintf (stderr, "Unable to create meta surface\n");
goto cleanup_sk;
}
s->pid = slave;
s->is_meta = TRUE;
s->target = meta;
s->fd = -1;
s->reference = NULL;
s++;
slave = spawn_recorder (socket_path, trace);
if (slave < 0) {
fprintf (stderr, "Unable to create meta surface\n");
goto cleanup_sk;
}
s->pid = slave;
s->is_meta = TRUE;
s->target = NULL;
s->fd = -1;
s->reference = NULL;
s++;
#endif
/* spawn slave processes to run the trace */
for (i = 0; i < test->num_targets; i++) {
pid_t slave;
const cairo_boilerplate_target_t *reference;
struct slave *master;

View file

@ -132,10 +132,15 @@ draw (cairo_t *cr, int width, int height)
uses_clip_rects = TRUE;
break;
case CAIRO_SURFACE_TYPE_QUARTZ:
case CAIRO_SURFACE_TYPE_QUARTZ_IMAGE:
case CAIRO_SURFACE_TYPE_PDF:
case CAIRO_SURFACE_TYPE_PS:
case CAIRO_SURFACE_TYPE_SVG:
case CAIRO_SURFACE_TYPE_OS2:
case CAIRO_SURFACE_TYPE_WIN32_PRINTING:
case CAIRO_SURFACE_TYPE_SCRIPT:
case CAIRO_SURFACE_TYPE_QT:
case CAIRO_SURFACE_TYPE_META:
default:
uses_clip_rects = FALSE;
break;