mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-25 00:10:10 +01:00
API: map-to-image and create-similar-image
A common requirement is the fast upload of pixel data. In order to allocate the most appropriate image buffer, we need knowledge of the destination. The most obvious example is that we could use a shared-memory region for the image to avoid the transfer cost of uploading the pixels to the X server. Similarly, gl, win32, quartz... The other side of the equation is that for manual modification of a remote surface, it would be more efficient if we can create a similar image to reduce the transfer costs. This strategy is already followed for the destination fallbacks and this merely exposes the same capability for the application fallbacks. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
c6812c6a36
commit
a69335a84e
42 changed files with 1168 additions and 360 deletions
|
|
@ -643,10 +643,14 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
|
|||
|
||||
static const cairo_surface_backend_t cairo_analysis_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_ANALYSIS,
|
||||
|
||||
_cairo_analysis_surface_finish,
|
||||
NULL,
|
||||
|
||||
NULL, /* create_similar */
|
||||
_cairo_analysis_surface_finish,
|
||||
NULL, /* create_similar_image */
|
||||
NULL, /* map_to_image */
|
||||
NULL, /* unmap */
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
NULL, /* acquire_dest_image */
|
||||
|
|
@ -842,10 +846,14 @@ typedef cairo_int_status_t
|
|||
|
||||
static const cairo_surface_backend_t cairo_null_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_NULL,
|
||||
NULL, /* finish */
|
||||
|
||||
_cairo_default_context_create, /* XXX */
|
||||
|
||||
NULL, /* create_similar */
|
||||
NULL, /* finish */
|
||||
NULL, /* create similar image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image*/
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
NULL, /* acquire_dest_image */
|
||||
|
|
|
|||
|
|
@ -1829,10 +1829,15 @@ _cairo_directfb_surface_is_similar (void *surface_a, void *surface_b)
|
|||
static cairo_surface_backend_t
|
||||
_cairo_directfb_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_DIRECTFB, /*type*/
|
||||
_cairo_directfb_surface_finish, /*finish*/
|
||||
|
||||
_cairo_default_context_create,
|
||||
|
||||
_cairo_directfb_surface_create_similar,/*create_similar*/
|
||||
_cairo_directfb_surface_finish, /*finish*/
|
||||
NULL, /* create similar image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image */
|
||||
|
||||
_cairo_directfb_surface_acquire_source_image,/*acquire_source_image*/
|
||||
_cairo_directfb_surface_release_source_image,/*release_source_image*/
|
||||
_cairo_directfb_surface_acquire_dest_image,/*acquire_dest_image*/
|
||||
|
|
|
|||
|
|
@ -41,6 +41,8 @@
|
|||
#include "cairo.h"
|
||||
#include "cairo-compiler-private.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
enum _cairo_int_status {
|
||||
|
|
@ -100,6 +102,13 @@ enum _cairo_int_status {
|
|||
#define _cairo_int_status_is_error(status) \
|
||||
(status != CAIRO_INT_STATUS_SUCCESS && status <= CAIRO_INT_STATUS_LAST_STATUS)
|
||||
|
||||
static inline cairo_status_t
|
||||
_cairo_public_status (cairo_int_status_t status)
|
||||
{
|
||||
assert (status <= CAIRO_INT_STATUS_LAST_STATUS);
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_error (cairo_status_t status);
|
||||
|
||||
|
|
|
|||
|
|
@ -1764,10 +1764,13 @@ _cairo_gl_surface_fill (void *abstract_surface,
|
|||
|
||||
const cairo_surface_backend_t _cairo_gl_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_GL,
|
||||
_cairo_gl_surface_finish,
|
||||
_cairo_default_context_create,
|
||||
|
||||
_cairo_gl_surface_create_similar,
|
||||
_cairo_gl_surface_finish,
|
||||
NULL, /* similar image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image */
|
||||
|
||||
_cairo_gl_surface_acquire_source_image,
|
||||
_cairo_gl_surface_release_source_image,
|
||||
|
|
|
|||
|
|
@ -728,6 +728,36 @@ _cairo_image_surface_create_similar (void *abstract_other,
|
|||
width, height);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_image_surface_map_to_image (void *abstract_other,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_image_surface_t *other = abstract_other;
|
||||
cairo_surface_t *surface;
|
||||
uint8_t *data;
|
||||
|
||||
data = other->data;
|
||||
data += extents->y * other->stride;
|
||||
data += extents->x * PIXMAN_FORMAT_BPP (other->pixman_format)/ 8;
|
||||
|
||||
surface =
|
||||
_cairo_image_surface_create_with_pixman_format (data,
|
||||
other->pixman_format,
|
||||
extents->width,
|
||||
extents->height,
|
||||
other->stride);
|
||||
|
||||
cairo_surface_set_device_offset (surface, -extents->x, -extents->y);
|
||||
return surface;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_image_surface_unmap_image (void *abstract_surface,
|
||||
cairo_image_surface_t *image)
|
||||
{
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_image_surface_finish (void *abstract_surface)
|
||||
{
|
||||
|
|
@ -4655,10 +4685,15 @@ _cairo_surface_is_image (const cairo_surface_t *surface)
|
|||
|
||||
const cairo_surface_backend_t _cairo_image_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
_cairo_image_surface_finish,
|
||||
|
||||
_cairo_default_context_create,
|
||||
|
||||
_cairo_image_surface_create_similar,
|
||||
_cairo_image_surface_finish,
|
||||
NULL, /* create similar image */
|
||||
_cairo_image_surface_map_to_image,
|
||||
_cairo_image_surface_unmap_image,
|
||||
|
||||
_cairo_image_surface_acquire_source_image,
|
||||
_cairo_image_surface_release_source_image,
|
||||
_cairo_image_surface_acquire_dest_image,
|
||||
|
|
|
|||
|
|
@ -1439,10 +1439,14 @@ _cairo_os2_surface_mark_dirty_rectangle (void *surface,
|
|||
|
||||
static const cairo_surface_backend_t cairo_os2_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_OS2,
|
||||
_cairo_os2_surface_finish,
|
||||
_cairo_default_context_create,
|
||||
|
||||
NULL, /* create_similar */
|
||||
_cairo_os2_surface_finish,
|
||||
NULL, /* create_similar_image */
|
||||
NULL, /* map_to_image */
|
||||
NULL, /* unmap_image */
|
||||
|
||||
_cairo_os2_surface_acquire_source_image,
|
||||
_cairo_os2_surface_release_source_image,
|
||||
_cairo_os2_surface_acquire_dest_image,
|
||||
|
|
|
|||
|
|
@ -649,10 +649,15 @@ _cairo_paginated_context_create (void *target)
|
|||
|
||||
static const cairo_surface_backend_t cairo_paginated_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_PAGINATED,
|
||||
_cairo_paginated_surface_finish,
|
||||
|
||||
_cairo_paginated_context_create,
|
||||
|
||||
_cairo_paginated_surface_create_similar,
|
||||
_cairo_paginated_surface_finish,
|
||||
NULL, /* create simlar image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image */
|
||||
|
||||
_cairo_paginated_surface_acquire_source_image,
|
||||
_cairo_paginated_surface_release_source_image,
|
||||
NULL, /* acquire_dest_image */
|
||||
|
|
|
|||
|
|
@ -6567,10 +6567,15 @@ _cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
|
|||
|
||||
static const cairo_surface_backend_t cairo_pdf_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_PDF,
|
||||
_cairo_pdf_surface_finish,
|
||||
|
||||
_cairo_default_context_create,
|
||||
|
||||
NULL, /* create similar: handled by wrapper */
|
||||
_cairo_pdf_surface_finish,
|
||||
NULL, /* create similar image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image */
|
||||
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
NULL, /* acquire_dest_image */
|
||||
|
|
|
|||
|
|
@ -3932,10 +3932,15 @@ _cairo_ps_surface_supports_fine_grained_fallbacks (void *abstract_surface)
|
|||
|
||||
static const cairo_surface_backend_t cairo_ps_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_PS,
|
||||
_cairo_ps_surface_finish,
|
||||
|
||||
_cairo_default_context_create,
|
||||
|
||||
NULL, /* create similar: handled by wrapper */
|
||||
_cairo_ps_surface_finish,
|
||||
NULL, /* create similar image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image */
|
||||
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
NULL, /* acquire_dest_image */
|
||||
|
|
|
|||
|
|
@ -160,10 +160,15 @@ _cairo_quartz_image_surface_flush (void *asurface)
|
|||
|
||||
static const cairo_surface_backend_t cairo_quartz_image_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_QUARTZ_IMAGE,
|
||||
_cairo_quartz_image_surface_finish,
|
||||
|
||||
_cairo_default_context_create,
|
||||
|
||||
_cairo_quartz_image_surface_create_similar,
|
||||
_cairo_quartz_image_surface_finish,
|
||||
NULL, /* create_similar_image */
|
||||
NULL, /* map_to_image */
|
||||
NULL, /* unmap_image */
|
||||
|
||||
_cairo_quartz_image_surface_acquire_source_image,
|
||||
NULL, /* release_source_image */
|
||||
_cairo_quartz_image_surface_acquire_dest_image,
|
||||
|
|
|
|||
|
|
@ -805,10 +805,15 @@ _cairo_surface_is_recording (const cairo_surface_t *surface)
|
|||
|
||||
static const cairo_surface_backend_t cairo_recording_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_RECORDING,
|
||||
_cairo_recording_surface_finish,
|
||||
|
||||
_cairo_default_context_create,
|
||||
|
||||
_cairo_recording_surface_create_similar,
|
||||
_cairo_recording_surface_finish,
|
||||
NULL, /* create similar image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image */
|
||||
|
||||
_cairo_recording_surface_acquire_source_image,
|
||||
_cairo_recording_surface_release_source_image,
|
||||
NULL, /* acquire_dest_image */
|
||||
|
|
|
|||
|
|
@ -298,3 +298,13 @@ _cairo_box_add_curve_to (cairo_box_t *extents,
|
|||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_rectangle_int_from_double (cairo_rectangle_int_t *recti,
|
||||
const cairo_rectangle_t *rectf)
|
||||
{
|
||||
recti->x = floor (rectf->x);
|
||||
recti->y = floor (rectf->y);
|
||||
recti->width = ceil (rectf->x + rectf->width) - floor (rectf->x);
|
||||
recti->height = ceil (rectf->y + rectf->height) - floor (rectf->y);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3409,10 +3409,15 @@ _cairo_script_surface_get_extents (void *abstract_surface,
|
|||
static const cairo_surface_backend_t
|
||||
_cairo_script_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_SCRIPT,
|
||||
_cairo_script_surface_finish,
|
||||
|
||||
_cairo_default_context_create,
|
||||
|
||||
_cairo_script_surface_create_similar,
|
||||
_cairo_script_surface_finish,
|
||||
NULL, /* create similar image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image */
|
||||
|
||||
_cairo_script_surface_acquire_source_image,
|
||||
_cairo_script_surface_release_source_image,
|
||||
NULL, /* acquire_dest_image */
|
||||
|
|
|
|||
|
|
@ -89,10 +89,13 @@ _cairo_surface_snapshot_get_extents (void *abstract_surface,
|
|||
|
||||
static const cairo_surface_backend_t _cairo_surface_snapshot_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_SNAPSHOT,
|
||||
_cairo_surface_snapshot_finish,
|
||||
NULL,
|
||||
|
||||
NULL, /* create similar */
|
||||
_cairo_surface_snapshot_finish,
|
||||
NULL, /* create similar image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image */
|
||||
|
||||
_cairo_surface_snapshot_acquire_source_image,
|
||||
_cairo_surface_snapshot_release_source_image,
|
||||
|
|
|
|||
|
|
@ -61,6 +61,48 @@ _cairo_surface_subsurface_create_similar (void *other,
|
|||
return surface->target->backend->create_similar (surface->target, content, width, height);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_surface_subsurface_create_similar_image (void *other,
|
||||
cairo_format_t format,
|
||||
int width, int height)
|
||||
{
|
||||
cairo_surface_subsurface_t *surface = other;
|
||||
return surface->target->backend->create_similar_image (surface->target,
|
||||
format,
|
||||
width, height);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_surface_subsurface_map_to_image (void *abstract_surface,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_surface_subsurface_t *surface = abstract_surface;
|
||||
cairo_rectangle_int_t target_extents;
|
||||
|
||||
if (surface->target->backend->map_to_image == NULL)
|
||||
return NULL;
|
||||
|
||||
target_extents.x = extents->x + surface->extents.x;
|
||||
target_extents.y = extents->y + surface->extents.y;
|
||||
target_extents.width = extents->width;
|
||||
target_extents.height = extents->height;
|
||||
|
||||
return surface->target->backend->map_to_image (surface->target,
|
||||
&target_extents);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_surface_subsurface_unmap_image (void *abstract_surface,
|
||||
cairo_image_surface_t *image)
|
||||
{
|
||||
cairo_surface_subsurface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->target->backend->unmap_image == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
return surface->target->backend->unmap_image (surface->target, image);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_surface_subsurface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
|
|
@ -426,10 +468,14 @@ _cairo_surface_subsurface_create_context(void *target)
|
|||
|
||||
static const cairo_surface_backend_t _cairo_surface_subsurface_backend = {
|
||||
CAIRO_SURFACE_TYPE_SUBSURFACE,
|
||||
_cairo_surface_subsurface_finish,
|
||||
|
||||
_cairo_surface_subsurface_create_context,
|
||||
|
||||
_cairo_surface_subsurface_create_similar,
|
||||
_cairo_surface_subsurface_finish,
|
||||
_cairo_surface_subsurface_create_similar_image,
|
||||
_cairo_surface_subsurface_map_to_image,
|
||||
_cairo_surface_subsurface_unmap_image,
|
||||
|
||||
_cairo_surface_subsurface_acquire_source_image,
|
||||
_cairo_surface_subsurface_release_source_image,
|
||||
|
|
@ -533,4 +579,36 @@ cairo_surface_create_for_rectangle (cairo_surface_t *target,
|
|||
|
||||
return &surface->base;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_surface_create_for_rectangle_int (cairo_surface_t *target,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_surface_subsurface_t *surface;
|
||||
|
||||
if (unlikely (target->status))
|
||||
return _cairo_surface_create_in_error (target->status);
|
||||
if (unlikely (target->finished))
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
|
||||
|
||||
assert (target->backend->type != CAIRO_SURFACE_TYPE_SUBSURFACE);
|
||||
|
||||
surface = malloc (sizeof (cairo_surface_subsurface_t));
|
||||
if (unlikely (surface == NULL))
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
||||
assert (_cairo_matrix_is_translation (&target->device_transform));
|
||||
|
||||
_cairo_surface_init (&surface->base,
|
||||
&_cairo_surface_subsurface_backend,
|
||||
NULL, /* device */
|
||||
target->content);
|
||||
|
||||
surface->extents = *extents;
|
||||
surface->extents.x += target->device_transform.x0;
|
||||
surface->extents.y += target->device_transform.y0;
|
||||
surface->target = cairo_surface_reference (target);
|
||||
|
||||
return &surface->base;
|
||||
}
|
||||
/* XXX observe mark-dirty */
|
||||
|
|
|
|||
|
|
@ -519,6 +519,188 @@ cairo_surface_create_similar (cairo_surface_t *other,
|
|||
return surface;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* cairo_surface_create_similar_image:
|
||||
* @other: an existing surface used to select the preference of the new surface
|
||||
* @format: the format for the new surface
|
||||
* @width: width of the new surface, (in device-space units)
|
||||
* @height: height of the new surface (in device-space units)
|
||||
*
|
||||
* Create a new image surface that is as compatible as possible for uploading
|
||||
* to and the use in conjunction with an existing surface.
|
||||
*
|
||||
* Initially the surface contents are all 0 (transparent if contents
|
||||
* have transparency, black otherwise.)
|
||||
*
|
||||
* Return value: a pointer to the newly allocated image surface. The caller
|
||||
* owns the surface and should call cairo_surface_destroy() when done
|
||||
* with it.
|
||||
*
|
||||
* This function always returns a valid pointer, but it will return a
|
||||
* pointer to a "nil" surface if @other is already in an error state
|
||||
* or any other error occurs.
|
||||
**/
|
||||
cairo_surface_t *
|
||||
cairo_surface_create_similar_image (cairo_surface_t *other,
|
||||
cairo_format_t format,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if (other->status)
|
||||
return _cairo_surface_create_in_error (other->status);
|
||||
if (unlikely (other->finished))
|
||||
return _cairo_surface_create_in_error (CAIRO_STATUS_SURFACE_FINISHED);
|
||||
|
||||
if (unlikely (width < 0 || height < 0))
|
||||
return _cairo_surface_create_in_error (CAIRO_STATUS_INVALID_SIZE);
|
||||
if (unlikely (! CAIRO_FORMAT_VALID (format)))
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
|
||||
|
||||
if (other->backend->create_similar_image)
|
||||
return other->backend->create_similar_image (other,
|
||||
format, width, height);
|
||||
|
||||
return cairo_image_surface_create (format, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_surface_map_to_image:
|
||||
* @surface: an existing surface used to extract the image from
|
||||
* @extents: limit the extraction to an rectangular region
|
||||
*
|
||||
* Returns an image surface that is the most efficient mechanism for
|
||||
* modifying the backing store of the target surface. The region retrieved
|
||||
* may be limited to the @extents or %NULL for the whole surface
|
||||
*
|
||||
* Note, the use of the original surface as a target or source whilst it is
|
||||
* mapped is undefined. The result of mapping the surface multiple times is
|
||||
* undefined.
|
||||
*
|
||||
* Return value: a pointer to the newly allocated image surface. The caller
|
||||
* owns the surface and should call cairo_surface_destroy() when done
|
||||
* with it.
|
||||
*
|
||||
* This function always returns a valid pointer, but it will return a
|
||||
* pointer to a "nil" surface if @other is already in an error state
|
||||
* or any other error occurs.
|
||||
**/
|
||||
cairo_surface_t *
|
||||
cairo_surface_map_to_image (cairo_surface_t *surface,
|
||||
const cairo_rectangle_t *extents)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_surface_t *image;
|
||||
|
||||
if (unlikely (surface->status))
|
||||
return _cairo_surface_create_in_error (surface->status);
|
||||
if (unlikely (surface->finished))
|
||||
return _cairo_surface_create_in_error (CAIRO_STATUS_SURFACE_FINISHED);
|
||||
|
||||
if (extents == NULL) {
|
||||
if (unlikely (! surface->backend->get_extents (surface, &rect)))
|
||||
return _cairo_surface_create_in_error (CAIRO_STATUS_INVALID_SIZE);
|
||||
} else {
|
||||
_cairo_rectangle_int_from_double (&rect, extents);
|
||||
}
|
||||
|
||||
image = NULL;
|
||||
if (surface->backend->map_to_image)
|
||||
image = surface->backend->map_to_image (surface, &rect);
|
||||
|
||||
if (image == NULL) {
|
||||
cairo_surface_pattern_t pattern;
|
||||
cairo_status_t status;
|
||||
|
||||
image = cairo_image_surface_create (_cairo_format_from_content (surface->content),
|
||||
rect.width, rect.height);
|
||||
cairo_surface_set_device_offset (image, -rect.y, -rect.y);
|
||||
|
||||
_cairo_pattern_init_for_surface (&pattern, surface);
|
||||
pattern.base.filter = CAIRO_FILTER_NEAREST;
|
||||
|
||||
status = _cairo_surface_paint (image,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
&pattern.base,
|
||||
NULL);
|
||||
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (image);
|
||||
image = _cairo_surface_create_in_error (status);
|
||||
}
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_surface_unmap_image:
|
||||
* @surface: an existing surface used to extract the image from
|
||||
* @image: the currently mapped image
|
||||
*
|
||||
* Unmaps the image surface as returned from #cairo_surface_map_to_image().
|
||||
* Returns an image surface that is the most efficient mechanism for
|
||||
* modifying the backing store of the target surface. The region retrieved
|
||||
* may be limited to the @extents or %NULL for the whole surface
|
||||
*
|
||||
* Return value: a pointer to the newly allocated image surface. The caller
|
||||
* owns the surface and should call cairo_surface_destroy() when done
|
||||
* with it.
|
||||
*
|
||||
* This function always returns a valid pointer, but it will return a
|
||||
* pointer to a "nil" surface if @other is already in an error state
|
||||
* or any other error occurs.
|
||||
**/
|
||||
void
|
||||
cairo_surface_unmap_image (cairo_surface_t *surface,
|
||||
cairo_surface_t *image)
|
||||
{
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (unlikely (surface->status)) {
|
||||
status = surface->status;
|
||||
goto error;
|
||||
}
|
||||
if (unlikely (surface->finished)) {
|
||||
status = _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (unlikely (image->status)) {
|
||||
status = image->status;
|
||||
goto error;
|
||||
}
|
||||
if (unlikely (image->finished)) {
|
||||
status = _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
|
||||
goto error;
|
||||
}
|
||||
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (surface->backend->unmap_image)
|
||||
status = surface->backend->unmap_image (surface, image);
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
cairo_surface_pattern_t pattern;
|
||||
|
||||
_cairo_pattern_init_for_surface (&pattern, image);
|
||||
pattern.base.filter = CAIRO_FILTER_NEAREST;
|
||||
|
||||
status = _cairo_surface_paint (surface,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
&pattern.base,
|
||||
NULL);
|
||||
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
}
|
||||
|
||||
error:
|
||||
cairo_surface_finish (image);
|
||||
cairo_surface_destroy (image);
|
||||
if (status)
|
||||
_cairo_status_set_error (&surface->status, status);
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_surface_create_similar_solid (cairo_surface_t *other,
|
||||
cairo_content_t content,
|
||||
|
|
|
|||
|
|
@ -2575,10 +2575,15 @@ _cairo_svg_surface_get_font_options (void *abstract_surface,
|
|||
|
||||
static const cairo_surface_backend_t cairo_svg_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_SVG,
|
||||
_cairo_svg_surface_finish,
|
||||
|
||||
_cairo_default_context_create,
|
||||
|
||||
NULL, /* create_similar: handled by wrapper */
|
||||
_cairo_svg_surface_finish,
|
||||
NULL, /* create_similar_image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image */
|
||||
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
NULL, /* acquire_dest_image */
|
||||
|
|
|
|||
|
|
@ -396,10 +396,15 @@ _cairo_tee_surface_show_text_glyphs (void *abstract_surface,
|
|||
|
||||
static const cairo_surface_backend_t cairo_tee_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_TEE,
|
||||
_cairo_tee_surface_finish,
|
||||
|
||||
_cairo_default_context_create, /* XXX */
|
||||
|
||||
_cairo_tee_surface_create_similar,
|
||||
_cairo_tee_surface_finish,
|
||||
NULL, /* create similar image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image */
|
||||
|
||||
_cairo_tee_surface_acquire_source_image,
|
||||
_cairo_tee_surface_release_source_image,
|
||||
NULL, NULL, /* dest_image */
|
||||
|
|
|
|||
|
|
@ -322,10 +322,15 @@ _cairo_type3_glyph_surface_show_glyphs (void *abstract_surface,
|
|||
|
||||
static const cairo_surface_backend_t cairo_type3_glyph_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TYPE3_GLYPH,
|
||||
_cairo_type3_glyph_surface_finish,
|
||||
|
||||
_cairo_default_context_create,
|
||||
|
||||
NULL, /* _cairo_type3_glyph_surface_create_similar */
|
||||
_cairo_type3_glyph_surface_finish,
|
||||
NULL, /* _cairo_type3_glyph_surface_create_similar_image */
|
||||
NULL, /* _cairo_type3_glyph_surface_create_map_to_image */
|
||||
NULL, /* _cairo_type3_glyph_surface_create_unmap_image */
|
||||
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
NULL, /* acquire_dest_image */
|
||||
|
|
|
|||
|
|
@ -1548,10 +1548,13 @@ _vg_surface_finish (void *abstract_surface)
|
|||
|
||||
static const cairo_surface_backend_t cairo_vg_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_VG,
|
||||
_vg_surface_finish,
|
||||
_cairo_default_context_create, /* XXX */
|
||||
|
||||
_vg_surface_create_similar,
|
||||
_vg_surface_finish,
|
||||
NULL, /* create similar image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image */
|
||||
|
||||
_vg_surface_acquire_source_image,
|
||||
_vg_surface_release_source_image,
|
||||
|
|
|
|||
|
|
@ -1862,10 +1862,15 @@ _cairo_surface_is_win32_printing (cairo_surface_t *surface)
|
|||
|
||||
static const cairo_surface_backend_t cairo_win32_printing_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_WIN32_PRINTING,
|
||||
_cairo_win32_surface_finish,
|
||||
|
||||
_cairo_default_context_create,
|
||||
|
||||
_cairo_win32_printing_surface_create_similar,
|
||||
_cairo_win32_surface_finish,
|
||||
NULL, /* create similar image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image */
|
||||
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
NULL, /* acquire_dest_image */
|
||||
|
|
|
|||
|
|
@ -549,6 +549,65 @@ _cairo_win32_surface_get_subimage (cairo_win32_surface_t *surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_win32_surface_map_to_image (void *abstract_surface,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_win32_surface_t *surface = abstract_surface;
|
||||
cairo_win32_surface_t *local = NULL;
|
||||
cairo_status_t status;
|
||||
|
||||
if (surface->image) {
|
||||
GdiFlush();
|
||||
return _cairo_surface_create_for_rectangle_int (surface->image,
|
||||
extents);
|
||||
}
|
||||
|
||||
status = _cairo_win32_surface_get_subimage (abstract_surface,
|
||||
extents->x,
|
||||
extents->y,
|
||||
extents->width,
|
||||
extents->height,
|
||||
&local);
|
||||
if (unlikely (status))
|
||||
return _cairo_surface_create_in_error (status);
|
||||
|
||||
status = _cairo_surface_set_user_data (&local->image->user_data,
|
||||
(const cairo_user_data_key_t *)surface->image,
|
||||
local, NULL);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (&local->base);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
cairo_surface_set_device_offset (local->image, -extents->x, -extents->y);
|
||||
return local->image;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_win32_surface_release_unmap_image (void *abstract_surface,
|
||||
cairo_image_surface_t *image)
|
||||
{
|
||||
cairo_win32_surface_t *surface = abstract_surface;
|
||||
cairo_win32_surface_t *local;
|
||||
|
||||
local = _cairo_surface_set_user_data (&image->base.user_data,
|
||||
(const cairo_user_data_key_t *)surface->image);
|
||||
if (!local)
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
|
||||
if (!BitBlt (surface->dc,
|
||||
image->device_transform.x0,
|
||||
image->device_transform.y0,
|
||||
image->width, image->height,
|
||||
local->dc,
|
||||
0, 0,
|
||||
SRCCOPY))
|
||||
_cairo_win32_print_gdi_error ("_cairo_win32_surface_release_dest_image");
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_surface_acquire_source_image (void *abstract_surface,
|
||||
cairo_image_surface_t **image_out,
|
||||
|
|
@ -2087,10 +2146,15 @@ _cairo_win32_surface_create_span_renderer (cairo_operator_t op,
|
|||
|
||||
static const cairo_surface_backend_t cairo_win32_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_WIN32,
|
||||
_cairo_win32_surface_finish,
|
||||
|
||||
_cairo_default_context_create,
|
||||
|
||||
_cairo_win32_surface_create_similar,
|
||||
_cairo_win32_surface_finish,
|
||||
NULL,
|
||||
_cairo_win32_surface_map_to_image,
|
||||
_cairo_win32_surface_unmap_image,
|
||||
|
||||
_cairo_win32_surface_acquire_source_image,
|
||||
_cairo_win32_surface_release_source_image,
|
||||
_cairo_win32_surface_acquire_dest_image,
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ struct _cairo_xcb_shm_info {
|
|||
|
||||
struct _cairo_xcb_surface {
|
||||
cairo_surface_t base;
|
||||
cairo_surface_t *fallback;
|
||||
cairo_image_surface_t *fallback;
|
||||
|
||||
cairo_xcb_connection_t *connection;
|
||||
cairo_xcb_screen_t *screen;
|
||||
|
|
@ -353,9 +353,10 @@ _cairo_xcb_screen_lookup_radial_picture (cairo_xcb_screen_t *screen,
|
|||
const cairo_radial_pattern_t *radial);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_xcb_surface_create_similar_image (cairo_xcb_surface_t *other,
|
||||
cairo_content_t content,
|
||||
int width, int height);
|
||||
_cairo_xcb_surface_create_similar_image (void *abstrct_other,
|
||||
cairo_format_t format,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_xcb_surface_create_similar (void *abstract_other,
|
||||
|
|
|
|||
|
|
@ -74,8 +74,6 @@ _cairo_xcb_pixmap_finish (void *abstract_surface)
|
|||
|
||||
static const cairo_surface_backend_t _cairo_xcb_pixmap_backend = {
|
||||
CAIRO_SURFACE_TYPE_XCB,
|
||||
NULL,
|
||||
NULL,
|
||||
_cairo_xcb_pixmap_finish,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -101,8 +101,6 @@ _cairo_xcb_picture_finish (void *abstract_surface)
|
|||
|
||||
static const cairo_surface_backend_t _cairo_xcb_picture_backend = {
|
||||
CAIRO_SURFACE_TYPE_XCB,
|
||||
NULL,
|
||||
NULL,
|
||||
_cairo_xcb_picture_finish,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -73,98 +73,6 @@ slim_hidden_proto (cairo_xcb_surface_create_with_xrender_format);
|
|||
* This macro can be used to conditionally compile backend-specific code.
|
||||
*/
|
||||
|
||||
#if CAIRO_HAS_XCB_SHM_FUNCTIONS
|
||||
static cairo_status_t
|
||||
_cairo_xcb_surface_create_similar_shm (cairo_xcb_surface_t *other,
|
||||
pixman_format_code_t pixman_format,
|
||||
int width, int height,
|
||||
cairo_surface_t **out)
|
||||
{
|
||||
size_t size, stride;
|
||||
cairo_xcb_shm_info_t *shm_info;
|
||||
cairo_status_t status;
|
||||
cairo_surface_t *image;
|
||||
|
||||
stride = CAIRO_STRIDE_FOR_WIDTH_BPP (width, PIXMAN_FORMAT_BPP (pixman_format));
|
||||
size = stride * height;
|
||||
if (size < CAIRO_XCB_SHM_SMALL_IMAGE)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_xcb_connection_allocate_shm_info (other->connection,
|
||||
size, &shm_info);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
image = _cairo_image_surface_create_with_pixman_format (shm_info->mem,
|
||||
pixman_format,
|
||||
width, height,
|
||||
stride);
|
||||
status = image->status;
|
||||
if (unlikely (status)) {
|
||||
_cairo_xcb_shm_info_destroy (shm_info);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = _cairo_user_data_array_set_data (&image->user_data,
|
||||
(const cairo_user_data_key_t *) other->connection,
|
||||
shm_info,
|
||||
(cairo_destroy_func_t) _cairo_xcb_shm_info_destroy);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (image);
|
||||
_cairo_xcb_shm_info_destroy (shm_info);
|
||||
return status;
|
||||
}
|
||||
|
||||
*out = image;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_xcb_surface_create_similar_image (cairo_xcb_surface_t *other,
|
||||
cairo_content_t content,
|
||||
int width, int height)
|
||||
{
|
||||
cairo_surface_t *image = NULL;
|
||||
pixman_format_code_t pixman_format;
|
||||
|
||||
/* XXX choose pixman_format from connection->image_formats */
|
||||
switch (content) {
|
||||
case CAIRO_CONTENT_ALPHA:
|
||||
pixman_format = PIXMAN_a8;
|
||||
break;
|
||||
case CAIRO_CONTENT_COLOR:
|
||||
pixman_format = PIXMAN_x8r8g8b8;
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
case CAIRO_CONTENT_COLOR_ALPHA:
|
||||
pixman_format = PIXMAN_a8r8g8b8;
|
||||
break;
|
||||
}
|
||||
|
||||
#if CAIRO_HAS_XCB_SHM_FUNCTIONS
|
||||
if (other->connection->flags & CAIRO_XCB_HAS_SHM) {
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_xcb_surface_create_similar_shm (other,
|
||||
pixman_format,
|
||||
width, height,
|
||||
&image);
|
||||
/* Ignore errors and fall through */
|
||||
}
|
||||
#endif
|
||||
|
||||
if (image == NULL) {
|
||||
image = _cairo_image_surface_create_with_pixman_format (NULL,
|
||||
pixman_format,
|
||||
width, height,
|
||||
0);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_xcb_surface_create_similar (void *abstract_other,
|
||||
cairo_content_t content,
|
||||
|
|
@ -181,10 +89,13 @@ _cairo_xcb_surface_create_similar (void *abstract_other,
|
|||
height > XLIB_COORD_MAX ||
|
||||
width <= 0 ||
|
||||
height <= 0))
|
||||
return _cairo_xcb_surface_create_similar_image (other, content, width, height);
|
||||
return cairo_image_surface_create (_cairo_format_from_content (content),
|
||||
width, height);
|
||||
|
||||
if ((other->connection->flags & CAIRO_XCB_HAS_RENDER) == 0)
|
||||
return _cairo_xcb_surface_create_similar_image (other, content, width, height);
|
||||
return _cairo_xcb_surface_create_similar_image (other,
|
||||
_cairo_format_from_content (content),
|
||||
width, height);
|
||||
|
||||
connection = other->connection;
|
||||
status = _cairo_xcb_connection_acquire (connection);
|
||||
|
|
@ -246,6 +157,64 @@ _cairo_xcb_surface_create_similar (void *abstract_other,
|
|||
return &surface->base;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_xcb_surface_create_similar_image (void *abstract_other,
|
||||
cairo_format_t format,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_xcb_surface_t *other = abstract_other;
|
||||
cairo_xcb_connection_t *connection = other->connection;
|
||||
|
||||
#if CAIRO_HAS_XCB_SHM_FUNCTIONS
|
||||
cairo_surface_t *image;
|
||||
cairo_xcb_shm_info_t *shm_info;
|
||||
cairo_status_t status;
|
||||
size_t stride;
|
||||
pixman_format_code_t pixman_format;
|
||||
|
||||
if (unlikely(width > XLIB_COORD_MAX || height > XLIB_COORD_MAX))
|
||||
return cairo_image_surface_create (format, width, height);
|
||||
|
||||
if ((connection->flags & CAIRO_XCB_HAS_SHM) == 0)
|
||||
return cairo_image_surface_create (format, width, height);
|
||||
|
||||
pixman_format = _cairo_format_to_pixman_format_code (format);
|
||||
|
||||
stride = CAIRO_STRIDE_FOR_WIDTH_BPP (width,
|
||||
PIXMAN_FORMAT_BPP (pixman_format));
|
||||
status = _cairo_xcb_connection_allocate_shm_info (connection,
|
||||
stride * height,
|
||||
&shm_info);
|
||||
if (unlikely (status))
|
||||
return _cairo_surface_create_in_error (status);
|
||||
|
||||
image = _cairo_image_surface_create_with_pixman_format (shm_info->mem,
|
||||
pixman_format,
|
||||
width,
|
||||
height,
|
||||
stride);
|
||||
if (unlikely (image->status)) {
|
||||
_cairo_xcb_shm_info_destroy (shm_info);
|
||||
return image;
|
||||
}
|
||||
|
||||
status = _cairo_user_data_array_set_data (&image->user_data,
|
||||
(const cairo_user_data_key_t *) connection,
|
||||
shm_info,
|
||||
(cairo_destroy_func_t) _cairo_xcb_shm_info_destroy);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (image);
|
||||
_cairo_xcb_shm_info_destroy (shm_info);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
return image;
|
||||
#else
|
||||
return cairo_image_surface_create (format, width, height);
|
||||
#endif
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xcb_surface_finish (void *abstract_surface)
|
||||
{
|
||||
|
|
@ -253,8 +222,8 @@ _cairo_xcb_surface_finish (void *abstract_surface)
|
|||
cairo_status_t status;
|
||||
|
||||
if (surface->fallback != NULL) {
|
||||
cairo_surface_finish (surface->fallback);
|
||||
cairo_surface_destroy (surface->fallback);
|
||||
cairo_surface_finish (&surface->fallback->base);
|
||||
cairo_surface_destroy (&surface->fallback->base);
|
||||
}
|
||||
|
||||
cairo_list_del (&surface->link);
|
||||
|
|
@ -283,144 +252,142 @@ _destroy_image (pixman_image_t *image, void *data)
|
|||
}
|
||||
|
||||
#if CAIRO_HAS_XCB_SHM_FUNCTIONS
|
||||
static cairo_int_status_t
|
||||
_cairo_xcb_surface_create_shm_image (cairo_xcb_surface_t *target,
|
||||
cairo_image_surface_t **image_out,
|
||||
static cairo_surface_t *
|
||||
_cairo_xcb_surface_create_shm_image (cairo_xcb_connection_t *connection,
|
||||
pixman_format_code_t pixman_format,
|
||||
int width, int height,
|
||||
cairo_xcb_shm_info_t **shm_info_out)
|
||||
{
|
||||
cairo_image_surface_t *image;
|
||||
cairo_surface_t *image;
|
||||
cairo_xcb_shm_info_t *shm_info;
|
||||
cairo_status_t status;
|
||||
size_t size, stride;
|
||||
size_t stride;
|
||||
|
||||
if ((target->connection->flags & CAIRO_XCB_HAS_SHM) == 0)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
*shm_info_out = NULL;
|
||||
|
||||
stride = CAIRO_STRIDE_FOR_WIDTH_BPP (target->width,
|
||||
PIXMAN_FORMAT_BPP (target->pixman_format));
|
||||
size = stride * target->height;
|
||||
if (size < CAIRO_XCB_SHM_SMALL_IMAGE) {
|
||||
target->connection->flags &= ~CAIRO_XCB_HAS_SHM;
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
status = _cairo_xcb_connection_allocate_shm_info (target->screen->connection,
|
||||
size, &shm_info);
|
||||
stride = CAIRO_STRIDE_FOR_WIDTH_BPP (width,
|
||||
PIXMAN_FORMAT_BPP (pixman_format));
|
||||
status = _cairo_xcb_connection_allocate_shm_info (connection,
|
||||
stride * height,
|
||||
&shm_info);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
return _cairo_surface_create_in_error (status);
|
||||
|
||||
image = (cairo_image_surface_t *)
|
||||
_cairo_image_surface_create_with_pixman_format (shm_info->mem,
|
||||
target->pixman_format,
|
||||
target->width,
|
||||
target->height,
|
||||
stride);
|
||||
status = image->base.status;
|
||||
if (unlikely (status)) {
|
||||
image = _cairo_image_surface_create_with_pixman_format (shm_info->mem,
|
||||
pixman_format,
|
||||
width, height,
|
||||
stride);
|
||||
if (unlikely (image->status)) {
|
||||
_cairo_xcb_shm_info_destroy (shm_info);
|
||||
return status;
|
||||
return image;
|
||||
}
|
||||
|
||||
status = _cairo_user_data_array_set_data (&image->base.user_data,
|
||||
(const cairo_user_data_key_t *) target->connection,
|
||||
status = _cairo_user_data_array_set_data (&image->user_data,
|
||||
(const cairo_user_data_key_t *) connection,
|
||||
shm_info,
|
||||
(cairo_destroy_func_t) _cairo_xcb_shm_info_destroy);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (&image->base);
|
||||
cairo_surface_destroy (image);
|
||||
_cairo_xcb_shm_info_destroy (shm_info);
|
||||
return status;
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
*image_out = image;
|
||||
*shm_info_out = shm_info;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return image;
|
||||
}
|
||||
#endif
|
||||
|
||||
static cairo_status_t
|
||||
_get_shm_image (cairo_xcb_surface_t *surface,
|
||||
cairo_image_surface_t **image_out)
|
||||
static cairo_image_surface_t *
|
||||
_get_shm_image (cairo_xcb_surface_t *surface,
|
||||
int x, int y,
|
||||
int width, int height)
|
||||
{
|
||||
#if CAIRO_HAS_XCB_SHM_FUNCTIONS
|
||||
cairo_image_surface_t *image;
|
||||
cairo_xcb_shm_info_t *shm_info;
|
||||
cairo_surface_t *image;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_xcb_surface_create_shm_image (surface, &image, &shm_info);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
if ((surface->connection->flags & CAIRO_XCB_HAS_SHM) == 0)
|
||||
return NULL;
|
||||
|
||||
if (! surface->base.is_clear) {
|
||||
status = _cairo_xcb_connection_shm_get_image (surface->connection,
|
||||
surface->drawable,
|
||||
0, 0,
|
||||
surface->width,
|
||||
surface->height,
|
||||
shm_info->shm,
|
||||
shm_info->offset);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
} else {
|
||||
memset (image->data, 0, image->stride * image->height);
|
||||
image = _cairo_xcb_surface_create_shm_image (surface->connection,
|
||||
surface->pixman_format,
|
||||
width, height,
|
||||
&shm_info);
|
||||
if (unlikely (image == NULL || image->status))
|
||||
goto done;
|
||||
|
||||
status = _cairo_xcb_connection_shm_get_image (surface->connection,
|
||||
surface->drawable,
|
||||
x, y,
|
||||
width, height,
|
||||
shm_info->shm,
|
||||
shm_info->offset);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (image);
|
||||
image = _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
*image_out = image;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
done:
|
||||
return (cairo_image_surface_t *) image;
|
||||
#else
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
return NULL;;
|
||||
#endif
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
static cairo_image_surface_t *
|
||||
_get_image (cairo_xcb_surface_t *surface,
|
||||
cairo_bool_t use_shm,
|
||||
cairo_image_surface_t **image_out)
|
||||
int x, int y,
|
||||
int width, int height)
|
||||
{
|
||||
cairo_image_surface_t *image;
|
||||
cairo_xcb_connection_t *connection;
|
||||
xcb_get_image_reply_t *reply;
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (surface->base.is_clear || surface->deferred_clear) {
|
||||
cairo_color_t color;
|
||||
|
||||
color = surface->deferred_clear_color;
|
||||
if (surface->deferred_clear) {
|
||||
image = (cairo_image_surface_t *)
|
||||
_cairo_image_surface_create_with_pixman_format (NULL,
|
||||
surface->pixman_format,
|
||||
surface->width,
|
||||
surface->height,
|
||||
width, height,
|
||||
0);
|
||||
if (surface->deferred_clear_color.alpha_short > 0x00ff) {
|
||||
cairo_solid_pattern_t solid;
|
||||
|
||||
if (surface->deferred_clear && color.alpha > 0) {
|
||||
cairo_t *cr = cairo_create (&image->base);
|
||||
cairo_set_source_rgba (cr, color.red, color.green,
|
||||
color.blue, color.alpha);
|
||||
cairo_paint (cr);
|
||||
cairo_destroy (cr);
|
||||
_cairo_pattern_init_solid (&solid, &surface->deferred_clear_color);
|
||||
status = _cairo_surface_paint (&image->base,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
&solid.base,
|
||||
NULL);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (&image->base);
|
||||
image = (cairo_image_surface_t *)
|
||||
_cairo_surface_create_in_error (status);
|
||||
}
|
||||
}
|
||||
*image_out = image;
|
||||
return image->base.status;
|
||||
return image;
|
||||
}
|
||||
|
||||
connection = surface->connection;
|
||||
|
||||
status = _cairo_xcb_connection_acquire (connection);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
return (cairo_image_surface_t *) _cairo_surface_create_in_error (status);
|
||||
|
||||
if (use_shm) {
|
||||
status = _get_shm_image (surface, image_out);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
goto FAIL;
|
||||
image = _get_shm_image (surface, x, y, width, height);
|
||||
if (image) {
|
||||
_cairo_xcb_connection_release (connection);
|
||||
return image;
|
||||
}
|
||||
}
|
||||
|
||||
if (surface->use_pixmap == 0) {
|
||||
status = _cairo_xcb_connection_get_image (connection,
|
||||
surface->drawable,
|
||||
0, 0,
|
||||
surface->width,
|
||||
surface->height,
|
||||
x, y,
|
||||
width, height,
|
||||
&reply);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
|
@ -445,25 +412,22 @@ _get_image (cairo_xcb_surface_t *surface,
|
|||
pixmap = _cairo_xcb_connection_create_pixmap (connection,
|
||||
surface->depth,
|
||||
surface->drawable,
|
||||
surface->width,
|
||||
surface->height);
|
||||
width, height);
|
||||
|
||||
/* XXX IncludeInferiors? */
|
||||
_cairo_xcb_connection_copy_area (connection,
|
||||
surface->drawable,
|
||||
pixmap, gc,
|
||||
x, y,
|
||||
0, 0,
|
||||
0, 0,
|
||||
surface->width,
|
||||
surface->height);
|
||||
width, height);
|
||||
|
||||
_cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc);
|
||||
|
||||
status = _cairo_xcb_connection_get_image (connection,
|
||||
pixmap,
|
||||
0, 0,
|
||||
surface->width,
|
||||
surface->height,
|
||||
width, height,
|
||||
&reply);
|
||||
_cairo_xcb_connection_free_pixmap (connection, pixmap);
|
||||
|
||||
|
|
@ -484,9 +448,8 @@ _get_image (cairo_xcb_surface_t *surface,
|
|||
_cairo_image_surface_create_with_pixman_format
|
||||
(xcb_get_image_data (reply),
|
||||
surface->pixman_format,
|
||||
surface->width,
|
||||
surface->height,
|
||||
CAIRO_STRIDE_FOR_WIDTH_BPP (surface->width,
|
||||
width, height,
|
||||
CAIRO_STRIDE_FOR_WIDTH_BPP (width,
|
||||
PIXMAN_FORMAT_BPP (surface->pixman_format)));
|
||||
status = image->base.status;
|
||||
if (unlikely (status)) {
|
||||
|
|
@ -500,12 +463,11 @@ _get_image (cairo_xcb_surface_t *surface,
|
|||
|
||||
_cairo_xcb_connection_release (connection);
|
||||
|
||||
*image_out = image;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return image;
|
||||
|
||||
FAIL:
|
||||
_cairo_xcb_connection_release (connection);
|
||||
return status;
|
||||
return (cairo_image_surface_t *) _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
@ -515,10 +477,9 @@ _cairo_xcb_surface_acquire_source_image (void *abstract_surface,
|
|||
{
|
||||
cairo_xcb_surface_t *surface = abstract_surface;
|
||||
cairo_image_surface_t *image;
|
||||
cairo_status_t status;
|
||||
|
||||
if (surface->fallback != NULL) {
|
||||
image = (cairo_image_surface_t *) cairo_surface_reference (surface->fallback);
|
||||
image = (cairo_image_surface_t *) cairo_surface_reference (&surface->fallback->base);
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
|
|
@ -530,9 +491,9 @@ _cairo_xcb_surface_acquire_source_image (void *abstract_surface,
|
|||
goto DONE;
|
||||
}
|
||||
|
||||
status = _get_image (surface, FALSE, &image);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
image = _get_image (surface, FALSE, 0, 0, surface->width, surface->height);
|
||||
if (unlikely (image->base.status))
|
||||
return image->base.status;
|
||||
|
||||
_cairo_surface_attach_snapshot (&surface->base, &image->base, NULL);
|
||||
|
||||
|
|
@ -588,7 +549,8 @@ _put_shm_image (cairo_xcb_surface_t *surface,
|
|||
surface->drawable,
|
||||
gc,
|
||||
surface->width, surface->height,
|
||||
0, 0,
|
||||
image->base.device_transform_inverse.x0,
|
||||
image->base.device_transform_inverse.y0,
|
||||
image->width, image->height,
|
||||
0, 0,
|
||||
image->depth,
|
||||
|
|
@ -616,8 +578,6 @@ _put_image (cairo_xcb_surface_t *surface,
|
|||
if (image->pixman_format == surface->pixman_format) {
|
||||
xcb_gcontext_t gc;
|
||||
|
||||
assert (image->width == surface->width);
|
||||
assert (image->height == surface->height);
|
||||
assert (image->depth == surface->depth);
|
||||
assert (image->stride == (int) CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format)));
|
||||
|
||||
|
|
@ -630,7 +590,8 @@ _put_image (cairo_xcb_surface_t *surface,
|
|||
_cairo_xcb_connection_put_image (surface->connection,
|
||||
surface->drawable, gc,
|
||||
image->width, image->height,
|
||||
0, 0,
|
||||
image->base.device_transform_inverse.x0,
|
||||
image->base.device_transform_inverse.y0,
|
||||
image->depth,
|
||||
image->stride,
|
||||
image->data);
|
||||
|
|
@ -662,42 +623,55 @@ _cairo_xcb_surface_flush (void *abstract_surface)
|
|||
|
||||
status = surface->base.status;
|
||||
if (status == CAIRO_STATUS_SUCCESS && ! surface->base.finished) {
|
||||
status = cairo_surface_status (surface->fallback);
|
||||
status = cairo_surface_status (&surface->fallback->base);
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
status = _put_image (surface,
|
||||
(cairo_image_surface_t *) surface->fallback);
|
||||
status = _put_image (surface, surface->fallback);
|
||||
}
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
_cairo_surface_attach_snapshot (&surface->base,
|
||||
surface->fallback,
|
||||
&surface->fallback->base,
|
||||
cairo_surface_finish);
|
||||
}
|
||||
}
|
||||
|
||||
cairo_surface_destroy (surface->fallback);
|
||||
cairo_surface_destroy (&surface->fallback->base);
|
||||
surface->fallback = NULL;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_xcb_surface_map_to_image (cairo_xcb_surface_t *surface)
|
||||
_cairo_xcb_surface_map_to_image (void *abstract_surface,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_xcb_surface_t *surface = abstract_surface;
|
||||
cairo_image_surface_t *image;
|
||||
|
||||
status = _get_image (surface, TRUE, &image);
|
||||
if (unlikely (status))
|
||||
return _cairo_surface_create_in_error (status);
|
||||
|
||||
/* If we had a pending clear, _get_image applied that */
|
||||
surface->deferred_clear = FALSE;
|
||||
image = _get_image (surface, TRUE,
|
||||
extents->x, extents->y,
|
||||
extents->width, extents->height);
|
||||
if (unlikely (image->base.status))
|
||||
return &image->base;
|
||||
|
||||
cairo_surface_set_device_offset (&image->base, -extents->x, -extents->y);
|
||||
return &image->base;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xcb_surface_unmap (void *abstract_surface,
|
||||
cairo_image_surface_t *image)
|
||||
{
|
||||
return _put_image (abstract_surface, image);
|
||||
}
|
||||
|
||||
static cairo_image_surface_t *
|
||||
_cairo_xcb_surface_fallback (cairo_xcb_surface_t *surface)
|
||||
{
|
||||
return _get_image (surface, TRUE, 0, 0, surface->width, surface->height);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xcb_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
|
|
@ -716,10 +690,10 @@ _cairo_xcb_surface_paint (void *abstract_surface,
|
|||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return status;
|
||||
|
||||
surface->fallback = _cairo_xcb_surface_map_to_image (surface);
|
||||
surface->fallback = _cairo_xcb_surface_fallback (surface);
|
||||
}
|
||||
|
||||
return _cairo_surface_paint (surface->fallback, op, source, clip);
|
||||
return _cairo_surface_paint (&surface->fallback->base, op, source, clip);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -743,10 +717,10 @@ _cairo_xcb_surface_mask (void *abstract_surface,
|
|||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return status;
|
||||
|
||||
surface->fallback = _cairo_xcb_surface_map_to_image (surface);
|
||||
surface->fallback = _cairo_xcb_surface_fallback (surface);
|
||||
}
|
||||
|
||||
return _cairo_surface_mask (surface->fallback,
|
||||
return _cairo_surface_mask (&surface->fallback->base,
|
||||
op, source, mask,
|
||||
clip);
|
||||
}
|
||||
|
|
@ -785,10 +759,10 @@ _cairo_xcb_surface_stroke (void *abstract_surface,
|
|||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return status;
|
||||
|
||||
surface->fallback = _cairo_xcb_surface_map_to_image (surface);
|
||||
surface->fallback = _cairo_xcb_surface_fallback (surface);
|
||||
}
|
||||
|
||||
return _cairo_surface_stroke (surface->fallback,
|
||||
return _cairo_surface_stroke (&surface->fallback->base,
|
||||
op, source,
|
||||
path, style,
|
||||
ctm, ctm_inverse,
|
||||
|
|
@ -824,10 +798,10 @@ _cairo_xcb_surface_fill (void *abstract_surface,
|
|||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return status;
|
||||
|
||||
surface->fallback = _cairo_xcb_surface_map_to_image (surface);
|
||||
surface->fallback = _cairo_xcb_surface_fallback (surface);
|
||||
}
|
||||
|
||||
return _cairo_surface_fill (surface->fallback,
|
||||
return _cairo_surface_fill (&surface->fallback->base,
|
||||
op, source,
|
||||
path, fill_rule,
|
||||
tolerance, antialias,
|
||||
|
|
@ -864,10 +838,10 @@ _cairo_xcb_surface_glyphs (void *abstract_surface,
|
|||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return status;
|
||||
|
||||
surface->fallback = _cairo_xcb_surface_map_to_image (surface);
|
||||
surface->fallback = _cairo_xcb_surface_fallback (surface);
|
||||
}
|
||||
|
||||
return _cairo_surface_show_text_glyphs (surface->fallback,
|
||||
return _cairo_surface_show_text_glyphs (&surface->fallback->base,
|
||||
op, source,
|
||||
NULL, 0,
|
||||
glyphs, num_glyphs,
|
||||
|
|
@ -878,12 +852,18 @@ _cairo_xcb_surface_glyphs (void *abstract_surface,
|
|||
|
||||
const cairo_surface_backend_t _cairo_xcb_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_XCB,
|
||||
_cairo_xcb_surface_finish,
|
||||
_cairo_default_context_create,
|
||||
|
||||
_cairo_xcb_surface_create_similar,
|
||||
_cairo_xcb_surface_finish,
|
||||
_cairo_xcb_surface_create_similar_image,
|
||||
|
||||
_cairo_xcb_surface_map_to_image,
|
||||
_cairo_xcb_surface_unmap,
|
||||
|
||||
_cairo_xcb_surface_acquire_source_image,
|
||||
_cairo_xcb_surface_release_source_image,
|
||||
|
||||
NULL, NULL, NULL, /* dest acquire/release/clone */
|
||||
|
||||
NULL, /* composite */
|
||||
|
|
|
|||
|
|
@ -815,51 +815,37 @@ static const int8_t dither_pattern[4][4] = {
|
|||
#undef X
|
||||
|
||||
|
||||
static cairo_status_t
|
||||
static cairo_surface_t *
|
||||
_get_image_surface (cairo_xlib_surface_t *surface,
|
||||
cairo_rectangle_int_t *interest_rect,
|
||||
cairo_image_surface_t **image_out,
|
||||
cairo_rectangle_int_t *image_rect)
|
||||
const cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_int_status_t status;
|
||||
cairo_image_surface_t *image = NULL;
|
||||
XImage *ximage;
|
||||
cairo_rectangle_int_t extents;
|
||||
pixman_format_code_t pixman_format;
|
||||
cairo_format_masks_t xlib_masks;
|
||||
cairo_xlib_display_t *display;
|
||||
|
||||
extents.x = 0;
|
||||
extents.y = 0;
|
||||
extents.width = surface->width;
|
||||
extents.height = surface->height;
|
||||
|
||||
if (interest_rect) {
|
||||
if (! _cairo_rectangle_intersect (&extents, interest_rect)) {
|
||||
*image_out = NULL;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
assert (extents->x >= 0);
|
||||
assert (extents->y >= 0);
|
||||
assert (extents->x + extents->width <= surface->width);
|
||||
assert (extents->y + extents->height <= surface->height);
|
||||
|
||||
status = _cairo_xlib_display_acquire (surface->base.device, &display);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (image_rect)
|
||||
*image_rect = extents;
|
||||
return _cairo_surface_create_in_error (status);
|
||||
|
||||
/* XXX: This should try to use the XShm extension if available */
|
||||
|
||||
if (surface->use_pixmap == 0)
|
||||
{
|
||||
if (surface->use_pixmap == 0) {
|
||||
cairo_xlib_error_func_t old_handler;
|
||||
|
||||
old_handler = XSetErrorHandler (_noop_error_handler);
|
||||
|
||||
ximage = XGetImage (display->display,
|
||||
surface->drawable,
|
||||
extents.x, extents.y,
|
||||
extents.width, extents.height,
|
||||
extents->x, extents->y,
|
||||
extents->width, extents->height,
|
||||
AllPlanes, ZPixmap);
|
||||
|
||||
XSetErrorHandler (old_handler);
|
||||
|
|
@ -869,9 +855,7 @@ _get_image_surface (cairo_xlib_surface_t *surface,
|
|||
*/
|
||||
if (!ximage)
|
||||
surface->use_pixmap = CAIRO_ASSUME_PIXMAP;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
surface->use_pixmap--;
|
||||
ximage = NULL;
|
||||
}
|
||||
|
|
@ -892,18 +876,18 @@ _get_image_surface (cairo_xlib_surface_t *surface,
|
|||
|
||||
pixmap = XCreatePixmap (display->display,
|
||||
surface->drawable,
|
||||
extents.width, extents.height,
|
||||
extents->width, extents->height,
|
||||
surface->depth);
|
||||
if (pixmap) {
|
||||
XCopyArea (display->display, surface->drawable, pixmap, gc,
|
||||
extents.x, extents.y,
|
||||
extents.width, extents.height,
|
||||
extents->x, extents->y,
|
||||
extents->width, extents->height,
|
||||
0, 0);
|
||||
|
||||
ximage = XGetImage (display->display,
|
||||
pixmap,
|
||||
0, 0,
|
||||
extents.width, extents.height,
|
||||
extents->width, extents->height,
|
||||
AllPlanes, ZPixmap);
|
||||
|
||||
XFreePixmap (display->display, pixmap);
|
||||
|
|
@ -1016,8 +1000,8 @@ _get_image_surface (cairo_xlib_surface_t *surface,
|
|||
data = cairo_image_surface_get_data (&image->base);
|
||||
rowstride = cairo_image_surface_get_stride (&image->base) >> 2;
|
||||
row = (uint32_t *) data;
|
||||
x0 = extents.x + surface->base.device_transform.x0;
|
||||
y0 = extents.y + surface->base.device_transform.y0;
|
||||
x0 = extents->x + surface->base.device_transform.x0;
|
||||
y0 = extents->y + surface->base.device_transform.y0;
|
||||
for (y = 0, y_off = y0 % ARRAY_LENGTH (dither_pattern);
|
||||
y < ximage->height;
|
||||
y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern)) {
|
||||
|
|
@ -1052,13 +1036,11 @@ _get_image_surface (cairo_xlib_surface_t *surface,
|
|||
cairo_device_release (&display->base);
|
||||
|
||||
if (unlikely (status)) {
|
||||
if (image) {
|
||||
cairo_surface_destroy (&image->base);
|
||||
image = NULL;
|
||||
}
|
||||
cairo_surface_destroy (&image->base);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
*image_out = image;
|
||||
return status;
|
||||
|
||||
return &image->base;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1391,31 +1373,29 @@ _cairo_xlib_surface_acquire_source_image (void *abstract_surf
|
|||
void **image_extra)
|
||||
{
|
||||
cairo_xlib_surface_t *surface = abstract_surface;
|
||||
cairo_image_surface_t *image;
|
||||
cairo_status_t status;
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
status = _get_image_surface (surface, NULL, &image, NULL);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
extents.x = extents.y = 0;
|
||||
extents.width = surface->width;
|
||||
extents.height = surface->width;
|
||||
|
||||
*image_out = image;
|
||||
*image_extra = NULL;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
*image_out = (cairo_image_surface_t*)_get_image_surface (surface, &extents);
|
||||
return (*image_out)->base.status;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_xlib_surface_snapshot (void *abstract_surface)
|
||||
{
|
||||
cairo_xlib_surface_t *surface = abstract_surface;
|
||||
cairo_image_surface_t *image;
|
||||
cairo_status_t status;
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
status = _get_image_surface (surface, NULL, &image, NULL);
|
||||
if (unlikely (status))
|
||||
return _cairo_surface_create_in_error (status);
|
||||
extents.x = extents.y = 0;
|
||||
extents.width = surface->width;
|
||||
extents.height = surface->width;
|
||||
|
||||
return &image->base;
|
||||
/* XXX notice the duplication */
|
||||
return _get_image_surface (surface, &extents);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1426,6 +1406,29 @@ _cairo_xlib_surface_release_source_image (void *abstract_surfa
|
|||
cairo_surface_destroy (&image->base);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_xlib_surface_map_to_image (void *abstract_surface,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_surface_t *image;
|
||||
|
||||
image = _get_image_surface (abstract_surface, extents);
|
||||
cairo_surface_set_device_offset (image, -extents->y, -extents->y);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xlib_surface_unmap_image (void *abstract_surface,
|
||||
cairo_image_surface_t *image)
|
||||
{
|
||||
return _draw_image_surface (abstract_surface, image,
|
||||
0, 0,
|
||||
image->width, image->height,
|
||||
image->base.device_transform_inverse.x0,
|
||||
image->base.device_transform_inverse.y0);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xlib_surface_acquire_dest_image (void *abstract_surface,
|
||||
cairo_rectangle_int_t *interest_rect,
|
||||
|
|
@ -1433,18 +1436,12 @@ _cairo_xlib_surface_acquire_dest_image (void *abstract_surfac
|
|||
cairo_rectangle_int_t *image_rect_out,
|
||||
void **image_extra)
|
||||
{
|
||||
cairo_xlib_surface_t *surface = abstract_surface;
|
||||
cairo_image_surface_t *image;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _get_image_surface (surface, interest_rect, &image, image_rect_out);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
*image_out = image;
|
||||
if (image_rect_out)
|
||||
*image_rect_out = *interest_rect;
|
||||
*image_extra = NULL;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
*image_out = (cairo_image_surface_t *)
|
||||
_get_image_surface (abstract_surface, interest_rect);
|
||||
return (*image_out)->base.status;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -3138,12 +3135,18 @@ _cairo_xlib_surface_is_similar (void *surface_a,
|
|||
|
||||
static const cairo_surface_backend_t cairo_xlib_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_XLIB,
|
||||
_cairo_xlib_surface_finish,
|
||||
|
||||
_cairo_default_context_create,
|
||||
|
||||
_cairo_xlib_surface_create_similar,
|
||||
_cairo_xlib_surface_finish,
|
||||
NULL, //_cairo_xlib_surface_create_similar_image, /* XXX shm */
|
||||
_cairo_xlib_surface_map_to_image,
|
||||
_cairo_xlib_surface_unmap_image,
|
||||
|
||||
_cairo_xlib_surface_acquire_source_image,
|
||||
_cairo_xlib_surface_release_source_image,
|
||||
|
||||
_cairo_xlib_surface_acquire_dest_image,
|
||||
_cairo_xlib_surface_release_dest_image,
|
||||
_cairo_xlib_surface_clone_similar,
|
||||
|
|
|
|||
|
|
@ -991,10 +991,14 @@ _cairo_xml_surface_glyphs (void *abstract_surface,
|
|||
static const cairo_surface_backend_t
|
||||
_cairo_xml_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_XML,
|
||||
NULL,
|
||||
_cairo_default_context_create,
|
||||
|
||||
_cairo_xml_surface_create_similar,
|
||||
NULL,
|
||||
NULL, /* create_similar_image */
|
||||
NULL, /* map_to_image */
|
||||
NULL, /* unmap_image */
|
||||
|
||||
NULL, NULL, /* source image */
|
||||
NULL, NULL, /* dst image */
|
||||
NULL, /* clone_similar */
|
||||
|
|
|
|||
93
src/cairo.h
93
src/cairo.h
|
|
@ -353,6 +353,46 @@ typedef enum _cairo_content {
|
|||
CAIRO_CONTENT_COLOR_ALPHA = 0x3000
|
||||
} cairo_content_t;
|
||||
|
||||
/**
|
||||
* cairo_format_t:
|
||||
* @CAIRO_FORMAT_INVALID: no such format exists or is supported.
|
||||
* @CAIRO_FORMAT_ARGB32: each pixel is a 32-bit quantity, with
|
||||
* alpha in the upper 8 bits, then red, then green, then blue.
|
||||
* The 32-bit quantities are stored native-endian. Pre-multiplied
|
||||
* alpha is used. (That is, 50% transparent red is 0x80800000,
|
||||
* not 0x80ff0000.)
|
||||
* @CAIRO_FORMAT_RGB24: each pixel is a 32-bit quantity, with
|
||||
* the upper 8 bits unused. Red, Green, and Blue are stored
|
||||
* in the remaining 24 bits in that order.
|
||||
* @CAIRO_FORMAT_A8: each pixel is a 8-bit quantity holding
|
||||
* an alpha value.
|
||||
* @CAIRO_FORMAT_A1: each pixel is a 1-bit quantity holding
|
||||
* an alpha value. Pixels are packed together into 32-bit
|
||||
* quantities. The ordering of the bits matches the
|
||||
* endianess of the platform. On a big-endian machine, the
|
||||
* first pixel is in the uppermost bit, on a little-endian
|
||||
* machine the first pixel is in the least-significant bit.
|
||||
* @CAIRO_FORMAT_RGB16_565: each pixel is a 16-bit quantity
|
||||
* with red in the upper 5 bits, then green in the middle
|
||||
* 6 bits, and blue in the lower 5 bits.
|
||||
* @CAIRO_FORMAT_RGB30: like RGB24 but with 10bpc
|
||||
*
|
||||
* #cairo_format_t is used to identify the memory format of
|
||||
* image data.
|
||||
*
|
||||
* New entries may be added in future versions.
|
||||
**/
|
||||
typedef enum _cairo_format {
|
||||
CAIRO_FORMAT_INVALID = -1,
|
||||
CAIRO_FORMAT_ARGB32 = 0,
|
||||
CAIRO_FORMAT_RGB24 = 1,
|
||||
CAIRO_FORMAT_A8 = 2,
|
||||
CAIRO_FORMAT_A1 = 3,
|
||||
CAIRO_FORMAT_RGB16_565 = 4,
|
||||
CAIRO_FORMAT_RGB30 = 5
|
||||
} cairo_format_t;
|
||||
|
||||
|
||||
/**
|
||||
* cairo_write_func_t:
|
||||
* @closure: the output closure
|
||||
|
|
@ -2033,6 +2073,20 @@ cairo_surface_create_similar (cairo_surface_t *other,
|
|||
int width,
|
||||
int height);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_surface_create_similar_image (cairo_surface_t *other,
|
||||
cairo_format_t format,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_surface_map_to_image (cairo_surface_t *surface,
|
||||
const cairo_rectangle_t *extents);
|
||||
|
||||
cairo_public void
|
||||
cairo_surface_unmap_image (cairo_surface_t *surface,
|
||||
cairo_surface_t *image);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_surface_create_for_rectangle (cairo_surface_t *target,
|
||||
double x,
|
||||
|
|
@ -2234,45 +2288,6 @@ cairo_surface_has_show_text_glyphs (cairo_surface_t *surface);
|
|||
|
||||
/* Image-surface functions */
|
||||
|
||||
/**
|
||||
* cairo_format_t:
|
||||
* @CAIRO_FORMAT_INVALID: no such format exists or is supported.
|
||||
* @CAIRO_FORMAT_ARGB32: each pixel is a 32-bit quantity, with
|
||||
* alpha in the upper 8 bits, then red, then green, then blue.
|
||||
* The 32-bit quantities are stored native-endian. Pre-multiplied
|
||||
* alpha is used. (That is, 50% transparent red is 0x80800000,
|
||||
* not 0x80ff0000.)
|
||||
* @CAIRO_FORMAT_RGB24: each pixel is a 32-bit quantity, with
|
||||
* the upper 8 bits unused. Red, Green, and Blue are stored
|
||||
* in the remaining 24 bits in that order.
|
||||
* @CAIRO_FORMAT_A8: each pixel is a 8-bit quantity holding
|
||||
* an alpha value.
|
||||
* @CAIRO_FORMAT_A1: each pixel is a 1-bit quantity holding
|
||||
* an alpha value. Pixels are packed together into 32-bit
|
||||
* quantities. The ordering of the bits matches the
|
||||
* endianess of the platform. On a big-endian machine, the
|
||||
* first pixel is in the uppermost bit, on a little-endian
|
||||
* machine the first pixel is in the least-significant bit.
|
||||
* @CAIRO_FORMAT_RGB16_565: each pixel is a 16-bit quantity
|
||||
* with red in the upper 5 bits, then green in the middle
|
||||
* 6 bits, and blue in the lower 5 bits.
|
||||
* @CAIRO_FORMAT_RGB30: like RGB24 but with 10bpc
|
||||
*
|
||||
* #cairo_format_t is used to identify the memory format of
|
||||
* image data.
|
||||
*
|
||||
* New entries may be added in future versions.
|
||||
**/
|
||||
typedef enum _cairo_format {
|
||||
CAIRO_FORMAT_INVALID = -1,
|
||||
CAIRO_FORMAT_ARGB32 = 0,
|
||||
CAIRO_FORMAT_RGB24 = 1,
|
||||
CAIRO_FORMAT_A8 = 2,
|
||||
CAIRO_FORMAT_A1 = 3,
|
||||
CAIRO_FORMAT_RGB16_565 = 4,
|
||||
CAIRO_FORMAT_RGB30 = 5
|
||||
} cairo_format_t;
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_image_surface_create (cairo_format_t format,
|
||||
int width,
|
||||
|
|
|
|||
|
|
@ -310,6 +310,10 @@ _cairo_rectangle_intersects (const cairo_rectangle_int_t *dst,
|
|||
src->y + (int) src->height <= dst->y);
|
||||
}
|
||||
|
||||
cairo_private void
|
||||
_cairo_rectangle_int_from_double (cairo_rectangle_int_t *recti,
|
||||
const cairo_rectangle_t *rectf);
|
||||
|
||||
/* Extends the dst rectangle to also contain src.
|
||||
* If one of the rectangles is empty, the result is undefined
|
||||
*/
|
||||
|
|
@ -650,6 +654,9 @@ extern const cairo_private struct _cairo_font_face_backend _cairo_quartz_font_fa
|
|||
struct _cairo_surface_backend {
|
||||
cairo_surface_type_t type;
|
||||
|
||||
cairo_warn cairo_status_t
|
||||
(*finish) (void *surface);
|
||||
|
||||
cairo_t *
|
||||
(*create_context) (void *surface);
|
||||
|
||||
|
|
@ -658,9 +665,18 @@ struct _cairo_surface_backend {
|
|||
cairo_content_t content,
|
||||
int width,
|
||||
int height);
|
||||
cairo_surface_t *
|
||||
(*create_similar_image) (void *surface,
|
||||
cairo_format_t format,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
cairo_warn cairo_status_t
|
||||
(*finish) (void *surface);
|
||||
cairo_surface_t *
|
||||
(*map_to_image) (void *surface,
|
||||
const cairo_rectangle_int_t *extents);
|
||||
cairo_int_status_t
|
||||
(*unmap_image) (void *surface,
|
||||
cairo_image_surface_t *image);
|
||||
|
||||
cairo_warn cairo_status_t
|
||||
(*acquire_source_image) (void *abstract_surface,
|
||||
|
|
@ -1619,6 +1635,10 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other,
|
|||
int width,
|
||||
int height);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_surface_create_for_rectangle_int (cairo_surface_t *target,
|
||||
cairo_rectangle_int_t *extents);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_surface_create_similar_solid (cairo_surface_t *other,
|
||||
cairo_content_t content,
|
||||
|
|
|
|||
|
|
@ -208,10 +208,14 @@ _test_fallback_surface_get_extents (void *abstract_surface,
|
|||
|
||||
static const cairo_surface_backend_t test_fallback_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
|
||||
_test_fallback_surface_finish,
|
||||
_cairo_default_context_create,
|
||||
|
||||
_test_fallback_surface_create_similar,
|
||||
_test_fallback_surface_finish,
|
||||
NULL, /* create similar image */
|
||||
NULL, /* map_to_image */
|
||||
NULL, /* unmap_image */
|
||||
|
||||
_test_fallback_surface_acquire_source_image,
|
||||
_test_fallback_surface_release_source_image,
|
||||
_test_fallback_surface_acquire_dest_image,
|
||||
|
|
|
|||
|
|
@ -205,10 +205,14 @@ _test_fallback16_surface_get_extents (void *abstract_surface,
|
|||
|
||||
static const cairo_surface_backend_t test_fallback16_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
|
||||
_test_fallback16_surface_finish,
|
||||
_cairo_default_context_create,
|
||||
|
||||
_test_fallback16_surface_create_similar,
|
||||
_test_fallback16_surface_finish,
|
||||
NULL, /* create similar image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image */
|
||||
|
||||
_test_fallback16_surface_acquire_source_image,
|
||||
_test_fallback16_surface_release_source_image,
|
||||
_test_fallback16_surface_acquire_dest_image,
|
||||
|
|
|
|||
|
|
@ -134,10 +134,14 @@ _cairo_null_surface_has_show_text_glyphs (void *surface)
|
|||
|
||||
static const cairo_surface_backend_t null_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_NULL,
|
||||
NULL, /* finish */
|
||||
_cairo_default_context_create,
|
||||
|
||||
_cairo_null_surface_create_similar,
|
||||
NULL, /* finish */
|
||||
NULL, /* create similar image */
|
||||
NULL, /* map_to_image */
|
||||
NULL, /* unmap image */
|
||||
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
NULL, /* acquire_dest_image */
|
||||
|
|
|
|||
|
|
@ -241,13 +241,17 @@ _test_paginated_surface_set_paginated_mode (void *abstract_surface,
|
|||
|
||||
static const cairo_surface_backend_t test_paginated_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
|
||||
_test_paginated_surface_finish,
|
||||
_cairo_default_context_create,
|
||||
|
||||
/* Since we are a paginated user, we get to regard most of the
|
||||
* surface backend interface as historical cruft and ignore it. */
|
||||
|
||||
NULL, /* create_similar */
|
||||
_test_paginated_surface_finish,
|
||||
NULL, /* create similar image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image */
|
||||
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
NULL, /* acquire_dest_image */
|
||||
|
|
|
|||
|
|
@ -235,10 +235,14 @@ _test_wrapping_surface_show_text_glyphs (void *abstract_surface,
|
|||
|
||||
static const cairo_surface_backend_t test_wrapping_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_WRAPPING,
|
||||
_test_wrapping_surface_finish,
|
||||
_cairo_default_context_create,
|
||||
|
||||
_test_wrapping_surface_create_similar,
|
||||
_test_wrapping_surface_finish,
|
||||
NULL, /* create similar image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image */
|
||||
|
||||
_test_wrapping_surface_acquire_source_image,
|
||||
_test_wrapping_surface_release_source_image,
|
||||
NULL, NULL, /* dest_image */
|
||||
|
|
|
|||
|
|
@ -167,6 +167,7 @@ test_sources = \
|
|||
linear-uniform.c \
|
||||
long-dashed-lines.c \
|
||||
long-lines.c \
|
||||
map-to-image.c \
|
||||
mask.c \
|
||||
mask-alpha.c \
|
||||
mask-ctm.c \
|
||||
|
|
|
|||
BIN
test/map-all-to-image.ref.png
Normal file
BIN
test/map-all-to-image.ref.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 86 B |
BIN
test/map-bit-to-image.ref.png
Normal file
BIN
test/map-bit-to-image.ref.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 103 B |
BIN
test/map-to-image-fill.ref.png
Normal file
BIN
test/map-to-image-fill.ref.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 103 B |
126
test/map-to-image.c
Normal file
126
test/map-to-image.c
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* 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"
|
||||
|
||||
#define WIDTH 3
|
||||
#define HEIGHT 3
|
||||
|
||||
/* A single, black pixel */
|
||||
static const uint32_t black_pixel = 0xff000000;
|
||||
|
||||
static cairo_test_status_t
|
||||
all (cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
uint8_t *data;
|
||||
int stride;
|
||||
int i, j;
|
||||
|
||||
/* Fill background white */
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_paint (cr);
|
||||
|
||||
surface = cairo_surface_map_to_image (cairo_get_target (cr), NULL);
|
||||
cairo_surface_flush (surface);
|
||||
stride = cairo_image_surface_get_stride (surface);
|
||||
data = cairo_image_surface_get_data (surface);
|
||||
if (data) {
|
||||
for (j = 0; j < HEIGHT; j++)
|
||||
for (i = 0; i < WIDTH; i++)
|
||||
*(uint32_t *)(data + j * stride + 4*i) = black_pixel;
|
||||
}
|
||||
cairo_surface_mark_dirty (surface);
|
||||
cairo_surface_unmap_image (cairo_get_target (cr), surface);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_test_status_t
|
||||
bit (cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_rectangle_t extents;
|
||||
uint8_t *data;
|
||||
|
||||
extents.x = extents.y = extents.width = extents.height = 1;
|
||||
|
||||
/* Fill background white */
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_paint (cr);
|
||||
|
||||
surface = cairo_surface_map_to_image (cairo_get_target (cr), &extents);
|
||||
cairo_surface_flush (surface);
|
||||
data = cairo_image_surface_get_data (surface);
|
||||
if (data)
|
||||
*(uint32_t *)data = black_pixel;
|
||||
cairo_surface_mark_dirty (surface);
|
||||
cairo_surface_unmap_image (cairo_get_target (cr), surface);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_test_status_t
|
||||
fill (cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_rectangle_t extents;
|
||||
cairo_t *cr2;
|
||||
|
||||
extents.x = extents.y = extents.width = extents.height = 1;
|
||||
|
||||
/* Fill background white */
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_paint (cr);
|
||||
|
||||
surface = cairo_surface_map_to_image (cairo_get_target (cr), &extents);
|
||||
cr2 = cairo_create (surface);
|
||||
cairo_set_source_rgb (cr2, 1, 0, 0);
|
||||
cairo_paint (cr2);
|
||||
cairo_destroy (cr2);
|
||||
cairo_surface_unmap_image (cairo_get_target (cr), surface);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
}
|
||||
|
||||
CAIRO_TEST (map_all_to_image,
|
||||
"Test maping a surface to an image and modifying it externally",
|
||||
"image", /* keywords */
|
||||
"target=raster", /* requirements */
|
||||
WIDTH, HEIGHT,
|
||||
NULL, all)
|
||||
CAIRO_TEST (map_bit_to_image,
|
||||
"Test maping a surface to an image and modifying it externally",
|
||||
"image", /* keywords */
|
||||
"target=raster", /* requirements */
|
||||
WIDTH, HEIGHT,
|
||||
NULL, bit)
|
||||
CAIRO_TEST (map_to_image_fill,
|
||||
"Test maping a surface to an image and modifying it externally",
|
||||
"image", /* keywords */
|
||||
"target=raster", /* requirements */
|
||||
WIDTH, HEIGHT,
|
||||
NULL, fill)
|
||||
|
|
@ -3619,6 +3619,67 @@ _matrix (csi_t *ctx)
|
|||
return push (&matrix);
|
||||
}
|
||||
|
||||
static csi_status_t
|
||||
_map_to_image (csi_t *ctx)
|
||||
{
|
||||
csi_object_t obj;
|
||||
csi_array_t *array;
|
||||
csi_status_t status;
|
||||
cairo_rectangle_t extents;
|
||||
cairo_rectangle_t *r;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
check (2);
|
||||
|
||||
status = _csi_ostack_get_array (ctx, 0, &array);
|
||||
if (_csi_unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _csi_ostack_get_surface (ctx, 1, &surface);
|
||||
if (_csi_unlikely (status))
|
||||
return status;
|
||||
|
||||
switch (array->stack.len) {
|
||||
case 0:
|
||||
r = NULL;
|
||||
case 4:
|
||||
extents.x = _csi_object_as_real (&array->stack.objects[0]);
|
||||
extents.y = _csi_object_as_real (&array->stack.objects[1]);
|
||||
extents.width = _csi_object_as_real (&array->stack.objects[2]);
|
||||
extents.height = _csi_object_as_real (&array->stack.objects[3]);
|
||||
r = &extents;
|
||||
break;
|
||||
default:
|
||||
return _csi_error (CSI_STATUS_INVALID_SCRIPT);
|
||||
}
|
||||
|
||||
obj.type = CSI_OBJECT_TYPE_SURFACE;
|
||||
obj.datum.surface = cairo_surface_map_to_image (surface, r);
|
||||
pop (2);
|
||||
return push (&obj);
|
||||
}
|
||||
|
||||
static csi_status_t
|
||||
_unmap_image (csi_t *ctx)
|
||||
{
|
||||
cairo_surface_t *surface, *image;
|
||||
csi_status_t status;
|
||||
|
||||
check (2);
|
||||
|
||||
status = _csi_ostack_get_surface (ctx, 0, &image);
|
||||
if (_csi_unlikely (status))
|
||||
return status;
|
||||
status = _csi_ostack_get_surface (ctx, 1, &surface);
|
||||
if (_csi_unlikely (status))
|
||||
return status;
|
||||
|
||||
cairo_surface_unmap_image (surface, image);
|
||||
|
||||
pop (2);
|
||||
return CSI_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static csi_status_t
|
||||
_mesh (csi_t *ctx)
|
||||
{
|
||||
|
|
@ -5520,6 +5581,38 @@ _similar (csi_t *ctx)
|
|||
return push (&obj);
|
||||
}
|
||||
|
||||
static csi_status_t
|
||||
_similar_image (csi_t *ctx)
|
||||
{
|
||||
csi_object_t obj;
|
||||
long format;
|
||||
double width, height;
|
||||
cairo_surface_t *other;
|
||||
csi_status_t status;
|
||||
|
||||
check (4);
|
||||
|
||||
status = _csi_ostack_get_number (ctx, 0, &height);
|
||||
if (_csi_unlikely (status))
|
||||
return status;
|
||||
status = _csi_ostack_get_number (ctx, 1, &width);
|
||||
if (_csi_unlikely (status))
|
||||
return status;
|
||||
status = _csi_ostack_get_integer (ctx, 2, &format);
|
||||
if (_csi_unlikely (status))
|
||||
return status;
|
||||
status = _csi_ostack_get_surface (ctx, 3, &other);
|
||||
if (_csi_unlikely (status))
|
||||
return status;
|
||||
|
||||
obj.type = CSI_OBJECT_TYPE_SURFACE;
|
||||
obj.datum.surface = cairo_surface_create_similar_image (other,
|
||||
format,
|
||||
width, height);
|
||||
pop (4);
|
||||
return push (&obj);
|
||||
}
|
||||
|
||||
static csi_status_t
|
||||
_subsurface (csi_t *ctx)
|
||||
{
|
||||
|
|
@ -6301,6 +6394,7 @@ _defs[] = {
|
|||
{ "lt", _lt },
|
||||
{ "m", _move_to },
|
||||
{ "M", _rel_move_to },
|
||||
{ "map-to-image", _map_to_image },
|
||||
{ "mark", _mark },
|
||||
{ "mask", _mask },
|
||||
{ "matrix", _matrix },
|
||||
|
|
@ -6381,6 +6475,7 @@ _defs[] = {
|
|||
{ "show-text-glyphs", _show_text_glyphs },
|
||||
{ "show-page", _show_page },
|
||||
{ "similar", _similar },
|
||||
{ "similar-image", _similar_image },
|
||||
{ "sin", NULL },
|
||||
{ "sqrt", NULL },
|
||||
{ "sub", _sub },
|
||||
|
|
@ -6399,6 +6494,7 @@ _defs[] = {
|
|||
{ "true", _true },
|
||||
{ "type", NULL },
|
||||
{ "undef", _undef },
|
||||
{ "unmap-image", _unmap_image },
|
||||
{ "unset", _unset },
|
||||
{ "user-to-device", NULL },
|
||||
{ "user-to-device-distance", NULL },
|
||||
|
|
|
|||
|
|
@ -3510,6 +3510,98 @@ cairo_surface_create_similar (cairo_surface_t *other,
|
|||
return ret;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_surface_create_similar_image (cairo_surface_t *other,
|
||||
cairo_format_t format,
|
||||
int width, int height)
|
||||
{
|
||||
cairo_surface_t *ret;
|
||||
|
||||
_enter_trace ();
|
||||
|
||||
ret = DLCALL (cairo_surface_create_similar_image,
|
||||
other, format, width, height);
|
||||
|
||||
_emit_line_info ();
|
||||
if (other != NULL && _write_lock ()) {
|
||||
Object *other_obj = _get_object(SURFACE, other);
|
||||
Object *new_obj = _create_surface (ret);
|
||||
|
||||
if (other_obj->defined)
|
||||
_trace_printf ("s%ld ", other_obj->token);
|
||||
else if (current_stack_depth == other_obj->operand + 1)
|
||||
_trace_printf ("dup ");
|
||||
else
|
||||
_trace_printf ("%d index ",
|
||||
current_stack_depth - other_obj->operand - 1);
|
||||
_trace_printf ("s%ld //%s %d %d similar-image %% s%ld\n",
|
||||
_get_surface_id (other),
|
||||
_format_to_string (format),
|
||||
width, height,
|
||||
new_obj->token);
|
||||
|
||||
_push_object (new_obj);
|
||||
_write_unlock ();
|
||||
}
|
||||
|
||||
_exit_trace ();
|
||||
return ret;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_surface_map_to_image (cairo_surface_t *surface,
|
||||
const cairo_rectangle_t *extents)
|
||||
{
|
||||
cairo_surface_t *ret;
|
||||
|
||||
_enter_trace ();
|
||||
|
||||
ret = DLCALL (cairo_surface_map_to_image, surface, extents);
|
||||
|
||||
_emit_line_info ();
|
||||
if (_write_lock ()) {
|
||||
Object *obj = _create_surface (ret);
|
||||
|
||||
if (extents) {
|
||||
_trace_printf ("[ %f %f %f %f ] map-to-image dup /s%ld exch def\n",
|
||||
extents->x, extents->y,
|
||||
extents->width,
|
||||
extents->height,
|
||||
obj->token);
|
||||
obj->width = extents->width;
|
||||
obj->height = extents->height;
|
||||
} else {
|
||||
_trace_printf ("[ ] map-to-image dup /s%ld exch def\n",
|
||||
obj->token);
|
||||
}
|
||||
obj->defined = TRUE;
|
||||
_push_object (obj);
|
||||
_write_unlock ();
|
||||
}
|
||||
|
||||
_exit_trace ();
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
cairo_surface_unmap_image (cairo_surface_t *surface,
|
||||
cairo_surface_t *image)
|
||||
{
|
||||
_enter_trace ();
|
||||
|
||||
_emit_line_info ();
|
||||
if (_write_lock ()) {
|
||||
_trace_printf ("/s%ld /s%ld unmap-image\n",
|
||||
_get_surface_id (surface),
|
||||
_get_surface_id (image));
|
||||
_write_unlock ();
|
||||
}
|
||||
|
||||
DLCALL (cairo_surface_unmap_image, surface, image);
|
||||
|
||||
_exit_trace ();
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
cairo_surface_create_for_rectangle (cairo_surface_t *target,
|
||||
double x, double y,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue