Convert cairo_mime_surface_t to cairo_raster_source_pattern_t
As discussed, overloading the cairo_surface_t semantics to include sources (i.e. read-only surfaces) was duplicating the definition of cairo_pattern_t. So rather than introduce a new surface type with pattern semantics, start along the thorny road of extensible pattern types. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -3132,6 +3156,29 @@ _surface_is_opaque (const cairo_surface_pattern_t *pattern,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
@ -3145,6 +3192,12 @@ _surface_is_clear (const cairo_surface_pattern_t *pattern)
|
|||
pattern->surface->content & CAIRO_CONTENT_ALPHA;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
@ -4380,6 +4481,13 @@ _cairo_debug_print_surface_pattern (FILE *file,
|
|||
printf (" surface type: %d\n", pattern->surface->type);
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
280
src/cairo-raster-source-pattern.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -1573,6 +1573,30 @@ _emit_surface_pattern (cairo_script_surface_t *surface,
|
|||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
90
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_mime_surface_set_snapshot (cairo_surface_t *surface,
|
||||
cairo_mime_surface_snapshot_t snapshot);
|
||||
cairo_raster_source_pattern_set_snapshot (cairo_pattern_t *pattern,
|
||||
cairo_raster_source_snapshot_func_t snapshot);
|
||||
|
||||
cairo_public cairo_mime_surface_snapshot_t
|
||||
cairo_mime_surface_get_snapshot (cairo_surface_t *surface);
|
||||
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_destroy (cairo_surface_t *surface,
|
||||
cairo_mime_surface_destroy_t destroy);
|
||||
cairo_raster_source_pattern_set_copy (cairo_pattern_t *pattern,
|
||||
cairo_raster_source_copy_func_t copy);
|
||||
|
||||
cairo_public cairo_mime_surface_destroy_t
|
||||
cairo_mime_surface_get_destroy (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_raster_source_pattern_set_finish (cairo_pattern_t *pattern,
|
||||
cairo_raster_source_finish_func_t finish);
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
cairo_pattern_destroy (red);
|
||||
cairo_pattern_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;
|
||||
|
||||
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)
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
|
|
|||