[cairo-commit] cairo/src cairo-array.c, 1.8,
1.9 cairo-meta-surface-private.h, 1.7,
1.8 cairo-meta-surface.c, 1.17, 1.18 cairo-ps-surface.c, 1.61,
1.62 cairo-surface.c, 1.112, 1.113 cairoint.h, 1.229, 1.230
Carl Worth
commit at pdx.freedesktop.org
Wed Dec 7 12:19:12 PST 2005
Committed by: cworth
Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv16041/src
Modified Files:
cairo-array.c cairo-meta-surface-private.h
cairo-meta-surface.c cairo-ps-surface.c cairo-surface.c
cairoint.h
Log Message:
2005-12-07 Carl Worth <cworth at cworth.org>
* ROADMAP: Note that self-copy now works with the PS backend.
* src/cairo-array.c: (_cairo_array_init),
(_cairo_array_init_snapshot), (_cairo_array_fini),
(_cairo_array_grow_by), (_cairo_array_truncate),
(_cairo_array_append), (_cairo_array_append_multiple),
(_cairo_array_allocate): Add _cairo_array_init_snapshot and checks
for is_snapshot throughout.
* src/cairoint.h:
* src/cairo-surface.c: (_cairo_surface_acquire_source_image),
(_fallback_snapshot), (_cairo_surface_snapshot): Add a new
surface->backend->snapshot function.
* src/cairo-meta-surface-private.h:
* src/cairo-meta-surface.c: (_cairo_meta_surface_create),
(_cairo_meta_surface_create_similar), (_cairo_meta_surface_finish),
(_cairo_meta_surface_acquire_source_image),
(_cairo_meta_surface_release_source_image),
(_cairo_meta_surface_snapshot), (_cairo_meta_surface_get_extents):
Implement _cairo_meta_surface_snapshot and
_cairo_meta_surface_acquire/release_source_image. Change
_cairo_meta_surface_create to require the width and height in
pixels to be used when replaying for purposed of
_cairo_meta_surface_aquire_source_image.
* src/cairo-ps-surface.c:
(_cairo_ps_surface_create_for_stream_internal),
(_cairo_ps_surface_show_page), (_cairo_ps_surface_snapshot),
(_ps_output_old_show_glyphs): Track change in prototype of
_cairo_meta_surface_create. Implement _cairo_ps_surface_snapshot
by deferring down into _cairo_meta_surface_snapshot.
Index: cairo-array.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-array.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- cairo-array.c 7 Nov 2005 21:23:32 -0000 1.8
+++ cairo-array.c 7 Dec 2005 20:19:10 -0000 1.9
@@ -58,6 +58,29 @@
array->num_elements = 0;
array->element_size = element_size;
array->elements = NULL;
+
+ array->is_snapshot = FALSE;
+}
+
+/**
+ * _cairo_array_init_snapshot:
+ * @array: A #cairo_array_t to be initialized as a snapshot
+ * @other: The #cairo_array_t from which to create the snapshot
+ *
+ * Initialize @array as an immutable copy of @other. It is an error to
+ * call an array-modifying function (other than _cairo_array_fini) on
+ * @array after calling this function.
+ **/
+void
+_cairo_array_init_snapshot (cairo_array_t *array,
+ const cairo_array_t *other)
+{
+ array->size = other->size;
+ array->num_elements = other->num_elements;
+ array->element_size = other->element_size;
+ array->elements = other->elements;
+
+ array->is_snapshot = TRUE;
}
/**
@@ -70,6 +93,9 @@
void
_cairo_array_fini (cairo_array_t *array)
{
+ if (array->is_snapshot)
+ return;
+
free (array->elements);
}
@@ -88,6 +114,8 @@
int required_size = array->num_elements + additional;
int new_size;
+ assert (! array->is_snapshot);
+
if (required_size <= old_size)
return CAIRO_STATUS_SUCCESS;
@@ -123,6 +151,8 @@
void
_cairo_array_truncate (cairo_array_t *array, int num_elements)
{
+ assert (! array->is_snapshot);
+
if (num_elements < array->num_elements)
array->num_elements = num_elements;
}
@@ -184,6 +214,8 @@
_cairo_array_append (cairo_array_t *array,
const void *element)
{
+ assert (! array->is_snapshot);
+
return _cairo_array_append_multiple (array, element, 1);
}
@@ -206,6 +238,8 @@
cairo_status_t status;
void *dest;
+ assert (! array->is_snapshot);
+
status = _cairo_array_allocate (array, num_elements, &dest);
if (status)
return status;
@@ -234,6 +268,8 @@
{
cairo_status_t status;
+ assert (! array->is_snapshot);
+
status = _cairo_array_grow_by (array, num_elements);
if (status)
return status;
Index: cairo-meta-surface-private.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-meta-surface-private.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- cairo-meta-surface-private.h 9 Nov 2005 01:16:21 -0000 1.7
+++ cairo-meta-surface-private.h 7 Dec 2005 20:19:10 -0000 1.8
@@ -179,13 +179,21 @@
typedef struct _cairo_meta_surface {
cairo_surface_t base;
+
+ /* 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;
+
cairo_array_t commands;
+ cairo_surface_t *commands_owner;
} cairo_meta_surface_t;
cairo_private cairo_surface_t *
-_cairo_meta_surface_create (void);
+_cairo_meta_surface_create (int width_pixels, int height_pixels);
-cairo_private cairo_int_status_t
+cairo_private cairo_status_t
_cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target);
Index: cairo-meta-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-meta-surface.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -d -r1.17 -r1.18
--- cairo-meta-surface.c 9 Nov 2005 01:16:21 -0000 1.17
+++ cairo-meta-surface.c 7 Dec 2005 20:19:10 -0000 1.18
@@ -41,7 +41,7 @@
static const cairo_surface_backend_t cairo_meta_surface_backend;
cairo_surface_t *
-_cairo_meta_surface_create (void)
+_cairo_meta_surface_create (int width_pixels, int height_pixels)
{
cairo_meta_surface_t *meta;
@@ -52,7 +52,12 @@
}
_cairo_surface_init (&meta->base, &cairo_meta_surface_backend);
+
+ meta->width_pixels = width_pixels;
+ meta->height_pixels = height_pixels;
+
_cairo_array_init (&meta->commands, sizeof (cairo_command_t *));
+ meta->commands_owner = NULL;
return &meta->base;
}
@@ -63,7 +68,7 @@
int width,
int height)
{
- return _cairo_meta_surface_create ();
+ return _cairo_meta_surface_create (width, height);
}
static cairo_status_t
@@ -74,6 +79,11 @@
cairo_command_t **elements;
int i, num_elements;
+ if (meta->commands_owner) {
+ cairo_surface_destroy (meta->commands_owner);
+ return CAIRO_STATUS_SUCCESS;
+ }
+
num_elements = meta->commands.num_elements;
elements = (cairo_command_t **) meta->commands.elements;
for (i = 0; i < num_elements; i++) {
@@ -150,6 +160,39 @@
}
static cairo_status_t
+_cairo_meta_surface_acquire_source_image (void *abstract_surface,
+ cairo_image_surface_t **image_out,
+ void **image_extra)
+{
+ cairo_status_t status;
+ cairo_meta_surface_t *surface = abstract_surface;
+ cairo_surface_t *image;
+
+ image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+ surface->width_pixels,
+ surface->height_pixels);
+
+ status = _cairo_meta_surface_replay (&surface->base, image);
+ if (status) {
+ cairo_surface_destroy (image);
+ return status;
+ }
+
+ *image_out = (cairo_image_surface_t *) image;
+ *image_extra = NULL;
+
+ return status;
+}
+
+static void
+_cairo_meta_surface_release_source_image (void *abstract_surface,
+ cairo_image_surface_t *image,
+ void *image_extra)
+{
+ cairo_surface_destroy (&image->base);
+}
+
+static cairo_status_t
_init_pattern_with_snapshot (cairo_pattern_t *pattern,
const cairo_pattern_t *other)
{
@@ -397,6 +440,43 @@
return status;
}
+/**
+ * _cairo_meta_surface_snapshot
+ * @surface: a #cairo_surface_t which must be a meta surface
+ *
+ * Make an immutable copy of @surface. It is an error to call a
+ * surface-modifying function on the result of this function.
+ *
+ * The caller owns the return value and should call
+ * cairo_surface_destroy when finished with it. This function will not
+ * return NULL, but will return a nil surface instead.
+ *
+ * Return value: The snapshot surface.
+ **/
+static cairo_surface_t *
+_cairo_meta_surface_snapshot (void *abstract_other)
+{
+ cairo_meta_surface_t *other = abstract_other;
+ cairo_meta_surface_t *meta;
+
+ meta = malloc (sizeof (cairo_meta_surface_t));
+ if (meta == NULL) {
+ _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ return (cairo_surface_t*) &_cairo_surface_nil;
+ }
+
+ _cairo_surface_init (&meta->base, &cairo_meta_surface_backend);
+ meta->base.is_snapshot = TRUE;
+
+ meta->width_pixels = other->width_pixels;
+ meta->height_pixels = other->height_pixels;
+
+ _cairo_array_init_snapshot (&meta->commands, &other->commands);
+ meta->commands_owner = cairo_surface_reference (&other->base);
+
+ return &meta->base;
+}
+
static cairo_int_status_t
_cairo_meta_surface_composite (cairo_operator_t operator,
cairo_pattern_t *src_pattern,
@@ -594,6 +674,26 @@
return CAIRO_STATUS_SUCCESS;
}
+/* A meta-surface is logically unbounded, but when it is used as a
+ * source, the drawing code can optimize based on the extents of the
+ * surface.
+ *
+ * XXX: The optimization being attempted here would only actually work
+ * if the meta-surface kept track of its extents as commands were
+ * added to it.
+ */
+static cairo_int_status_t
+_cairo_meta_surface_get_extents (void *abstract_surface,
+ cairo_rectangle_t *rectangle)
+{
+ rectangle->x = 0;
+ rectangle->y = 0;
+ rectangle->width = CAIRO_MAXSHORT;
+ rectangle->height = CAIRO_MAXSHORT;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
/**
* _cairo_surface_is_meta:
* @surface: a #cairo_surface_t
@@ -611,8 +711,8 @@
static const cairo_surface_backend_t cairo_meta_surface_backend = {
_cairo_meta_surface_create_similar,
_cairo_meta_surface_finish,
- NULL, /* acquire_source_image */
- NULL, /* release_source_image */
+ _cairo_meta_surface_acquire_source_image,
+ _cairo_meta_surface_release_source_image,
NULL, /* acquire_dest_image */
NULL, /* release_dest_image */
NULL, /* clone_similar */
@@ -623,7 +723,7 @@
NULL, /* show_page */
NULL, /* set_clip_region */
_cairo_meta_surface_intersect_clip_path,
- NULL, /* get_extents */
+ _cairo_meta_surface_get_extents,
NULL, /* old_show_glyphs */
NULL, /* get_font_options */
NULL, /* flush */
@@ -639,10 +739,12 @@
_cairo_meta_surface_mask,
_cairo_meta_surface_stroke,
_cairo_meta_surface_fill,
- _cairo_meta_surface_show_glyphs
+ _cairo_meta_surface_show_glyphs,
+
+ _cairo_meta_surface_snapshot
};
-cairo_int_status_t
+cairo_status_t
_cairo_meta_surface_replay (cairo_surface_t *surface,
cairo_surface_t *target)
{
Index: cairo-ps-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-ps-surface.c,v
retrieving revision 1.61
retrieving revision 1.62
diff -u -d -r1.61 -r1.62
--- cairo-ps-surface.c 9 Nov 2005 01:43:14 -0000 1.61
+++ cairo-ps-surface.c 7 Dec 2005 20:19:10 -0000 1.62
@@ -106,7 +106,8 @@
surface->base.device_x_scale = surface->x_dpi / 72.0;
surface->base.device_y_scale = surface->y_dpi / 72.0;
- surface->current_page = _cairo_meta_surface_create ();
+ surface->current_page = _cairo_meta_surface_create (width * surface->x_dpi / 72,
+ height * surface->y_dpi / 72);
if (surface->current_page->status) {
free (surface);
_cairo_error (CAIRO_STATUS_NO_MEMORY);
@@ -343,7 +344,8 @@
if (status)
return status;
- surface->current_page = _cairo_meta_surface_create ();
+ surface->current_page = _cairo_meta_surface_create (surface->width * surface->x_dpi / 72,
+ surface->height * surface->y_dpi / 72);
if (surface->current_page->status)
return CAIRO_STATUS_NO_MEMORY;
@@ -549,6 +551,16 @@
scaled_font);
}
+static cairo_surface_t *
+_cairo_ps_surface_snapshot (void *abstract_surface)
+{
+ cairo_ps_surface_t *surface = abstract_surface;
+
+ assert (_cairo_surface_is_meta (surface->current_page));
+
+ return _cairo_surface_snapshot (surface->current_page);
+}
+
static const cairo_surface_backend_t cairo_ps_surface_backend = {
NULL, /* create_similar */
_cairo_ps_surface_finish,
@@ -578,7 +590,9 @@
_cairo_ps_surface_mask,
_cairo_ps_surface_stroke,
_cairo_ps_surface_fill,
- _cairo_ps_surface_show_glyphs
+ _cairo_ps_surface_show_glyphs,
+
+ _cairo_ps_surface_snapshot
};
static cairo_int_status_t
@@ -1400,6 +1414,9 @@
if (! _cairo_scaled_font_is_ft (scaled_font))
return CAIRO_INT_STATUS_UNSUPPORTED;
+ if (surface->fallback)
+ return CAIRO_STATUS_SUCCESS;
+
if (pattern_operation_needs_fallback (operator, pattern))
return _ps_output_add_fallback_area (surface, dest_x, dest_y, width, height);
Index: cairo-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-surface.c,v
retrieving revision 1.112
retrieving revision 1.113
diff -u -d -r1.112 -r1.113
--- cairo-surface.c 9 Nov 2005 01:16:21 -0000 1.112
+++ cairo-surface.c 7 Dec 2005 20:19:10 -0000 1.113
@@ -581,7 +581,8 @@
{
assert (!surface->finished);
- return surface->backend->acquire_source_image (surface, image_out, image_extra);
+ return surface->backend->acquire_source_image (surface,
+ image_out, image_extra);
}
/**
@@ -722,21 +723,11 @@
return status;
}
-/**
- * _cairo_surface_snapshot
- * @surface: a #cairo_surface_t
- * @snapshot_out: return value surface---not necessarily of the same type as @surface
- *
- * Make an immutable copy of @surface. It is an error to call a
- * surface-modifying function on the result of this function.
- *
- * The caller owns the return value and should call
- * cairo_surface_destroy when finished with it. This function will not
- * return NULL, but will return a nil surface instead.
- **/
-cairo_surface_t *
-_cairo_surface_snapshot (cairo_surface_t *surface)
+/* XXX: Shouldn't really need to do this here. */
+#include "cairo-meta-surface-private.h"
+static cairo_surface_t *
+_fallback_snapshot (cairo_surface_t *surface)
{
cairo_surface_t *snapshot;
cairo_status_t status;
@@ -744,12 +735,6 @@
cairo_image_surface_t *image;
void *image_extra;
- if (surface->finished)
- return (cairo_surface_t *) &_cairo_surface_nil;
-
- /* XXX: Will need to do something very different here to snapshot
- * a meta-surface. */
-
status = _cairo_surface_acquire_source_image (surface,
&image, &image_extra);
if (status != CAIRO_STATUS_SUCCESS)
@@ -783,6 +768,32 @@
return snapshot;
}
+/**
+ * _cairo_surface_snapshot
+ * @surface: a #cairo_surface_t
+ *
+ * Make an immutable copy of @surface. It is an error to call a
+ * surface-modifying function on the result of this function.
+ *
+ * The caller owns the return value and should call
+ * cairo_surface_destroy when finished with it. This function will not
+ * return NULL, but will return a nil surface instead.
+ *
+ * Return value: The snapshot surface. Note that the return surface
+ * may not necessarily be of the same type as @surface.
+ **/
+cairo_surface_t *
+_cairo_surface_snapshot (cairo_surface_t *surface)
+{
+ if (surface->finished)
+ return (cairo_surface_t *) &_cairo_surface_nil;
+
+ if (surface->backend->snapshot)
+ return surface->backend->snapshot (surface);
+
+ return _fallback_snapshot (surface);
+}
+
typedef struct {
cairo_surface_t *dst;
cairo_rectangle_t extents;
Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.229
retrieving revision 1.230
diff -u -d -r1.229 -r1.230
--- cairoint.h 9 Nov 2005 01:43:14 -0000 1.229
+++ cairoint.h 7 Dec 2005 20:19:10 -0000 1.230
@@ -318,11 +318,17 @@
int num_elements;
int element_size;
char *elements;
+
+ cairo_bool_t is_snapshot;
};
cairo_private void
_cairo_array_init (cairo_array_t *array, int element_size);
+void
+_cairo_array_init_snapshot (cairo_array_t *array,
+ const cairo_array_t *other);
+
cairo_private void
_cairo_array_fini (cairo_array_t *array);
@@ -790,6 +796,9 @@
const cairo_glyph_t *glyphs,
int num_glyphs,
cairo_scaled_font_t *scaled_font);
+
+ cairo_surface_t *
+ (*snapshot) (void *surface);
};
typedef struct _cairo_format_masks {
@@ -1843,6 +1852,9 @@
cairo_private cairo_bool_t
_cairo_surface_is_image (const cairo_surface_t *surface);
+cairo_private cairo_bool_t
+_cairo_surface_is_meta (const cairo_surface_t *surface);
+
/* cairo_pen.c */
cairo_private cairo_status_t
_cairo_pen_init (cairo_pen_t *pen,
More information about the cairo-commit
mailing list