mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 08:48:00 +02:00
Introduce cairo_mime_surface_t
The mime surface is a user-callback surface designed for interfacing cairo with an opaque data source. For instance, in a web browser, the incoming page may be laid out and rendered to a recording surface before all the image data has finished being downloaded. In this circumstance we need to pass a place holder to cairo and to supply the image data later upon demand. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
eed1f2efdf
commit
2220693a40
14 changed files with 739 additions and 21 deletions
|
|
@ -398,6 +398,16 @@ enabled_cairo_boilerplate_private += $(cairo_boilerplate_image_private)
|
|||
enabled_cairo_boilerplate_cxx_sources += $(cairo_boilerplate_image_cxx_sources)
|
||||
enabled_cairo_boilerplate_sources += $(cairo_boilerplate_image_sources)
|
||||
|
||||
supported_cairo_boilerplate_headers += $(cairo_boilerplate_mime_headers)
|
||||
all_cairo_boilerplate_headers += $(cairo_boilerplate_mime_headers)
|
||||
all_cairo_boilerplate_private += $(cairo_boilerplate_mime_private)
|
||||
all_cairo_boilerplate_cxx_sources += $(cairo_boilerplate_mime_cxx_sources)
|
||||
all_cairo_boilerplate_sources += $(cairo_boilerplate_mime_sources)
|
||||
enabled_cairo_boilerplate_headers += $(cairo_boilerplate_mime_headers)
|
||||
enabled_cairo_boilerplate_private += $(cairo_boilerplate_mime_private)
|
||||
enabled_cairo_boilerplate_cxx_sources += $(cairo_boilerplate_mime_cxx_sources)
|
||||
enabled_cairo_boilerplate_sources += $(cairo_boilerplate_mime_sources)
|
||||
|
||||
supported_cairo_boilerplate_headers += $(cairo_boilerplate_recording_headers)
|
||||
all_cairo_boilerplate_headers += $(cairo_boilerplate_recording_headers)
|
||||
all_cairo_boilerplate_private += $(cairo_boilerplate_recording_private)
|
||||
|
|
|
|||
|
|
@ -99,6 +99,7 @@ ifeq ($(CAIRO_HAS_TEST_SURFACES),1)
|
|||
@echo "#define CAIRO_HAS_TEST_SURFACES 1" >> $(top_srcdir)/src/cairo-features.h
|
||||
endif
|
||||
@echo "#define CAIRO_HAS_IMAGE_SURFACE 1" >> $(top_srcdir)/src/cairo-features.h
|
||||
@echo "#define CAIRO_HAS_MIME_SURFACE 1" >> $(top_srcdir)/src/cairo-features.h
|
||||
@echo "#define CAIRO_HAS_RECORDING_SURFACE 1" >> $(top_srcdir)/src/cairo-features.h
|
||||
@echo "#define CAIRO_HAS_OBSERVER_SURFACE 1" >> $(top_srcdir)/src/cairo-features.h
|
||||
ifeq ($(CAIRO_HAS_TEE_SURFACE),1)
|
||||
|
|
|
|||
|
|
@ -366,6 +366,7 @@ AC_DEFUN([CAIRO_REPORT],
|
|||
echo " Image: yes (always builtin)"
|
||||
echo " Recording: yes (always builtin)"
|
||||
echo " Observer: yes (always builtin)"
|
||||
echo " Mime: yes (always builtin)"
|
||||
echo " Tee: $use_tee"
|
||||
echo " XML: $use_xml"
|
||||
echo " Skia: $use_skia"
|
||||
|
|
|
|||
|
|
@ -620,6 +620,7 @@ CAIRO_ENABLE_SURFACE_BACKEND(image, image, always, [
|
|||
|
||||
dnl ===========================================================================
|
||||
|
||||
CAIRO_ENABLE_SURFACE_BACKEND(mime, mime, always)
|
||||
CAIRO_ENABLE_SURFACE_BACKEND(recording, recording, always)
|
||||
CAIRO_ENABLE_SURFACE_BACKEND(observer, observer, always)
|
||||
CAIRO_ENABLE_SURFACE_BACKEND(tee, tee, no)
|
||||
|
|
|
|||
|
|
@ -151,6 +151,7 @@ cairo_sources = \
|
|||
cairo-lzw.c \
|
||||
cairo-matrix.c \
|
||||
cairo-mesh-pattern-rasterizer.c \
|
||||
cairo-mime-surface.c \
|
||||
cairo-misc.c \
|
||||
cairo-mutex.c \
|
||||
cairo-observer.c \
|
||||
|
|
|
|||
|
|
@ -520,6 +520,16 @@ enabled_cairo_private += $(cairo_image_private)
|
|||
enabled_cairo_cxx_sources += $(cairo_image_cxx_sources)
|
||||
enabled_cairo_sources += $(cairo_image_sources)
|
||||
|
||||
supported_cairo_headers += $(cairo_mime_headers)
|
||||
all_cairo_headers += $(cairo_mime_headers)
|
||||
all_cairo_private += $(cairo_mime_private)
|
||||
all_cairo_cxx_sources += $(cairo_mime_cxx_sources)
|
||||
all_cairo_sources += $(cairo_mime_sources)
|
||||
enabled_cairo_headers += $(cairo_mime_headers)
|
||||
enabled_cairo_private += $(cairo_mime_private)
|
||||
enabled_cairo_cxx_sources += $(cairo_mime_cxx_sources)
|
||||
enabled_cairo_sources += $(cairo_mime_sources)
|
||||
|
||||
supported_cairo_headers += $(cairo_recording_headers)
|
||||
all_cairo_headers += $(cairo_recording_headers)
|
||||
all_cairo_private += $(cairo_recording_private)
|
||||
|
|
|
|||
411
src/cairo-mime-surface.c
Normal file
411
src/cairo-mime-surface.c
Normal file
|
|
@ -0,0 +1,411 @@
|
|||
/* -*- 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"
|
||||
|
||||
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,
|
||||
NULL, /* acquire_dest_image */
|
||||
NULL, /* release_dest_image */
|
||||
NULL, /* clone_similar */
|
||||
NULL, /* composite */
|
||||
NULL, /* fill_rectangles */
|
||||
NULL, /* composite_trapezoids */
|
||||
NULL, /* create_span_renderer */
|
||||
NULL, /* check_span_renderer */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
_cairo_mime_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
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_mime_surface_snapshot,
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
11
src/cairo.c
11
src/cairo.c
|
|
@ -212,9 +212,11 @@ _cairo_create_in_error (cairo_status_t status)
|
|||
* with cairo_destroy() when you are done using the #cairo_t.
|
||||
* This function never returns %NULL. If memory cannot be
|
||||
* allocated, a special #cairo_t object will be returned on
|
||||
* which cairo_status() returns %CAIRO_STATUS_NO_MEMORY.
|
||||
* You can use this object normally, but no drawing will
|
||||
* be done.
|
||||
* which cairo_status() returns %CAIRO_STATUS_NO_MEMORY. If
|
||||
* you attempt to target a surface which does not support
|
||||
* writing (such as #cairo_mime_surface_t) then a
|
||||
* %CAIRO_STATUS_WRITE_ERROR will be raised. You can use this
|
||||
* object normally, but no drawing will be done.
|
||||
**/
|
||||
cairo_t *
|
||||
cairo_create (cairo_surface_t *target)
|
||||
|
|
@ -224,6 +226,9 @@ cairo_create (cairo_surface_t *target)
|
|||
if (unlikely (target->status))
|
||||
return _cairo_create_in_error (target->status);
|
||||
|
||||
if (target->backend->create_context == NULL)
|
||||
return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
|
||||
|
||||
return target->backend->create_context (target);
|
||||
|
||||
}
|
||||
|
|
|
|||
89
src/cairo.h
89
src/cairo.h
|
|
@ -433,6 +433,24 @@ typedef cairo_status_t (*cairo_read_func_t) (void *closure,
|
|||
unsigned char *data,
|
||||
unsigned int length);
|
||||
|
||||
/**
|
||||
* cairo_rectangle_int_t:
|
||||
* @x: X coordinate of the left side of the rectangle
|
||||
* @y: Y coordinate of the the top side of the rectangle
|
||||
* @width: width of the rectangle
|
||||
* @height: height of the rectangle
|
||||
*
|
||||
* A data structure for holding a rectangle with integer coordinates.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
|
||||
typedef struct _cairo_rectangle_int {
|
||||
int x, y;
|
||||
int width, height;
|
||||
} cairo_rectangle_int_t;
|
||||
|
||||
|
||||
/* Functions for manipulating state objects */
|
||||
cairo_public cairo_t *
|
||||
cairo_create (cairo_surface_t *target);
|
||||
|
|
@ -2153,6 +2171,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_t is used to describe the type of a given
|
||||
* surface. The surface types are also known as "backends" or "surface
|
||||
|
|
@ -2202,7 +2221,8 @@ typedef enum _cairo_surface_type {
|
|||
CAIRO_SURFACE_TYPE_TEE,
|
||||
CAIRO_SURFACE_TYPE_XML,
|
||||
CAIRO_SURFACE_TYPE_SKIA,
|
||||
CAIRO_SURFACE_TYPE_SUBSURFACE
|
||||
CAIRO_SURFACE_TYPE_SUBSURFACE,
|
||||
CAIRO_SURFACE_TYPE_MIME
|
||||
} cairo_surface_type_t;
|
||||
|
||||
cairo_public cairo_surface_type_t
|
||||
|
|
@ -2357,6 +2377,56 @@ cairo_recording_surface_ink_extents (cairo_surface_t *surface,
|
|||
double *width,
|
||||
double *height);
|
||||
|
||||
/* Mime-surface (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 void (*cairo_mime_surface_release_t) (cairo_surface_t *mime_surface,
|
||||
void *callback_data,
|
||||
cairo_surface_t *image_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);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_mime_surface_create (void *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_public void *
|
||||
cairo_mime_surface_get_callback_data (cairo_surface_t *surface);
|
||||
|
||||
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_public void
|
||||
cairo_mime_surface_get_acquire (cairo_surface_t *surface,
|
||||
cairo_mime_surface_acquire_t *acquire,
|
||||
cairo_mime_surface_release_t *release);
|
||||
cairo_public void
|
||||
cairo_mime_surface_set_snapshot (cairo_surface_t *surface,
|
||||
cairo_mime_surface_snapshot_t snapshot);
|
||||
|
||||
cairo_public cairo_mime_surface_snapshot_t
|
||||
cairo_mime_surface_get_snapshot (cairo_surface_t *surface);
|
||||
|
||||
cairo_public void
|
||||
cairo_mime_surface_set_destroy (cairo_surface_t *surface,
|
||||
cairo_mime_surface_destroy_t destroy);
|
||||
|
||||
cairo_public cairo_mime_surface_destroy_t
|
||||
cairo_mime_surface_get_destroy (cairo_surface_t *surface);
|
||||
|
||||
/* Pattern creation functions */
|
||||
|
||||
cairo_public cairo_pattern_t *
|
||||
|
|
@ -2684,23 +2754,6 @@ cairo_matrix_transform_point (const cairo_matrix_t *matrix,
|
|||
**/
|
||||
typedef struct _cairo_region cairo_region_t;
|
||||
|
||||
/**
|
||||
* cairo_rectangle_int_t:
|
||||
* @x: X coordinate of the left side of the rectangle
|
||||
* @y: Y coordinate of the the top side of the rectangle
|
||||
* @width: width of the rectangle
|
||||
* @height: height of the rectangle
|
||||
*
|
||||
* A data structure for holding a rectangle with integer coordinates.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
|
||||
typedef struct _cairo_rectangle_int {
|
||||
int x, y;
|
||||
int width, height;
|
||||
} cairo_rectangle_int_t;
|
||||
|
||||
typedef enum _cairo_region_overlap {
|
||||
CAIRO_REGION_OVERLAP_IN, /* completely inside region */
|
||||
CAIRO_REGION_OVERLAP_OUT, /* completely outside region */
|
||||
|
|
|
|||
|
|
@ -789,6 +789,7 @@ REFERENCE_IMAGES = \
|
|||
mime-data.ref.png \
|
||||
mime-data.script.ref.png \
|
||||
mime-data.svg.ref.png \
|
||||
mime-surface.ref.png \
|
||||
miter-precision.ps2.ref.png \
|
||||
miter-precision.ps3.ref.png \
|
||||
miter-precision.ref.png \
|
||||
|
|
|
|||
|
|
@ -190,6 +190,7 @@ test_sources = \
|
|||
mesh-pattern-overlap.c \
|
||||
mesh-pattern-transformed.c \
|
||||
mime-data.c \
|
||||
mime-surface.c \
|
||||
miter-precision.c \
|
||||
move-to-show-surface.c \
|
||||
new-sub-path.c \
|
||||
|
|
|
|||
174
test/mime-surface.c
Normal file
174
test/mime-surface.c
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairo-test.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* Basic test to exercise the new mime-surface callback. */
|
||||
|
||||
#define WIDTH 200
|
||||
#define HEIGHT 80
|
||||
|
||||
/* Lazy way of determining PNG dimensions... */
|
||||
static void
|
||||
png_dimensions (const char *filename,
|
||||
cairo_content_t *content, int *width, int *height)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
|
||||
surface = cairo_image_surface_create_from_png (filename);
|
||||
*content = cairo_surface_get_content (surface);
|
||||
*width = cairo_image_surface_get_width (surface);
|
||||
*height = cairo_image_surface_get_height (surface);
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
cairo_surface_t *image;
|
||||
cairo_t *cr;
|
||||
|
||||
image = cairo_surface_create_similar_image (target,
|
||||
CAIRO_FORMAT_RGB24,
|
||||
roi->width, roi->height);
|
||||
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)
|
||||
{
|
||||
cairo_surface_destroy (image);
|
||||
}
|
||||
|
||||
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_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);
|
||||
|
||||
red = cairo_mime_surface_create (NULL, CAIRO_CONTENT_COLOR, WIDTH, HEIGHT);
|
||||
cairo_mime_surface_set_acquire (red, red_acquire, release);
|
||||
|
||||
cairo_set_source_rgb (cr, 0, 0, 1);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_translate (cr, 0, (HEIGHT-png_height)/2);
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
cairo_surface_t *source;
|
||||
if ((i ^ j) & 1)
|
||||
source = red;
|
||||
else
|
||||
source = png;
|
||||
cairo_set_source_surface (cr, source, 0, 0);
|
||||
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;
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
}
|
||||
|
||||
CAIRO_TEST (mime_surface,
|
||||
"Check that the mime-surface embedding works",
|
||||
"api", /* keywords */
|
||||
NULL, /* requirements */
|
||||
WIDTH, HEIGHT,
|
||||
preamble, draw)
|
||||
BIN
test/mime-surface.ref.png
Normal file
BIN
test/mime-surface.ref.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
|
|
@ -3495,6 +3495,55 @@ 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_surface_t *ret;
|
||||
|
||||
_enter_trace ();
|
||||
|
||||
ret = DLCALL (cairo_mime_surface_create, data, content, width, height);
|
||||
|
||||
_emit_line_info ();
|
||||
if (_write_lock ()) {
|
||||
Object *obj = _create_surface (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 */
|
||||
switch (content) {
|
||||
case CAIRO_CONTENT_ALPHA: format = CAIRO_FORMAT_A8; break;
|
||||
case CAIRO_CONTENT_COLOR: format = CAIRO_FORMAT_RGB24; break;
|
||||
default:
|
||||
case CAIRO_CONTENT_COLOR_ALPHA: format = CAIRO_FORMAT_ARGB32; break;
|
||||
}
|
||||
|
||||
_trace_printf ("%% mime-surface\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_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);
|
||||
|
||||
obj->width = width;
|
||||
obj->height = height;
|
||||
obj->defined = TRUE;
|
||||
_push_object (obj);
|
||||
_write_unlock ();
|
||||
}
|
||||
|
||||
_exit_trace ();
|
||||
return ret;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_surface_create_similar (cairo_surface_t *other,
|
||||
cairo_content_t content,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue