mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-01 05:37:59 +02:00
ps: Enable native encoding of subsurface patterns.
Carefully handle subsurfaces of a recording surface through the analysis and paginated surfaces so that we can generate a native pattern for the vector backends, demonstrated by the PostScript backend. Nothing remarkable, just a lot of bookkeeping to track the wrapped surface types and to apply the correct offsets when generating the subsurface pattern.
This commit is contained in:
parent
5fc04bba9f
commit
8ded35fd69
21 changed files with 565 additions and 126 deletions
|
|
@ -40,6 +40,7 @@
|
|||
#include "cairo-error-private.h"
|
||||
#include "cairo-paginated-private.h"
|
||||
#include "cairo-recording-surface-private.h"
|
||||
#include "cairo-surface-subsurface-private.h"
|
||||
#include "cairo-region-private.h"
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -100,10 +101,11 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface,
|
|||
cairo_bool_t old_has_ctm;
|
||||
cairo_matrix_t old_ctm, p2d;
|
||||
cairo_status_t status;
|
||||
cairo_surface_t *source;
|
||||
|
||||
assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
|
||||
surface_pattern = (const cairo_surface_pattern_t *) pattern;
|
||||
assert (_cairo_surface_is_recording (surface_pattern->surface));
|
||||
assert (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING);
|
||||
|
||||
old_ctm = surface->ctm;
|
||||
old_has_ctm = surface->has_ctm;
|
||||
|
|
@ -115,8 +117,13 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface,
|
|||
cairo_matrix_multiply (&surface->ctm, &p2d, &surface->ctm);
|
||||
surface->has_ctm = ! _cairo_matrix_is_identity (&surface->ctm);
|
||||
|
||||
status = _cairo_recording_surface_replay_and_create_regions (surface_pattern->surface,
|
||||
&surface->base);
|
||||
source = surface_pattern->surface;
|
||||
if (source->backend->type == CAIRO_INTERNAL_SURFACE_TYPE_SUBSURFACE) {
|
||||
cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
|
||||
source = sub->target;
|
||||
}
|
||||
|
||||
status = _cairo_recording_surface_replay_and_create_regions (source, &surface->base);
|
||||
|
||||
surface->ctm = old_ctm;
|
||||
surface->has_ctm = old_has_ctm;
|
||||
|
|
|
|||
|
|
@ -362,6 +362,7 @@ _paint_page (cairo_paginated_surface_t *surface)
|
|||
CAIRO_PAGINATED_MODE_RENDER);
|
||||
|
||||
status = _cairo_recording_surface_replay_region (surface->recording_surface,
|
||||
NULL,
|
||||
surface->target,
|
||||
CAIRO_RECORDING_REGION_NATIVE);
|
||||
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
|
|
|
|||
|
|
@ -2224,7 +2224,9 @@ _cairo_pdf_surface_emit_recording_surface (cairo_pdf_surface_t *surface,
|
|||
surface->height);
|
||||
}
|
||||
|
||||
status = _cairo_recording_surface_replay_region (recording_surface, &surface->base,
|
||||
status = _cairo_recording_surface_replay_region (recording_surface,
|
||||
NULL,
|
||||
&surface->base,
|
||||
CAIRO_RECORDING_REGION_NATIVE);
|
||||
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
if (unlikely (status))
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@
|
|||
#include "cairo-paginated-private.h"
|
||||
#include "cairo-recording-surface-private.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
#include "cairo-surface-subsurface-private.h"
|
||||
#include "cairo-output-stream-private.h"
|
||||
#include "cairo-type3-glyph-surface-private.h"
|
||||
#include "cairo-image-info-private.h"
|
||||
|
|
@ -1642,7 +1643,7 @@ _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t
|
|||
static cairo_bool_t
|
||||
surface_pattern_supported (const cairo_surface_pattern_t *pattern)
|
||||
{
|
||||
if (_cairo_surface_is_recording (pattern->surface))
|
||||
if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
|
||||
return TRUE;
|
||||
|
||||
if (pattern->surface->backend->acquire_source_image == NULL)
|
||||
|
|
@ -1753,7 +1754,7 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
|
|||
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
|
||||
|
||||
if ( _cairo_surface_is_recording (surface_pattern->surface)) {
|
||||
if (surface_pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
|
||||
if (pattern->extend == CAIRO_EXTEND_PAD)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
else
|
||||
|
|
@ -2431,7 +2432,81 @@ _cairo_ps_surface_emit_recording_surface (cairo_ps_surface_t *surface,
|
|||
surface->page_bbox.height);
|
||||
}
|
||||
|
||||
status = _cairo_recording_surface_replay_region (recording_surface, &surface->base,
|
||||
status = _cairo_recording_surface_replay_region (recording_surface,
|
||||
NULL,
|
||||
&surface->base,
|
||||
CAIRO_RECORDING_REGION_NATIVE);
|
||||
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->stream, " Q\n");
|
||||
surface->content = old_content;
|
||||
surface->width = old_width;
|
||||
surface->height = old_height;
|
||||
surface->page_bbox = old_page_bbox;
|
||||
surface->current_pattern_is_solid_color = FALSE;
|
||||
_cairo_pdf_operators_reset (&surface->pdf_operators);
|
||||
surface->cairo_to_ps = old_cairo_to_ps;
|
||||
|
||||
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
|
||||
&surface->cairo_to_ps);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_ps_surface_emit_recording_subsurface (cairo_ps_surface_t *surface,
|
||||
cairo_surface_t *recording_surface,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
{
|
||||
double old_width, old_height;
|
||||
cairo_matrix_t old_cairo_to_ps;
|
||||
cairo_content_t old_content;
|
||||
cairo_rectangle_int_t old_page_bbox;
|
||||
cairo_status_t status;
|
||||
|
||||
old_content = surface->content;
|
||||
old_width = surface->width;
|
||||
old_height = surface->height;
|
||||
old_page_bbox = surface->page_bbox;
|
||||
old_cairo_to_ps = surface->cairo_to_ps;
|
||||
|
||||
#if DEBUG_PS
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"%% _cairo_ps_surface_emit_recording_subsurface (%d, %d), (%d, %d)\n",
|
||||
extents->x, extents->y,
|
||||
extents->width, extents->height);
|
||||
#endif
|
||||
|
||||
surface->page_bbox.x = surface->page_bbox.y = 0;
|
||||
surface->page_bbox.width = surface->width = extents->width;
|
||||
surface->page_bbox.height = surface->height = extents->height;
|
||||
|
||||
surface->current_pattern_is_solid_color = FALSE;
|
||||
_cairo_pdf_operators_reset (&surface->pdf_operators);
|
||||
cairo_matrix_init (&surface->cairo_to_ps, 1, 0, 0, -1, 0, surface->height);
|
||||
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
|
||||
&surface->cairo_to_ps);
|
||||
_cairo_output_stream_printf (surface->stream, " q\n");
|
||||
|
||||
if (recording_surface->content == CAIRO_CONTENT_COLOR) {
|
||||
surface->content = CAIRO_CONTENT_COLOR;
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
" 0 g %d %d %d %d rectfill\n",
|
||||
surface->page_bbox.x,
|
||||
surface->page_bbox.y,
|
||||
surface->page_bbox.width,
|
||||
surface->page_bbox.height);
|
||||
}
|
||||
|
||||
status = _cairo_recording_surface_replay_region (recording_surface,
|
||||
extents,
|
||||
&surface->base,
|
||||
CAIRO_RECORDING_REGION_NATIVE);
|
||||
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
if (unlikely (status))
|
||||
|
|
@ -2515,18 +2590,25 @@ _cairo_ps_surface_acquire_surface (cairo_ps_surface_t *surface,
|
|||
surface->acquired_image = NULL;
|
||||
surface->image = NULL;
|
||||
|
||||
if (_cairo_surface_is_recording (pattern->surface)) {
|
||||
cairo_recording_surface_t *recording_surface = (cairo_recording_surface_t *) pattern->surface;
|
||||
cairo_box_t bbox;
|
||||
cairo_rectangle_int_t extents;
|
||||
if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
|
||||
if (pattern->surface->backend->type == CAIRO_INTERNAL_SURFACE_TYPE_SUBSURFACE) {
|
||||
cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) pattern->surface;
|
||||
|
||||
status = _cairo_recording_surface_get_bbox (recording_surface, &bbox, NULL);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
*width = sub->extents.width;
|
||||
*height = sub->extents.height;
|
||||
} else {
|
||||
cairo_recording_surface_t *recording_surface = (cairo_recording_surface_t *) pattern->surface;
|
||||
cairo_box_t bbox;
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
_cairo_box_round_to_rectangle (&bbox, &extents);
|
||||
*width = extents.width;
|
||||
*height =extents.height;
|
||||
status = _cairo_recording_surface_get_bbox (recording_surface, &bbox, NULL);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_box_round_to_rectangle (&bbox, &extents);
|
||||
*width = extents.width;
|
||||
*height = extents.height;
|
||||
}
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
} else {
|
||||
status = _cairo_surface_acquire_source_image (pattern->surface,
|
||||
|
|
@ -2596,10 +2678,15 @@ _cairo_ps_surface_emit_surface (cairo_ps_surface_t *surface,
|
|||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (_cairo_surface_is_recording (pattern->surface)) {
|
||||
cairo_surface_t *recording_surface = pattern->surface;
|
||||
if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING) {
|
||||
cairo_surface_t *source = pattern->surface;
|
||||
|
||||
status = _cairo_ps_surface_emit_recording_surface (surface, recording_surface);
|
||||
if (source->backend->type == CAIRO_INTERNAL_SURFACE_TYPE_SUBSURFACE) {
|
||||
cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
|
||||
status = _cairo_ps_surface_emit_recording_subsurface (surface, sub->target, &sub->extents);
|
||||
} else {
|
||||
status = _cairo_ps_surface_emit_recording_surface (surface, source);
|
||||
}
|
||||
} else {
|
||||
if (pattern->base.extend != CAIRO_EXTEND_PAD) {
|
||||
status = _cairo_ps_surface_emit_jpeg_image (surface, pattern->surface,
|
||||
|
|
@ -2622,7 +2709,7 @@ _cairo_ps_surface_release_surface (cairo_ps_surface_t *surface,
|
|||
if (surface->image != surface->acquired_image)
|
||||
cairo_surface_destroy (&surface->image->base);
|
||||
|
||||
if (! _cairo_surface_is_recording (pattern->surface)) {
|
||||
if (pattern->surface->type != CAIRO_SURFACE_TYPE_RECORDING) {
|
||||
_cairo_surface_release_source_image (pattern->surface,
|
||||
surface->acquired_image,
|
||||
surface->image_extra);
|
||||
|
|
|
|||
|
|
@ -157,6 +157,7 @@ _cairo_recording_surface_replay_and_create_regions (cairo_surface_t *surface,
|
|||
cairo_surface_t *target);
|
||||
cairo_private cairo_status_t
|
||||
_cairo_recording_surface_replay_region (cairo_surface_t *surface,
|
||||
const cairo_rectangle_int_t *surface_extents,
|
||||
cairo_surface_t *target,
|
||||
cairo_recording_region_type_t region);
|
||||
|
||||
|
|
|
|||
|
|
@ -786,6 +786,7 @@ _cairo_recording_surface_get_path (cairo_surface_t *surface,
|
|||
#define _clip(c) ((c)->header.clip.path ? &(c)->header.clip : NULL)
|
||||
static cairo_status_t
|
||||
_cairo_recording_surface_replay_internal (cairo_surface_t *surface,
|
||||
const cairo_rectangle_int_t *surface_extents,
|
||||
cairo_surface_t *target,
|
||||
cairo_recording_replay_type_t type,
|
||||
cairo_recording_region_type_t region)
|
||||
|
|
@ -802,13 +803,17 @@ _cairo_recording_surface_replay_internal (cairo_surface_t *surface,
|
|||
if (unlikely (target->status))
|
||||
return _cairo_surface_set_error (surface, target->status);
|
||||
|
||||
assert (_cairo_surface_is_recording (surface));
|
||||
|
||||
_cairo_surface_wrapper_init (&wrapper, target);
|
||||
_cairo_surface_wrapper_set_extents (&wrapper, surface_extents);
|
||||
|
||||
recording_surface = (cairo_recording_surface_t *) surface;
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
num_elements = recording_surface->commands.num_elements;
|
||||
elements = _cairo_array_index (&recording_surface->commands, 0);
|
||||
|
||||
for (i = recording_surface->replay_start_idx; i < num_elements; i++) {
|
||||
cairo_command_t *command = elements[i];
|
||||
|
||||
|
|
@ -975,7 +980,7 @@ cairo_status_t
|
|||
_cairo_recording_surface_replay (cairo_surface_t *surface,
|
||||
cairo_surface_t *target)
|
||||
{
|
||||
return _cairo_recording_surface_replay_internal (surface,
|
||||
return _cairo_recording_surface_replay_internal (surface, NULL,
|
||||
target,
|
||||
CAIRO_RECORDING_REPLAY,
|
||||
CAIRO_RECORDING_REGION_ALL);
|
||||
|
|
@ -991,7 +996,7 @@ cairo_status_t
|
|||
_cairo_recording_surface_replay_and_create_regions (cairo_surface_t *surface,
|
||||
cairo_surface_t *target)
|
||||
{
|
||||
return _cairo_recording_surface_replay_internal (surface,
|
||||
return _cairo_recording_surface_replay_internal (surface, NULL,
|
||||
target,
|
||||
CAIRO_RECORDING_CREATE_REGIONS,
|
||||
CAIRO_RECORDING_REGION_ALL);
|
||||
|
|
@ -999,10 +1004,11 @@ _cairo_recording_surface_replay_and_create_regions (cairo_surface_t *surface,
|
|||
|
||||
cairo_status_t
|
||||
_cairo_recording_surface_replay_region (cairo_surface_t *surface,
|
||||
const cairo_rectangle_int_t *surface_extents,
|
||||
cairo_surface_t *target,
|
||||
cairo_recording_region_type_t region)
|
||||
{
|
||||
return _cairo_recording_surface_replay_internal (surface,
|
||||
return _cairo_recording_surface_replay_internal (surface, surface_extents,
|
||||
target,
|
||||
CAIRO_RECORDING_REPLAY,
|
||||
region);
|
||||
|
|
|
|||
|
|
@ -86,8 +86,10 @@ struct _cairo_surface {
|
|||
/* A "snapshot" surface is immutable. See _cairo_surface_snapshot. */
|
||||
cairo_surface_t *snapshot_of;
|
||||
cairo_surface_func_t snapshot_detach;
|
||||
/* current snapshots of this surface, or place upon snapshot list */
|
||||
/* current snapshots of this surface*/
|
||||
cairo_list_t snapshots;
|
||||
/* place upon snapshot list */
|
||||
cairo_list_t snapshot;
|
||||
|
||||
/*
|
||||
* Surface font options, falling back to backend's default options,
|
||||
|
|
|
|||
|
|
@ -41,8 +41,10 @@
|
|||
struct _cairo_surface_subsurface {
|
||||
cairo_surface_t base;
|
||||
|
||||
cairo_surface_t *target;
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
cairo_surface_t *target;
|
||||
cairo_bool_t owns_target;
|
||||
};
|
||||
|
||||
#endif /* CAIRO_SURFACE_SUBSURFACE_PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -36,17 +36,26 @@
|
|||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-recording-surface-private.h"
|
||||
#include "cairo-surface-offset-private.h"
|
||||
#include "cairo-surface-subsurface-private.h"
|
||||
|
||||
static const cairo_surface_backend_t _cairo_surface_subsurface_backend;
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_surface_subsurface_finish (void *abstract_surface)
|
||||
{
|
||||
cairo_surface_subsurface_t *surface = abstract_surface;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (surface->owns_target) {
|
||||
cairo_surface_finish (surface->target);
|
||||
status = surface->target->status;
|
||||
}
|
||||
|
||||
cairo_surface_destroy (surface->target);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
|
|
@ -284,6 +293,46 @@ _cairo_surface_subsurface_acquire_source_image (void *abstrac
|
|||
struct extra *extra;
|
||||
uint8_t *data;
|
||||
|
||||
if (surface->target->type == CAIRO_SURFACE_TYPE_RECORDING) {
|
||||
cairo_recording_surface_t *meta = (cairo_recording_surface_t *) surface->target;
|
||||
cairo_surface_t *snapshot;
|
||||
|
||||
snapshot = _cairo_surface_has_snapshot (&surface->base,
|
||||
&_cairo_image_surface_backend);
|
||||
if (snapshot != NULL) {
|
||||
*image_out = (cairo_image_surface_t *) cairo_surface_reference (snapshot);
|
||||
*extra_out = NULL;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (! _cairo_surface_has_snapshot (&meta->base,
|
||||
&_cairo_image_surface_backend))
|
||||
{
|
||||
image = (cairo_image_surface_t *)
|
||||
_cairo_image_surface_create_with_content (meta->content,
|
||||
surface->extents.width,
|
||||
surface->extents.height);
|
||||
if (unlikely (image->base.status))
|
||||
return image->base.status;
|
||||
|
||||
cairo_surface_set_device_offset (&image->base,
|
||||
-surface->extents.x,
|
||||
-surface->extents.y);
|
||||
|
||||
status = _cairo_recording_surface_replay (&meta->base, &image->base);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (&image->base);
|
||||
return status;
|
||||
}
|
||||
|
||||
_cairo_surface_attach_snapshot (&surface->base, &image->base, NULL);
|
||||
|
||||
*image_out = image;
|
||||
*extra_out = NULL;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
extra = malloc (sizeof (struct extra));
|
||||
if (unlikely (extra == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
|
@ -344,10 +393,13 @@ _cairo_surface_subsurface_release_source_image (void *abstract
|
|||
void *abstract_extra)
|
||||
{
|
||||
cairo_surface_subsurface_t *surface = abstract_surface;
|
||||
struct extra *extra = abstract_extra;
|
||||
|
||||
_cairo_surface_release_source_image (surface->target, extra->image, extra->image_extra);
|
||||
free (extra);
|
||||
if (abstract_extra != NULL) {
|
||||
struct extra *extra = abstract_extra;
|
||||
|
||||
_cairo_surface_release_source_image (surface->target, extra->image, extra->image_extra);
|
||||
free (extra);
|
||||
}
|
||||
|
||||
cairo_surface_destroy (&image->base);
|
||||
}
|
||||
|
|
@ -356,37 +408,23 @@ static cairo_surface_t *
|
|||
_cairo_surface_subsurface_snapshot (void *abstract_surface)
|
||||
{
|
||||
cairo_surface_subsurface_t *surface = abstract_surface;
|
||||
cairo_image_surface_t *image, *clone;
|
||||
void *image_extra;
|
||||
cairo_status_t status;
|
||||
cairo_surface_subsurface_t *snapshot;
|
||||
|
||||
/* XXX Alternatively we could snapshot the target and return a subsurface
|
||||
* of that.
|
||||
*/
|
||||
snapshot = malloc (sizeof (cairo_surface_subsurface_t));
|
||||
if (unlikely (snapshot == NULL))
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
||||
status = _cairo_surface_acquire_source_image (surface->target, &image, &image_extra);
|
||||
if (unlikely (status))
|
||||
return _cairo_surface_create_in_error (status);
|
||||
_cairo_surface_init (&snapshot->base,
|
||||
&_cairo_surface_subsurface_backend,
|
||||
NULL, /* device */
|
||||
surface->target->content);
|
||||
snapshot->target = _cairo_surface_snapshot (surface->target);
|
||||
snapshot->owns_target = TRUE;
|
||||
|
||||
clone = (cairo_image_surface_t *)
|
||||
_cairo_image_surface_create_with_pixman_format (NULL,
|
||||
image->pixman_format,
|
||||
surface->extents.width,
|
||||
surface->extents.height,
|
||||
0);
|
||||
if (likely (clone->base.status == CAIRO_STATUS_SUCCESS)) {
|
||||
pixman_image_composite32 (PIXMAN_OP_SRC,
|
||||
image->pixman_image, NULL, clone->pixman_image,
|
||||
surface->extents.x, surface->extents.y,
|
||||
0, 0,
|
||||
0, 0,
|
||||
surface->extents.width, surface->extents.height);
|
||||
clone->base.is_clear = FALSE;
|
||||
}
|
||||
snapshot->base.type = snapshot->target->type;
|
||||
snapshot->extents = surface->extents;
|
||||
|
||||
_cairo_surface_release_source_image (surface->target, image, image_extra);
|
||||
|
||||
return &clone->base;
|
||||
return &snapshot->base;
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t _cairo_surface_subsurface_backend = {
|
||||
|
|
@ -486,6 +524,7 @@ cairo_surface_create_for_rectangle (cairo_surface_t *target,
|
|||
}
|
||||
|
||||
surface->target = cairo_surface_reference (target);
|
||||
surface->owns_target = FALSE;
|
||||
|
||||
return &surface->base;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,13 +46,18 @@ CAIRO_BEGIN_DECLS
|
|||
struct _cairo_surface_wrapper {
|
||||
cairo_surface_t *target;
|
||||
|
||||
/* any other information? */
|
||||
cairo_bool_t has_extents;
|
||||
cairo_rectangle_int_t extents;
|
||||
};
|
||||
|
||||
cairo_private void
|
||||
_cairo_surface_wrapper_init (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_surface_t *target);
|
||||
|
||||
cairo_private void
|
||||
_cairo_surface_wrapper_set_extents (cairo_surface_wrapper_t *wrapper,
|
||||
const cairo_rectangle_int_t *extents);
|
||||
|
||||
cairo_private void
|
||||
_cairo_surface_wrapper_fini (cairo_surface_wrapper_t *wrapper);
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,12 @@ _cairo_surface_wrapper_needs_device_transform (cairo_surface_wrapper_t *wrapper)
|
|||
return ! _cairo_matrix_is_identity (&wrapper->target->device_transform);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_surface_wrapper_needs_extents_transform (cairo_surface_wrapper_t *wrapper)
|
||||
{
|
||||
return wrapper->has_extents && (wrapper->extents.x | wrapper->extents.y);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_surface_wrapper_acquire_source_image (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_image_surface_t **image_out,
|
||||
|
|
@ -100,30 +106,58 @@ _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper,
|
|||
cairo_status_t status;
|
||||
cairo_clip_t clip_copy, *dev_clip = clip;
|
||||
cairo_pattern_union_t source_copy;
|
||||
cairo_clip_t target_clip;
|
||||
|
||||
if (unlikely (wrapper->target->status))
|
||||
return wrapper->target->status;
|
||||
|
||||
if (clip && clip->all_clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
if (wrapper->has_extents) {
|
||||
_cairo_clip_init_copy (&target_clip, clip);
|
||||
status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
dev_clip = clip = &target_clip;
|
||||
}
|
||||
|
||||
if (clip && clip->all_clipped) {
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
|
||||
_cairo_surface_wrapper_needs_extents_transform (wrapper))
|
||||
{
|
||||
cairo_matrix_t m;
|
||||
|
||||
cairo_matrix_init_identity (&m);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
|
||||
cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper))
|
||||
cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper)) {
|
||||
if (clip != NULL) {
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip,
|
||||
&wrapper->target->device_transform);
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
dev_clip = &clip_copy;
|
||||
}
|
||||
|
||||
_copy_transformed_pattern (&source_copy.base, source, &wrapper->target->device_transform_inverse);
|
||||
status = cairo_matrix_invert (&m);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
_copy_transformed_pattern (&source_copy.base, source, &m);
|
||||
source = &source_copy.base;
|
||||
}
|
||||
|
||||
status = _cairo_surface_paint (wrapper->target, op, source, dev_clip);
|
||||
|
||||
FINISH:
|
||||
if (wrapper->has_extents)
|
||||
_cairo_clip_reset (&target_clip);
|
||||
if (dev_clip != clip)
|
||||
_cairo_clip_reset (dev_clip);
|
||||
return status;
|
||||
|
|
@ -140,33 +174,61 @@ _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper,
|
|||
cairo_clip_t clip_copy, *dev_clip = clip;
|
||||
cairo_pattern_union_t source_copy;
|
||||
cairo_pattern_union_t mask_copy;
|
||||
cairo_clip_t target_clip;
|
||||
|
||||
if (unlikely (wrapper->target->status))
|
||||
return wrapper->target->status;
|
||||
|
||||
if (clip && clip->all_clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
if (wrapper->has_extents) {
|
||||
_cairo_clip_init_copy (&target_clip, clip);
|
||||
status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
dev_clip = clip = &target_clip;
|
||||
}
|
||||
|
||||
if (clip && clip->all_clipped) {
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
|
||||
_cairo_surface_wrapper_needs_extents_transform (wrapper))
|
||||
{
|
||||
cairo_matrix_t m;
|
||||
|
||||
cairo_matrix_init_identity (&m);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
|
||||
cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper))
|
||||
cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper)) {
|
||||
if (clip != NULL) {
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip,
|
||||
&wrapper->target->device_transform);
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
dev_clip = &clip_copy;
|
||||
}
|
||||
|
||||
_copy_transformed_pattern (&source_copy.base, source, &wrapper->target->device_transform_inverse);
|
||||
status = cairo_matrix_invert (&m);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
_copy_transformed_pattern (&source_copy.base, source, &m);
|
||||
source = &source_copy.base;
|
||||
|
||||
_copy_transformed_pattern (&mask_copy.base, mask, &wrapper->target->device_transform_inverse);
|
||||
_copy_transformed_pattern (&mask_copy.base, mask, &m);
|
||||
mask = &mask_copy.base;
|
||||
}
|
||||
|
||||
status = _cairo_surface_mask (wrapper->target, op, source, mask, dev_clip);
|
||||
|
||||
FINISH:
|
||||
if (wrapper->has_extents)
|
||||
_cairo_clip_reset (&target_clip);
|
||||
if (dev_clip != clip)
|
||||
_cairo_clip_reset (dev_clip);
|
||||
return status;
|
||||
|
|
@ -190,38 +252,65 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper,
|
|||
cairo_matrix_t dev_ctm = *ctm;
|
||||
cairo_matrix_t dev_ctm_inverse = *ctm_inverse;
|
||||
cairo_pattern_union_t source_copy;
|
||||
cairo_clip_t target_clip;
|
||||
|
||||
if (unlikely (wrapper->target->status))
|
||||
return wrapper->target->status;
|
||||
|
||||
if (clip && clip->all_clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
if (wrapper->has_extents) {
|
||||
_cairo_clip_init_copy (&target_clip, clip);
|
||||
status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
dev_clip = clip = &target_clip;
|
||||
}
|
||||
|
||||
if (clip && clip->all_clipped) {
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
|
||||
_cairo_surface_wrapper_needs_extents_transform (wrapper))
|
||||
{
|
||||
cairo_matrix_t m;
|
||||
|
||||
cairo_matrix_init_identity (&m);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
|
||||
cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper))
|
||||
cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper)) {
|
||||
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
_cairo_path_fixed_transform (&path_copy, &wrapper->target->device_transform);
|
||||
_cairo_path_fixed_transform (&path_copy, &m);
|
||||
dev_path = &path_copy;
|
||||
|
||||
if (clip != NULL) {
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip,
|
||||
&wrapper->target->device_transform);
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
dev_clip = &clip_copy;
|
||||
}
|
||||
|
||||
cairo_matrix_multiply (&dev_ctm, &dev_ctm, &wrapper->target->device_transform);
|
||||
cairo_matrix_multiply (&dev_ctm_inverse,
|
||||
&wrapper->target->device_transform_inverse,
|
||||
&dev_ctm_inverse);
|
||||
cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m);
|
||||
|
||||
_copy_transformed_pattern (&source_copy.base, source, &wrapper->target->device_transform_inverse);
|
||||
status = cairo_matrix_invert (&m);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse);
|
||||
|
||||
_copy_transformed_pattern (&source_copy.base, source, &m);
|
||||
source = &source_copy.base;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (clip != NULL) {
|
||||
dev_clip = &clip_copy;
|
||||
_cairo_clip_init_copy (&clip_copy, clip);
|
||||
|
|
@ -237,6 +326,8 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper,
|
|||
FINISH:
|
||||
if (dev_path != path)
|
||||
_cairo_path_fixed_fini (dev_path);
|
||||
if (wrapper->has_extents)
|
||||
_cairo_clip_reset (&target_clip);
|
||||
if (dev_clip != clip)
|
||||
_cairo_clip_reset (dev_clip);
|
||||
return status;
|
||||
|
|
@ -266,41 +357,68 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper,
|
|||
cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse;
|
||||
cairo_pattern_union_t stroke_source_copy;
|
||||
cairo_pattern_union_t fill_source_copy;
|
||||
cairo_clip_t target_clip;
|
||||
|
||||
if (unlikely (wrapper->target->status))
|
||||
return wrapper->target->status;
|
||||
|
||||
if (clip && clip->all_clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
if (wrapper->has_extents) {
|
||||
_cairo_clip_init_copy (&target_clip, clip);
|
||||
status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
dev_clip = clip = &target_clip;
|
||||
}
|
||||
|
||||
if (clip && clip->all_clipped) {
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
|
||||
_cairo_surface_wrapper_needs_extents_transform (wrapper))
|
||||
{
|
||||
cairo_matrix_t m;
|
||||
|
||||
cairo_matrix_init_identity (&m);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
|
||||
cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper))
|
||||
cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper)) {
|
||||
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
_cairo_path_fixed_transform (&path_copy, &wrapper->target->device_transform);
|
||||
_cairo_path_fixed_transform (&path_copy, &m);
|
||||
dev_path = &path_copy;
|
||||
|
||||
if (clip != NULL) {
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip,
|
||||
&wrapper->target->device_transform);
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
dev_clip = &clip_copy;
|
||||
}
|
||||
|
||||
cairo_matrix_multiply (&dev_ctm, &dev_ctm, &wrapper->target->device_transform);
|
||||
cairo_matrix_multiply (&dev_ctm_inverse,
|
||||
&wrapper->target->device_transform_inverse,
|
||||
&dev_ctm_inverse);
|
||||
cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m);
|
||||
|
||||
_copy_transformed_pattern (&stroke_source_copy.base, stroke_source, &wrapper->target->device_transform_inverse);
|
||||
status = cairo_matrix_invert (&m);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse);
|
||||
|
||||
_copy_transformed_pattern (&stroke_source_copy.base, stroke_source, &m);
|
||||
stroke_source = &stroke_source_copy.base;
|
||||
|
||||
_copy_transformed_pattern (&fill_source_copy.base, fill_source, &wrapper->target->device_transform_inverse);
|
||||
_copy_transformed_pattern (&fill_source_copy.base, fill_source, &m);
|
||||
fill_source = &fill_source_copy.base;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (clip != NULL) {
|
||||
dev_clip = &clip_copy;
|
||||
_cairo_clip_init_copy (&clip_copy, clip);
|
||||
|
|
@ -320,6 +438,8 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper,
|
|||
FINISH:
|
||||
if (dev_path != path)
|
||||
_cairo_path_fixed_fini (dev_path);
|
||||
if (wrapper->has_extents)
|
||||
_cairo_clip_reset (&target_clip);
|
||||
if (dev_clip != clip)
|
||||
_cairo_clip_reset (dev_clip);
|
||||
return status;
|
||||
|
|
@ -339,33 +459,61 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper,
|
|||
cairo_path_fixed_t path_copy, *dev_path = path;
|
||||
cairo_clip_t clip_copy, *dev_clip = clip;
|
||||
cairo_pattern_union_t source_copy;
|
||||
cairo_clip_t target_clip;
|
||||
|
||||
if (unlikely (wrapper->target->status))
|
||||
return wrapper->target->status;
|
||||
|
||||
if (clip && clip->all_clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
if (wrapper->has_extents) {
|
||||
_cairo_clip_init_copy (&target_clip, clip);
|
||||
status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
dev_clip = clip = &target_clip;
|
||||
}
|
||||
|
||||
if (clip && clip->all_clipped) {
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
|
||||
_cairo_surface_wrapper_needs_extents_transform (wrapper))
|
||||
{
|
||||
cairo_matrix_t m;
|
||||
|
||||
cairo_matrix_init_identity (&m);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
|
||||
cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper))
|
||||
cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper)) {
|
||||
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
_cairo_path_fixed_transform (&path_copy, &wrapper->target->device_transform);
|
||||
_cairo_path_fixed_transform (&path_copy, &m);
|
||||
dev_path = &path_copy;
|
||||
|
||||
if (clip != NULL) {
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip,
|
||||
&wrapper->target->device_transform);
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
dev_clip = &clip_copy;
|
||||
}
|
||||
|
||||
_copy_transformed_pattern (&source_copy.base, source, &wrapper->target->device_transform_inverse);
|
||||
status = cairo_matrix_invert (&m);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
_copy_transformed_pattern (&source_copy.base, source, &m);
|
||||
source = &source_copy.base;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (clip != NULL) {
|
||||
dev_clip = &clip_copy;
|
||||
_cairo_clip_init_copy (&clip_copy, clip);
|
||||
|
|
@ -380,6 +528,8 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper,
|
|||
FINISH:
|
||||
if (dev_path != path)
|
||||
_cairo_path_fixed_fini (dev_path);
|
||||
if (wrapper->has_extents)
|
||||
_cairo_clip_reset (&target_clip);
|
||||
if (dev_clip != clip)
|
||||
_cairo_clip_reset (dev_clip);
|
||||
return status;
|
||||
|
|
@ -403,6 +553,7 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
|
|||
cairo_clip_t clip_copy, *dev_clip = clip;
|
||||
cairo_glyph_t *dev_glyphs = glyphs;
|
||||
cairo_pattern_union_t source_copy;
|
||||
cairo_clip_t target_clip;
|
||||
|
||||
if (unlikely (wrapper->target->status))
|
||||
return wrapper->target->status;
|
||||
|
|
@ -410,15 +561,36 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
|
|||
if (glyphs == NULL || num_glyphs == 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (clip && clip->all_clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
if (wrapper->has_extents) {
|
||||
_cairo_clip_init_copy (&target_clip, clip);
|
||||
status = _cairo_clip_rectangle (&target_clip, &wrapper->extents);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper)) {
|
||||
dev_clip = clip = &target_clip;
|
||||
}
|
||||
|
||||
if (clip && clip->all_clipped) {
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper) ||
|
||||
_cairo_surface_wrapper_needs_extents_transform (wrapper))
|
||||
{
|
||||
cairo_matrix_t m;
|
||||
int i;
|
||||
|
||||
cairo_matrix_init_identity (&m);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_extents_transform (wrapper))
|
||||
cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y);
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper))
|
||||
cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m);
|
||||
|
||||
if (clip != NULL) {
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip,
|
||||
&wrapper->target->device_transform);
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
|
|
@ -433,14 +605,17 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
|
|||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
dev_glyphs[i] = glyphs[i];
|
||||
cairo_matrix_transform_point (&wrapper->target->device_transform,
|
||||
&dev_glyphs[i].x,
|
||||
&dev_glyphs[i].y);
|
||||
cairo_matrix_transform_point (&m, &dev_glyphs[i].x, &dev_glyphs[i].y);
|
||||
}
|
||||
|
||||
_copy_transformed_pattern (&source_copy.base, source, &wrapper->target->device_transform_inverse);
|
||||
status = cairo_matrix_invert (&m);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
_copy_transformed_pattern (&source_copy.base, source, &m);
|
||||
source = &source_copy.base;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (clip != NULL) {
|
||||
dev_clip = &clip_copy;
|
||||
_cairo_clip_init_copy (&clip_copy, clip);
|
||||
|
|
@ -454,9 +629,12 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
|
|||
cluster_flags,
|
||||
scaled_font,
|
||||
dev_clip);
|
||||
|
||||
FINISH:
|
||||
if (dev_clip != clip)
|
||||
_cairo_clip_reset (dev_clip);
|
||||
if (wrapper->has_extents)
|
||||
_cairo_clip_reset (&target_clip);
|
||||
if (dev_glyphs != glyphs)
|
||||
free (dev_glyphs);
|
||||
return status;
|
||||
|
|
@ -476,7 +654,28 @@ cairo_bool_t
|
|||
_cairo_surface_wrapper_get_extents (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
return _cairo_surface_get_extents (wrapper->target, extents);
|
||||
if (wrapper->has_extents) {
|
||||
if (_cairo_surface_get_extents (wrapper->target, extents))
|
||||
_cairo_rectangle_intersect (extents, &wrapper->extents);
|
||||
else
|
||||
*extents = wrapper->extents;
|
||||
|
||||
return TRUE;
|
||||
} else {
|
||||
return _cairo_surface_get_extents (wrapper->target, extents);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_surface_wrapper_set_extents (cairo_surface_wrapper_t *wrapper,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
{
|
||||
if (extents != NULL) {
|
||||
wrapper->extents = *extents;
|
||||
wrapper->has_extents = TRUE;
|
||||
} else {
|
||||
wrapper->has_extents = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -503,6 +702,7 @@ _cairo_surface_wrapper_init (cairo_surface_wrapper_t *wrapper,
|
|||
cairo_surface_t *target)
|
||||
{
|
||||
wrapper->target = cairo_surface_reference (target);
|
||||
wrapper->has_extents = FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ const cairo_surface_t name = { \
|
|||
NULL, /* snapshot_of */ \
|
||||
NULL, /* snapshot_detach */ \
|
||||
{ NULL, NULL }, /* snapshots */ \
|
||||
{ NULL, NULL }, /* snapshot */ \
|
||||
{ CAIRO_ANTIALIAS_DEFAULT, /* antialias */ \
|
||||
CAIRO_SUBPIXEL_ORDER_DEFAULT, /* subpixel_order */ \
|
||||
CAIRO_HINT_STYLE_DEFAULT, /* hint_style */ \
|
||||
|
|
@ -258,13 +259,10 @@ _cairo_surface_detach_mime_data (cairo_surface_t *surface)
|
|||
static void
|
||||
_cairo_surface_detach_snapshots (cairo_surface_t *surface)
|
||||
{
|
||||
if (surface->snapshot_of != NULL)
|
||||
return;
|
||||
|
||||
while (_cairo_surface_has_snapshots (surface)) {
|
||||
_cairo_surface_detach_snapshot (cairo_list_first_entry (&surface->snapshots,
|
||||
cairo_surface_t,
|
||||
snapshots));
|
||||
snapshot));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -274,7 +272,7 @@ _cairo_surface_detach_snapshot (cairo_surface_t *snapshot)
|
|||
assert (snapshot->snapshot_of != NULL);
|
||||
|
||||
snapshot->snapshot_of = NULL;
|
||||
cairo_list_del (&snapshot->snapshots);
|
||||
cairo_list_del (&snapshot->snapshot);
|
||||
|
||||
if (snapshot->snapshot_detach != NULL)
|
||||
snapshot->snapshot_detach (snapshot);
|
||||
|
|
@ -288,7 +286,6 @@ _cairo_surface_attach_snapshot (cairo_surface_t *surface,
|
|||
cairo_surface_func_t detach_func)
|
||||
{
|
||||
assert (surface != snapshot);
|
||||
assert (surface->snapshot_of == NULL);
|
||||
assert (snapshot->snapshot_of != surface);
|
||||
|
||||
cairo_surface_reference (snapshot);
|
||||
|
|
@ -299,7 +296,7 @@ _cairo_surface_attach_snapshot (cairo_surface_t *surface,
|
|||
snapshot->snapshot_of = surface;
|
||||
snapshot->snapshot_detach = detach_func;
|
||||
|
||||
cairo_list_add (&snapshot->snapshots, &surface->snapshots);
|
||||
cairo_list_add (&snapshot->snapshot, &surface->snapshots);
|
||||
|
||||
assert (_cairo_surface_has_snapshot (surface, snapshot->backend) == snapshot);
|
||||
}
|
||||
|
|
@ -311,7 +308,7 @@ _cairo_surface_has_snapshot (cairo_surface_t *surface,
|
|||
cairo_surface_t *snapshot;
|
||||
|
||||
cairo_list_foreach_entry (snapshot, cairo_surface_t,
|
||||
&surface->snapshots, snapshots)
|
||||
&surface->snapshots, snapshot)
|
||||
{
|
||||
/* XXX is_similar? */
|
||||
if (snapshot->backend == backend)
|
||||
|
|
|
|||
|
|
@ -1070,6 +1070,7 @@ REFERENCE_IMAGES = \
|
|||
stroke-image.xlib.ref.png \
|
||||
subsurface.ref.png \
|
||||
subsurface.image16.ref.png \
|
||||
subsurface-reflect.ref.png \
|
||||
subsurface-repeat.ref.png \
|
||||
subsurface-similar-repeat.ref.png \
|
||||
surface-pattern-big-scale-down.ref.png \
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ test_sources = \
|
|||
spline-decomposition.c \
|
||||
subsurface.c \
|
||||
subsurface-repeat.c \
|
||||
subsurface-reflect.c \
|
||||
subsurface-similar-repeat.c \
|
||||
surface-finish-twice.c \
|
||||
surface-pattern.c \
|
||||
|
|
|
|||
76
test/subsurface-reflect.c
Normal file
76
test/subsurface-reflect.c
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright 2009 Intel Corporation
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software
|
||||
* and its documentation for any purpose is hereby granted without
|
||||
* fee, provided that the above copyright notice appear in all copies
|
||||
* and that both that copyright notice and this permission notice
|
||||
* appear in supporting documentation, and that the name of
|
||||
* Intel not be used in advertising or publicity pertaining to
|
||||
* distribution of the software without specific, written prior
|
||||
* permission. Intel makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* INTEL CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
|
||||
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS, IN NO EVENT SHALL INTEL CORPORATION BE LIABLE FOR ANY SPECIAL,
|
||||
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
|
||||
* RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
* IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* Author: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairo-test.h"
|
||||
|
||||
static cairo_test_status_t
|
||||
draw (cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_surface_t *region;
|
||||
cairo_t *cr_region;
|
||||
|
||||
cairo_set_source_rgb (cr, .5, .5, .5);
|
||||
cairo_paint (cr);
|
||||
|
||||
/* fill the centre */
|
||||
region = cairo_surface_create_for_rectangle (cairo_get_target (cr),
|
||||
20, 20, 20, 20);
|
||||
cr_region = cairo_create (region);
|
||||
cairo_surface_destroy (region);
|
||||
|
||||
cairo_set_source_rgb (cr_region, 1, 1, 1);
|
||||
cairo_rectangle (cr_region, 0, 0, 10, 10);
|
||||
cairo_fill (cr_region);
|
||||
|
||||
cairo_set_source_rgb (cr_region, 1, 0, 0);
|
||||
cairo_rectangle (cr_region, 10, 0, 10, 10);
|
||||
cairo_fill (cr_region);
|
||||
|
||||
cairo_set_source_rgb (cr_region, 0, 1, 0);
|
||||
cairo_rectangle (cr_region, 0, 10, 10, 10);
|
||||
cairo_fill (cr_region);
|
||||
|
||||
cairo_set_source_rgb (cr_region, 0, 0, 1);
|
||||
cairo_rectangle (cr_region, 10, 10, 10, 10);
|
||||
cairo_fill (cr_region);
|
||||
|
||||
cairo_set_source_surface (cr, cairo_get_target (cr_region), 20, 20);
|
||||
cairo_destroy (cr_region);
|
||||
|
||||
/* reflect the pattern around the outside, but do not overwrite...*/
|
||||
cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REFLECT);
|
||||
cairo_rectangle (cr, 0, 0, width, height);
|
||||
cairo_rectangle (cr, 20, 40, 20, -20);
|
||||
cairo_fill (cr);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
}
|
||||
|
||||
CAIRO_TEST (subsurface_reflect,
|
||||
"Tests source clipping with reflect",
|
||||
"subsurface, reflect", /* keywords */
|
||||
NULL, /* requirements */
|
||||
60, 60,
|
||||
NULL, draw)
|
||||
BIN
test/subsurface-reflect.ref.png
Normal file
BIN
test/subsurface-reflect.ref.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 210 B |
|
|
@ -36,7 +36,7 @@ draw (cairo_t *cr, int width, int height)
|
|||
|
||||
/* fill the centre */
|
||||
region = cairo_surface_create_for_rectangle (cairo_get_target (cr),
|
||||
0, 0, 20, 20);
|
||||
20, 20, 20, 20);
|
||||
cr_region = cairo_create (region);
|
||||
cairo_surface_destroy (region);
|
||||
|
||||
|
|
@ -58,8 +58,12 @@ draw (cairo_t *cr, int width, int height)
|
|||
|
||||
cairo_set_source_surface (cr, cairo_get_target (cr_region), 20, 20);
|
||||
cairo_destroy (cr_region);
|
||||
|
||||
/* repeat the pattern around the outside, but do not overwrite...*/
|
||||
cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
|
||||
cairo_paint (cr);
|
||||
cairo_rectangle (cr, 0, 0, width, height);
|
||||
cairo_rectangle (cr, 20, 40, 20, -20);
|
||||
cairo_fill (cr);
|
||||
|
||||
return CAIRO_TEST_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ draw (cairo_t *cr, int width, int height)
|
|||
60, 60);
|
||||
cr_region = cairo_create (similar);
|
||||
cairo_surface_destroy (similar);
|
||||
|
||||
cairo_set_source_rgb (cr_region, .5, .5, .0);
|
||||
cairo_paint (cr_region);
|
||||
similar = cairo_surface_reference (cairo_get_target (cr_region));
|
||||
|
|
@ -48,6 +49,7 @@ draw (cairo_t *cr, int width, int height)
|
|||
/* fill the centre */
|
||||
region = cairo_surface_create_for_rectangle (similar, 20, 20, 20, 20);
|
||||
cairo_surface_destroy (similar);
|
||||
|
||||
cr_region = cairo_create (region);
|
||||
cairo_surface_destroy (region);
|
||||
|
||||
|
|
@ -69,6 +71,7 @@ draw (cairo_t *cr, int width, int height)
|
|||
|
||||
cairo_set_source_surface (cr, cairo_get_target (cr_region), 20, 20);
|
||||
cairo_destroy (cr_region);
|
||||
|
||||
cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
|
||||
cairo_paint (cr);
|
||||
|
||||
|
|
|
|||
|
|
@ -63,6 +63,11 @@ draw (cairo_t *cr, int width, int height)
|
|||
|
||||
for (i = 0; i < 5; i++) {
|
||||
cairo_set_source_surface (cr, region[5-i-1], 20 * i, 20);
|
||||
cairo_paint (cr);
|
||||
}
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
cairo_set_source_surface (cr, region[5-i-1], 20 * i, 40);
|
||||
cairo_paint_with_alpha (cr, .5);
|
||||
}
|
||||
|
||||
|
|
@ -76,5 +81,5 @@ CAIRO_TEST (subsurface,
|
|||
"Tests clipping of both source and destination using subsurfaces",
|
||||
"subsurface", /* keywords */
|
||||
NULL, /* requirements */
|
||||
100, 40,
|
||||
100, 60,
|
||||
NULL, draw)
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.8 KiB |
Loading…
Add table
Reference in a new issue