diff options
-rw-r--r-- | src/Makefile.sources | 2 | ||||
-rw-r--r-- | src/cairo-gl-operand.c | 55 | ||||
-rw-r--r-- | src/cairo-image-source.c | 95 | ||||
-rw-r--r-- | src/cairo-mime-surface.c | 405 | ||||
-rw-r--r-- | src/cairo-pattern-private.h | 41 | ||||
-rw-r--r-- | src/cairo-pattern.c | 130 | ||||
-rw-r--r-- | src/cairo-pdf-surface.c | 4 | ||||
-rw-r--r-- | src/cairo-ps-surface.c | 5 | ||||
-rw-r--r-- | src/cairo-raster-source-pattern.c | 280 | ||||
-rw-r--r-- | src/cairo-script-surface.c | 32 | ||||
-rw-r--r-- | src/cairo-surface-observer.c | 6 | ||||
-rw-r--r-- | src/cairo-svg-surface.c | 1 | ||||
-rw-r--r-- | src/cairo-xcb-surface-core.c | 1 | ||||
-rw-r--r-- | src/cairo-xcb-surface-render.c | 3 | ||||
-rw-r--r-- | src/cairo.h | 90 | ||||
-rw-r--r-- | test/Makefile.sources | 2 | ||||
-rw-r--r-- | test/raster-source.c (renamed from test/mime-surface.c) | 90 | ||||
-rw-r--r-- | test/reference/raster-source.base.argb32.ref.png (renamed from test/reference/mime-surface.base.argb32.ref.png) | bin | 1209 -> 1209 bytes | |||
-rw-r--r-- | test/reference/raster-source.base.rgb24.ref.png (renamed from test/reference/mime-surface.base.rgb24.ref.png) | bin | 1209 -> 1209 bytes | |||
-rw-r--r-- | test/reference/raster-source.ref.png (renamed from test/reference/mime-surface.ref.png) | bin | 1209 -> 1209 bytes | |||
-rw-r--r-- | test/reference/raster-source.traps.argb32.ref.png (renamed from test/reference/mime-surface.traps.argb32.ref.png) | bin | 1209 -> 1209 bytes | |||
-rw-r--r-- | test/reference/raster-source.traps.rgb24.ref.png (renamed from test/reference/mime-surface.traps.rgb24.ref.png) | bin | 1209 -> 1209 bytes | |||
-rw-r--r-- | util/cairo-trace/trace.c | 27 |
23 files changed, 692 insertions, 577 deletions
diff --git a/src/Makefile.sources b/src/Makefile.sources index 867cc35d..11826317 100644 --- a/src/Makefile.sources +++ b/src/Makefile.sources @@ -165,7 +165,6 @@ cairo_sources = \ cairo-matrix.c \ cairo-mask-compositor.c \ cairo-mesh-pattern-rasterizer.c \ - cairo-mime-surface.c \ cairo-misc.c \ cairo-mono-scan-converter.c \ cairo-mutex.c \ @@ -187,6 +186,7 @@ cairo_sources = \ cairo-polygon.c \ cairo-polygon-intersect.c \ cairo-polygon-reduce.c \ + cairo-raster-source-pattern.c \ cairo-recording-surface.c \ cairo-rectangle.c \ cairo-rectangular-scan-converter.c \ diff --git a/src/cairo-gl-operand.c b/src/cairo-gl-operand.c index 31776ff4..8ff37c8a 100644 --- a/src/cairo-gl-operand.c +++ b/src/cairo-gl-operand.c @@ -197,12 +197,11 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand, cairo_gl_surface_t *dst, const cairo_rectangle_int_t *extents) { - const cairo_surface_pattern_t *src = (cairo_surface_pattern_t *)_src; cairo_status_t status; - cairo_matrix_t m; cairo_gl_surface_t *surface; cairo_gl_context_t *ctx; cairo_surface_attributes_t *attributes; + cairo_surface_t *image; attributes = &operand->texture.attributes; @@ -212,57 +211,34 @@ _cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand, surface = (cairo_gl_surface_t *) _cairo_gl_surface_create_scratch (ctx, - src->surface->content, + CAIRO_CONTENT_COLOR_ALPHA, extents->width, extents->height); - if (src->surface->backend->type == CAIRO_SURFACE_TYPE_IMAGE) { - status = _cairo_gl_surface_draw_image (surface, - (cairo_image_surface_t *)src->surface, - 0, 0, - extents->width, extents->height, - 0, 0); - - attributes->extend = src->base.extend; - attributes->filter = src->base.filter; - } else { - cairo_surface_t *image; - image = cairo_surface_map_to_image (&surface->base, NULL); - status = _cairo_surface_paint (image, CAIRO_OPERATOR_SOURCE, - _src, NULL); - cairo_surface_unmap_image (&surface->base, image); - - attributes->extend = CAIRO_EXTEND_NONE; - attributes->filter = CAIRO_FILTER_NEAREST; + image = cairo_surface_map_to_image (&surface->base, NULL); + status = _cairo_surface_offset_paint (image, -extents->x, -extents->y, + CAIRO_OPERATOR_SOURCE, _src, NULL); + cairo_surface_unmap_image (&surface->base, image); + status = _cairo_gl_context_release (ctx, status); + if (unlikely (status)) { + cairo_surface_destroy (&surface->base); + return status; } - status = _cairo_gl_context_release (ctx, status); + attributes->extend = CAIRO_EXTEND_NONE; + attributes->filter = CAIRO_FILTER_NEAREST; + attributes->has_component_alpha = FALSE; operand->type = CAIRO_GL_OPERAND_TEXTURE; operand->texture.surface = surface; operand->texture.tex = surface->tex; - /* Translate the matrix from - * (unnormalized src -> unnormalized src) to - * (unnormalized dst -> unnormalized src) - */ - attributes->matrix = src->base.matrix; - - /* Translate the matrix from - * (unnormalized dst -> unnormalized src) to - * (unnormalized dst -> normalized src) - */ if (_cairo_gl_device_requires_power_of_two_textures (dst->base.device)) { - cairo_matrix_init_scale (&m, - 1.0, - 1.0); + cairo_matrix_init_identity (&attributes->matrix); } else { - cairo_matrix_init_scale (&m, + cairo_matrix_init_scale (&attributes->matrix, 1.0 / surface->width, 1.0 / surface->height); } - cairo_matrix_multiply (&attributes->matrix, - &attributes->matrix, - &m); return CAIRO_STATUS_SUCCESS; } @@ -447,6 +423,7 @@ _cairo_gl_operand_init (cairo_gl_operand_t *operand, default: case CAIRO_PATTERN_TYPE_MESH: + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: break; } diff --git a/src/cairo-image-source.c b/src/cairo-image-source.c index cdf9a7f7..26f245a3 100644 --- a/src/cairo-image-source.c +++ b/src/cairo-image-source.c @@ -889,6 +889,96 @@ _pixman_image_for_surface (cairo_image_surface_t *dst, return pixman_image; } +struct raster_source_cleanup { + const cairo_pattern_t *pattern; + cairo_surface_t *surface; + cairo_image_surface_t *image; + void *image_extra; +}; + +static void +_raster_source_cleanup (pixman_image_t *pixman_image, + void *closure) +{ + struct raster_source_cleanup *data = closure; + + _cairo_surface_release_source_image (data->surface, + data->image, + data->image_extra); + + _cairo_raster_source_pattern_release (data->pattern, + data->surface); + + free (data); +} + +static pixman_image_t * +_pixman_image_for_raster (cairo_image_surface_t *dst, + const cairo_raster_source_pattern_t *pattern, + cairo_bool_t is_mask, + const cairo_rectangle_int_t *extents, + const cairo_rectangle_int_t *sample, + int *ix, int *iy) +{ + pixman_image_t *pixman_image; + struct raster_source_cleanup *cleanup; + cairo_image_surface_t *image; + void *extra; + cairo_status_t status; + cairo_surface_t *surface; + + *ix = *iy = 0; + + surface = _cairo_raster_source_pattern_acquire (&pattern->base, + &dst->base, NULL); + if (unlikely (surface == NULL || surface->status)) + return NULL; + + status = _cairo_surface_acquire_source_image (surface, &image, &extra); + if (unlikely (status)) { + _cairo_raster_source_pattern_release (&pattern->base, surface); + return NULL; + } + + assert (image->width == pattern->extents.width); + assert (image->height == pattern->extents.height); + + pixman_image = pixman_image_create_bits (image->pixman_format, + image->width, + image->height, + (uint32_t *) image->data, + image->stride); + if (unlikely (pixman_image == NULL)) { + _cairo_surface_release_source_image (surface, image, extra); + _cairo_raster_source_pattern_release (&pattern->base, surface); + return NULL; + } + + cleanup = malloc (sizeof (*cleanup)); + if (unlikely (cleanup == NULL)) { + pixman_image_unref (pixman_image); + _cairo_surface_release_source_image (surface, image, extra); + _cairo_raster_source_pattern_release (&pattern->base, surface); + return NULL; + } + + cleanup->pattern = &pattern->base; + cleanup->surface = surface; + cleanup->image = image; + cleanup->image_extra = extra; + pixman_image_set_destroy_function (pixman_image, + _raster_source_cleanup, cleanup); + + if (! _pixman_image_set_properties (pixman_image, + &pattern->base, extents, + ix, iy)) { + pixman_image_unref (pixman_image); + pixman_image= NULL; + } + + return pixman_image; +} + pixman_image_t * _pixman_image_for_pattern (cairo_image_surface_t *dst, const cairo_pattern_t *pattern, @@ -923,6 +1013,11 @@ _pixman_image_for_pattern (cairo_image_surface_t *dst, is_mask, extents, sample, tx, ty); + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + return _pixman_image_for_raster (dst, + (const cairo_raster_source_pattern_t *) pattern, + is_mask, extents, sample, + tx, ty); } } diff --git a/src/cairo-mime-surface.c b/src/cairo-mime-surface.c deleted file mode 100644 index e19852f7..00000000 --- a/src/cairo-mime-surface.c +++ /dev/null @@ -1,405 +0,0 @@ -/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ -/* cairo - a vector graphics library with display and print output - * - * Copyright © 2011 Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it either under the terms of the GNU Lesser General Public - * License version 2.1 as published by the Free Software Foundation - * (the "LGPL") or, at your option, under the terms of the Mozilla - * Public License Version 1.1 (the "MPL"). If you do not alter this - * notice, a recipient may use your version of this file under either - * the MPL or the LGPL. - * - * You should have received a copy of the LGPL along with this library - * in the file COPYING-LGPL-2.1; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA - * You should have received a copy of the MPL along with this library - * in the file COPYING-MPL-1.1 - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY - * OF ANY KIND, either express or implied. See the LGPL or the MPL for - * the specific language governing rights and limitations. - * - * The Original Code is the cairo graphics library. - * - * The Initial Developer of the Original Code is Red Hat, Inc. - * - * Contributor(s): - * Chris Wilson <chris@chris-wilson.co.uk> - */ - -/** - * SECTION:cairo-mime-surface - * @Title: Callback Surfaces - * @Short_Description: Allows the user to provide a callback to supply image - * data upon demand - * @See_Also: #cairo_surface_t - * - * The mime surfaces provide the ability to render from arbitrary sources - * not necessarily resident nor immediately usable by Cairo. The user is - * given the ability to insert a placeholder surface which can be used - * with a pattern and then later supply the actual pixel data upon demand. - * This deferred source is given both the sample region for the operation - * along with the destination surface such that they may be taken into - * account when creating the actual surface to use as the source of pixel - * data. - * - * The reason why it is called the mime surface is two-fold. First it came - * about as an extension of the mime-data property to handle deferred - * image decoding when rendering to pixel buffers (as opposed to the pass- - * through support in PDF and friends.) And then to further rationalise - * the name, it is a surface that mimics a real source without ever - * holding onto to any pixels of its own - a mime surface. - * - * The mime-surface callback interface consists of 4 functions. The principal - * pair are the acquire/release callbacks which are called when pixel data - * is required for an operation (along with the target surface and the sample - * extents). The callee must supply a surface that covers the sample area and - * set the actual extents of the returned surface in the output rectangle - * parameter. The surface does not necessarily have to be an image surface, - * but it is expected that an image surface is likely to be the most - * convenient for uploading pixel data. (Use - * cairo_surface_create_similar_image() to create an image surface that is - * optimised for uploading to the target.) The release callback is - * subsequently called when the returned surface is no longer needed (before - * the operation completes, within the lifetime of the source). - * - * The other pair of functions are to aide with lifetime management of the - * surface with respect to patterns and other users. The destroy callback - * allows for the caller to cleanup the associated data when the last - * reference to surface is destroyed. The snapshot callback is triggered - * when there is an immutable surface pattern referencing the mime-surface - * and the mime-surface will be be invalidated. (Since the mime-surface is - * read-only and a reference will be held by the pattern, this can only be - * triggered through an explicit cairo_surface_finish().) In this - * circumstance, we need to clone the source in order to preserve the pixel - * data for later use (i.e. we have recorded the pattern). The snapshot - * callback provides an interface for the caller to clone the mime-surface - * in an efficient manner. The returned surface may be of any type so long - * as it holds all pixel data and remains accessible. - */ - -/** - * CAIRO_HAS_MIME_SURFACE: - * - * Defined if the mime surface backend is available. - * The mime surface backend is always built in. - * - * @Since: 1.12 - */ - -#include "cairoint.h" -#include "cairo-error-private.h" -#include "cairo-image-surface-private.h" -#include "cairo-surface-backend-private.h" - -typedef struct _cairo_mime_surface { - cairo_surface_t base; - - cairo_rectangle_int_t extents; - - cairo_mime_surface_acquire_t acquire; - cairo_mime_surface_release_t release; - cairo_mime_surface_snapshot_t snapshot; - cairo_mime_surface_destroy_t destroy; - - /* an explicit pre-allocated member in preference to the general user-data */ - void *user_data; -} cairo_mime_surface_t; - -static cairo_status_t -_cairo_mime_surface_finish (void *abstract_surface) -{ - cairo_mime_surface_t *surface = abstract_surface; - - if (surface->destroy) - surface->destroy (&surface->base, surface->user_data); - - return CAIRO_STATUS_SUCCESS; -} - -static cairo_bool_t -_cairo_mime_surface_get_extents (void *abstract_surface, - cairo_rectangle_int_t *rectangle) -{ - cairo_mime_surface_t *surface = abstract_surface; - - *rectangle = surface->extents; - return TRUE; -} - -static cairo_status_t -_cairo_mime_surface_acquire_source_image (void *abstract_surface, - //cairo_surface_t *target, - cairo_image_surface_t **image_out, - void **image_extra) -{ - cairo_mime_surface_t *mime = abstract_surface; - cairo_surface_t *acquired; - cairo_surface_t *dummy_target; - cairo_rectangle_int_t extents; - - if (mime->acquire == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* Force the callee to populate the extents rectangle */ - memset (&extents, 0, sizeof (extents)); - - /* Masquerade for a flexible user-interface */ - dummy_target = _cairo_image_surface_create_with_content (mime->base.content, 0, 0); - acquired = mime->acquire (&mime->base, mime->user_data, - dummy_target, &mime->extents, &extents); - cairo_surface_destroy (dummy_target); - - if (acquired == NULL) - return CAIRO_INT_STATUS_UNSUPPORTED; - - /* The callee must have supplied us with all the image data */ - assert (extents.width == mime->extents.width && extents.height == mime->extents.height); - - if (! _cairo_surface_is_image (acquired)) { - cairo_status_t status; - void *extra = NULL; - - status = _cairo_surface_acquire_source_image (acquired, image_out, &extra); - if (unlikely (status)) { - cairo_surface_destroy (acquired); - return status; - } - - assert (extra == NULL); - *image_extra = acquired; - } else { - *image_out = (cairo_image_surface_t *) acquired; - *image_extra = NULL; - } - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_mime_surface_release_source_image (void *abstract_surface, - cairo_image_surface_t *image, - void *image_extra) -{ - cairo_mime_surface_t *mime = abstract_surface; - - if (image_extra) { - cairo_surface_destroy (&image->base); - image = image_extra; - } - - if (mime->release) - mime->release (&mime->base, mime->user_data, &image->base); -} - -static cairo_surface_t * -_cairo_mime_surface_snapshot (void *abstract_surface) -{ - cairo_mime_surface_t *mime = abstract_surface; - - if (mime->snapshot == NULL) - return NULL; - - return mime->snapshot (&mime->base, mime->user_data); -} - -static const cairo_surface_backend_t cairo_mime_surface_backend = { - CAIRO_SURFACE_TYPE_MIME, - _cairo_mime_surface_finish, - - NULL, /* Read-only */ - - NULL, /* create similar */ - NULL, /* create similar image */ - NULL, /* map to image */ - NULL, /* unmap image */ - - _cairo_mime_surface_acquire_source_image, - _cairo_mime_surface_release_source_image, - _cairo_mime_surface_snapshot, - - NULL, /* copy_page */ - NULL, /* show_page */ - - _cairo_mime_surface_get_extents, - NULL, /* get_font_options */ - - NULL, /* flush */ - NULL, /* mark_dirty_rectangle */ - - NULL, /* scaled_font_fini */ - NULL, /* scaled_glyph_fini */ - - NULL, /* paint */ - NULL, /* mask */ - NULL, /* stroke */ - NULL, /* fill */ - NULL, /* glyphs */ -}; - -cairo_surface_t * -cairo_mime_surface_create (void *data, cairo_content_t content, int width, int height) -{ - cairo_mime_surface_t *surface; - - if (width < 0 || height < 0) - return _cairo_surface_create_in_error (CAIRO_STATUS_INVALID_SIZE); - - if (! CAIRO_CONTENT_VALID (content)) - return _cairo_surface_create_in_error (CAIRO_STATUS_INVALID_CONTENT); - - surface = calloc (1, sizeof (*surface)); - if (unlikely (surface == NULL)) - return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY); - - _cairo_surface_init (&surface->base, - &cairo_mime_surface_backend, - NULL, /* device */ - content); - - surface->extents.x = 0; - surface->extents.y = 0; - surface->extents.width = width; - surface->extents.height = height; - - surface->user_data = data; - - return &surface->base; -} - -void -cairo_mime_surface_set_callback_data (cairo_surface_t *surface, - void *data) -{ - cairo_mime_surface_t *mime; - - if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) - return; - - if (surface->backend != &cairo_mime_surface_backend) - return; - - mime = (cairo_mime_surface_t *)surface; - mime->user_data = data; -} - -void * -cairo_mime_surface_get_callback_data (cairo_surface_t *surface) -{ - cairo_mime_surface_t *mime; - - if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) - return NULL; - - if (surface->backend != &cairo_mime_surface_backend) - return NULL; - - mime = (cairo_mime_surface_t *)surface; - return mime->user_data; -} - -void -cairo_mime_surface_set_acquire (cairo_surface_t *surface, - cairo_mime_surface_acquire_t acquire, - cairo_mime_surface_release_t release) -{ - cairo_mime_surface_t *mime; - - if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) - return; - - if (surface->backend != &cairo_mime_surface_backend) - return; - - mime = (cairo_mime_surface_t *)surface; - mime->acquire = acquire; - mime->release = release; -} - -void -cairo_mime_surface_get_acquire (cairo_surface_t *surface, - cairo_mime_surface_acquire_t *acquire, - cairo_mime_surface_release_t *release) -{ - cairo_mime_surface_t *mime; - - if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) - return; - - if (surface->backend != &cairo_mime_surface_backend) - return; - - mime = (cairo_mime_surface_t *)surface; - if (acquire) - *acquire = mime->acquire; - if (release) - *release = mime->release; -} - -void -cairo_mime_surface_set_snapshot (cairo_surface_t *surface, - cairo_mime_surface_snapshot_t snapshot) -{ - cairo_mime_surface_t *mime; - - if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) - return; - - if (surface->backend != &cairo_mime_surface_backend) - return; - - mime = (cairo_mime_surface_t *)surface; - mime->snapshot = snapshot; -} - -cairo_mime_surface_snapshot_t -cairo_mime_surface_get_snapshot (cairo_surface_t *surface) -{ - cairo_mime_surface_t *mime; - - if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) - return NULL; - - if (surface->backend != &cairo_mime_surface_backend) - return NULL; - - mime = (cairo_mime_surface_t *)surface; - return mime->snapshot; -} - -void -cairo_mime_surface_set_destroy (cairo_surface_t *surface, - cairo_mime_surface_destroy_t destroy) -{ - cairo_mime_surface_t *mime; - - if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) - return; - - if (surface->backend != &cairo_mime_surface_backend) - return; - - mime = (cairo_mime_surface_t *)surface; - mime->destroy = destroy; -} - -cairo_mime_surface_destroy_t -cairo_mime_surface_get_destroy (cairo_surface_t *surface) -{ - cairo_mime_surface_t *mime; - - if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count)) - return NULL; - - if (surface->backend != &cairo_mime_surface_backend) - return NULL; - - mime = (cairo_mime_surface_t *)surface; - return mime->destroy; -} diff --git a/src/cairo-pattern-private.h b/src/cairo-pattern-private.h index 8be319e1..9b2f875e 100644 --- a/src/cairo-pattern-private.h +++ b/src/cairo-pattern-private.h @@ -167,6 +167,22 @@ typedef struct _cairo_mesh_pattern { cairo_bool_t has_color[4]; } cairo_mesh_pattern_t; +typedef struct _cairo_raster_source_pattern { + cairo_pattern_t base; + + cairo_content_t content; + cairo_rectangle_int_t extents; + + cairo_raster_source_acquire_func_t acquire; + cairo_raster_source_release_func_t release; + cairo_raster_source_snapshot_func_t snapshot; + cairo_raster_source_copy_func_t copy; + cairo_raster_source_finish_func_t finish; + + /* an explicit pre-allocated member in preference to the general user-data */ + void *user_data; +} cairo_raster_source_pattern_t; + typedef union { cairo_pattern_t base; @@ -174,9 +190,9 @@ typedef union { cairo_surface_pattern_t surface; cairo_gradient_pattern_union_t gradient; cairo_mesh_pattern_t mesh; + cairo_raster_source_pattern_t raster_source; } cairo_pattern_union_t; - /* cairo-pattern.c */ cairo_private cairo_pattern_t * @@ -186,6 +202,10 @@ cairo_private cairo_status_t _cairo_pattern_create_copy (cairo_pattern_t **pattern, const cairo_pattern_t *other); +cairo_private void +_cairo_pattern_init (cairo_pattern_t *pattern, + cairo_pattern_type_t type); + cairo_private cairo_status_t _cairo_pattern_init_copy (cairo_pattern_t *pattern, const cairo_pattern_t *other); @@ -328,6 +348,25 @@ _cairo_mesh_pattern_rasterize (const cairo_mesh_pattern_t *mesh, double x_offset, double y_offset); +cairo_private cairo_surface_t * +_cairo_raster_source_pattern_acquire (const cairo_pattern_t *abstract_pattern, + cairo_surface_t *target, + const cairo_rectangle_int_t *extents); + +cairo_private void +_cairo_raster_source_pattern_release (const cairo_pattern_t *abstract_pattern, + cairo_surface_t *surface); + +cairo_private cairo_status_t +_cairo_raster_source_pattern_snapshot (cairo_pattern_t *abstract_pattern); + +cairo_private cairo_status_t +_cairo_raster_source_pattern_init_copy (cairo_pattern_t *pattern, + const cairo_pattern_t *other); + +cairo_private void +_cairo_raster_source_pattern_finish (cairo_pattern_t *abstract_pattern); + cairo_private void _cairo_debug_print_pattern (FILE *file, const cairo_pattern_t *pattern); diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c index f91de265..e55e5eb5 100644 --- a/src/cairo-pattern.c +++ b/src/cairo-pattern.c @@ -187,7 +187,7 @@ _cairo_pattern_set_error (cairo_pattern_t *pattern, return _cairo_error (status); } -static void +void _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type) { #if HAVE_VALGRIND @@ -207,6 +207,8 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type) case CAIRO_PATTERN_TYPE_MESH: VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t)); break; + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + break; } #endif @@ -219,7 +221,8 @@ _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type) _cairo_user_data_array_init (&pattern->user_data); - if (type == CAIRO_PATTERN_TYPE_SURFACE) + if (type == CAIRO_PATTERN_TYPE_SURFACE || + type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT; else pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT; @@ -291,6 +294,8 @@ cairo_status_t _cairo_pattern_init_copy (cairo_pattern_t *pattern, const cairo_pattern_t *other) { + cairo_status_t status; + if (other->status) return _cairo_pattern_set_error (pattern, other->status); @@ -316,7 +321,6 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern, case CAIRO_PATTERN_TYPE_RADIAL: { cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern; cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other; - cairo_status_t status; if (other->type == CAIRO_PATTERN_TYPE_LINEAR) { VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t))); @@ -332,7 +336,6 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern, case CAIRO_PATTERN_TYPE_MESH: { cairo_mesh_pattern_t *dst = (cairo_mesh_pattern_t *) pattern; cairo_mesh_pattern_t *src = (cairo_mesh_pattern_t *) other; - cairo_status_t status; VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t))); @@ -341,6 +344,12 @@ _cairo_pattern_init_copy (cairo_pattern_t *pattern, return status; } break; + + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: { + status = _cairo_raster_source_pattern_init_copy (pattern, other); + if (unlikely (status)) + return status; + } break; } /* The reference count and user_data array are unique to the copy. */ @@ -376,6 +385,9 @@ _cairo_pattern_init_static_copy (cairo_pattern_t *pattern, case CAIRO_PATTERN_TYPE_MESH: size = sizeof (cairo_mesh_pattern_t); break; + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + size = sizeof (cairo_raster_source_pattern_t); + break; } memcpy (pattern, other, size); @@ -407,11 +419,11 @@ _cairo_pattern_init_snapshot (cairo_pattern_t *pattern, cairo_surface_destroy (surface); - if (surface_pattern->surface->status) - return surface_pattern->surface->status; - } + status = surface_pattern->surface->status; + } else if (pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE) + status = _cairo_raster_source_pattern_snapshot (pattern); - return CAIRO_STATUS_SUCCESS; + return status; } void @@ -442,6 +454,9 @@ _cairo_pattern_fini (cairo_pattern_t *pattern) _cairo_array_fini (&mesh->patches); } break; + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + _cairo_raster_source_pattern_finish (pattern); + break; } #if HAVE_VALGRIND @@ -461,6 +476,8 @@ _cairo_pattern_fini (cairo_pattern_t *pattern) case CAIRO_PATTERN_TYPE_MESH: VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_mesh_pattern_t)); break; + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + break; } #endif } @@ -491,6 +508,9 @@ _cairo_pattern_create_copy (cairo_pattern_t **pattern_out, case CAIRO_PATTERN_TYPE_MESH: pattern = malloc (sizeof (cairo_mesh_pattern_t)); break; + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + pattern = malloc (sizeof (cairo_raster_source_pattern_t)); + break; default: ASSERT_NOT_REACHED; return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); @@ -1093,7 +1113,10 @@ cairo_pattern_destroy (cairo_pattern_t *pattern) _cairo_pattern_fini (pattern); /* maintain a small cache of freed patterns */ - _freed_pool_put (&freed_pattern_pool[type], pattern); + if (type < ARRAY_LENGTH (freed_pattern_pool)) + _freed_pool_put (&freed_pattern_pool[type], pattern); + else + free (pattern); } slim_hidden_def (cairo_pattern_destroy); @@ -2929,6 +2952,7 @@ _cairo_pattern_alpha_range (const cairo_pattern_t *pattern, /* fall through */ case CAIRO_PATTERN_TYPE_SURFACE: + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: alpha_min = 0; alpha_max = 1; break; @@ -3133,6 +3157,29 @@ _surface_is_opaque (const cairo_surface_pattern_t *pattern, } static cairo_bool_t +_raster_source_is_opaque (const cairo_raster_source_pattern_t *pattern, + const cairo_rectangle_int_t *sample) +{ + if (pattern->content & CAIRO_CONTENT_ALPHA) + return FALSE; + + if (pattern->base.extend != CAIRO_EXTEND_NONE) + return TRUE; + + if (sample != NULL) { + if (sample->x >= pattern->extents.x && + sample->y >= pattern->extents.y && + sample->x + sample->width <= pattern->extents.x + pattern->extents.width && + sample->y + sample->height <= pattern->extents.y + pattern->extents.height) + { + return TRUE; + } + } + + return FALSE; +} + +static cairo_bool_t _surface_is_clear (const cairo_surface_pattern_t *pattern) { cairo_rectangle_int_t extents; @@ -3146,6 +3193,12 @@ _surface_is_clear (const cairo_surface_pattern_t *pattern) } static cairo_bool_t +_raster_source_is_clear (const cairo_raster_source_pattern_t *pattern) +{ + return pattern->extents.width == 0 || pattern->extents.height == 0; +} + +static cairo_bool_t _gradient_is_opaque (const cairo_gradient_pattern_t *gradient, const cairo_rectangle_int_t *sample) { @@ -3215,6 +3268,8 @@ _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern, return _cairo_pattern_is_opaque_solid (abstract_pattern); case CAIRO_PATTERN_TYPE_SURFACE: return _surface_is_opaque (&pattern->surface, sample); + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + return _raster_source_is_opaque (&pattern->raster_source, sample); case CAIRO_PATTERN_TYPE_LINEAR: case CAIRO_PATTERN_TYPE_RADIAL: return _gradient_is_opaque (&pattern->gradient.base, sample); @@ -3240,6 +3295,8 @@ _cairo_pattern_is_clear (const cairo_pattern_t *abstract_pattern) return CAIRO_COLOR_IS_CLEAR (&pattern->solid.color); case CAIRO_PATTERN_TYPE_SURFACE: return _surface_is_clear (&pattern->surface); + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + return _raster_source_is_clear (&pattern->raster_source); case CAIRO_PATTERN_TYPE_LINEAR: case CAIRO_PATTERN_TYPE_RADIAL: return _gradient_is_clear (&pattern->gradient.base, NULL); @@ -3409,6 +3466,29 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern, } break; + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + { + const cairo_raster_source_pattern_t *raster = + (const cairo_raster_source_pattern_t *) pattern; + double pad; + + if (raster->extents.width == 0 || raster->extents.height == 0) + goto EMPTY; + + if (pattern->extend != CAIRO_EXTEND_NONE) + goto UNBOUNDED; + + /* The filter can effectively enlarge the extents of the + * pattern, so extend as necessary. + */ + _cairo_pattern_analyze_filter (pattern, &pad); + x1 = raster->extents.x - pad; + y1 = raster->extents.y - pad; + x2 = raster->extents.x + (int) raster->extents.width + pad; + y2 = raster->extents.y + (int) raster->extents.height + pad; + } + break; + case CAIRO_PATTERN_TYPE_RADIAL: { const cairo_radial_pattern_t *radial = @@ -3666,6 +3746,15 @@ _cairo_surface_pattern_hash (unsigned long hash, return hash; } +static unsigned long +_cairo_raster_source_pattern_hash (unsigned long hash, + const cairo_raster_source_pattern_t *raster) +{ + hash ^= (uintptr_t)raster->user_data; + + return hash; +} + unsigned long _cairo_pattern_hash (const cairo_pattern_t *pattern) { @@ -3698,6 +3787,8 @@ _cairo_pattern_hash (const cairo_pattern_t *pattern) return _cairo_mesh_pattern_hash (hash, (cairo_mesh_pattern_t *) pattern); case CAIRO_PATTERN_TYPE_SURFACE: return _cairo_surface_pattern_hash (hash, (cairo_surface_pattern_t *) pattern); + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + return _cairo_raster_source_pattern_hash (hash, (cairo_raster_source_pattern_t *) pattern); default: ASSERT_NOT_REACHED; return FALSE; @@ -3804,6 +3895,13 @@ _cairo_surface_pattern_equal (const cairo_surface_pattern_t *a, return a->surface->unique_id == b->surface->unique_id; } +static cairo_bool_t +_cairo_raster_source_pattern_equal (const cairo_raster_source_pattern_t *a, + const cairo_raster_source_pattern_t *b) +{ + return a->user_data == b->user_data; +} + cairo_bool_t _cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b) { @@ -3846,6 +3944,9 @@ _cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b) case CAIRO_PATTERN_TYPE_SURFACE: return _cairo_surface_pattern_equal ((cairo_surface_pattern_t *) a, (cairo_surface_pattern_t *) b); + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + return _cairo_raster_source_pattern_equal ((cairo_raster_source_pattern_t *) a, + (cairo_raster_source_pattern_t *) b); default: ASSERT_NOT_REACHED; return FALSE; @@ -4381,6 +4482,13 @@ _cairo_debug_print_surface_pattern (FILE *file, } static void +_cairo_debug_print_raster_source_pattern (FILE *file, + const cairo_raster_source_pattern_t *raster) +{ + printf (" content: %x, size %dx%d\n", raster->content, raster->extents.width, raster->extents.height); +} + +static void _cairo_debug_print_linear_pattern (FILE *file, const cairo_linear_pattern_t *pattern) { @@ -4408,6 +4516,7 @@ _cairo_debug_print_pattern (FILE *file, const cairo_pattern_t *pattern) case CAIRO_PATTERN_TYPE_LINEAR: s = "linear"; break; case CAIRO_PATTERN_TYPE_RADIAL: s = "radial"; break; case CAIRO_PATTERN_TYPE_MESH: s = "mesh"; break; + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: s = "raster"; break; default: s = "invalid"; ASSERT_NOT_REACHED; break; } @@ -4442,6 +4551,9 @@ _cairo_debug_print_pattern (FILE *file, const cairo_pattern_t *pattern) default: case CAIRO_PATTERN_TYPE_SOLID: break; + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + _cairo_debug_print_raster_source_pattern (file, (cairo_raster_source_pattern_t *)pattern); + break; case CAIRO_PATTERN_TYPE_SURFACE: _cairo_debug_print_surface_pattern (file, (cairo_surface_pattern_t *)pattern); break; diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c index 988a2155..f45846cd 100644 --- a/src/cairo-pdf-surface.c +++ b/src/cairo-pdf-surface.c @@ -3621,6 +3621,7 @@ _cairo_pdf_surface_emit_pattern (cairo_pdf_surface_t *surface, cairo_pdf_pattern switch (pdf_pattern->pattern->type) { case CAIRO_PATTERN_TYPE_SOLID: + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: ASSERT_NOT_REACHED; status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); break; @@ -5742,7 +5743,7 @@ _pattern_supported (const cairo_pattern_t *pattern) case CAIRO_PATTERN_TYPE_SOLID: case CAIRO_PATTERN_TYPE_LINEAR: case CAIRO_PATTERN_TYPE_RADIAL: - case CAIRO_PATTERN_TYPE_MESH: + case CAIRO_PATTERN_TYPE_MESH: return TRUE; case CAIRO_PATTERN_TYPE_SURFACE: @@ -5750,6 +5751,7 @@ _pattern_supported (const cairo_pattern_t *pattern) default: ASSERT_NOT_REACHED; + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: /* XXX */ return FALSE; } } diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c index 36d555d8..95b3d123 100644 --- a/src/cairo-ps-surface.c +++ b/src/cairo-ps-surface.c @@ -1769,6 +1769,8 @@ pattern_supported (cairo_ps_surface_t *surface, const cairo_pattern_t *pattern) case CAIRO_PATTERN_TYPE_SURFACE: return surface_pattern_supported ((cairo_surface_pattern_t *) pattern); + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + return FALSE; default: ASSERT_NOT_REACHED; @@ -3714,6 +3716,9 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface, if (unlikely (status)) return status; break; + + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: /* XXX */ + break; } return CAIRO_STATUS_SUCCESS; diff --git a/src/cairo-raster-source-pattern.c b/src/cairo-raster-source-pattern.c new file mode 100644 index 00000000..40031f79 --- /dev/null +++ b/src/cairo-raster-source-pattern.c @@ -0,0 +1,280 @@ +/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */ +/* cairo - a vector graphics library with display and print output + * + * Copyright © 2011 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it either under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation + * (the "LGPL") or, at your option, under the terms of the Mozilla + * Public License Version 1.1 (the "MPL"). If you do not alter this + * notice, a recipient may use your version of this file under either + * the MPL or the LGPL. + * + * You should have received a copy of the LGPL along with this library + * in the file COPYING-LGPL-2.1; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA + * You should have received a copy of the MPL along with this library + * in the file COPYING-MPL-1.1 + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY + * OF ANY KIND, either express or implied. See the LGPL or the MPL for + * the specific language governing rights and limitations. + * + * The Original Code is the cairo graphics library. + * + * The Initial Developer of the Original Code is Red Hat, Inc. + * + * Contributor(s): + * Chris Wilson <chris@chris-wilson.co.uk> + */ + +#include "cairoint.h" +#include "cairo-error-private.h" +#include "cairo-pattern-private.h" + +cairo_surface_t * +_cairo_raster_source_pattern_acquire (const cairo_pattern_t *abstract_pattern, + cairo_surface_t *target, + const cairo_rectangle_int_t *extents) +{ + cairo_raster_source_pattern_t *pattern = + (cairo_raster_source_pattern_t *) abstract_pattern; + + if (pattern->acquire == NULL) + return NULL; + + if (extents == NULL) + extents = &pattern->extents; + + return pattern->acquire (&pattern->base, pattern->user_data, + target, extents); +} + +void +_cairo_raster_source_pattern_release (const cairo_pattern_t *abstract_pattern, + cairo_surface_t *surface) +{ + cairo_raster_source_pattern_t *pattern = + (cairo_raster_source_pattern_t *) abstract_pattern; + + if (pattern->release == NULL) + return; + + return pattern->release (&pattern->base, pattern->user_data, + surface); +} + +cairo_status_t +_cairo_raster_source_pattern_init_copy (cairo_pattern_t *abstract_pattern, + const cairo_pattern_t *other) +{ + cairo_raster_source_pattern_t *pattern = + (cairo_raster_source_pattern_t *) abstract_pattern; + cairo_status_t status; + + VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_raster_source_pattern_t))); + memcpy(pattern, other, sizeof (cairo_raster_source_pattern_t)); + + status = CAIRO_STATUS_SUCCESS; + if (pattern->copy) + status = pattern->copy (&pattern->base, pattern->user_data, other); + + return status; +} + +cairo_status_t +_cairo_raster_source_pattern_snapshot (cairo_pattern_t *abstract_pattern) +{ + cairo_raster_source_pattern_t *pattern = + (cairo_raster_source_pattern_t *) abstract_pattern; + + if (pattern->snapshot == NULL) + return CAIRO_STATUS_SUCCESS; + + return pattern->snapshot (&pattern->base, pattern->user_data); +} + +void +_cairo_raster_source_pattern_finish (cairo_pattern_t *abstract_pattern) +{ + cairo_raster_source_pattern_t *pattern = + (cairo_raster_source_pattern_t *) abstract_pattern; + + if (pattern->finish == NULL) + return; + + pattern->finish (&pattern->base, pattern->user_data); +} + +cairo_pattern_t * +cairo_pattern_create_raster_source (void *user_data, + cairo_content_t content, + int width, int height) +{ + cairo_raster_source_pattern_t *pattern; + + CAIRO_MUTEX_INITIALIZE (); + + if (width < 0 || height < 0) + return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_SIZE); + + if (! CAIRO_CONTENT_VALID (content)) + return _cairo_pattern_create_in_error (CAIRO_STATUS_INVALID_CONTENT); + + pattern = calloc (1, sizeof (*pattern)); + if (unlikely (pattern == NULL)) + return _cairo_pattern_create_in_error (CAIRO_STATUS_NO_MEMORY); + + _cairo_pattern_init (&pattern->base, + CAIRO_PATTERN_TYPE_RASTER_SOURCE); + CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1); + + pattern->content = content; + + pattern->extents.x = 0; + pattern->extents.y = 0; + pattern->extents.width = width; + pattern->extents.height = height; + + pattern->user_data = user_data; + + return &pattern->base; +} + +void +cairo_raster_source_pattern_set_callback_data (cairo_pattern_t *abstract_pattern, + void *data) +{ + cairo_raster_source_pattern_t *pattern; + + if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) + return; + + pattern = (cairo_raster_source_pattern_t *) abstract_pattern; + pattern->user_data = data; +} + +void * +cairo_raster_source_pattern_get_callback_data (cairo_pattern_t *abstract_pattern) +{ + cairo_raster_source_pattern_t *pattern; + + if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) + return NULL; + + pattern = (cairo_raster_source_pattern_t *) abstract_pattern; + return pattern->user_data; +} + +void +cairo_raster_source_pattern_set_acquire (cairo_pattern_t *abstract_pattern, + cairo_raster_source_acquire_func_t acquire, + cairo_raster_source_release_func_t release) +{ + cairo_raster_source_pattern_t *pattern; + + if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) + return; + + pattern = (cairo_raster_source_pattern_t *) abstract_pattern; + pattern->acquire = acquire; + pattern->release = release; +} + +void +cairo_raster_source_pattern_get_acquire (cairo_pattern_t *abstract_pattern, + cairo_raster_source_acquire_func_t *acquire, + cairo_raster_source_release_func_t *release) +{ + cairo_raster_source_pattern_t *pattern; + + if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) + return; + + pattern = (cairo_raster_source_pattern_t *) abstract_pattern; + if (acquire) + *acquire = pattern->acquire; + if (release) + *release = pattern->release; +} + +void +cairo_raster_source_pattern_set_snapshot (cairo_pattern_t *abstract_pattern, + cairo_raster_source_snapshot_func_t snapshot) +{ + cairo_raster_source_pattern_t *pattern; + + if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) + return; + + pattern = (cairo_raster_source_pattern_t *) abstract_pattern; + pattern->snapshot = snapshot; +} + +cairo_raster_source_snapshot_func_t +cairo_raster_source_pattern_get_snapshot (cairo_pattern_t *abstract_pattern) +{ + cairo_raster_source_pattern_t *pattern; + + if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) + return NULL; + + pattern = (cairo_raster_source_pattern_t *) abstract_pattern; + return pattern->snapshot; +} + +void +cairo_raster_source_pattern_set_copy (cairo_pattern_t *abstract_pattern, + cairo_raster_source_copy_func_t copy) +{ + cairo_raster_source_pattern_t *pattern; + + if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) + return; + + pattern = (cairo_raster_source_pattern_t *) abstract_pattern; + pattern->copy = copy; +} + +cairo_raster_source_copy_func_t +cairo_raster_source_pattern_get_copy (cairo_pattern_t *abstract_pattern) +{ + cairo_raster_source_pattern_t *pattern; + + if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) + return NULL; + + pattern = (cairo_raster_source_pattern_t *) abstract_pattern; + return pattern->copy; +} + +void +cairo_raster_source_pattern_set_finish (cairo_pattern_t *abstract_pattern, + cairo_raster_source_finish_func_t finish) +{ + cairo_raster_source_pattern_t *pattern; + + if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) + return; + + pattern = (cairo_raster_source_pattern_t *) abstract_pattern; + pattern->finish = finish; +} + +cairo_raster_source_finish_func_t +cairo_raster_source_pattern_get_finish (cairo_pattern_t *abstract_pattern) +{ + cairo_raster_source_pattern_t *pattern; + + if (abstract_pattern->type != CAIRO_PATTERN_TYPE_RASTER_SOURCE) + return NULL; + + pattern = (cairo_raster_source_pattern_t *) abstract_pattern; + return pattern->finish; +} diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c index 811b015a..29a6ae4b 100644 --- a/src/cairo-script-surface.c +++ b/src/cairo-script-surface.c @@ -53,8 +53,9 @@ #include "cairo-error-private.h" #include "cairo-list-private.h" #include "cairo-image-surface-private.h" -#include "cairo-recording-surface-private.h" #include "cairo-output-stream-private.h" +#include "cairo-pattern-private.h" +#include "cairo-recording-surface-private.h" #include "cairo-scaled-font-private.h" #include "cairo-surface-clipper-private.h" #include "cairo-surface-snapshot-private.h" @@ -1469,7 +1470,6 @@ _emit_image_surface (cairo_script_surface_t *surface, _cairo_output_stream_puts (ctx->stream, "~> set-mime-data\n"); } - attach_snapshot (ctx, &image->base); return CAIRO_INT_STATUS_SUCCESS; } @@ -1574,6 +1574,30 @@ _emit_surface_pattern (cairo_script_surface_t *surface, } static cairo_int_status_t +_emit_raster_pattern (cairo_script_surface_t *surface, + const cairo_pattern_t *pattern) +{ + cairo_surface_t *source; + cairo_int_status_t status; + + source = _cairo_raster_source_pattern_acquire (pattern, &surface->base, NULL); + if (unlikely (source == NULL)) { + ASSERT_NOT_REACHED; + return CAIRO_INT_STATUS_UNSUPPORTED; + } + if (unlikely (source->status)) + return source->status; + + status = _emit_image_surface_pattern (surface, source); + _cairo_raster_source_pattern_release (pattern, source); + if (unlikely (status)) + return status; + + _cairo_output_stream_puts (to_context(surface)->stream, "pattern"); + return CAIRO_INT_STATUS_SUCCESS; +} + +static cairo_int_status_t _emit_pattern (cairo_script_surface_t *surface, const cairo_pattern_t *pattern) { @@ -1603,6 +1627,10 @@ _emit_pattern (cairo_script_surface_t *surface, status = _emit_surface_pattern (surface, pattern); is_default_extend = pattern->extend == CAIRO_EXTEND_SURFACE_DEFAULT; break; + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + status = _emit_raster_pattern (surface, pattern); + is_default_extend = pattern->extend == CAIRO_EXTEND_SURFACE_DEFAULT; + break; default: ASSERT_NOT_REACHED; diff --git a/src/cairo-surface-observer.c b/src/cairo-surface-observer.c index ebb38b98..c70c0cc0 100644 --- a/src/cairo-surface-observer.c +++ b/src/cairo-surface-observer.c @@ -184,6 +184,9 @@ classify_pattern (const cairo_pattern_t *pattern, case CAIRO_PATTERN_TYPE_MESH: classify = 6; break; + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: + classify = 7; + break; } return classify; } @@ -1687,7 +1690,8 @@ static const char *pattern_names[] = { "solid", "linear", "radial", - "mesh" + "mesh", + "raster" }; static void print_pattern (cairo_output_stream_t *stream, diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c index 6f607d3c..eab50c88 100644 --- a/src/cairo-svg-surface.c +++ b/src/cairo-svg-surface.c @@ -2035,6 +2035,7 @@ _cairo_svg_surface_emit_pattern (cairo_svg_surface_t *surface, output, is_stroke, parent_matrix); case CAIRO_PATTERN_TYPE_MESH: + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: ASSERT_NOT_REACHED; } return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH); diff --git a/src/cairo-xcb-surface-core.c b/src/cairo-xcb-surface-core.c index 447529d5..c608c9ac 100644 --- a/src/cairo-xcb-surface-core.c +++ b/src/cairo-xcb-surface-core.c @@ -485,6 +485,7 @@ _cairo_xcb_pixmap_for_pattern (cairo_xcb_surface_t *target, case CAIRO_PATTERN_TYPE_LINEAR: case CAIRO_PATTERN_TYPE_RADIAL: case CAIRO_PATTERN_TYPE_MESH: + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: return _render_to_pixmap (target, pattern, extents); default: diff --git a/src/cairo-xcb-surface-render.c b/src/cairo-xcb-surface-render.c index 5bc8b09f..662eb74e 100644 --- a/src/cairo-xcb-surface-render.c +++ b/src/cairo-xcb-surface-render.c @@ -1242,9 +1242,10 @@ _cairo_xcb_picture_for_pattern (cairo_xcb_surface_t *target, return _cairo_xcb_surface_picture (target, (cairo_surface_pattern_t *) pattern, extents); - case CAIRO_PATTERN_TYPE_MESH: default: ASSERT_NOT_REACHED; + case CAIRO_PATTERN_TYPE_MESH: + case CAIRO_PATTERN_TYPE_RASTER_SOURCE: return _render_to_picture (target, pattern, extents); } } diff --git a/src/cairo.h b/src/cairo.h index 25c32c2e..bc5abcfd 100644 --- a/src/cairo.h +++ b/src/cairo.h @@ -2260,8 +2260,7 @@ cairo_surface_status (cairo_surface_t *surface); * @CAIRO_SURFACE_TYPE_SKIA: The surface is of type Skia, since 1.10 * @CAIRO_SURFACE_TYPE_SUBSURFACE: The surface is a subsurface created with * cairo_surface_create_for_rectangle(), since 1.10 - * @CAIRO_SURFACE_TYPE_MIME: The surface is a callback (mime) surface, since 1.12 - * @CAIRO_SURFACE_TYPE_COGL: This surface is of type Cogl + * @CAIRO_SURFACE_TYPE_COGL: This surface is of type Cogl, since 1.12 * * #cairo_surface_type_t is used to describe the type of a given * surface. The surface types are also known as "backends" or "surface @@ -2312,7 +2311,6 @@ typedef enum _cairo_surface_type { CAIRO_SURFACE_TYPE_XML, CAIRO_SURFACE_TYPE_SKIA, CAIRO_SURFACE_TYPE_SUBSURFACE, - CAIRO_SURFACE_TYPE_MIME, CAIRO_SURFACE_TYPE_COGL } cairo_surface_type_t; @@ -2472,55 +2470,73 @@ cairo_public cairo_bool_t cairo_recording_surface_get_extents (cairo_surface_t *surface, cairo_rectangle_t *extents); -/* Mime-surface (callback) functions */ +/* raster-source pattern (callback) functions */ -typedef cairo_surface_t *(*cairo_mime_surface_acquire_t) (cairo_surface_t *mime_surface, - void *callback_data, - cairo_surface_t *target, - const cairo_rectangle_int_t *sample_extents, - cairo_rectangle_int_t *surface_extents); +typedef cairo_surface_t * +(*cairo_raster_source_acquire_func_t) (cairo_pattern_t *pattern, + void *callback_data, + cairo_surface_t *target, + const cairo_rectangle_int_t *extents); -typedef void (*cairo_mime_surface_release_t) (cairo_surface_t *mime_surface, - void *callback_data, - cairo_surface_t *image_surface); +typedef void +(*cairo_raster_source_release_func_t) (cairo_pattern_t *pattern, + void *callback_data, + cairo_surface_t *surface); -typedef cairo_surface_t *(*cairo_mime_surface_snapshot_t) (cairo_surface_t *mime_surface, - void *callback_data); -typedef void (*cairo_mime_surface_destroy_t) (cairo_surface_t *mime_surface, - void *callback_data); +typedef cairo_status_t +(*cairo_raster_source_snapshot_func_t) (cairo_pattern_t *pattern, + void *callback_data); -cairo_public cairo_surface_t * -cairo_mime_surface_create (void *data, cairo_content_t content, int width, int height); +typedef cairo_status_t +(*cairo_raster_source_copy_func_t) (cairo_pattern_t *pattern, + void *callback_data, + const cairo_pattern_t *other); + +typedef void +(*cairo_raster_source_finish_func_t) (cairo_pattern_t *pattern, + void *callback_data); + +cairo_public cairo_pattern_t * +cairo_pattern_create_raster_source (void *user_data, + cairo_content_t content, + int width, int height); cairo_public void -cairo_mime_surface_set_callback_data (cairo_surface_t *surface, - void *data); +cairo_raster_source_pattern_set_callback_data (cairo_pattern_t *pattern, + void *data); cairo_public void * -cairo_mime_surface_get_callback_data (cairo_surface_t *surface); +cairo_raster_source_pattern_get_callback_data (cairo_pattern_t *pattern); cairo_public void -cairo_mime_surface_set_acquire (cairo_surface_t *surface, - cairo_mime_surface_acquire_t acquire, - cairo_mime_surface_release_t release); +cairo_raster_source_pattern_set_acquire (cairo_pattern_t *pattern, + cairo_raster_source_acquire_func_t acquire, + cairo_raster_source_release_func_t release); cairo_public void -cairo_mime_surface_get_acquire (cairo_surface_t *surface, - cairo_mime_surface_acquire_t *acquire, - cairo_mime_surface_release_t *release); +cairo_raster_source_pattern_get_acquire (cairo_pattern_t *pattern, + cairo_raster_source_acquire_func_t *acquire, + cairo_raster_source_release_func_t *release); +cairo_public void +cairo_raster_source_pattern_set_snapshot (cairo_pattern_t *pattern, + cairo_raster_source_snapshot_func_t snapshot); + +cairo_public cairo_raster_source_snapshot_func_t +cairo_raster_source_pattern_get_snapshot (cairo_pattern_t *pattern); + cairo_public void -cairo_mime_surface_set_snapshot (cairo_surface_t *surface, - cairo_mime_surface_snapshot_t snapshot); +cairo_raster_source_pattern_set_copy (cairo_pattern_t *pattern, + cairo_raster_source_copy_func_t copy); -cairo_public cairo_mime_surface_snapshot_t -cairo_mime_surface_get_snapshot (cairo_surface_t *surface); +cairo_public cairo_raster_source_copy_func_t +cairo_raster_source_pattern_get_copy (cairo_pattern_t *pattern); cairo_public void -cairo_mime_surface_set_destroy (cairo_surface_t *surface, - cairo_mime_surface_destroy_t destroy); +cairo_raster_source_pattern_set_finish (cairo_pattern_t *pattern, + cairo_raster_source_finish_func_t finish); -cairo_public cairo_mime_surface_destroy_t -cairo_mime_surface_get_destroy (cairo_surface_t *surface); +cairo_public cairo_raster_source_finish_func_t +cairo_raster_source_pattern_get_finish (cairo_pattern_t *pattern); /* Pattern creation functions */ @@ -2575,6 +2591,7 @@ cairo_pattern_set_user_data (cairo_pattern_t *pattern, * @CAIRO_PATTERN_TYPE_LINEAR: The pattern is a linear gradient. * @CAIRO_PATTERN_TYPE_RADIAL: The pattern is a radial gradient. * @CAIRO_PATTERN_TYPE_MESH: The pattern is a mesh. + * @CAIRO_PATTERN_TYPE_RASTER_SOURCE: The pattern is a user pattern providing raster data, since 1.12. * * #cairo_pattern_type_t is used to describe the type of a given pattern. * @@ -2603,7 +2620,8 @@ typedef enum _cairo_pattern_type { CAIRO_PATTERN_TYPE_SURFACE, CAIRO_PATTERN_TYPE_LINEAR, CAIRO_PATTERN_TYPE_RADIAL, - CAIRO_PATTERN_TYPE_MESH + CAIRO_PATTERN_TYPE_MESH, + CAIRO_PATTERN_TYPE_RASTER_SOURCE } cairo_pattern_type_t; cairo_public cairo_pattern_type_t diff --git a/test/Makefile.sources b/test/Makefile.sources index 8acc266e..2d356667 100644 --- a/test/Makefile.sources +++ b/test/Makefile.sources @@ -203,7 +203,6 @@ test_sources = \ mesh-pattern-overlap.c \ mesh-pattern-transformed.c \ mime-data.c \ - mime-surface.c \ mime-surface-api.c \ miter-precision.c \ move-to-show-surface.c \ @@ -247,6 +246,7 @@ test_sources = \ random-intersections-nonzero.c \ random-intersections-curves-eo.c \ random-intersections-curves-nz.c \ + raster-source.c \ record.c \ record-extend.c \ record-mesh.c \ diff --git a/test/mime-surface.c b/test/raster-source.c index d59112f2..5a7646e8 100644 --- a/test/mime-surface.c +++ b/test/raster-source.c @@ -49,41 +49,37 @@ png_dimensions (const char *filename, } static cairo_surface_t * -png_acquire (cairo_surface_t *mime_surface, void *closure, - cairo_surface_t *target, const cairo_rectangle_int_t *roi, - cairo_rectangle_int_t *extents) +png_acquire (cairo_pattern_t *pattern, void *closure, + cairo_surface_t *target, + const cairo_rectangle_int_t *extents) { - cairo_surface_t *image; - - image = cairo_image_surface_create_from_png (closure); - extents->x = extents->y = 0; - extents->width = cairo_image_surface_get_width (image); - extents->height = cairo_image_surface_get_height (image); - return image; + return cairo_image_surface_create_from_png (closure); } static cairo_surface_t * -red_acquire (cairo_surface_t *mime_surface, void *closure, - cairo_surface_t *target, const cairo_rectangle_int_t *roi, - cairo_rectangle_int_t *extents) +red_acquire (cairo_pattern_t *pattern, void *closure, + cairo_surface_t *target, + const cairo_rectangle_int_t *extents) { cairo_surface_t *image; cairo_t *cr; image = cairo_surface_create_similar_image (target, CAIRO_FORMAT_RGB24, - roi->width, roi->height); + extents->width, + extents->height); + cairo_surface_set_device_offset (image, extents->x, extents->y); + cr = cairo_create (image); cairo_set_source_rgb (cr, 1, 0, 0); cairo_paint (cr); cairo_destroy (cr); - *extents = *roi; return image; } static void -release (cairo_surface_t *mime_surface, void *closure, cairo_surface_t *image) +release (cairo_pattern_t *pattern, void *closure, cairo_surface_t *image) { cairo_surface_destroy (image); } @@ -92,18 +88,20 @@ static cairo_test_status_t draw (cairo_t *cr, int width, int height) { const char *png_filename = "png.png"; - cairo_surface_t *png, *red; + cairo_pattern_t *png, *red; cairo_content_t content; int png_width, png_height; int i, j; png_dimensions (png_filename, &content, &png_width, &png_height); - png = cairo_mime_surface_create ((void*)png_filename, content, png_width, png_height); - cairo_mime_surface_set_acquire (png, png_acquire, release); + png = cairo_pattern_create_raster_source ((void*)png_filename, + content, png_width, png_height); + cairo_raster_source_pattern_set_acquire (png, png_acquire, release); - red = cairo_mime_surface_create (NULL, CAIRO_CONTENT_COLOR, WIDTH, HEIGHT); - cairo_mime_surface_set_acquire (red, red_acquire, release); + red = cairo_pattern_create_raster_source (NULL, + CAIRO_CONTENT_COLOR, WIDTH, HEIGHT); + cairo_raster_source_pattern_set_acquire (red, red_acquire, release); cairo_set_source_rgb (cr, 0, 0, 1); cairo_paint (cr); @@ -111,64 +109,26 @@ draw (cairo_t *cr, int width, int height) cairo_translate (cr, 0, (HEIGHT-png_height)/2); for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { - cairo_surface_t *source; + cairo_pattern_t *source; if ((i ^ j) & 1) source = red; else source = png; - cairo_set_source_surface (cr, source, 0, 0); + cairo_set_source (cr, source); cairo_rectangle (cr, i * WIDTH/4, j * png_height/4, WIDTH/4, png_height/4); cairo_fill (cr); } } - cairo_surface_destroy (red); - cairo_surface_destroy (png); - - return CAIRO_TEST_SUCCESS; -} - -static cairo_test_status_t -check_status (const cairo_test_context_t *ctx, - cairo_status_t status, - cairo_status_t expected) -{ - if (status == expected) - return CAIRO_TEST_SUCCESS; - - cairo_test_log (ctx, - "Error: Expected status value %d (%s), received %d (%s)\n", - expected, - cairo_status_to_string (expected), - status, - cairo_status_to_string (status)); - return CAIRO_TEST_FAILURE; -} - -static cairo_test_status_t -preamble (cairo_test_context_t *ctx) -{ - cairo_surface_t *mime; - cairo_status_t status; - cairo_t *cr; - - /* drawing to a mime-surface is verboten */ - - mime = cairo_mime_surface_create (NULL, CAIRO_CONTENT_COLOR, 0, 0); - cr = cairo_create (mime); - cairo_surface_destroy (mime); - status = cairo_status (cr); - cairo_destroy (cr); - status = check_status (ctx, status, CAIRO_STATUS_WRITE_ERROR); - if (status) - return status; + cairo_pattern_destroy (red); + cairo_pattern_destroy (png); return CAIRO_TEST_SUCCESS; } -CAIRO_TEST (mime_surface, +CAIRO_TEST (raster_source, "Check that the mime-surface embedding works", "api", /* keywords */ NULL, /* requirements */ WIDTH, HEIGHT, - preamble, draw) + NULL, draw) diff --git a/test/reference/mime-surface.base.argb32.ref.png b/test/reference/raster-source.base.argb32.ref.png Binary files differindex ac5e5606..ac5e5606 100644 --- a/test/reference/mime-surface.base.argb32.ref.png +++ b/test/reference/raster-source.base.argb32.ref.png diff --git a/test/reference/mime-surface.base.rgb24.ref.png b/test/reference/raster-source.base.rgb24.ref.png Binary files differindex ac5e5606..ac5e5606 100644 --- a/test/reference/mime-surface.base.rgb24.ref.png +++ b/test/reference/raster-source.base.rgb24.ref.png diff --git a/test/reference/mime-surface.ref.png b/test/reference/raster-source.ref.png Binary files differindex ac5e5606..ac5e5606 100644 --- a/test/reference/mime-surface.ref.png +++ b/test/reference/raster-source.ref.png diff --git a/test/reference/mime-surface.traps.argb32.ref.png b/test/reference/raster-source.traps.argb32.ref.png Binary files differindex ac5e5606..ac5e5606 100644 --- a/test/reference/mime-surface.traps.argb32.ref.png +++ b/test/reference/raster-source.traps.argb32.ref.png diff --git a/test/reference/mime-surface.traps.rgb24.ref.png b/test/reference/raster-source.traps.rgb24.ref.png Binary files differindex ac5e5606..ac5e5606 100644 --- a/test/reference/mime-surface.traps.rgb24.ref.png +++ b/test/reference/raster-source.traps.rgb24.ref.png diff --git a/util/cairo-trace/trace.c b/util/cairo-trace/trace.c index 74759583..3c698a6c 100644 --- a/util/cairo-trace/trace.c +++ b/util/cairo-trace/trace.c @@ -3511,24 +3511,24 @@ cairo_image_surface_create_for_data (unsigned char *data, cairo_format_t format, return ret; } -cairo_surface_t * -cairo_mime_surface_create (void *data, cairo_content_t content, int width, int height) +cairo_pattern_t * +cairo_pattern_create_raster_source (void *data, cairo_content_t content, int width, int height) { - cairo_surface_t *ret; + cairo_pattern_t *ret; _enter_trace (); - ret = DLCALL (cairo_mime_surface_create, data, content, width, height); + ret = DLCALL (cairo_pattern_create_raster_source, data, content, width, height); _emit_line_info (); if (_write_lock ()) { - Object *obj = _create_surface (ret); + long pattern_id = _create_pattern_id (ret); cairo_format_t format; cairo_surface_t *image; cairo_t *cr; - /* Impossible to accurately record the interaction with a mime-surface - * so just suck all the data into an image upfront */ + /* Impossible to accurately record the interaction with this custom + * pattern so just suck all the data into an image upfront */ switch (content) { case CAIRO_CONTENT_ALPHA: format = CAIRO_FORMAT_A8; break; case CAIRO_CONTENT_COLOR: format = CAIRO_FORMAT_RGB24; break; @@ -3536,23 +3536,20 @@ cairo_mime_surface_create (void *data, cairo_content_t content, int width, int h case CAIRO_CONTENT_COLOR_ALPHA: format = CAIRO_FORMAT_ARGB32; break; } - _trace_printf ("%% mime-surface\n"); + _trace_printf ("%% raster-source\n"); image = DLCALL (cairo_image_surface_create, format, width, height); cr = DLCALL (cairo_create, image); - DLCALL (cairo_set_source_surface, cr, ret, 0, 0); + DLCALL (cairo_set_source, cr, ret); DLCALL (cairo_paint, cr); DLCALL (cairo_destroy, cr); _emit_image (image, NULL); DLCALL (cairo_surface_destroy, image); - _trace_printf (" dup /s%ld exch def\n", - obj->token); + _trace_printf (" pattern dup /s%ld exch def\n", + pattern_id); - obj->width = width; - obj->height = height; - obj->defined = TRUE; - _push_object (obj); + _push_operand (PATTERN, ret); _write_unlock (); } |