Remove clip handling from generic surface layer.
Handling clip as part of the surface state, as opposed to being part of the operation state, is cumbersome and a hindrance to providing true proxy surface support. For example, the clip must be copied from the surface onto the fallback image, but this was forgotten causing undue hassle in each backend. Another example is the contortion the meta surface endures to ensure the clip is correctly recorded. By contrast passing the clip along with the operation is quite simple and enables us to write generic handlers for providing surface wrappers. (And in the future, we should be able to write more esoteric wrappers, e.g. automatic 2x FSAA, trivially.) In brief, instead of the surface automatically applying the clip before calling the backend, the backend can call into a generic helper to apply clipping. For raster surfaces, clip regions are handled automatically as part of the composite interface. For vector surfaces, a clip helper is introduced to replay and callback into an intersect_clip_path() function as necessary. Whilst this is not primarily a performance related change (the change should just move the computation of the clip from the moment it is applied by the user to the moment it is required by the backend), it is important to track any potential regression: ppc: Speedups ======== image-rgba evolution-20090607-0 1026085.22 0.18% -> 672972.07 0.77%: 1.52x speedup ▌ image-rgba evolution-20090618-0 680579.98 0.12% -> 573237.66 0.16%: 1.19x speedup ▎ image-rgba swfdec-fill-rate-4xaa-0 460296.92 0.36% -> 407464.63 0.42%: 1.13x speedup ▏ image-rgba swfdec-fill-rate-2xaa-0 128431.95 0.47% -> 115051.86 0.42%: 1.12x speedup ▏ Slowdowns ========= image-rgba firefox-periodic-table-0 56837.61 0.78% -> 66055.17 3.20%: 1.09x slowdown ▏
6
NEWS
|
|
@ -9,6 +9,12 @@ API additions:
|
|||
Finally exporting the internal meta-surface so that applications
|
||||
have a method to record and replay a sequence of drawing commands.
|
||||
|
||||
cairo_in_clip()
|
||||
|
||||
Determines whether a given point is inside the current clip.
|
||||
??? Should this be called cairo_in_paint() instead? in-clip is the test
|
||||
that is performed, but in-paint would be similar to in-fill and in-stroke.
|
||||
|
||||
New utilities:
|
||||
|
||||
cairo-test-trace
|
||||
|
|
|
|||
|
|
@ -33,7 +33,6 @@
|
|||
static const cairo_user_data_key_t glitz_closure_key;
|
||||
|
||||
typedef struct _glitz_glx_target_closure {
|
||||
glitz_target_closure_base_t base;
|
||||
Display *dpy;
|
||||
int scr;
|
||||
Window win;
|
||||
|
|
@ -206,9 +205,6 @@ _cairo_boilerplate_glitz_glx_create_surface (const char *name,
|
|||
if (cairo_surface_status (surface))
|
||||
goto FAIL_CLOSE_DISPLAY;
|
||||
|
||||
gxtc->base.width = width;
|
||||
gxtc->base.height = height;
|
||||
gxtc->base.content = content;
|
||||
status = cairo_surface_set_user_data (surface,
|
||||
&glitz_closure_key, gxtc, NULL);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
|
|
|
|||
|
|
@ -129,7 +129,6 @@ _cairo_boilerplate_pdf_finish_surface (cairo_surface_t *surface)
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
cairo_surface_finish (surface);
|
||||
status = cairo_surface_status (surface);
|
||||
if (status)
|
||||
return status;
|
||||
|
|
|
|||
|
|
@ -178,6 +178,7 @@ _cairo_boilerplate_ps_finish_surface (cairo_surface_t *surface)
|
|||
|
||||
if (ptc->target) {
|
||||
cairo_t *cr;
|
||||
|
||||
cr = cairo_create (ptc->target);
|
||||
cairo_set_source_surface (cr, surface, 0, 0);
|
||||
cairo_paint (cr);
|
||||
|
|
@ -188,7 +189,6 @@ _cairo_boilerplate_ps_finish_surface (cairo_surface_t *surface)
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
cairo_surface_finish (surface);
|
||||
status = cairo_surface_status (surface);
|
||||
if (status)
|
||||
return status;
|
||||
|
|
@ -197,11 +197,7 @@ _cairo_boilerplate_ps_finish_surface (cairo_surface_t *surface)
|
|||
}
|
||||
|
||||
cairo_surface_finish (surface);
|
||||
status = cairo_surface_status (surface);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return cairo_surface_status (surface);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
* The Initial Developer of the Original Code is Chris Wilson.
|
||||
*/
|
||||
|
||||
#include "cairo-boilerplate.h"
|
||||
#include "cairo-boilerplate-private.h"
|
||||
|
||||
#include <cairo-qt.h>
|
||||
|
||||
|
|
@ -108,4 +108,6 @@ static const cairo_boilerplate_target_t targets[] = {
|
|||
_cairo_boilerplate_qt_cleanup
|
||||
},
|
||||
};
|
||||
extern "C" {
|
||||
CAIRO_BOILERPLATE (qt, targets)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -166,7 +166,6 @@ _cairo_boilerplate_svg_finish_surface (cairo_surface_t *surface)
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
cairo_surface_finish (surface);
|
||||
status = cairo_surface_status (surface);
|
||||
if (status)
|
||||
return status;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include <test-paginated-surface.h>
|
||||
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,9,3)
|
||||
#include <test-null-surface.h>
|
||||
#include <test-wrapping-surface.h>
|
||||
#endif
|
||||
|
||||
#include <cairo-types-private.h>
|
||||
|
|
@ -49,7 +50,8 @@ _cairo_boilerplate_test_fallback_create_surface (const char *name,
|
|||
void **closure)
|
||||
{
|
||||
*closure = NULL;
|
||||
return _cairo_test_fallback_surface_create (content, width, height);
|
||||
return _cairo_test_fallback_surface_create (content,
|
||||
ceil (width), ceil (height));
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
|
|
@ -64,7 +66,8 @@ _cairo_boilerplate_test_fallback16_create_surface (const char *name,
|
|||
void **closure)
|
||||
{
|
||||
*closure = NULL;
|
||||
return _cairo_test_fallback16_surface_create (content, width, height);
|
||||
return _cairo_test_fallback16_surface_create (content,
|
||||
ceil (width), ceil (height));
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
|
|
@ -89,11 +92,7 @@ _cairo_boilerplate_test_null_create_surface (const char *name,
|
|||
static const cairo_user_data_key_t test_paginated_closure_key;
|
||||
|
||||
typedef struct {
|
||||
unsigned char *data;
|
||||
cairo_content_t content;
|
||||
int width;
|
||||
int height;
|
||||
int stride;
|
||||
cairo_surface_t *target;
|
||||
} test_paginated_closure_t;
|
||||
|
||||
static cairo_surface_t *
|
||||
|
|
@ -115,18 +114,10 @@ _cairo_boilerplate_test_paginated_create_surface (const char *name,
|
|||
*closure = tpc = xmalloc (sizeof (test_paginated_closure_t));
|
||||
|
||||
format = cairo_boilerplate_format_from_content (content);
|
||||
tpc->target = cairo_image_surface_create (format,
|
||||
ceil (width), ceil (height));
|
||||
|
||||
tpc->content = content;
|
||||
tpc->width = width;
|
||||
tpc->height = height;
|
||||
tpc->stride = cairo_format_stride_for_width (format, width);
|
||||
tpc->data = xcalloc (tpc->stride, height);
|
||||
|
||||
surface = _cairo_test_paginated_surface_create_for_data (tpc->data,
|
||||
tpc->content,
|
||||
tpc->width,
|
||||
tpc->height,
|
||||
tpc->stride);
|
||||
surface = _cairo_test_paginated_surface_create (tpc->target);
|
||||
if (cairo_surface_status (surface))
|
||||
goto CLEANUP;
|
||||
|
||||
|
|
@ -139,8 +130,9 @@ _cairo_boilerplate_test_paginated_create_surface (const char *name,
|
|||
cairo_surface_destroy (surface);
|
||||
surface = cairo_boilerplate_surface_create_in_error (status);
|
||||
|
||||
cairo_surface_destroy (tpc->target);
|
||||
|
||||
CLEANUP:
|
||||
free (tpc->data);
|
||||
free (tpc);
|
||||
return surface;
|
||||
}
|
||||
|
|
@ -160,8 +152,6 @@ static cairo_status_t
|
|||
_cairo_boilerplate_test_paginated_surface_write_to_png (cairo_surface_t *surface,
|
||||
const char *filename)
|
||||
{
|
||||
cairo_surface_t *image;
|
||||
cairo_format_t format;
|
||||
test_paginated_closure_t *tpc;
|
||||
cairo_status_t status;
|
||||
|
||||
|
|
@ -172,19 +162,7 @@ _cairo_boilerplate_test_paginated_surface_write_to_png (cairo_surface_t *surface
|
|||
return status;
|
||||
|
||||
tpc = cairo_surface_get_user_data (surface, &test_paginated_closure_key);
|
||||
|
||||
format = cairo_boilerplate_format_from_content (tpc->content);
|
||||
|
||||
image = cairo_image_surface_create_for_data (tpc->data,
|
||||
format,
|
||||
tpc->width,
|
||||
tpc->height,
|
||||
tpc->stride);
|
||||
|
||||
status = cairo_surface_write_to_png (image, filename);
|
||||
cairo_surface_destroy (image);
|
||||
|
||||
return status;
|
||||
return cairo_surface_write_to_png (tpc->target, filename);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
|
|
@ -193,7 +171,6 @@ _cairo_boilerplate_test_paginated_get_image_surface (cairo_surface_t *surface,
|
|||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_format_t format;
|
||||
test_paginated_closure_t *tpc;
|
||||
cairo_status_t status;
|
||||
|
||||
|
|
@ -208,30 +185,7 @@ _cairo_boilerplate_test_paginated_get_image_surface (cairo_surface_t *surface,
|
|||
return cairo_boilerplate_surface_create_in_error (status);
|
||||
|
||||
tpc = cairo_surface_get_user_data (surface, &test_paginated_closure_key);
|
||||
|
||||
format = cairo_boilerplate_format_from_content (tpc->content);
|
||||
|
||||
if (0) {
|
||||
return cairo_image_surface_create_for_data (tpc->data + tpc->stride * (tpc->height - height) + 4 * (tpc->width - width), /* hide the device offset */
|
||||
format,
|
||||
width,
|
||||
height,
|
||||
tpc->stride);
|
||||
} else {
|
||||
cairo_surface_t *image, *surface;
|
||||
|
||||
image = cairo_image_surface_create_for_data (tpc->data,
|
||||
format,
|
||||
tpc->width,
|
||||
tpc->height,
|
||||
tpc->stride);
|
||||
cairo_surface_set_device_offset (image,
|
||||
tpc->width - width,
|
||||
tpc->height - height);
|
||||
surface = _cairo_boilerplate_get_image_surface (image, 0, width, height);
|
||||
cairo_surface_destroy (image);
|
||||
return surface;
|
||||
}
|
||||
return _cairo_boilerplate_get_image_surface (tpc->target, 0, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -239,10 +193,40 @@ _cairo_boilerplate_test_paginated_cleanup (void *closure)
|
|||
{
|
||||
test_paginated_closure_t *tpc = closure;
|
||||
|
||||
free (tpc->data);
|
||||
cairo_surface_destroy (tpc->target);
|
||||
free (tpc);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_boilerplate_test_wrapping_create_surface (const char *name,
|
||||
cairo_content_t content,
|
||||
double width,
|
||||
double height,
|
||||
double max_width,
|
||||
double max_height,
|
||||
cairo_boilerplate_mode_t mode,
|
||||
int id,
|
||||
void **closure)
|
||||
{
|
||||
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1,9,3)
|
||||
cairo_surface_t *target;
|
||||
cairo_surface_t *surface;
|
||||
cairo_format_t format;
|
||||
|
||||
*closure = NULL;
|
||||
|
||||
format = cairo_boilerplate_format_from_content (content);
|
||||
target = cairo_image_surface_create (format, ceil (width), ceil (height));
|
||||
surface = _cairo_test_wrapping_surface_create (target);
|
||||
cairo_surface_destroy (target);
|
||||
|
||||
return surface;
|
||||
#else
|
||||
*closure = NULL;
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static const cairo_boilerplate_target_t targets[] = {
|
||||
{
|
||||
"test-fallback", "image", NULL, NULL,
|
||||
|
|
@ -304,6 +288,15 @@ static const cairo_boilerplate_target_t targets[] = {
|
|||
NULL,
|
||||
FALSE, TRUE
|
||||
},
|
||||
{
|
||||
"test-wrapping", "image", NULL, NULL,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_WRAPPING,
|
||||
CAIRO_CONTENT_COLOR_ALPHA, 0,
|
||||
_cairo_boilerplate_test_wrapping_create_surface,
|
||||
NULL, NULL,
|
||||
_cairo_boilerplate_get_image_surface,
|
||||
cairo_surface_write_to_png,
|
||||
},
|
||||
{
|
||||
"null", "image", NULL, NULL,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_NULL,
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@
|
|||
#include <cairo-types-private.h>
|
||||
#include <cairo-scaled-font-private.h>
|
||||
|
||||
#if CAIRO_HAS_SCRIPT_SURFACE
|
||||
#include <cairo-script.h>
|
||||
#endif
|
||||
|
||||
/* get the "real" version info instead of dummy cairo-version.h */
|
||||
#undef CAIRO_VERSION_H
|
||||
#include "../cairo-version.h"
|
||||
|
|
@ -136,48 +140,74 @@ _cairo_boilerplate_meta_create_surface (const char *name,
|
|||
int id,
|
||||
void **closure)
|
||||
{
|
||||
cairo_rectangle_t extents;
|
||||
|
||||
*closure = NULL;
|
||||
return cairo_meta_surface_create (content, width, height);
|
||||
|
||||
extents.x = 0;
|
||||
extents.y = 0;
|
||||
extents.width = width;
|
||||
extents.height = height;
|
||||
return cairo_meta_surface_create (content, &extents);
|
||||
}
|
||||
|
||||
const cairo_user_data_key_t cairo_boilerplate_output_basename_key;
|
||||
|
||||
#if CAIRO_HAS_SCRIPT_SURFACE
|
||||
static cairo_status_t
|
||||
stdio_write (void *closure, const unsigned char *data, unsigned int len)
|
||||
{
|
||||
if (fwrite (data, len, 1, closure) != 1)
|
||||
return CAIRO_STATUS_WRITE_ERROR;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_boilerplate_get_image_surface (cairo_surface_t *src,
|
||||
int page,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
FILE *file = NULL;
|
||||
cairo_surface_t *surface, *image;
|
||||
cairo_t *cr;
|
||||
cairo_status_t status;
|
||||
|
||||
if (cairo_surface_status (src))
|
||||
return cairo_surface_reference (src);
|
||||
|
||||
#if 0
|
||||
if (cairo_surface_get_type (src) == CAIRO_SURFACE_TYPE_IMAGE) {
|
||||
int ww = cairo_image_surface_get_width (src);
|
||||
int hh = cairo_image_surface_get_height (src);
|
||||
if (width == ww && hh == height) {
|
||||
return cairo_surface_reference (src);
|
||||
} else {
|
||||
cairo_format_t format = cairo_image_surface_get_format (src);
|
||||
unsigned char *data = cairo_image_surface_get_data (src);
|
||||
int stride = cairo_image_surface_get_stride (src);
|
||||
|
||||
data += stride * (hh - height) + 4 * (ww - width);
|
||||
return cairo_image_surface_create_for_data (data,
|
||||
format,
|
||||
width,
|
||||
height,
|
||||
stride);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (page != 0)
|
||||
return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
||||
|
||||
/* extract sub-surface */
|
||||
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
|
||||
image = cairo_surface_reference (surface);
|
||||
|
||||
/* open a logging channel (only interesting for meta surfaces) */
|
||||
#if CAIRO_HAS_SCRIPT_SURFACE
|
||||
if (cairo_surface_get_type (src) == CAIRO_SURFACE_TYPE_META) {
|
||||
const char *test_name;
|
||||
|
||||
test_name = cairo_surface_get_user_data (src,
|
||||
&cairo_boilerplate_output_basename_key);
|
||||
if (test_name != NULL) {
|
||||
char *filename;
|
||||
|
||||
xasprintf (&filename, "%s.out.trace", test_name);
|
||||
file = fopen (filename, "w");
|
||||
free (filename);
|
||||
|
||||
if (file != NULL) {
|
||||
surface = cairo_script_surface_create_for_target (image,
|
||||
stdio_write,
|
||||
file);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
cr = cairo_create (surface);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
|
|
@ -185,10 +215,17 @@ _cairo_boilerplate_get_image_surface (cairo_surface_t *src,
|
|||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_paint (cr);
|
||||
|
||||
surface = cairo_surface_reference (cairo_get_target (cr));
|
||||
status = cairo_status (cr);
|
||||
if (status) {
|
||||
cairo_surface_destroy (image);
|
||||
image = cairo_surface_reference (cairo_get_target (cr));
|
||||
}
|
||||
cairo_destroy (cr);
|
||||
|
||||
return surface;
|
||||
if (file != NULL)
|
||||
fclose (file);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
|
|
@ -705,8 +742,13 @@ cairo_boilerplate_convert_to_image (const char *filename, int page)
|
|||
|
||||
image = cairo_boilerplate_image_surface_create_from_ppm_stream (file);
|
||||
ret = pclose (file);
|
||||
/* check for fatal errors from the interpreter */
|
||||
if (ret) { /* any2pmm should never die... */
|
||||
cairo_surface_destroy (image);
|
||||
return cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_INVALID_STATUS);
|
||||
}
|
||||
|
||||
if (cairo_surface_status (image) == CAIRO_STATUS_READ_ERROR) {
|
||||
if (ret == 0 && cairo_surface_status (image) == CAIRO_STATUS_READ_ERROR) {
|
||||
if (flags == 0) {
|
||||
/* Try again in a standalone process. */
|
||||
cairo_surface_destroy (image);
|
||||
|
|
@ -715,12 +757,6 @@ cairo_boilerplate_convert_to_image (const char *filename, int page)
|
|||
}
|
||||
}
|
||||
|
||||
if (cairo_surface_status (image) == CAIRO_STATUS_SUCCESS && ret != 0) {
|
||||
cairo_surface_destroy (image);
|
||||
image =
|
||||
cairo_boilerplate_surface_create_in_error (CAIRO_STATUS_READ_ERROR);
|
||||
};
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,6 +99,8 @@ CAIRO_BEGIN_DECLS
|
|||
* PDF surfaces. */
|
||||
#define CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED ((unsigned int) -1)
|
||||
|
||||
extern const cairo_user_data_key_t cairo_boilerplate_output_basename_key;
|
||||
|
||||
cairo_content_t
|
||||
cairo_boilerplate_content (cairo_content_t content);
|
||||
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ do_unaligned_clip (cairo_t *cr, int width, int height)
|
|||
cairo_rectangle (cr, 55, 55, 35, 35);
|
||||
cairo_clip (cr);
|
||||
|
||||
/* And paint something to force the clip to be evaluated. */
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_restore (cr);
|
||||
|
|
|
|||
|
|
@ -79,11 +79,14 @@ cairo_private = \
|
|||
cairo-path-private.h \
|
||||
cairo-private.h \
|
||||
cairo-reference-count-private.h \
|
||||
cairo-region-private.h \
|
||||
cairo-scaled-font-private.h \
|
||||
cairo-skiplist-private.h \
|
||||
cairo-spans-private.h \
|
||||
cairo-surface-fallback-private.h \
|
||||
cairo-surface-private.h \
|
||||
cairo-surface-clipper-private.h \
|
||||
cairo-surface-wrapper-private.h \
|
||||
cairo-types-private.h \
|
||||
cairo-user-font-private.h \
|
||||
cairo-wideint-private.h \
|
||||
|
|
@ -138,6 +141,8 @@ cairo_sources = \
|
|||
cairo-stroke-style.c \
|
||||
cairo-surface.c \
|
||||
cairo-surface-fallback.c \
|
||||
cairo-surface-clipper.c \
|
||||
cairo-surface-wrapper.c \
|
||||
cairo-tor-scan-converter.c \
|
||||
cairo-system.c \
|
||||
cairo-traps.c \
|
||||
|
|
@ -198,12 +203,14 @@ cairo_test_surfaces_private = \
|
|||
test-fallback16-surface.h \
|
||||
test-null-surface.h \
|
||||
test-paginated-surface.h \
|
||||
test-wrapping-surface.h \
|
||||
$(NULL)
|
||||
cairo_test_surfaces_sources = \
|
||||
test-fallback-surface.c \
|
||||
test-fallback16-surface.c \
|
||||
test-null-surface.c \
|
||||
test-paginated-surface.c \
|
||||
test-wrapping-surface.c \
|
||||
$(NULL)
|
||||
|
||||
cairo_xlib_headers = cairo-xlib.h
|
||||
|
|
|
|||
|
|
@ -38,13 +38,11 @@
|
|||
#include "cairoint.h"
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_analysis_surface_create (cairo_surface_t *target,
|
||||
int width,
|
||||
int height);
|
||||
_cairo_analysis_surface_create (cairo_surface_t *target);
|
||||
|
||||
cairo_private void
|
||||
_cairo_analysis_surface_set_ctm (cairo_surface_t *surface,
|
||||
cairo_matrix_t *ctm);
|
||||
const cairo_matrix_t *ctm);
|
||||
|
||||
cairo_private void
|
||||
_cairo_analysis_surface_get_ctm (cairo_surface_t *surface,
|
||||
|
|
|
|||
|
|
@ -39,13 +39,12 @@
|
|||
#include "cairo-analysis-surface-private.h"
|
||||
#include "cairo-paginated-private.h"
|
||||
#include "cairo-meta-surface-private.h"
|
||||
#include "cairo-region-private.h"
|
||||
|
||||
typedef struct {
|
||||
cairo_surface_t base;
|
||||
int width;
|
||||
int height;
|
||||
|
||||
cairo_surface_t *target;
|
||||
cairo_surface_t *target;
|
||||
|
||||
cairo_bool_t first_op;
|
||||
cairo_bool_t has_supported;
|
||||
|
|
@ -53,7 +52,6 @@ typedef struct {
|
|||
|
||||
cairo_region_t supported_region;
|
||||
cairo_region_t fallback_region;
|
||||
cairo_rectangle_int_t current_clip;
|
||||
cairo_box_t page_bbox;
|
||||
|
||||
cairo_bool_t has_ctm;
|
||||
|
|
@ -97,61 +95,38 @@ static cairo_int_status_t
|
|||
_analyze_meta_surface_pattern (cairo_analysis_surface_t *surface,
|
||||
const cairo_pattern_t *pattern)
|
||||
{
|
||||
cairo_surface_t *analysis = &surface->base;
|
||||
const cairo_surface_pattern_t *surface_pattern;
|
||||
cairo_status_t status;
|
||||
cairo_bool_t old_has_ctm;
|
||||
cairo_matrix_t old_ctm, p2d;
|
||||
cairo_rectangle_int_t old_clip;
|
||||
cairo_rectangle_int_t meta_extents;
|
||||
int old_width;
|
||||
int old_height;
|
||||
cairo_status_t status;
|
||||
|
||||
assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
|
||||
surface_pattern = (const cairo_surface_pattern_t *) pattern;
|
||||
assert (_cairo_surface_is_meta (surface_pattern->surface));
|
||||
|
||||
old_width = surface->width;
|
||||
old_height = surface->height;
|
||||
old_clip = surface->current_clip;
|
||||
status = _cairo_surface_get_extents (surface_pattern->surface, &meta_extents);
|
||||
if (_cairo_status_is_error (status))
|
||||
return status;
|
||||
|
||||
surface->width = meta_extents.width;
|
||||
surface->height = meta_extents.height;
|
||||
surface->current_clip.x = 0;
|
||||
surface->current_clip.y = 0;
|
||||
surface->current_clip.width = surface->width;
|
||||
surface->current_clip.height = surface->height;
|
||||
old_ctm = surface->ctm;
|
||||
old_has_ctm = surface->has_ctm;
|
||||
|
||||
p2d = pattern->matrix;
|
||||
status = cairo_matrix_invert (&p2d);
|
||||
/* _cairo_pattern_set_matrix guarantees invertibility */
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
cairo_matrix_multiply (&surface->ctm, &p2d, &surface->ctm);
|
||||
surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
|
||||
surface->has_ctm = ! _cairo_matrix_is_identity (&surface->ctm);
|
||||
|
||||
status = _cairo_meta_surface_replay_and_create_regions (surface_pattern->surface,
|
||||
analysis);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = analysis->status;
|
||||
&surface->base);
|
||||
|
||||
surface->ctm = old_ctm;
|
||||
surface->has_ctm = old_has_ctm;
|
||||
surface->current_clip = old_clip;
|
||||
surface->width = old_width;
|
||||
surface->height = old_height;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_add_operation (cairo_analysis_surface_t *surface,
|
||||
cairo_rectangle_int_t *rect,
|
||||
cairo_int_status_t backend_status)
|
||||
_add_operation (cairo_analysis_surface_t *surface,
|
||||
cairo_rectangle_int_t *rect,
|
||||
cairo_int_status_t backend_status)
|
||||
{
|
||||
cairo_int_status_t status;
|
||||
cairo_box_t bbox;
|
||||
|
|
@ -174,26 +149,33 @@ _add_operation (cairo_analysis_surface_t *surface,
|
|||
_cairo_box_from_rectangle (&bbox, rect);
|
||||
|
||||
if (surface->has_ctm) {
|
||||
int tx, ty;
|
||||
|
||||
_cairo_matrix_transform_bounding_box_fixed (&surface->ctm, &bbox, NULL);
|
||||
if (_cairo_matrix_is_integer_translation (&surface->ctm, &tx, &ty)) {
|
||||
rect->x += tx;
|
||||
rect->y += ty;
|
||||
} else {
|
||||
_cairo_matrix_transform_bounding_box_fixed (&surface->ctm,
|
||||
&bbox, NULL);
|
||||
|
||||
if (bbox.p1.x == bbox.p2.x || bbox.p1.y == bbox.p2.y) {
|
||||
/* Even though the operation is not visible we must be
|
||||
* careful to not allow unsupported operations to be
|
||||
* replayed to the backend during
|
||||
* CAIRO_PAGINATED_MODE_RENDER */
|
||||
if (backend_status == CAIRO_STATUS_SUCCESS ||
|
||||
backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY)
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CAIRO_INT_STATUS_IMAGE_FALLBACK;
|
||||
if (bbox.p1.x == bbox.p2.x || bbox.p1.y == bbox.p2.y) {
|
||||
/* Even though the operation is not visible we must be
|
||||
* careful to not allow unsupported operations to be
|
||||
* replayed to the backend during
|
||||
* CAIRO_PAGINATED_MODE_RENDER */
|
||||
if (backend_status == CAIRO_STATUS_SUCCESS ||
|
||||
backend_status == CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY)
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CAIRO_INT_STATUS_IMAGE_FALLBACK;
|
||||
}
|
||||
}
|
||||
|
||||
_cairo_box_round_to_rectangle (&bbox, rect);
|
||||
}
|
||||
|
||||
_cairo_box_round_to_rectangle (&bbox, rect);
|
||||
}
|
||||
|
||||
if (surface->first_op) {
|
||||
|
|
@ -234,8 +216,7 @@ _add_operation (cairo_analysis_surface_t *surface,
|
|||
* this region will be emitted as native operations.
|
||||
*/
|
||||
surface->has_supported = TRUE;
|
||||
status = cairo_region_union_rectangle (&surface->supported_region, rect);
|
||||
return status;
|
||||
return cairo_region_union_rectangle (&surface->supported_region, rect);
|
||||
}
|
||||
|
||||
/* Add the operation to the unsupported region. This region will
|
||||
|
|
@ -270,33 +251,7 @@ _cairo_analysis_surface_finish (void *abstract_surface)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_analysis_surface_intersect_clip_path (void *abstract_surface,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
|
||||
if (path == NULL) {
|
||||
surface->current_clip.x = 0;
|
||||
surface->current_clip.y = 0;
|
||||
surface->current_clip.width = surface->width;
|
||||
surface->current_clip.height = surface->height;
|
||||
} else {
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_bool_t is_empty;
|
||||
|
||||
_cairo_path_fixed_approximate_clip_extents (path, &extents);
|
||||
is_empty = _cairo_rectangle_intersect (&surface->current_clip,
|
||||
&extents);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_analysis_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
|
|
@ -305,66 +260,92 @@ _cairo_analysis_surface_get_extents (void *abstract_surface,
|
|||
return _cairo_surface_get_extents (surface->target, rectangle);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_analysis_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_rectangle_int_t *paint_extents)
|
||||
static void
|
||||
_rectangle_intersect_clip (cairo_rectangle_int_t *extents, cairo_clip_t *clip)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status, backend_status;
|
||||
cairo_rectangle_int_t extents;
|
||||
const cairo_rectangle_int_t *clip_extents;
|
||||
cairo_bool_t is_empty;
|
||||
|
||||
if (!surface->target->backend->paint)
|
||||
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
else
|
||||
backend_status = (*surface->target->backend->paint) (surface->target, op,
|
||||
source, NULL);
|
||||
clip_extents = NULL;
|
||||
if (clip != NULL)
|
||||
clip_extents = _cairo_clip_get_extents (clip);
|
||||
|
||||
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
||||
backend_status = _analyze_meta_surface_pattern (surface, source);
|
||||
if (clip_extents != NULL)
|
||||
is_empty = _cairo_rectangle_intersect (extents, clip_extents);
|
||||
}
|
||||
|
||||
status = _cairo_surface_get_extents (&surface->base, &extents);
|
||||
if (_cairo_status_is_error (status))
|
||||
return status;
|
||||
static void
|
||||
_cairo_analysis_surface_operation_extents (cairo_analysis_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_clip_t *clip,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_bool_t is_empty;
|
||||
|
||||
is_empty = _cairo_surface_get_extents (&surface->base, extents);
|
||||
|
||||
if (_cairo_operator_bounded_by_source (op)) {
|
||||
cairo_rectangle_int_t source_extents;
|
||||
|
||||
status = _cairo_pattern_get_extents (source, &source_extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
|
||||
_cairo_pattern_get_extents (source, &source_extents);
|
||||
is_empty = _cairo_rectangle_intersect (extents, &source_extents);
|
||||
}
|
||||
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
|
||||
if (paint_extents)
|
||||
*paint_extents = extents;
|
||||
|
||||
status = _add_operation (surface, &extents, backend_status);
|
||||
|
||||
return status;
|
||||
_rectangle_intersect_clip (extents, clip);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_analysis_surface_mask (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_rectangle_int_t *mask_extents)
|
||||
_cairo_analysis_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status, backend_status;
|
||||
cairo_status_t backend_status;
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
if (surface->target->backend->paint == NULL) {
|
||||
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
} else {
|
||||
backend_status =
|
||||
surface->target->backend->paint (surface->target,
|
||||
op, source, clip);
|
||||
if (_cairo_status_is_error (backend_status))
|
||||
return backend_status;
|
||||
}
|
||||
|
||||
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
||||
backend_status = _analyze_meta_surface_pattern (surface, source);
|
||||
|
||||
_cairo_analysis_surface_operation_extents (surface,
|
||||
op, source, clip,
|
||||
&extents);
|
||||
|
||||
return _add_operation (surface, &extents, backend_status);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_analysis_surface_mask (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t backend_status;
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_bool_t is_empty;
|
||||
|
||||
if (!surface->target->backend->mask)
|
||||
if (surface->target->backend->mask == NULL) {
|
||||
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
else
|
||||
backend_status = (*surface->target->backend->mask) (surface->target, op,
|
||||
source, mask, NULL);
|
||||
} else {
|
||||
backend_status =
|
||||
surface->target->backend->mask (surface->target,
|
||||
op, source, mask, clip);
|
||||
if (_cairo_status_is_error (backend_status))
|
||||
return backend_status;
|
||||
}
|
||||
|
||||
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN) {
|
||||
cairo_int_status_t backend_source_status = CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -395,37 +376,19 @@ _cairo_analysis_surface_mask (void *abstract_surface,
|
|||
backend_mask_status);
|
||||
}
|
||||
|
||||
status = _cairo_surface_get_extents (&surface->base, &extents);
|
||||
if (_cairo_status_is_error (status))
|
||||
return status;
|
||||
|
||||
if (_cairo_operator_bounded_by_source (op)) {
|
||||
cairo_rectangle_int_t source_extents;
|
||||
|
||||
status = _cairo_pattern_get_extents (source, &source_extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
|
||||
}
|
||||
_cairo_analysis_surface_operation_extents (surface,
|
||||
op, source, clip,
|
||||
&extents);
|
||||
|
||||
if (_cairo_operator_bounded_by_mask (op)) {
|
||||
cairo_rectangle_int_t mask_extents;
|
||||
|
||||
status = _cairo_pattern_get_extents (mask, &mask_extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_pattern_get_extents (mask, &mask_extents);
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
|
||||
|
||||
}
|
||||
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
|
||||
if (mask_extents)
|
||||
*mask_extents = extents;
|
||||
|
||||
status = _add_operation (surface, &extents, backend_status);
|
||||
|
||||
return status;
|
||||
return _add_operation (surface, &extents, backend_status);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -438,55 +401,61 @@ _cairo_analysis_surface_stroke (void *abstract_surface,
|
|||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *stroke_extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status, backend_status;
|
||||
cairo_status_t backend_status;
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_bool_t is_empty;
|
||||
|
||||
if (!surface->target->backend->stroke)
|
||||
if (surface->target->backend->stroke == NULL) {
|
||||
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
else
|
||||
backend_status = (*surface->target->backend->stroke) (surface->target, op,
|
||||
source, path, style,
|
||||
ctm, ctm_inverse,
|
||||
tolerance, antialias, NULL);
|
||||
} else {
|
||||
backend_status =
|
||||
surface->target->backend->stroke (surface->target, op,
|
||||
source, path, style,
|
||||
ctm, ctm_inverse,
|
||||
tolerance, antialias,
|
||||
clip);
|
||||
if (_cairo_status_is_error (backend_status))
|
||||
return backend_status;
|
||||
}
|
||||
|
||||
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
||||
backend_status = _analyze_meta_surface_pattern (surface, source);
|
||||
|
||||
status = _cairo_surface_get_extents (&surface->base, &extents);
|
||||
if (_cairo_status_is_error (status))
|
||||
return status;
|
||||
|
||||
if (_cairo_operator_bounded_by_source (op)) {
|
||||
cairo_rectangle_int_t source_extents;
|
||||
|
||||
status = _cairo_pattern_get_extents (source, &source_extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
|
||||
}
|
||||
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
|
||||
_cairo_analysis_surface_operation_extents (surface,
|
||||
op, source, clip,
|
||||
&extents);
|
||||
|
||||
if (_cairo_operator_bounded_by_mask (op)) {
|
||||
cairo_rectangle_int_t mask_extents;
|
||||
|
||||
_cairo_path_fixed_approximate_stroke_extents (path,
|
||||
style, ctm,
|
||||
&mask_extents);
|
||||
/* If the backend can handle the stroke, then mark the approximate
|
||||
* extents of the operation. However, if we need to fallback in order
|
||||
* to draw the stroke, then ensure that the fallback is as tight as
|
||||
* possible -- both to minimise output file size and to ensure good
|
||||
* quality printed output for neighbouring regions.
|
||||
*/
|
||||
if (backend_status == CAIRO_STATUS_SUCCESS) {
|
||||
_cairo_path_fixed_approximate_stroke_extents (path,
|
||||
style, ctm,
|
||||
&mask_extents);
|
||||
} else {
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_path_fixed_stroke_extents (path, style,
|
||||
ctm, ctm_inverse,
|
||||
tolerance,
|
||||
&mask_extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
|
||||
}
|
||||
if (stroke_extents)
|
||||
*stroke_extents = extents;
|
||||
|
||||
status = _add_operation (surface, &extents, backend_status);
|
||||
|
||||
return status;
|
||||
return _add_operation (surface, &extents, backend_status);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -497,53 +466,49 @@ _cairo_analysis_surface_fill (void *abstract_surface,
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *fill_extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status, backend_status;
|
||||
cairo_status_t backend_status;
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_bool_t is_empty;
|
||||
|
||||
if (!surface->target->backend->fill)
|
||||
if (surface->target->backend->fill == NULL) {
|
||||
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
else
|
||||
backend_status = (*surface->target->backend->fill) (surface->target, op,
|
||||
source, path, fill_rule,
|
||||
tolerance, antialias, NULL);
|
||||
} else {
|
||||
backend_status =
|
||||
surface->target->backend->fill (surface->target, op,
|
||||
source, path, fill_rule,
|
||||
tolerance, antialias,
|
||||
clip);
|
||||
if (_cairo_status_is_error (backend_status))
|
||||
return backend_status;
|
||||
}
|
||||
|
||||
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
||||
backend_status = _analyze_meta_surface_pattern (surface, source);
|
||||
|
||||
status = _cairo_surface_get_extents (&surface->base, &extents);
|
||||
if (_cairo_status_is_error (status))
|
||||
return status;
|
||||
|
||||
if (_cairo_operator_bounded_by_source (op)) {
|
||||
cairo_rectangle_int_t source_extents;
|
||||
|
||||
status = _cairo_pattern_get_extents (source, &source_extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
|
||||
}
|
||||
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
|
||||
_cairo_analysis_surface_operation_extents (surface,
|
||||
op, source, clip,
|
||||
&extents);
|
||||
|
||||
if (_cairo_operator_bounded_by_mask (op)) {
|
||||
cairo_rectangle_int_t mask_extents;
|
||||
|
||||
_cairo_path_fixed_approximate_fill_extents (path,
|
||||
&mask_extents);
|
||||
|
||||
/* We want speed for the likely case where the operation can be
|
||||
* performed natively, but accuracy if we have to resort to
|
||||
* using images.
|
||||
*/
|
||||
if (backend_status == CAIRO_STATUS_SUCCESS) {
|
||||
_cairo_path_fixed_approximate_fill_extents (path, &mask_extents);
|
||||
} else {
|
||||
_cairo_path_fixed_fill_extents (path, fill_rule, tolerance,
|
||||
&mask_extents);
|
||||
}
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &mask_extents);
|
||||
}
|
||||
if (fill_extents)
|
||||
*fill_extents = extents;
|
||||
|
||||
status = _add_operation (surface, &extents, backend_status);
|
||||
|
||||
return status;
|
||||
return _add_operation (surface, &extents, backend_status);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -553,8 +518,8 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface,
|
|||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
int *remaining_glyphs,
|
||||
cairo_rectangle_int_t *show_glyphs_extents)
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status, backend_status;
|
||||
|
|
@ -562,41 +527,42 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface,
|
|||
cairo_bool_t is_empty;
|
||||
|
||||
/* Adapted from _cairo_surface_show_glyphs */
|
||||
if (surface->target->backend->show_glyphs)
|
||||
backend_status = (*surface->target->backend->show_glyphs) (surface->target, op,
|
||||
source,
|
||||
glyphs, num_glyphs,
|
||||
scaled_font,
|
||||
remaining_glyphs, NULL);
|
||||
else if (surface->target->backend->show_text_glyphs)
|
||||
backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
|
||||
source,
|
||||
NULL, 0,
|
||||
glyphs, num_glyphs,
|
||||
NULL, 0,
|
||||
FALSE,
|
||||
scaled_font, NULL);
|
||||
if (surface->target->backend->show_glyphs != NULL) {
|
||||
backend_status =
|
||||
surface->target->backend->show_glyphs (surface->target, op,
|
||||
source,
|
||||
glyphs, num_glyphs,
|
||||
scaled_font,
|
||||
clip,
|
||||
remaining_glyphs);
|
||||
if (_cairo_status_is_error (backend_status))
|
||||
return backend_status;
|
||||
}
|
||||
else if (surface->target->backend->show_text_glyphs != NULL)
|
||||
{
|
||||
backend_status =
|
||||
surface->target->backend->show_text_glyphs (surface->target, op,
|
||||
source,
|
||||
NULL, 0,
|
||||
glyphs, num_glyphs,
|
||||
NULL, 0,
|
||||
FALSE,
|
||||
scaled_font,
|
||||
clip);
|
||||
if (_cairo_status_is_error (backend_status))
|
||||
return backend_status;
|
||||
}
|
||||
else
|
||||
{
|
||||
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
||||
backend_status = _analyze_meta_surface_pattern (surface, source);
|
||||
|
||||
status = _cairo_surface_get_extents (&surface->base, &extents);
|
||||
if (_cairo_status_is_error (status))
|
||||
return status;
|
||||
|
||||
if (_cairo_operator_bounded_by_source (op)) {
|
||||
cairo_rectangle_int_t source_extents;
|
||||
|
||||
status = _cairo_pattern_get_extents (source, &source_extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
|
||||
}
|
||||
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
|
||||
_cairo_analysis_surface_operation_extents (surface,
|
||||
op, source, clip,
|
||||
&extents);
|
||||
|
||||
if (_cairo_operator_bounded_by_mask (op)) {
|
||||
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
|
||||
|
|
@ -608,12 +574,8 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface,
|
|||
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents);
|
||||
}
|
||||
if (show_glyphs_extents)
|
||||
*show_glyphs_extents = extents;
|
||||
|
||||
status = _add_operation (surface, &extents, backend_status);
|
||||
|
||||
return status;
|
||||
return _add_operation (surface, &extents, backend_status);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
|
|
@ -636,7 +598,7 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
|
|||
int num_clusters,
|
||||
cairo_text_cluster_flags_t cluster_flags,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_rectangle_int_t *show_text_glyphs_extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status, backend_status;
|
||||
|
|
@ -645,20 +607,33 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
|
|||
|
||||
/* Adapted from _cairo_surface_show_glyphs */
|
||||
backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (surface->target->backend->show_text_glyphs)
|
||||
backend_status = surface->target->backend->show_text_glyphs (surface->target, op,
|
||||
source,
|
||||
utf8, utf8_len,
|
||||
glyphs, num_glyphs,
|
||||
clusters, num_clusters, cluster_flags,
|
||||
scaled_font, NULL);
|
||||
if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED && surface->target->backend->show_glyphs) {
|
||||
if (surface->target->backend->show_text_glyphs != NULL) {
|
||||
backend_status =
|
||||
surface->target->backend->show_text_glyphs (surface->target, op,
|
||||
source,
|
||||
utf8, utf8_len,
|
||||
glyphs, num_glyphs,
|
||||
clusters, num_clusters,
|
||||
cluster_flags,
|
||||
scaled_font,
|
||||
clip);
|
||||
if (_cairo_status_is_error (backend_status))
|
||||
return backend_status;
|
||||
}
|
||||
if (backend_status == CAIRO_INT_STATUS_UNSUPPORTED &&
|
||||
surface->target->backend->show_glyphs != NULL)
|
||||
{
|
||||
int remaining_glyphs = num_glyphs;
|
||||
backend_status = surface->target->backend->show_glyphs (surface->target, op,
|
||||
source,
|
||||
glyphs, num_glyphs,
|
||||
scaled_font,
|
||||
&remaining_glyphs, NULL);
|
||||
backend_status =
|
||||
surface->target->backend->show_glyphs (surface->target, op,
|
||||
source,
|
||||
glyphs, num_glyphs,
|
||||
scaled_font,
|
||||
clip,
|
||||
&remaining_glyphs);
|
||||
if (_cairo_status_is_error (backend_status))
|
||||
return backend_status;
|
||||
|
||||
glyphs += num_glyphs - remaining_glyphs;
|
||||
num_glyphs = remaining_glyphs;
|
||||
if (remaining_glyphs == 0)
|
||||
|
|
@ -668,21 +643,9 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
|
|||
if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
|
||||
backend_status = _analyze_meta_surface_pattern (surface, source);
|
||||
|
||||
status = _cairo_surface_get_extents (&surface->base, &extents);
|
||||
if (_cairo_status_is_error (status))
|
||||
return status;
|
||||
|
||||
if (_cairo_operator_bounded_by_source (op)) {
|
||||
cairo_rectangle_int_t source_extents;
|
||||
|
||||
status = _cairo_pattern_get_extents (source, &source_extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &source_extents);
|
||||
}
|
||||
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &surface->current_clip);
|
||||
_cairo_analysis_surface_operation_extents (surface,
|
||||
op, source, clip,
|
||||
&extents);
|
||||
|
||||
if (_cairo_operator_bounded_by_mask (op)) {
|
||||
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
|
||||
|
|
@ -694,12 +657,8 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
|
|||
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &glyph_extents);
|
||||
}
|
||||
if (show_text_glyphs_extents)
|
||||
*show_text_glyphs_extents = extents;
|
||||
|
||||
status = _add_operation (surface, &extents, backend_status);
|
||||
|
||||
return status;
|
||||
return _add_operation (surface, &extents, backend_status);
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_analysis_surface_backend = {
|
||||
|
|
@ -718,8 +677,6 @@ static const cairo_surface_backend_t cairo_analysis_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
NULL, /* set_clip_region */
|
||||
_cairo_analysis_surface_intersect_clip_path,
|
||||
_cairo_analysis_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
|
|
@ -734,7 +691,6 @@ static const cairo_surface_backend_t cairo_analysis_surface_backend = {
|
|||
_cairo_analysis_surface_show_glyphs,
|
||||
NULL, /* snapshot */
|
||||
NULL, /* is_similar */
|
||||
NULL, /* reset */
|
||||
NULL, /* fill_stroke */
|
||||
NULL, /* create_solid_pattern_surface */
|
||||
NULL, /* can_repaint_solid_pattern_surface */
|
||||
|
|
@ -743,9 +699,7 @@ static const cairo_surface_backend_t cairo_analysis_surface_backend = {
|
|||
};
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_analysis_surface_create (cairo_surface_t *target,
|
||||
int width,
|
||||
int height)
|
||||
_cairo_analysis_surface_create (cairo_surface_t *target)
|
||||
{
|
||||
cairo_analysis_surface_t *surface;
|
||||
cairo_status_t status;
|
||||
|
|
@ -763,8 +717,6 @@ _cairo_analysis_surface_create (cairo_surface_t *target,
|
|||
_cairo_surface_init (&surface->base, &cairo_analysis_surface_backend,
|
||||
CAIRO_CONTENT_COLOR_ALPHA);
|
||||
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
cairo_matrix_init_identity (&surface->ctm);
|
||||
surface->has_ctm = FALSE;
|
||||
|
||||
|
|
@ -781,24 +733,12 @@ _cairo_analysis_surface_create (cairo_surface_t *target,
|
|||
surface->page_bbox.p2.x = 0;
|
||||
surface->page_bbox.p2.y = 0;
|
||||
|
||||
if (width == -1 && height == -1) {
|
||||
surface->current_clip.x = CAIRO_RECT_INT_MIN;
|
||||
surface->current_clip.y = CAIRO_RECT_INT_MIN;
|
||||
surface->current_clip.width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
|
||||
surface->current_clip.height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
|
||||
} else {
|
||||
surface->current_clip.x = 0;
|
||||
surface->current_clip.y = 0;
|
||||
surface->current_clip.width = width;
|
||||
surface->current_clip.height = height;
|
||||
}
|
||||
|
||||
return &surface->base;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_analysis_surface_set_ctm (cairo_surface_t *abstract_surface,
|
||||
cairo_matrix_t *ctm)
|
||||
const cairo_matrix_t *ctm)
|
||||
{
|
||||
cairo_analysis_surface_t *surface;
|
||||
|
||||
|
|
@ -808,7 +748,7 @@ _cairo_analysis_surface_set_ctm (cairo_surface_t *abstract_surface,
|
|||
surface = (cairo_analysis_surface_t *) abstract_surface;
|
||||
|
||||
surface->ctm = *ctm;
|
||||
surface->has_ctm = !_cairo_matrix_is_identity (&surface->ctm);
|
||||
surface->has_ctm = ! _cairo_matrix_is_identity (&surface->ctm);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -871,22 +811,18 @@ _return_success (void)
|
|||
}
|
||||
|
||||
/* These typedefs are just to silence the compiler... */
|
||||
typedef cairo_int_status_t
|
||||
(*_set_clip_region_func) (void *surface,
|
||||
cairo_region_t *region);
|
||||
|
||||
typedef cairo_int_status_t
|
||||
(*_paint_func) (void *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
typedef cairo_int_status_t
|
||||
(*_mask_func) (void *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
typedef cairo_int_status_t
|
||||
(*_stroke_func) (void *surface,
|
||||
|
|
@ -898,7 +834,7 @@ typedef cairo_int_status_t
|
|||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
typedef cairo_int_status_t
|
||||
(*_fill_func) (void *surface,
|
||||
|
|
@ -908,7 +844,7 @@ typedef cairo_int_status_t
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
typedef cairo_int_status_t
|
||||
(*_show_glyphs_func) (void *surface,
|
||||
|
|
@ -917,8 +853,8 @@ typedef cairo_int_status_t
|
|||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
int *remaining_glyphs,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs);
|
||||
|
||||
static const cairo_surface_backend_t cairo_null_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_NULL,
|
||||
|
|
@ -937,8 +873,6 @@ static const cairo_surface_backend_t cairo_null_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
(_set_clip_region_func) _return_success, /* set_clip_region */
|
||||
NULL, /* intersect_clip_path */
|
||||
NULL, /* get_extents */
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
|
|
@ -953,7 +887,6 @@ static const cairo_surface_backend_t cairo_null_surface_backend = {
|
|||
(_show_glyphs_func) _return_success, /* show_glyphs */
|
||||
NULL, /* snapshot */
|
||||
NULL, /* is_similar */
|
||||
NULL, /* reset */
|
||||
NULL, /* fill_stroke */
|
||||
NULL, /* create_solid_pattern_surface */
|
||||
NULL, /* can_repaint_solid_pattern_surface */
|
||||
|
|
|
|||
|
|
@ -56,6 +56,8 @@
|
|||
struct cairo_beos_surface_t {
|
||||
cairo_surface_t base;
|
||||
|
||||
cairo_region_t *clip_region;
|
||||
|
||||
BView* view;
|
||||
|
||||
/*
|
||||
|
|
@ -70,7 +72,6 @@ struct cairo_beos_surface_t {
|
|||
|
||||
BBitmap* bitmap;
|
||||
|
||||
|
||||
// If true, surface and view should be deleted when this surface is
|
||||
// destroyed
|
||||
bool owns_bitmap_view;
|
||||
|
|
@ -101,27 +102,28 @@ _cairo_beos_surface_create_internal (BView* view,
|
|||
BBitmap* bmp,
|
||||
bool owns_bitmap_view = false);
|
||||
|
||||
static BRect
|
||||
_cairo_rect_to_brect (const cairo_rectangle_int16_t* rect)
|
||||
static inline BRect
|
||||
_cairo_rectangle_to_brect (const cairo_rectangle_int_t* rect)
|
||||
{
|
||||
// A BRect is one pixel wider than you'd think
|
||||
return BRect(rect->x, rect->y, rect->x + rect->width - 1,
|
||||
rect->y + rect->height - 1);
|
||||
return BRect (rect->x, rect->y,
|
||||
rect->x + rect->width - 1,
|
||||
rect->y + rect->height - 1);
|
||||
}
|
||||
|
||||
static cairo_rectangle_int16_t
|
||||
_brect_to_cairo_rect (const BRect& rect)
|
||||
static inline cairo_rectangle_int_t
|
||||
_brect_to_cairo_rectangle (const BRect &rect)
|
||||
{
|
||||
cairo_rectangle_int16_t retval;
|
||||
retval.x = int(rect.left + 0.5);
|
||||
retval.y = int(rect.top + 0.5);
|
||||
retval.width = rect.IntegerWidth() + 1;
|
||||
retval.height = rect.IntegerHeight() + 1;
|
||||
cairo_rectangle_int_t retval;
|
||||
retval.x = floor (rect.left);
|
||||
retval.y = floor (rect.top);
|
||||
retval.width = ceil (rect.right) - retval.x + 1;
|
||||
retval.height = ceil (rect.bottom) - rectval.y + 1;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static rgb_color
|
||||
_cairo_color_to_be_color (const cairo_color_t* color)
|
||||
static inline rgb_color
|
||||
_cairo_color_to_be_color (const cairo_color_t *color)
|
||||
{
|
||||
// This factor ensures a uniform distribution of numbers
|
||||
const float factor = 256 - 1e-5;
|
||||
|
|
@ -199,32 +201,8 @@ _cairo_beos_view_to_bitmap (BView* view,
|
|||
return ERROR;
|
||||
}
|
||||
|
||||
inline unsigned char
|
||||
unpremultiply (unsigned char color,
|
||||
unsigned char alpha)
|
||||
{
|
||||
if (alpha == 0)
|
||||
return 0;
|
||||
// plus alpha/2 to round instead of truncate
|
||||
return (color * 255 + alpha / 2) / alpha;
|
||||
}
|
||||
|
||||
inline unsigned char
|
||||
premultiply (unsigned char color,
|
||||
unsigned char alpha)
|
||||
{
|
||||
// + 127 to round, instead of truncate
|
||||
return (color * alpha + 127) / 255;
|
||||
}
|
||||
|
||||
/**
|
||||
* unpremultiply_rgba:
|
||||
*
|
||||
* Takes an input in ABGR premultiplied image data and unmultiplies it.
|
||||
* The result is stored in retdata.
|
||||
**/
|
||||
static void
|
||||
unpremultiply_rgba (unsigned char* data,
|
||||
unpremultiply_bgra (unsigned char* data,
|
||||
int width,
|
||||
int height,
|
||||
int stride,
|
||||
|
|
@ -235,52 +213,108 @@ unpremultiply_rgba (unsigned char* data,
|
|||
in < end;
|
||||
in += stride, out += stride)
|
||||
{
|
||||
for (int i = 0; i < width; ++i) {
|
||||
// XXX for a big-endian platform this'd have to change
|
||||
int idx = 4 * i;
|
||||
unsigned char alpha = in[idx + 3];
|
||||
out[idx + 0] = unpremultiply(in[idx + 0], alpha); // B
|
||||
out[idx + 1] = unpremultiply(in[idx + 1], alpha); // G
|
||||
out[idx + 2] = unpremultiply(in[idx + 2], alpha); // R
|
||||
out[idx + 3] = in[idx + 3]; // Alpha
|
||||
for (int i = 0; i < width; i ++) {
|
||||
uint8_t *b = &out[4*i];
|
||||
uint32_t pixel;
|
||||
uint8_t alpha;
|
||||
|
||||
memcpy (&pixel, &data[4*i], sizeof (uint32_t));
|
||||
alpha = pixel & 0xff;
|
||||
if (alpha == 0) {
|
||||
b[0] = b[1] = b[2] = b[3] = 0;
|
||||
} else {
|
||||
b[0] = (((pixel >> 24) & 0xff) * 255 + alpha / 2) / alpha;
|
||||
b[1] = (((pixel >> 16) & 0xff) * 255 + alpha / 2) / alpha;
|
||||
b[2] = (((pixel >> 8) & 0xff) * 255 + alpha / 2) / alpha;
|
||||
b[3] = alpha;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* premultiply_rgba:
|
||||
*
|
||||
* Takes an input in ABGR non-premultiplied image data and premultiplies it.
|
||||
* The returned data must be freed with free().
|
||||
**/
|
||||
static inline int
|
||||
multiply_alpha (int alpha, int color)
|
||||
{
|
||||
int temp = (alpha * color) + 0x80;
|
||||
return ((temp + (temp >> 8)) >> 8);
|
||||
}
|
||||
|
||||
static unsigned char*
|
||||
premultiply_rgba (unsigned char* data,
|
||||
premultiply_bgra (unsigned char* data,
|
||||
int width,
|
||||
int height,
|
||||
int stride)
|
||||
{
|
||||
unsigned char* retdata = reinterpret_cast<unsigned char*>(_cairo_malloc_ab(height, stride));
|
||||
uint8_t * retdata = reinterpret_cast<unsigned char*>(_cairo_malloc_ab(height, stride));
|
||||
if (!retdata)
|
||||
return NULL;
|
||||
|
||||
unsigned char* end = data + stride * height;
|
||||
for (unsigned char* in = data, *out = retdata;
|
||||
uint8_t * end = data + stride * height;
|
||||
for (uint8_t * in = data, *out = retdata;
|
||||
in < end;
|
||||
in += stride, out += stride)
|
||||
{
|
||||
for (int i = 0; i < width; ++i) {
|
||||
// XXX for a big-endian platform this'd have to change
|
||||
int idx = 4 * i;
|
||||
unsigned char alpha = in[idx + 3];
|
||||
out[idx + 0] = premultiply(in[idx + 0], alpha); // B
|
||||
out[idx + 1] = premultiply(in[idx + 1], alpha); // G
|
||||
out[idx + 2] = premultiply(in[idx + 2], alpha); // R
|
||||
out[idx + 3] = in[idx + 3]; // Alpha
|
||||
for (int i = 0; i < width; i ++) {
|
||||
uint8_t *base = &in[4*i];
|
||||
uint8_t alpha = base[3];
|
||||
uint32_t p;
|
||||
|
||||
if (alpha == 0) {
|
||||
p = 0;
|
||||
} else {
|
||||
uint8_t blue = base[0];
|
||||
uint8_t green = base[1];
|
||||
uint8_t red = base[2];
|
||||
|
||||
if (alpha != 0xff) {
|
||||
blue = multiply_alpha (alpha, blue);
|
||||
green = multiply_alpha (alpha, green);
|
||||
red = multiply_alpha (alpha, red);
|
||||
}
|
||||
p = (alpha << 0) | (red << 8) | (green << 16) | (blue << 24);
|
||||
}
|
||||
memcpy (&out[4*i], &p, sizeof (uint32_t));
|
||||
}
|
||||
}
|
||||
return retdata;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_beos_surface_set_clip_region (cairo_beos_surface_t *surface,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
|
||||
abstract_surface);
|
||||
AutoLockView locker(surface->view);
|
||||
assert (locker);
|
||||
|
||||
if (region == surface->clip_region)
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
|
||||
cairo_region_destroy (surface->clip_region);
|
||||
surface->clip_region = cairo_region_reference (region);
|
||||
|
||||
if (region == NULL) {
|
||||
// No clipping
|
||||
surface->view->ConstrainClippingRegion(NULL);
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int count = cairo_region_num_rectangles (region);
|
||||
BRegion bregion;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
// Have to substract one, because for pixman, the second coordinate
|
||||
// lies outside the rectangle.
|
||||
bregion.Include (_cairo_rectangle_to_brect (&rect));
|
||||
}
|
||||
surface->view->ConstrainClippingRegion(&bregion);
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* _cairo_beos_bitmap_to_surface:
|
||||
*
|
||||
|
|
@ -309,8 +343,8 @@ _cairo_beos_bitmap_to_surface (BBitmap* bitmap)
|
|||
return imgsurf;
|
||||
}
|
||||
|
||||
cairo_format_t cformat = format == B_RGB32 ? CAIRO_FORMAT_RGB24
|
||||
: CAIRO_FORMAT_ARGB32;
|
||||
cairo_format_t cformat = format == B_RGB32 ?
|
||||
CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32;
|
||||
|
||||
BRect bounds(bitmap->Bounds());
|
||||
unsigned char* bits = reinterpret_cast<unsigned char*>(bitmap->Bits());
|
||||
|
|
@ -318,8 +352,8 @@ _cairo_beos_bitmap_to_surface (BBitmap* bitmap)
|
|||
int height = bounds.IntegerHeight() + 1;
|
||||
unsigned char* premultiplied;
|
||||
if (cformat == CAIRO_FORMAT_ARGB32) {
|
||||
premultiplied = premultiply_rgba(bits, width, height,
|
||||
bitmap->BytesPerRow());
|
||||
premultiplied = premultiply_bgra (bits, width, height,
|
||||
bitmap->BytesPerRow());
|
||||
} else {
|
||||
premultiplied = reinterpret_cast<unsigned char*>(
|
||||
_cairo_malloc_ab(bitmap->BytesPerRow(), height));
|
||||
|
|
@ -327,7 +361,7 @@ _cairo_beos_bitmap_to_surface (BBitmap* bitmap)
|
|||
memcpy(premultiplied, bits, bitmap->BytesPerRow() * height);
|
||||
}
|
||||
if (!premultiplied)
|
||||
return NULL;
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
||||
cairo_image_surface_t* surf = reinterpret_cast<cairo_image_surface_t*>
|
||||
(cairo_image_surface_create_for_data(premultiplied,
|
||||
|
|
@ -355,11 +389,11 @@ _cairo_image_surface_to_bitmap (cairo_image_surface_t* surface)
|
|||
switch (surface->format) {
|
||||
case CAIRO_FORMAT_ARGB32: {
|
||||
BBitmap* data = new BBitmap(size, B_RGBA32);
|
||||
unpremultiply_rgba(surface->data,
|
||||
surface->width,
|
||||
surface->height,
|
||||
surface->stride,
|
||||
reinterpret_cast<unsigned char*>(data->Bits()));
|
||||
unpremultiply_bgra (surface->data,
|
||||
surface->width,
|
||||
surface->height,
|
||||
surface->stride,
|
||||
reinterpret_cast<unsigned char*>(data->Bits()));
|
||||
return data;
|
||||
}
|
||||
case CAIRO_FORMAT_RGB24: {
|
||||
|
|
@ -384,44 +418,44 @@ _cairo_op_to_be_op (cairo_operator_t cairo_op,
|
|||
drawing_mode* beos_op)
|
||||
{
|
||||
switch (cairo_op) {
|
||||
case CAIRO_OPERATOR_SOURCE:
|
||||
*beos_op = B_OP_COPY;
|
||||
return true;
|
||||
case CAIRO_OPERATOR_OVER:
|
||||
*beos_op = B_OP_ALPHA;
|
||||
return true;
|
||||
|
||||
case CAIRO_OPERATOR_SOURCE:
|
||||
*beos_op = B_OP_COPY;
|
||||
return true;
|
||||
case CAIRO_OPERATOR_OVER:
|
||||
*beos_op = B_OP_ALPHA;
|
||||
return true;
|
||||
|
||||
case CAIRO_OPERATOR_ADD:
|
||||
// Does not actually work
|
||||
case CAIRO_OPERATOR_ADD:
|
||||
// Does not actually work
|
||||
// XXX This is a fundamental compositing operator, it has to work!
|
||||
#if 1
|
||||
return false;
|
||||
return false;
|
||||
#else
|
||||
*beos_op = B_OP_ADD;
|
||||
return true;
|
||||
*beos_op = B_OP_ADD;
|
||||
return true;
|
||||
#endif
|
||||
|
||||
case CAIRO_OPERATOR_CLEAR:
|
||||
// Does not map to B_OP_ERASE - it replaces the dest with the low
|
||||
// color, instead of transparency; could be done by setting low
|
||||
// color appropriately.
|
||||
case CAIRO_OPERATOR_CLEAR:
|
||||
// Does not map to B_OP_ERASE - it replaces the dest with the low
|
||||
// color, instead of transparency; could be done by setting low
|
||||
// color appropriately.
|
||||
|
||||
case CAIRO_OPERATOR_IN:
|
||||
case CAIRO_OPERATOR_OUT:
|
||||
case CAIRO_OPERATOR_ATOP:
|
||||
case CAIRO_OPERATOR_IN:
|
||||
case CAIRO_OPERATOR_OUT:
|
||||
case CAIRO_OPERATOR_ATOP:
|
||||
|
||||
case CAIRO_OPERATOR_DEST:
|
||||
case CAIRO_OPERATOR_DEST_OVER:
|
||||
case CAIRO_OPERATOR_DEST_IN:
|
||||
case CAIRO_OPERATOR_DEST_OUT:
|
||||
case CAIRO_OPERATOR_DEST_ATOP:
|
||||
case CAIRO_OPERATOR_DEST:
|
||||
case CAIRO_OPERATOR_DEST_OVER:
|
||||
case CAIRO_OPERATOR_DEST_IN:
|
||||
case CAIRO_OPERATOR_DEST_OUT:
|
||||
case CAIRO_OPERATOR_DEST_ATOP:
|
||||
|
||||
case CAIRO_OPERATOR_XOR:
|
||||
case CAIRO_OPERATOR_SATURATE:
|
||||
case CAIRO_OPERATOR_XOR:
|
||||
case CAIRO_OPERATOR_SATURATE:
|
||||
|
||||
default:
|
||||
return false;
|
||||
};
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
|
|
@ -430,8 +464,6 @@ _cairo_beos_surface_create_similar (void *abstract_surface,
|
|||
int width,
|
||||
int height)
|
||||
{
|
||||
fprintf(stderr, "Creating similar\n");
|
||||
|
||||
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
|
||||
abstract_surface);
|
||||
|
||||
|
|
@ -444,9 +476,7 @@ _cairo_beos_surface_create_similar (void *abstract_surface,
|
|||
BBitmap* bmp;
|
||||
switch (content) {
|
||||
case CAIRO_CONTENT_ALPHA:
|
||||
// Can't support this natively
|
||||
return _cairo_image_surface_create_with_content(content, width,
|
||||
height);
|
||||
return NULL;
|
||||
case CAIRO_CONTENT_COLOR_ALPHA:
|
||||
bmp = new BBitmap(rect, B_RGBA32, true);
|
||||
break;
|
||||
|
|
@ -470,10 +500,9 @@ _cairo_beos_surface_create_similar (void *abstract_surface,
|
|||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
ASSERT_NOT_REACHED;
|
||||
return NULL;
|
||||
|
||||
};
|
||||
}
|
||||
BView* view = new BView(rect, "Cairo bitmap view", B_FOLLOW_ALL_SIDES, 0);
|
||||
bmp->AddChild(view);
|
||||
return _cairo_beos_surface_create_internal(view, bmp, true);
|
||||
|
|
@ -495,6 +524,8 @@ _cairo_beos_surface_finish (void *abstract_surface)
|
|||
surface->bitmap = NULL;
|
||||
}
|
||||
|
||||
cairo_region_destroy (surface->clip_region);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -503,7 +534,6 @@ _cairo_beos_surface_acquire_source_image (void *abstract_surfa
|
|||
cairo_image_surface_t **image_out,
|
||||
void **image_extra)
|
||||
{
|
||||
fprintf(stderr, "Getting source image\n");
|
||||
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
|
||||
abstract_surface);
|
||||
AutoLockView locker(surface->view);
|
||||
|
|
@ -514,9 +544,9 @@ _cairo_beos_surface_acquire_source_image (void *abstract_surfa
|
|||
surface->view->Sync();
|
||||
|
||||
if (surface->bitmap) {
|
||||
*image_out = _cairo_beos_bitmap_to_surface(surface->bitmap);
|
||||
if (!*image_out)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
*image_out = _cairo_beos_bitmap_to_surface (surface->bitmap);
|
||||
if (unlikely ((*image_out)->base.status))
|
||||
return (*image_out)->base.status;
|
||||
|
||||
*image_extra = NULL;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -526,10 +556,10 @@ _cairo_beos_surface_acquire_source_image (void *abstract_surfa
|
|||
if (_cairo_beos_view_to_bitmap(surface->view, &bmp) != OK)
|
||||
return CAIRO_STATUS_NO_MEMORY; /// XXX incorrect if the error was NOT_VISIBLE
|
||||
|
||||
*image_out = _cairo_beos_bitmap_to_surface(bmp);
|
||||
if (!*image_out) {
|
||||
*image_out = _cairo_beos_bitmap_to_surface (bmp);
|
||||
if (unlikely ((*image_out)->base.status)) {
|
||||
delete bmp;
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
return (*image_out)->base.status;
|
||||
}
|
||||
*image_extra = bmp;
|
||||
|
||||
|
|
@ -543,17 +573,17 @@ _cairo_beos_surface_release_source_image (void *abstract_surfac
|
|||
{
|
||||
cairo_surface_destroy (&image->base);
|
||||
|
||||
BBitmap* bmp = static_cast<BBitmap*>(image_extra);
|
||||
delete bmp;
|
||||
if (image_extra != NULL) {
|
||||
BBitmap* bmp = static_cast<BBitmap*>(image_extra);
|
||||
delete bmp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_beos_surface_acquire_dest_image (void *abstract_surface,
|
||||
cairo_rectangle_int16_t *interest_rect,
|
||||
cairo_rectangle_int_t *interest_rect,
|
||||
cairo_image_surface_t **image_out,
|
||||
cairo_rectangle_int16_t *image_rect,
|
||||
cairo_rectangle_int_t *image_rect,
|
||||
void **image_extra)
|
||||
{
|
||||
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
|
||||
|
|
@ -563,14 +593,14 @@ _cairo_beos_surface_acquire_dest_image (void *abstract_surface,
|
|||
if (!locker) {
|
||||
*image_out = NULL;
|
||||
*image_extra = NULL;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return (cairo_status_t) CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
if (surface->bitmap) {
|
||||
surface->view->Sync();
|
||||
*image_out = _cairo_beos_bitmap_to_surface(surface->bitmap);
|
||||
if (!*image_out)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
if (unlikely ((*image_out)->base.status))
|
||||
return (*image_out)->base.status;
|
||||
|
||||
image_rect->x = 0;
|
||||
image_rect->y = 0;
|
||||
|
|
@ -581,7 +611,7 @@ _cairo_beos_surface_acquire_dest_image (void *abstract_surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
BRect b_interest_rect(_cairo_rect_to_brect(interest_rect));
|
||||
BRect b_interest_rect (_cairo_rectangle_to_brect (interest_rect));
|
||||
|
||||
BRect rect;
|
||||
BBitmap* bitmap;
|
||||
|
|
@ -595,18 +625,11 @@ _cairo_beos_surface_acquire_dest_image (void *abstract_surface,
|
|||
if (status == ERROR)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
*image_rect = _brect_to_cairo_rect(rect);
|
||||
|
||||
#if 0
|
||||
fprintf(stderr, "Requested: (cairo rects) (%ix%i) dim (%u, %u) returning (%ix%i) dim (%u, %u)\n",
|
||||
interest_rect->x, interest_rect->y, interest_rect->width, interest_rect->height,
|
||||
image_rect->x, image_rect->y, image_rect->width, image_rect->height);
|
||||
#endif
|
||||
|
||||
*image_rect = _brect_to_cairo_rectangle(rect);
|
||||
*image_out = _cairo_beos_bitmap_to_surface(bitmap);
|
||||
delete bitmap;
|
||||
if (!*image_out)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
if (unlikely ((*image_out)->base.status))
|
||||
return (*image_out)->base.status;
|
||||
|
||||
*image_extra = NULL;
|
||||
|
||||
|
|
@ -616,13 +639,11 @@ _cairo_beos_surface_acquire_dest_image (void *abstract_surface,
|
|||
|
||||
static void
|
||||
_cairo_beos_surface_release_dest_image (void *abstract_surface,
|
||||
cairo_rectangle_int16_t *intersect_rect,
|
||||
cairo_rectangle_int_t *intersect_rect,
|
||||
cairo_image_surface_t *image,
|
||||
cairo_rectangle_int16_t *image_rect,
|
||||
cairo_rectangle_int_t *image_rect,
|
||||
void *image_extra)
|
||||
{
|
||||
fprintf(stderr, "Fallback drawing\n");
|
||||
|
||||
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
|
||||
abstract_surface);
|
||||
|
||||
|
|
@ -634,9 +655,9 @@ _cairo_beos_surface_release_dest_image (void *abstract_surface,
|
|||
surface->view->PushState();
|
||||
|
||||
surface->view->SetDrawingMode(B_OP_COPY);
|
||||
BRect rect(_cairo_rect_to_brect(image_rect));
|
||||
|
||||
surface->view->DrawBitmap(bitmap_to_draw, rect);
|
||||
surface->view->DrawBitmap (bitmap_to_draw,
|
||||
_cairo_rectangle_to_brect (image_rect));
|
||||
|
||||
surface->view->PopState();
|
||||
|
||||
|
|
@ -649,17 +670,19 @@ _cairo_beos_surface_composite (cairo_operator_t op,
|
|||
cairo_pattern_t *src,
|
||||
cairo_pattern_t *mask,
|
||||
void *dst,
|
||||
int src_x,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int mask_x,
|
||||
int mask_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height)
|
||||
unsigned int height,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
|
||||
dst);
|
||||
cairo_int_status_t status;
|
||||
AutoLockView locker(surface->view);
|
||||
if (!locker)
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
|
|
@ -684,6 +707,10 @@ _cairo_beos_surface_composite (cairo_operator_t op,
|
|||
if (!_cairo_matrix_is_integer_translation(&src->matrix, &itx, &ity))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_beos_surface_set_clip_region (surface, clip_region);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
BRect srcRect(src_x + itx,
|
||||
src_y + ity,
|
||||
src_x + itx + width - 1,
|
||||
|
|
@ -731,8 +758,6 @@ _cairo_beos_surface_composite (cairo_operator_t op,
|
|||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
fprintf(stderr, "Composite\n");
|
||||
|
||||
// Draw it on screen.
|
||||
surface->view->PushState();
|
||||
|
||||
|
|
@ -767,24 +792,17 @@ _cairo_beos_surface_composite (cairo_operator_t op,
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
_cairo_beos_surface_fill_rectangle (cairo_beos_surface_t *surface,
|
||||
cairo_rectangle_int16_t *rect)
|
||||
{
|
||||
BRect brect(_cairo_rect_to_brect(rect));
|
||||
surface->view->FillRect(brect);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_beos_surface_fill_rectangles (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_color_t *color,
|
||||
cairo_rectangle_int16_t *rects,
|
||||
int num_rects)
|
||||
cairo_rectangle_int_t *rects,
|
||||
int num_rects,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
fprintf(stderr, "Drawing %i rectangles\n", num_rects);
|
||||
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
|
||||
abstract_surface);
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (num_rects <= 0)
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
|
|
@ -797,6 +815,10 @@ _cairo_beos_surface_fill_rectangles (void *abstract_surface,
|
|||
if (!_cairo_op_to_be_op(op, &mode))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_beos_surface_set_clip_region (surface, clip_region);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
rgb_color be_color = _cairo_color_to_be_color(color);
|
||||
|
||||
if (mode == B_OP_ALPHA && be_color.alpha == 0xFF)
|
||||
|
|
@ -808,9 +830,9 @@ _cairo_beos_surface_fill_rectangles (void *abstract_surface,
|
|||
if (mode == B_OP_COPY && be_color.alpha != 0xFF &&
|
||||
(!surface->bitmap || surface->bitmap->ColorSpace() != B_RGBA32))
|
||||
{
|
||||
be_color.red = premultiply(be_color.red, be_color.alpha);
|
||||
be_color.green = premultiply(be_color.green, be_color.alpha);
|
||||
be_color.blue = premultiply(be_color.blue, be_color.alpha);
|
||||
be_color.red = color->red_short >> 8;
|
||||
be_color.green = color->green_short >> 8;
|
||||
be_color.blue = color->blue_short >> 8;
|
||||
}
|
||||
|
||||
surface->view->PushState();
|
||||
|
|
@ -822,65 +844,26 @@ _cairo_beos_surface_fill_rectangles (void *abstract_surface,
|
|||
else
|
||||
surface->view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
|
||||
|
||||
for (int i = 0; i < num_rects; ++i) {
|
||||
_cairo_beos_surface_fill_rectangle(surface, &rects[i]);
|
||||
}
|
||||
for (int i = 0; i < num_rects; ++i)
|
||||
surface->view->FillRect (_cairo_rectangle_to_brect (&rects[i]));
|
||||
|
||||
surface->view->PopState();
|
||||
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_beos_surface_set_clip_region (void *abstract_surface,
|
||||
pixman_region16_t *region)
|
||||
{
|
||||
fprintf(stderr, "Setting clip region\n");
|
||||
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
|
||||
abstract_surface);
|
||||
AutoLockView locker(surface->view);
|
||||
if (!locker)
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
|
||||
if (region == NULL) {
|
||||
// No clipping
|
||||
surface->view->ConstrainClippingRegion(NULL);
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
int count = pixman_region_num_rects(region);
|
||||
pixman_box16_t* rects = pixman_region_rects(region);
|
||||
BRegion bregion;
|
||||
for (int i = 0; i < count; ++i) {
|
||||
// Have to substract one, because for pixman, the second coordinate
|
||||
// lies outside the rectangle.
|
||||
bregion.Include(BRect(rects[i].x1, rects[i].y1, rects[i].x2 - 1, rects[i].y2 - 1));
|
||||
}
|
||||
surface->view->ConstrainClippingRegion(&bregion);
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_beos_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int16_t *rectangle)
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
cairo_beos_surface_t *surface = reinterpret_cast<cairo_beos_surface_t*>(
|
||||
abstract_surface);
|
||||
AutoLockView locker(surface->view);
|
||||
if (!locker)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
return FALSE;
|
||||
|
||||
BRect size = surface->view->Bounds();
|
||||
|
||||
*rectangle = _brect_to_cairo_rect(size);
|
||||
|
||||
// Make sure to have our upperleft edge as (0,0)
|
||||
rectangle->x = 0;
|
||||
rectangle->y = 0;
|
||||
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
*rectangle = _brect_to_cairo_rectangle (surface->view->Bounds());
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const struct _cairo_surface_backend cairo_beos_surface_backend = {
|
||||
|
|
@ -899,8 +882,6 @@ static const struct _cairo_surface_backend cairo_beos_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
_cairo_beos_surface_set_clip_region,
|
||||
NULL, /* intersect_clip_path */
|
||||
_cairo_beos_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
|
|
@ -938,7 +919,9 @@ _cairo_beos_surface_create_internal (BView* view,
|
|||
surface->bitmap = bmp;
|
||||
surface->owns_bitmap_view = owns_bitmap_view;
|
||||
|
||||
return (cairo_surface_t *) surface;
|
||||
surface->clip_region = NULL;
|
||||
|
||||
return &surface->base;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@
|
|||
|
||||
extern const cairo_private cairo_rectangle_list_t _cairo_rectangles_nil;
|
||||
|
||||
enum {
|
||||
CAIRO_CLIP_PATH_HAS_REGION = 0x1,
|
||||
CAIRO_CLIP_PATH_REGION_IS_UNSUPPORTED = 0x2
|
||||
};
|
||||
|
||||
struct _cairo_clip_path {
|
||||
cairo_reference_count_t ref_count;
|
||||
cairo_path_fixed_t path;
|
||||
|
|
@ -50,84 +55,74 @@ struct _cairo_clip_path {
|
|||
double tolerance;
|
||||
cairo_antialias_t antialias;
|
||||
cairo_clip_path_t *prev;
|
||||
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
/* partial caches */
|
||||
unsigned int flags;
|
||||
cairo_region_t *region;
|
||||
cairo_surface_t *surface;
|
||||
};
|
||||
|
||||
struct _cairo_clip {
|
||||
cairo_clip_mode_t mode;
|
||||
/* can be used as a cairo_hash_entry_t for live clips */
|
||||
cairo_clip_path_t *path;
|
||||
|
||||
cairo_bool_t all_clipped;
|
||||
|
||||
/*
|
||||
* Mask-based clipping for cases where the backend
|
||||
* clipping isn't sufficiently able.
|
||||
*
|
||||
* The rectangle here represents the
|
||||
* portion of the destination surface that this
|
||||
* clip surface maps to, it does not
|
||||
* represent the extents of the clip region or
|
||||
* clip paths
|
||||
*/
|
||||
cairo_surface_t *surface;
|
||||
cairo_rectangle_int_t surface_rect;
|
||||
/*
|
||||
* Surface clip serial number to store
|
||||
* in the surface when this clip is set
|
||||
*/
|
||||
unsigned int serial;
|
||||
/*
|
||||
* A clip region that can be placed in the surface
|
||||
*/
|
||||
cairo_region_t *region;
|
||||
/*
|
||||
* If the surface supports path clipping, we store the list of
|
||||
* clipping paths that has been set here as a linked list.
|
||||
*/
|
||||
cairo_clip_path_t *path;
|
||||
};
|
||||
|
||||
cairo_private void
|
||||
_cairo_clip_init (cairo_clip_t *clip, cairo_surface_t *target);
|
||||
_cairo_clip_init (cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_clip_init_rectangle (cairo_clip_t *clip,
|
||||
const cairo_rectangle_int_t *rect);
|
||||
|
||||
cairo_private void
|
||||
_cairo_clip_init_copy (cairo_clip_t *clip, cairo_clip_t *other);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_clip_init_deep_copy (cairo_clip_t *clip,
|
||||
cairo_clip_t *other,
|
||||
cairo_surface_t *target);
|
||||
_cairo_clip_init_copy_transformed (cairo_clip_t *clip,
|
||||
cairo_clip_t *other,
|
||||
const cairo_matrix_t *matrix);
|
||||
|
||||
cairo_private void
|
||||
_cairo_clip_reset (cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_clip_clip (cairo_clip_t *clip,
|
||||
cairo_path_fixed_t *path,
|
||||
const cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_surface_t *target);
|
||||
cairo_antialias_t antialias);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_clip_intersect_to_rectangle (cairo_clip_t *clip,
|
||||
cairo_rectangle_int_t *rectangle);
|
||||
_cairo_clip_apply_clip (cairo_clip_t *clip,
|
||||
const cairo_clip_t *other);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_clip_intersect_to_region (cairo_clip_t *clip,
|
||||
cairo_region_t *region);
|
||||
cairo_private const cairo_rectangle_int_t *
|
||||
_cairo_clip_get_extents (const cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_clip_combine_to_surface (cairo_clip_t *clip,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *dst,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
const cairo_rectangle_int_t *extents);
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_clip_get_surface (cairo_clip_t *clip, cairo_surface_t *dst);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_clip_get_region (cairo_clip_t *clip,
|
||||
cairo_region_t **region);
|
||||
|
||||
cairo_private void
|
||||
_cairo_clip_translate (cairo_clip_t *clip,
|
||||
cairo_fixed_t tx,
|
||||
cairo_fixed_t ty);
|
||||
|
||||
cairo_private void
|
||||
_cairo_clip_transform (cairo_clip_t *clip,
|
||||
const cairo_matrix_t *transform);
|
||||
|
||||
cairo_private void
|
||||
_cairo_clip_drop_cache (cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_rectangle_list_t*
|
||||
_cairo_clip_copy_rectangle_list (cairo_clip_t *clip, cairo_gstate_t *gstate);
|
||||
|
||||
|
|
|
|||
1452
src/cairo-clip.c
|
|
@ -75,6 +75,8 @@ cairo_debug_reset_static_data (void)
|
|||
|
||||
_cairo_pattern_reset_static_data ();
|
||||
|
||||
_cairo_clip_reset_static_data ();
|
||||
|
||||
CAIRO_MUTEX_FINALIZE ();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,14 +38,16 @@
|
|||
#include "cairoint.h"
|
||||
#include "cairo-directfb.h"
|
||||
|
||||
#include "cairo-clip-private.h"
|
||||
|
||||
#include <pixman.h>
|
||||
|
||||
#include <directfb.h>
|
||||
#include <direct/types.h>
|
||||
#include <direct/debug.h>
|
||||
#include <direct/memcpy.h>
|
||||
#include <direct/util.h>
|
||||
|
||||
#include "cairo-clip-private.h"
|
||||
|
||||
/*
|
||||
* Rectangle works fine.
|
||||
* Bugs 361377, 359553, 359243 in Gnome BTS are caused
|
||||
|
|
@ -68,6 +70,8 @@
|
|||
*/
|
||||
#define DFB_SHOW_GLYPHS 1
|
||||
|
||||
#define PIXMAN_invalid (pixman_format_code_t) 0
|
||||
|
||||
|
||||
D_DEBUG_DOMAIN (CairoDFB_Acquire, "CairoDFB/Acquire", "Cairo DirectFB Acquire");
|
||||
D_DEBUG_DOMAIN (CairoDFB_Clip, "CairoDFB/Clip", "Cairo DirectFB Clipping");
|
||||
|
|
@ -78,17 +82,15 @@ D_DEBUG_DOMAIN (CairoDFB_Surface, "CairoDFB/Surface", "Cairo DirectFB Surface");
|
|||
/*****************************************************************************/
|
||||
|
||||
typedef struct _cairo_directfb_surface {
|
||||
cairo_surface_t base;
|
||||
cairo_format_t format;
|
||||
cairo_content_t content;
|
||||
cairo_surface_t base;
|
||||
|
||||
IDirectFB *dfb;
|
||||
IDirectFBSurface *dfbsurface;
|
||||
IDirectFBSurface *tmpsurface;
|
||||
pixman_format_code_t pixman_format;
|
||||
cairo_bool_t supported_destination;
|
||||
|
||||
cairo_bool_t has_clip;
|
||||
DFBRegion *clips;
|
||||
int n_clips;
|
||||
IDirectFB *dfb;
|
||||
IDirectFBSurface *dfbsurface;
|
||||
IDirectFBSurface *tmpsurface;
|
||||
pixman_format_code_t tmpformat;
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
|
@ -119,13 +121,18 @@ static int _directfb_argb_font = 0;
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
#define RUN_CLIPPED(surface, clip, func) {\
|
||||
if ((surface)->has_clip) {\
|
||||
int k;\
|
||||
for (k = 0; k < (surface)->n_clips; k++) {\
|
||||
#define RUN_CLIPPED(surface, clip_region, clip, func) {\
|
||||
if ((clip_region) != NULL) {\
|
||||
int n_clips = cairo_region_num_rectangles (clip_region), n; \
|
||||
for (n = 0; n < n_clips; n++) {\
|
||||
if (clip) {\
|
||||
DFBRegion reg = (surface)->clips[k];\
|
||||
DFBRegion *cli = (clip);\
|
||||
DFBRegion reg, *cli = (clip); \
|
||||
cairo_rectangle_int_t rect; \
|
||||
cairo_region_get_rectangle (clip_region, n, &rect); \
|
||||
reg.x1 = rect.x; \
|
||||
reg.y1 = rect.y; \
|
||||
reg.x2 = rect.x + rect.width - 1; \
|
||||
reg.y2 = rect.y + rect.height - 1; \
|
||||
if (reg.x2 < cli->x1 || reg.y2 < cli->y1 ||\
|
||||
reg.x1 > cli->x2 || reg.y1 > cli->y2)\
|
||||
continue;\
|
||||
|
|
@ -139,8 +146,14 @@ static int _directfb_argb_font = 0;
|
|||
reg.y2 = cli->y2;\
|
||||
(surface)->dfbsurface->SetClip ((surface)->dfbsurface, ®);\
|
||||
} else {\
|
||||
(surface)->dfbsurface->SetClip ((surface)->dfbsurface,\
|
||||
&(surface)->clips[k]);\
|
||||
DFBRegion reg; \
|
||||
cairo_rectangle_int_t rect; \
|
||||
cairo_region_get_rectangle (clip_region, n, &rect); \
|
||||
reg.x1 = rect.x; \
|
||||
reg.y1 = rect.y; \
|
||||
reg.x2 = rect.x + rect.width - 1; \
|
||||
reg.y2 = rect.y + rect.height - 1; \
|
||||
(surface)->dfbsurface->SetClip ((surface)->dfbsurface, ®); \
|
||||
}\
|
||||
func;\
|
||||
}\
|
||||
|
|
@ -150,19 +163,19 @@ static int _directfb_argb_font = 0;
|
|||
}\
|
||||
}
|
||||
|
||||
#define TRANSFORM_POINT2X(m, x, y, ret_x, ret_y) {\
|
||||
double _x = (x);\
|
||||
double _y = (y);\
|
||||
(ret_x) = (_x * (m).xx + (m).x0);\
|
||||
(ret_y) = (_y * (m).yy + (m).y0);\
|
||||
}
|
||||
#define TRANSFORM_POINT2X(m, x, y, ret_x, ret_y) do { \
|
||||
double _x = (x); \
|
||||
double _y = (y); \
|
||||
(ret_x) = (_x * (m).xx + (m).x0); \
|
||||
(ret_y) = (_y * (m).yy + (m).y0); \
|
||||
} while (0)
|
||||
|
||||
#define TRANSFORM_POINT3X(m, x, y, ret_x, ret_y) {\
|
||||
double _x = (x);\
|
||||
double _y = (y);\
|
||||
(ret_x) = (_x * (m).xx + _y * (m).xy + (m).x0);\
|
||||
(ret_y) = (_x * (m).yx + _y * (m).yy + (m).y0);\
|
||||
}
|
||||
#define TRANSFORM_POINT3X(m, x, y, ret_x, ret_y) do { \
|
||||
double _x = (x); \
|
||||
double _y = (y); \
|
||||
(ret_x) = (_x * (m).xx + _y * (m).xy + (m).x0); \
|
||||
(ret_y) = (_x * (m).yx + _y * (m).yy + (m).y0); \
|
||||
} while (0)
|
||||
|
||||
/* XXX: A1 has a different bits ordering in cairo.
|
||||
* Probably we should drop it.
|
||||
|
|
@ -200,23 +213,65 @@ _cairo_to_directfb_format (cairo_format_t format)
|
|||
return -1;
|
||||
}
|
||||
|
||||
static inline cairo_format_t
|
||||
_directfb_to_cairo_format (DFBSurfacePixelFormat format)
|
||||
static inline pixman_format_code_t
|
||||
_directfb_to_pixman_format (DFBSurfacePixelFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case DSPF_RGB32:
|
||||
return CAIRO_FORMAT_RGB24;
|
||||
case DSPF_ARGB:
|
||||
return CAIRO_FORMAT_ARGB32;
|
||||
case DSPF_A8:
|
||||
return CAIRO_FORMAT_A8;
|
||||
case DSPF_A1:
|
||||
return CAIRO_FORMAT_A1;
|
||||
default:
|
||||
break;
|
||||
case DSPF_UNKNOWN: return PIXMAN_invalid;
|
||||
case DSPF_ARGB1555: return PIXMAN_a1r5g5b5;
|
||||
case DSPF_RGB16: return PIXMAN_r5g6b5;
|
||||
case DSPF_RGB24: return PIXMAN_r8g8b8;
|
||||
case DSPF_RGB32: return PIXMAN_x8r8g8b8;
|
||||
case DSPF_ARGB: return PIXMAN_a8r8g8b8;
|
||||
case DSPF_A8: return PIXMAN_a8;
|
||||
case DSPF_YUY2: return PIXMAN_yuy2;
|
||||
case DSPF_RGB332: return PIXMAN_r3g3b2;
|
||||
case DSPF_UYVY: return PIXMAN_invalid;
|
||||
case DSPF_I420: return PIXMAN_invalid;
|
||||
case DSPF_YV12: return PIXMAN_yv12;
|
||||
case DSPF_LUT8: return PIXMAN_invalid;
|
||||
case DSPF_ALUT44: return PIXMAN_invalid;
|
||||
case DSPF_AiRGB: return PIXMAN_invalid;
|
||||
case DSPF_A1: return PIXMAN_a1; /* bit reversed, oops */
|
||||
case DSPF_NV12: return PIXMAN_invalid;
|
||||
case DSPF_NV16: return PIXMAN_invalid;
|
||||
case DSPF_ARGB2554: return PIXMAN_invalid;
|
||||
case DSPF_ARGB4444: return PIXMAN_a4r4g4b4;
|
||||
case DSPF_NV21: return PIXMAN_invalid;
|
||||
case DSPF_AYUV: return PIXMAN_invalid;
|
||||
case DSPF_A4: return PIXMAN_a4;
|
||||
case DSPF_ARGB1666: return PIXMAN_invalid;
|
||||
case DSPF_ARGB6666: return PIXMAN_invalid;
|
||||
case DSPF_RGB18: return PIXMAN_invalid;
|
||||
case DSPF_LUT2: return PIXMAN_invalid;
|
||||
case DSPF_RGB444: return PIXMAN_x4r4g4b4;
|
||||
case DSPF_RGB555: return PIXMAN_x1r5g5b5;
|
||||
case DSPF_BGR555: return PIXMAN_x1b5g5r5;
|
||||
}
|
||||
return PIXMAN_invalid;
|
||||
}
|
||||
|
||||
return -1;
|
||||
static inline DFBSurfacePixelFormat
|
||||
_directfb_from_pixman_format (pixman_format_code_t format)
|
||||
{
|
||||
switch ((int) format) {
|
||||
case PIXMAN_a1r5g5b5: return DSPF_ARGB1555;
|
||||
case PIXMAN_r5g6b5: return DSPF_RGB16;
|
||||
case PIXMAN_r8g8b8: return DSPF_RGB24;
|
||||
case PIXMAN_x8r8g8b8: return DSPF_RGB32;
|
||||
case PIXMAN_a8r8g8b8: return DSPF_ARGB;
|
||||
case PIXMAN_a8: return DSPF_A8;
|
||||
case PIXMAN_yuy2: return DSPF_YUY2;
|
||||
case PIXMAN_r3g3b2: return DSPF_RGB332;
|
||||
case PIXMAN_yv12: return DSPF_YV12;
|
||||
case PIXMAN_a1: return DSPF_A1; /* bit reversed, oops */
|
||||
case PIXMAN_a4r4g4b4: return DSPF_ARGB4444;
|
||||
case PIXMAN_a4: return DSPF_A4;
|
||||
case PIXMAN_x4r4g4b4: return DSPF_RGB444;
|
||||
case PIXMAN_x1r5g5b5: return DSPF_RGB555;
|
||||
case PIXMAN_x1b5g5r5: return DSPF_BGR555;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
|
|
@ -350,17 +405,14 @@ _directfb_acquire_surface (cairo_directfb_surface_t *surface,
|
|||
IDirectFBSurface *buffer = NULL;
|
||||
DFBRectangle source_rect;
|
||||
cairo_surface_t *image;
|
||||
cairo_format_t cairo_format;
|
||||
pixman_image_t *pixman_image;
|
||||
pixman_format_code_t pixman_format;
|
||||
cairo_status_t status;
|
||||
void *data;
|
||||
int pitch;
|
||||
|
||||
if (surface->format == (cairo_format_t) -1 ||
|
||||
(lock_flags & DSLF_WRITE && surface->has_clip))
|
||||
{
|
||||
DFBSurfaceCapabilities caps;
|
||||
|
||||
if (intrest_rec) {
|
||||
if (surface->pixman_format == PIXMAN_invalid) {
|
||||
if (intrest_rec != NULL) {
|
||||
source_rect.x = intrest_rec->x;
|
||||
source_rect.y = intrest_rec->y;
|
||||
source_rect.w = intrest_rec->width;
|
||||
|
|
@ -372,30 +424,38 @@ _directfb_acquire_surface (cairo_directfb_surface_t *surface,
|
|||
&source_rect.w, &source_rect.h);
|
||||
}
|
||||
|
||||
if (surface->tmpsurface) {
|
||||
if (surface->tmpsurface != NULL) {
|
||||
int w, h;
|
||||
|
||||
surface->tmpsurface->GetSize (surface->tmpsurface, &w, &h);
|
||||
if (w < source_rect.w || h < source_rect.h) {
|
||||
surface->tmpsurface->Release (surface->tmpsurface);
|
||||
surface->tmpsurface = NULL;
|
||||
surface->tmpformat = PIXMAN_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
cairo_format = _cairo_format_from_content (surface->content);
|
||||
if (!surface->tmpsurface) {
|
||||
if (surface->tmpsurface == NULL) {
|
||||
DFBSurfacePixelFormat format;
|
||||
|
||||
D_DEBUG_AT (CairoDFB_Acquire, "Allocating buffer for surface %p.\n", surface);
|
||||
|
||||
format = _cairo_to_directfb_format (_cairo_format_from_content (surface->base.content));
|
||||
status =
|
||||
_directfb_buffer_surface_create (surface->dfb,
|
||||
_cairo_to_directfb_format (cairo_format),
|
||||
_directfb_buffer_surface_create (surface->dfb, format,
|
||||
source_rect.w, source_rect.h,
|
||||
&surface->tmpsurface);
|
||||
if (status)
|
||||
if (unlikely (status))
|
||||
goto ERROR;
|
||||
|
||||
surface->tmpformat = _directfb_to_pixman_format (format);
|
||||
}
|
||||
buffer = surface->tmpsurface;
|
||||
pixman_format = surface->tmpformat;
|
||||
|
||||
|
||||
/* surface->dfbsurface->GetCapabilities (surface->dfbsurface, &caps);
|
||||
DFBSurfaceCapabilities caps;
|
||||
if (caps & DSCAPS_FLIPPING) {
|
||||
DFBRegion region = { .x1 = source_rect.x, .y1 = source_rect.y,
|
||||
.x2 = source_rect.x + source_rect.w - 1,
|
||||
|
|
@ -406,7 +466,7 @@ _directfb_acquire_surface (cairo_directfb_surface_t *surface,
|
|||
} else {
|
||||
/*might be a subsurface get the offset*/
|
||||
surface->dfbsurface->GetVisibleRectangle (surface->dfbsurface, &source_rect);
|
||||
cairo_format = surface->format;
|
||||
pixman_format = surface->pixman_format;
|
||||
buffer = surface->dfbsurface;
|
||||
}
|
||||
|
||||
|
|
@ -416,9 +476,16 @@ _directfb_acquire_surface (cairo_directfb_surface_t *surface,
|
|||
goto ERROR;
|
||||
}
|
||||
|
||||
image = cairo_image_surface_create_for_data (data, cairo_format,
|
||||
source_rect.w, source_rect.h,
|
||||
pitch);
|
||||
pixman_image = pixman_image_create_bits (pixman_format,
|
||||
source_rect.w, source_rect.h,
|
||||
data, pitch);
|
||||
if (pixman_image == NULL) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
image = _cairo_image_surface_create_for_pixman_image (pixman_image,
|
||||
pixman_format);
|
||||
status = image->status;
|
||||
if (status)
|
||||
goto ERROR;
|
||||
|
|
@ -451,37 +518,27 @@ ERROR:
|
|||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_directfb_surface_create_similar (void *abstract_src,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height)
|
||||
_cairo_directfb_surface_create_internal (IDirectFB *dfb,
|
||||
DFBSurfacePixelFormat format,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_directfb_surface_t *source = abstract_src;
|
||||
cairo_directfb_surface_t *surface;
|
||||
cairo_format_t format;
|
||||
cairo_status_t status;
|
||||
|
||||
D_DEBUG_AT (CairoDFB_Surface,
|
||||
"%s( src=%p, content=0x%x, width=%d, height=%d).\n",
|
||||
__FUNCTION__, source, content, width, height);
|
||||
|
||||
width = (width <= 0) ? 1 : width;
|
||||
height = (height<= 0) ? 1 : height;
|
||||
|
||||
format = _cairo_format_from_content (content);
|
||||
surface = calloc (1, sizeof (cairo_directfb_surface_t));
|
||||
if (unlikely (surface == NULL))
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
||||
surface->dfb = source->dfb;
|
||||
surface->dfb = dfb;
|
||||
|
||||
if (width < 8 || height < 8) {
|
||||
IDirectFBSurface *tmp;
|
||||
DFBRectangle rect = { .x=0, .y=0, .w=width, .h=height };
|
||||
|
||||
/* Some cards (e.g. Matrox) don't support surfaces smaller than 8x8 */
|
||||
status = _directfb_buffer_surface_create (surface->dfb,
|
||||
_cairo_to_directfb_format (format),
|
||||
status = _directfb_buffer_surface_create (dfb, format,
|
||||
MAX (width, 8), MAX (height, 8),
|
||||
&tmp);
|
||||
if (status) {
|
||||
|
|
@ -492,11 +549,9 @@ _cairo_directfb_surface_create_similar (void *abstract_src,
|
|||
tmp->GetSubSurface (tmp, &rect, &surface->dfbsurface);
|
||||
tmp->Release (tmp);
|
||||
} else {
|
||||
status =
|
||||
_directfb_buffer_surface_create (surface->dfb,
|
||||
_cairo_to_directfb_format (format),
|
||||
width, height,
|
||||
&surface->dfbsurface);
|
||||
status = _directfb_buffer_surface_create (dfb, format,
|
||||
width, height,
|
||||
&surface->dfbsurface);
|
||||
if (status) {
|
||||
free (surface);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
|
|
@ -506,8 +561,9 @@ _cairo_directfb_surface_create_similar (void *abstract_src,
|
|||
_cairo_surface_init (&surface->base,
|
||||
&_cairo_directfb_surface_backend,
|
||||
content);
|
||||
surface->format = format;
|
||||
surface->content = content;
|
||||
surface->pixman_format = _directfb_to_pixman_format (format);
|
||||
surface->supported_destination = pixman_format_supported_destination (surface->pixman_format);
|
||||
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
surface->local = TRUE;
|
||||
|
|
@ -516,6 +572,27 @@ _cairo_directfb_surface_create_similar (void *abstract_src,
|
|||
return &surface->base;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_directfb_surface_create_similar (void *abstract_src,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_directfb_surface_t *other = abstract_src;
|
||||
DFBSurfacePixelFormat format;
|
||||
|
||||
D_DEBUG_AT (CairoDFB_Surface,
|
||||
"%s( src=%p, content=0x%x, width=%d, height=%d).\n",
|
||||
__FUNCTION__, other, content, width, height);
|
||||
|
||||
width = (width <= 0) ? 1 : width;
|
||||
height = (height<= 0) ? 1 : height;
|
||||
|
||||
format = _cairo_to_directfb_format (_cairo_format_from_content (content));
|
||||
return _cairo_directfb_surface_create_internal (other->dfb, format,
|
||||
content, width, height);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_directfb_surface_finish (void *data)
|
||||
{
|
||||
|
|
@ -523,12 +600,6 @@ _cairo_directfb_surface_finish (void *data)
|
|||
|
||||
D_DEBUG_AT (CairoDFB_Surface, "%s( surface=%p ).\n", __FUNCTION__, surface);
|
||||
|
||||
if (surface->clips) {
|
||||
free (surface->clips);
|
||||
surface->clips = NULL;
|
||||
surface->n_clips = 0;
|
||||
}
|
||||
|
||||
if (surface->tmpsurface) {
|
||||
surface->tmpsurface->Release (surface->tmpsurface);
|
||||
surface->tmpsurface = NULL;
|
||||
|
|
@ -564,11 +635,10 @@ _cairo_directfb_surface_release_source_image (void *abstract_su
|
|||
cairo_image_surface_t *image,
|
||||
void *image_extra)
|
||||
{
|
||||
cairo_directfb_surface_t *surface = abstract_surface;
|
||||
IDirectFBSurface *buffer = image_extra;
|
||||
|
||||
D_DEBUG_AT (CairoDFB_Acquire,
|
||||
"%s( surface=%p ).\n", __FUNCTION__, surface);
|
||||
"%s( release=%p ).\n", __FUNCTION__, abstract_surface);
|
||||
|
||||
buffer->Unlock (buffer);
|
||||
|
||||
|
|
@ -620,10 +690,10 @@ _cairo_directfb_surface_release_dest_image (void *abstract_surf
|
|||
.y2 = interest_rect->y + interest_rect->height - 1
|
||||
};
|
||||
surface->dfbsurface->SetBlittingFlags (surface->dfbsurface, DSBLIT_NOFX);
|
||||
RUN_CLIPPED (surface, ®ion,
|
||||
surface->dfbsurface->Blit (surface->dfbsurface,
|
||||
buffer, NULL,
|
||||
image_rect->x, image_rect->y));
|
||||
surface->dfbsurface->SetClip (surface->dfbsurface, ®ion);
|
||||
surface->dfbsurface->Blit (surface->dfbsurface,
|
||||
buffer, NULL,
|
||||
image_rect->x, image_rect->y);
|
||||
}
|
||||
|
||||
cairo_surface_destroy (&image->base);
|
||||
|
|
@ -655,56 +725,51 @@ _cairo_directfb_surface_clone_similar (void *abstract_surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
} else if (_cairo_surface_is_image (src)) {
|
||||
cairo_image_surface_t *image_src = (cairo_image_surface_t *) src;
|
||||
unsigned char *dst, *src = image_src->data;
|
||||
int pitch;
|
||||
int i, j;
|
||||
DFBSurfacePixelFormat format;
|
||||
DFBResult ret;
|
||||
pixman_image_t *pixman_image;
|
||||
void *data;
|
||||
int pitch;
|
||||
|
||||
format = _directfb_from_pixman_format (image_src->pixman_format);
|
||||
if (format == 0)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
clone = (cairo_directfb_surface_t *)
|
||||
_cairo_directfb_surface_create_similar (surface,
|
||||
_cairo_content_from_format (image_src->format),
|
||||
width, height);
|
||||
if (clone == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (clone->base.status)
|
||||
_cairo_directfb_surface_create_internal (surface->dfb, format,
|
||||
image_src->base.content,
|
||||
width, height);
|
||||
if (unlikely (clone->base.status))
|
||||
return clone->base.status;
|
||||
|
||||
ret = clone->dfbsurface->Lock (clone->dfbsurface,
|
||||
DSLF_WRITE, (void *)&dst, &pitch);
|
||||
DSLF_WRITE, (void *)&data, &pitch);
|
||||
if (ret) {
|
||||
DirectFBError ("IDirectFBSurface::Lock()", ret);
|
||||
cairo_surface_destroy (&clone->base);
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
src += image_src->stride * src_y;
|
||||
if (image_src->format == CAIRO_FORMAT_A1) {
|
||||
/* A1 -> A8 */
|
||||
dst -= src_x;
|
||||
for (i = 0; i < height; i++) {
|
||||
for (j = src_x; j < src_x + width; j++)
|
||||
dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0x00;
|
||||
dst += pitch;
|
||||
src += image_src->stride;
|
||||
}
|
||||
} else {
|
||||
int len;
|
||||
|
||||
if (image_src->format == CAIRO_FORMAT_A8) {
|
||||
src += src_x;
|
||||
len = width;
|
||||
} else {
|
||||
src += src_x * 4;
|
||||
len = width * 4;
|
||||
}
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
direct_memcpy (dst, src, len);
|
||||
dst += pitch;
|
||||
src += image_src->stride;
|
||||
}
|
||||
pixman_image = pixman_image_create_bits (clone->pixman_format,
|
||||
width, height,
|
||||
data, pitch);
|
||||
if (unlikely (pixman_image == NULL)) {
|
||||
DirectFBError ("IDirectFBSurface::Lock()", ret);
|
||||
cairo_surface_destroy (&clone->base);
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
pixman_image_composite (PIXMAN_OP_SRC,
|
||||
image_src->pixman_image,
|
||||
NULL,
|
||||
pixman_image,
|
||||
src_x, src_y,
|
||||
0, 0,
|
||||
0, 0,
|
||||
width, height);
|
||||
|
||||
pixman_image_unref (pixman_image);
|
||||
|
||||
clone->dfbsurface->Unlock (clone->dfbsurface);
|
||||
|
||||
*clone_offset_x = src_x;
|
||||
|
|
@ -745,8 +810,6 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst,
|
|||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (mask_pattern) {
|
||||
cairo_solid_pattern_t *pattern;
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
|
||||
const cairo_pattern_t *tmp;
|
||||
|
|
@ -794,7 +857,7 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst,
|
|||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (src->content == CAIRO_CONTENT_COLOR) {
|
||||
if ((src->base.content & CAIRO_CONTENT_ALPHA) == 0) {
|
||||
if (sblend == DSBF_SRCALPHA)
|
||||
sblend = DSBF_ONE;
|
||||
else if (sblend == DSBF_INVSRCALPHA)
|
||||
|
|
@ -806,7 +869,7 @@ _directfb_prepare_composite (cairo_directfb_surface_t *dst,
|
|||
dblend = DSBF_ZERO;
|
||||
}
|
||||
|
||||
if (dst->content == CAIRO_CONTENT_COLOR) {
|
||||
if ((dst->base.content & CAIRO_CONTENT_ALPHA) == 0) {
|
||||
if (sblend == DSBF_DESTALPHA)
|
||||
sblend = DSBF_ONE;
|
||||
else if (sblend == DSBF_INVDESTALPHA)
|
||||
|
|
@ -913,7 +976,8 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
|
|||
int mask_x, int mask_y,
|
||||
int dst_x, int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height)
|
||||
unsigned int height,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_directfb_surface_t *dst = abstract_dst;
|
||||
cairo_directfb_surface_t *src;
|
||||
|
|
@ -930,6 +994,9 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
|
|||
__FUNCTION__, op, src_pattern, mask_pattern, dst,
|
||||
src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height);
|
||||
|
||||
if (! dst->supported_destination)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _directfb_prepare_composite (dst, src_pattern, mask_pattern, op,
|
||||
&src_x, &src_y, &mask_x, &mask_y,
|
||||
width, height, &src, &src_attr);
|
||||
|
|
@ -956,7 +1023,7 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
|
|||
src_x += src_attr.x_offset;
|
||||
src_y += src_attr.y_offset;
|
||||
|
||||
switch (accel) {
|
||||
switch ((int) accel) {
|
||||
case DFXL_BLIT:
|
||||
{
|
||||
DFBRectangle sr;
|
||||
|
|
@ -974,11 +1041,10 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
|
|||
if (src_attr.extend == CAIRO_EXTEND_NONE) {
|
||||
D_DEBUG_AT (CairoDFB_Render, "Running Blit().\n");
|
||||
|
||||
RUN_CLIPPED (dst, NULL,
|
||||
RUN_CLIPPED (dst, clip_region, NULL,
|
||||
dst->dfbsurface->Blit (dst->dfbsurface,
|
||||
src->dfbsurface,
|
||||
&sr,
|
||||
dst_x, dst_y));
|
||||
&sr, dst_x, dst_y));
|
||||
} else if (src_attr.extend == CAIRO_EXTEND_REPEAT) {
|
||||
DFBRegion clip;
|
||||
|
||||
|
|
@ -989,11 +1055,10 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
|
|||
|
||||
D_DEBUG_AT (CairoDFB_Render, "Running TileBlit().\n");
|
||||
|
||||
RUN_CLIPPED (dst, &clip,
|
||||
RUN_CLIPPED (dst, clip_region, &clip,
|
||||
dst->dfbsurface->TileBlit (dst->dfbsurface,
|
||||
src->dfbsurface,
|
||||
&sr,
|
||||
dst_x, dst_y));
|
||||
&sr, dst_x, dst_y));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -1020,9 +1085,10 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
|
|||
|
||||
D_DEBUG_AT (CairoDFB_Render, "Running StretchBlit().\n");
|
||||
|
||||
RUN_CLIPPED (dst, NULL,
|
||||
RUN_CLIPPED (dst, clip_region, NULL,
|
||||
dst->dfbsurface->StretchBlit (dst->dfbsurface,
|
||||
src->dfbsurface, &sr, &dr));
|
||||
src->dfbsurface,
|
||||
&sr, &dr));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1044,29 +1110,25 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
|
|||
|
||||
src->dfbsurface->GetSize (src->dfbsurface, &w, &h);
|
||||
|
||||
TRANSFORM_POINT3X (src_attr.matrix,
|
||||
x1, y1, v[0].x, v[0].y);
|
||||
TRANSFORM_POINT3X (src_attr.matrix, x1, y1, v[0].x, v[0].y);
|
||||
v[0].z = 0;
|
||||
v[0].w = 1;
|
||||
v[0].s = x1 / w;
|
||||
v[0].t = y1 / h;
|
||||
|
||||
TRANSFORM_POINT3X (src_attr.matrix,
|
||||
x2, y1, v[1].x, v[1].y);
|
||||
TRANSFORM_POINT3X (src_attr.matrix, x2, y1, v[1].x, v[1].y);
|
||||
v[1].z = 0;
|
||||
v[1].w = 1;
|
||||
v[1].s = x2 / w;
|
||||
v[1].t = y1 / h;
|
||||
|
||||
TRANSFORM_POINT3X (src_attr.matrix,
|
||||
x2, y2, v[2].x, v[2].y);
|
||||
TRANSFORM_POINT3X (src_attr.matrix, x2, y2, v[2].x, v[2].y);
|
||||
v[2].z = 0;
|
||||
v[2].w = 1;
|
||||
v[2].s = x2 / w;
|
||||
v[2].t = y2 / h;
|
||||
|
||||
TRANSFORM_POINT3X (src_attr.matrix,
|
||||
x1, y2, v[3].x, v[3].y);
|
||||
TRANSFORM_POINT3X (src_attr.matrix, x1, y2, v[3].x, v[3].y);
|
||||
v[3].z = 0;
|
||||
v[3].w = 1;
|
||||
v[3].s = x1 / w;
|
||||
|
|
@ -1079,9 +1141,11 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
|
|||
|
||||
D_DEBUG_AT (CairoDFB_Render, "Running TextureTriangles().\n");
|
||||
|
||||
RUN_CLIPPED (dst, &clip,
|
||||
RUN_CLIPPED (dst, clip_region, &clip,
|
||||
dst->dfbsurface->TextureTriangles (dst->dfbsurface,
|
||||
src->dfbsurface, v, NULL, 4, DTTF_FAN));
|
||||
src->dfbsurface,
|
||||
v, NULL,
|
||||
4, DTTF_FAN));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1092,7 +1156,7 @@ _cairo_directfb_surface_composite (cairo_operator_t op,
|
|||
|
||||
_directfb_finish_composite (dst, src_pattern, &src->base, &src_attr);
|
||||
|
||||
return status;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
#endif /* DFB_COMPOSITE */
|
||||
|
||||
|
|
@ -1115,8 +1179,8 @@ _cairo_directfb_surface_fill_rectangles (void *abstract_surface
|
|||
"%s( dst=%p, op=%d, color=%p, rects=%p, n_rects=%d ).\n",
|
||||
__FUNCTION__, dst, op, color, rects, n_rects);
|
||||
|
||||
if (! _cairo_operator_bounded_by_source (op))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (! dst->supported_destination)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (! _directfb_get_operator (op, &sblend, &dblend))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
|
@ -1132,7 +1196,7 @@ _cairo_directfb_surface_fill_rectangles (void *abstract_surface
|
|||
else if (dblend == DSBF_INVSRCALPHA)
|
||||
dblend = DSBF_ZERO;
|
||||
}
|
||||
if (dst->content == CAIRO_CONTENT_COLOR) {
|
||||
if ((dst->base.content & CAIRO_CONTENT_ALPHA) == 0) {
|
||||
if (sblend == DSBF_DESTALPHA)
|
||||
sblend = DSBF_ONE;
|
||||
else if (sblend == DSBF_INVDESTALPHA)
|
||||
|
|
@ -1164,7 +1228,7 @@ _cairo_directfb_surface_fill_rectangles (void *abstract_surface
|
|||
r[i].h = rects[i].height;
|
||||
}
|
||||
|
||||
RUN_CLIPPED (dst, NULL,
|
||||
RUN_CLIPPED (dst, NULL, NULL,
|
||||
dst->dfbsurface->FillRectangles (dst->dfbsurface, r, n_rects));
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -1182,7 +1246,8 @@ _cairo_directfb_surface_composite_trapezoids (cairo_operator_t op,
|
|||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_trapezoid_t *traps,
|
||||
int num_traps)
|
||||
int num_traps,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_directfb_surface_t *dst = abstract_dst;
|
||||
cairo_directfb_surface_t *src;
|
||||
|
|
@ -1197,6 +1262,9 @@ _cairo_directfb_surface_composite_trapezoids (cairo_operator_t op,
|
|||
__FUNCTION__, op, pattern, dst, antialias,
|
||||
src_x, src_y, dst_x, dst_y, width, height, traps, num_traps);
|
||||
|
||||
if (! dst->supported_destination)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (antialias != CAIRO_ANTIALIAS_NONE)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
|
|
@ -1291,7 +1359,7 @@ _cairo_directfb_surface_composite_trapezoids (cairo_operator_t op,
|
|||
|
||||
D_DEBUG_AT (CairoDFB_Render, "Running TextureTriangles().\n");
|
||||
|
||||
RUN_CLIPPED (dst, NULL,
|
||||
RUN_CLIPPED (dst, clip_region, NULL,
|
||||
dst->dfbsurface->TextureTriangles (dst->dfbsurface,
|
||||
src->dfbsurface,
|
||||
vertex, NULL, n,
|
||||
|
|
@ -1306,64 +1374,7 @@ _cairo_directfb_surface_composite_trapezoids (cairo_operator_t op,
|
|||
}
|
||||
#endif /* DFB_COMPOSITE_TRAPEZOIDS */
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_directfb_surface_set_clip_region (void *abstract_surface,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
cairo_directfb_surface_t *surface = abstract_surface;
|
||||
|
||||
D_DEBUG_AT (CairoDFB_Clip,
|
||||
"%s( surface=%p, region=%p ).\n",
|
||||
__FUNCTION__, surface, region);
|
||||
|
||||
if (region) {
|
||||
int n_rects;
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
|
||||
surface->has_clip = TRUE;
|
||||
|
||||
n_rects = cairo_region_num_rectangles (region);
|
||||
|
||||
if (n_rects == 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (surface->n_clips != n_rects) {
|
||||
if (surface->clips)
|
||||
free (surface->clips);
|
||||
|
||||
surface->clips = _cairo_malloc_ab (n_rects, sizeof (DFBRegion));
|
||||
if (!surface->clips) {
|
||||
surface->n_clips = 0;
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
surface->n_clips = n_rects;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_rects; i++) {
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
|
||||
surface->clips[i].x1 = rect.x;
|
||||
surface->clips[i].y1 = rect.y;
|
||||
surface->clips[i].x2 = rect.x + rect.width - 1;
|
||||
surface->clips[i].y2 = rect.y + rect.height - 1;
|
||||
}
|
||||
} else {
|
||||
surface->has_clip = FALSE;
|
||||
if (surface->clips) {
|
||||
free (surface->clips);
|
||||
surface->clips = NULL;
|
||||
surface->n_clips = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_directfb_abstract_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
|
|
@ -1383,7 +1394,7 @@ _cairo_directfb_abstract_surface_get_extents (void *abstract_su
|
|||
rectangle->width = surface->width;
|
||||
rectangle->height = surface->height;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if DFB_SHOW_GLYPHS
|
||||
|
|
@ -1422,6 +1433,7 @@ _directfb_destroy_font_cache (cairo_directfb_font_cache_t *cache)
|
|||
free (cache);
|
||||
}
|
||||
|
||||
/* XXX hook into rtree font cache from drm */
|
||||
static cairo_status_t
|
||||
_directfb_acquire_font_cache (cairo_directfb_surface_t *surface,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
|
|
@ -1473,6 +1485,7 @@ _directfb_acquire_font_cache (cairo_directfb_surface_t *surface,
|
|||
case CAIRO_FORMAT_A8:
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
break;
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
default:
|
||||
D_DEBUG_AT (CairoDFB_Font,
|
||||
" -> Unsupported font format %d!\n", img->format);
|
||||
|
|
@ -1705,8 +1718,8 @@ _cairo_directfb_surface_show_glyphs (void *abstract_dst,
|
|||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
int *remaining_glyphs,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs)
|
||||
{
|
||||
cairo_directfb_surface_t *dst = abstract_dst;
|
||||
cairo_directfb_font_cache_t *cache;
|
||||
|
|
@ -1718,28 +1731,29 @@ _cairo_directfb_surface_show_glyphs (void *abstract_dst,
|
|||
DFBPoint points[num_glyphs];
|
||||
int num;
|
||||
const cairo_color_t *color;
|
||||
|
||||
cairo_region_t *clip_region = NULL;
|
||||
|
||||
D_DEBUG_AT (CairoDFB_Font,
|
||||
"%s( dst=%p, op=%d, pattern=%p, glyphs=%p, num_glyphs=%d, scaled_font=%p ).\n",
|
||||
__FUNCTION__, dst, op, pattern, glyphs, num_glyphs, scaled_font);
|
||||
|
||||
if (! dst->supported_destination)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
/* Fallback if we need to emulate clip regions */
|
||||
if (dst->base.clip &&
|
||||
(dst->base.clip->mode != CAIRO_CLIP_MODE_REGION ||
|
||||
dst->base.clip->surface != NULL))
|
||||
{
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (clip != NULL) {
|
||||
status = _cairo_clip_get_region (clip, &clip_region);
|
||||
assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* XXX Unbounded operators are not handled correctly */
|
||||
if (! _cairo_operator_bounded_by_mask (op))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (! _cairo_operator_bounded_by_source (op))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (! _directfb_get_operator (op, &sblend, &dblend) ||
|
||||
sblend == DSBF_DESTALPHA || sblend == DSBF_INVDESTALPHA)
|
||||
|
|
@ -1788,7 +1802,7 @@ _cairo_directfb_surface_show_glyphs (void *abstract_dst,
|
|||
|
||||
D_DEBUG_AT (CairoDFB_Font, "Running BatchBlit().\n");
|
||||
|
||||
RUN_CLIPPED (dst, NULL,
|
||||
RUN_CLIPPED (dst, clip_region, NULL,
|
||||
dst->dfbsurface->BatchBlit (dst->dfbsurface,
|
||||
cache->dfbsurface, rects, points, num));
|
||||
|
||||
|
|
@ -1835,8 +1849,6 @@ _cairo_directfb_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
_cairo_directfb_surface_set_clip_region,/* set_clip_region */
|
||||
NULL, /* intersect_clip_path */
|
||||
_cairo_directfb_abstract_surface_get_extents,/* get_extents */
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
|
|
@ -1860,7 +1872,6 @@ _cairo_directfb_surface_backend = {
|
|||
#endif
|
||||
NULL, /* snapshot */
|
||||
_cairo_directfb_surface_is_similar,
|
||||
NULL /* reset */
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -1933,8 +1944,8 @@ cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface)
|
|||
dfbsurface->GetSize (dfbsurface, &surface->width, &surface->height);
|
||||
surface->dfb = dfb;
|
||||
surface->dfbsurface = dfbsurface;
|
||||
surface->format = _directfb_to_cairo_format (format);
|
||||
surface->content = _directfb_format_to_content (format);
|
||||
surface->pixman_format = _directfb_to_pixman_format (format);
|
||||
surface->supported_destination = pixman_format_supported_destination (surface->pixman_format);
|
||||
|
||||
dfbsurface->GetCapabilities (dfbsurface, &caps);
|
||||
if (caps & DSCAPS_PREMULTIPLIED)
|
||||
|
|
@ -1942,7 +1953,7 @@ cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface)
|
|||
|
||||
_cairo_surface_init (&surface->base,
|
||||
&_cairo_directfb_surface_backend,
|
||||
surface->content);
|
||||
_directfb_format_to_content (format));
|
||||
|
||||
return &surface->base;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1146,7 +1146,7 @@ _render_glyph_bitmap (FT_Face face,
|
|||
cairo_image_surface_t **surface)
|
||||
{
|
||||
FT_GlyphSlot glyphslot = face->glyph;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_status_t status;
|
||||
FT_Error error;
|
||||
|
||||
/* According to the FreeType docs, glyphslot->format could be
|
||||
|
|
@ -1162,7 +1162,9 @@ _render_glyph_bitmap (FT_Face face,
|
|||
if (error == FT_Err_Out_Of_Memory)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface);
|
||||
status = _get_bitmap_surface (&glyphslot->bitmap,
|
||||
FALSE, font_options,
|
||||
surface);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
|
|
@ -1177,7 +1179,7 @@ _render_glyph_bitmap (FT_Face face,
|
|||
-glyphslot->bitmap_left,
|
||||
+glyphslot->bitmap_top);
|
||||
|
||||
return status;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
@ -1275,11 +1277,8 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
|
|||
_cairo_pattern_init_for_surface (&pattern, &(*surface)->base);
|
||||
cairo_pattern_set_matrix (&pattern.base, &transformed_to_original);
|
||||
|
||||
status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
|
||||
&pattern.base, NULL, image,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
width,
|
||||
height);
|
||||
status = _cairo_surface_paint (image, CAIRO_OPERATOR_OVER,
|
||||
&pattern.base, NULL);
|
||||
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
|
||||
|
|
@ -1301,7 +1300,7 @@ _transform_glyph_bitmap (cairo_matrix_t * shape,
|
|||
cairo_surface_set_device_offset (&(*surface)->base,
|
||||
_cairo_lround (origin_x),
|
||||
_cairo_lround (origin_y));
|
||||
return status;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = {
|
||||
|
|
@ -1390,8 +1389,8 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
|
|||
ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
|
||||
}
|
||||
|
||||
#ifdef FC_HINT_STYLE
|
||||
if (FcPatternGetInteger (pattern,
|
||||
#ifdef FC_HINT_STYLE
|
||||
if (FcPatternGetInteger (pattern,
|
||||
FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
|
||||
hintstyle = FC_HINT_FULL;
|
||||
|
||||
|
|
@ -1400,7 +1399,7 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
|
|||
|
||||
switch (hintstyle) {
|
||||
case FC_HINT_NONE:
|
||||
ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
|
||||
ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
|
||||
break;
|
||||
case FC_HINT_SLIGHT:
|
||||
ft_options.base.hint_style = CAIRO_HINT_STYLE_SLIGHT;
|
||||
|
|
@ -1444,14 +1443,14 @@ _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
|
|||
|
||||
if (vertical_layout)
|
||||
ft_options.load_flags |= FT_LOAD_VERTICAL_LAYOUT;
|
||||
|
||||
|
||||
#ifndef FC_EMBOLDEN
|
||||
#define FC_EMBOLDEN "embolden"
|
||||
#endif
|
||||
if (FcPatternGetBool (pattern,
|
||||
FC_EMBOLDEN, 0, &embolden) != FcResultMatch)
|
||||
embolden = FcFalse;
|
||||
|
||||
|
||||
if (embolden)
|
||||
ft_options.extra_flags |= CAIRO_FT_OPTIONS_EMBOLDEN;
|
||||
|
||||
|
|
@ -1468,7 +1467,7 @@ _cairo_ft_options_merge (cairo_ft_options_t *options,
|
|||
|
||||
/* clear load target mode */
|
||||
load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(other->load_flags)));
|
||||
|
||||
|
||||
if (load_flags & FT_LOAD_NO_HINTING)
|
||||
other->base.hint_style = CAIRO_HINT_STYLE_NONE;
|
||||
|
||||
|
|
@ -1479,7 +1478,7 @@ _cairo_ft_options_merge (cairo_ft_options_t *options,
|
|||
}
|
||||
|
||||
if (other->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL &&
|
||||
(options->base.antialias == CAIRO_ANTIALIAS_DEFAULT ||
|
||||
(options->base.antialias == CAIRO_ANTIALIAS_DEFAULT ||
|
||||
options->base.antialias == CAIRO_ANTIALIAS_GRAY)) {
|
||||
options->base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
|
||||
options->base.subpixel_order = other->base.subpixel_order;
|
||||
|
|
@ -1934,12 +1933,12 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
|
|||
x2 = (metrics->horiBearingX + metrics->width + 63) & -64;
|
||||
y1 = (-metrics->horiBearingY) & -64;
|
||||
y2 = (-metrics->horiBearingY + metrics->height + 63) & -64;
|
||||
|
||||
|
||||
advance = ((metrics->horiAdvance + 32) & -64);
|
||||
|
||||
|
||||
fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor;
|
||||
fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor;
|
||||
|
||||
|
||||
fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor;
|
||||
fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor;
|
||||
|
||||
|
|
@ -1950,12 +1949,12 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
|
|||
x2 = (metrics->vertBearingX + metrics->width + 63) & -64;
|
||||
y1 = (metrics->vertBearingY) & -64;
|
||||
y2 = (metrics->vertBearingY + metrics->height + 63) & -64;
|
||||
|
||||
|
||||
advance = ((metrics->vertAdvance + 32) & -64);
|
||||
|
||||
|
||||
fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor;
|
||||
fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor;
|
||||
|
||||
|
||||
fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor;
|
||||
fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor;
|
||||
|
||||
|
|
@ -1969,7 +1968,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
|
|||
if (!vertical_layout) {
|
||||
fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor;
|
||||
fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor;
|
||||
|
||||
|
||||
if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
|
||||
fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor;
|
||||
else
|
||||
|
|
@ -1978,7 +1977,7 @@ _cairo_ft_scaled_glyph_init (void *abstract_font,
|
|||
} else {
|
||||
fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingX) * x_factor;
|
||||
fs_metrics.y_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingY) * y_factor;
|
||||
|
||||
|
||||
fs_metrics.x_advance = 0 * x_factor;
|
||||
if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
|
||||
fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor;
|
||||
|
|
@ -2154,7 +2153,7 @@ static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
|
|||
_cairo_ft_scaled_glyph_init,
|
||||
NULL, /* text_to_glyphs */
|
||||
_cairo_ft_ucs4_to_index,
|
||||
NULL, /* show_glyphs */
|
||||
NULL, /* show_glyphs */
|
||||
_cairo_ft_load_truetype_table,
|
||||
_cairo_ft_index_to_ucs4
|
||||
};
|
||||
|
|
@ -2911,10 +2910,10 @@ cairo_bool_t
|
|||
_cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_ft_scaled_font_t *ft_scaled_font;
|
||||
|
||||
|
||||
if (!_cairo_scaled_font_is_ft (scaled_font))
|
||||
return FALSE;
|
||||
|
||||
|
||||
ft_scaled_font = (cairo_ft_scaled_font_t *) scaled_font;
|
||||
if (ft_scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT)
|
||||
return TRUE;
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@ typedef struct _cairo_gl_surface {
|
|||
int width, height;
|
||||
|
||||
GLuint tex; /* GL texture object containing our data. */
|
||||
GLuint depth_stencil_tex;
|
||||
GLuint fb; /* GL framebuffer object wrapping our data. */
|
||||
} cairo_gl_surface_t;
|
||||
|
||||
|
|
|
|||
|
|
@ -312,6 +312,10 @@ _cairo_gl_get_image_format_and_type (pixman_format_code_t pixman_format,
|
|||
case PIXMAN_g1:
|
||||
case PIXMAN_yuy2:
|
||||
case PIXMAN_yv12:
|
||||
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,15,16)
|
||||
case PIXMAN_x2r10g10b10:
|
||||
case PIXMAN_a2r10g10b10:
|
||||
#endif
|
||||
default:
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
|
@ -766,6 +770,8 @@ _cairo_gl_surface_finish (void *abstract_surface)
|
|||
|
||||
glDeleteFramebuffersEXT (1, &surface->fb);
|
||||
glDeleteTextures (1, &surface->tex);
|
||||
if (surface->depth_stencil_tex)
|
||||
glDeleteTextures (1, &surface->depth_stencil_tex);
|
||||
|
||||
if (surface->ctx->current_target == surface)
|
||||
surface->ctx->current_target = NULL;
|
||||
|
|
@ -1264,16 +1270,20 @@ _cairo_gl_surface_composite (cairo_operator_t op,
|
|||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height)
|
||||
unsigned int height,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_gl_surface_t *dst = abstract_dst;
|
||||
cairo_surface_attributes_t *src_attributes, *mask_attributes = NULL;
|
||||
cairo_gl_context_t *ctx;
|
||||
GLfloat vertices[4][2];
|
||||
GLfloat texcoord_src[4][2];
|
||||
GLfloat texcoord_mask[4][2];
|
||||
struct gl_point {
|
||||
GLfloat x, y;
|
||||
} vertices_stack[8], texcoord_src_stack[8], texcoord_mask_stack[8];
|
||||
struct gl_point *vertices = vertices_stack;
|
||||
struct gl_point *texcoord_src = texcoord_src_stack;
|
||||
struct gl_point *texcoord_mask = texcoord_mask_stack;
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
int num_vertices, i;
|
||||
GLenum err;
|
||||
cairo_gl_composite_setup_t setup;
|
||||
|
||||
|
|
@ -1345,27 +1355,62 @@ _cairo_gl_surface_composite (cairo_operator_t op,
|
|||
}
|
||||
}
|
||||
|
||||
vertices[0][0] = dst_x;
|
||||
vertices[0][1] = dst_y;
|
||||
vertices[1][0] = dst_x + width;
|
||||
vertices[1][1] = dst_y;
|
||||
vertices[2][0] = dst_x + width;
|
||||
vertices[2][1] = dst_y + height;
|
||||
vertices[3][0] = dst_x;
|
||||
vertices[3][1] = dst_y + height;
|
||||
if (clip_region != NULL) {
|
||||
int num_rectangles;
|
||||
|
||||
num_rectangles = cairo_region_num_rectangles (clip_region);
|
||||
if (num_rectangles * 4 > ARRAY_LENGTH (vertices_stack)) {
|
||||
vertices = _cairo_malloc_ab (num_rectangles,
|
||||
4*3*sizeof (vertices[0]));
|
||||
if (unlikely (vertices == NULL)) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto CONTEXT_RELEASE;
|
||||
}
|
||||
|
||||
texcoord_src = vertices + num_rectangles * 4;
|
||||
texcoord_mask = texcoord_src + num_rectangles * 4;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_rectangles; i++) {
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (clip_region, i, &rect);
|
||||
vertices[4*i + 0].x = rect.x;
|
||||
vertices[4*i + 0].y = rect.y;
|
||||
vertices[4*i + 1].x = rect.x + rect.width;
|
||||
vertices[4*i + 1].y = rect.y;
|
||||
vertices[4*i + 2].x = rect.x + rect.width;
|
||||
vertices[4*i + 2].y = rect.y + rect.height;
|
||||
vertices[4*i + 3].x = rect.x;
|
||||
vertices[4*i + 3].y = rect.y + rect.height;
|
||||
}
|
||||
|
||||
num_vertices = 4 * num_rectangles;
|
||||
} else {
|
||||
vertices[0].x = dst_x;
|
||||
vertices[0].y = dst_y;
|
||||
vertices[1].x = dst_x + width;
|
||||
vertices[1].y = dst_y;
|
||||
vertices[2].x = dst_x + width;
|
||||
vertices[2].y = dst_y + height;
|
||||
vertices[3].x = dst_x;
|
||||
vertices[3].y = dst_y + height;
|
||||
|
||||
num_vertices = 4;
|
||||
}
|
||||
|
||||
glVertexPointer (2, GL_FLOAT, sizeof (GLfloat) * 2, vertices);
|
||||
glEnableClientState (GL_VERTEX_ARRAY);
|
||||
|
||||
if (setup.src.type == OPERAND_TEXTURE) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (i = 0; i < num_vertices; i++) {
|
||||
double s, t;
|
||||
|
||||
s = vertices[i][0];
|
||||
t = vertices[i][1];
|
||||
s = vertices[i].x;
|
||||
t = vertices[i].y;
|
||||
cairo_matrix_transform_point (&src_attributes->matrix, &s, &t);
|
||||
texcoord_src[i][0] = s;
|
||||
texcoord_src[i][1] = t;
|
||||
texcoord_src[i].x = s;
|
||||
texcoord_src[i].y = t;
|
||||
}
|
||||
|
||||
glClientActiveTexture (GL_TEXTURE0);
|
||||
|
|
@ -1375,14 +1420,14 @@ _cairo_gl_surface_composite (cairo_operator_t op,
|
|||
|
||||
if (mask != NULL) {
|
||||
if (setup.mask.type == OPERAND_TEXTURE) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
for (i = 0; i < num_vertices; i++) {
|
||||
double s, t;
|
||||
|
||||
s = vertices[i][0];
|
||||
t = vertices[i][1];
|
||||
s = vertices[i].x;
|
||||
t = vertices[i].y;
|
||||
cairo_matrix_transform_point (&mask_attributes->matrix, &s, &t);
|
||||
texcoord_mask[i][0] = s;
|
||||
texcoord_mask[i][1] = t;
|
||||
texcoord_mask[i].x = s;
|
||||
texcoord_mask[i].y = t;
|
||||
}
|
||||
|
||||
glClientActiveTexture (GL_TEXTURE1);
|
||||
|
|
@ -1391,7 +1436,7 @@ _cairo_gl_surface_composite (cairo_operator_t op,
|
|||
}
|
||||
}
|
||||
|
||||
glDrawArrays (GL_TRIANGLE_FAN, 0, 4);
|
||||
glDrawArrays (GL_QUADS, 0, num_vertices);
|
||||
|
||||
glDisable (GL_BLEND);
|
||||
|
||||
|
|
@ -1410,13 +1455,17 @@ _cairo_gl_surface_composite (cairo_operator_t op,
|
|||
while ((err = glGetError ()))
|
||||
fprintf (stderr, "GL error 0x%08x\n", (int) err);
|
||||
|
||||
CONTEXT_RELEASE:
|
||||
_cairo_gl_context_release (ctx);
|
||||
|
||||
_cairo_gl_operand_destroy (&setup.src);
|
||||
if (mask != NULL)
|
||||
_cairo_gl_operand_destroy (&setup.mask);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
if (vertices != vertices_stack)
|
||||
free (vertices);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -1429,7 +1478,8 @@ _cairo_gl_surface_composite_trapezoids (cairo_operator_t op,
|
|||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_trapezoid_t *traps,
|
||||
int num_traps)
|
||||
int num_traps,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_gl_surface_t *dst = abstract_dst;
|
||||
cairo_surface_pattern_t traps_pattern;
|
||||
|
|
@ -1447,7 +1497,8 @@ _cairo_gl_surface_composite_trapezoids (cairo_operator_t op,
|
|||
src_x, src_y,
|
||||
0, 0,
|
||||
dst_x, dst_y,
|
||||
width, height);
|
||||
width, height,
|
||||
clip_region);
|
||||
|
||||
_cairo_pattern_fini (&traps_pattern.base);
|
||||
|
||||
|
|
@ -1737,6 +1788,7 @@ _cairo_gl_surface_span_renderer_finish (void *abstract_renderer)
|
|||
glDisable (GL_TEXTURE_2D);
|
||||
|
||||
glDisable (GL_BLEND);
|
||||
glDisable (GL_DEPTH_TEST);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -1756,27 +1808,112 @@ _cairo_gl_surface_check_span_renderer (cairo_operator_t op,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_gl_surface_ensure_depth_buffer (cairo_gl_surface_t *surface)
|
||||
{
|
||||
if (surface->depth_stencil_tex)
|
||||
return;
|
||||
|
||||
glGenTextures (1, &surface->depth_stencil_tex);
|
||||
glBindTexture (GL_TEXTURE_2D, surface->depth_stencil_tex);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexImage2D (GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8_EXT,
|
||||
surface->width, surface->height, 0,
|
||||
GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, NULL);
|
||||
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
|
||||
GL_DEPTH_ATTACHMENT_EXT,
|
||||
GL_TEXTURE_2D,
|
||||
surface->depth_stencil_tex, 0);
|
||||
glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
|
||||
GL_STENCIL_ATTACHMENT_EXT,
|
||||
GL_TEXTURE_2D,
|
||||
surface->depth_stencil_tex, 0);
|
||||
}
|
||||
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gl_surface_set_clip_region (cairo_gl_surface_t *surface,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
GLfloat vertices_stack[CAIRO_STACK_ARRAY_LENGTH(GLfloat)], *vertices;
|
||||
int num_rectangles, i, n;
|
||||
|
||||
if (clip_region == NULL)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
num_rectangles = cairo_region_num_rectangles (clip_region);
|
||||
|
||||
vertices = vertices_stack;
|
||||
if (num_rectangles * 8 > ARRAY_LENGTH (vertices_stack)) {
|
||||
vertices = _cairo_malloc_ab (num_rectangles,
|
||||
4*3*sizeof (vertices[0]));
|
||||
if (unlikely (vertices == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
for (i = n = 0; i < num_rectangles; i++) {
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (clip_region, i, &rect);
|
||||
vertices[n++] = rect.x;
|
||||
vertices[n++] = rect.y;
|
||||
vertices[n++] = rect.x + rect.width;
|
||||
vertices[n++] = rect.y;
|
||||
vertices[n++] = rect.x + rect.width;
|
||||
vertices[n++] = rect.y + rect.height;
|
||||
vertices[n++] = rect.x;
|
||||
vertices[n++] = rect.y +rect. height;
|
||||
}
|
||||
|
||||
_cairo_gl_surface_ensure_depth_buffer (surface);
|
||||
|
||||
glDisable (GL_BLEND);
|
||||
glDepthFunc (GL_ALWAYS);
|
||||
glEnable (GL_DEPTH_TEST);
|
||||
glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
|
||||
|
||||
glDepthMask (GL_TRUE);
|
||||
glClear (GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glVertexPointer (2, GL_FLOAT, sizeof (GLfloat) * 2, vertices);
|
||||
glEnableClientState (GL_VERTEX_ARRAY);
|
||||
glDrawArrays (GL_QUADS, 0, 4 * num_rectangles);
|
||||
glDisableClientState (GL_VERTEX_ARRAY);
|
||||
|
||||
glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glDepthFunc (GL_EQUAL);
|
||||
glDepthMask (GL_FALSE);
|
||||
|
||||
if (vertices != vertices_stack)
|
||||
free (vertices);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_span_renderer_t *
|
||||
_cairo_gl_surface_create_span_renderer (cairo_operator_t op,
|
||||
const cairo_pattern_t *src,
|
||||
void *abstract_dst,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_composite_rectangles_t *rects)
|
||||
const cairo_composite_rectangles_t *rects,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_gl_surface_t *dst = abstract_dst;
|
||||
cairo_gl_surface_span_renderer_t *renderer = calloc (1, sizeof (*renderer));
|
||||
cairo_gl_surface_span_renderer_t *renderer;
|
||||
cairo_status_t status;
|
||||
int width = rects->width;
|
||||
int height = rects->height;
|
||||
cairo_surface_attributes_t *src_attributes;
|
||||
GLenum err;
|
||||
|
||||
if (renderer == NULL)
|
||||
return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
if (!GLEW_ARB_vertex_buffer_object)
|
||||
return _cairo_span_renderer_create_in_error (CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
|
||||
renderer = calloc (1, sizeof (*renderer));
|
||||
if (unlikely (renderer == NULL))
|
||||
return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
renderer->base.destroy = _cairo_gl_surface_span_renderer_destroy;
|
||||
renderer->base.finish = _cairo_gl_surface_span_renderer_finish;
|
||||
renderer->base.render_row =
|
||||
|
|
@ -1801,6 +1938,12 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
|
|||
|
||||
_cairo_gl_set_destination (dst);
|
||||
|
||||
status = _cairo_gl_surface_set_clip_region (dst, clip_region);
|
||||
if (unlikely (status)) {
|
||||
_cairo_gl_surface_span_renderer_destroy (renderer);
|
||||
return _cairo_span_renderer_create_in_error (status);
|
||||
}
|
||||
|
||||
src_attributes = &renderer->setup.src.operand.texture.attributes;
|
||||
|
||||
status = _cairo_gl_set_operator (dst, op);
|
||||
|
|
@ -1838,7 +1981,7 @@ _cairo_gl_surface_create_span_renderer (cairo_operator_t op,
|
|||
return &renderer->base;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_gl_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
|
|
@ -1849,7 +1992,7 @@ _cairo_gl_surface_get_extents (void *abstract_surface,
|
|||
rectangle->width = surface->width;
|
||||
rectangle->height = surface->height;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1888,20 +2031,21 @@ static const cairo_surface_backend_t _cairo_gl_surface_backend = {
|
|||
CAIRO_SURFACE_TYPE_GL,
|
||||
_cairo_gl_surface_create_similar,
|
||||
_cairo_gl_surface_finish,
|
||||
|
||||
_cairo_gl_surface_acquire_source_image,
|
||||
_cairo_gl_surface_release_source_image,
|
||||
_cairo_gl_surface_acquire_dest_image,
|
||||
_cairo_gl_surface_release_dest_image,
|
||||
|
||||
_cairo_gl_surface_clone_similar,
|
||||
_cairo_gl_surface_composite,
|
||||
_cairo_gl_surface_fill_rectangles,
|
||||
_cairo_gl_surface_composite_trapezoids,
|
||||
_cairo_gl_surface_create_span_renderer,
|
||||
_cairo_gl_surface_check_span_renderer,
|
||||
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
NULL, /* set_clip_region */
|
||||
NULL, /* intersect_clip_path */
|
||||
_cairo_gl_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
_cairo_gl_surface_get_font_options,
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "cairoint.h"
|
||||
#include "cairo-glitz.h"
|
||||
#include "cairo-glitz-private.h"
|
||||
#include "cairo-region-private.h"
|
||||
|
||||
typedef struct _cairo_glitz_surface {
|
||||
cairo_surface_t base;
|
||||
|
|
@ -34,6 +35,7 @@ typedef struct _cairo_glitz_surface {
|
|||
glitz_surface_t *surface;
|
||||
glitz_format_t *format;
|
||||
|
||||
cairo_region_t *clip_region;
|
||||
cairo_bool_t has_clip;
|
||||
glitz_box_t *clip_boxes;
|
||||
int num_clip_boxes;
|
||||
|
|
@ -50,6 +52,7 @@ _cairo_glitz_surface_finish (void *abstract_surface)
|
|||
if (surface->clip_boxes)
|
||||
free (surface->clip_boxes);
|
||||
|
||||
cairo_region_destroy (surface->clip_region);
|
||||
glitz_surface_destroy (surface->surface);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -106,43 +109,6 @@ _cairo_glitz_surface_create_similar (void *abstract_src,
|
|||
return crsurface;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_glitz_get_boxes_from_region (cairo_region_t *region,
|
||||
glitz_box_t **boxes,
|
||||
int *nboxes)
|
||||
{
|
||||
pixman_box32_t *pboxes;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
int n, i;
|
||||
|
||||
n = 0;
|
||||
pboxes = pixman_region32_rectangles (®ion->rgn, &n);
|
||||
if (n == 0) {
|
||||
*nboxes = 0;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (n > *nboxes) {
|
||||
*boxes = _cairo_malloc_ab (n, sizeof (glitz_box_t));
|
||||
if (*boxes == NULL) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
(*boxes)[i].x1 = pboxes[i].x1;
|
||||
(*boxes)[i].y1 = pboxes[i].y1;
|
||||
(*boxes)[i].x2 = pboxes[i].x2;
|
||||
(*boxes)[i].y2 = pboxes[i].y2;
|
||||
}
|
||||
|
||||
*nboxes = n;
|
||||
done:
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_glitz_surface_get_image (cairo_glitz_surface_t *surface,
|
||||
cairo_rectangle_int_t *interest,
|
||||
|
|
@ -463,6 +429,8 @@ _is_supported_operator (cairo_operator_t op)
|
|||
case CAIRO_OPERATOR_ADD:
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
case CAIRO_OPERATOR_SATURATE:
|
||||
/* nobody likes saturate, expect that it's required to do
|
||||
* seamless polygons!
|
||||
|
|
@ -485,6 +453,7 @@ _is_supported_operator (cairo_operator_t op)
|
|||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static glitz_operator_t
|
||||
_glitz_operator (cairo_operator_t op)
|
||||
{
|
||||
|
|
@ -686,9 +655,9 @@ _cairo_glitz_pattern_acquire_surface (const cairo_pattern_t *pattern,
|
|||
}
|
||||
|
||||
src = (cairo_glitz_surface_t *)
|
||||
_cairo_surface_create_similar_scratch (&dst->base,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
gradient->n_stops, 1);
|
||||
_cairo_glitz_surface_create_similar (&dst->base,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
gradient->n_stops, 1);
|
||||
if (src->base.status) {
|
||||
glitz_buffer_destroy (buffer);
|
||||
free (data);
|
||||
|
|
@ -914,6 +883,77 @@ _cairo_glitz_surface_set_attributes (cairo_glitz_surface_t *surface,
|
|||
a->params, a->n_params);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_glitz_get_boxes_from_region (cairo_region_t *region,
|
||||
glitz_box_t **boxes,
|
||||
int *nboxes)
|
||||
{
|
||||
pixman_box32_t *pboxes;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
int n, i;
|
||||
|
||||
n = 0;
|
||||
pboxes = pixman_region32_rectangles (®ion->rgn, &n);
|
||||
if (n == 0) {
|
||||
*nboxes = 0;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (n > *nboxes) {
|
||||
*boxes = _cairo_malloc_ab (n, sizeof (glitz_box_t));
|
||||
if (*boxes == NULL) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
(*boxes)[i].x1 = pboxes[i].x1;
|
||||
(*boxes)[i].y1 = pboxes[i].y1;
|
||||
(*boxes)[i].x2 = pboxes[i].x2;
|
||||
(*boxes)[i].y2 = pboxes[i].y2;
|
||||
}
|
||||
|
||||
*nboxes = n;
|
||||
done:
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_glitz_surface_set_clip_region (void *abstract_surface,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
cairo_glitz_surface_t *surface = abstract_surface;
|
||||
|
||||
if (region == surface->clip_region)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
cairo_region_destroy (surface->clip_region);
|
||||
surface->clip_region = cairo_region_reference (region);
|
||||
|
||||
if (region != NULL) {
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_glitz_get_boxes_from_region (region,
|
||||
&surface->clip_boxes,
|
||||
&surface->num_clip_boxes);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
glitz_surface_set_clip_region (surface->surface,
|
||||
0, 0,
|
||||
surface->clip_boxes,
|
||||
surface->num_clip_boxes);
|
||||
surface->has_clip = TRUE;
|
||||
} else {
|
||||
glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);
|
||||
surface->has_clip = FALSE;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_glitz_surface_composite (cairo_operator_t op,
|
||||
const cairo_pattern_t *src_pattern,
|
||||
|
|
@ -926,7 +966,8 @@ _cairo_glitz_surface_composite (cairo_operator_t op,
|
|||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height)
|
||||
unsigned int height,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_glitz_surface_attributes_t src_attr, mask_attr;
|
||||
cairo_glitz_surface_t *dst = abstract_dst;
|
||||
|
|
@ -940,6 +981,10 @@ _cairo_glitz_surface_composite (cairo_operator_t op,
|
|||
if (_glitz_ensure_target (dst->surface))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_glitz_surface_set_clip_region (dst, clip_region);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
status = _cairo_glitz_pattern_acquire_surfaces (src_pattern, mask_pattern,
|
||||
dst,
|
||||
src_x, src_y,
|
||||
|
|
@ -1006,7 +1051,8 @@ _cairo_glitz_surface_composite (cairo_operator_t op,
|
|||
mask_width, mask_height,
|
||||
src_x, src_y,
|
||||
mask_x, mask_y,
|
||||
dst_x, dst_y, width, height);
|
||||
dst_x, dst_y, width, height,
|
||||
clip_region);
|
||||
}
|
||||
|
||||
if (mask)
|
||||
|
|
@ -1037,11 +1083,15 @@ _cairo_glitz_surface_fill_rectangles (void *abstract_dst,
|
|||
glitz_rectangle_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (glitz_rectangle_t)];
|
||||
glitz_rectangle_t *glitz_rects = stack_rects;
|
||||
glitz_rectangle_t *current_rect;
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
|
||||
if (! _is_supported_operator (op))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_glitz_surface_set_clip_region (dst, NULL);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
if (n_rects > ARRAY_LENGTH (stack_rects)) {
|
||||
glitz_rects = _cairo_malloc_ab (n_rects, sizeof (glitz_rectangle_t));
|
||||
if (glitz_rects == NULL)
|
||||
|
|
@ -1104,12 +1154,12 @@ _cairo_glitz_surface_fill_rectangles (void *abstract_dst,
|
|||
_cairo_surface_create_similar_solid (&dst->base,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
1, 1,
|
||||
(cairo_color_t *) color);
|
||||
if (src->base.status)
|
||||
{
|
||||
(cairo_color_t *) color,
|
||||
FALSE);
|
||||
if (src == NULL || src->base.status) {
|
||||
if (glitz_rects != stack_rects)
|
||||
free (glitz_rects);
|
||||
return src->base.status;
|
||||
return src ? src->base.status : CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
glitz_surface_set_fill (src->surface, GLITZ_FILL_REPEAT);
|
||||
|
|
@ -1153,7 +1203,8 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
|
|||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_trapezoid_t *traps,
|
||||
int n_traps)
|
||||
int n_traps,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_glitz_surface_attributes_t attributes;
|
||||
cairo_glitz_surface_t *dst = abstract_dst;
|
||||
|
|
@ -1179,6 +1230,10 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
|
|||
if (_glitz_ensure_target (dst->surface))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_glitz_surface_set_clip_region (dst, clip_region);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
/* Convert traps to pixman traps */
|
||||
if (n_traps > ARRAY_LENGTH (stack_traps)) {
|
||||
pixman_traps = _cairo_malloc_ab (n_traps, sizeof (pixman_trapezoid_t));
|
||||
|
|
@ -1321,7 +1376,7 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
|
|||
n_traps, (pixman_trapezoid_t *) pixman_traps);
|
||||
|
||||
mask = (cairo_glitz_surface_t *)
|
||||
_cairo_surface_create_similar_scratch (&dst->base,
|
||||
_cairo_glitz_surface_create_similar (&dst->base,
|
||||
CAIRO_CONTENT_ALPHA,
|
||||
width, height);
|
||||
status = mask->base.status;
|
||||
|
|
@ -1378,7 +1433,8 @@ _cairo_glitz_surface_composite_trapezoids (cairo_operator_t op,
|
|||
src_x, src_y,
|
||||
0, 0,
|
||||
dst_x, dst_y,
|
||||
width, height);
|
||||
width, height,
|
||||
clip_region);
|
||||
}
|
||||
|
||||
FAIL:
|
||||
|
|
@ -1393,35 +1449,7 @@ FAIL:
|
|||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_glitz_surface_set_clip_region (void *abstract_surface,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
cairo_glitz_surface_t *surface = abstract_surface;
|
||||
|
||||
if (region != NULL) {
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_glitz_get_boxes_from_region (region,
|
||||
&surface->clip_boxes,
|
||||
&surface->num_clip_boxes);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
glitz_surface_set_clip_region (surface->surface,
|
||||
0, 0,
|
||||
surface->clip_boxes,
|
||||
surface->num_clip_boxes);
|
||||
surface->has_clip = TRUE;
|
||||
} else {
|
||||
glitz_surface_set_clip_region (surface->surface, 0, 0, NULL, 0);
|
||||
surface->has_clip = FALSE;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_glitz_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
|
|
@ -1432,7 +1460,7 @@ _cairo_glitz_surface_get_extents (void *abstract_surface,
|
|||
rectangle->width = glitz_surface_get_width (surface->surface);
|
||||
rectangle->height = glitz_surface_get_height (surface->surface);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define CAIRO_GLITZ_AREA_AVAILABLE 0
|
||||
|
|
@ -2035,7 +2063,8 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs)
|
||||
int num_glyphs,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_glitz_surface_attributes_t attributes;
|
||||
cairo_glitz_surface_glyph_private_t *glyph_private;
|
||||
|
|
@ -2078,6 +2107,10 @@ _cairo_glitz_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
if (_glitz_ensure_target (dst->surface))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_glitz_surface_set_clip_region (dst, NULL);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_glitz_pattern_acquire_surface (pattern, dst,
|
||||
src_x, src_y,
|
||||
width, height,
|
||||
|
|
@ -2326,25 +2359,13 @@ _cairo_glitz_surface_is_similar (void *surface_a,
|
|||
return drawable_a == drawable_b;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_glitz_surface_reset (void *abstract_surface)
|
||||
{
|
||||
cairo_glitz_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_glitz_surface_set_clip_region (surface, NULL);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_glitz_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_GLITZ,
|
||||
_cairo_glitz_surface_create_similar,
|
||||
_cairo_glitz_surface_finish,
|
||||
_cairo_glitz_surface_acquire_source_image,
|
||||
_cairo_glitz_surface_release_source_image,
|
||||
|
||||
_cairo_glitz_surface_acquire_dest_image,
|
||||
_cairo_glitz_surface_release_dest_image,
|
||||
_cairo_glitz_surface_clone_similar,
|
||||
|
|
@ -2353,10 +2374,9 @@ static const cairo_surface_backend_t cairo_glitz_surface_backend = {
|
|||
_cairo_glitz_surface_composite_trapezoids,
|
||||
NULL, /* create_span_renderer */
|
||||
NULL, /* check_span_renderer */
|
||||
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
_cairo_glitz_surface_set_clip_region,
|
||||
NULL, /* intersect_clip_path */
|
||||
_cairo_glitz_surface_get_extents,
|
||||
_cairo_glitz_surface_old_show_glyphs,
|
||||
NULL, /* get_font_options */
|
||||
|
|
@ -2373,8 +2393,6 @@ static const cairo_surface_backend_t cairo_glitz_surface_backend = {
|
|||
|
||||
_cairo_glitz_surface_snapshot,
|
||||
_cairo_glitz_surface_is_similar,
|
||||
|
||||
_cairo_glitz_surface_reset
|
||||
};
|
||||
|
||||
static const cairo_surface_backend_t *
|
||||
|
|
@ -2424,6 +2442,7 @@ cairo_glitz_surface_create (glitz_surface_t *surface)
|
|||
crsurface->has_clip = FALSE;
|
||||
crsurface->clip_boxes = NULL;
|
||||
crsurface->num_clip_boxes = 0;
|
||||
crsurface->clip_region = NULL;
|
||||
|
||||
return &crsurface->base;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ _cairo_gstate_init (cairo_gstate_t *gstate,
|
|||
|
||||
_cairo_font_options_init_default (&gstate->font_options);
|
||||
|
||||
_cairo_clip_init (&gstate->clip, target);
|
||||
_cairo_clip_init (&gstate->clip);
|
||||
|
||||
gstate->target = cairo_surface_reference (target);
|
||||
gstate->parent_target = NULL;
|
||||
|
|
@ -164,14 +164,7 @@ _cairo_gstate_init_copy (cairo_gstate_t *gstate, cairo_gstate_t *other)
|
|||
|
||||
_cairo_font_options_init_copy (&gstate->font_options , &other->font_options);
|
||||
|
||||
status = _cairo_clip_init_copy (&gstate->clip, &other->clip);
|
||||
if (unlikely (status)) {
|
||||
_cairo_stroke_style_fini (&gstate->stroke_style);
|
||||
cairo_font_face_destroy (gstate->font_face);
|
||||
cairo_scaled_font_destroy (gstate->scaled_font);
|
||||
cairo_scaled_font_destroy (gstate->previous_scaled_font);
|
||||
return status;
|
||||
}
|
||||
_cairo_clip_init_copy (&gstate->clip, &other->clip);
|
||||
|
||||
gstate->target = cairo_surface_reference (other->target);
|
||||
/* parent_target is always set to NULL; it's only ever set by redirect_target */
|
||||
|
|
@ -299,7 +292,7 @@ _cairo_gstate_restore (cairo_gstate_t **gstate, cairo_gstate_t **freelist)
|
|||
cairo_status_t
|
||||
_cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_matrix_t matrix;
|
||||
|
||||
/* If this gstate is already redirected, this is an error; we need a
|
||||
* new gstate to be able to redirect */
|
||||
|
|
@ -315,18 +308,15 @@ _cairo_gstate_redirect_target (cairo_gstate_t *gstate, cairo_surface_t *child)
|
|||
* since its ref is now owned by gstate->parent_target */
|
||||
gstate->target = cairo_surface_reference (child);
|
||||
|
||||
_cairo_clip_reset (&gstate->clip);
|
||||
status = _cairo_clip_init_deep_copy (&gstate->clip, &gstate->next->clip, child);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
/* The clip is in surface backend coordinates for the previous target;
|
||||
* translate it into the child's backend coordinates. */
|
||||
_cairo_clip_translate (&gstate->clip,
|
||||
_cairo_fixed_from_double (child->device_transform.x0 - gstate->parent_target->device_transform.x0),
|
||||
_cairo_fixed_from_double (child->device_transform.y0 - gstate->parent_target->device_transform.y0));
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
cairo_matrix_init_translate (&matrix,
|
||||
child->device_transform.x0 - gstate->parent_target->device_transform.x0,
|
||||
child->device_transform.y0 - gstate->parent_target->device_transform.y0);
|
||||
_cairo_clip_reset (&gstate->clip);
|
||||
return _cairo_clip_init_copy_transformed (&gstate->clip,
|
||||
&gstate->next->clip,
|
||||
&matrix);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -870,43 +860,63 @@ _cairo_gstate_copy_transformed_mask (cairo_gstate_t *gstate,
|
|||
&gstate->ctm_inverse);
|
||||
}
|
||||
|
||||
#define _gstate_get_clip(g) ((g)->clip.path ? &(g)->clip : NULL)
|
||||
|
||||
static cairo_bool_t
|
||||
_clipped (const cairo_gstate_t *gstate)
|
||||
{
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
if (gstate->clip.all_clipped)
|
||||
return TRUE;
|
||||
|
||||
if (gstate->clip.path == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (_cairo_surface_get_extents (gstate->target, &extents)) {
|
||||
if (! _cairo_rectangle_intersect (&extents,
|
||||
&gstate->clip.path->extents))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_gstate_paint (cairo_gstate_t *gstate)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_pattern_union_t pattern;
|
||||
|
||||
if (gstate->source->status)
|
||||
if (unlikely (gstate->source->status))
|
||||
return gstate->source->status;
|
||||
|
||||
status = _cairo_surface_set_clip (gstate->target, &gstate->clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
if (_clipped (gstate))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
|
||||
|
||||
return _cairo_surface_paint (gstate->target,
|
||||
gstate->op,
|
||||
&pattern.base,
|
||||
NULL);
|
||||
_gstate_get_clip (gstate));
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_gstate_mask (cairo_gstate_t *gstate,
|
||||
cairo_pattern_t *mask)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_pattern_union_t source_pattern, mask_pattern;
|
||||
|
||||
if (mask->status)
|
||||
if (unlikely (mask->status))
|
||||
return mask->status;
|
||||
|
||||
if (gstate->source->status)
|
||||
if (unlikely (gstate->source->status))
|
||||
return gstate->source->status;
|
||||
|
||||
status = _cairo_surface_set_clip (gstate->target, &gstate->clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
if (_clipped (gstate))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
||||
_cairo_gstate_copy_transformed_mask (gstate, &mask_pattern.base, mask);
|
||||
|
|
@ -915,24 +925,22 @@ _cairo_gstate_mask (cairo_gstate_t *gstate,
|
|||
gstate->op,
|
||||
&source_pattern.base,
|
||||
&mask_pattern.base,
|
||||
NULL);
|
||||
_gstate_get_clip (gstate));
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_pattern_union_t source_pattern;
|
||||
|
||||
if (gstate->source->status)
|
||||
if (unlikely (gstate->source->status))
|
||||
return gstate->source->status;
|
||||
|
||||
if (gstate->stroke_style.line_width <= 0.0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_surface_set_clip (gstate->target, &gstate->clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
if (_clipped (gstate))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_gstate_copy_transformed_source (gstate, &source_pattern.base);
|
||||
|
||||
|
|
@ -945,7 +953,7 @@ _cairo_gstate_stroke (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
|
|||
&gstate->ctm_inverse,
|
||||
gstate->tolerance,
|
||||
gstate->antialias,
|
||||
NULL);
|
||||
_gstate_get_clip (gstate));
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
|
|
@ -1009,15 +1017,26 @@ BAIL:
|
|||
cairo_status_t
|
||||
_cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_pattern_union_t pattern;
|
||||
|
||||
if (gstate->source->status)
|
||||
if (unlikely (gstate->source->status))
|
||||
return gstate->source->status;
|
||||
|
||||
status = _cairo_surface_set_clip (gstate->target, &gstate->clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
if (_clipped (gstate))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (_cairo_path_fixed_fill_is_empty (path)) {
|
||||
if (_cairo_operator_bounded_by_mask (gstate->op))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_pattern_init_solid (&pattern.solid,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
CAIRO_CONTENT_COLOR_ALPHA);
|
||||
return _cairo_surface_paint (gstate->target,
|
||||
CAIRO_OPERATOR_CLEAR,
|
||||
&pattern.base,
|
||||
_gstate_get_clip (gstate));
|
||||
}
|
||||
|
||||
_cairo_gstate_copy_transformed_source (gstate, &pattern.base);
|
||||
|
||||
|
|
@ -1028,23 +1047,56 @@ _cairo_gstate_fill (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
|
|||
gstate->fill_rule,
|
||||
gstate->tolerance,
|
||||
gstate->antialias,
|
||||
NULL);
|
||||
_gstate_get_clip (gstate));
|
||||
}
|
||||
|
||||
void
|
||||
cairo_bool_t
|
||||
_cairo_gstate_in_fill (cairo_gstate_t *gstate,
|
||||
cairo_path_fixed_t *path,
|
||||
double x,
|
||||
double y,
|
||||
cairo_bool_t *inside_ret)
|
||||
double y)
|
||||
{
|
||||
_cairo_gstate_user_to_backend (gstate, &x, &y);
|
||||
|
||||
_cairo_path_fixed_in_fill (path,
|
||||
gstate->fill_rule,
|
||||
gstate->tolerance,
|
||||
x, y,
|
||||
inside_ret);
|
||||
return _cairo_path_fixed_in_fill (path,
|
||||
gstate->fill_rule,
|
||||
gstate->tolerance,
|
||||
x, y);
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_gstate_in_clip (cairo_gstate_t *gstate,
|
||||
double x,
|
||||
double y)
|
||||
{
|
||||
cairo_clip_path_t *clip_path;
|
||||
|
||||
if (gstate->clip.all_clipped)
|
||||
return FALSE;
|
||||
|
||||
clip_path = gstate->clip.path;
|
||||
if (clip_path == NULL)
|
||||
return TRUE;
|
||||
|
||||
_cairo_gstate_user_to_backend (gstate, &x, &y);
|
||||
|
||||
if (x < clip_path->extents.x ||
|
||||
x >= clip_path->extents.x + clip_path->extents.width ||
|
||||
y < clip_path->extents.y ||
|
||||
y >= clip_path->extents.y + clip_path->extents.height)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
do {
|
||||
if (! _cairo_path_fixed_in_fill (&clip_path->path,
|
||||
clip_path->fill_rule,
|
||||
clip_path->tolerance,
|
||||
x, y))
|
||||
return FALSE;
|
||||
} while ((clip_path = clip_path->prev) != NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
|
|
@ -1179,26 +1231,31 @@ cairo_status_t
|
|||
_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path)
|
||||
{
|
||||
return _cairo_clip_clip (&gstate->clip,
|
||||
path, gstate->fill_rule, gstate->tolerance,
|
||||
gstate->antialias, gstate->target);
|
||||
path, gstate->fill_rule,
|
||||
gstate->tolerance, gstate->antialias);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_gstate_int_clip_extents (cairo_gstate_t *gstate,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_status_t status;
|
||||
const cairo_rectangle_int_t *clip_extents;
|
||||
cairo_bool_t is_bounded;
|
||||
|
||||
status = _cairo_surface_get_extents (gstate->target, extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
is_bounded = _cairo_surface_get_extents (gstate->target, extents);
|
||||
|
||||
status = _cairo_clip_intersect_to_rectangle (&gstate->clip, extents);
|
||||
clip_extents = _cairo_clip_get_extents (&gstate->clip);
|
||||
if (clip_extents != NULL) {
|
||||
cairo_bool_t is_empty;
|
||||
|
||||
return status;
|
||||
is_empty = _cairo_rectangle_intersect (extents, clip_extents);
|
||||
is_bounded = TRUE;
|
||||
}
|
||||
|
||||
return is_bounded;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
cairo_bool_t
|
||||
_cairo_gstate_clip_extents (cairo_gstate_t *gstate,
|
||||
double *x1,
|
||||
double *y1,
|
||||
|
|
@ -1207,11 +1264,9 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
|
|||
{
|
||||
cairo_rectangle_int_t extents;
|
||||
double px1, py1, px2, py2;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_gstate_int_clip_extents (gstate, &extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
if (! _cairo_gstate_int_clip_extents (gstate, &extents))
|
||||
return FALSE;
|
||||
|
||||
px1 = extents.x;
|
||||
py1 = extents.y;
|
||||
|
|
@ -1231,7 +1286,7 @@ _cairo_gstate_clip_extents (cairo_gstate_t *gstate,
|
|||
if (y2)
|
||||
*y2 = py2;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cairo_rectangle_list_t*
|
||||
|
|
@ -1576,12 +1631,11 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
|||
cairo_text_cluster_t *transformed_clusters;
|
||||
cairo_status_t status;
|
||||
|
||||
if (gstate->source->status)
|
||||
if (unlikely (gstate->source->status))
|
||||
return gstate->source->status;
|
||||
|
||||
status = _cairo_surface_set_clip (gstate->target, &gstate->clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
if (_clipped (gstate))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_gstate_ensure_scaled_font (gstate);
|
||||
if (unlikely (status))
|
||||
|
|
@ -1635,7 +1689,8 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
|||
*
|
||||
* Needless to say, do this only if show_text_glyphs is not available. */
|
||||
if (cairo_surface_has_show_text_glyphs (gstate->target) ||
|
||||
_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240) {
|
||||
_cairo_scaled_font_get_max_scale (gstate->scaled_font) <= 10240)
|
||||
{
|
||||
status = _cairo_surface_show_text_glyphs (gstate->target,
|
||||
gstate->op,
|
||||
&source_pattern.base,
|
||||
|
|
@ -1643,8 +1698,11 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
|||
transformed_glyphs, num_glyphs,
|
||||
transformed_clusters, num_clusters,
|
||||
cluster_flags,
|
||||
gstate->scaled_font, NULL);
|
||||
} else {
|
||||
gstate->scaled_font,
|
||||
_gstate_get_clip (gstate));
|
||||
}
|
||||
else
|
||||
{
|
||||
cairo_path_fixed_t path;
|
||||
|
||||
_cairo_path_fixed_init (&path);
|
||||
|
|
@ -1653,14 +1711,16 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
|||
transformed_glyphs, num_glyphs,
|
||||
&path);
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = _cairo_surface_fill (gstate->target,
|
||||
gstate->op,
|
||||
&source_pattern.base,
|
||||
&path,
|
||||
CAIRO_FILL_RULE_WINDING,
|
||||
gstate->tolerance,
|
||||
gstate->scaled_font->options.antialias, NULL);
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
status = _cairo_surface_fill (gstate->target,
|
||||
gstate->op,
|
||||
&source_pattern.base,
|
||||
&path,
|
||||
CAIRO_FILL_RULE_WINDING,
|
||||
gstate->tolerance,
|
||||
gstate->scaled_font->options.antialias,
|
||||
_gstate_get_clip (gstate));
|
||||
}
|
||||
|
||||
_cairo_path_fixed_fini (&path);
|
||||
}
|
||||
|
|
@ -1765,17 +1825,12 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
|||
cairo_matrix_t *device_transform = &gstate->target->device_transform;
|
||||
cairo_bool_t drop = FALSE;
|
||||
double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
|
||||
cairo_status_t status;
|
||||
|
||||
if (num_transformed_glyphs != NULL) {
|
||||
cairo_rectangle_int_t surface_extents;
|
||||
|
||||
drop = TRUE;
|
||||
status = _cairo_gstate_int_clip_extents (gstate, &surface_extents);
|
||||
if (_cairo_status_is_error (status))
|
||||
return status;
|
||||
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
if (! _cairo_gstate_int_clip_extents (gstate, &surface_extents)) {
|
||||
drop = FALSE; /* unbounded surface */
|
||||
} else {
|
||||
double scale10 = 10 * _cairo_scaled_font_get_max_scale (gstate->scaled_font);
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-clip-private.h"
|
||||
#include "cairo-region-private.h"
|
||||
|
||||
static cairo_format_t
|
||||
_cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
|
||||
{
|
||||
|
|
@ -63,6 +66,14 @@ _cairo_format_from_pixman_format (pixman_format_code_t pixman_format)
|
|||
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
|
||||
case PIXMAN_x2b10g10r10:
|
||||
case PIXMAN_a2b10g10r10:
|
||||
#endif
|
||||
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,14,1)
|
||||
case PIXMAN_b8g8r8x8:
|
||||
case PIXMAN_b8g8r8a8:
|
||||
#endif
|
||||
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,15,16)
|
||||
case PIXMAN_x2r10g10b10:
|
||||
case PIXMAN_a2r10g10b10:
|
||||
#endif
|
||||
default:
|
||||
return CAIRO_FORMAT_INVALID;
|
||||
|
|
@ -87,6 +98,12 @@ _cairo_content_from_pixman_format (pixman_format_code_t pixman_format)
|
|||
case PIXMAN_a1b1g1r1:
|
||||
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
|
||||
case PIXMAN_a2b10g10r10:
|
||||
#endif
|
||||
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,14,1)
|
||||
case PIXMAN_b8g8r8a8:
|
||||
#endif
|
||||
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,15,16)
|
||||
case PIXMAN_a2r10g10b10:
|
||||
#endif
|
||||
return CAIRO_CONTENT_COLOR_ALPHA;
|
||||
case PIXMAN_x8r8g8b8:
|
||||
|
|
@ -112,6 +129,12 @@ _cairo_content_from_pixman_format (pixman_format_code_t pixman_format)
|
|||
case PIXMAN_yv12:
|
||||
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,11,9)
|
||||
case PIXMAN_x2b10g10r10:
|
||||
#endif
|
||||
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,14,1)
|
||||
case PIXMAN_b8g8r8x8:
|
||||
#endif
|
||||
#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,15,16)
|
||||
case PIXMAN_x2r10g10b10:
|
||||
#endif
|
||||
return CAIRO_CONTENT_COLOR;
|
||||
case PIXMAN_a8:
|
||||
|
|
@ -143,7 +166,6 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
|
|||
surface->format = _cairo_format_from_pixman_format (pixman_format);
|
||||
surface->data = (unsigned char *) pixman_image_get_data (pixman_image);
|
||||
surface->owns_data = FALSE;
|
||||
surface->has_clip = FALSE;
|
||||
surface->transparency = CAIRO_IMAGE_UNKNOWN;
|
||||
|
||||
surface->width = pixman_image_get_width (pixman_image);
|
||||
|
|
@ -151,6 +173,8 @@ _cairo_image_surface_create_for_pixman_image (pixman_image_t *pixman_image,
|
|||
surface->stride = pixman_image_get_stride (pixman_image);
|
||||
surface->depth = pixman_image_get_depth (pixman_image);
|
||||
|
||||
surface->clip_region = NULL;
|
||||
|
||||
return &surface->base;
|
||||
}
|
||||
|
||||
|
|
@ -725,6 +749,8 @@ _cairo_image_surface_finish (void *abstract_surface)
|
|||
surface->data = NULL;
|
||||
}
|
||||
|
||||
cairo_region_destroy (surface->clip_region);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -974,25 +1000,52 @@ _pixman_operator (cairo_operator_t op)
|
|||
}
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_image_surface_set_clip_region (cairo_image_surface_t *surface,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
if (region == surface->clip_region)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (cairo_region_equal (surface->clip_region, region))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
cairo_region_destroy (surface->clip_region);
|
||||
surface->clip_region = cairo_region_reference (region);
|
||||
|
||||
if (! pixman_image_set_clip_region32 (surface->pixman_image,
|
||||
region ? ®ion->rgn : NULL))
|
||||
{
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_image_surface_composite (cairo_operator_t op,
|
||||
_cairo_image_surface_composite (cairo_operator_t op,
|
||||
const cairo_pattern_t *src_pattern,
|
||||
const cairo_pattern_t *mask_pattern,
|
||||
void *abstract_dst,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int mask_x,
|
||||
int mask_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height)
|
||||
int src_x,
|
||||
int src_y,
|
||||
int mask_x,
|
||||
int mask_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_surface_attributes_t src_attr, mask_attr;
|
||||
cairo_surface_attributes_t src_attr, mask_attr;
|
||||
cairo_image_surface_t *dst = abstract_dst;
|
||||
cairo_image_surface_t *src;
|
||||
cairo_image_surface_t *mask;
|
||||
cairo_int_status_t status;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_image_surface_set_clip_region (dst, clip_region);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_pattern_acquire_surfaces (src_pattern, mask_pattern,
|
||||
&dst->base,
|
||||
|
|
@ -1013,8 +1066,7 @@ _cairo_image_surface_composite (cairo_operator_t op,
|
|||
if (unlikely (status))
|
||||
goto CLEANUP_SURFACES;
|
||||
|
||||
if (mask)
|
||||
{
|
||||
if (mask) {
|
||||
status = _cairo_image_surface_set_attributes (mask, &mask_attr,
|
||||
dst_x + width / 2.,
|
||||
dst_y + height / 2.);
|
||||
|
|
@ -1031,9 +1083,7 @@ _cairo_image_surface_composite (cairo_operator_t op,
|
|||
mask_y + mask_attr.y_offset,
|
||||
dst_x, dst_y,
|
||||
width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
pixman_image_composite (_pixman_operator (op),
|
||||
src->pixman_image,
|
||||
NULL,
|
||||
|
|
@ -1045,7 +1095,7 @@ _cairo_image_surface_composite (cairo_operator_t op,
|
|||
width, height);
|
||||
}
|
||||
|
||||
if (! _cairo_operator_bounded_by_source (op))
|
||||
if (! _cairo_operator_bounded_by_source (op)) {
|
||||
status = _cairo_surface_composite_fixup_unbounded (&dst->base,
|
||||
&src_attr, src->width, src->height,
|
||||
mask ? &mask_attr : NULL,
|
||||
|
|
@ -1053,7 +1103,9 @@ _cairo_image_surface_composite (cairo_operator_t op,
|
|||
mask ? mask->height : 0,
|
||||
src_x, src_y,
|
||||
mask_x, mask_y,
|
||||
dst_x, dst_y, width, height);
|
||||
dst_x, dst_y, width, height,
|
||||
clip_region);
|
||||
}
|
||||
|
||||
CLEANUP_SURFACES:
|
||||
if (mask)
|
||||
|
|
@ -1078,7 +1130,7 @@ _cairo_image_surface_fill_rectangles (void *abstract_surface,
|
|||
pixman_rectangle16_t *pixman_rects = stack_rects;
|
||||
int i;
|
||||
|
||||
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (CAIRO_INJECT_FAULT ())
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
|
@ -1088,6 +1140,9 @@ _cairo_image_surface_fill_rectangles (void *abstract_surface,
|
|||
pixman_color.blue = color->blue_short;
|
||||
pixman_color.alpha = color->alpha_short;
|
||||
|
||||
status = _cairo_image_surface_set_clip_region (surface, NULL);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
if (num_rects > ARRAY_LENGTH (stack_rects)) {
|
||||
pixman_rects = _cairo_malloc_ab (num_rects, sizeof (pixman_rectangle16_t));
|
||||
if (unlikely (pixman_rects == NULL))
|
||||
|
|
@ -1101,7 +1156,8 @@ _cairo_image_surface_fill_rectangles (void *abstract_surface,
|
|||
pixman_rects[i].height = rects[i].height;
|
||||
}
|
||||
|
||||
/* XXX: pixman_fill_rectangles() should be implemented */
|
||||
/* XXX: pixman_fill_region() should be implemented */
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
if (! pixman_image_fill_rectangles (_pixman_operator (op),
|
||||
surface->pixman_image,
|
||||
&pixman_color,
|
||||
|
|
@ -1165,7 +1221,8 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
|
|||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_trapezoid_t *traps,
|
||||
int num_traps)
|
||||
int num_traps,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_surface_attributes_t attributes;
|
||||
cairo_image_surface_t *dst = abstract_dst;
|
||||
|
|
@ -1186,22 +1243,26 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
|
|||
* contained within the surface is bounded by [dst_x,dst_y,width,height];
|
||||
* the Cairo core code passes bounds based on the trapezoid extents.
|
||||
*
|
||||
* Currently the check surface->has_clip is needed for correct
|
||||
* Currently the check clip_region == NULL is needed for correct
|
||||
* functioning, since pixman_add_trapezoids() doesn't obey the
|
||||
* surface clip, which is a libpixman bug , but there's no harm in
|
||||
* falling through to the general case when the surface is clipped
|
||||
* since libpixman would have to generate an intermediate mask anyways.
|
||||
*/
|
||||
if (op == CAIRO_OPERATOR_ADD &&
|
||||
clip_region == NULL &&
|
||||
_cairo_pattern_is_opaque_solid (pattern) &&
|
||||
dst->base.content == CAIRO_CONTENT_ALPHA &&
|
||||
! dst->has_clip &&
|
||||
antialias != CAIRO_ANTIALIAS_NONE)
|
||||
{
|
||||
_pixman_add_trapezoids (dst->pixman_image, 0, 0, traps, num_traps);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
status = _cairo_image_surface_set_clip_region (dst, clip_region);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_pattern_acquire_surface (pattern, &dst->base,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
src_x, src_y, width, height,
|
||||
|
|
@ -1238,14 +1299,16 @@ _cairo_image_surface_composite_trapezoids (cairo_operator_t op,
|
|||
|
||||
pixman_image_unref (mask);
|
||||
|
||||
if (! _cairo_operator_bounded_by_mask (op))
|
||||
if (! _cairo_operator_bounded_by_mask (op)) {
|
||||
status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
|
||||
&attributes,
|
||||
src->width, src->height,
|
||||
width, height,
|
||||
src_x, src_y,
|
||||
0, 0,
|
||||
dst_x, dst_y, width, height);
|
||||
dst_x, dst_y, width, height,
|
||||
clip_region);
|
||||
}
|
||||
|
||||
CLEANUP_SOURCE:
|
||||
_cairo_pattern_release_surface (pattern, &src->base, &attributes);
|
||||
|
|
@ -1382,7 +1445,7 @@ _cairo_image_surface_span_renderer_finish (void *abstract_renderer)
|
|||
rects->dst.x, rects->dst.y,
|
||||
width, height);
|
||||
|
||||
if (! _cairo_operator_bounded_by_mask (renderer->op))
|
||||
if (! _cairo_operator_bounded_by_mask (renderer->op)) {
|
||||
status = _cairo_surface_composite_shape_fixup_unbounded (
|
||||
&dst->base,
|
||||
src_attributes,
|
||||
|
|
@ -1391,7 +1454,9 @@ _cairo_image_surface_span_renderer_finish (void *abstract_renderer)
|
|||
rects->src.x, rects->src.y,
|
||||
0, 0, /* mask.x, mask.y */
|
||||
rects->dst.x, rects->dst.y,
|
||||
rects->width, rects->height);
|
||||
rects->width, rects->height,
|
||||
dst->clip_region);
|
||||
}
|
||||
}
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
return _cairo_span_renderer_set_error (abstract_renderer,
|
||||
|
|
@ -1406,12 +1471,12 @@ _cairo_image_surface_check_span_renderer (cairo_operator_t op,
|
|||
cairo_antialias_t antialias,
|
||||
const cairo_composite_rectangles_t *rects)
|
||||
{
|
||||
return TRUE;
|
||||
(void) op;
|
||||
(void) pattern;
|
||||
(void) abstract_dst;
|
||||
(void) antialias;
|
||||
(void) rects;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static cairo_span_renderer_t *
|
||||
|
|
@ -1419,22 +1484,25 @@ _cairo_image_surface_create_span_renderer (cairo_operator_t op,
|
|||
const cairo_pattern_t *pattern,
|
||||
void *abstract_dst,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_composite_rectangles_t *rects)
|
||||
const cairo_composite_rectangles_t *rects,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_image_surface_t *dst = abstract_dst;
|
||||
cairo_image_surface_span_renderer_t *renderer
|
||||
= calloc(1, sizeof(*renderer));
|
||||
cairo_image_surface_span_renderer_t *renderer = calloc(1, sizeof(*renderer));
|
||||
cairo_status_t status;
|
||||
int width = rects->width;
|
||||
int height = rects->height;
|
||||
|
||||
status = _cairo_image_surface_set_clip_region (dst, clip_region);
|
||||
if (unlikely (status))
|
||||
return _cairo_span_renderer_create_in_error (status);
|
||||
|
||||
if (renderer == NULL)
|
||||
return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
renderer->base.destroy = _cairo_image_surface_span_renderer_destroy;
|
||||
renderer->base.finish = _cairo_image_surface_span_renderer_finish;
|
||||
renderer->base.render_row =
|
||||
_cairo_image_surface_span_renderer_render_row;
|
||||
renderer->base.render_row = _cairo_image_surface_span_renderer_render_row;
|
||||
renderer->op = op;
|
||||
renderer->pattern = pattern;
|
||||
renderer->antialias = antialias;
|
||||
|
|
@ -1475,21 +1543,7 @@ _cairo_image_surface_create_span_renderer (cairo_operator_t op,
|
|||
return &renderer->base;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_image_surface_set_clip_region (void *abstract_surface,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
cairo_image_surface_t *surface = (cairo_image_surface_t *) abstract_surface;
|
||||
|
||||
if (! pixman_image_set_clip_region32 (surface->pixman_image, region? ®ion->rgn : NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
surface->has_clip = region != NULL;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_image_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
|
|
@ -1500,7 +1554,7 @@ _cairo_image_surface_get_extents (void *abstract_surface,
|
|||
rectangle->width = surface->width;
|
||||
rectangle->height = surface->height;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -1512,18 +1566,6 @@ _cairo_image_surface_get_font_options (void *abstract_surface,
|
|||
cairo_font_options_set_hint_metrics (options, CAIRO_HINT_METRICS_ON);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_image_surface_reset (void *abstract_surface)
|
||||
{
|
||||
cairo_image_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_image_surface_set_clip_region (surface, NULL);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_surface_is_image:
|
||||
* @surface: a #cairo_surface_t
|
||||
|
|
@ -1554,8 +1596,6 @@ const cairo_surface_backend_t _cairo_image_surface_backend = {
|
|||
_cairo_image_surface_check_span_renderer,
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
_cairo_image_surface_set_clip_region,
|
||||
NULL, /* intersect_clip_path */
|
||||
_cairo_image_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
_cairo_image_surface_get_font_options,
|
||||
|
|
@ -1571,8 +1611,6 @@ const cairo_surface_backend_t _cairo_image_surface_backend = {
|
|||
NULL, /* show_glyphs */
|
||||
NULL, /* snapshot */
|
||||
NULL, /* is_similar */
|
||||
|
||||
_cairo_image_surface_reset
|
||||
};
|
||||
|
||||
/* A convenience function for when one needs to coerce an image
|
||||
|
|
@ -1600,7 +1638,8 @@ _cairo_image_surface_coerce (cairo_image_surface_t *surface,
|
|||
_cairo_pattern_init_for_surface (&pattern, &surface->base);
|
||||
status = _cairo_surface_paint (&clone->base,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
&pattern.base, NULL);
|
||||
&pattern.base,
|
||||
NULL);
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
|
||||
if (unlikely (status)) {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
#include "cairo-clip-private.h"
|
||||
|
||||
typedef enum {
|
||||
/* The 5 basic drawing operations. */
|
||||
|
|
@ -47,15 +48,6 @@ typedef enum {
|
|||
CAIRO_COMMAND_STROKE,
|
||||
CAIRO_COMMAND_FILL,
|
||||
CAIRO_COMMAND_SHOW_TEXT_GLYPHS,
|
||||
|
||||
/* Other junk. For most of these, we should be able to assert that
|
||||
* they never get called except as part of fallbacks for the 5
|
||||
* basic drawing operations (which we implement already so the
|
||||
* fallbacks should never get triggered). So the plan is to
|
||||
* eliminate as many of these as possible. */
|
||||
|
||||
CAIRO_COMMAND_INTERSECT_CLIP_PATH
|
||||
|
||||
} cairo_command_type_t;
|
||||
|
||||
typedef enum {
|
||||
|
|
@ -67,25 +59,23 @@ typedef enum {
|
|||
typedef struct _cairo_command_header {
|
||||
cairo_command_type_t type;
|
||||
cairo_meta_region_type_t region;
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_operator_t op;
|
||||
cairo_clip_t clip;
|
||||
} cairo_command_header_t;
|
||||
|
||||
typedef struct _cairo_command_paint {
|
||||
cairo_command_header_t header;
|
||||
cairo_operator_t op;
|
||||
cairo_pattern_union_t source;
|
||||
} cairo_command_paint_t;
|
||||
|
||||
typedef struct _cairo_command_mask {
|
||||
cairo_command_header_t header;
|
||||
cairo_operator_t op;
|
||||
cairo_pattern_union_t source;
|
||||
cairo_pattern_union_t mask;
|
||||
} cairo_command_mask_t;
|
||||
|
||||
typedef struct _cairo_command_stroke {
|
||||
cairo_command_header_t header;
|
||||
cairo_operator_t op;
|
||||
cairo_pattern_union_t source;
|
||||
cairo_path_fixed_t path;
|
||||
cairo_stroke_style_t style;
|
||||
|
|
@ -97,7 +87,6 @@ typedef struct _cairo_command_stroke {
|
|||
|
||||
typedef struct _cairo_command_fill {
|
||||
cairo_command_header_t header;
|
||||
cairo_operator_t op;
|
||||
cairo_pattern_union_t source;
|
||||
cairo_path_fixed_t path;
|
||||
cairo_fill_rule_t fill_rule;
|
||||
|
|
@ -107,7 +96,6 @@ typedef struct _cairo_command_fill {
|
|||
|
||||
typedef struct _cairo_command_show_text_glyphs {
|
||||
cairo_command_header_t header;
|
||||
cairo_operator_t op;
|
||||
cairo_pattern_union_t source;
|
||||
char *utf8;
|
||||
int utf8_len;
|
||||
|
|
@ -119,27 +107,14 @@ typedef struct _cairo_command_show_text_glyphs {
|
|||
cairo_scaled_font_t *scaled_font;
|
||||
} cairo_command_show_text_glyphs_t;
|
||||
|
||||
typedef struct _cairo_command_intersect_clip_path {
|
||||
cairo_command_header_t header;
|
||||
cairo_path_fixed_t *path_pointer;
|
||||
cairo_path_fixed_t path;
|
||||
cairo_fill_rule_t fill_rule;
|
||||
double tolerance;
|
||||
cairo_antialias_t antialias;
|
||||
} cairo_command_intersect_clip_path_t;
|
||||
|
||||
typedef union _cairo_command {
|
||||
cairo_command_header_t header;
|
||||
|
||||
/* The 5 basic drawing operations. */
|
||||
cairo_command_paint_t paint;
|
||||
cairo_command_mask_t mask;
|
||||
cairo_command_stroke_t stroke;
|
||||
cairo_command_fill_t fill;
|
||||
cairo_command_show_text_glyphs_t show_text_glyphs;
|
||||
|
||||
/* The other junk. */
|
||||
cairo_command_intersect_clip_path_t intersect_clip_path;
|
||||
} cairo_command_t;
|
||||
|
||||
typedef struct _cairo_meta_surface {
|
||||
|
|
@ -150,14 +125,15 @@ typedef struct _cairo_meta_surface {
|
|||
/* A meta-surface is logically unbounded, but when used as a
|
||||
* source we need to render it to an image, so we need a size at
|
||||
* which to create that image. */
|
||||
double width_pixels;
|
||||
double height_pixels;
|
||||
cairo_rectangle_t extents_pixels;
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_bool_t unbounded;
|
||||
|
||||
cairo_clip_t clip;
|
||||
|
||||
cairo_array_t commands;
|
||||
cairo_surface_t *commands_owner;
|
||||
|
||||
cairo_bool_t is_clipped;
|
||||
int replay_start_idx;
|
||||
} cairo_meta_surface_t;
|
||||
|
||||
|
|
@ -181,6 +157,11 @@ _cairo_meta_surface_replay_region (cairo_surface_t *surface,
|
|||
cairo_surface_t *target,
|
||||
cairo_meta_region_type_t region);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_meta_surface_get_bbox (cairo_meta_surface_t *meta,
|
||||
cairo_box_t *bbox,
|
||||
const cairo_matrix_t *transform);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_surface_is_meta (const cairo_surface_t *surface);
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,12 @@
|
|||
* that would have been obtained if the original operations applied to
|
||||
* the meta surface had instead been applied to the target surface.
|
||||
*
|
||||
* A meta surface is logically unbounded, i.e. it has no implicit constraint
|
||||
* on the size of the drawing surface. However, in practice this is rarely
|
||||
* useful as you wish to replay against a particular target surface with
|
||||
* known bounds. For this case, it is more efficient to specify the target
|
||||
* extents to the meta surface upon creation.
|
||||
*
|
||||
* The recording phase of the meta surface is careful to snapshot all
|
||||
* necessary objects (paths, patterns, etc.), in order to achieve
|
||||
* accurate replay. The efficiency of the meta surface could be
|
||||
|
|
@ -58,10 +64,13 @@
|
|||
* copy-on-write implementation for _cairo_surface_snapshot.
|
||||
*/
|
||||
|
||||
/* XXX Rename to recording surface */
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-analysis-surface-private.h"
|
||||
#include "cairo-meta-surface-private.h"
|
||||
#include "cairo-clip-private.h"
|
||||
#include "cairo-surface-wrapper-private.h"
|
||||
|
||||
typedef enum {
|
||||
CAIRO_META_REPLAY,
|
||||
|
|
@ -82,8 +91,8 @@ static const cairo_surface_backend_t cairo_meta_surface_backend;
|
|||
/**
|
||||
* cairo_meta_surface_create:
|
||||
* @content: the content of the meta surface
|
||||
* @width_pixels: width of the surface, in pixels
|
||||
* @height_pixels: height of the surface, in pixels
|
||||
* @extents_pixels: the extents to record in pixels, can be %NULL to record
|
||||
* unbounded operations.
|
||||
*
|
||||
* Creates a meta-surface which can be used to record all drawing operations
|
||||
* at the highest level (that is, the level of paint, mask, stroke, fill
|
||||
|
|
@ -105,50 +114,45 @@ static const cairo_surface_backend_t cairo_meta_surface_backend;
|
|||
* Since 1.10
|
||||
**/
|
||||
cairo_surface_t *
|
||||
cairo_meta_surface_create (cairo_content_t content,
|
||||
double width_pixels,
|
||||
double height_pixels)
|
||||
cairo_meta_surface_create (cairo_content_t content,
|
||||
const cairo_rectangle_t *extents)
|
||||
{
|
||||
cairo_meta_surface_t *meta;
|
||||
cairo_status_t status;
|
||||
|
||||
meta = malloc (sizeof (cairo_meta_surface_t));
|
||||
if (unlikely (meta == NULL))
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
||||
_cairo_surface_init (&meta->base, &cairo_meta_surface_backend,
|
||||
content);
|
||||
_cairo_surface_init (&meta->base, &cairo_meta_surface_backend, content);
|
||||
|
||||
meta->content = content;
|
||||
meta->width_pixels = width_pixels;
|
||||
meta->height_pixels = height_pixels;
|
||||
|
||||
/* unbounded -> 'infinite' extents */
|
||||
if (width_pixels < 0) {
|
||||
meta->extents.x = CAIRO_RECT_INT_MIN;
|
||||
meta->extents.width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
|
||||
} else {
|
||||
meta->extents.x = 0;
|
||||
if (ceil (width_pixels) > CAIRO_RECT_INT_MAX)
|
||||
meta->extents.width = CAIRO_RECT_INT_MAX;
|
||||
else
|
||||
meta->extents.width = ceil (width_pixels);
|
||||
}
|
||||
if (extents != NULL) {
|
||||
meta->extents_pixels = *extents;
|
||||
|
||||
if (height_pixels < 0) {
|
||||
meta->extents.y = CAIRO_RECT_INT_MIN;
|
||||
meta->extents.height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
|
||||
/* XXX check for overflow */
|
||||
meta->extents.x = floor (extents->x);
|
||||
meta->extents.y = floor (extents->y);
|
||||
meta->extents.width = ceil (extents->x + extents->width) - meta->extents.x;
|
||||
meta->extents.height = ceil (extents->y + extents->height) - meta->extents.y;
|
||||
|
||||
status = _cairo_clip_init_rectangle (&meta->clip, &meta->extents);
|
||||
if (unlikely (status)) {
|
||||
free (meta);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
meta->unbounded = FALSE;
|
||||
} else {
|
||||
meta->extents.y = 0;
|
||||
if (ceil (height_pixels) > CAIRO_RECT_INT_MAX)
|
||||
meta->extents.height = CAIRO_RECT_INT_MAX;
|
||||
else
|
||||
meta->extents.height = ceil (height_pixels);
|
||||
meta->unbounded = TRUE;
|
||||
_cairo_clip_init (&meta->clip);
|
||||
}
|
||||
|
||||
_cairo_array_init (&meta->commands, sizeof (cairo_command_t *));
|
||||
meta->commands_owner = NULL;
|
||||
|
||||
meta->is_clipped = FALSE;
|
||||
meta->replay_start_idx = 0;
|
||||
|
||||
return &meta->base;
|
||||
|
|
@ -161,14 +165,17 @@ _cairo_meta_surface_create_similar (void *abstract_surface,
|
|||
int width,
|
||||
int height)
|
||||
{
|
||||
return cairo_meta_surface_create (content, width, height);
|
||||
cairo_rectangle_t extents;
|
||||
extents.x = extents.y = 0;
|
||||
extents.width = width;
|
||||
extents.height = height;
|
||||
return cairo_meta_surface_create (content, &extents);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_meta_surface_finish (void *abstract_surface)
|
||||
{
|
||||
cairo_meta_surface_t *meta = abstract_surface;
|
||||
cairo_command_t *command;
|
||||
cairo_command_t **elements;
|
||||
int i, num_elements;
|
||||
|
||||
|
|
@ -180,11 +187,11 @@ _cairo_meta_surface_finish (void *abstract_surface)
|
|||
num_elements = meta->commands.num_elements;
|
||||
elements = _cairo_array_index (&meta->commands, 0);
|
||||
for (i = 0; i < num_elements; i++) {
|
||||
command = elements[i];
|
||||
cairo_command_t *command = elements[i];
|
||||
|
||||
_cairo_clip_reset (&command->header.clip);
|
||||
|
||||
switch (command->header.type) {
|
||||
|
||||
/* 5 basic drawing operations */
|
||||
|
||||
case CAIRO_COMMAND_PAINT:
|
||||
_cairo_pattern_fini_snapshot (&command->paint.source.base);
|
||||
free (command);
|
||||
|
|
@ -218,19 +225,13 @@ _cairo_meta_surface_finish (void *abstract_surface)
|
|||
free (command);
|
||||
break;
|
||||
|
||||
/* Other junk. */
|
||||
case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
|
||||
if (command->intersect_clip_path.path_pointer)
|
||||
_cairo_path_fixed_fini (&command->intersect_clip_path.path);
|
||||
free (command);
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
}
|
||||
}
|
||||
|
||||
_cairo_array_fini (&meta->commands);
|
||||
_cairo_clip_reset (&meta->clip);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -254,8 +255,12 @@ _cairo_meta_surface_acquire_source_image (void *abstract_surface,
|
|||
}
|
||||
|
||||
image = _cairo_image_surface_create_with_content (surface->content,
|
||||
ceil (surface->width_pixels),
|
||||
ceil (surface->height_pixels));
|
||||
surface->extents.width,
|
||||
surface->extents.height);
|
||||
|
||||
cairo_surface_set_device_offset (image,
|
||||
-surface->extents.x,
|
||||
-surface->extents.y);
|
||||
|
||||
status = cairo_meta_surface_replay (&surface->base, image);
|
||||
if (unlikely (status)) {
|
||||
|
|
@ -282,21 +287,30 @@ _cairo_meta_surface_release_source_image (void *abstract_surface,
|
|||
cairo_surface_destroy (&image->base);
|
||||
}
|
||||
|
||||
static void
|
||||
_draw_command_init (cairo_command_header_t *command,
|
||||
cairo_command_type_t type,
|
||||
cairo_meta_surface_t *meta)
|
||||
static cairo_status_t
|
||||
_command_init (cairo_meta_surface_t *meta,
|
||||
cairo_command_header_t *command,
|
||||
cairo_command_type_t type,
|
||||
cairo_operator_t op,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
command->type = type;
|
||||
command->op = op;
|
||||
command->region = CAIRO_META_REGION_ALL;
|
||||
command->extents = meta->extents;
|
||||
_cairo_clip_init_copy (&command->clip, clip);
|
||||
if (meta->clip.path != NULL)
|
||||
status = _cairo_clip_apply_clip (&command->clip, &meta->clip);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_meta_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
_cairo_meta_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_meta_surface_t *meta = abstract_surface;
|
||||
|
|
@ -306,8 +320,10 @@ _cairo_meta_surface_paint (void *abstract_surface,
|
|||
if (unlikely (command == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
_draw_command_init (&command->header, CAIRO_COMMAND_PAINT, meta);
|
||||
command->op = op;
|
||||
status = _command_init (meta,
|
||||
&command->header, CAIRO_COMMAND_PAINT, op, clip);
|
||||
if (unlikely (status))
|
||||
goto CLEANUP_COMMAND;
|
||||
|
||||
status = _cairo_pattern_init_snapshot (&command->source.base, source);
|
||||
if (unlikely (status))
|
||||
|
|
@ -320,7 +336,7 @@ _cairo_meta_surface_paint (void *abstract_surface,
|
|||
/* An optimisation that takes care to not replay what was done
|
||||
* before surface is cleared. We don't erase recorded commands
|
||||
* since we may have earlier snapshots of this surface. */
|
||||
if (op == CAIRO_OPERATOR_CLEAR && !meta->is_clipped)
|
||||
if (op == CAIRO_OPERATOR_CLEAR && clip == NULL)
|
||||
meta->replay_start_idx = meta->commands.num_elements;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -337,7 +353,7 @@ _cairo_meta_surface_mask (void *abstract_surface,
|
|||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_meta_surface_t *meta = abstract_surface;
|
||||
|
|
@ -347,8 +363,10 @@ _cairo_meta_surface_mask (void *abstract_surface,
|
|||
if (unlikely (command == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
_draw_command_init (&command->header, CAIRO_COMMAND_MASK, meta);
|
||||
command->op = op;
|
||||
status = _command_init (meta,
|
||||
&command->header, CAIRO_COMMAND_MASK, op, clip);
|
||||
if (unlikely (status))
|
||||
goto CLEANUP_COMMAND;
|
||||
|
||||
status = _cairo_pattern_init_snapshot (&command->source.base, source);
|
||||
if (unlikely (status))
|
||||
|
|
@ -383,7 +401,7 @@ _cairo_meta_surface_stroke (void *abstract_surface,
|
|||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_meta_surface_t *meta = abstract_surface;
|
||||
|
|
@ -393,8 +411,10 @@ _cairo_meta_surface_stroke (void *abstract_surface,
|
|||
if (unlikely (command == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
_draw_command_init (&command->header, CAIRO_COMMAND_STROKE, meta);
|
||||
command->op = op;
|
||||
status = _command_init (meta,
|
||||
&command->header, CAIRO_COMMAND_STROKE, op, clip);
|
||||
if (unlikely (status))
|
||||
goto CLEANUP_COMMAND;
|
||||
|
||||
status = _cairo_pattern_init_snapshot (&command->source.base, source);
|
||||
if (unlikely (status))
|
||||
|
|
@ -438,7 +458,7 @@ _cairo_meta_surface_fill (void *abstract_surface,
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_meta_surface_t *meta = abstract_surface;
|
||||
|
|
@ -448,8 +468,10 @@ _cairo_meta_surface_fill (void *abstract_surface,
|
|||
if (unlikely (command == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
_draw_command_init (&command->header, CAIRO_COMMAND_FILL, meta);
|
||||
command->op = op;
|
||||
status =_command_init (meta,
|
||||
&command->header, CAIRO_COMMAND_FILL, op, clip);
|
||||
if (unlikely (status))
|
||||
goto CLEANUP_COMMAND;
|
||||
|
||||
status = _cairo_pattern_init_snapshot (&command->source.base, source);
|
||||
if (unlikely (status))
|
||||
|
|
@ -496,7 +518,7 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface,
|
|||
int num_clusters,
|
||||
cairo_text_cluster_flags_t cluster_flags,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_meta_surface_t *meta = abstract_surface;
|
||||
|
|
@ -506,8 +528,11 @@ _cairo_meta_surface_show_text_glyphs (void *abstract_surface,
|
|||
if (unlikely (command == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
_draw_command_init (&command->header, CAIRO_COMMAND_SHOW_TEXT_GLYPHS, meta);
|
||||
command->op = op;
|
||||
status = _command_init (meta,
|
||||
&command->header, CAIRO_COMMAND_SHOW_TEXT_GLYPHS,
|
||||
op, clip);
|
||||
if (unlikely (status))
|
||||
goto CLEANUP_COMMAND;
|
||||
|
||||
status = _cairo_pattern_init_snapshot (&command->source.base, source);
|
||||
if (unlikely (status))
|
||||
|
|
@ -594,82 +619,31 @@ _cairo_meta_surface_snapshot (void *abstract_other)
|
|||
_cairo_surface_init (&meta->base, &cairo_meta_surface_backend,
|
||||
other->base.content);
|
||||
|
||||
meta->width_pixels = other->width_pixels;
|
||||
meta->height_pixels = other->height_pixels;
|
||||
meta->extents_pixels = other->extents_pixels;
|
||||
meta->extents = other->extents;
|
||||
meta->unbounded = other->unbounded;
|
||||
meta->replay_start_idx = other->replay_start_idx;
|
||||
meta->content = other->content;
|
||||
|
||||
_cairo_array_init_snapshot (&meta->commands, &other->commands);
|
||||
meta->commands_owner = cairo_surface_reference (&other->base);
|
||||
|
||||
_cairo_clip_init_copy (&meta->clip, &other->clip);
|
||||
|
||||
return &meta->base;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_meta_surface_intersect_clip_path (void *dst,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_meta_surface_t *meta = dst;
|
||||
cairo_command_intersect_clip_path_t *command;
|
||||
cairo_status_t status;
|
||||
|
||||
command = malloc (sizeof (cairo_command_intersect_clip_path_t));
|
||||
if (unlikely (command == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
command->header.type = CAIRO_COMMAND_INTERSECT_CLIP_PATH;
|
||||
command->header.region = CAIRO_META_REGION_ALL;
|
||||
|
||||
if (path) {
|
||||
status = _cairo_path_fixed_init_copy (&command->path, path);
|
||||
if (unlikely (status)) {
|
||||
free (command);
|
||||
return status;
|
||||
}
|
||||
command->path_pointer = &command->path;
|
||||
meta->is_clipped = TRUE;
|
||||
} else {
|
||||
command->path_pointer = NULL;
|
||||
meta->is_clipped = FALSE;
|
||||
}
|
||||
command->fill_rule = fill_rule;
|
||||
command->tolerance = tolerance;
|
||||
command->antialias = antialias;
|
||||
|
||||
status = _cairo_array_append (&meta->commands, &command);
|
||||
if (unlikely (status)) {
|
||||
if (path)
|
||||
_cairo_path_fixed_fini (&command->path);
|
||||
free (command);
|
||||
return status;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Currently, we're using as the "size" of a meta surface the largest
|
||||
* surface size against which the meta-surface is expected to be
|
||||
* replayed, (as passed in to cairo_meta_surface_create()).
|
||||
*/
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_meta_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
cairo_meta_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->width_pixels < 0 || surface->height_pixels < 0)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (surface->unbounded)
|
||||
return FALSE;
|
||||
|
||||
rectangle->x = 0;
|
||||
rectangle->y = 0;
|
||||
rectangle->width = ceil (surface->width_pixels);
|
||||
rectangle->height = ceil (surface->height_pixels);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
*rectangle = surface->extents;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -702,8 +676,6 @@ static const cairo_surface_backend_t cairo_meta_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
NULL, /* set_clip_region */
|
||||
_cairo_meta_surface_intersect_clip_path,
|
||||
_cairo_meta_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
|
|
@ -726,7 +698,6 @@ static const cairo_surface_backend_t cairo_meta_surface_backend = {
|
|||
_cairo_meta_surface_snapshot,
|
||||
|
||||
NULL, /* is_similar */
|
||||
NULL, /* reset */
|
||||
NULL, /* fill_stroke */
|
||||
NULL, /* create_solid_pattern_surface */
|
||||
NULL, /* can_repaint_solid_pattern_surface */
|
||||
|
|
@ -735,32 +706,12 @@ static const cairo_surface_backend_t cairo_meta_surface_backend = {
|
|||
_cairo_meta_surface_show_text_glyphs
|
||||
};
|
||||
|
||||
static cairo_path_fixed_t *
|
||||
_cairo_command_get_path (cairo_command_t *command)
|
||||
{
|
||||
switch (command->header.type) {
|
||||
case CAIRO_COMMAND_PAINT:
|
||||
case CAIRO_COMMAND_MASK:
|
||||
case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
|
||||
return NULL;
|
||||
case CAIRO_COMMAND_STROKE:
|
||||
return &command->stroke.path;
|
||||
case CAIRO_COMMAND_FILL:
|
||||
return &command->fill.path;
|
||||
case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
|
||||
return command->intersect_clip_path.path_pointer;
|
||||
}
|
||||
|
||||
ASSERT_NOT_REACHED;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_meta_surface_get_path (cairo_surface_t *surface,
|
||||
cairo_path_fixed_t *path)
|
||||
{
|
||||
cairo_meta_surface_t *meta;
|
||||
cairo_command_t *command, **elements;
|
||||
cairo_command_t **elements;
|
||||
int i, num_elements;
|
||||
cairo_int_status_t status;
|
||||
|
||||
|
|
@ -773,12 +724,11 @@ _cairo_meta_surface_get_path (cairo_surface_t *surface,
|
|||
num_elements = meta->commands.num_elements;
|
||||
elements = _cairo_array_index (&meta->commands, 0);
|
||||
for (i = meta->replay_start_idx; i < num_elements; i++) {
|
||||
command = elements[i];
|
||||
cairo_command_t *command = elements[i];
|
||||
|
||||
switch (command->header.type) {
|
||||
case CAIRO_COMMAND_PAINT:
|
||||
case CAIRO_COMMAND_MASK:
|
||||
case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
break;
|
||||
|
||||
|
|
@ -804,7 +754,9 @@ _cairo_meta_surface_get_path (cairo_surface_t *surface,
|
|||
}
|
||||
case CAIRO_COMMAND_FILL:
|
||||
{
|
||||
status = _cairo_path_fixed_append (path, &command->fill.path, CAIRO_DIRECTION_FORWARD);
|
||||
status = _cairo_path_fixed_append (path,
|
||||
&command->fill.path, CAIRO_DIRECTION_FORWARD,
|
||||
0, 0);
|
||||
break;
|
||||
}
|
||||
case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
|
||||
|
|
@ -827,6 +779,7 @@ _cairo_meta_surface_get_path (cairo_surface_t *surface,
|
|||
return _cairo_surface_set_error (surface, status);
|
||||
}
|
||||
|
||||
#define _clip(c) ((c)->header.clip.path ? &(c)->header.clip : NULL)
|
||||
static cairo_status_t
|
||||
_cairo_meta_surface_replay_internal (cairo_surface_t *surface,
|
||||
cairo_surface_t *target,
|
||||
|
|
@ -834,209 +787,155 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
|
|||
cairo_meta_region_type_t region)
|
||||
{
|
||||
cairo_meta_surface_t *meta;
|
||||
cairo_command_t *command, **elements;
|
||||
cairo_command_t **elements;
|
||||
int i, num_elements;
|
||||
cairo_int_status_t status, status2;
|
||||
cairo_clip_t clip, *old_clip;
|
||||
cairo_bool_t has_device_transform = _cairo_surface_has_device_transform (target);
|
||||
cairo_matrix_t *device_transform = &target->device_transform;
|
||||
cairo_path_fixed_t path_copy, *dev_path;
|
||||
cairo_int_status_t status;
|
||||
cairo_surface_wrapper_t wrapper;
|
||||
|
||||
if (surface->status)
|
||||
if (unlikely (surface->status))
|
||||
return surface->status;
|
||||
|
||||
if (target->status)
|
||||
if (unlikely (target->status))
|
||||
return _cairo_surface_set_error (surface, target->status);
|
||||
|
||||
_cairo_surface_wrapper_init (&wrapper, target);
|
||||
|
||||
meta = (cairo_meta_surface_t *) surface;
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_clip_init (&clip, target);
|
||||
old_clip = _cairo_surface_get_clip (target);
|
||||
|
||||
num_elements = meta->commands.num_elements;
|
||||
elements = _cairo_array_index (&meta->commands, 0);
|
||||
for (i = meta->replay_start_idx; i < num_elements; i++) {
|
||||
command = elements[i];
|
||||
cairo_command_t *command = elements[i];
|
||||
|
||||
if (type == CAIRO_META_REPLAY && region != CAIRO_META_REGION_ALL) {
|
||||
if (command->header.region != region)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* For all commands except intersect_clip_path, we have to
|
||||
* ensure the current clip gets set on the surface. */
|
||||
if (command->header.type != CAIRO_COMMAND_INTERSECT_CLIP_PATH) {
|
||||
status = _cairo_surface_set_clip (target, &clip);
|
||||
if (unlikely (status))
|
||||
break;
|
||||
}
|
||||
|
||||
dev_path = _cairo_command_get_path (command);
|
||||
if (dev_path && has_device_transform) {
|
||||
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
|
||||
if (unlikely (status))
|
||||
break;
|
||||
_cairo_path_fixed_transform (&path_copy, device_transform);
|
||||
dev_path = &path_copy;
|
||||
}
|
||||
|
||||
switch (command->header.type) {
|
||||
case CAIRO_COMMAND_PAINT:
|
||||
status = _cairo_surface_paint (target,
|
||||
command->paint.op,
|
||||
&command->paint.source.base, &command->header.extents);
|
||||
status = _cairo_surface_wrapper_paint (&wrapper,
|
||||
command->header.op,
|
||||
&command->paint.source.base,
|
||||
_clip (command));
|
||||
break;
|
||||
|
||||
case CAIRO_COMMAND_MASK:
|
||||
status = _cairo_surface_mask (target,
|
||||
command->mask.op,
|
||||
&command->mask.source.base,
|
||||
&command->mask.mask.base, &command->header.extents);
|
||||
status = _cairo_surface_wrapper_mask (&wrapper,
|
||||
command->header.op,
|
||||
&command->mask.source.base,
|
||||
&command->mask.mask.base,
|
||||
_clip (command));
|
||||
break;
|
||||
|
||||
case CAIRO_COMMAND_STROKE:
|
||||
{
|
||||
cairo_matrix_t dev_ctm = command->stroke.ctm;
|
||||
cairo_matrix_t dev_ctm_inverse = command->stroke.ctm_inverse;
|
||||
|
||||
if (has_device_transform) {
|
||||
cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform);
|
||||
cairo_matrix_multiply (&dev_ctm_inverse,
|
||||
&target->device_transform_inverse,
|
||||
&dev_ctm_inverse);
|
||||
}
|
||||
|
||||
status = _cairo_surface_stroke (target,
|
||||
command->stroke.op,
|
||||
&command->stroke.source.base,
|
||||
dev_path,
|
||||
&command->stroke.style,
|
||||
&dev_ctm,
|
||||
&dev_ctm_inverse,
|
||||
command->stroke.tolerance,
|
||||
command->stroke.antialias, &command->header.extents);
|
||||
status = _cairo_surface_wrapper_stroke (&wrapper,
|
||||
command->header.op,
|
||||
&command->stroke.source.base,
|
||||
&command->stroke.path,
|
||||
&command->stroke.style,
|
||||
&command->stroke.ctm,
|
||||
&command->stroke.ctm_inverse,
|
||||
command->stroke.tolerance,
|
||||
command->stroke.antialias,
|
||||
_clip (command));
|
||||
break;
|
||||
}
|
||||
case CAIRO_COMMAND_FILL:
|
||||
{
|
||||
cairo_command_t *stroke_command;
|
||||
|
||||
if (type != CAIRO_META_CREATE_REGIONS)
|
||||
stroke_command = (i < num_elements - 1) ? elements[i + 1] : NULL;
|
||||
else
|
||||
stroke_command = NULL;
|
||||
stroke_command = NULL;
|
||||
if (type != CAIRO_META_CREATE_REGIONS && i < num_elements - 1)
|
||||
stroke_command = elements[i + 1];
|
||||
|
||||
if (stroke_command != NULL &&
|
||||
type == CAIRO_META_REPLAY && region != CAIRO_META_REGION_ALL)
|
||||
type == CAIRO_META_REPLAY &&
|
||||
region != CAIRO_META_REGION_ALL)
|
||||
{
|
||||
if (stroke_command->header.region != region)
|
||||
stroke_command = NULL;
|
||||
}
|
||||
|
||||
if (stroke_command != NULL &&
|
||||
stroke_command->header.type == CAIRO_COMMAND_STROKE &&
|
||||
_cairo_path_fixed_is_equal (dev_path, _cairo_command_get_path (stroke_command))) {
|
||||
cairo_matrix_t dev_ctm;
|
||||
cairo_matrix_t dev_ctm_inverse;
|
||||
|
||||
dev_ctm = stroke_command->stroke.ctm;
|
||||
dev_ctm_inverse = stroke_command->stroke.ctm_inverse;
|
||||
|
||||
if (has_device_transform) {
|
||||
cairo_matrix_multiply (&dev_ctm, &dev_ctm, device_transform);
|
||||
cairo_matrix_multiply (&dev_ctm_inverse,
|
||||
&surface->device_transform_inverse,
|
||||
&dev_ctm_inverse);
|
||||
}
|
||||
|
||||
status = _cairo_surface_fill_stroke (target,
|
||||
command->fill.op,
|
||||
&command->fill.source.base,
|
||||
command->fill.fill_rule,
|
||||
command->fill.tolerance,
|
||||
command->fill.antialias,
|
||||
dev_path,
|
||||
stroke_command->stroke.op,
|
||||
&stroke_command->stroke.source.base,
|
||||
&stroke_command->stroke.style,
|
||||
&dev_ctm,
|
||||
&dev_ctm_inverse,
|
||||
stroke_command->stroke.tolerance,
|
||||
stroke_command->stroke.antialias,
|
||||
&stroke_command->header.extents);
|
||||
_cairo_path_fixed_is_equal (&command->fill.path,
|
||||
&stroke_command->stroke.path))
|
||||
{
|
||||
status = _cairo_surface_wrapper_fill_stroke (&wrapper,
|
||||
command->header.op,
|
||||
&command->fill.source.base,
|
||||
command->fill.fill_rule,
|
||||
command->fill.tolerance,
|
||||
command->fill.antialias,
|
||||
&command->fill.path,
|
||||
stroke_command->header.op,
|
||||
&stroke_command->stroke.source.base,
|
||||
&stroke_command->stroke.style,
|
||||
&stroke_command->stroke.ctm,
|
||||
&stroke_command->stroke.ctm_inverse,
|
||||
stroke_command->stroke.tolerance,
|
||||
stroke_command->stroke.antialias,
|
||||
_clip (command));
|
||||
i++;
|
||||
} else
|
||||
status = _cairo_surface_fill (target,
|
||||
command->fill.op,
|
||||
&command->fill.source.base,
|
||||
dev_path,
|
||||
command->fill.fill_rule,
|
||||
command->fill.tolerance,
|
||||
command->fill.antialias, &command->header.extents);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = _cairo_surface_wrapper_fill (&wrapper,
|
||||
command->header.op,
|
||||
&command->fill.source.base,
|
||||
&command->fill.path,
|
||||
command->fill.fill_rule,
|
||||
command->fill.tolerance,
|
||||
command->fill.antialias,
|
||||
_clip (command));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CAIRO_COMMAND_SHOW_TEXT_GLYPHS:
|
||||
{
|
||||
cairo_glyph_t *glyphs = command->show_text_glyphs.glyphs;
|
||||
cairo_glyph_t *dev_glyphs;
|
||||
int i, num_glyphs = command->show_text_glyphs.num_glyphs;
|
||||
cairo_glyph_t *glyphs_copy;
|
||||
int num_glyphs = command->show_text_glyphs.num_glyphs;
|
||||
|
||||
/* show_text_glyphs is special because _cairo_surface_show_text_glyphs is allowed
|
||||
* to modify the glyph array that's passed in. We must always
|
||||
* copy the array before handing it to the backend.
|
||||
*/
|
||||
dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
|
||||
if (unlikely (dev_glyphs == NULL)) {
|
||||
glyphs_copy = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
|
||||
if (unlikely (glyphs_copy == NULL)) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
break;
|
||||
}
|
||||
|
||||
if (has_device_transform) {
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
dev_glyphs[i] = glyphs[i];
|
||||
cairo_matrix_transform_point (device_transform,
|
||||
&dev_glyphs[i].x,
|
||||
&dev_glyphs[i].y);
|
||||
}
|
||||
} else {
|
||||
memcpy (dev_glyphs, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
|
||||
}
|
||||
memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
|
||||
|
||||
status = _cairo_surface_show_text_glyphs (target,
|
||||
command->show_text_glyphs.op,
|
||||
&command->show_text_glyphs.source.base,
|
||||
command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len,
|
||||
dev_glyphs, num_glyphs,
|
||||
command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
|
||||
command->show_text_glyphs.cluster_flags,
|
||||
command->show_text_glyphs.scaled_font, &command->header.extents);
|
||||
|
||||
free (dev_glyphs);
|
||||
status = _cairo_surface_wrapper_show_text_glyphs (&wrapper,
|
||||
command->header.op,
|
||||
&command->show_text_glyphs.source.base,
|
||||
command->show_text_glyphs.utf8, command->show_text_glyphs.utf8_len,
|
||||
glyphs_copy, num_glyphs,
|
||||
command->show_text_glyphs.clusters, command->show_text_glyphs.num_clusters,
|
||||
command->show_text_glyphs.cluster_flags,
|
||||
command->show_text_glyphs.scaled_font,
|
||||
_clip (command));
|
||||
free (glyphs_copy);
|
||||
break;
|
||||
}
|
||||
case CAIRO_COMMAND_INTERSECT_CLIP_PATH:
|
||||
/* XXX Meta surface clipping is broken and requires some
|
||||
* cairo-gstate.c rewriting. Work around it for now. */
|
||||
if (dev_path == NULL)
|
||||
_cairo_clip_reset (&clip);
|
||||
else
|
||||
status = _cairo_clip_clip (&clip, dev_path,
|
||||
command->intersect_clip_path.fill_rule,
|
||||
command->intersect_clip_path.tolerance,
|
||||
command->intersect_clip_path.antialias,
|
||||
target);
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
}
|
||||
|
||||
if (dev_path == &path_copy)
|
||||
_cairo_path_fixed_fini (&path_copy);
|
||||
|
||||
if (type == CAIRO_META_CREATE_REGIONS) {
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
command->header.region = CAIRO_META_REGION_NATIVE;
|
||||
} else if (status == CAIRO_INT_STATUS_IMAGE_FALLBACK) {
|
||||
command->header.region = CAIRO_META_REGION_IMAGE_FALLBACK;
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
} else {
|
||||
assert (_cairo_status_is_error (status));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1044,10 +943,14 @@ _cairo_meta_surface_replay_internal (cairo_surface_t *surface,
|
|||
break;
|
||||
}
|
||||
|
||||
_cairo_clip_reset (&clip);
|
||||
status2 = _cairo_surface_set_clip (target, old_clip);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = status2;
|
||||
/* free up any caches */
|
||||
for (i = meta->replay_start_idx; i < num_elements; i++) {
|
||||
cairo_command_t *command = elements[i];
|
||||
|
||||
_cairo_clip_drop_cache (&command->header.clip);
|
||||
}
|
||||
|
||||
_cairo_surface_wrapper_fini (&wrapper);
|
||||
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
}
|
||||
|
|
@ -1104,6 +1007,33 @@ _cairo_meta_surface_replay_region (cairo_surface_t *surface,
|
|||
region);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_meta_surface_get_ink_bbox (cairo_meta_surface_t *surface,
|
||||
cairo_box_t *bbox,
|
||||
const cairo_matrix_t *transform)
|
||||
{
|
||||
cairo_surface_t *null_surface;
|
||||
cairo_surface_t *analysis_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
null_surface = _cairo_null_surface_create (surface->content);
|
||||
analysis_surface = _cairo_analysis_surface_create (null_surface);
|
||||
cairo_surface_destroy (null_surface);
|
||||
|
||||
status = analysis_surface->status;
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (transform != NULL)
|
||||
_cairo_analysis_surface_set_ctm (analysis_surface, transform);
|
||||
|
||||
status = cairo_meta_surface_replay (&surface->base, analysis_surface);
|
||||
_cairo_analysis_surface_get_bounding_box (analysis_surface, bbox);
|
||||
cairo_surface_destroy (analysis_surface);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_meta_surface_ink_extents:
|
||||
* @surface: a #cairo_meta_surface_t
|
||||
|
|
@ -1114,7 +1044,7 @@ _cairo_meta_surface_replay_region (cairo_surface_t *surface,
|
|||
*
|
||||
* Measures the extents of the operations stored within the meta-surface.
|
||||
* This is useful to compute the required size of an image surface (or
|
||||
* equivalent) into which to replay the full sequence of drawing operaitions.
|
||||
* equivalent) into which to replay the full sequence of drawing operations.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
|
|
@ -1125,8 +1055,6 @@ cairo_meta_surface_ink_extents (cairo_surface_t *surface,
|
|||
double *width,
|
||||
double *height)
|
||||
{
|
||||
cairo_surface_t *null_surface;
|
||||
cairo_surface_t *analysis_surface;
|
||||
cairo_status_t status;
|
||||
cairo_box_t bbox;
|
||||
|
||||
|
|
@ -1137,17 +1065,11 @@ cairo_meta_surface_ink_extents (cairo_surface_t *surface,
|
|||
goto DONE;
|
||||
}
|
||||
|
||||
null_surface = _cairo_null_surface_create (CAIRO_CONTENT_COLOR_ALPHA);
|
||||
analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1);
|
||||
cairo_surface_destroy (null_surface);
|
||||
|
||||
status = analysis_surface->status;
|
||||
status = _meta_surface_get_ink_bbox ((cairo_meta_surface_t *) surface,
|
||||
&bbox,
|
||||
NULL);
|
||||
if (unlikely (status))
|
||||
goto DONE;
|
||||
|
||||
status = cairo_meta_surface_replay (surface, analysis_surface);
|
||||
_cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
|
||||
cairo_surface_destroy (analysis_surface);
|
||||
status = _cairo_surface_set_error (surface, status);
|
||||
|
||||
DONE:
|
||||
if (x0)
|
||||
|
|
@ -1159,3 +1081,19 @@ DONE:
|
|||
if (height)
|
||||
*height = _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_meta_surface_get_bbox (cairo_meta_surface_t *surface,
|
||||
cairo_box_t *bbox,
|
||||
const cairo_matrix_t *transform)
|
||||
{
|
||||
if (! surface->unbounded) {
|
||||
_cairo_box_from_rectangle (bbox, &surface->extents);
|
||||
if (transform != NULL)
|
||||
_cairo_matrix_transform_bounding_box_fixed (transform, bbox, NULL);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return _meta_surface_get_ink_bbox (surface, bbox, transform);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -716,26 +716,18 @@ _cairo_os2_surface_release_dest_image (void *abstract_surface
|
|||
DosReleaseMutexSem (local_os2_surface->hmtx_use_private_fields);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_os2_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
cairo_os2_surface_t *local_os2_surface;
|
||||
|
||||
local_os2_surface = (cairo_os2_surface_t *) abstract_surface;
|
||||
if ((!local_os2_surface) ||
|
||||
(local_os2_surface->base.backend != &cairo_os2_surface_backend))
|
||||
{
|
||||
/* Invalid parameter (wrong surface)! */
|
||||
return _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
rectangle->x = 0;
|
||||
rectangle->y = 0;
|
||||
rectangle->width = local_os2_surface->bitmap_info.cx;
|
||||
rectangle->height = local_os2_surface->bitmap_info.cy;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1327,8 +1319,6 @@ static const cairo_surface_backend_t cairo_os2_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
NULL, /* set_clip_region */
|
||||
NULL, /* intersect_clip_path */
|
||||
_cairo_os2_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
|
|
|
|||
|
|
@ -149,8 +149,6 @@ struct _cairo_paginated_surface_backend {
|
|||
cairo_private cairo_surface_t *
|
||||
_cairo_paginated_surface_create (cairo_surface_t *target,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height,
|
||||
const cairo_paginated_surface_backend_t *backend);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
|
|
|
|||
|
|
@ -48,14 +48,6 @@ typedef struct _cairo_paginated_surface {
|
|||
|
||||
cairo_content_t content;
|
||||
|
||||
/* XXX: These shouldn't actually exist. We inherit this ugliness
|
||||
* from _cairo_meta_surface_create. The width/height parameters
|
||||
* from that function also should not exist. The fix that will
|
||||
* allow us to remove all of these is to fix acquire_source_image
|
||||
* to pass an interest rectangle. */
|
||||
int width;
|
||||
int height;
|
||||
|
||||
/* Paginated-surface specific functions for the target */
|
||||
const cairo_paginated_surface_backend_t *backend;
|
||||
|
||||
|
|
@ -66,7 +58,6 @@ typedef struct _cairo_paginated_surface {
|
|||
|
||||
int page_num;
|
||||
cairo_bool_t page_is_blank;
|
||||
|
||||
} cairo_paginated_surface_t;
|
||||
|
||||
#endif /* CAIRO_PAGINATED_SURFACE_H */
|
||||
|
|
|
|||
|
|
@ -60,17 +60,36 @@ _cairo_paginated_surface_create_similar (void *abstract_surface,
|
|||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
return cairo_surface_create_similar (surface->target, content,
|
||||
width, height);
|
||||
cairo_rectangle_t rect;
|
||||
rect.x = rect.y = 0.;
|
||||
rect.width = width;
|
||||
rect.height = height;
|
||||
return cairo_meta_surface_create (content, &rect);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_create_meta_surface_for_target (cairo_surface_t *target,
|
||||
cairo_content_t content)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
if (_cairo_surface_get_extents (target, &rect)) {
|
||||
cairo_rectangle_t meta_extents;
|
||||
|
||||
meta_extents.x = rect.x;
|
||||
meta_extents.y = rect.y;
|
||||
meta_extents.width = rect.width;
|
||||
meta_extents.height = rect.height;
|
||||
|
||||
return cairo_meta_surface_create (content, &meta_extents);
|
||||
} else {
|
||||
return cairo_meta_surface_create (content, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX The integer width,height here should be doubles and all uses updated */
|
||||
cairo_surface_t *
|
||||
_cairo_paginated_surface_create (cairo_surface_t *target,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height,
|
||||
const cairo_paginated_surface_backend_t *backend)
|
||||
{
|
||||
cairo_paginated_surface_t *surface;
|
||||
|
|
@ -87,18 +106,15 @@ _cairo_paginated_surface_create (cairo_surface_t *target,
|
|||
|
||||
/* Override surface->base.type with target's type so we don't leak
|
||||
* evidence of the paginated wrapper out to the user. */
|
||||
surface->base.type = cairo_surface_get_type (target);
|
||||
surface->base.type = target->type;
|
||||
|
||||
surface->target = cairo_surface_reference (target);
|
||||
|
||||
surface->content = content;
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
|
||||
surface->backend = backend;
|
||||
|
||||
surface->meta = cairo_meta_surface_create (content, width, height);
|
||||
status = cairo_surface_status (surface->meta);
|
||||
surface->meta = _create_meta_surface_for_target (target, content);
|
||||
status = surface->meta->status;
|
||||
if (unlikely (status))
|
||||
goto FAIL_CLEANUP_SURFACE;
|
||||
|
||||
|
|
@ -132,31 +148,6 @@ _cairo_paginated_surface_get_target (cairo_surface_t *surface)
|
|||
return paginated_surface->target;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_paginated_surface_set_size (cairo_surface_t *surface,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
cairo_paginated_surface_t *paginated_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
assert (_cairo_surface_is_paginated (surface));
|
||||
|
||||
paginated_surface = (cairo_paginated_surface_t *) surface;
|
||||
|
||||
paginated_surface->width = width;
|
||||
paginated_surface->height = height;
|
||||
|
||||
cairo_surface_destroy (paginated_surface->meta);
|
||||
paginated_surface->meta = cairo_meta_surface_create (paginated_surface->content,
|
||||
width, height);
|
||||
status = cairo_surface_status (paginated_surface->meta);
|
||||
if (unlikely (status))
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_paginated_surface_finish (void *abstract_surface)
|
||||
{
|
||||
|
|
@ -168,18 +159,11 @@ _cairo_paginated_surface_finish (void *abstract_surface)
|
|||
status = cairo_surface_status (abstract_surface);
|
||||
}
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
cairo_surface_finish (surface->target);
|
||||
status = cairo_surface_status (surface->target);
|
||||
}
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
cairo_surface_finish (surface->meta);
|
||||
status = cairo_surface_status (surface->meta);
|
||||
}
|
||||
|
||||
cairo_surface_destroy (surface->target);
|
||||
|
||||
cairo_surface_finish (surface->meta);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = cairo_surface_status (surface->meta);
|
||||
cairo_surface_destroy (surface->meta);
|
||||
|
||||
return status;
|
||||
|
|
@ -210,13 +194,14 @@ _cairo_paginated_surface_acquire_source_image (void *abstract_surface,
|
|||
void **image_extra)
|
||||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
cairo_bool_t is_bounded;
|
||||
cairo_surface_t *image;
|
||||
cairo_status_t status;
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
status = _cairo_surface_get_extents (surface->target, &extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
is_bounded = _cairo_surface_get_extents (surface->target, &extents);
|
||||
if (! is_bounded)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
image = _cairo_paginated_surface_create_image_surface (surface,
|
||||
extents.width,
|
||||
|
|
@ -248,11 +233,11 @@ _paint_fallback_image (cairo_paginated_surface_t *surface,
|
|||
{
|
||||
double x_scale = surface->base.x_fallback_resolution / surface->target->x_resolution;
|
||||
double y_scale = surface->base.y_fallback_resolution / surface->target->y_resolution;
|
||||
cairo_matrix_t matrix;
|
||||
int x, y, width, height;
|
||||
cairo_status_t status;
|
||||
cairo_surface_t *image;
|
||||
cairo_surface_pattern_t pattern;
|
||||
cairo_clip_t clip;
|
||||
|
||||
x = rect->x;
|
||||
y = rect->y;
|
||||
|
|
@ -271,15 +256,21 @@ _paint_fallback_image (cairo_paginated_surface_t *surface,
|
|||
goto CLEANUP_IMAGE;
|
||||
|
||||
_cairo_pattern_init_for_surface (&pattern, image);
|
||||
cairo_matrix_init (&matrix, x_scale, 0, 0, y_scale, -x*x_scale, -y*y_scale);
|
||||
cairo_pattern_set_matrix (&pattern.base, &matrix);
|
||||
cairo_matrix_init (&pattern.base.matrix,
|
||||
x_scale, 0, 0, y_scale, -x*x_scale, -y*y_scale);
|
||||
/* the fallback should be rendered at native resolution, so disable
|
||||
* filtering (if possible) to avoid introducing potential artifacts. */
|
||||
pattern.base.filter = CAIRO_FILTER_NEAREST;
|
||||
|
||||
status = _cairo_clip_init_rectangle (&clip, rect);
|
||||
if (unlikely (status))
|
||||
goto CLEANUP_IMAGE;
|
||||
|
||||
status = _cairo_surface_paint (surface->target,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
&pattern.base, NULL);
|
||||
&pattern.base, &clip);
|
||||
|
||||
_cairo_clip_reset (&clip);
|
||||
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
CLEANUP_IMAGE:
|
||||
|
|
@ -295,12 +286,11 @@ _paint_page (cairo_paginated_surface_t *surface)
|
|||
cairo_status_t status;
|
||||
cairo_bool_t has_supported, has_page_fallback, has_finegrained_fallback;
|
||||
|
||||
if (surface->target->status)
|
||||
if (unlikely (surface->target->status))
|
||||
return surface->target->status;
|
||||
|
||||
analysis = _cairo_analysis_surface_create (surface->target,
|
||||
surface->width, surface->height);
|
||||
if (analysis->status)
|
||||
analysis = _cairo_analysis_surface_create (surface->target);
|
||||
if (unlikely (analysis->status))
|
||||
return _cairo_surface_set_error (surface->target, analysis->status);
|
||||
|
||||
surface->backend->set_paginated_mode (surface->target,
|
||||
|
|
@ -365,16 +355,19 @@ _paint_page (cairo_paginated_surface_t *surface)
|
|||
}
|
||||
|
||||
if (has_page_fallback) {
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_bool_t is_bounded;
|
||||
|
||||
surface->backend->set_paginated_mode (surface->target,
|
||||
CAIRO_PAGINATED_MODE_FALLBACK);
|
||||
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
rect.width = surface->width;
|
||||
rect.height = surface->height;
|
||||
status = _paint_fallback_image (surface, &rect);
|
||||
is_bounded = _cairo_surface_get_extents (surface->target, &extents);
|
||||
if (! is_bounded) {
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
status = _paint_fallback_image (surface, &extents);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
}
|
||||
|
|
@ -386,15 +379,6 @@ _paint_page (cairo_paginated_surface_t *surface)
|
|||
surface->backend->set_paginated_mode (surface->target,
|
||||
CAIRO_PAGINATED_MODE_FALLBACK);
|
||||
|
||||
/* Reset clip region before drawing the fall back images */
|
||||
status = _cairo_surface_intersect_clip_path (surface->target,
|
||||
NULL,
|
||||
CAIRO_FILL_RULE_WINDING,
|
||||
CAIRO_GSTATE_TOLERANCE_DEFAULT,
|
||||
CAIRO_ANTIALIAS_DEFAULT);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
region = _cairo_analysis_surface_get_unsupported (analysis);
|
||||
|
||||
num_rects = cairo_region_num_rectangles (region);
|
||||
|
|
@ -402,9 +386,7 @@ _paint_page (cairo_paginated_surface_t *surface)
|
|||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
|
||||
status = _paint_fallback_image (surface, &rect);
|
||||
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
}
|
||||
|
|
@ -445,7 +427,7 @@ _cairo_paginated_surface_copy_page (void *abstract_surface)
|
|||
|
||||
surface->page_num++;
|
||||
|
||||
/* XXX: It might make sense to add some suport here for calling
|
||||
/* XXX: It might make sense to add some support here for calling
|
||||
* cairo_surface_copy_page on the target surface. It would be an
|
||||
* optimization for the output, but the interaction with image
|
||||
* fallbacks gets tricky. For now, we just let the target see a
|
||||
|
|
@ -471,20 +453,19 @@ _cairo_paginated_surface_show_page (void *abstract_surface)
|
|||
return status;
|
||||
|
||||
cairo_surface_show_page (surface->target);
|
||||
status = cairo_surface_status (surface->target);
|
||||
status = surface->target->status;
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = cairo_surface_status (surface->meta);
|
||||
status = surface->meta->status;
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
cairo_surface_destroy (surface->meta);
|
||||
|
||||
surface->meta = cairo_meta_surface_create (surface->content,
|
||||
surface->width,
|
||||
surface->height);
|
||||
status = cairo_surface_status (surface->meta);
|
||||
surface->meta = _create_meta_surface_for_target (surface->target,
|
||||
surface->content);
|
||||
status = surface->meta->status;
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
|
|
@ -494,21 +475,7 @@ _cairo_paginated_surface_show_page (void *abstract_surface)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_paginated_surface_intersect_clip_path (void *abstract_surface,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
return _cairo_surface_intersect_clip_path (surface->meta,
|
||||
path, fill_rule,
|
||||
tolerance, antialias);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_paginated_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
|
|
@ -530,7 +497,7 @@ static cairo_int_status_t
|
|||
_cairo_paginated_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
|
|
@ -540,7 +507,7 @@ _cairo_paginated_surface_paint (void *abstract_surface,
|
|||
|
||||
surface->page_is_blank = FALSE;
|
||||
|
||||
return _cairo_surface_paint (surface->meta, op, source, NULL);
|
||||
return _cairo_surface_paint (surface->meta, op, source, clip);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -548,11 +515,17 @@ _cairo_paginated_surface_mask (void *abstract_surface,
|
|||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
return _cairo_surface_mask (surface->meta, op, source, mask, NULL);
|
||||
/* Optimize away erasing of nothing. */
|
||||
if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
surface->page_is_blank = FALSE;
|
||||
|
||||
return _cairo_surface_mask (surface->meta, op, source, mask, clip);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -565,7 +538,7 @@ _cairo_paginated_surface_stroke (void *abstract_surface,
|
|||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
|
|
@ -578,7 +551,8 @@ _cairo_paginated_surface_stroke (void *abstract_surface,
|
|||
return _cairo_surface_stroke (surface->meta, op, source,
|
||||
path, style,
|
||||
ctm, ctm_inverse,
|
||||
tolerance, antialias, NULL);
|
||||
tolerance, antialias,
|
||||
clip);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -589,7 +563,7 @@ _cairo_paginated_surface_fill (void *abstract_surface,
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
|
|
@ -601,7 +575,8 @@ _cairo_paginated_surface_fill (void *abstract_surface,
|
|||
|
||||
return _cairo_surface_fill (surface->meta, op, source,
|
||||
path, fill_rule,
|
||||
tolerance, antialias, NULL);
|
||||
tolerance, antialias,
|
||||
clip);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
|
|
@ -614,20 +589,19 @@ _cairo_paginated_surface_has_show_text_glyphs (void *abstract_surface)
|
|||
|
||||
static cairo_int_status_t
|
||||
_cairo_paginated_surface_show_text_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const char *utf8,
|
||||
int utf8_len,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
const cairo_text_cluster_t *clusters,
|
||||
int num_clusters,
|
||||
cairo_text_cluster_flags_t cluster_flags,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const char *utf8,
|
||||
int utf8_len,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
const cairo_text_cluster_t *clusters,
|
||||
int num_clusters,
|
||||
cairo_text_cluster_flags_t cluster_flags,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_paginated_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
|
||||
/* Optimize away erasing of nothing. */
|
||||
if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR)
|
||||
|
|
@ -635,24 +609,13 @@ _cairo_paginated_surface_show_text_glyphs (void *abstract_surface,
|
|||
|
||||
surface->page_is_blank = FALSE;
|
||||
|
||||
/* Since this is a "wrapping" surface, we're calling back into
|
||||
* _cairo_surface_show_text_glyphs from within a call to the same.
|
||||
* Since _cairo_surface_show_text_glyphs acquires a mutex, we release
|
||||
* and re-acquire the mutex around this nested call.
|
||||
*
|
||||
* Yes, this is ugly, but we consider it pragmatic as compared to
|
||||
* adding locking code to all 18 surface-backend-specific
|
||||
* show_glyphs functions, (which would get less testing and likely
|
||||
* lead to bugs).
|
||||
*/
|
||||
status = _cairo_surface_show_text_glyphs (surface->meta, op, source,
|
||||
utf8, utf8_len,
|
||||
glyphs, num_glyphs,
|
||||
clusters, num_clusters,
|
||||
cluster_flags,
|
||||
scaled_font, NULL);
|
||||
|
||||
return status;
|
||||
return _cairo_surface_show_text_glyphs (surface->meta, op, source,
|
||||
utf8, utf8_len,
|
||||
glyphs, num_glyphs,
|
||||
clusters, num_clusters,
|
||||
cluster_flags,
|
||||
scaled_font,
|
||||
clip);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
|
|
@ -679,8 +642,6 @@ static const cairo_surface_backend_t cairo_paginated_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
_cairo_paginated_surface_copy_page,
|
||||
_cairo_paginated_surface_show_page,
|
||||
NULL, /* set_clip_region */
|
||||
_cairo_paginated_surface_intersect_clip_path,
|
||||
_cairo_paginated_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
_cairo_paginated_surface_get_font_options,
|
||||
|
|
@ -695,7 +656,6 @@ static const cairo_surface_backend_t cairo_paginated_surface_backend = {
|
|||
NULL, /* show_glyphs */
|
||||
_cairo_paginated_surface_snapshot,
|
||||
NULL, /* is_similar */
|
||||
NULL, /* reset */
|
||||
NULL, /* fill_stroke */
|
||||
NULL, /* create_solid_pattern_surface */
|
||||
NULL, /* can_repaint_solid_pattern_surface */
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ _cairo_path_bounder_close_path (void *closure)
|
|||
* the control points of the curves, not the flattened path).
|
||||
*/
|
||||
void
|
||||
_cairo_path_fixed_approximate_clip_extents (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_approximate_clip_extents (const cairo_path_fixed_t *path,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_path_bounder_t bounder;
|
||||
|
|
@ -203,7 +203,7 @@ _cairo_path_fixed_approximate_clip_extents (cairo_path_fixed_t *path,
|
|||
* Bezier, but we continue to ignore winding.
|
||||
*/
|
||||
void
|
||||
_cairo_path_fixed_approximate_fill_extents (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_approximate_fill_extents (const cairo_path_fixed_t *path,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_path_bounder_t bounder;
|
||||
|
|
@ -229,9 +229,37 @@ _cairo_path_fixed_approximate_fill_extents (cairo_path_fixed_t *path,
|
|||
_cairo_path_bounder_fini (&bounder);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_path_fixed_fill_extents (const cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_path_bounder_t bounder;
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_path_bounder_init (&bounder);
|
||||
|
||||
status = _cairo_path_fixed_interpret_flat (path, CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_path_bounder_move_to,
|
||||
_cairo_path_bounder_line_to,
|
||||
_cairo_path_bounder_close_path,
|
||||
&bounder, tolerance);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
if (bounder.has_point) {
|
||||
_cairo_box_round_to_rectangle (&bounder.extents, extents);
|
||||
} else {
|
||||
extents->x = extents->y = 0;
|
||||
extents->width = extents->height = 0;
|
||||
}
|
||||
|
||||
_cairo_path_bounder_fini (&bounder);
|
||||
}
|
||||
|
||||
/* Adjusts the fill extents (above) by the device-space pen. */
|
||||
void
|
||||
_cairo_path_fixed_approximate_stroke_extents (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_approximate_stroke_extents (const cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
cairo_rectangle_int_t *extents)
|
||||
|
|
@ -268,8 +296,37 @@ _cairo_path_fixed_approximate_stroke_extents (cairo_path_fixed_t *path,
|
|||
_cairo_path_bounder_fini (&bounder);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_stroke_extents (const cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_traps_t traps;
|
||||
cairo_box_t bbox;
|
||||
cairo_status_t status;
|
||||
|
||||
_cairo_traps_init (&traps);
|
||||
|
||||
status = _cairo_path_fixed_stroke_to_traps (path,
|
||||
stroke_style,
|
||||
ctm,
|
||||
ctm_inverse,
|
||||
tolerance,
|
||||
&traps);
|
||||
|
||||
_cairo_traps_extents (&traps, &bbox);
|
||||
_cairo_traps_fini (&traps);
|
||||
|
||||
_cairo_box_round_to_rectangle (&bbox, extents);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_path_fixed_bounds (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_bounds (const cairo_path_fixed_t *path,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -125,12 +125,12 @@ _cairo_filler_close_path (void *closure)
|
|||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_path_fixed_fill_rectangle (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_fill_rectangle (const cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
cairo_traps_t *traps);
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_fill_to_traps (const cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_traps_t *traps)
|
||||
|
|
@ -138,6 +138,8 @@ _cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
|
|||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_filler_t filler;
|
||||
|
||||
traps->maybe_region = path->maybe_fill_region;
|
||||
|
||||
/* Before we do anything else, we use a special-case filler for
|
||||
* a device-axis aligned rectangle if possible. */
|
||||
status = _cairo_path_fixed_fill_rectangle (path, fill_rule, traps);
|
||||
|
|
@ -181,12 +183,15 @@ BAIL:
|
|||
* this function will return %CAIRO_INT_STATUS_UNSUPPORTED.
|
||||
*/
|
||||
static cairo_int_status_t
|
||||
_cairo_path_fixed_fill_rectangle (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_fill_rectangle (const cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
cairo_traps_t *traps)
|
||||
{
|
||||
cairo_box_t box;
|
||||
|
||||
if (! path->is_rectilinear)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (_cairo_path_fixed_is_box (path, &box)) {
|
||||
if (box.p1.x > box.p2.x) {
|
||||
cairo_fixed_t t;
|
||||
|
|
|
|||
|
|
@ -81,12 +81,26 @@ struct _cairo_path_fixed {
|
|||
cairo_point_t current_point;
|
||||
unsigned int has_current_point : 1;
|
||||
unsigned int has_curve_to : 1;
|
||||
unsigned int is_box : 1;
|
||||
unsigned int is_region : 1;
|
||||
unsigned int is_rectilinear : 1;
|
||||
unsigned int maybe_fill_region : 1;
|
||||
unsigned int is_empty_fill : 1;
|
||||
|
||||
cairo_path_buf_fixed_t buf;
|
||||
};
|
||||
|
||||
|
||||
cairo_private void
|
||||
_cairo_path_fixed_translate (cairo_path_fixed_t *path,
|
||||
cairo_fixed_t offx,
|
||||
cairo_fixed_t offy);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_path_fixed_append (cairo_path_fixed_t *path,
|
||||
const cairo_path_fixed_t *other,
|
||||
cairo_direction_t dir,
|
||||
cairo_fixed_t tx,
|
||||
cairo_fixed_t ty);
|
||||
|
||||
cairo_private unsigned long
|
||||
_cairo_path_fixed_hash (const cairo_path_fixed_t *path);
|
||||
|
||||
|
|
@ -98,14 +112,14 @@ _cairo_path_fixed_equal (const cairo_path_fixed_t *a,
|
|||
const cairo_path_fixed_t *b);
|
||||
|
||||
typedef struct _cairo_path_fixed_iter {
|
||||
cairo_path_buf_t *buf;
|
||||
const cairo_path_buf_t *buf;
|
||||
unsigned int n_op;
|
||||
unsigned int n_point;
|
||||
} cairo_path_fixed_iter_t;
|
||||
|
||||
cairo_private void
|
||||
_cairo_path_fixed_iter_init (cairo_path_fixed_iter_t *iter,
|
||||
cairo_path_fixed_t *path);
|
||||
const cairo_path_fixed_t *path);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_path_fixed_iter_is_fill_box (cairo_path_fixed_iter_t *_iter,
|
||||
|
|
@ -115,13 +129,19 @@ cairo_private cairo_bool_t
|
|||
_cairo_path_fixed_iter_at_end (const cairo_path_fixed_iter_t *iter);
|
||||
|
||||
static inline cairo_bool_t
|
||||
_cairo_path_fixed_is_region (cairo_path_fixed_t *path)
|
||||
_cairo_path_fixed_fill_is_empty (const cairo_path_fixed_t *path)
|
||||
{
|
||||
return path->is_empty_fill;
|
||||
}
|
||||
|
||||
static inline cairo_bool_t
|
||||
_cairo_path_fixed_maybe_fill_region (const cairo_path_fixed_t *path)
|
||||
{
|
||||
#if WATCH_PATH
|
||||
fprintf (stderr, "_cairo_path_fixed_is_region () = %s\n",
|
||||
path->is_region ? "true" : "false");
|
||||
fprintf (stderr, "_cairo_path_fixed_maybe_fill_region () = %s\n",
|
||||
path->maybe_fill_region ? "true" : "false");
|
||||
#endif
|
||||
return path->is_region;
|
||||
return path->maybe_fill_region;
|
||||
}
|
||||
|
||||
#endif /* CAIRO_PATH_FIXED_PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -96,25 +96,32 @@ _cairo_path_fixed_init (cairo_path_fixed_t *path)
|
|||
path->last_move_point = path->current_point;
|
||||
path->has_current_point = FALSE;
|
||||
path->has_curve_to = FALSE;
|
||||
path->is_region = TRUE;
|
||||
path->is_box = TRUE;
|
||||
path->is_rectilinear = TRUE;
|
||||
path->maybe_fill_region = TRUE;
|
||||
path->is_empty_fill = TRUE;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
|
||||
cairo_path_fixed_t *other)
|
||||
const cairo_path_fixed_t *other)
|
||||
{
|
||||
cairo_path_buf_t *buf, *other_buf;
|
||||
unsigned int num_points, num_ops, buf_size;
|
||||
|
||||
_cairo_path_fixed_init (path);
|
||||
VG (VALGRIND_MAKE_MEM_UNDEFINED (path, sizeof (cairo_path_fixed_t)));
|
||||
|
||||
cairo_list_init (&path->buf.base.link);
|
||||
|
||||
path->buf.base.op = path->buf.op;
|
||||
path->buf.base.points = path->buf.points;
|
||||
|
||||
path->current_point = other->current_point;
|
||||
path->has_current_point = other->has_current_point;
|
||||
path->last_move_point = other->last_move_point;
|
||||
path->has_current_point = other->has_current_point;
|
||||
path->has_curve_to = other->has_curve_to;
|
||||
path->is_box = other->is_box;
|
||||
path->is_region = other->is_region;
|
||||
path->is_rectilinear = other->is_rectilinear;
|
||||
path->maybe_fill_region = other->maybe_fill_region;
|
||||
path->is_empty_fill = other->is_empty_fill;
|
||||
|
||||
path->buf.base.num_ops = other->buf.base.num_ops;
|
||||
path->buf.base.num_points = other->buf.base.num_points;
|
||||
|
|
@ -214,9 +221,10 @@ _cairo_path_fixed_equal (const cairo_path_fixed_t *a,
|
|||
return TRUE;
|
||||
|
||||
/* use the flags to quickly differentiate based on contents */
|
||||
if (a->has_curve_to != b->has_curve_to ||
|
||||
a->is_region != b->is_region ||
|
||||
a->is_box != b->is_box)
|
||||
if (a->is_empty_fill != b->is_empty_fill ||
|
||||
a->has_curve_to != b->has_curve_to ||
|
||||
a->maybe_fill_region != b->maybe_fill_region ||
|
||||
a->is_rectilinear != b->is_rectilinear)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
|
@ -378,15 +386,16 @@ _cairo_path_fixed_move_to (cairo_path_fixed_t *path,
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (path->has_current_point && path->is_box) {
|
||||
if (path->has_current_point && path->is_rectilinear) {
|
||||
/* a move-to is first an implicit close */
|
||||
path->is_box = path->current_point.x == path->last_move_point.x ||
|
||||
path->current_point.y == path->last_move_point.y;
|
||||
path->is_region &= path->is_box;
|
||||
path->is_rectilinear = path->current_point.x == path->last_move_point.x ||
|
||||
path->current_point.y == path->last_move_point.y;
|
||||
path->maybe_fill_region &= path->is_rectilinear;
|
||||
}
|
||||
if (path->is_region) {
|
||||
path->is_region = _cairo_fixed_is_integer (x) &&
|
||||
_cairo_fixed_is_integer (y);
|
||||
if (path->maybe_fill_region) {
|
||||
path->maybe_fill_region =
|
||||
_cairo_fixed_is_integer (path->last_move_point.x) &&
|
||||
_cairo_fixed_is_integer (path->last_move_point.y);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -437,14 +446,18 @@ _cairo_path_fixed_line_to (cairo_path_fixed_t *path,
|
|||
status = _cairo_path_fixed_move_to (path, point.x, point.y);
|
||||
} else {
|
||||
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
|
||||
if (path->is_box) {
|
||||
path->is_box = path->current_point.x == x ||
|
||||
path->current_point.y == y;
|
||||
path->is_region &= path->is_box;
|
||||
if (path->is_rectilinear) {
|
||||
path->is_rectilinear = path->current_point.x == x ||
|
||||
path->current_point.y == y;
|
||||
path->maybe_fill_region &= path->is_rectilinear;
|
||||
}
|
||||
if (path->is_region) {
|
||||
path->is_region = _cairo_fixed_is_integer (x) &&
|
||||
_cairo_fixed_is_integer (y);
|
||||
if (path->maybe_fill_region) {
|
||||
path->maybe_fill_region = _cairo_fixed_is_integer (x) &&
|
||||
_cairo_fixed_is_integer (y);
|
||||
}
|
||||
if (path->is_empty_fill) {
|
||||
path->is_empty_fill = path->current_point.x == x &&
|
||||
path->current_point.y == y;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -495,9 +508,10 @@ _cairo_path_fixed_curve_to (cairo_path_fixed_t *path,
|
|||
|
||||
path->current_point = point[2];
|
||||
path->has_current_point = TRUE;
|
||||
path->is_empty_fill = FALSE;
|
||||
path->has_curve_to = TRUE;
|
||||
path->is_box = FALSE;
|
||||
path->is_region = FALSE;
|
||||
path->is_rectilinear = FALSE;
|
||||
path->maybe_fill_region = FALSE;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -732,49 +746,77 @@ _cairo_path_fixed_interpret (const cairo_path_fixed_t *path,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
typedef struct _cairo_path_fixed_append_closure {
|
||||
cairo_point_t offset;
|
||||
cairo_path_fixed_t *path;
|
||||
} cairo_path_fixed_append_closure_t;
|
||||
|
||||
static cairo_status_t
|
||||
_append_move_to (void *closure,
|
||||
_append_move_to (void *abstract_closure,
|
||||
const cairo_point_t *point)
|
||||
{
|
||||
return _cairo_path_fixed_move_to (closure, point->x, point->y);
|
||||
cairo_path_fixed_append_closure_t *closure = abstract_closure;
|
||||
|
||||
return _cairo_path_fixed_move_to (closure->path,
|
||||
point->x + closure->offset.x,
|
||||
point->y + closure->offset.y);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_append_line_to (void *closure,
|
||||
_append_line_to (void *abstract_closure,
|
||||
const cairo_point_t *point)
|
||||
{
|
||||
return _cairo_path_fixed_line_to (closure, point->x, point->y);
|
||||
cairo_path_fixed_append_closure_t *closure = abstract_closure;
|
||||
|
||||
return _cairo_path_fixed_line_to (closure->path,
|
||||
point->x + closure->offset.x,
|
||||
point->y + closure->offset.y);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_append_curve_to (void *closure,
|
||||
_append_curve_to (void *abstract_closure,
|
||||
const cairo_point_t *p0,
|
||||
const cairo_point_t *p1,
|
||||
const cairo_point_t *p2)
|
||||
{
|
||||
return _cairo_path_fixed_curve_to (closure,
|
||||
p0->x, p0->y,
|
||||
p1->x, p1->y,
|
||||
p2->x, p2->y);
|
||||
cairo_path_fixed_append_closure_t *closure = abstract_closure;
|
||||
|
||||
return _cairo_path_fixed_curve_to (closure->path,
|
||||
p0->x + closure->offset.x,
|
||||
p0->y + closure->offset.y,
|
||||
p1->x + closure->offset.x,
|
||||
p1->y + closure->offset.y,
|
||||
p2->x + closure->offset.x,
|
||||
p2->y + closure->offset.y);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_append_close_path (void *closure)
|
||||
_append_close_path (void *abstract_closure)
|
||||
{
|
||||
return _cairo_path_fixed_close_path (closure);
|
||||
cairo_path_fixed_append_closure_t *closure = abstract_closure;
|
||||
|
||||
return _cairo_path_fixed_close_path (closure->path);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_append (cairo_path_fixed_t *path,
|
||||
const cairo_path_fixed_t *other,
|
||||
cairo_direction_t dir)
|
||||
_cairo_path_fixed_append (cairo_path_fixed_t *path,
|
||||
const cairo_path_fixed_t *other,
|
||||
cairo_direction_t dir,
|
||||
cairo_fixed_t tx,
|
||||
cairo_fixed_t ty)
|
||||
{
|
||||
cairo_path_fixed_append_closure_t closure;
|
||||
|
||||
closure.path = path;
|
||||
closure.offset.x = tx;
|
||||
closure.offset.y = ty;
|
||||
|
||||
return _cairo_path_fixed_interpret (other, dir,
|
||||
_append_move_to,
|
||||
_append_line_to,
|
||||
_append_curve_to,
|
||||
_append_close_path,
|
||||
path);
|
||||
&closure);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -787,6 +829,13 @@ _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
|
|||
cairo_path_buf_t *buf;
|
||||
unsigned int i;
|
||||
|
||||
if (path->maybe_fill_region) {
|
||||
path->maybe_fill_region = _cairo_fixed_is_integer (offx) &&
|
||||
_cairo_fixed_is_integer (offy) &&
|
||||
_cairo_fixed_is_integer (scalex) &&
|
||||
_cairo_fixed_is_integer (scaley);
|
||||
}
|
||||
|
||||
cairo_path_foreach_buf_start (buf, path) {
|
||||
for (i = 0; i < buf->num_points; i++) {
|
||||
if (scalex != CAIRO_FIXED_ONE)
|
||||
|
|
@ -800,6 +849,36 @@ _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
|
|||
} cairo_path_foreach_buf_end (buf, path);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_path_fixed_translate (cairo_path_fixed_t *path,
|
||||
cairo_fixed_t offx,
|
||||
cairo_fixed_t offy)
|
||||
{
|
||||
cairo_path_buf_t *buf;
|
||||
unsigned int i;
|
||||
|
||||
if (offx == 0 && offy == 0)
|
||||
return;
|
||||
|
||||
if (path->maybe_fill_region &&
|
||||
! (_cairo_fixed_is_integer (offx) && _cairo_fixed_is_integer (offy)))
|
||||
{
|
||||
path->maybe_fill_region = FALSE;
|
||||
}
|
||||
|
||||
path->last_move_point.x += offx;
|
||||
path->last_move_point.y += offx;
|
||||
path->current_point.x += offx;
|
||||
path->current_point.y += offx;
|
||||
|
||||
cairo_path_foreach_buf_start (buf, path) {
|
||||
for (i = 0; i < buf->num_points; i++) {
|
||||
buf->points[i].x += offx;
|
||||
buf->points[i].y += offy;
|
||||
}
|
||||
} cairo_path_foreach_buf_end (buf, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_path_fixed_transform:
|
||||
* @path: a #cairo_path_fixed_t to be transformed
|
||||
|
|
@ -811,12 +890,14 @@ _cairo_path_fixed_offset_and_scale (cairo_path_fixed_t *path,
|
|||
**/
|
||||
void
|
||||
_cairo_path_fixed_transform (cairo_path_fixed_t *path,
|
||||
cairo_matrix_t *matrix)
|
||||
const cairo_matrix_t *matrix)
|
||||
{
|
||||
cairo_path_buf_t *buf;
|
||||
unsigned int i;
|
||||
double dx, dy;
|
||||
|
||||
/* XXX current_point, last_move_to */
|
||||
|
||||
if (matrix->yx == 0.0 && matrix->xy == 0.0) {
|
||||
/* Fast path for the common case of scale+transform */
|
||||
_cairo_path_fixed_offset_and_scale (path,
|
||||
|
|
@ -827,6 +908,7 @@ _cairo_path_fixed_transform (cairo_path_fixed_t *path,
|
|||
return;
|
||||
}
|
||||
|
||||
path->maybe_fill_region = FALSE;
|
||||
cairo_path_foreach_buf_start (buf, path) {
|
||||
for (i = 0; i < buf->num_points; i++) {
|
||||
dx = _cairo_fixed_to_double (buf->points[i].x);
|
||||
|
|
@ -841,20 +923,22 @@ _cairo_path_fixed_transform (cairo_path_fixed_t *path,
|
|||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_path_fixed_is_equal (cairo_path_fixed_t *path,
|
||||
cairo_path_fixed_t *other)
|
||||
_cairo_path_fixed_is_equal (const cairo_path_fixed_t *path,
|
||||
const cairo_path_fixed_t *other)
|
||||
{
|
||||
cairo_path_buf_t *path_buf, *other_buf;
|
||||
const cairo_path_buf_t *path_buf, *other_buf;
|
||||
|
||||
if (path->current_point.x != other->current_point.x ||
|
||||
path->current_point.y != other->current_point.y ||
|
||||
path->has_current_point != other->has_current_point ||
|
||||
path->has_curve_to != other->has_curve_to ||
|
||||
path->is_box != other->is_box ||
|
||||
path->is_region != other->is_region ||
|
||||
path->is_rectilinear != other->is_rectilinear ||
|
||||
path->maybe_fill_region != other->maybe_fill_region ||
|
||||
path->last_move_point.x != other->last_move_point.x ||
|
||||
path->last_move_point.y != other->last_move_point.y)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
other_buf = cairo_path_head (other);
|
||||
cairo_path_foreach_buf_start (path_buf, path) {
|
||||
|
|
@ -970,25 +1054,16 @@ _cairo_path_fixed_interpret_flat (const cairo_path_fixed_t *path,
|
|||
&flattener);
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_path_fixed_is_empty (cairo_path_fixed_t *path)
|
||||
{
|
||||
if (cairo_path_head (path)->num_ops == 0)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether the given path contains a single rectangle.
|
||||
*/
|
||||
cairo_bool_t
|
||||
_cairo_path_fixed_is_box (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_is_box (const cairo_path_fixed_t *path,
|
||||
cairo_box_t *box)
|
||||
{
|
||||
cairo_path_buf_t *buf = cairo_path_head (path);
|
||||
const cairo_path_buf_t *buf = cairo_path_head (path);
|
||||
|
||||
if (! path->is_box)
|
||||
if (! path->is_rectilinear)
|
||||
return FALSE;
|
||||
|
||||
/* Do we have the right number of ops? */
|
||||
|
|
@ -1058,12 +1133,12 @@ _cairo_path_fixed_is_box (cairo_path_fixed_t *path,
|
|||
* </programlisting></informalexample>
|
||||
*/
|
||||
cairo_bool_t
|
||||
_cairo_path_fixed_is_rectangle (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_is_rectangle (const cairo_path_fixed_t *path,
|
||||
cairo_box_t *box)
|
||||
{
|
||||
cairo_path_buf_t *buf;
|
||||
const cairo_path_buf_t *buf;
|
||||
|
||||
if (!_cairo_path_fixed_is_box (path, box))
|
||||
if (! _cairo_path_fixed_is_box (path, box))
|
||||
return FALSE;
|
||||
|
||||
buf = cairo_path_head (path);
|
||||
|
|
@ -1075,7 +1150,7 @@ _cairo_path_fixed_is_rectangle (cairo_path_fixed_t *path,
|
|||
|
||||
void
|
||||
_cairo_path_fixed_iter_init (cairo_path_fixed_iter_t *iter,
|
||||
cairo_path_fixed_t *path)
|
||||
const cairo_path_fixed_t *path)
|
||||
{
|
||||
iter->buf = cairo_path_head (path);
|
||||
iter->n_op = 0;
|
||||
|
|
|
|||
|
|
@ -38,10 +38,10 @@
|
|||
|
||||
typedef struct cairo_in_fill {
|
||||
double tolerance;
|
||||
cairo_bool_t on_edge;
|
||||
int winding;
|
||||
|
||||
cairo_fixed_t x, y;
|
||||
cairo_bool_t on_edge;
|
||||
|
||||
cairo_bool_t has_current_point;
|
||||
cairo_point_t current_point;
|
||||
|
|
@ -54,12 +54,12 @@ _cairo_in_fill_init (cairo_in_fill_t *in_fill,
|
|||
double x,
|
||||
double y)
|
||||
{
|
||||
in_fill->on_edge = FALSE;
|
||||
in_fill->winding = 0;
|
||||
in_fill->tolerance = tolerance;
|
||||
|
||||
in_fill->x = _cairo_fixed_from_double (x);
|
||||
in_fill->y = _cairo_fixed_from_double (y);
|
||||
in_fill->on_edge = FALSE;
|
||||
|
||||
in_fill->has_current_point = FALSE;
|
||||
in_fill->current_point.x = 0;
|
||||
|
|
@ -142,7 +142,7 @@ _cairo_in_fill_add_edge (cairo_in_fill_t *in_fill,
|
|||
return;
|
||||
|
||||
if ((p1->x <= in_fill->x && p2->x <= in_fill->x) ||
|
||||
edge_compare_for_y_against_x (p1, p2, in_fill->y, in_fill->x) <= 0)
|
||||
edge_compare_for_y_against_x (p1, p2, in_fill->y, in_fill->x) < 0)
|
||||
{
|
||||
in_fill->winding += dir;
|
||||
}
|
||||
|
|
@ -243,16 +243,19 @@ _cairo_in_fill_close_path (void *closure)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_path_fixed_in_fill (cairo_path_fixed_t *path,
|
||||
cairo_bool_t
|
||||
_cairo_path_fixed_in_fill (const cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
double x,
|
||||
double y,
|
||||
cairo_bool_t *is_inside)
|
||||
double y)
|
||||
{
|
||||
cairo_in_fill_t in_fill;
|
||||
cairo_status_t status;
|
||||
cairo_bool_t is_inside;
|
||||
|
||||
if (path->is_empty_fill)
|
||||
return FALSE;
|
||||
|
||||
_cairo_in_fill_init (&in_fill, tolerance, x, y);
|
||||
|
||||
|
|
@ -268,19 +271,21 @@ _cairo_path_fixed_in_fill (cairo_path_fixed_t *path,
|
|||
_cairo_in_fill_close_path (&in_fill);
|
||||
|
||||
if (in_fill.on_edge) {
|
||||
*is_inside = TRUE;
|
||||
is_inside = TRUE;
|
||||
} else switch (fill_rule) {
|
||||
case CAIRO_FILL_RULE_EVEN_ODD:
|
||||
*is_inside = in_fill.winding & 1;
|
||||
is_inside = in_fill.winding & 1;
|
||||
break;
|
||||
case CAIRO_FILL_RULE_WINDING:
|
||||
*is_inside = in_fill.winding != 0;
|
||||
is_inside = in_fill.winding != 0;
|
||||
break;
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
*is_inside = FALSE;
|
||||
is_inside = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
_cairo_in_fill_fini (&in_fill);
|
||||
|
||||
return is_inside;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1140,13 +1140,13 @@ _cairo_stroker_close_path (void *closure)
|
|||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_stroke_rectilinear (const cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
const cairo_matrix_t *ctm,
|
||||
cairo_traps_t *traps);
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_stroke_to_traps (const cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
|
|
@ -1737,7 +1737,7 @@ _cairo_rectilinear_stroker_close_path (void *closure)
|
|||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_stroke_rectilinear (const cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
const cairo_matrix_t *ctm,
|
||||
cairo_traps_t *traps)
|
||||
|
|
@ -1755,7 +1755,7 @@ _cairo_path_fixed_stroke_rectilinear (cairo_path_fixed_t *path,
|
|||
* UNSUPPORTED from _cairo_rectilinear_stroker_line_to if any
|
||||
* non-rectilinear line_to is encountered.
|
||||
*/
|
||||
if (path->has_curve_to)
|
||||
if (! path->is_rectilinear)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (stroke_style->line_join != CAIRO_LINE_JOIN_MITER)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
|
|
|||
|
|
@ -1686,10 +1686,6 @@ _cairo_pattern_acquire_surface_for_solid (const cairo_solid_pattern_t *patt
|
|||
pattern,
|
||||
dst))
|
||||
{
|
||||
status = _cairo_surface_reset (solid_surface_cache.cache[i].surface);
|
||||
if (unlikely (status))
|
||||
goto UNLOCK;
|
||||
|
||||
goto DONE;
|
||||
}
|
||||
|
||||
|
|
@ -1698,10 +1694,6 @@ _cairo_pattern_acquire_surface_for_solid (const cairo_solid_pattern_t *patt
|
|||
pattern,
|
||||
dst))
|
||||
{
|
||||
status = _cairo_surface_reset (solid_surface_cache.cache[i].surface);
|
||||
if (unlikely (status))
|
||||
goto UNLOCK;
|
||||
|
||||
goto DONE;
|
||||
}
|
||||
}
|
||||
|
|
@ -1717,11 +1709,6 @@ _cairo_pattern_acquire_surface_for_solid (const cairo_solid_pattern_t *patt
|
|||
dst))
|
||||
{
|
||||
/* Reuse the surface instead of evicting */
|
||||
|
||||
status = _cairo_surface_reset (surface);
|
||||
if (unlikely (status))
|
||||
goto EVICT;
|
||||
|
||||
status = _cairo_surface_repaint_solid_pattern_surface (dst, surface, pattern);
|
||||
if (unlikely (status))
|
||||
goto EVICT;
|
||||
|
|
@ -1738,14 +1725,21 @@ _cairo_pattern_acquire_surface_for_solid (const cairo_solid_pattern_t *patt
|
|||
if (surface == NULL) {
|
||||
/* Not cached, need to create new */
|
||||
surface = _cairo_surface_create_solid_pattern_surface (dst, pattern);
|
||||
if (surface->status) {
|
||||
if (surface == NULL) {
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
goto UNLOCK;
|
||||
}
|
||||
if (unlikely (surface->status)) {
|
||||
status = surface->status;
|
||||
goto UNLOCK;
|
||||
}
|
||||
|
||||
if (! _cairo_surface_is_similar (surface, dst, pattern->content)) {
|
||||
/* in the rare event of a substitute surface being returned (e.g.
|
||||
* malloc failure) don't cache the fallback surface */
|
||||
if (unlikely (! _cairo_surface_is_similar (surface,
|
||||
dst, pattern->content)))
|
||||
{
|
||||
/* In the rare event of a substitute surface being returned,
|
||||
* don't cache the fallback.
|
||||
*/
|
||||
*out = surface;
|
||||
goto NOCACHE;
|
||||
}
|
||||
|
|
@ -1953,6 +1947,7 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t *pat
|
|||
double pad;
|
||||
cairo_bool_t is_identity;
|
||||
cairo_bool_t is_empty;
|
||||
cairo_bool_t is_bounded;
|
||||
cairo_int_status_t status;
|
||||
|
||||
surface = cairo_surface_reference (pattern->surface);
|
||||
|
|
@ -2010,9 +2005,8 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t *pat
|
|||
cairo_surface_t *src;
|
||||
int w, h;
|
||||
|
||||
status = _cairo_surface_get_extents (surface, &extents);
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
is_bounded = _cairo_surface_get_extents (surface, &extents);
|
||||
assert (is_bounded);
|
||||
|
||||
status = _cairo_surface_clone_similar (dst, surface, content,
|
||||
extents.x, extents.y,
|
||||
|
|
@ -2045,8 +2039,13 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t *pat
|
|||
}
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
surface = cairo_surface_create_similar (dst, dst->content, w, h);
|
||||
if (surface->status) {
|
||||
surface = _cairo_surface_create_similar_solid (dst,
|
||||
dst->content, w, h,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
FALSE);
|
||||
if (surface == NULL)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (unlikely (surface->status)) {
|
||||
cairo_surface_destroy (src);
|
||||
return surface->status;
|
||||
}
|
||||
|
|
@ -2092,10 +2091,6 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t *pat
|
|||
attr->extend = CAIRO_EXTEND_REPEAT;
|
||||
}
|
||||
|
||||
status = _cairo_surface_get_extents (surface, &extents);
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
||||
/* We first transform the rectangle to the coordinate space of the
|
||||
* source surface so that we only need to clone that portion of the
|
||||
* surface that will be read.
|
||||
|
|
@ -2118,36 +2113,38 @@ _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t *pat
|
|||
sampled_area.x += tx;
|
||||
sampled_area.y += ty;
|
||||
|
||||
if (attr->extend != CAIRO_EXTEND_REPEAT) {
|
||||
/* Never acquire a larger area than the source itself */
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &sampled_area);
|
||||
} else {
|
||||
int trim = 0;
|
||||
if ( _cairo_surface_get_extents (surface, &extents)) {
|
||||
if (attr->extend != CAIRO_EXTEND_REPEAT) {
|
||||
/* Never acquire a larger area than the source itself */
|
||||
is_empty = _cairo_rectangle_intersect (&extents, &sampled_area);
|
||||
} else {
|
||||
int trim = 0;
|
||||
|
||||
if (sampled_area.x >= extents.x &&
|
||||
sampled_area.x + (int) sampled_area.width <= extents.x + (int) extents.width)
|
||||
{
|
||||
/* source is horizontally contained within extents, trim */
|
||||
extents.x = sampled_area.x;
|
||||
extents.width = sampled_area.width;
|
||||
trim |= 0x1;
|
||||
if (sampled_area.x >= extents.x &&
|
||||
sampled_area.x + (int) sampled_area.width <= extents.x + (int) extents.width)
|
||||
{
|
||||
/* source is horizontally contained within extents, trim */
|
||||
extents.x = sampled_area.x;
|
||||
extents.width = sampled_area.width;
|
||||
trim |= 0x1;
|
||||
}
|
||||
|
||||
if (sampled_area.y >= extents.y &&
|
||||
sampled_area.y + (int) sampled_area.height <= extents.y + (int) extents.height)
|
||||
{
|
||||
/* source is vertically contained within extents, trim */
|
||||
extents.y = sampled_area.y;
|
||||
extents.height = sampled_area.height;
|
||||
trim |= 0x2;
|
||||
}
|
||||
|
||||
if (trim == 0x3) {
|
||||
/* source is wholly contained within extents, drop the REPEAT */
|
||||
attr->extend = CAIRO_EXTEND_NONE;
|
||||
}
|
||||
|
||||
is_empty = extents.width == 0 || extents.height == 0;
|
||||
}
|
||||
|
||||
if (sampled_area.y >= extents.y &&
|
||||
sampled_area.y + (int) sampled_area.height <= extents.y + (int) extents.height)
|
||||
{
|
||||
/* source is vertically contained within extents, trim */
|
||||
extents.y = sampled_area.y;
|
||||
extents.height = sampled_area.height;
|
||||
trim |= 0x2;
|
||||
}
|
||||
|
||||
if (trim == 0x3) {
|
||||
/* source is wholly contained within extents, drop the REPEAT */
|
||||
attr->extend = CAIRO_EXTEND_NONE;
|
||||
}
|
||||
|
||||
is_empty = extents.width == 0 || extents.height == 0;
|
||||
}
|
||||
|
||||
/* XXX can we use is_empty? */
|
||||
|
|
@ -2237,7 +2234,7 @@ _cairo_pattern_acquire_surface (const cairo_pattern_t *pattern,
|
|||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (pattern->status) {
|
||||
if (unlikely (pattern->status)) {
|
||||
*surface_out = NULL;
|
||||
return pattern->status;
|
||||
}
|
||||
|
|
@ -2371,9 +2368,9 @@ _cairo_pattern_acquire_surfaces (const cairo_pattern_t *src,
|
|||
cairo_int_status_t status;
|
||||
cairo_pattern_union_t src_tmp;
|
||||
|
||||
if (src->status)
|
||||
if (unlikely (src->status))
|
||||
return src->status;
|
||||
if (mask && mask->status)
|
||||
if (unlikely (mask != NULL && mask->status))
|
||||
return mask->status;
|
||||
|
||||
/* If src and mask are both solid, then the mask alpha can be
|
||||
|
|
@ -2441,7 +2438,7 @@ _cairo_pattern_acquire_surfaces (const cairo_pattern_t *src,
|
|||
* "infinite" extents, though it would be possible to optimize these
|
||||
* with a little more work.
|
||||
**/
|
||||
cairo_status_t
|
||||
void
|
||||
_cairo_pattern_get_extents (const cairo_pattern_t *pattern,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
|
|
@ -2457,11 +2454,8 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
|
|||
double x1, y1, x2, y2;
|
||||
double pad;
|
||||
|
||||
status = _cairo_surface_get_extents (surface, &surface_extents);
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
if (! _cairo_surface_get_extents (surface, &surface_extents))
|
||||
goto UNBOUNDED;
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
/* The filter can effectively enlarge the extents of the
|
||||
* pattern, so extend as necessary.
|
||||
|
|
@ -2497,8 +2491,7 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
|
|||
|
||||
extents->x = x1; extents->width = x2 - x1;
|
||||
extents->y = y1; extents->height = y2 - y1;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return;
|
||||
}
|
||||
|
||||
/* XXX: We could optimize gradients with pattern->extend of NONE
|
||||
|
|
@ -2508,12 +2501,7 @@ _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
|
|||
|
||||
UNBOUNDED:
|
||||
/* unbounded patterns -> 'infinite' extents */
|
||||
extents->x = CAIRO_RECT_INT_MIN;
|
||||
extents->y = CAIRO_RECT_INT_MIN;
|
||||
extents->width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
|
||||
extents->height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
_cairo_unbounded_rectangle_init (extents);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2749,6 +2737,9 @@ _cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b)
|
|||
if (a->status || b->status)
|
||||
return FALSE;
|
||||
|
||||
if (a == b)
|
||||
return TRUE;
|
||||
|
||||
if (a->type != b->type)
|
||||
return FALSE;
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@
|
|||
#include "cairo-pdf.h"
|
||||
|
||||
#include "cairo-surface-private.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
#include "cairo-pdf-operators-private.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
|
||||
|
|
@ -174,6 +175,8 @@ struct _cairo_pdf_surface {
|
|||
cairo_bool_t is_knockout;
|
||||
} group_stream;
|
||||
|
||||
cairo_surface_clipper_t clipper;
|
||||
|
||||
cairo_pdf_operators_t pdf_operators;
|
||||
cairo_paginated_mode_t paginated_mode;
|
||||
cairo_bool_t select_pattern_gstate_saved;
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@
|
|||
#include "cairo-output-stream-private.h"
|
||||
#include "cairo-paginated-private.h"
|
||||
#include "cairo-scaled-font-subsets-private.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
#include "cairo-type3-glyph-surface-private.h"
|
||||
|
||||
#include <time.h>
|
||||
|
|
@ -243,6 +244,34 @@ _cairo_pdf_surface_set_size_internal (cairo_pdf_surface_t *surface,
|
|||
&surface->cairo_to_pdf);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_pdf_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = cairo_container_of (clipper,
|
||||
cairo_pdf_surface_t,
|
||||
clipper);
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (path == NULL) {
|
||||
_cairo_output_stream_printf (surface->output, "Q q\n");
|
||||
|
||||
surface->current_pattern_is_solid_color = FALSE;
|
||||
_cairo_pdf_operators_reset (&surface->pdf_operators);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
|
||||
double width,
|
||||
|
|
@ -313,6 +342,9 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
|
|||
surface->current_operator = CAIRO_OPERATOR_OVER;
|
||||
surface->header_emitted = FALSE;
|
||||
|
||||
_cairo_surface_clipper_init (&surface->clipper,
|
||||
_cairo_pdf_surface_clipper_intersect_clip_path);
|
||||
|
||||
_cairo_pdf_operators_init (&surface->pdf_operators,
|
||||
surface->output,
|
||||
&surface->cairo_to_pdf,
|
||||
|
|
@ -325,7 +357,6 @@ _cairo_pdf_surface_create_for_stream_internal (cairo_output_stream_t *output,
|
|||
surface->paginated_surface = _cairo_paginated_surface_create (
|
||||
&surface->base,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
width, height,
|
||||
&cairo_pdf_surface_paginated_backend);
|
||||
|
||||
status = surface->paginated_surface->status;
|
||||
|
|
@ -572,11 +603,6 @@ cairo_pdf_surface_set_size (cairo_surface_t *surface,
|
|||
_cairo_pdf_surface_set_size_internal (pdf_surface,
|
||||
width_in_points,
|
||||
height_in_points);
|
||||
status = _cairo_paginated_surface_set_size (pdf_surface->paginated_surface,
|
||||
width_in_points,
|
||||
height_in_points);
|
||||
if (unlikely (status))
|
||||
status = _cairo_surface_set_error (surface, status);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -981,9 +1007,9 @@ _get_jpx_image_info (cairo_surface_t *source,
|
|||
|
||||
static cairo_int_status_t
|
||||
_get_jpeg_image_info (cairo_surface_t *source,
|
||||
cairo_image_info_t *info,
|
||||
const unsigned char **mime_data,
|
||||
unsigned int *mime_data_length)
|
||||
cairo_image_info_t *info,
|
||||
const unsigned char **mime_data,
|
||||
unsigned int *mime_data_length)
|
||||
{
|
||||
cairo_surface_get_mime_data (source, CAIRO_MIME_TYPE_JPEG,
|
||||
mime_data, mime_data_length);
|
||||
|
|
@ -998,52 +1024,48 @@ _get_source_surface_size (cairo_surface_t *source,
|
|||
int *width,
|
||||
int *height)
|
||||
{
|
||||
cairo_image_surface_t *image;
|
||||
void *image_extra;
|
||||
cairo_status_t status;
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_image_info_t info;
|
||||
const unsigned char *mime_data;
|
||||
unsigned int mime_data_length;
|
||||
|
||||
if (_cairo_surface_is_meta (source)) {
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_meta_surface_t *meta_surface = (cairo_meta_surface_t *) source;
|
||||
cairo_box_t bbox;
|
||||
|
||||
status = _cairo_surface_get_extents (source, &extents);
|
||||
status = _cairo_meta_surface_get_bbox (meta_surface, &bbox, NULL);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_box_round_to_rectangle (&bbox, &extents);
|
||||
|
||||
*width = extents.width;
|
||||
*height = extents.height;
|
||||
|
||||
return status;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
status = _get_jpx_image_info (source, &info, &mime_data, &mime_data_length);
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
*width = info.width;
|
||||
*height = info.height;
|
||||
} else if (_cairo_status_is_error (status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = _get_jpeg_image_info (source, &info, &mime_data, &mime_data_length);
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
*width = info.width;
|
||||
*height = info.height;
|
||||
} else if (_cairo_status_is_error (status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = _cairo_surface_acquire_source_image (source, &image, &image_extra);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
if (! _cairo_surface_get_extents (source, &extents))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
*width = image->width;
|
||||
*height = image->height;
|
||||
*width = extents.width;
|
||||
*height = extents.height;
|
||||
|
||||
_cairo_surface_release_source_image (source, image, image_extra);
|
||||
|
||||
return status;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
@ -1123,7 +1145,7 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t *surface,
|
|||
static cairo_status_t
|
||||
_cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_rectangle_int_t *extents,
|
||||
cairo_clip_t *clip,
|
||||
cairo_pdf_resource_t *pattern_res,
|
||||
cairo_pdf_resource_t *gstate_res)
|
||||
{
|
||||
|
|
@ -1182,8 +1204,8 @@ _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t *surface,
|
|||
|
||||
pdf_pattern.width = surface->width;
|
||||
pdf_pattern.height = surface->height;
|
||||
if (extents) {
|
||||
pdf_pattern.extents = *extents;
|
||||
if (clip != NULL) {
|
||||
pdf_pattern.extents = clip->path->extents;
|
||||
} else {
|
||||
pdf_pattern.extents.x = 0;
|
||||
pdf_pattern.extents.y = 0;
|
||||
|
|
@ -1540,15 +1562,6 @@ _cairo_pdf_surface_close_content_stream (cairo_pdf_surface_t *surface)
|
|||
return _cairo_output_stream_get_status (surface->output);
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_pdf_surface_create_similar (void *abstract_surface,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
return cairo_meta_surface_create (content, width, height);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_pdf_source_surface_entry_pluck (void *entry, void *closure)
|
||||
{
|
||||
|
|
@ -1653,6 +1666,8 @@ _cairo_pdf_surface_finish (void *abstract_surface)
|
|||
surface->font_subsets = NULL;
|
||||
}
|
||||
|
||||
_cairo_surface_clipper_reset (&surface->clipper);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -2090,7 +2105,7 @@ _cairo_pdf_surface_emit_padded_image_surface (cairo_pdf_surface_t *surface,
|
|||
return status;
|
||||
|
||||
pad_image = &image->base;
|
||||
if (cairo_pattern_get_extend (&pattern->base) == CAIRO_EXTEND_PAD) {
|
||||
if (pattern->base.extend == CAIRO_EXTEND_PAD) {
|
||||
cairo_box_t box;
|
||||
cairo_rectangle_int_t rect;
|
||||
cairo_surface_pattern_t pad_pattern;
|
||||
|
|
@ -2121,7 +2136,8 @@ _cairo_pdf_surface_emit_padded_image_surface (cairo_pdf_surface_t *surface,
|
|||
0, 0,
|
||||
0, 0,
|
||||
rect.width,
|
||||
rect.height);
|
||||
rect.height,
|
||||
NULL);
|
||||
_cairo_pattern_fini (&pad_pattern.base);
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
|
@ -2173,19 +2189,18 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
|
|||
{
|
||||
double old_width, old_height;
|
||||
cairo_paginated_mode_t old_paginated_mode;
|
||||
cairo_clip_t *old_clip;
|
||||
cairo_rectangle_int_t meta_extents;
|
||||
cairo_bool_t is_bounded;
|
||||
cairo_status_t status;
|
||||
int alpha = 0;
|
||||
|
||||
status = _cairo_surface_get_extents (meta_surface, &meta_extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
is_bounded = _cairo_surface_get_extents (meta_surface, &meta_extents);
|
||||
assert (is_bounded);
|
||||
|
||||
old_width = surface->width;
|
||||
old_height = surface->height;
|
||||
old_paginated_mode = surface->paginated_mode;
|
||||
old_clip = _cairo_surface_get_clip (&surface->base);
|
||||
|
||||
_cairo_pdf_surface_set_size_internal (surface,
|
||||
meta_extents.width,
|
||||
meta_extents.height);
|
||||
|
|
@ -2217,10 +2232,6 @@ _cairo_pdf_surface_emit_meta_surface (cairo_pdf_surface_t *surface,
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_surface_set_clip (&surface->base, old_clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_pdf_surface_close_content_stream (surface);
|
||||
|
||||
_cairo_pdf_surface_set_size_internal (surface,
|
||||
|
|
@ -2264,7 +2275,7 @@ _cairo_pdf_surface_emit_surface_pattern (cairo_pdf_surface_t *surface,
|
|||
int bbox_x, bbox_y;
|
||||
char draw_surface[200];
|
||||
|
||||
if (cairo_pattern_get_extend (&pattern->base) == CAIRO_EXTEND_PAD &&
|
||||
if (pattern->base.extend == CAIRO_EXTEND_PAD &&
|
||||
! _cairo_surface_is_meta (pattern->surface))
|
||||
{
|
||||
status = _cairo_pdf_surface_emit_padded_image_surface (surface,
|
||||
|
|
@ -3249,7 +3260,7 @@ _cairo_pdf_surface_select_operator (cairo_pdf_surface_t *surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (status)
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
|
|
@ -3405,7 +3416,7 @@ _cairo_pdf_surface_show_page (void *abstract_surface)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_pdf_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
|
|
@ -3421,32 +3432,7 @@ _cairo_pdf_surface_get_extents (void *abstract_surface,
|
|||
rectangle->width = (int) ceil (surface->width);
|
||||
rectangle->height = (int) ceil (surface->height);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_pdf_surface_intersect_clip_path (void *abstract_surface,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (path == NULL) {
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->output, "Q q\n");
|
||||
surface->current_pattern_is_solid_color = FALSE;
|
||||
_cairo_pdf_operators_reset (&surface->pdf_operators);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return _cairo_pdf_operators_clip (&surface->pdf_operators, path, fill_rule);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -5227,7 +5213,7 @@ static cairo_int_status_t
|
|||
_cairo_pdf_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
|
@ -5244,17 +5230,21 @@ _cairo_pdf_surface_paint (void *abstract_surface,
|
|||
|
||||
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
pattern_res.id = 0;
|
||||
gstate_res.id = 0;
|
||||
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, extents,
|
||||
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, clip,
|
||||
&pattern_res, &gstate_res);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_pdf_surface_select_operator (surface, op);
|
||||
if (status)
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (gstate_res.id != 0) {
|
||||
|
|
@ -5292,7 +5282,8 @@ _cairo_pdf_surface_paint (void *abstract_surface,
|
|||
gstate_res.id,
|
||||
group->group_res.id);
|
||||
} else {
|
||||
status = _cairo_pdf_surface_select_pattern (surface, source, pattern_res, FALSE);
|
||||
status = _cairo_pdf_surface_select_pattern (surface, source,
|
||||
pattern_res, FALSE);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
|
|
@ -5313,7 +5304,7 @@ _cairo_pdf_surface_mask (void *abstract_surface,
|
|||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
cairo_pdf_smask_group_t *group;
|
||||
|
|
@ -5341,6 +5332,10 @@ _cairo_pdf_surface_mask (void *abstract_surface,
|
|||
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
|
||||
assert (_cairo_pdf_surface_operation_supported (surface, op, mask));
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
group = _cairo_pdf_surface_create_smask_group (surface);
|
||||
if (unlikely (group == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
|
@ -5381,7 +5376,7 @@ _cairo_pdf_surface_mask (void *abstract_surface,
|
|||
return status;
|
||||
|
||||
status = _cairo_pdf_surface_select_operator (surface, op);
|
||||
if (status)
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->output,
|
||||
|
|
@ -5402,7 +5397,7 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
|
|||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
|
@ -5414,17 +5409,21 @@ _cairo_pdf_surface_stroke (void *abstract_surface,
|
|||
|
||||
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
pattern_res.id = 0;
|
||||
gstate_res.id = 0;
|
||||
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, extents,
|
||||
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, clip,
|
||||
&pattern_res, &gstate_res);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_pdf_surface_select_operator (surface, op);
|
||||
if (status)
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (gstate_res.id != 0) {
|
||||
|
|
@ -5499,7 +5498,7 @@ _cairo_pdf_surface_fill (void *abstract_surface,
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
|
@ -5516,17 +5515,21 @@ _cairo_pdf_surface_fill (void *abstract_surface,
|
|||
|
||||
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
pattern_res.id = 0;
|
||||
gstate_res.id = 0;
|
||||
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, extents,
|
||||
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, clip,
|
||||
&pattern_res, &gstate_res);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_pdf_surface_select_operator (surface, op);
|
||||
if (status)
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (gstate_res.id != 0) {
|
||||
|
|
@ -5604,7 +5607,7 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
|
|||
cairo_matrix_t *stroke_ctm_inverse,
|
||||
double stroke_tolerance,
|
||||
cairo_antialias_t stroke_antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
|
@ -5632,14 +5635,18 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
|
|||
if (fill_op != stroke_op)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_pdf_surface_select_operator (surface, fill_op);
|
||||
if (status)
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
fill_pattern_res.id = 0;
|
||||
gstate_res.id = 0;
|
||||
status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source,
|
||||
extents,
|
||||
clip,
|
||||
&fill_pattern_res,
|
||||
&gstate_res);
|
||||
if (unlikely (status))
|
||||
|
|
@ -5651,7 +5658,7 @@ _cairo_pdf_surface_fill_stroke (void *abstract_surface,
|
|||
gstate_res.id = 0;
|
||||
status = _cairo_pdf_surface_add_pdf_pattern (surface,
|
||||
stroke_source,
|
||||
extents,
|
||||
clip,
|
||||
&stroke_pattern_res,
|
||||
&gstate_res);
|
||||
if (unlikely (status))
|
||||
|
|
@ -5705,7 +5712,7 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
|
|||
int num_clusters,
|
||||
cairo_text_cluster_flags_t cluster_flags,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_pdf_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
|
@ -5717,17 +5724,21 @@ _cairo_pdf_surface_show_text_glyphs (void *abstract_surface,
|
|||
|
||||
assert (_cairo_pdf_surface_operation_supported (surface, op, source));
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
pattern_res.id = 0;
|
||||
gstate_res.id = 0;
|
||||
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, extents,
|
||||
status = _cairo_pdf_surface_add_pdf_pattern (surface, source, clip,
|
||||
&pattern_res, &gstate_res);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_pdf_surface_select_operator (surface, op);
|
||||
if (status)
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (gstate_res.id != 0) {
|
||||
|
|
@ -5840,7 +5851,7 @@ _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_create_similar,
|
||||
NULL, /* create similar: handled by wrapper */
|
||||
_cairo_pdf_surface_finish,
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
|
|
@ -5854,8 +5865,6 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* _cairo_pdf_surface_copy_page */
|
||||
_cairo_pdf_surface_show_page,
|
||||
NULL, /* set_clip_region */
|
||||
_cairo_pdf_surface_intersect_clip_path,
|
||||
_cairo_pdf_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
_cairo_pdf_surface_get_font_options,
|
||||
|
|
@ -5874,7 +5883,6 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
|
|||
NULL, /* snapshot */
|
||||
|
||||
NULL, /* is_compatible */
|
||||
NULL, /* reset */
|
||||
_cairo_pdf_surface_fill_stroke,
|
||||
NULL, /* create_solid_pattern_surface */
|
||||
NULL, /* can_repaint_solid_pattern_surface */
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "cairo-ps.h"
|
||||
|
||||
#include "cairo-surface-private.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
#include "cairo-pdf-operators-private.h"
|
||||
|
||||
#include <time.h>
|
||||
|
|
@ -65,6 +66,7 @@ typedef struct cairo_ps_surface {
|
|||
cairo_content_t content;
|
||||
double width;
|
||||
double height;
|
||||
cairo_rectangle_int_t page_bbox;
|
||||
int bbox_x1, bbox_y1, bbox_x2, bbox_y2;
|
||||
cairo_matrix_t cairo_to_ps;
|
||||
|
||||
|
|
@ -97,6 +99,8 @@ typedef struct cairo_ps_surface {
|
|||
cairo_ps_level_t ps_level;
|
||||
cairo_ps_level_t ps_level_used;
|
||||
|
||||
cairo_surface_clipper_t clipper;
|
||||
|
||||
cairo_pdf_operators_t pdf_operators;
|
||||
cairo_surface_t *paginated_surface;
|
||||
} cairo_ps_surface_t;
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@
|
|||
#include "cairo-scaled-font-subsets-private.h"
|
||||
#include "cairo-paginated-private.h"
|
||||
#include "cairo-meta-surface-private.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
#include "cairo-output-stream-private.h"
|
||||
#include "cairo-type3-glyph-surface-private.h"
|
||||
#include "cairo-image-info-private.h"
|
||||
|
|
@ -73,6 +74,13 @@
|
|||
|
||||
#define DEBUG_PS 0
|
||||
|
||||
#if DEBUG_PS
|
||||
#define DEBUG_FALLBACK(s) \
|
||||
fprintf (stderr, "%s::%d -- %s\n", __FUNCTION__, __LINE__, (s))
|
||||
#else
|
||||
#define DEBUG_FALLBACK(s)
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_CTIME_R
|
||||
#define ctime_r(T, BUF) ctime (T)
|
||||
#endif
|
||||
|
|
@ -700,6 +708,74 @@ _cairo_ps_surface_emit_footer (cairo_ps_surface_t *surface)
|
|||
"%%%%EOF\n");
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_path_covers_bbox (cairo_ps_surface_t *surface,
|
||||
cairo_path_fixed_t *path)
|
||||
{
|
||||
cairo_box_t box;
|
||||
|
||||
if (_cairo_path_fixed_is_rectangle (path, &box)) {
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
_cairo_box_round_to_rectangle (&box, &rect);
|
||||
|
||||
/* skip trivial whole-page clips */
|
||||
if (_cairo_rectangle_intersect (&rect, &surface->page_bbox)) {
|
||||
if (rect.x == surface->page_bbox.x &&
|
||||
rect.width == surface->page_bbox.width &&
|
||||
rect.y == surface->page_bbox.y &&
|
||||
rect.height == surface->page_bbox.height)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_ps_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_ps_surface_t *surface = cairo_container_of (clipper,
|
||||
cairo_ps_surface_t,
|
||||
clipper);
|
||||
cairo_output_stream_t *stream = surface->stream;
|
||||
cairo_status_t status;
|
||||
|
||||
assert (surface->paginated_mode != CAIRO_PAGINATED_MODE_ANALYZE);
|
||||
|
||||
#if DEBUG_PS
|
||||
_cairo_output_stream_printf (stream,
|
||||
"%% _cairo_ps_surface_intersect_clip_path\n");
|
||||
#endif
|
||||
|
||||
if (path == NULL) {
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (stream, "Q q\n");
|
||||
|
||||
surface->current_pattern_is_solid_color = FALSE;
|
||||
_cairo_pdf_operators_reset (&surface->pdf_operators);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (_path_covers_bbox (surface, path))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return _cairo_pdf_operators_clip (&surface->pdf_operators,
|
||||
path,
|
||||
fill_rule);
|
||||
}
|
||||
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
||||
double width,
|
||||
|
|
@ -756,6 +832,9 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
|||
surface->use_string_datasource = FALSE;
|
||||
surface->current_pattern_is_solid_color = FALSE;
|
||||
|
||||
_cairo_surface_clipper_init (&surface->clipper,
|
||||
_cairo_ps_surface_clipper_intersect_clip_path);
|
||||
|
||||
_cairo_pdf_operators_init (&surface->pdf_operators,
|
||||
surface->stream,
|
||||
&surface->cairo_to_ps,
|
||||
|
|
@ -771,7 +850,6 @@ _cairo_ps_surface_create_for_stream_internal (cairo_output_stream_t *stream,
|
|||
surface->paginated_surface = _cairo_paginated_surface_create (
|
||||
&surface->base,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
width, height,
|
||||
&cairo_ps_surface_paginated_backend);
|
||||
status = surface->paginated_surface->status;
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
|
|
@ -1083,11 +1161,6 @@ cairo_ps_surface_set_size (cairo_surface_t *surface,
|
|||
cairo_matrix_init (&ps_surface->cairo_to_ps, 1, 0, 0, -1, 0, height_in_points);
|
||||
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&ps_surface->pdf_operators,
|
||||
&ps_surface->cairo_to_ps);
|
||||
status = _cairo_paginated_surface_set_size (ps_surface->paginated_surface,
|
||||
width_in_points,
|
||||
height_in_points);
|
||||
if (unlikely (status))
|
||||
status = _cairo_surface_set_error (surface, status);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1288,15 +1361,6 @@ cairo_ps_surface_dsc_begin_page_setup (cairo_surface_t *surface)
|
|||
}
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_ps_surface_create_similar (void *abstract_surface,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
return cairo_meta_surface_create (content, width, height);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_ps_surface_finish (void *abstract_surface)
|
||||
{
|
||||
|
|
@ -1346,6 +1410,8 @@ CLEANUP:
|
|||
free (comments[i]);
|
||||
_cairo_array_fini (&surface->dsc_page_setup_comments);
|
||||
|
||||
_cairo_surface_clipper_reset (&surface->clipper);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -1369,8 +1435,11 @@ _cairo_ps_surface_end_page (cairo_ps_surface_t *surface)
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"Q\n");
|
||||
if (surface->clipper.clip.path != NULL) {
|
||||
_cairo_output_stream_printf (surface->stream, "Q Q\n");
|
||||
_cairo_surface_clipper_reset (&surface->clipper);
|
||||
} else
|
||||
_cairo_output_stream_printf (surface->stream, "Q\n");
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -1448,8 +1517,6 @@ _cairo_ps_surface_analyze_surface_pattern_transparency (cairo_ps_surface_t
|
|||
static cairo_bool_t
|
||||
surface_pattern_supported (const cairo_surface_pattern_t *pattern)
|
||||
{
|
||||
cairo_extend_t extend;
|
||||
|
||||
if (_cairo_surface_is_meta (pattern->surface))
|
||||
return TRUE;
|
||||
|
||||
|
|
@ -1465,24 +1532,7 @@ surface_pattern_supported (const cairo_surface_pattern_t *pattern)
|
|||
return FALSE;
|
||||
*/
|
||||
|
||||
/* Cast away the const, trusting get_extend not to muck with it.
|
||||
* And I really wish I had a way to cast away just the const, and
|
||||
* not potentially coerce this pointer to an incorrect type at the
|
||||
* same time. :-(
|
||||
*/
|
||||
extend = cairo_pattern_get_extend ((cairo_pattern_t*)&pattern->base);
|
||||
switch (extend) {
|
||||
case CAIRO_EXTEND_NONE:
|
||||
case CAIRO_EXTEND_REPEAT:
|
||||
case CAIRO_EXTEND_REFLECT:
|
||||
/* There's no point returning FALSE for EXTEND_PAD, as the image
|
||||
* surface does not currently implement it either */
|
||||
case CAIRO_EXTEND_PAD:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ASSERT_NOT_REACHED;
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
|
|
@ -1567,10 +1617,11 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
|
|||
}
|
||||
|
||||
if (! pattern_supported (surface, pattern))
|
||||
{
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (!(op == CAIRO_OPERATOR_SOURCE ||
|
||||
op == CAIRO_OPERATOR_OVER))
|
||||
if (! (op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_OVER))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
|
|
@ -1596,7 +1647,6 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
|
|||
* render stage and we blend the transparency into the white
|
||||
* background to convert the pattern to opaque.
|
||||
*/
|
||||
|
||||
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
|
||||
|
||||
|
|
@ -1606,8 +1656,8 @@ _cairo_ps_surface_analyze_operation (cairo_ps_surface_t *surface,
|
|||
|
||||
if (_cairo_pattern_is_opaque (pattern))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
else
|
||||
return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
|
||||
|
||||
return CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
|
|
@ -1824,7 +1874,8 @@ _cairo_ps_surface_flatten_image_transparency (cairo_ps_surface_t *surface,
|
|||
0, 0,
|
||||
0, 0,
|
||||
image->width,
|
||||
image->height);
|
||||
image->height,
|
||||
NULL);
|
||||
if (unlikely (status))
|
||||
goto fail;
|
||||
|
||||
|
|
@ -2109,6 +2160,7 @@ _cairo_ps_surface_emit_image (cairo_ps_surface_t *surface,
|
|||
data_compressed,
|
||||
data_compressed_size,
|
||||
FALSE);
|
||||
_cairo_output_stream_printf (surface->stream, "\n");
|
||||
} else {
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -2221,31 +2273,31 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t *surface,
|
|||
double old_width, old_height;
|
||||
cairo_matrix_t old_cairo_to_ps;
|
||||
cairo_content_t old_content;
|
||||
cairo_clip_t *old_clip;
|
||||
cairo_rectangle_int_t meta_extents;
|
||||
cairo_box_t bbox;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_surface_get_extents (meta_surface, &meta_extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
old_content = surface->content;
|
||||
old_width = surface->width;
|
||||
old_height = surface->height;
|
||||
old_cairo_to_ps = surface->cairo_to_ps;
|
||||
old_clip = _cairo_surface_get_clip (&surface->base);
|
||||
surface->width = meta_extents.width;
|
||||
surface->height = meta_extents.height;
|
||||
|
||||
status =
|
||||
_cairo_meta_surface_get_bbox ((cairo_meta_surface_t *) meta_surface,
|
||||
&bbox,
|
||||
NULL);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
/* XXX is this still necessary? */
|
||||
surface->width = _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x);
|
||||
surface->height = _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y);
|
||||
|
||||
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"
|
||||
" 0 0 %f %f rectclip\n",
|
||||
surface->width,
|
||||
surface->height);
|
||||
_cairo_output_stream_printf (surface->stream, " q\n");
|
||||
|
||||
if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) {
|
||||
surface->content = CAIRO_CONTENT_COLOR;
|
||||
|
|
@ -2265,17 +2317,13 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t *surface,
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
" Q\n");
|
||||
_cairo_output_stream_printf (surface->stream, " Q\n");
|
||||
surface->content = old_content;
|
||||
surface->width = old_width;
|
||||
surface->height = old_height;
|
||||
surface->current_pattern_is_solid_color = FALSE;
|
||||
_cairo_pdf_operators_reset (&surface->pdf_operators);
|
||||
surface->cairo_to_ps = old_cairo_to_ps;
|
||||
status = _cairo_surface_set_clip (&surface->base, old_clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_pdf_operators_set_cairo_to_pdf_matrix (&surface->pdf_operators,
|
||||
&surface->cairo_to_ps);
|
||||
|
|
@ -2331,11 +2379,11 @@ _cairo_ps_surface_acquire_surface (cairo_ps_surface_t *surface,
|
|||
cairo_rectangle_int_t *extents,
|
||||
int *width,
|
||||
int *height,
|
||||
int *origin_x,
|
||||
int *origin_y)
|
||||
int *origin_x,
|
||||
int *origin_y)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_surface_t *pad_image;
|
||||
cairo_surface_t *pad_image;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
|
|
@ -2343,15 +2391,18 @@ _cairo_ps_surface_acquire_surface (cairo_ps_surface_t *surface,
|
|||
surface->image = NULL;
|
||||
|
||||
if (_cairo_surface_is_meta (pattern->surface)) {
|
||||
cairo_surface_t *meta_surface = pattern->surface;
|
||||
cairo_rectangle_int_t pattern_extents;
|
||||
cairo_meta_surface_t *meta_surface = (cairo_meta_surface_t *) pattern->surface;
|
||||
cairo_box_t bbox;
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
status = _cairo_surface_get_extents (meta_surface, &pattern_extents);
|
||||
status = _cairo_meta_surface_get_bbox (meta_surface, &bbox, NULL);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
*width = pattern_extents.width;
|
||||
*height = pattern_extents.height;
|
||||
_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,
|
||||
&surface->acquired_image,
|
||||
|
|
@ -2391,7 +2442,8 @@ _cairo_ps_surface_acquire_surface (cairo_ps_surface_t *surface,
|
|||
0, 0,
|
||||
0, 0,
|
||||
rect.width,
|
||||
rect.height);
|
||||
rect.height,
|
||||
NULL);
|
||||
_cairo_pattern_fini (&pad_pattern.base);
|
||||
if (unlikely (status)) {
|
||||
if (pad_image != &surface->acquired_image->base)
|
||||
|
|
@ -2406,13 +2458,11 @@ _cairo_ps_surface_acquire_surface (cairo_ps_surface_t *surface,
|
|||
*height = surface->image->height;
|
||||
*origin_x = x;
|
||||
*origin_y = y;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
BAIL:
|
||||
_cairo_ps_surface_release_surface (surface, pattern);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -2428,10 +2478,9 @@ _cairo_ps_surface_emit_surface (cairo_ps_surface_t *surface,
|
|||
if (_cairo_surface_is_meta (pattern->surface)) {
|
||||
cairo_surface_t *meta_surface = pattern->surface;
|
||||
|
||||
status = _cairo_ps_surface_emit_meta_surface (surface,
|
||||
meta_surface);
|
||||
status = _cairo_ps_surface_emit_meta_surface (surface, meta_surface);
|
||||
} else {
|
||||
if (cairo_pattern_get_extend (&pattern->base) != CAIRO_EXTEND_PAD) {
|
||||
if (pattern->base.extend != CAIRO_EXTEND_PAD) {
|
||||
status = _cairo_ps_surface_emit_jpeg_image (surface, pattern->surface,
|
||||
width, height);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
|
|
@ -2540,7 +2589,6 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
|
|||
int pattern_height = 0; /* squelch bogus compiler warning */
|
||||
double xstep, ystep;
|
||||
cairo_matrix_t cairo_p2d, ps_p2d;
|
||||
cairo_rectangle_int_t surface_extents;
|
||||
cairo_bool_t old_use_string_datasource;
|
||||
int origin_x = 0;
|
||||
int origin_y = 0;
|
||||
|
|
@ -2550,12 +2598,6 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
|
|||
/* cairo_pattern_set_matrix ensures the matrix is invertible */
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
ps_p2d = surface->cairo_to_ps;
|
||||
cairo_matrix_multiply (&ps_p2d, &cairo_p2d, &ps_p2d);
|
||||
cairo_matrix_translate (&ps_p2d, -origin_x, -origin_y);
|
||||
cairo_matrix_translate (&ps_p2d, 0.0, pattern_height);
|
||||
cairo_matrix_scale (&ps_p2d, 1.0, -1.0);
|
||||
|
||||
status = _cairo_ps_surface_acquire_surface (surface,
|
||||
pattern,
|
||||
extents,
|
||||
|
|
@ -2669,17 +2711,13 @@ _cairo_ps_surface_emit_surface_pattern (cairo_ps_surface_t *surface,
|
|||
_cairo_output_stream_printf (surface->stream,
|
||||
">>\n");
|
||||
|
||||
status = _cairo_surface_get_extents (&surface->base, &surface_extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
cairo_p2d = pattern->base.matrix;
|
||||
status = cairo_matrix_invert (&cairo_p2d);
|
||||
/* cairo_pattern_set_matrix ensures the matrix is invertible */
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
cairo_matrix_init_identity (&ps_p2d);
|
||||
cairo_matrix_translate (&ps_p2d, 0.0, surface_extents.height);
|
||||
cairo_matrix_translate (&ps_p2d, 0.0, surface->height);
|
||||
cairo_matrix_scale (&ps_p2d, 1.0, -1.0);
|
||||
cairo_matrix_multiply (&ps_p2d, &cairo_p2d, &ps_p2d);
|
||||
cairo_matrix_translate (&ps_p2d, 0.0, pattern_height);
|
||||
|
|
@ -3163,43 +3201,7 @@ _cairo_ps_surface_emit_pattern (cairo_ps_surface_t *surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_ps_surface_intersect_clip_path (void *abstract_surface,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_ps_surface_t *surface = abstract_surface;
|
||||
cairo_output_stream_t *stream = surface->stream;
|
||||
cairo_status_t status;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
#if DEBUG_PS
|
||||
_cairo_output_stream_printf (stream,
|
||||
"%% _cairo_ps_surface_intersect_clip_path\n");
|
||||
#endif
|
||||
|
||||
if (path == NULL) {
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (stream, "Q q\n");
|
||||
surface->current_pattern_is_solid_color = FALSE;
|
||||
_cairo_pdf_operators_reset (&surface->pdf_operators);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return _cairo_pdf_operators_clip (&surface->pdf_operators,
|
||||
path,
|
||||
fill_rule);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_ps_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
|
|
@ -3215,7 +3217,7 @@ _cairo_ps_surface_get_extents (void *abstract_surface,
|
|||
rectangle->width = (int) ceil (surface->width);
|
||||
rectangle->height = (int) ceil (surface->height);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -3229,11 +3231,26 @@ _cairo_ps_surface_get_font_options (void *abstract_surface,
|
|||
cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_rectangle_intersect_clip (cairo_rectangle_int_t *extents, cairo_clip_t *clip)
|
||||
{
|
||||
const cairo_rectangle_int_t *clip_extents;
|
||||
|
||||
clip_extents = NULL;
|
||||
if (clip != NULL)
|
||||
clip_extents = _cairo_clip_get_extents (clip);
|
||||
|
||||
if (clip_extents != NULL)
|
||||
return _cairo_rectangle_intersect (extents, clip_extents);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_ps_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_rectangle_int_t *paint_extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_ps_surface_t *surface = abstract_surface;
|
||||
cairo_output_stream_t *stream = surface->stream;
|
||||
|
|
@ -3250,11 +3267,11 @@ _cairo_ps_surface_paint (void *abstract_surface,
|
|||
"%% _cairo_ps_surface_paint\n");
|
||||
#endif
|
||||
|
||||
status = _cairo_surface_get_extents (&surface->base, &extents);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
extents = surface->page_bbox;
|
||||
if (! _rectangle_intersect_clip (&extents, clip))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
|
|
@ -3262,28 +3279,25 @@ _cairo_ps_surface_paint (void *abstract_surface,
|
|||
(source->extend == CAIRO_EXTEND_NONE ||
|
||||
source->extend == CAIRO_EXTEND_PAD))
|
||||
{
|
||||
_cairo_output_stream_printf (stream, "q 0 0 %d %d rectclip\n",
|
||||
extents.width,
|
||||
extents.height);
|
||||
|
||||
_cairo_output_stream_printf (stream, "q\n");
|
||||
status = _cairo_ps_surface_paint_surface (surface,
|
||||
(cairo_surface_pattern_t *) source,
|
||||
paint_extents, op);
|
||||
&extents, op);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (stream, "Q\n");
|
||||
} else {
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, paint_extents, op);
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, &extents, op);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (stream, "0 0 %d %d rectfill\n",
|
||||
extents.width,
|
||||
extents.height);
|
||||
_cairo_output_stream_printf (stream, "%d %d %d %d rectfill\n",
|
||||
extents.x, extents.y,
|
||||
extents.width, extents.height);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -3299,10 +3313,11 @@ _cairo_ps_surface_stroke (void *abstract_surface,
|
|||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_ps_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _cairo_ps_surface_analyze_operation (surface, op, source);
|
||||
|
|
@ -3314,7 +3329,15 @@ _cairo_ps_surface_stroke (void *abstract_surface,
|
|||
"%% _cairo_ps_surface_stroke\n");
|
||||
#endif
|
||||
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, extents, op);
|
||||
extents = surface->page_bbox;
|
||||
if (! _rectangle_intersect_clip (&extents, clip))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, &extents, op);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
|
@ -3336,10 +3359,11 @@ _cairo_ps_surface_fill (void *abstract_surface,
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_ps_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _cairo_ps_surface_analyze_operation (surface, op, source);
|
||||
|
|
@ -3351,14 +3375,22 @@ _cairo_ps_surface_fill (void *abstract_surface,
|
|||
"%% _cairo_ps_surface_fill\n");
|
||||
#endif
|
||||
|
||||
extents = surface->page_bbox;
|
||||
if (! _rectangle_intersect_clip (&extents, clip))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
|
||||
(source->extend == CAIRO_EXTEND_NONE ||
|
||||
source->extend == CAIRO_EXTEND_PAD))
|
||||
{
|
||||
status = _cairo_pdf_operators_flush (&surface->pdf_operators);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->stream, "q\n");
|
||||
|
||||
status = _cairo_pdf_operators_clip (&surface->pdf_operators,
|
||||
|
|
@ -3369,14 +3401,14 @@ _cairo_ps_surface_fill (void *abstract_surface,
|
|||
|
||||
status = _cairo_ps_surface_paint_surface (surface,
|
||||
(cairo_surface_pattern_t *) source,
|
||||
extents, op);
|
||||
&extents, op);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->stream, "Q\n");
|
||||
_cairo_pdf_operators_reset (&surface->pdf_operators);
|
||||
} else {
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, extents, op);
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, &extents, op);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
|
@ -3398,11 +3430,12 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
|
|||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
int *remaining_glyphs,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs)
|
||||
{
|
||||
cairo_ps_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _cairo_ps_surface_analyze_operation (surface, op, source);
|
||||
|
|
@ -3417,7 +3450,15 @@ _cairo_ps_surface_show_glyphs (void *abstract_surface,
|
|||
if (num_glyphs <= 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, extents, op);
|
||||
extents = surface->page_bbox;
|
||||
if (! _rectangle_intersect_clip (&extents, clip))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_ps_surface_emit_pattern (surface, source, &extents, op);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
|
@ -3439,6 +3480,11 @@ _cairo_ps_surface_set_paginated_mode (void *abstract_surface,
|
|||
cairo_ps_surface_t *surface = abstract_surface;
|
||||
|
||||
surface->paginated_mode = paginated_mode;
|
||||
|
||||
if (surface->clipper.clip.path != NULL) {
|
||||
_cairo_output_stream_printf (surface->stream, "Q\n");
|
||||
_cairo_surface_clipper_reset (&surface->clipper);
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -3462,6 +3508,11 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface,
|
|||
y2 = (int) ceil (surface->height);
|
||||
}
|
||||
|
||||
surface->page_bbox.x = x1;
|
||||
surface->page_bbox.y = y1;
|
||||
surface->page_bbox.width = x2 - x1;
|
||||
surface->page_bbox.height = y2 - y1;
|
||||
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"%%%%Page: %d %d\n",
|
||||
surface->num_pages,
|
||||
|
|
@ -3486,7 +3537,11 @@ _cairo_ps_surface_set_bounding_box (void *abstract_surface,
|
|||
|
||||
_cairo_output_stream_printf (surface->stream,
|
||||
"%%%%EndPageSetup\n"
|
||||
"q\n");
|
||||
"q %d %d %d %d rectclip q\n",
|
||||
surface->page_bbox.x,
|
||||
surface->page_bbox.y,
|
||||
surface->page_bbox.width,
|
||||
surface->page_bbox.height);
|
||||
|
||||
if (surface->num_pages == 1) {
|
||||
surface->bbox_x1 = x1;
|
||||
|
|
@ -3517,7 +3572,7 @@ _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_create_similar,
|
||||
NULL, /* create similar: handled by wrapper */
|
||||
_cairo_ps_surface_finish,
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
|
|
@ -3531,8 +3586,6 @@ static const cairo_surface_backend_t cairo_ps_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* cairo_ps_surface_copy_page */
|
||||
_cairo_ps_surface_show_page,
|
||||
NULL, /* set_clip_region */
|
||||
_cairo_ps_surface_intersect_clip_path,
|
||||
_cairo_ps_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
_cairo_ps_surface_get_font_options,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-types-private.h"
|
||||
#include "cairo-clip-private.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
#include "cairo-region-private.h"
|
||||
|
||||
#include "cairo-qt.h"
|
||||
|
||||
|
|
@ -65,6 +68,8 @@
|
|||
|
||||
#include <sys/time.h>
|
||||
|
||||
#define ENABLE_FAST_FILL 1 /* Enable workaround slow regional Qt paths */
|
||||
|
||||
#if 0
|
||||
#define D(x) x
|
||||
static const char *
|
||||
|
|
@ -104,14 +109,9 @@ _opstr (cairo_operator_t op)
|
|||
#define DOT_LENGTH 1.0
|
||||
#define DASH_LENGTH 3.0
|
||||
|
||||
typedef struct {
|
||||
struct cairo_qt_surface_t {
|
||||
cairo_surface_t base;
|
||||
|
||||
bool has_clipping;
|
||||
// if this is true, calls to intersect_clip_path won't
|
||||
// update the clip_bounds rect
|
||||
bool no_update_clip_bounds;
|
||||
|
||||
cairo_bool_t supports_porter_duff;
|
||||
|
||||
#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE
|
||||
|
|
@ -131,11 +131,10 @@ typedef struct {
|
|||
|
||||
QRect window;
|
||||
|
||||
|
||||
QRect clip_bounds;
|
||||
cairo_surface_clipper_t clipper;
|
||||
|
||||
cairo_surface_t *image_equiv;
|
||||
} cairo_qt_surface_t;
|
||||
};
|
||||
|
||||
/* Will be true if we ever try to create a QPixmap and end
|
||||
* up with one without an alpha channel.
|
||||
|
|
@ -186,6 +185,21 @@ _qpainter_compositionmode_from_cairo_op (cairo_operator_t op)
|
|||
default:
|
||||
case CAIRO_OPERATOR_ADD:
|
||||
case CAIRO_OPERATOR_SATURATE:
|
||||
case CAIRO_OPERATOR_MULTIPLY:
|
||||
case CAIRO_OPERATOR_SCREEN:
|
||||
case CAIRO_OPERATOR_OVERLAY:
|
||||
case CAIRO_OPERATOR_DARKEN:
|
||||
case CAIRO_OPERATOR_LIGHTEN:
|
||||
case CAIRO_OPERATOR_COLOR_DODGE:
|
||||
case CAIRO_OPERATOR_COLOR_BURN:
|
||||
case CAIRO_OPERATOR_HARD_LIGHT:
|
||||
case CAIRO_OPERATOR_SOFT_LIGHT:
|
||||
case CAIRO_OPERATOR_DIFFERENCE:
|
||||
case CAIRO_OPERATOR_EXCLUSION:
|
||||
case CAIRO_OPERATOR_HSL_HUE:
|
||||
case CAIRO_OPERATOR_HSL_SATURATION:
|
||||
case CAIRO_OPERATOR_HSL_COLOR:
|
||||
case CAIRO_OPERATOR_HSL_LUMINOSITY:
|
||||
ASSERT_NOT_REACHED;
|
||||
}
|
||||
}
|
||||
|
|
@ -211,12 +225,27 @@ _op_is_supported (cairo_qt_surface_t *qs, cairo_operator_t op)
|
|||
case CAIRO_OPERATOR_XOR:
|
||||
return TRUE;
|
||||
|
||||
case CAIRO_OPERATOR_ADD:
|
||||
case CAIRO_OPERATOR_SATURATE:
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
case CAIRO_OPERATOR_ADD:
|
||||
case CAIRO_OPERATOR_SATURATE:
|
||||
case CAIRO_OPERATOR_MULTIPLY:
|
||||
case CAIRO_OPERATOR_SCREEN:
|
||||
case CAIRO_OPERATOR_OVERLAY:
|
||||
case CAIRO_OPERATOR_DARKEN:
|
||||
case CAIRO_OPERATOR_LIGHTEN:
|
||||
case CAIRO_OPERATOR_COLOR_DODGE:
|
||||
case CAIRO_OPERATOR_COLOR_BURN:
|
||||
case CAIRO_OPERATOR_HARD_LIGHT:
|
||||
case CAIRO_OPERATOR_SOFT_LIGHT:
|
||||
case CAIRO_OPERATOR_DIFFERENCE:
|
||||
case CAIRO_OPERATOR_EXCLUSION:
|
||||
case CAIRO_OPERATOR_HSL_HUE:
|
||||
case CAIRO_OPERATOR_HSL_SATURATION:
|
||||
case CAIRO_OPERATOR_HSL_COLOR:
|
||||
case CAIRO_OPERATOR_HSL_LUMINOSITY:
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
} else {
|
||||
return op == CAIRO_OPERATOR_OVER;
|
||||
|
|
@ -458,6 +487,8 @@ _cairo_qt_surface_finish (void *abstract_surface)
|
|||
if (qs->image_equiv)
|
||||
cairo_surface_destroy (qs->image_equiv);
|
||||
|
||||
_cairo_surface_clipper_reset (&qs->clipper);
|
||||
|
||||
#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE
|
||||
if (qs->xlib_equiv)
|
||||
cairo_surface_destroy (qs->xlib_equiv);
|
||||
|
|
@ -655,7 +686,7 @@ _cairo_qt_surface_clone_similar (void *abstract_surface,
|
|||
return (cairo_status_t) CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_qt_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
|
|
@ -666,25 +697,40 @@ _cairo_qt_surface_get_extents (void *abstract_surface,
|
|||
extents->width = qs->window.width();
|
||||
extents->height = qs->window.height();
|
||||
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_qt_surface_intersect_clip_path (void *abstract_surface,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
static cairo_status_t
|
||||
_cairo_qt_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
|
||||
cairo_qt_surface_t *qs = cairo_container_of (clipper,
|
||||
cairo_qt_surface_t,
|
||||
clipper);
|
||||
QPainterPath qpath;
|
||||
cairo_status_t status;
|
||||
|
||||
D(fprintf(stderr, "q[%p] intersect_clip_path %s\n", abstract_surface, path ? "(path)" : "(clear)"));
|
||||
// XXX Antialiasing is ignored
|
||||
status = _cairo_quartz_cairo_path_to_qpainterpath (path,
|
||||
&qpath,
|
||||
fill_rule);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (!qs->p)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
qs->p->setClipPath (qpath, Qt::IntersectClip);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (path == NULL) {
|
||||
//fprintf (stderr, "clip clear\n");
|
||||
static void
|
||||
_cairo_qt_surface_set_clip_region (cairo_qt_surface_t *qs,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
_cairo_surface_clipper_reset (&qs->clipper);
|
||||
|
||||
if (clip_region == NULL) {
|
||||
// How the clip path is reset depends on whether we own p or not
|
||||
if (qs->pixmap || qs->image) {
|
||||
// we own p
|
||||
|
|
@ -693,10 +739,38 @@ _cairo_qt_surface_intersect_clip_path (void *abstract_surface,
|
|||
qs->p->restore ();
|
||||
qs->p->save ();
|
||||
}
|
||||
} else {
|
||||
QRegion qr;
|
||||
int num_rects = cairo_region_num_rectangles (clip_region);
|
||||
for (int i = 0; i < num_rects; ++i) {
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
if (!qs->no_update_clip_bounds) {
|
||||
qs->clip_bounds.setRect(0, 0, 0, 0);
|
||||
qs->has_clipping = false;
|
||||
cairo_region_get_rectangle (clip_region, i, &rect);
|
||||
|
||||
QRect r(rect.x, rect.y, rect.width, rect.height);
|
||||
qr = qr.unite(r);
|
||||
}
|
||||
|
||||
qs->p->setClipRegion (qr, Qt::IntersectClip);
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_qt_surface_set_clip (cairo_qt_surface_t *qs,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
|
||||
D(fprintf(stderr, "q[%p] intersect_clip_path %s\n", abstract_surface, path ? "(path)" : "(clear)"));
|
||||
|
||||
if (clip == NULL) {
|
||||
_cairo_surface_clipper_reset (&qs->clipper);
|
||||
// How the clip path is reset depends on whether we own p or not
|
||||
if (qs->pixmap || qs->image) {
|
||||
// we own p
|
||||
qs->p->setClipping (false);
|
||||
} else {
|
||||
qs->p->restore ();
|
||||
qs->p->save ();
|
||||
}
|
||||
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
|
|
@ -711,125 +785,21 @@ _cairo_qt_surface_intersect_clip_path (void *abstract_surface,
|
|||
// we do a bunch of work here to try to get rectangles or regions
|
||||
// down to Qt for clipping.
|
||||
|
||||
QRect clip_bounds;
|
||||
cairo_region_t *clip_region = NULL;
|
||||
|
||||
// First check if it's an integer-aligned single rectangle
|
||||
cairo_box_t box;
|
||||
if (_cairo_path_fixed_is_box (path, &box) &&
|
||||
_cairo_fixed_is_integer (box.p1.x) &&
|
||||
_cairo_fixed_is_integer (box.p1.y) &&
|
||||
_cairo_fixed_is_integer (box.p2.x) &&
|
||||
_cairo_fixed_is_integer (box.p2.y))
|
||||
{
|
||||
QRect r(_cairo_fixed_integer_part(box.p1.x),
|
||||
_cairo_fixed_integer_part(box.p1.y),
|
||||
_cairo_fixed_integer_part(box.p2.x - box.p1.x),
|
||||
_cairo_fixed_integer_part(box.p2.y - box.p1.y));
|
||||
|
||||
r = r.normalized();
|
||||
|
||||
clip_bounds = r;
|
||||
|
||||
qs->p->setClipRect (r, Qt::IntersectClip);
|
||||
} else {
|
||||
// Then if it's not an integer-aligned rectangle, check
|
||||
// if we can extract a region (a set of rectangles) out.
|
||||
// We use cairo to convert the path to traps.
|
||||
|
||||
cairo_traps_t traps;
|
||||
cairo_int_status_t status;
|
||||
cairo_region_t *region = NULL;
|
||||
|
||||
_cairo_traps_init (&traps);
|
||||
cairo_int_status_t status;
|
||||
status = _cairo_clip_get_region (clip, &clip_region);
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
// We weren't able to extract a region from the traps.
|
||||
// Just hand the path down to QPainter.
|
||||
status = (cairo_int_status_t)
|
||||
_cairo_path_fixed_fill_to_traps (path,
|
||||
fill_rule, tolerance, &traps);
|
||||
if (status) {
|
||||
_cairo_traps_fini (&traps);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = _cairo_traps_extract_region (&traps, ®ion);
|
||||
_cairo_traps_fini (&traps);
|
||||
|
||||
if (_cairo_status_is_error ((cairo_status_t) status))
|
||||
return status;
|
||||
|
||||
if (status == CAIRO_INT_STATUS_SUCCESS) {
|
||||
#if 0
|
||||
cairo_box_int_t *boxes;
|
||||
int n_boxes;
|
||||
|
||||
QRegion qr;
|
||||
|
||||
_cairo_region_get_boxes (®ion, &n_boxes, &boxes);
|
||||
|
||||
for (int i = 0; i < n_boxes; i++) {
|
||||
QRect r(boxes[i].p1.x,
|
||||
boxes[i].p1.y,
|
||||
boxes[i].p2.x - boxes[i].p1.x,
|
||||
boxes[i].p2.y - boxes[i].p1.y);
|
||||
|
||||
if (i == 0)
|
||||
clip_bounds = r;
|
||||
else
|
||||
clip_bounds = clip_bounds.united(r);
|
||||
|
||||
qr = qr.unite(r);
|
||||
}
|
||||
_cairo_region_boxes_fini (®ion, boxes);
|
||||
#else
|
||||
int n_boxes;
|
||||
|
||||
QRegion qr;
|
||||
|
||||
n_boxes = cairo_region_num_rectangles (region);
|
||||
for (int i = 0; i < n_boxes; ++i) {
|
||||
cairo_rectangle_int_t box;
|
||||
cairo_region_get_rectangle (region, i, &box);
|
||||
QRect r(box.x, box.y, box.width, box.height);
|
||||
|
||||
if (0 == i)
|
||||
clip_bounds = r;
|
||||
else
|
||||
clip_bounds = clip_bounds.united(r);
|
||||
|
||||
qr = qr.unite(r);
|
||||
}
|
||||
#endif
|
||||
_cairo_region_fini (region);
|
||||
|
||||
qs->p->setClipRegion (qr, Qt::IntersectClip);
|
||||
} else {
|
||||
// We weren't able to extract a region from the traps.
|
||||
// Just hand the path down to QPainter.
|
||||
QPainterPath qpath;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_quartz_cairo_path_to_qpainterpath (path,
|
||||
&qpath,
|
||||
fill_rule);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
clip_bounds = qpath.boundingRect().toAlignedRect();
|
||||
|
||||
// XXX Antialiasing is ignored
|
||||
qs->p->setClipPath (qpath, Qt::IntersectClip);
|
||||
}
|
||||
_cairo_surface_clipper_set_clip (&qs->clipper, clip);
|
||||
} else if (status == CAIRO_INT_STATUS_SUCCESS) {
|
||||
_cairo_qt_surface_set_clip_region (qs, clip_region);
|
||||
status = CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (!qs->no_update_clip_bounds) {
|
||||
clip_bounds = qs->p->worldTransform().mapRect(clip_bounds);
|
||||
|
||||
if (qs->has_clipping) {
|
||||
qs->clip_bounds = qs->clip_bounds.intersect(clip_bounds);
|
||||
} else {
|
||||
qs->clip_bounds = clip_bounds;
|
||||
qs->has_clipping = true;
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1156,10 +1126,12 @@ _cairo_qt_fast_fill (cairo_qt_surface_t *qs,
|
|||
double tolerance = 0.0,
|
||||
cairo_antialias_t antialias = CAIRO_ANTIALIAS_NONE)
|
||||
{
|
||||
#if ENABLE_FAST_FILL
|
||||
QImage *qsSrc_image = NULL;
|
||||
QPixmap *qsSrc_pixmap = NULL;
|
||||
std::auto_ptr<QImage> qsSrc_image_d;
|
||||
|
||||
|
||||
if (source->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t*) source;
|
||||
if (spattern->surface->type == CAIRO_SURFACE_TYPE_QT) {
|
||||
|
|
@ -1190,7 +1162,6 @@ _cairo_qt_fast_fill (cairo_qt_surface_t *qs,
|
|||
}
|
||||
|
||||
QMatrix sourceMatrix = _qmatrix_from_cairo_matrix (source->matrix);
|
||||
cairo_int_status_t status;
|
||||
|
||||
// We can draw this faster by clipping and calling drawImage/drawPixmap.
|
||||
// Use our own clipping function so that we can get the
|
||||
|
|
@ -1201,14 +1172,29 @@ _cairo_qt_fast_fill (cairo_qt_surface_t *qs,
|
|||
qs->p->save();
|
||||
|
||||
if (path) {
|
||||
qs->no_update_clip_bounds = true;
|
||||
status = _cairo_qt_surface_intersect_clip_path (qs, path, fill_rule, tolerance, antialias);
|
||||
qs->no_update_clip_bounds = false;
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (status != CAIRO_INT_STATUS_SUCCESS) {
|
||||
qs->p->restore();
|
||||
return false;
|
||||
}
|
||||
cairo_clip_t clip, old_clip = qs->clipper.clip;
|
||||
|
||||
_cairo_clip_init_copy (&clip, &qs->clipper.clip);
|
||||
status = (cairo_int_status_t) _cairo_clip_clip (&clip,
|
||||
path,
|
||||
fill_rule,
|
||||
tolerance,
|
||||
antialias);
|
||||
if (unlikely (status)) {
|
||||
qs->p->restore();
|
||||
return false;
|
||||
}
|
||||
|
||||
status = _cairo_qt_surface_set_clip (qs, &clip);
|
||||
if (unlikely (status)) {
|
||||
qs->p->restore();
|
||||
return false;
|
||||
}
|
||||
|
||||
_cairo_clip_reset (&clip);
|
||||
qs->clipper.clip = old_clip;
|
||||
}
|
||||
|
||||
qs->p->setWorldMatrix (sourceMatrix.inverted(), true);
|
||||
|
|
@ -1242,16 +1228,19 @@ _cairo_qt_fast_fill (cairo_qt_surface_t *qs,
|
|||
qs->p->restore();
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_qt_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
Q_UNUSED(extents);
|
||||
cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
|
||||
D(fprintf(stderr, "q[%p] paint op:%s\n", abstract_surface, _opstr(op)));
|
||||
|
||||
|
|
@ -1261,6 +1250,10 @@ _cairo_qt_surface_paint (void *abstract_surface,
|
|||
if (! _op_is_supported (qs, op))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_qt_surface_set_clip (qs, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (qs->supports_porter_duff)
|
||||
qs->p->setCompositionMode (_qpainter_compositionmode_from_cairo_op (op));
|
||||
|
||||
|
|
@ -1283,9 +1276,8 @@ _cairo_qt_surface_fill (void *abstract_surface,
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t * extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
Q_UNUSED(extents);
|
||||
cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
|
||||
|
||||
D(fprintf(stderr, "q[%p] fill op:%s\n", abstract_surface, _opstr(op)));
|
||||
|
|
@ -1296,6 +1288,10 @@ _cairo_qt_surface_fill (void *abstract_surface,
|
|||
if (! _op_is_supported (qs, op))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
cairo_int_status_t status = _cairo_qt_surface_set_clip (qs, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (qs->supports_porter_duff)
|
||||
qs->p->setCompositionMode (_qpainter_compositionmode_from_cairo_op (op));
|
||||
|
||||
|
|
@ -1333,9 +1329,8 @@ _cairo_qt_surface_stroke (void *abstract_surface,
|
|||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
Q_UNUSED(extents);
|
||||
cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
|
||||
|
||||
D(fprintf(stderr, "q[%p] stroke op:%s\n", abstract_surface, _opstr(op)));
|
||||
|
|
@ -1346,6 +1341,10 @@ _cairo_qt_surface_stroke (void *abstract_surface,
|
|||
if (! _op_is_supported (qs, op))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
cairo_int_status_t int_status = _cairo_qt_surface_set_clip (qs, clip);
|
||||
if (unlikely (int_status))
|
||||
return int_status;
|
||||
|
||||
QPainterPath qpath;
|
||||
cairo_status_t status;
|
||||
|
||||
|
|
@ -1387,8 +1386,8 @@ _cairo_qt_surface_show_glyphs (void *abstract_surface,
|
|||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
int *remaining_glyphs,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs)
|
||||
{
|
||||
cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
|
||||
|
||||
|
|
@ -1404,37 +1403,6 @@ _cairo_qt_surface_show_glyphs (void *abstract_surface,
|
|||
glyphs[i].y -= qs->redir_offset.y();
|
||||
}
|
||||
|
||||
if (qs->has_clipping != qs->xlib_has_clipping ||
|
||||
qs->clip_bounds != qs->xlib_clip_bounds)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_surface_reset_clip (qs->xlib_equiv);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
if (qs->has_clipping) {
|
||||
cairo_region_t region;
|
||||
cairo_rectangle_int_t rect = {
|
||||
qs->clip_bounds.x() - qs->redir_offset.x(),
|
||||
qs->clip_bounds.y() - qs->redir_offset.y(),
|
||||
qs->clip_bounds.width(),
|
||||
qs->clip_bounds.height()
|
||||
};
|
||||
|
||||
_cairo_region_init_rectangle (®ion, &rect);
|
||||
status = _cairo_surface_set_clip_region (qs->xlib_equiv,
|
||||
®ion,
|
||||
++qs->xlib_clip_serial);
|
||||
_cairo_region_fini (®ion);
|
||||
|
||||
if (status)
|
||||
return (cairo_int_status_t) status;
|
||||
}
|
||||
|
||||
qs->xlib_has_clipping = qs->has_clipping;
|
||||
qs->xlib_clip_bounds = qs->clip_bounds;
|
||||
}
|
||||
|
||||
return (cairo_int_status_t)
|
||||
_cairo_surface_show_text_glyphs (qs->xlib_equiv,
|
||||
op, source,
|
||||
|
|
@ -1443,7 +1411,7 @@ _cairo_qt_surface_show_glyphs (void *abstract_surface,
|
|||
NULL, 0,
|
||||
(cairo_text_cluster_flags_t) 0,
|
||||
scaled_font,
|
||||
extents);
|
||||
clip);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -1452,12 +1420,11 @@ _cairo_qt_surface_show_glyphs (void *abstract_surface,
|
|||
|
||||
static cairo_int_status_t
|
||||
_cairo_qt_surface_mask (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
Q_UNUSED(extents);
|
||||
cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
|
||||
|
||||
D(fprintf(stderr, "q[%p] mask op:%s\n", abstract_surface, _opstr(op)));
|
||||
|
|
@ -1471,7 +1438,7 @@ _cairo_qt_surface_mask (void *abstract_surface,
|
|||
|
||||
qs->p->setOpacity (solid_mask->color.alpha);
|
||||
|
||||
result = _cairo_qt_surface_paint (abstract_surface, op, source, 0);
|
||||
result = _cairo_qt_surface_paint (abstract_surface, op, source, clip);
|
||||
|
||||
qs->p->setOpacity (1.0);
|
||||
|
||||
|
|
@ -1498,7 +1465,8 @@ _cairo_qt_surface_composite (cairo_operator_t op,
|
|||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height)
|
||||
unsigned int height,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_qt_surface_t *qs = (cairo_qt_surface_t *) abstract_surface;
|
||||
|
||||
|
|
@ -1508,6 +1476,8 @@ _cairo_qt_surface_composite (cairo_operator_t op,
|
|||
if (! _op_is_supported (qs, op))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
_cairo_qt_surface_set_clip_region (qs, clip_region);
|
||||
|
||||
D(fprintf(stderr, "q[%p] composite op:%s src:%p [%d %d] dst [%d %d] dim [%d %d]\n",
|
||||
abstract_surface, _opstr(op), (void*)pattern,
|
||||
src_x, src_y, dst_x, dst_y, width, height));
|
||||
|
|
@ -1618,8 +1588,6 @@ static const cairo_surface_backend_t cairo_qt_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
NULL, /* set_clip_region */
|
||||
_cairo_qt_surface_intersect_clip_path,
|
||||
_cairo_qt_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
|
|
@ -1636,7 +1604,6 @@ static const cairo_surface_backend_t cairo_qt_surface_backend = {
|
|||
|
||||
NULL, /* snapshot */
|
||||
NULL, /* is_similar */
|
||||
NULL, /* reset */
|
||||
NULL, /* fill_stroke */
|
||||
NULL, /* create_solid_pattern_surface */
|
||||
NULL, /* can_repaint_solid_pattern_surface */
|
||||
|
|
@ -1728,6 +1695,10 @@ cairo_qt_surface_create (QPainter *painter)
|
|||
|
||||
qs->window = painter->window();
|
||||
|
||||
_cairo_surface_clipper_init (&qs->clipper,
|
||||
_cairo_qt_surface_clipper_intersect_clip_path);
|
||||
|
||||
|
||||
#if defined(Q_WS_X11) && CAIRO_HAS_XLIB_XRENDER_SURFACE
|
||||
qs->xlib_equiv = _cairo_qt_create_xlib_surface (qs);
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -58,9 +58,8 @@ _cairo_quartz_image_surface_create_similar (void *asurface,
|
|||
int height)
|
||||
{
|
||||
cairo_surface_t *result;
|
||||
cairo_surface_t *isurf = cairo_image_surface_create (_cairo_format_from_content (content),
|
||||
width,
|
||||
height);
|
||||
cairo_surface_t *isurf =
|
||||
_cairo_image_surface_create_for_content (content, width, height);
|
||||
if (cairo_surface_status(isurf))
|
||||
return isurf;
|
||||
|
||||
|
|
@ -108,18 +107,16 @@ _cairo_quartz_image_surface_acquire_dest_image (void *asurface,
|
|||
*image_extra = NULL;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_quartz_image_surface_get_extents (void *asurface,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) asurface;
|
||||
|
||||
*extents = surface->extents;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* we assume some drawing happened to the image buffer; make sure it's
|
||||
|
|
@ -168,8 +165,6 @@ static const cairo_surface_backend_t cairo_quartz_image_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
NULL, /* set_clip_region */
|
||||
NULL, /* intersect_clip_path */
|
||||
_cairo_quartz_image_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
|
|
@ -185,7 +180,6 @@ static const cairo_surface_backend_t cairo_quartz_image_surface_backend = {
|
|||
NULL, /* surface_show_glyphs */
|
||||
NULL, /* snapshot */
|
||||
NULL, /* is_similar */
|
||||
NULL, /* reset */
|
||||
NULL /* fill_stroke */
|
||||
|
||||
};
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
#if CAIRO_HAS_QUARTZ_SURFACE
|
||||
#include "cairo-quartz.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
|
||||
typedef struct cairo_quartz_surface {
|
||||
cairo_surface_t base;
|
||||
|
|
@ -52,6 +53,7 @@ typedef struct cairo_quartz_surface {
|
|||
void *imageData;
|
||||
cairo_surface_t *imageSurfaceEquiv;
|
||||
|
||||
cairo_surface_clipper_t clipper;
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
/* These are stored while drawing operations are in place, set up
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-quartz-private.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
|
|
@ -837,7 +838,8 @@ _cairo_surface_to_cgimage (cairo_surface_t *target,
|
|||
}
|
||||
|
||||
if (stype != CAIRO_SURFACE_TYPE_IMAGE) {
|
||||
status = _cairo_surface_acquire_source_image (source, &isurf, &image_extra);
|
||||
status = _cairo_surface_acquire_source_image (source,
|
||||
&isurf, &image_extra);
|
||||
if (status)
|
||||
return status;
|
||||
} else {
|
||||
|
|
@ -848,12 +850,11 @@ _cairo_surface_to_cgimage (cairo_surface_t *target,
|
|||
*image_out = NULL;
|
||||
} else {
|
||||
cairo_image_surface_t *isurf_snap = NULL;
|
||||
isurf_snap = (cairo_image_surface_t*) _cairo_surface_snapshot ((cairo_surface_t*) isurf);
|
||||
if (isurf_snap == NULL)
|
||||
return CAIRO_STATUS_NO_MEMORY;
|
||||
|
||||
if (isurf_snap->base.type != CAIRO_SURFACE_TYPE_IMAGE)
|
||||
return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
|
||||
isurf_snap = (cairo_image_surface_t*)
|
||||
_cairo_surface_snapshot (&isurf->base);
|
||||
if (isurf_snap->base.status)
|
||||
return isurf_snap->base.status;
|
||||
|
||||
image = _cairo_quartz_create_cgimage (isurf_snap->format,
|
||||
isurf_snap->width,
|
||||
|
|
@ -868,10 +869,10 @@ _cairo_surface_to_cgimage (cairo_surface_t *target,
|
|||
*image_out = image;
|
||||
}
|
||||
|
||||
if ((cairo_surface_t*) isurf != source)
|
||||
if (&isurf->base != source)
|
||||
_cairo_surface_release_source_image (source, isurf, image_extra);
|
||||
|
||||
return status;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Generic #cairo_pattern_t -> CGPattern function */
|
||||
|
|
@ -942,6 +943,7 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t
|
|||
SurfacePatternDrawInfo *info;
|
||||
float rw, rh;
|
||||
cairo_status_t status;
|
||||
cairo_bool_t is_bounded;
|
||||
|
||||
cairo_matrix_t m;
|
||||
|
||||
|
|
@ -952,9 +954,8 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t
|
|||
spattern = (cairo_surface_pattern_t *) apattern;
|
||||
pat_surf = spattern->surface;
|
||||
|
||||
status = _cairo_surface_get_extents (pat_surf, &extents);
|
||||
if (status)
|
||||
return status;
|
||||
is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
|
||||
assert (is_bounded);
|
||||
|
||||
status = _cairo_surface_to_cgimage ((cairo_surface_t*) dest, pat_surf, &image);
|
||||
if (status != CAIRO_STATUS_SUCCESS)
|
||||
|
|
@ -1042,9 +1043,7 @@ _cairo_quartz_setup_fallback_source (cairo_quartz_surface_t *surface,
|
|||
double x0, y0, w, h;
|
||||
|
||||
cairo_surface_t *fallback;
|
||||
cairo_t *fallback_cr;
|
||||
CGImageRef img;
|
||||
cairo_pattern_t *source_copy;
|
||||
|
||||
cairo_status_t status;
|
||||
|
||||
|
|
@ -1070,20 +1069,38 @@ _cairo_quartz_setup_fallback_source (cairo_quartz_surface_t *surface,
|
|||
fallback = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, (int) w, (int) h);
|
||||
cairo_surface_set_device_offset (fallback, -x0, -y0);
|
||||
|
||||
/* Paint the source onto our temporary */
|
||||
fallback_cr = cairo_create (fallback);
|
||||
cairo_set_operator (fallback_cr, CAIRO_OPERATOR_SOURCE);
|
||||
#if 0
|
||||
{
|
||||
cairo_t *fallback_cr;
|
||||
cairo_pattern_t *source_copy;
|
||||
|
||||
/* Use a copy of the pattern because it is const and could be allocated
|
||||
* on the stack */
|
||||
status = _cairo_pattern_create_copy (&source_copy, source);
|
||||
cairo_set_source (fallback_cr, source_copy);
|
||||
cairo_pattern_destroy (source_copy);
|
||||
/* Paint the source onto our temporary */
|
||||
fallback_cr = cairo_create (fallback);
|
||||
cairo_set_operator (fallback_cr, CAIRO_OPERATOR_SOURCE);
|
||||
|
||||
cairo_paint (fallback_cr);
|
||||
cairo_destroy (fallback_cr);
|
||||
/* Use a copy of the pattern because it is const and could be allocated
|
||||
* on the stack */
|
||||
status = _cairo_pattern_create_copy (&source_copy, source);
|
||||
cairo_set_source (fallback_cr, source_copy);
|
||||
cairo_pattern_destroy (source_copy);
|
||||
|
||||
status = _cairo_surface_to_cgimage ((cairo_surface_t*) surface, fallback, &img);
|
||||
cairo_paint (fallback_cr);
|
||||
cairo_destroy (fallback_cr);
|
||||
}
|
||||
#else
|
||||
{
|
||||
cairo_pattern_union_t pattern;
|
||||
|
||||
_cairo_pattern_init_static_copy (&pattern, source);
|
||||
_cairo_pattern_transform (pattern_copy,
|
||||
&fallback->device_transform_inverse);
|
||||
status = _cairo_surface_paint (fallback,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
&pattern.base, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
status = _cairo_surface_to_cgimage (&surface->base, fallback, &img);
|
||||
if (status == CAIRO_STATUS_SUCCESS && img == NULL)
|
||||
return DO_NOTHING;
|
||||
if (status)
|
||||
|
|
@ -1251,6 +1268,7 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
|
|||
CGAffineTransform xform;
|
||||
CGRect srcRect;
|
||||
cairo_fixed_t fw, fh;
|
||||
cairo_bool_t is_bounded;
|
||||
|
||||
status = _cairo_surface_to_cgimage ((cairo_surface_t *) surface, pat_surf, &img);
|
||||
if (status == CAIRO_STATUS_SUCCESS && img == NULL)
|
||||
|
|
@ -1263,9 +1281,8 @@ _cairo_quartz_setup_source (cairo_quartz_surface_t *surface,
|
|||
cairo_matrix_invert(&m);
|
||||
_cairo_quartz_cairo_matrix_to_quartz (&m, &surface->sourceTransform);
|
||||
|
||||
status = _cairo_surface_get_extents (pat_surf, &extents);
|
||||
if (status)
|
||||
return DO_UNSUPPORTED;
|
||||
is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
|
||||
assert (is_bounded);
|
||||
|
||||
if (source->extend == CAIRO_EXTEND_NONE) {
|
||||
surface->sourceImageRect = CGRectMake (0, 0, extents.width, extents.height);
|
||||
|
|
@ -1485,6 +1502,7 @@ _cairo_quartz_surface_finish (void *abstract_surface)
|
|||
|
||||
/* Restore our saved gstate that we use to reset clipping */
|
||||
CGContextRestoreGState (surface->cgContext);
|
||||
_cairo_surface_clipper_reset (&surface->clipper);
|
||||
|
||||
CGContextRelease (surface->cgContext);
|
||||
|
||||
|
|
@ -1700,22 +1718,21 @@ FINISH:
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_quartz_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
|
||||
|
||||
*extents = surface->extents;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_quartz_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
|
||||
cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -1729,6 +1746,10 @@ _cairo_quartz_surface_paint (void *abstract_surface,
|
|||
if (op == CAIRO_OPERATOR_DEST)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
rv = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (rv))
|
||||
return rv;
|
||||
|
||||
CGContextSetCompositeOperation (surface->cgContext, _cairo_quartz_cairo_operator_to_quartz (op));
|
||||
|
||||
action = _cairo_quartz_setup_source (surface, source);
|
||||
|
|
@ -1771,7 +1792,7 @@ _cairo_quartz_surface_fill (void *abstract_surface,
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
|
||||
cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -1790,7 +1811,7 @@ _cairo_quartz_surface_fill (void *abstract_surface,
|
|||
|
||||
/* Check whether the path would be a no-op */
|
||||
/* XXX handle unbounded ops */
|
||||
if (_cairo_path_fixed_is_empty(path) ||
|
||||
if (_cairo_path_fixed_fill_is_empty(path) ||
|
||||
(_cairo_path_fixed_is_box(path, &box) &&
|
||||
box.p1.x == box.p2.x &&
|
||||
box.p1.y == box.p2.y))
|
||||
|
|
@ -1798,6 +1819,10 @@ _cairo_quartz_surface_fill (void *abstract_surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
rv = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (rv))
|
||||
return rv;
|
||||
|
||||
CGContextSaveGState (surface->cgContext);
|
||||
|
||||
CGContextSetShouldAntialias (surface->cgContext, (antialias != CAIRO_ANTIALIAS_NONE));
|
||||
|
|
@ -1879,7 +1904,7 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
|
|||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
|
||||
cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -1896,6 +1921,10 @@ _cairo_quartz_surface_stroke (void *abstract_surface,
|
|||
if (op == CAIRO_OPERATOR_DEST)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
rv = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (rv))
|
||||
return rv;
|
||||
|
||||
CGContextSaveGState (surface->cgContext);
|
||||
|
||||
// Turning antialiasing off used to cause misrendering with
|
||||
|
|
@ -2024,7 +2053,7 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
|
|||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
int *remaining_glyphs,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
CGAffineTransform textTransform, ctm;
|
||||
#define STATIC_BUF_SIZE 64
|
||||
|
|
@ -2055,6 +2084,10 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
|
|||
if (cairo_scaled_font_get_type (scaled_font) != CAIRO_FONT_TYPE_QUARTZ)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
rv = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (rv))
|
||||
return rv;
|
||||
|
||||
CGContextSaveGState (surface->cgContext);
|
||||
|
||||
action = _cairo_quartz_setup_source (surface, source);
|
||||
|
|
@ -2239,10 +2272,10 @@ _cairo_quartz_surface_mask_with_surface (cairo_quartz_surface_t *surface,
|
|||
cairo_surface_t *pat_surf = mask->surface;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
CGAffineTransform ctm, mask_matrix;
|
||||
cairo_bool_t is_bounded;
|
||||
|
||||
status = _cairo_surface_get_extents (pat_surf, &mask_extents);
|
||||
if (status)
|
||||
return status;
|
||||
is_bounded = _cairo_surface_get_extents (pat_surf, &mask_extents);
|
||||
assert (is_bounded);
|
||||
|
||||
// everything would be masked out, so do nothing
|
||||
if (mask_extents.width == 0 || mask_extents.height == 0)
|
||||
|
|
@ -2347,7 +2380,7 @@ _cairo_quartz_surface_mask (void *abstract_surface,
|
|||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
|
||||
cairo_int_status_t rv = CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -2357,6 +2390,10 @@ _cairo_quartz_surface_mask (void *abstract_surface,
|
|||
if (IS_EMPTY(surface))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
rv = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (rv))
|
||||
return rv;
|
||||
|
||||
if (mask->type == CAIRO_PATTERN_TYPE_SOLID) {
|
||||
/* This is easy; we just need to paint with the alpha. */
|
||||
cairo_solid_pattern_t *solid_mask = (cairo_solid_pattern_t *) mask;
|
||||
|
|
@ -2387,14 +2424,15 @@ _cairo_quartz_surface_mask (void *abstract_surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_quartz_surface_intersect_clip_path (void *abstract_surface,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
static cairo_status_t
|
||||
_cairo_quartz_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *) abstract_surface;
|
||||
cairo_quartz_surface_t *surface =
|
||||
cairo_container_of (clipper, cairo_quartz_surface_t, clipper);
|
||||
quartz_stroke_t stroke;
|
||||
cairo_status_t status;
|
||||
|
||||
|
|
@ -2455,8 +2493,6 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
NULL, /* set_clip_region */
|
||||
_cairo_quartz_surface_intersect_clip_path,
|
||||
_cairo_quartz_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
|
|
@ -2477,7 +2513,6 @@ static const struct _cairo_surface_backend cairo_quartz_surface_backend = {
|
|||
|
||||
_cairo_quartz_surface_snapshot,
|
||||
NULL, /* is_similar */
|
||||
NULL, /* reset */
|
||||
NULL /* fill_stroke */
|
||||
};
|
||||
|
||||
|
|
@ -2501,6 +2536,9 @@ _cairo_quartz_surface_create_internal (CGContextRef cgContext,
|
|||
_cairo_surface_init(&surface->base, &cairo_quartz_surface_backend,
|
||||
content);
|
||||
|
||||
_cairo_surface_clipper_init (&surface->clipper,
|
||||
_cairo_quartz_surface_intersect_clip_path);
|
||||
|
||||
/* Save our extents */
|
||||
surface->extents.x = surface->extents.y = 0;
|
||||
surface->extents.width = width;
|
||||
|
|
|
|||
73
src/cairo-region-private.h
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2005 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Owen Taylor <otaylor@redhat.com>
|
||||
* Vladimir Vukicevic <vladimir@pobox.com>
|
||||
* Søren Sandmann <sandmann@daimi.au.dk>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_REGION_PRIVATE_H
|
||||
#define CAIRO_REGION_PRIVATE_H
|
||||
|
||||
#include "cairo-types-private.h"
|
||||
#include "cairo-reference-count-private.h"
|
||||
|
||||
#include <pixman.h>
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
struct _cairo_region {
|
||||
cairo_reference_count_t ref_count;
|
||||
cairo_status_t status;
|
||||
|
||||
pixman_region32_t rgn;
|
||||
};
|
||||
|
||||
cairo_private void
|
||||
_cairo_region_init (cairo_region_t *region);
|
||||
|
||||
cairo_private void
|
||||
_cairo_region_init_rectangle (cairo_region_t *region,
|
||||
const cairo_rectangle_int_t *rectangle);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_region_init_rectangles (cairo_region_t *region,
|
||||
const cairo_rectangle_int_t *rects,
|
||||
int count);
|
||||
|
||||
cairo_private void
|
||||
_cairo_region_fini (cairo_region_t *region);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif /* CAIRO_REGION_PRIVATE_H */
|
||||
|
|
@ -38,7 +38,13 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-region-private.h"
|
||||
|
||||
/* XXX need to update pixman headers to be const as appropriate */
|
||||
#define CONST_CAST (pixman_region32_t *)
|
||||
|
||||
static const cairo_region_t _cairo_region_nil = {
|
||||
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
};
|
||||
|
||||
|
|
@ -82,6 +88,7 @@ _cairo_region_init (cairo_region_t *region)
|
|||
VG (VALGRIND_MAKE_MEM_UNDEFINED (region, sizeof (cairo_region_t)));
|
||||
|
||||
region->status = CAIRO_STATUS_SUCCESS;
|
||||
CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 0);
|
||||
pixman_region32_init (®ion->rgn);
|
||||
}
|
||||
|
||||
|
|
@ -92,6 +99,7 @@ _cairo_region_init_rectangle (cairo_region_t *region,
|
|||
VG (VALGRIND_MAKE_MEM_UNDEFINED (region, sizeof (cairo_region_t)));
|
||||
|
||||
region->status = CAIRO_STATUS_SUCCESS;
|
||||
CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 0);
|
||||
pixman_region32_init_rect (®ion->rgn,
|
||||
rectangle->x, rectangle->y,
|
||||
rectangle->width, rectangle->height);
|
||||
|
|
@ -100,6 +108,7 @@ _cairo_region_init_rectangle (cairo_region_t *region,
|
|||
void
|
||||
_cairo_region_fini (cairo_region_t *region)
|
||||
{
|
||||
assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (®ion->ref_count));
|
||||
pixman_region32_fini (®ion->rgn);
|
||||
VG (VALGRIND_MAKE_MEM_NOACCESS (region, sizeof (cairo_region_t)));
|
||||
}
|
||||
|
|
@ -127,6 +136,7 @@ cairo_region_create (void)
|
|||
return (cairo_region_t *) &_cairo_region_nil;
|
||||
|
||||
region->status = CAIRO_STATUS_SUCCESS;
|
||||
CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 1);
|
||||
|
||||
pixman_region32_init (®ion->rgn);
|
||||
|
||||
|
|
@ -134,29 +144,23 @@ cairo_region_create (void)
|
|||
}
|
||||
slim_hidden_def (cairo_region_create);
|
||||
|
||||
cairo_region_t *
|
||||
cairo_region_create_rectangles (cairo_rectangle_int_t *rects,
|
||||
int count)
|
||||
cairo_status_t
|
||||
_cairo_region_init_rectangles (cairo_region_t *region,
|
||||
const cairo_rectangle_int_t *rects,
|
||||
int count)
|
||||
{
|
||||
pixman_box32_t stack_pboxes[CAIRO_STACK_ARRAY_LENGTH (pixman_box32_t)];
|
||||
pixman_box32_t *pboxes = stack_pboxes;
|
||||
cairo_region_t *region;
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
|
||||
region = _cairo_malloc (sizeof (cairo_region_t));
|
||||
|
||||
if (!region)
|
||||
return (cairo_region_t *)&_cairo_region_nil;
|
||||
|
||||
region->status = CAIRO_STATUS_SUCCESS;
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 0);
|
||||
|
||||
if (count > ARRAY_LENGTH (stack_pboxes)) {
|
||||
pboxes = _cairo_malloc_ab (count, sizeof (pixman_box32_t));
|
||||
|
||||
if (unlikely (pboxes == NULL)) {
|
||||
free (region);
|
||||
return (cairo_region_t *)&_cairo_region_nil;
|
||||
}
|
||||
if (unlikely (pboxes == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
|
|
@ -166,15 +170,35 @@ cairo_region_create_rectangles (cairo_rectangle_int_t *rects,
|
|||
pboxes[i].y2 = rects[i].y + rects[i].height;
|
||||
}
|
||||
|
||||
if (! pixman_region32_init_rects (®ion->rgn, pboxes, count)) {
|
||||
free (region);
|
||||
|
||||
region = (cairo_region_t *)&_cairo_region_nil;
|
||||
}
|
||||
if (! pixman_region32_init_rects (®ion->rgn, pboxes, count))
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
if (pboxes != stack_pboxes)
|
||||
free (pboxes);
|
||||
|
||||
return region->status = status;
|
||||
}
|
||||
|
||||
cairo_region_t *
|
||||
cairo_region_create_rectangles (const cairo_rectangle_int_t *rects,
|
||||
int count)
|
||||
{
|
||||
cairo_region_t *region;
|
||||
cairo_status_t status;
|
||||
|
||||
region = _cairo_malloc (sizeof (cairo_region_t));
|
||||
if (unlikely (region == NULL)) {
|
||||
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
|
||||
return (cairo_region_t *) &_cairo_region_nil;
|
||||
}
|
||||
|
||||
status = _cairo_region_init_rectangles (region, rects, count);
|
||||
if (unlikely (status)) {
|
||||
cairo_region_destroy (region);
|
||||
return (cairo_region_t *) &_cairo_region_nil;
|
||||
}
|
||||
|
||||
CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 1);
|
||||
return region;
|
||||
}
|
||||
slim_hidden_def (cairo_region_create_rectangles);
|
||||
|
|
@ -199,10 +223,11 @@ cairo_region_create_rectangle (const cairo_rectangle_int_t *rectangle)
|
|||
cairo_region_t *region;
|
||||
|
||||
region = _cairo_malloc (sizeof (cairo_region_t));
|
||||
if (region == NULL)
|
||||
if (unlikely (region == NULL))
|
||||
return (cairo_region_t *) &_cairo_region_nil;
|
||||
|
||||
region->status = CAIRO_STATUS_SUCCESS;
|
||||
CAIRO_REFERENCE_COUNT_INIT (®ion->ref_count, 1);
|
||||
|
||||
pixman_region32_init_rect (®ion->rgn,
|
||||
rectangle->x, rectangle->y,
|
||||
|
|
@ -227,18 +252,20 @@ slim_hidden_def (cairo_region_create_rectangle);
|
|||
* Since: 1.10
|
||||
**/
|
||||
cairo_region_t *
|
||||
cairo_region_copy (cairo_region_t *original)
|
||||
cairo_region_copy (const cairo_region_t *original)
|
||||
{
|
||||
cairo_region_t *copy;
|
||||
|
||||
if (original->status)
|
||||
if (original != NULL && original->status)
|
||||
return (cairo_region_t *) &_cairo_region_nil;
|
||||
|
||||
copy = cairo_region_create ();
|
||||
if (copy->status)
|
||||
if (unlikely (copy->status))
|
||||
return copy;
|
||||
|
||||
if (! pixman_region32_copy (©->rgn, &original->rgn)) {
|
||||
if (original != NULL &&
|
||||
! pixman_region32_copy (©->rgn, CONST_CAST &original->rgn))
|
||||
{
|
||||
cairo_region_destroy (copy);
|
||||
return (cairo_region_t *) &_cairo_region_nil;
|
||||
}
|
||||
|
|
@ -247,6 +274,31 @@ cairo_region_copy (cairo_region_t *original)
|
|||
}
|
||||
slim_hidden_def (cairo_region_copy);
|
||||
|
||||
/**
|
||||
* cairo_region_reference:
|
||||
* @region: a #cairo_region_t
|
||||
*
|
||||
* Increases the reference count on @region by one. This prevents
|
||||
* @region from being destroyed until a matching call to
|
||||
* cairo_region_destroy() is made.
|
||||
*
|
||||
* Return value: the referenced #cairo_region_t.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
cairo_region_t *
|
||||
cairo_region_reference (cairo_region_t *region)
|
||||
{
|
||||
if (region == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (®ion->ref_count))
|
||||
return NULL;
|
||||
|
||||
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (®ion->ref_count));
|
||||
|
||||
_cairo_reference_count_inc (®ion->ref_count);
|
||||
return region;
|
||||
}
|
||||
slim_hidden_def (cairo_region_reference);
|
||||
|
||||
/**
|
||||
* cairo_region_destroy:
|
||||
* @region: a #cairo_region_t
|
||||
|
|
@ -260,10 +312,15 @@ slim_hidden_def (cairo_region_copy);
|
|||
void
|
||||
cairo_region_destroy (cairo_region_t *region)
|
||||
{
|
||||
if (region == (cairo_region_t *) &_cairo_region_nil)
|
||||
if (region == NULL || CAIRO_REFERENCE_COUNT_IS_INVALID (®ion->ref_count))
|
||||
return;
|
||||
|
||||
pixman_region32_fini (®ion->rgn);
|
||||
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (®ion->ref_count));
|
||||
|
||||
if (! _cairo_reference_count_dec_and_test (®ion->ref_count))
|
||||
return;
|
||||
|
||||
_cairo_region_fini (region);
|
||||
free (region);
|
||||
}
|
||||
slim_hidden_def (cairo_region_destroy);
|
||||
|
|
@ -279,12 +336,12 @@ slim_hidden_def (cairo_region_destroy);
|
|||
* Since: 1.10
|
||||
**/
|
||||
int
|
||||
cairo_region_num_rectangles (cairo_region_t *region)
|
||||
cairo_region_num_rectangles (const cairo_region_t *region)
|
||||
{
|
||||
if (region->status)
|
||||
return 0;
|
||||
|
||||
return pixman_region32_n_rects (®ion->rgn);
|
||||
return pixman_region32_n_rects (CONST_CAST ®ion->rgn);
|
||||
}
|
||||
slim_hidden_def (cairo_region_num_rectangles);
|
||||
|
||||
|
|
@ -299,7 +356,7 @@ slim_hidden_def (cairo_region_num_rectangles);
|
|||
* Since: 1.10
|
||||
**/
|
||||
void
|
||||
cairo_region_get_rectangle (cairo_region_t *region,
|
||||
cairo_region_get_rectangle (const cairo_region_t *region,
|
||||
int nth,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
|
|
@ -311,7 +368,7 @@ cairo_region_get_rectangle (cairo_region_t *region,
|
|||
return;
|
||||
}
|
||||
|
||||
pbox = pixman_region32_rectangles (®ion->rgn, NULL) + nth;
|
||||
pbox = pixman_region32_rectangles (CONST_CAST ®ion->rgn, NULL) + nth;
|
||||
|
||||
rectangle->x = pbox->x1;
|
||||
rectangle->y = pbox->y1;
|
||||
|
|
@ -330,7 +387,7 @@ slim_hidden_def (cairo_region_get_rectangle);
|
|||
* Since: 1.10
|
||||
**/
|
||||
void
|
||||
cairo_region_get_extents (cairo_region_t *region,
|
||||
cairo_region_get_extents (const cairo_region_t *region,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
pixman_box32_t *pextents;
|
||||
|
|
@ -341,7 +398,7 @@ cairo_region_get_extents (cairo_region_t *region,
|
|||
return;
|
||||
}
|
||||
|
||||
pextents = pixman_region32_extents (®ion->rgn);
|
||||
pextents = pixman_region32_extents (CONST_CAST ®ion->rgn);
|
||||
|
||||
extents->x = pextents->x1;
|
||||
extents->y = pextents->y1;
|
||||
|
|
@ -362,7 +419,7 @@ slim_hidden_def (cairo_region_get_extents);
|
|||
* Since: 1.10
|
||||
**/
|
||||
cairo_status_t
|
||||
cairo_region_status (cairo_region_t *region)
|
||||
cairo_region_status (const cairo_region_t *region)
|
||||
{
|
||||
return region->status;
|
||||
}
|
||||
|
|
@ -564,12 +621,12 @@ slim_hidden_def (cairo_region_union_rectangle);
|
|||
* Since: 1.10
|
||||
**/
|
||||
cairo_bool_t
|
||||
cairo_region_is_empty (cairo_region_t *region)
|
||||
cairo_region_is_empty (const cairo_region_t *region)
|
||||
{
|
||||
if (region->status)
|
||||
return TRUE;
|
||||
|
||||
return ! pixman_region32_not_empty (®ion->rgn);
|
||||
return ! pixman_region32_not_empty (CONST_CAST ®ion->rgn);
|
||||
}
|
||||
slim_hidden_def (cairo_region_is_empty);
|
||||
|
||||
|
|
@ -610,7 +667,7 @@ slim_hidden_def (cairo_region_translate);
|
|||
* Since: 1.10
|
||||
**/
|
||||
cairo_region_overlap_t
|
||||
cairo_region_contains_rectangle (cairo_region_t *region,
|
||||
cairo_region_contains_rectangle (const cairo_region_t *region,
|
||||
const cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
pixman_box32_t pbox;
|
||||
|
|
@ -624,7 +681,8 @@ cairo_region_contains_rectangle (cairo_region_t *region,
|
|||
pbox.x2 = rectangle->x + rectangle->width;
|
||||
pbox.y2 = rectangle->y + rectangle->height;
|
||||
|
||||
poverlap = pixman_region32_contains_rectangle (®ion->rgn, &pbox);
|
||||
poverlap = pixman_region32_contains_rectangle (CONST_CAST ®ion->rgn,
|
||||
&pbox);
|
||||
switch (poverlap) {
|
||||
default:
|
||||
case PIXMAN_REGION_OUT: return CAIRO_REGION_OVERLAP_OUT;
|
||||
|
|
@ -647,14 +705,44 @@ slim_hidden_def (cairo_region_contains_rectangle);
|
|||
* Since: 1.10
|
||||
**/
|
||||
cairo_bool_t
|
||||
cairo_region_contains_point (cairo_region_t *region,
|
||||
cairo_region_contains_point (const cairo_region_t *region,
|
||||
int x, int y)
|
||||
{
|
||||
pixman_box32_t box;
|
||||
|
||||
|
||||
if (region->status)
|
||||
return FALSE;
|
||||
|
||||
return pixman_region32_contains_point (®ion->rgn, x, y, &box);
|
||||
return pixman_region32_contains_point (CONST_CAST ®ion->rgn, x, y, &box);
|
||||
}
|
||||
slim_hidden_def (cairo_region_contains_point);
|
||||
|
||||
/**
|
||||
* cairo_region_equal:
|
||||
* @region_a: a #cairo_region_t
|
||||
* @region_b: a #cairo_region_t
|
||||
*
|
||||
* Compares whether region_a is equivalent to region_b.
|
||||
*
|
||||
* Return value: %TRUE if both regions contained the same coverage,
|
||||
* %FALSE if it is not.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
cairo_bool_t
|
||||
cairo_region_equal (const cairo_region_t *a,
|
||||
const cairo_region_t *b)
|
||||
{
|
||||
/* error objects are never equal */
|
||||
if ((a != NULL && a->status) || (b != NULL && b->status))
|
||||
return FALSE;
|
||||
|
||||
if (a == b)
|
||||
return TRUE;
|
||||
|
||||
if (a == NULL || b == NULL)
|
||||
return FALSE;
|
||||
|
||||
return pixman_region32_equal (CONST_CAST &a->rgn, CONST_CAST &b->rgn);
|
||||
}
|
||||
slim_hidden_def (cairo_region_equal);
|
||||
|
|
|
|||
|
|
@ -1969,18 +1969,19 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
|
|||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
||||
cairo_operator_t op,
|
||||
_cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_surface_t *surface,
|
||||
int source_x,
|
||||
int source_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs)
|
||||
cairo_surface_t *surface,
|
||||
int source_x,
|
||||
int source_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_surface_t *mask = NULL;
|
||||
|
|
@ -2008,7 +2009,9 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
source_x, source_y,
|
||||
dest_x, dest_y,
|
||||
width, height,
|
||||
glyphs, num_glyphs, &remaining_glyphs);
|
||||
glyphs, num_glyphs,
|
||||
clip_region,
|
||||
&remaining_glyphs);
|
||||
glyphs += num_glyphs - remaining_glyphs;
|
||||
num_glyphs = remaining_glyphs;
|
||||
if (remaining_glyphs == 0)
|
||||
|
|
@ -2088,7 +2091,8 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
width, height);
|
||||
width, height,
|
||||
NULL);
|
||||
|
||||
_cairo_pattern_fini (&mask_pattern.base);
|
||||
|
||||
|
|
@ -2116,7 +2120,8 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
0, 0,
|
||||
x - dest_x, y - dest_y,
|
||||
glyph_surface->width,
|
||||
glyph_surface->height);
|
||||
glyph_surface->height,
|
||||
NULL);
|
||||
|
||||
_cairo_pattern_fini (&glyph_pattern.base);
|
||||
|
||||
|
|
@ -2134,7 +2139,8 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
source_x, source_y,
|
||||
0, 0,
|
||||
dest_x, dest_y,
|
||||
width, height);
|
||||
width, height,
|
||||
clip_region);
|
||||
|
||||
_cairo_pattern_fini (&mask_pattern.base);
|
||||
|
||||
|
|
@ -2148,58 +2154,6 @@ CLEANUP_MASK:
|
|||
return _cairo_scaled_font_set_error (scaled_font, status);
|
||||
}
|
||||
|
||||
typedef struct _cairo_scaled_glyph_path_closure {
|
||||
cairo_point_t offset;
|
||||
cairo_path_fixed_t *path;
|
||||
} cairo_scaled_glyph_path_closure_t;
|
||||
|
||||
static cairo_status_t
|
||||
_scaled_glyph_path_move_to (void *abstract_closure,
|
||||
const cairo_point_t *point)
|
||||
{
|
||||
cairo_scaled_glyph_path_closure_t *closure = abstract_closure;
|
||||
|
||||
return _cairo_path_fixed_move_to (closure->path,
|
||||
point->x + closure->offset.x,
|
||||
point->y + closure->offset.y);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_scaled_glyph_path_line_to (void *abstract_closure,
|
||||
const cairo_point_t *point)
|
||||
{
|
||||
cairo_scaled_glyph_path_closure_t *closure = abstract_closure;
|
||||
|
||||
return _cairo_path_fixed_line_to (closure->path,
|
||||
point->x + closure->offset.x,
|
||||
point->y + closure->offset.y);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_scaled_glyph_path_curve_to (void *abstract_closure,
|
||||
const cairo_point_t *p0,
|
||||
const cairo_point_t *p1,
|
||||
const cairo_point_t *p2)
|
||||
{
|
||||
cairo_scaled_glyph_path_closure_t *closure = abstract_closure;
|
||||
|
||||
return _cairo_path_fixed_curve_to (closure->path,
|
||||
p0->x + closure->offset.x,
|
||||
p0->y + closure->offset.y,
|
||||
p1->x + closure->offset.x,
|
||||
p1->y + closure->offset.y,
|
||||
p2->x + closure->offset.x,
|
||||
p2->y + closure->offset.y);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_scaled_glyph_path_close_path (void *abstract_closure)
|
||||
{
|
||||
cairo_scaled_glyph_path_closure_t *closure = abstract_closure;
|
||||
|
||||
return _cairo_path_fixed_close_path (closure->path);
|
||||
}
|
||||
|
||||
/* Add a single-device-unit rectangle to a path. */
|
||||
static cairo_status_t
|
||||
_add_unit_rectangle_to_path (cairo_path_fixed_t *path, int x, int y)
|
||||
|
|
@ -2309,14 +2263,13 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
|
|||
{
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
cairo_scaled_glyph_path_closure_t closure;
|
||||
cairo_path_fixed_t glyph_path_static;
|
||||
cairo_path_fixed_t *glyph_path;
|
||||
|
||||
status = scaled_font->status;
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
closure.path = path;
|
||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
|
|
@ -2325,14 +2278,12 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
|
|||
glyphs[i].index,
|
||||
CAIRO_SCALED_GLYPH_INFO_PATH,
|
||||
&scaled_glyph);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
glyph_path = scaled_glyph->path;
|
||||
else if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
goto BAIL;
|
||||
|
||||
/* If the font is incapable of providing a path, then we'll
|
||||
* have to trace our own from a surface. */
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
} else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
/* If the font is incapable of providing a path, then we'll
|
||||
* have to trace our own from a surface.
|
||||
*/
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
glyphs[i].index,
|
||||
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
||||
|
|
@ -2340,31 +2291,22 @@ _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
|
|||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
||||
glyph_path = _cairo_path_fixed_create ();
|
||||
if (unlikely (glyph_path == NULL)) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto BAIL;
|
||||
}
|
||||
|
||||
_cairo_path_fixed_init (&glyph_path_static);
|
||||
glyph_path = &glyph_path_static;
|
||||
status = _trace_mask_to_path (scaled_glyph->surface, glyph_path);
|
||||
if (unlikely (status)) {
|
||||
_cairo_path_fixed_destroy (glyph_path);
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
}
|
||||
} else {
|
||||
goto BAIL;
|
||||
}
|
||||
|
||||
closure.offset.x = _cairo_fixed_from_double (glyphs[i].x);
|
||||
closure.offset.y = _cairo_fixed_from_double (glyphs[i].y);
|
||||
status = _cairo_path_fixed_append (path,
|
||||
glyph_path, CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_fixed_from_double (glyphs[i].x),
|
||||
_cairo_fixed_from_double (glyphs[i].y));
|
||||
|
||||
status = _cairo_path_fixed_interpret (glyph_path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_scaled_glyph_path_move_to,
|
||||
_scaled_glyph_path_line_to,
|
||||
_scaled_glyph_path_curve_to,
|
||||
_scaled_glyph_path_close_path,
|
||||
&closure);
|
||||
if (glyph_path != scaled_glyph->path)
|
||||
_cairo_path_fixed_destroy (glyph_path);
|
||||
_cairo_path_fixed_fini (glyph_path);
|
||||
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
|
|
|||
|
|
@ -53,6 +53,16 @@ cairo_script_surface_create_for_stream (cairo_write_func_t write_func,
|
|||
double width,
|
||||
double height);
|
||||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_script_surface_create_for_target (cairo_surface_t *surface,
|
||||
cairo_write_func_t write_func,
|
||||
void *closure);
|
||||
|
||||
cairo_public void
|
||||
cairo_script_surface_write_comment (cairo_surface_t *abstract_surface,
|
||||
const char *comment,
|
||||
int len);
|
||||
|
||||
typedef enum {
|
||||
CAIRO_SCRIPT_MODE_BINARY,
|
||||
CAIRO_SCRIPT_MODE_ASCII
|
||||
|
|
|
|||
|
|
@ -132,13 +132,14 @@ _cairo_span_renderer_set_error (void *abstract_renderer,
|
|||
cairo_status_t error);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_path_fixed_fill_using_spans (
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_surface_t *dst,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_composite_rectangles_t *rects);
|
||||
_cairo_path_fixed_fill_using_spans (cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_surface_t *dst,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_composite_rectangles_t *rects,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
#endif /* CAIRO_SPANS_PRIVATE_H */
|
||||
|
|
|
|||
|
|
@ -149,19 +149,19 @@ _create_scan_converter (cairo_fill_rule_t fill_rule,
|
|||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_path_fixed_fill_using_spans (
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_surface_t *dst,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_composite_rectangles_t *rects)
|
||||
_cairo_path_fixed_fill_using_spans (cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_surface_t *dst,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_composite_rectangles_t *rects,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_span_renderer_t *renderer = _cairo_surface_create_span_renderer (
|
||||
op, pattern, dst, antialias, rects);
|
||||
op, pattern, dst, antialias, rects, clip_region);
|
||||
cairo_scan_converter_t *converter = _create_scan_converter (
|
||||
fill_rule, antialias, rects);
|
||||
|
||||
|
|
|
|||
|
|
@ -110,13 +110,13 @@ _cairo_stroke_style_max_distance_from_path (const cairo_stroke_style_t *style,
|
|||
style_expansion = M_SQRT1_2;
|
||||
|
||||
if (style->line_join == CAIRO_LINE_JOIN_MITER &&
|
||||
style_expansion < style->miter_limit)
|
||||
style_expansion < M_SQRT2 * style->miter_limit)
|
||||
{
|
||||
style_expansion = style->miter_limit;
|
||||
style_expansion = M_SQRT2 * style->miter_limit;
|
||||
}
|
||||
|
||||
style_expansion *= style->line_width;
|
||||
|
||||
*dx = style_expansion * (fabs (ctm->xx) + fabs (ctm->xy));
|
||||
*dy = style_expansion * (fabs (ctm->yy) + fabs (ctm->yx));
|
||||
*dx = style_expansion * hypot (ctm->xx, ctm->xy);
|
||||
*dy = style_expansion * hypot (ctm->yy, ctm->yx);
|
||||
}
|
||||
|
|
|
|||
72
src/cairo-surface-clipper-private.h
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Chris Wilson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.u>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_SURFACE_CLIPPER_PRIVATE_H
|
||||
#define CAIRO_SURFACE_CLIPPER_PRIVATE_H
|
||||
|
||||
#include "cairo-types-private.h"
|
||||
#include "cairo-clip-private.h"
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
typedef struct _cairo_surface_clipper cairo_surface_clipper_t;
|
||||
|
||||
typedef cairo_status_t
|
||||
(*cairo_surface_clipper_intersect_clip_path_func_t) (cairo_surface_clipper_t *,
|
||||
cairo_path_fixed_t *,
|
||||
cairo_fill_rule_t,
|
||||
double,
|
||||
cairo_antialias_t);
|
||||
struct _cairo_surface_clipper {
|
||||
cairo_clip_t clip;
|
||||
cairo_bool_t is_clipped;
|
||||
cairo_surface_clipper_intersect_clip_path_func_t intersect_clip_path;
|
||||
};
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_clipper_set_clip (cairo_surface_clipper_t *clipper,
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private void
|
||||
_cairo_surface_clipper_init (cairo_surface_clipper_t *clipper,
|
||||
cairo_surface_clipper_intersect_clip_path_func_t intersect);
|
||||
|
||||
cairo_private void
|
||||
_cairo_surface_clipper_reset (cairo_surface_clipper_t *clipper);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif /* CAIRO_SURFACE_CLIPPER_PRIVATE_H */
|
||||
138
src/cairo-surface-clipper.c
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Chris Wilson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
|
||||
/* A collection of routines to facilitate vector surface clipping */
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_surface_clipper_intersect_clip_path_recursive (cairo_surface_clipper_t *clipper,
|
||||
cairo_clip_path_t *clip_path)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (clip_path->prev != NULL) {
|
||||
status =
|
||||
_cairo_surface_clipper_intersect_clip_path_recursive (clipper,
|
||||
clip_path->prev);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
||||
return clipper->intersect_clip_path (clipper,
|
||||
&clip_path->path,
|
||||
clip_path->fill_rule,
|
||||
clip_path->tolerance,
|
||||
clip_path->antialias);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_surface_clipper_set_clip (cairo_surface_clipper_t *clipper,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_bool_t clear;
|
||||
|
||||
/* XXX as we cache a reference to the path, and compare every time,
|
||||
* we may in future need to install a notification if the clip->path
|
||||
* is every modified (e.g. cairo_clip_translate).
|
||||
*/
|
||||
|
||||
if (clip == NULL && clipper->clip.path == NULL)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (clip != NULL && clip->path == clipper->clip.path)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (clip != NULL && clipper->clip.path != NULL &&
|
||||
_cairo_path_fixed_equal (&clip->path->path, &clipper->clip.path->path))
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* all clipped out state should never propagate this far */
|
||||
assert (clip == NULL || clip->path != NULL);
|
||||
|
||||
/* Check whether this clip is a continuation of the previous.
|
||||
* If not, we have to remove the current clip and rebuild.
|
||||
*/
|
||||
clear = clip == NULL || clip->path->prev != clipper->clip.path;
|
||||
|
||||
_cairo_clip_reset (&clipper->clip);
|
||||
_cairo_clip_init_copy (&clipper->clip, clip);
|
||||
|
||||
if (clear) {
|
||||
clipper->is_clipped = FALSE;
|
||||
status = clipper->intersect_clip_path (clipper, NULL, 0, 0, 0);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (clip != NULL && clip->path != NULL) {
|
||||
status =
|
||||
_cairo_surface_clipper_intersect_clip_path_recursive (clipper,
|
||||
clip->path);
|
||||
clipper->is_clipped = TRUE;
|
||||
}
|
||||
} else {
|
||||
cairo_clip_path_t *path = clip->path;
|
||||
|
||||
clipper->is_clipped = TRUE;
|
||||
status = clipper->intersect_clip_path (clipper,
|
||||
&path->path,
|
||||
path->fill_rule,
|
||||
path->tolerance,
|
||||
path->antialias);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_surface_clipper_init (cairo_surface_clipper_t *clipper,
|
||||
cairo_surface_clipper_intersect_clip_path_func_t func)
|
||||
{
|
||||
_cairo_clip_init (&clipper->clip);
|
||||
clipper->is_clipped = FALSE;
|
||||
clipper->intersect_clip_path = func;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_surface_clipper_reset (cairo_surface_clipper_t *clipper)
|
||||
{
|
||||
_cairo_clip_reset (&clipper->clip);
|
||||
clipper->is_clipped = FALSE;
|
||||
}
|
||||
|
|
@ -44,13 +44,15 @@
|
|||
cairo_private cairo_status_t
|
||||
_cairo_surface_fallback_paint (cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source);
|
||||
const cairo_pattern_t *source,
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_fallback_mask (cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask);
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_fallback_stroke (cairo_surface_t *surface,
|
||||
|
|
@ -61,7 +63,8 @@ _cairo_surface_fallback_stroke (cairo_surface_t *surface,
|
|||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias);
|
||||
cairo_antialias_t antialias,
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_fallback_fill (cairo_surface_t *surface,
|
||||
|
|
@ -70,7 +73,8 @@ _cairo_surface_fallback_fill (cairo_surface_t *surface,
|
|||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias);
|
||||
cairo_antialias_t antialias,
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
|
||||
|
|
@ -78,7 +82,8 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface,
|
|||
const cairo_pattern_t *source,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font);
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_surface_fallback_snapshot (cairo_surface_t *surface);
|
||||
|
|
@ -95,7 +100,8 @@ _cairo_surface_fallback_composite (cairo_operator_t op,
|
|||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
unsigned int height,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_fallback_fill_rectangles (cairo_surface_t *surface,
|
||||
|
|
@ -116,7 +122,8 @@ _cairo_surface_fallback_composite_trapezoids (cairo_operator_t op,
|
|||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_trapezoid_t *traps,
|
||||
int num_traps);
|
||||
int num_traps,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_fallback_clone_similar (cairo_surface_t *surface,
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
#include "cairo-types-private.h"
|
||||
#include "cairo-reference-count-private.h"
|
||||
#include "cairo-clip-private.h"
|
||||
|
||||
typedef void (*cairo_surface_func_t) (cairo_surface_t *);
|
||||
|
||||
|
|
@ -77,24 +78,6 @@ struct _cairo_surface {
|
|||
double x_fallback_resolution;
|
||||
double y_fallback_resolution;
|
||||
|
||||
cairo_clip_t *clip;
|
||||
|
||||
/*
|
||||
* Each time a clip region is modified, it gets the next value in this
|
||||
* sequence. This means that clip regions for this surface are uniquely
|
||||
* identified and updates to the clip can be readily identified
|
||||
*/
|
||||
unsigned int next_clip_serial;
|
||||
/*
|
||||
* The serial number of the current clip. This is set when
|
||||
* the surface clipping is set. The gstate can then cheaply
|
||||
* check whether the surface clipping is already correct before
|
||||
* performing a rendering operation.
|
||||
*
|
||||
* The special value '0' is reserved for the unclipped case.
|
||||
*/
|
||||
unsigned int current_clip_serial;
|
||||
|
||||
/* A "snapshot" surface is immutable. See _cairo_surface_snapshot. */
|
||||
cairo_surface_t *snapshot_of;
|
||||
cairo_surface_func_t snapshot_detach;
|
||||
|
|
|
|||
156
src/cairo-surface-wrapper-private.h
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2002 University of Southern California
|
||||
* Copyright © 2005 Red Hat, Inc.
|
||||
* Copyright © 2009 Chris Wilson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.u>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_SURFACE_WRAPPER_PRIVATE_H
|
||||
#define CAIRO_SURFACE_WRAPPER_PRIVATE_H
|
||||
|
||||
#include "cairo-types-private.h"
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
struct _cairo_surface_wrapper {
|
||||
cairo_surface_t *target;
|
||||
|
||||
/* any other information? */
|
||||
};
|
||||
|
||||
cairo_private void
|
||||
_cairo_surface_wrapper_init (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_surface_t *target);
|
||||
|
||||
cairo_private void
|
||||
_cairo_surface_wrapper_fini (cairo_surface_wrapper_t *wrapper);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_wrapper_acquire_source_image (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_image_surface_t **image_out,
|
||||
void **image_extra);
|
||||
|
||||
cairo_private void
|
||||
_cairo_surface_wrapper_release_source_image (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_image_surface_t *image,
|
||||
void *image_extra);
|
||||
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_operator_t fill_op,
|
||||
const cairo_pattern_t *fill_source,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double fill_tolerance,
|
||||
cairo_antialias_t fill_antialias,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_operator_t stroke_op,
|
||||
const cairo_pattern_t *stroke_source,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
cairo_matrix_t *stroke_ctm,
|
||||
cairo_matrix_t *stroke_ctm_inverse,
|
||||
double stroke_tolerance,
|
||||
cairo_antialias_t stroke_antialias,
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const char *utf8,
|
||||
int utf8_len,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
const cairo_text_cluster_t *clusters,
|
||||
int num_clusters,
|
||||
cairo_text_cluster_flags_t cluster_flags,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_surface_wrapper_create_similar (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height);
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_surface_wrapper_get_extents (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_rectangle_int_t *extents);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_surface_wrapper_has_show_text_glyphs (cairo_surface_wrapper_t *wrapper);
|
||||
|
||||
static inline cairo_bool_t
|
||||
_cairo_surface_wrapper_is_active (cairo_surface_wrapper_t *wrapper)
|
||||
{
|
||||
return wrapper->target != (cairo_surface_t *) 0;
|
||||
}
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif /* CAIRO_SURFACE_WRAPPER_PRIVATE_H */
|
||||
449
src/cairo-surface-wrapper.c
Normal file
|
|
@ -0,0 +1,449 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2005 Red Hat, Inc
|
||||
* Copyright © 2007 Adrian Johnson
|
||||
* Copyright © 2009 Chris Wilson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-surface-wrapper-private.h"
|
||||
|
||||
/* A collection of routines to facilitate surface wrapping */
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_surface_wrapper_needs_device_transform (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_matrix_t *matrix)
|
||||
{
|
||||
if (_cairo_matrix_is_identity (&wrapper->target->device_transform))
|
||||
return FALSE;
|
||||
|
||||
*matrix = wrapper->target->device_transform;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_surface_wrapper_acquire_source_image (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_image_surface_t **image_out,
|
||||
void **image_extra)
|
||||
{
|
||||
if (unlikely (wrapper->target->status))
|
||||
return wrapper->target->status;
|
||||
|
||||
return _cairo_surface_acquire_source_image (wrapper->target,
|
||||
image_out, image_extra);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_surface_wrapper_release_source_image (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_image_surface_t *image,
|
||||
void *image_extra)
|
||||
{
|
||||
_cairo_surface_release_source_image (wrapper->target, image, image_extra);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_matrix_t device_transform;
|
||||
cairo_clip_t clip_copy, *dev_clip = clip;
|
||||
|
||||
if (unlikely (wrapper->target->status))
|
||||
return wrapper->target->status;
|
||||
|
||||
if (clip && clip->all_clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (clip != NULL &&
|
||||
_cairo_surface_wrapper_needs_device_transform (wrapper,
|
||||
&device_transform))
|
||||
{
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip,
|
||||
&device_transform);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
dev_clip = &clip_copy;
|
||||
}
|
||||
|
||||
status = _cairo_surface_paint (wrapper->target, op, source, dev_clip);
|
||||
|
||||
FINISH:
|
||||
if (dev_clip != clip)
|
||||
_cairo_clip_reset (dev_clip);
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_matrix_t device_transform;
|
||||
cairo_clip_t clip_copy, *dev_clip = clip;
|
||||
|
||||
if (unlikely (wrapper->target->status))
|
||||
return wrapper->target->status;
|
||||
|
||||
if (clip && clip->all_clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (clip != NULL &&
|
||||
_cairo_surface_wrapper_needs_device_transform (wrapper,
|
||||
&device_transform))
|
||||
{
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip,
|
||||
&device_transform);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
dev_clip = &clip_copy;
|
||||
}
|
||||
|
||||
status = _cairo_surface_mask (wrapper->target, op, source, mask, dev_clip);
|
||||
|
||||
FINISH:
|
||||
if (dev_clip != clip)
|
||||
_cairo_clip_reset (dev_clip);
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_matrix_t device_transform;
|
||||
cairo_path_fixed_t path_copy, *dev_path = path;
|
||||
cairo_clip_t clip_copy, *dev_clip = clip;
|
||||
cairo_matrix_t dev_ctm = *ctm;
|
||||
cairo_matrix_t dev_ctm_inverse = *ctm_inverse;
|
||||
|
||||
if (unlikely (wrapper->target->status))
|
||||
return wrapper->target->status;
|
||||
|
||||
if (clip && clip->all_clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper,
|
||||
&device_transform))
|
||||
{
|
||||
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
_cairo_path_fixed_transform (&path_copy, &device_transform);
|
||||
dev_path = &path_copy;
|
||||
|
||||
if (clip != NULL) {
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip,
|
||||
&device_transform);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
dev_clip = &clip_copy;
|
||||
}
|
||||
|
||||
cairo_matrix_multiply (&dev_ctm, &dev_ctm, &device_transform);
|
||||
status = cairo_matrix_invert (&device_transform);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
cairo_matrix_multiply (&dev_ctm_inverse,
|
||||
&device_transform,
|
||||
&dev_ctm_inverse);
|
||||
}
|
||||
|
||||
status = _cairo_surface_stroke (wrapper->target, op, source,
|
||||
dev_path, stroke_style,
|
||||
&dev_ctm, &dev_ctm_inverse,
|
||||
tolerance, antialias,
|
||||
dev_clip);
|
||||
|
||||
FINISH:
|
||||
if (dev_path != path)
|
||||
_cairo_path_fixed_fini (dev_path);
|
||||
if (dev_clip != clip)
|
||||
_cairo_clip_reset (dev_clip);
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_operator_t fill_op,
|
||||
const cairo_pattern_t *fill_source,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double fill_tolerance,
|
||||
cairo_antialias_t fill_antialias,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_operator_t stroke_op,
|
||||
const cairo_pattern_t *stroke_source,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
cairo_matrix_t *stroke_ctm,
|
||||
cairo_matrix_t *stroke_ctm_inverse,
|
||||
double stroke_tolerance,
|
||||
cairo_antialias_t stroke_antialias,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_matrix_t device_transform;
|
||||
cairo_path_fixed_t path_copy, *dev_path = path;
|
||||
cairo_clip_t clip_copy, *dev_clip = clip;
|
||||
cairo_matrix_t dev_ctm = *stroke_ctm;
|
||||
cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse;
|
||||
|
||||
if (unlikely (wrapper->target->status))
|
||||
return wrapper->target->status;
|
||||
|
||||
if (clip && clip->all_clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper,
|
||||
&device_transform))
|
||||
{
|
||||
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
_cairo_path_fixed_transform (&path_copy, &device_transform);
|
||||
dev_path = &path_copy;
|
||||
|
||||
if (clip != NULL) {
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip,
|
||||
&device_transform);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
dev_clip = &clip_copy;
|
||||
}
|
||||
|
||||
cairo_matrix_multiply (&dev_ctm, &dev_ctm, &device_transform);
|
||||
status = cairo_matrix_invert (&device_transform);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
cairo_matrix_multiply (&dev_ctm_inverse,
|
||||
&device_transform,
|
||||
&dev_ctm_inverse);
|
||||
}
|
||||
|
||||
status = _cairo_surface_fill_stroke (wrapper->target,
|
||||
fill_op, fill_source, fill_rule,
|
||||
fill_tolerance, fill_antialias,
|
||||
dev_path,
|
||||
stroke_op, stroke_source,
|
||||
stroke_style,
|
||||
&dev_ctm, &dev_ctm_inverse,
|
||||
stroke_tolerance, stroke_antialias,
|
||||
dev_clip);
|
||||
|
||||
FINISH:
|
||||
if (dev_path != path)
|
||||
_cairo_path_fixed_fini (dev_path);
|
||||
if (dev_clip != clip)
|
||||
_cairo_clip_reset (dev_clip);
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_matrix_t device_transform;
|
||||
cairo_path_fixed_t path_copy, *dev_path = path;
|
||||
cairo_clip_t clip_copy, *dev_clip = clip;
|
||||
|
||||
if (unlikely (wrapper->target->status))
|
||||
return wrapper->target->status;
|
||||
|
||||
if (clip && clip->all_clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper,
|
||||
&device_transform))
|
||||
{
|
||||
status = _cairo_path_fixed_init_copy (&path_copy, dev_path);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
_cairo_path_fixed_transform (&path_copy, &device_transform);
|
||||
dev_path = &path_copy;
|
||||
|
||||
if (clip != NULL) {
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip,
|
||||
&device_transform);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
dev_clip = &clip_copy;
|
||||
}
|
||||
}
|
||||
|
||||
status = _cairo_surface_fill (wrapper->target, op, source,
|
||||
dev_path, fill_rule,
|
||||
tolerance, antialias,
|
||||
dev_clip);
|
||||
|
||||
FINISH:
|
||||
if (dev_path != path)
|
||||
_cairo_path_fixed_fini (dev_path);
|
||||
if (dev_clip != clip)
|
||||
_cairo_clip_reset (dev_clip);
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const char *utf8,
|
||||
int utf8_len,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
const cairo_text_cluster_t *clusters,
|
||||
int num_clusters,
|
||||
cairo_text_cluster_flags_t cluster_flags,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_matrix_t device_transform;
|
||||
cairo_clip_t clip_copy, *dev_clip = clip;
|
||||
cairo_glyph_t *dev_glyphs = glyphs;
|
||||
|
||||
if (unlikely (wrapper->target->status))
|
||||
return wrapper->target->status;
|
||||
|
||||
if (glyphs == NULL || num_glyphs == 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (clip && clip->all_clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (_cairo_surface_wrapper_needs_device_transform (wrapper,
|
||||
&device_transform))
|
||||
{
|
||||
int i;
|
||||
|
||||
if (clip != NULL) {
|
||||
dev_clip = &clip_copy;
|
||||
status = _cairo_clip_init_copy_transformed (&clip_copy, clip,
|
||||
&device_transform);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
dev_glyphs = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
|
||||
if (dev_glyphs == NULL) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
dev_glyphs[i] = glyphs[i];
|
||||
cairo_matrix_transform_point (&device_transform,
|
||||
&dev_glyphs[i].x,
|
||||
&dev_glyphs[i].y);
|
||||
}
|
||||
}
|
||||
|
||||
status = _cairo_surface_show_text_glyphs (wrapper->target, op, source,
|
||||
utf8, utf8_len,
|
||||
dev_glyphs, num_glyphs,
|
||||
clusters, num_clusters,
|
||||
cluster_flags,
|
||||
scaled_font,
|
||||
dev_clip);
|
||||
FINISH:
|
||||
if (dev_clip != clip)
|
||||
_cairo_clip_reset (dev_clip);
|
||||
if (dev_glyphs != glyphs)
|
||||
free (dev_glyphs);
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_surface_wrapper_create_similar (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
return _cairo_surface_create_similar_solid (wrapper->target,
|
||||
content, width, height,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_surface_wrapper_has_show_text_glyphs (cairo_surface_wrapper_t *wrapper)
|
||||
{
|
||||
return cairo_surface_has_show_text_glyphs (wrapper->target);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_surface_wrapper_init (cairo_surface_wrapper_t *wrapper,
|
||||
cairo_surface_t *target)
|
||||
{
|
||||
wrapper->target = cairo_surface_reference (target);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_surface_wrapper_fini (cairo_surface_wrapper_t *wrapper)
|
||||
{
|
||||
cairo_surface_destroy (wrapper->target);
|
||||
}
|
||||
|
|
@ -44,6 +44,7 @@
|
|||
#include "cairo-svg.h"
|
||||
|
||||
#include "cairo-surface-private.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
|
||||
typedef struct cairo_svg_document cairo_svg_document_t;
|
||||
|
||||
|
|
@ -52,8 +53,6 @@ typedef struct cairo_svg_surface {
|
|||
|
||||
cairo_content_t content;
|
||||
|
||||
unsigned int id;
|
||||
|
||||
double width;
|
||||
double height;
|
||||
|
||||
|
|
@ -62,6 +61,7 @@ typedef struct cairo_svg_surface {
|
|||
cairo_output_stream_t *xml_node;
|
||||
cairo_array_t page_set;
|
||||
|
||||
cairo_surface_clipper_t clipper;
|
||||
unsigned int clip_level;
|
||||
unsigned int base_clip;
|
||||
cairo_bool_t is_base_clip_emitted;
|
||||
|
|
|
|||
|
|
@ -49,6 +49,7 @@
|
|||
#include "cairo-path-fixed-private.h"
|
||||
#include "cairo-paginated-private.h"
|
||||
#include "cairo-scaled-font-subsets-private.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
#include "cairo-svg-surface-private.h"
|
||||
|
||||
typedef struct cairo_svg_page cairo_svg_page_t;
|
||||
|
|
@ -63,6 +64,11 @@ static const cairo_svg_version_t _cairo_svg_versions[] =
|
|||
|
||||
#define CAIRO_SVG_VERSION_LAST ARRAY_LENGTH (_cairo_svg_versions)
|
||||
|
||||
static void
|
||||
_cairo_svg_surface_emit_path (cairo_output_stream_t *output,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_matrix_t *ctm_inverse);
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_svg_version_has_page_set_support (cairo_svg_version_t version)
|
||||
{
|
||||
|
|
@ -99,7 +105,6 @@ struct cairo_svg_document {
|
|||
cairo_output_stream_t *xml_node_defs;
|
||||
cairo_output_stream_t *xml_node_glyphs;
|
||||
|
||||
unsigned int surface_id;
|
||||
unsigned int linear_pattern_id;
|
||||
unsigned int radial_pattern_id;
|
||||
unsigned int pattern_id;
|
||||
|
|
@ -109,18 +114,11 @@ struct cairo_svg_document {
|
|||
|
||||
cairo_bool_t alpha_filter;
|
||||
|
||||
cairo_array_t meta_snapshots;
|
||||
|
||||
cairo_svg_version_t svg_version;
|
||||
|
||||
cairo_scaled_font_subsets_t *font_subsets;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
unsigned int id;
|
||||
cairo_meta_surface_t *meta;
|
||||
} cairo_meta_snapshot_t;
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_svg_document_create (cairo_output_stream_t *stream,
|
||||
double width,
|
||||
|
|
@ -278,8 +276,8 @@ _extract_svg_surface (cairo_surface_t *surface,
|
|||
* Since: 1.2
|
||||
**/
|
||||
void
|
||||
cairo_svg_surface_restrict_to_version (cairo_surface_t *abstract_surface,
|
||||
cairo_svg_version_t version)
|
||||
cairo_svg_surface_restrict_to_version (cairo_surface_t *abstract_surface,
|
||||
cairo_svg_version_t version)
|
||||
{
|
||||
cairo_svg_surface_t *surface = NULL; /* hide compiler warning */
|
||||
cairo_status_t status;
|
||||
|
|
@ -306,7 +304,7 @@ cairo_svg_surface_restrict_to_version (cairo_surface_t *abstract_surface,
|
|||
**/
|
||||
void
|
||||
cairo_svg_get_versions (cairo_svg_version_t const **versions,
|
||||
int *num_versions)
|
||||
int *num_versions)
|
||||
{
|
||||
if (versions != NULL)
|
||||
*versions = _cairo_svg_versions;
|
||||
|
|
@ -336,6 +334,73 @@ cairo_svg_version_to_string (cairo_svg_version_t version)
|
|||
return _cairo_svg_version_strings[version];
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cliprect_covers_surface (cairo_svg_surface_t *surface,
|
||||
cairo_path_fixed_t *path)
|
||||
{
|
||||
cairo_box_t box;
|
||||
|
||||
if (_cairo_path_fixed_is_rectangle (path, &box)) {
|
||||
if (box.p1.x <= 0 &&
|
||||
box.p1.y <= 0 &&
|
||||
_cairo_fixed_to_double (box.p2.x) >= surface->width &&
|
||||
_cairo_fixed_to_double (box.p2.y) >= surface->height)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_svg_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_svg_surface_t *surface = cairo_container_of (clipper,
|
||||
cairo_svg_surface_t,
|
||||
clipper);
|
||||
cairo_svg_document_t *document = surface->document;
|
||||
unsigned int i;
|
||||
|
||||
if (path == NULL) {
|
||||
for (i = 0; i < surface->clip_level; i++)
|
||||
_cairo_output_stream_printf (surface->xml_node, "</g>\n");
|
||||
|
||||
surface->clip_level = 0;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* skip trivial whole-page clips */
|
||||
if (_cliprect_covers_surface (surface, path))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<clipPath id=\"clip%d\">\n"
|
||||
" <path ",
|
||||
document->clip_id);
|
||||
_cairo_svg_surface_emit_path (document->xml_node_defs, path, NULL);
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"/>\n"
|
||||
"</clipPath>\n");
|
||||
|
||||
_cairo_output_stream_printf (surface->xml_node,
|
||||
"<g clip-path=\"url(#clip%d)\" "
|
||||
"clip-rule=\"%s\">\n",
|
||||
document->clip_id,
|
||||
fill_rule == CAIRO_FILL_RULE_EVEN_ODD ?
|
||||
"evenodd" : "nonzero");
|
||||
|
||||
document->clip_id++;
|
||||
surface->clip_level++;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
|
||||
cairo_content_t content,
|
||||
|
|
@ -359,8 +424,9 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
|
|||
surface->document = _cairo_svg_document_reference (document);
|
||||
|
||||
surface->clip_level = 0;
|
||||
_cairo_surface_clipper_init (&surface->clipper,
|
||||
_cairo_svg_surface_clipper_intersect_clip_path);
|
||||
|
||||
surface->id = document->surface_id++;
|
||||
surface->base_clip = document->clip_id++;
|
||||
surface->is_base_clip_emitted = FALSE;
|
||||
|
||||
|
|
@ -388,8 +454,6 @@ _cairo_svg_surface_create_for_document (cairo_svg_document_t *document,
|
|||
|
||||
paginated = _cairo_paginated_surface_create (&surface->base,
|
||||
surface->content,
|
||||
surface->width,
|
||||
surface->height,
|
||||
&cairo_svg_surface_paginated_backend);
|
||||
status = paginated->status;
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
|
|
@ -457,7 +521,7 @@ _cairo_svg_surface_store_page (cairo_svg_surface_t *surface)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
page.surface_id = surface->id;
|
||||
page.surface_id = surface->base.unique_id;
|
||||
page.clip_level = surface->clip_level;
|
||||
page.xml_node = surface->xml_node;
|
||||
|
||||
|
|
@ -468,11 +532,13 @@ _cairo_svg_surface_store_page (cairo_svg_surface_t *surface)
|
|||
|
||||
surface->xml_node = stream;
|
||||
surface->clip_level = 0;
|
||||
|
||||
for (i = 0; i < page.clip_level; i++)
|
||||
_cairo_output_stream_printf (page.xml_node, "</g>\n");
|
||||
|
||||
return _cairo_array_index (&surface->page_set, surface->page_set.num_elements - 1);
|
||||
_cairo_surface_clipper_reset (&surface->clipper);
|
||||
|
||||
return _cairo_array_index (&surface->page_set,
|
||||
surface->page_set.num_elements - 1);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -486,7 +552,6 @@ _cairo_svg_surface_copy_page (void *abstract_surface)
|
|||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
_cairo_memory_stream_copy (page->xml_node, surface->xml_node);
|
||||
surface->clip_level = page->clip_level;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
@ -596,7 +661,7 @@ _cairo_svg_path_close_path (void *closure)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
static void
|
||||
_cairo_svg_surface_emit_path (cairo_output_stream_t *output,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_matrix_t *ctm_inverse)
|
||||
|
|
@ -615,12 +680,9 @@ _cairo_svg_surface_emit_path (cairo_output_stream_t *output,
|
|||
_cairo_svg_path_curve_to,
|
||||
_cairo_svg_path_close_path,
|
||||
&info);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
_cairo_output_stream_printf (output, "\"");
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -642,9 +704,8 @@ _cairo_svg_document_emit_outline_glyph_data (cairo_svg_document_t *document,
|
|||
_cairo_output_stream_printf (document->xml_node_glyphs,
|
||||
"<path style=\"stroke:none;\" ");
|
||||
|
||||
status = _cairo_svg_surface_emit_path (document->xml_node_glyphs, scaled_glyph->path, NULL);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
_cairo_svg_surface_emit_path (document->xml_node_glyphs,
|
||||
scaled_glyph->path, NULL);
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_glyphs,
|
||||
"/>\n");
|
||||
|
|
@ -847,22 +908,7 @@ _cairo_svg_surface_operation_supported (cairo_svg_surface_t *surface,
|
|||
cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern)
|
||||
{
|
||||
if (_cairo_svg_surface_analyze_operation (surface, op, pattern)
|
||||
!= CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
{
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_svg_surface_create_similar (void *abstract_src,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
return cairo_meta_surface_create (content, width, height);
|
||||
return _cairo_svg_surface_analyze_operation (surface, op, pattern) != CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
@ -893,6 +939,8 @@ _cairo_svg_surface_finish (void *abstract_surface)
|
|||
}
|
||||
_cairo_array_fini (&surface->page_set);
|
||||
|
||||
_cairo_surface_clipper_reset (&surface->clipper);
|
||||
|
||||
status2 = _cairo_svg_document_destroy (document);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = status2;
|
||||
|
|
@ -900,6 +948,7 @@ _cairo_svg_surface_finish (void *abstract_surface)
|
|||
return status;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
_cairo_svg_surface_emit_alpha_filter (cairo_svg_document_t *document)
|
||||
{
|
||||
|
|
@ -1120,112 +1169,139 @@ _cairo_svg_surface_emit_operator_for_style (cairo_output_stream_t *output,
|
|||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_svg_surface_emit_composite_image_pattern (cairo_output_stream_t *output,
|
||||
cairo_svg_surface_t *svg_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_pattern_t *pattern,
|
||||
int pattern_id,
|
||||
const cairo_matrix_t *parent_matrix,
|
||||
const char *extra_attributes)
|
||||
_cairo_svg_surface_emit_surface (cairo_svg_document_t *document,
|
||||
cairo_surface_t *surface)
|
||||
{
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_bool_t is_bounded;
|
||||
cairo_status_t status;
|
||||
cairo_matrix_t p2u;
|
||||
|
||||
status = _cairo_surface_get_extents (pattern->surface, &extents);
|
||||
if (_cairo_user_data_array_get_data (&surface->user_data,
|
||||
(cairo_user_data_key_t *) document))
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
is_bounded = _cairo_surface_get_extents (surface, &extents);
|
||||
assert (is_bounded);
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<image id=\"image%d\" width=\"%d\" height=\"%d\"",
|
||||
surface->unique_id,
|
||||
extents.width, extents.height);
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_defs, " xlink:href=\"");
|
||||
|
||||
status = _cairo_surface_base64_encode (surface,
|
||||
document->xml_node_defs);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_defs, "\"/>\n");
|
||||
|
||||
/* and tag it */
|
||||
return _cairo_user_data_array_set_data (&surface->user_data,
|
||||
(cairo_user_data_key_t *) document,
|
||||
document, NULL);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_svg_surface_emit_composite_surface_pattern (cairo_output_stream_t *output,
|
||||
cairo_svg_surface_t *svg_surface,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_pattern_t *pattern,
|
||||
int pattern_id,
|
||||
const cairo_matrix_t *parent_matrix,
|
||||
const char *extra_attributes)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_matrix_t p2u;
|
||||
|
||||
p2u = pattern->base.matrix;
|
||||
status = cairo_matrix_invert (&p2u);
|
||||
/* cairo_pattern_set_matrix ensures the matrix is invertible */
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
status = _cairo_svg_surface_emit_surface (svg_surface->document,
|
||||
pattern->surface);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (pattern_id != invalid_pattern_id) {
|
||||
cairo_rectangle_int_t extents;
|
||||
cairo_bool_t is_bounded;
|
||||
|
||||
is_bounded = _cairo_surface_get_extents (pattern->surface, &extents);
|
||||
assert (is_bounded);
|
||||
|
||||
_cairo_output_stream_printf (output,
|
||||
"<pattern id=\"pattern%d\" "
|
||||
"patternUnits=\"userSpaceOnUse\" "
|
||||
"width=\"%d\" height=\"%d\"",
|
||||
"width=\"%d\" height=\"%d\" ",
|
||||
pattern_id,
|
||||
extents.width, extents.height);
|
||||
_cairo_svg_surface_emit_transform (output, " patternTransform", &p2u, parent_matrix);
|
||||
_cairo_output_stream_printf (output, ">\n");
|
||||
_cairo_svg_surface_emit_transform (output,
|
||||
" patternTransform",
|
||||
&p2u, parent_matrix);
|
||||
_cairo_output_stream_printf (output, ">\n ");
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (output,
|
||||
" <image width=\"%d\" height=\"%d\"",
|
||||
extents.width, extents.height);
|
||||
|
||||
if (pattern_id == invalid_pattern_id) {
|
||||
_cairo_svg_surface_emit_operator (output, svg_surface, op);
|
||||
_cairo_svg_surface_emit_transform (output, " transform", &p2u, parent_matrix);
|
||||
}
|
||||
|
||||
"<use xlink:href=\"#image%d\"",
|
||||
pattern->surface->unique_id);
|
||||
if (extra_attributes)
|
||||
_cairo_output_stream_printf (output, " %s", extra_attributes);
|
||||
|
||||
_cairo_output_stream_printf (output, " xlink:href=\"");
|
||||
if (pattern_id == invalid_pattern_id) {
|
||||
_cairo_svg_surface_emit_operator (output, svg_surface, op);
|
||||
_cairo_svg_surface_emit_transform (output,
|
||||
" transform",
|
||||
&p2u, parent_matrix);
|
||||
}
|
||||
_cairo_output_stream_printf (output, "/>\n");
|
||||
|
||||
status = _cairo_surface_base64_encode (pattern->surface, output);
|
||||
|
||||
_cairo_output_stream_printf (output, "\"/>\n");
|
||||
|
||||
if (pattern_id != invalid_pattern_id)
|
||||
_cairo_output_stream_printf (output, "</pattern>\n");
|
||||
|
||||
return status;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
|
||||
cairo_meta_surface_t *surface,
|
||||
int *id)
|
||||
cairo_meta_surface_t *source)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_surface_t *paginated_surface;
|
||||
cairo_svg_surface_t *svg_surface;
|
||||
cairo_meta_snapshot_t new_snapshot;
|
||||
cairo_array_t *page_set;
|
||||
|
||||
cairo_output_stream_t *contents;
|
||||
cairo_meta_surface_t *meta;
|
||||
cairo_meta_snapshot_t *snapshot;
|
||||
unsigned int num_elements;
|
||||
unsigned int i;
|
||||
|
||||
/* search in already emitted meta snapshots */
|
||||
num_elements = document->meta_snapshots.num_elements;
|
||||
for (i = 0; i < num_elements; i++) {
|
||||
snapshot = _cairo_array_index (&document->meta_snapshots, i);
|
||||
meta = snapshot->meta;
|
||||
if (meta->commands.num_elements == surface->commands.num_elements &&
|
||||
_cairo_array_index (&meta->commands, 0) == _cairo_array_index (&surface->commands, 0)) {
|
||||
*id = snapshot->id;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
if (_cairo_user_data_array_get_data (&source->base.user_data,
|
||||
(cairo_user_data_key_t *) document))
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
meta = (cairo_meta_surface_t *) _cairo_surface_snapshot (&surface->base);
|
||||
if (unlikely (meta->base.status))
|
||||
return meta->base.status;
|
||||
|
||||
paginated_surface = _cairo_svg_surface_create_for_document (document,
|
||||
meta->content,
|
||||
meta->width_pixels,
|
||||
meta->height_pixels);
|
||||
if (paginated_surface->status) {
|
||||
cairo_surface_destroy (&meta->base);
|
||||
source->content,
|
||||
source->extents_pixels.width,
|
||||
source->extents_pixels.height);
|
||||
if (unlikely (paginated_surface->status))
|
||||
return paginated_surface->status;
|
||||
}
|
||||
|
||||
svg_surface = (cairo_svg_surface_t *) _cairo_paginated_surface_get_target (paginated_surface);
|
||||
svg_surface = (cairo_svg_surface_t *)
|
||||
_cairo_paginated_surface_get_target (paginated_surface);
|
||||
cairo_surface_set_fallback_resolution (paginated_surface,
|
||||
document->owner->x_fallback_resolution,
|
||||
document->owner->y_fallback_resolution);
|
||||
cairo_surface_set_device_offset (&svg_surface->base,
|
||||
-source->extents_pixels.x,
|
||||
-source->extents_pixels.y);
|
||||
|
||||
status = cairo_meta_surface_replay (&meta->base, paginated_surface);
|
||||
status = cairo_meta_surface_replay (&source->base, paginated_surface);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (&meta->base);
|
||||
cairo_surface_destroy (paginated_surface);
|
||||
return status;
|
||||
}
|
||||
|
|
@ -1233,21 +1309,11 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
|
|||
cairo_surface_show_page (paginated_surface);
|
||||
status = cairo_surface_status (paginated_surface);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (&meta->base);
|
||||
cairo_surface_destroy (paginated_surface);
|
||||
return status;
|
||||
}
|
||||
|
||||
new_snapshot.meta = meta;
|
||||
new_snapshot.id = svg_surface->id;
|
||||
status = _cairo_array_append (&document->meta_snapshots, &new_snapshot);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (&meta->base);
|
||||
cairo_surface_destroy (paginated_surface);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!svg_surface->is_base_clip_emitted) {
|
||||
if (! svg_surface->is_base_clip_emitted) {
|
||||
svg_surface->is_base_clip_emitted = TRUE;
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<clipPath id=\"clip%d\">\n"
|
||||
|
|
@ -1258,19 +1324,19 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
|
|||
svg_surface->height);
|
||||
}
|
||||
|
||||
if (meta->content == CAIRO_CONTENT_ALPHA) {
|
||||
if (source->content == CAIRO_CONTENT_ALPHA) {
|
||||
_cairo_svg_surface_emit_alpha_filter (document);
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<g id=\"surface%d\" "
|
||||
"clip-path=\"url(#clip%d)\" "
|
||||
"filter=\"url(#alpha)\">\n",
|
||||
svg_surface->id,
|
||||
source->base.unique_id,
|
||||
svg_surface->base_clip);
|
||||
} else {
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<g id=\"surface%d\" "
|
||||
"clip-path=\"url(#clip%d)\">\n",
|
||||
svg_surface->id,
|
||||
source->base.unique_id,
|
||||
svg_surface->base_clip);
|
||||
}
|
||||
|
||||
|
|
@ -1293,19 +1359,16 @@ _cairo_svg_surface_emit_meta_surface (cairo_svg_document_t *document,
|
|||
|
||||
_cairo_output_stream_printf (document->xml_node_defs, "</g>\n");
|
||||
|
||||
*id = new_snapshot.id;
|
||||
|
||||
status = cairo_surface_status (paginated_surface);
|
||||
cairo_surface_destroy (paginated_surface);
|
||||
|
||||
/* FIXME: cairo_paginated_surface doesn't take a ref to the
|
||||
* passed in target surface so we can't call destroy here.
|
||||
* cairo_paginated_surface should be fixed, but for now just
|
||||
* work around it. */
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
/* cairo_surface_destroy (svg_surface); */
|
||||
|
||||
return status;
|
||||
/* and tag it */
|
||||
return _cairo_user_data_array_set_data (&source->base.user_data,
|
||||
(cairo_user_data_key_t *) document,
|
||||
document, NULL);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
@ -1321,7 +1384,6 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
|
|||
cairo_meta_surface_t *meta_surface;
|
||||
cairo_matrix_t p2u;
|
||||
cairo_status_t status;
|
||||
int id = 0;
|
||||
|
||||
p2u = pattern->base.matrix;
|
||||
status = cairo_matrix_invert (&p2u);
|
||||
|
|
@ -1329,8 +1391,7 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
|
|||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
meta_surface = (cairo_meta_surface_t *) pattern->surface;
|
||||
|
||||
status = _cairo_svg_surface_emit_meta_surface (document, meta_surface, &id);
|
||||
status = _cairo_svg_surface_emit_meta_surface (document, meta_surface);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
|
|
@ -1340,15 +1401,15 @@ _cairo_svg_surface_emit_composite_meta_pattern (cairo_output_stream_t *output,
|
|||
"patternUnits=\"userSpaceOnUse\" "
|
||||
"width=\"%d\" height=\"%d\"",
|
||||
pattern_id,
|
||||
(int) ceil (meta_surface->width_pixels),
|
||||
(int) ceil (meta_surface->height_pixels));
|
||||
meta_surface->extents.width,
|
||||
meta_surface->extents.height);
|
||||
_cairo_svg_surface_emit_transform (output, " patternTransform", &p2u, parent_matrix);
|
||||
_cairo_output_stream_printf (output, ">\n");
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (output,
|
||||
"<use xlink:href=\"#surface%d\"",
|
||||
id);
|
||||
meta_surface->base.unique_id);
|
||||
|
||||
if (pattern_id == invalid_pattern_id) {
|
||||
_cairo_svg_surface_emit_operator (output, surface, op);
|
||||
|
|
@ -1377,12 +1438,18 @@ _cairo_svg_surface_emit_composite_pattern (cairo_output_stream_t *output,
|
|||
{
|
||||
|
||||
if (_cairo_surface_is_meta (pattern->surface)) {
|
||||
return _cairo_svg_surface_emit_composite_meta_pattern (output, surface, op, pattern,
|
||||
pattern_id, parent_matrix, extra_attributes);
|
||||
return _cairo_svg_surface_emit_composite_meta_pattern (output, surface,
|
||||
op, pattern,
|
||||
pattern_id,
|
||||
parent_matrix,
|
||||
extra_attributes);
|
||||
}
|
||||
|
||||
return _cairo_svg_surface_emit_composite_image_pattern (output, surface, op, pattern,
|
||||
pattern_id, parent_matrix, extra_attributes);
|
||||
return _cairo_svg_surface_emit_composite_surface_pattern (output, surface,
|
||||
op, pattern,
|
||||
pattern_id,
|
||||
parent_matrix,
|
||||
extra_attributes);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
@ -1716,7 +1783,9 @@ _cairo_svg_surface_emit_radial_pattern (cairo_svg_surface_t *surface,
|
|||
document->radial_pattern_id,
|
||||
x1, y1,
|
||||
x1, y1, r1);
|
||||
_cairo_svg_surface_emit_transform (document->xml_node_defs, "gradientTransform", &p2u, parent_matrix);
|
||||
_cairo_svg_surface_emit_transform (document->xml_node_defs,
|
||||
"gradientTransform",
|
||||
&p2u, parent_matrix);
|
||||
_cairo_output_stream_printf (document->xml_node_defs, ">\n");
|
||||
|
||||
if (extend == CAIRO_EXTEND_NONE || n_stops < 1)
|
||||
|
|
@ -1981,11 +2050,15 @@ _cairo_svg_surface_fill_stroke (void *abstract_surface,
|
|||
cairo_matrix_t *stroke_ctm_inverse,
|
||||
double stroke_tolerance,
|
||||
cairo_antialias_t stroke_antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->xml_node, "<path style=\"");
|
||||
status = _cairo_svg_surface_emit_fill_style (surface->xml_node, surface, fill_op,
|
||||
fill_source, fill_rule, stroke_ctm_inverse);
|
||||
|
|
@ -1999,9 +2072,7 @@ _cairo_svg_surface_fill_stroke (void *abstract_surface,
|
|||
|
||||
_cairo_output_stream_printf (surface->xml_node, "\" ");
|
||||
|
||||
status = _cairo_svg_surface_emit_path (surface->xml_node, path, stroke_ctm_inverse);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
_cairo_svg_surface_emit_path (surface->xml_node, path, stroke_ctm_inverse);
|
||||
|
||||
_cairo_svg_surface_emit_transform (surface->xml_node, " transform", stroke_ctm, NULL);
|
||||
_cairo_output_stream_printf (surface->xml_node, "/>\n");
|
||||
|
|
@ -2017,7 +2088,7 @@ _cairo_svg_surface_fill (void *abstract_surface,
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
|
@ -2027,6 +2098,10 @@ _cairo_svg_surface_fill (void *abstract_surface,
|
|||
|
||||
assert (_cairo_svg_surface_operation_supported (surface, op, source));
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->xml_node, "<path style=\" stroke:none;");
|
||||
status = _cairo_svg_surface_emit_fill_style (surface->xml_node, surface, op, source, fill_rule, NULL);
|
||||
if (unlikely (status))
|
||||
|
|
@ -2034,16 +2109,14 @@ _cairo_svg_surface_fill (void *abstract_surface,
|
|||
|
||||
_cairo_output_stream_printf (surface->xml_node, "\" ");
|
||||
|
||||
status = _cairo_svg_surface_emit_path (surface->xml_node, path, NULL);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
_cairo_svg_surface_emit_path (surface->xml_node, path, NULL);
|
||||
|
||||
_cairo_output_stream_printf (surface->xml_node, "/>\n");
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_svg_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
|
|
@ -2053,13 +2126,13 @@ _cairo_svg_surface_get_extents (void *abstract_surface,
|
|||
rectangle->y = 0;
|
||||
|
||||
/* XXX: The conversion to integers here is pretty bogus, (not to
|
||||
* mention the aribitray limitation of width to a short(!). We
|
||||
* mention the arbitrary limitation of width to a short(!). We
|
||||
* may need to come up with a better interface for get_size.
|
||||
*/
|
||||
rectangle->width = (int) ceil (surface->width);
|
||||
rectangle->height = (int) ceil (surface->height);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
@ -2106,52 +2179,63 @@ static cairo_int_status_t
|
|||
_cairo_svg_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _cairo_svg_surface_analyze_operation (surface, op, source);
|
||||
|
||||
assert (_cairo_svg_surface_operation_supported (surface, op, source));
|
||||
|
||||
/* Emulation of clear and source operators, when no clipping region
|
||||
* is defined. We just delete existing content of surface root node,
|
||||
* and exit early if operator is clear.
|
||||
* XXX: optimization of SOURCE operator doesn't work, since analyze
|
||||
* above always return FALSE. In order to make it work, we need a way
|
||||
* to know if there's an active clipping path.
|
||||
* Optimization of CLEAR works because of a test in paginated surface,
|
||||
* and an optimization in meta surface. */
|
||||
if (surface->clip_level == 0 && op == CAIRO_OPERATOR_CLEAR) {
|
||||
status = _cairo_output_stream_destroy (surface->xml_node);
|
||||
if (unlikely (status)) {
|
||||
surface->xml_node = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
surface->xml_node = _cairo_memory_stream_create ();
|
||||
if (_cairo_output_stream_get_status (surface->xml_node)) {
|
||||
status = _cairo_output_stream_destroy (surface->xml_node);
|
||||
surface->xml_node = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
if (surface->content == CAIRO_CONTENT_COLOR) {
|
||||
_cairo_output_stream_printf (surface->xml_node,
|
||||
"<rect "
|
||||
"width=\"%f\" height=\"%f\" "
|
||||
"style=\"opacity:1;"
|
||||
"stroke:none;"
|
||||
"fill:rgb(0,0,0);\"/>\n",
|
||||
surface->width, surface->height);
|
||||
}
|
||||
*/
|
||||
if ((op == CAIRO_OPERATOR_CLEAR || op == CAIRO_OPERATOR_SOURCE) &&
|
||||
clip == NULL)
|
||||
{
|
||||
switch (surface->paginated_mode) {
|
||||
case CAIRO_PAGINATED_MODE_FALLBACK:
|
||||
ASSERT_NOT_REACHED;
|
||||
case CAIRO_PAGINATED_MODE_ANALYZE:
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
case CAIRO_PAGINATED_MODE_RENDER:
|
||||
status = _cairo_output_stream_destroy (surface->xml_node);
|
||||
if (unlikely (status)) {
|
||||
surface->xml_node = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
surface->xml_node = _cairo_memory_stream_create ();
|
||||
if (_cairo_output_stream_get_status (surface->xml_node)) {
|
||||
status = _cairo_output_stream_destroy (surface->xml_node);
|
||||
surface->xml_node = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
if (surface->content == CAIRO_CONTENT_COLOR) {
|
||||
_cairo_output_stream_printf (surface->xml_node,
|
||||
"<rect "
|
||||
"width=\"%f\" height=\"%f\" "
|
||||
"style=\"opacity:1;"
|
||||
"stroke:none;"
|
||||
"fill:rgb(0,0,0);\"/>\n",
|
||||
surface->width, surface->height);
|
||||
}
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return _cairo_svg_surface_analyze_operation (surface, op, source);
|
||||
|
||||
assert (_cairo_svg_surface_operation_supported (surface, op, source));
|
||||
}
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
return _cairo_svg_surface_emit_paint (surface->xml_node,
|
||||
surface, op, source, 0, NULL);
|
||||
}
|
||||
|
|
@ -2161,7 +2245,7 @@ _cairo_svg_surface_mask (void *abstract_surface,
|
|||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
|
|
@ -2189,6 +2273,10 @@ _cairo_svg_surface_mask (void *abstract_surface,
|
|||
assert (_cairo_svg_surface_operation_supported (surface, op, source));
|
||||
assert (_cairo_svg_surface_operation_supported (surface, CAIRO_OPERATOR_OVER, mask));
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (mask->type == CAIRO_PATTERN_TYPE_SURFACE) {
|
||||
const cairo_surface_pattern_t *surface_pattern = (const cairo_surface_pattern_t*) mask;
|
||||
cairo_content_t content = cairo_surface_get_content (surface_pattern->surface);
|
||||
|
|
@ -2249,7 +2337,7 @@ _cairo_svg_surface_stroke (void *abstract_dst,
|
|||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_svg_surface_t *surface = abstract_dst;
|
||||
cairo_status_t status;
|
||||
|
|
@ -2259,6 +2347,10 @@ _cairo_svg_surface_stroke (void *abstract_dst,
|
|||
|
||||
assert (_cairo_svg_surface_operation_supported (surface, op, source));
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (surface->xml_node, "<path style=\"fill:none;");
|
||||
status = _cairo_svg_surface_emit_stroke_style (surface->xml_node, surface, op,
|
||||
source, stroke_style, ctm_inverse);
|
||||
|
|
@ -2267,9 +2359,7 @@ _cairo_svg_surface_stroke (void *abstract_dst,
|
|||
|
||||
_cairo_output_stream_printf (surface->xml_node, "\" ");
|
||||
|
||||
status = _cairo_svg_surface_emit_path (surface->xml_node, path, ctm_inverse);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
_cairo_svg_surface_emit_path (surface->xml_node, path, ctm_inverse);
|
||||
|
||||
_cairo_svg_surface_emit_transform (surface->xml_node, " transform", ctm, NULL);
|
||||
_cairo_output_stream_printf (surface->xml_node, "/>\n");
|
||||
|
|
@ -2284,8 +2374,8 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
|
|||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
int *remaining_glyphs,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs)
|
||||
{
|
||||
cairo_svg_surface_t *surface = abstract_surface;
|
||||
cairo_svg_document_t *document = surface->document;
|
||||
|
|
@ -2302,6 +2392,10 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
|
|||
if (num_glyphs <= 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
/* FIXME it's probably possible to apply a pattern of a gradient to
|
||||
* a group of symbols, but I don't know how yet. Gradients or patterns
|
||||
* are translated by x and y properties of use element. */
|
||||
|
|
@ -2349,7 +2443,9 @@ _cairo_svg_surface_show_glyphs (void *abstract_surface,
|
|||
FALLBACK:
|
||||
_cairo_path_fixed_init (&path);
|
||||
|
||||
status = _cairo_scaled_font_glyph_path (scaled_font,(cairo_glyph_t *) glyphs, num_glyphs, &path);
|
||||
status = _cairo_scaled_font_glyph_path (scaled_font,
|
||||
(cairo_glyph_t *) glyphs,
|
||||
num_glyphs, &path);
|
||||
|
||||
if (unlikely (status)) {
|
||||
_cairo_path_fixed_fini (&path);
|
||||
|
|
@ -2357,58 +2453,15 @@ FALLBACK:
|
|||
}
|
||||
|
||||
status = _cairo_svg_surface_fill (abstract_surface, op, pattern,
|
||||
&path, CAIRO_FILL_RULE_WINDING, 0.0, CAIRO_ANTIALIAS_SUBPIXEL, NULL);
|
||||
&path, CAIRO_FILL_RULE_WINDING,
|
||||
0.0, CAIRO_ANTIALIAS_SUBPIXEL,
|
||||
clip);
|
||||
|
||||
_cairo_path_fixed_fini (&path);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_svg_surface_intersect_clip_path (void *dst,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_svg_surface_t *surface = dst;
|
||||
cairo_svg_document_t *document = surface->document;
|
||||
cairo_status_t status;
|
||||
unsigned int i;
|
||||
|
||||
if (path == NULL) {
|
||||
for (i = 0; i < surface->clip_level; i++)
|
||||
_cairo_output_stream_printf (surface->xml_node, "</g>\n");
|
||||
|
||||
surface->clip_level = 0;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"<clipPath id=\"clip%d\">\n"
|
||||
" <path ",
|
||||
document->clip_id);
|
||||
status = _cairo_svg_surface_emit_path (document->xml_node_defs, path, NULL);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_output_stream_printf (document->xml_node_defs,
|
||||
"/>\n"
|
||||
"</clipPath>\n");
|
||||
|
||||
_cairo_output_stream_printf (surface->xml_node,
|
||||
"<g clip-path=\"url(#clip%d)\" "
|
||||
"clip-rule=\"%s\">\n",
|
||||
document->clip_id,
|
||||
fill_rule == CAIRO_FILL_RULE_EVEN_ODD ?
|
||||
"evenodd" : "nonzero");
|
||||
|
||||
document->clip_id++;
|
||||
surface->clip_level++;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_svg_surface_get_font_options (void *abstract_surface,
|
||||
cairo_font_options_t *options)
|
||||
|
|
@ -2422,7 +2475,7 @@ _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_create_similar,
|
||||
NULL, /* create_similar: handled by wrapper */
|
||||
_cairo_svg_surface_finish,
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
|
|
@ -2436,8 +2489,6 @@ static const cairo_surface_backend_t cairo_svg_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
_cairo_svg_surface_copy_page,
|
||||
_cairo_svg_surface_show_page,
|
||||
NULL, /* set_clip_region */
|
||||
_cairo_svg_surface_intersect_clip_path,
|
||||
_cairo_svg_surface_get_extents,
|
||||
NULL, /* _cairo_svg_surface_old_show_glyphs, */
|
||||
_cairo_svg_surface_get_font_options,
|
||||
|
|
@ -2452,7 +2503,6 @@ static const cairo_surface_backend_t cairo_svg_surface_backend = {
|
|||
_cairo_svg_surface_show_glyphs,
|
||||
NULL, /* snapshot */
|
||||
NULL, /* is_similar */
|
||||
NULL, /* reset */
|
||||
_cairo_svg_surface_fill_stroke
|
||||
};
|
||||
|
||||
|
|
@ -2487,7 +2537,6 @@ _cairo_svg_document_create (cairo_output_stream_t *output_stream,
|
|||
document->width = width;
|
||||
document->height = height;
|
||||
|
||||
document->surface_id = 0;
|
||||
document->linear_pattern_id = 0;
|
||||
document->radial_pattern_id = 0;
|
||||
document->pattern_id = 0;
|
||||
|
|
@ -2507,9 +2556,6 @@ _cairo_svg_document_create (cairo_output_stream_t *output_stream,
|
|||
|
||||
document->alpha_filter = FALSE;
|
||||
|
||||
_cairo_array_init (&document->meta_snapshots,
|
||||
sizeof (cairo_meta_snapshot_t));
|
||||
|
||||
document->svg_version = version;
|
||||
|
||||
*document_out = document;
|
||||
|
|
@ -2560,7 +2606,6 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
|
|||
{
|
||||
cairo_status_t status, status2;
|
||||
cairo_output_stream_t *output = document->output_stream;
|
||||
cairo_meta_snapshot_t *snapshot;
|
||||
cairo_svg_page_t *page;
|
||||
unsigned int i;
|
||||
|
||||
|
|
@ -2662,16 +2707,6 @@ _cairo_svg_document_finish (cairo_svg_document_t *document)
|
|||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = status2;
|
||||
|
||||
for (i = 0; i < document->meta_snapshots.num_elements; i++) {
|
||||
snapshot = _cairo_array_index (&document->meta_snapshots, i);
|
||||
cairo_surface_finish (&snapshot->meta->base);
|
||||
status2 = cairo_surface_status (&snapshot->meta->base);
|
||||
cairo_surface_destroy (&snapshot->meta->base);
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
status = status2;
|
||||
}
|
||||
_cairo_array_fini (&document->meta_snapshots);
|
||||
|
||||
document->finished = TRUE;
|
||||
|
||||
return status;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-region-private.h"
|
||||
|
||||
/* private functions */
|
||||
|
||||
static int
|
||||
|
|
@ -51,6 +53,8 @@ _cairo_traps_init (cairo_traps_t *traps)
|
|||
|
||||
traps->status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
traps->maybe_region = 1;
|
||||
|
||||
traps->num_traps = 0;
|
||||
|
||||
traps->traps_size = ARRAY_LENGTH (traps->traps_embedded);
|
||||
|
|
@ -83,6 +87,8 @@ _cairo_traps_clear (cairo_traps_t *traps)
|
|||
{
|
||||
traps->status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
traps->maybe_region = 1;
|
||||
|
||||
traps->num_traps = 0;
|
||||
traps->extents.p1.x = traps->extents.p1.y = INT32_MAX;
|
||||
traps->extents.p2.x = traps->extents.p2.y = INT32_MIN;
|
||||
|
|
@ -616,14 +622,18 @@ _cairo_traps_extents (const cairo_traps_t *traps,
|
|||
* or %CAIRO_STATUS_NO_MEMORY
|
||||
**/
|
||||
cairo_int_status_t
|
||||
_cairo_traps_extract_region (const cairo_traps_t *traps,
|
||||
cairo_region_t **region)
|
||||
_cairo_traps_extract_region (cairo_traps_t *traps,
|
||||
cairo_region_t **region)
|
||||
{
|
||||
cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
|
||||
cairo_rectangle_int_t *rects = stack_rects;
|
||||
cairo_int_status_t status;
|
||||
int i, rect_count;
|
||||
|
||||
/* we only treat this a hint... */
|
||||
if (! traps->maybe_region)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
for (i = 0; i < traps->num_traps; i++) {
|
||||
if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x ||
|
||||
traps->traps[i].right.p1.x != traps->traps[i].right.p2.x ||
|
||||
|
|
@ -632,6 +642,7 @@ _cairo_traps_extract_region (const cairo_traps_t *traps,
|
|||
! _cairo_fixed_is_integer (traps->traps[i].left.p1.x) ||
|
||||
! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
|
||||
{
|
||||
traps->maybe_region = FALSE;
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
|
@ -655,7 +666,7 @@ _cairo_traps_extract_region (const cairo_traps_t *traps,
|
|||
*/
|
||||
if (x1 == x2 || y1 == y2)
|
||||
continue;
|
||||
|
||||
|
||||
rects[rect_count].x = x1;
|
||||
rects[rect_count].y = y1;
|
||||
rects[rect_count].width = x2 - x1;
|
||||
|
|
@ -663,18 +674,13 @@ _cairo_traps_extract_region (const cairo_traps_t *traps,
|
|||
|
||||
rect_count++;
|
||||
}
|
||||
|
||||
|
||||
*region = cairo_region_create_rectangles (rects, rect_count);
|
||||
status = cairo_region_status (*region);
|
||||
status = (*region)->status;
|
||||
|
||||
if (rects != stack_rects)
|
||||
free (rects);
|
||||
|
||||
if (unlikely (status)) {
|
||||
cairo_region_destroy (*region);
|
||||
*region = NULL;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#if CAIRO_HAS_FONT_SUBSET
|
||||
|
||||
#include "cairo-surface-private.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
#include "cairo-pdf-operators-private.h"
|
||||
|
||||
typedef cairo_status_t (*cairo_type3_glyph_surface_emit_image_t) (cairo_image_surface_t *image,
|
||||
|
|
@ -55,16 +56,18 @@ typedef struct cairo_type3_glyph_surface {
|
|||
cairo_pdf_operators_t pdf_operators;
|
||||
cairo_matrix_t cairo_to_pdf;
|
||||
cairo_type3_glyph_surface_emit_image_t emit_image;
|
||||
|
||||
cairo_surface_clipper_t clipper;
|
||||
} cairo_type3_glyph_surface_t;
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
|
||||
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
|
||||
cairo_output_stream_t *stream,
|
||||
cairo_type3_glyph_surface_emit_image_t emit_image,
|
||||
cairo_scaled_font_subsets_t *font_subsets);
|
||||
cairo_scaled_font_subsets_t *font_subsets);
|
||||
|
||||
cairo_private void
|
||||
_cairo_type3_glyph_surface_set_font_subsets_callback (void *abstract_surface,
|
||||
_cairo_type3_glyph_surface_set_font_subsets_callback (void *abstract_surface,
|
||||
cairo_pdf_operators_use_font_subset_t use_font_subset,
|
||||
void *closure);
|
||||
|
||||
|
|
|
|||
|
|
@ -42,9 +42,31 @@
|
|||
#include "cairo-output-stream-private.h"
|
||||
#include "cairo-meta-surface-private.h"
|
||||
#include "cairo-analysis-surface-private.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
|
||||
static const cairo_surface_backend_t cairo_type3_glyph_surface_backend;
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_type3_glyph_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_type3_glyph_surface_t *surface = cairo_container_of (clipper,
|
||||
cairo_type3_glyph_surface_t,
|
||||
clipper);
|
||||
|
||||
if (path == NULL) {
|
||||
_cairo_output_stream_printf (surface->stream, "Q q\n");
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return _cairo_pdf_operators_clip (&surface->pdf_operators,
|
||||
path,
|
||||
fill_rule);
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
|
||||
cairo_output_stream_t *stream,
|
||||
|
|
@ -81,6 +103,9 @@ _cairo_type3_glyph_surface_create (cairo_scaled_font_t *scaled_font,
|
|||
&surface->cairo_to_pdf,
|
||||
font_subsets);
|
||||
|
||||
_cairo_surface_clipper_init (&surface->clipper,
|
||||
_cairo_type3_glyph_surface_clipper_intersect_clip_path);
|
||||
|
||||
return &surface->base;
|
||||
}
|
||||
|
||||
|
|
@ -155,30 +180,11 @@ _cairo_type3_glyph_surface_finish (void *abstract_surface)
|
|||
return _cairo_pdf_operators_fini (&surface->pdf_operators);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_type3_glyph_surface_intersect_clip_path (void *abstract_surface,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_type3_glyph_surface_t *surface = abstract_surface;
|
||||
|
||||
if (path == NULL) {
|
||||
_cairo_output_stream_printf (surface->stream, "Q q\n");
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return _cairo_pdf_operators_clip (&surface->pdf_operators,
|
||||
path,
|
||||
fill_rule);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_type3_glyph_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_type3_glyph_surface_t *surface = abstract_surface;
|
||||
const cairo_surface_pattern_t *pattern;
|
||||
|
|
@ -189,8 +195,13 @@ _cairo_type3_glyph_surface_paint (void *abstract_surface,
|
|||
if (source->type != CAIRO_PATTERN_TYPE_SURFACE)
|
||||
return CAIRO_INT_STATUS_IMAGE_FALLBACK;
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
pattern = (const cairo_surface_pattern_t *) source;
|
||||
status = _cairo_surface_acquire_source_image (pattern->surface, &image, &image_extra);
|
||||
status = _cairo_surface_acquire_source_image (pattern->surface,
|
||||
&image, &image_extra);
|
||||
if (unlikely (status))
|
||||
goto fail;
|
||||
|
||||
|
|
@ -209,9 +220,11 @@ _cairo_type3_glyph_surface_mask (void *abstract_surface,
|
|||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
return _cairo_type3_glyph_surface_paint (abstract_surface, op, mask, extents);
|
||||
return _cairo_type3_glyph_surface_paint (abstract_surface,
|
||||
op, mask,
|
||||
clip);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -224,9 +237,14 @@ _cairo_type3_glyph_surface_stroke (void *abstract_surface,
|
|||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_type3_glyph_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
return _cairo_pdf_operators_stroke (&surface->pdf_operators,
|
||||
path,
|
||||
|
|
@ -243,16 +261,18 @@ _cairo_type3_glyph_surface_fill (void *abstract_surface,
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_type3_glyph_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_pdf_operators_fill (&surface->pdf_operators,
|
||||
path,
|
||||
fill_rule);
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
return status;
|
||||
return _cairo_pdf_operators_fill (&surface->pdf_operators,
|
||||
path,
|
||||
fill_rule);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -262,8 +282,8 @@ _cairo_type3_glyph_surface_show_glyphs (void *abstract_surface,
|
|||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
int *remaining_glyphs,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs)
|
||||
{
|
||||
cairo_type3_glyph_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
|
|
@ -271,8 +291,14 @@ _cairo_type3_glyph_surface_show_glyphs (void *abstract_surface,
|
|||
cairo_matrix_t new_ctm, ctm_inverse;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_glyphs; i++)
|
||||
cairo_matrix_transform_point (&surface->cairo_to_pdf, &glyphs[i].x, &glyphs[i].y);
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
cairo_matrix_transform_point (&surface->cairo_to_pdf,
|
||||
&glyphs[i].x, &glyphs[i].y);
|
||||
}
|
||||
|
||||
/* We require the matrix to be invertable. */
|
||||
ctm_inverse = scaled_font->ctm;
|
||||
|
|
@ -316,8 +342,6 @@ static const cairo_surface_backend_t cairo_type3_glyph_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* cairo_type3_glyph_surface_copy_page */
|
||||
NULL, /* _cairo_type3_glyph_surface_show_page */
|
||||
NULL, /* set_clip_region */
|
||||
_cairo_type3_glyph_surface_intersect_clip_path,
|
||||
NULL, /* _cairo_type3_glyph_surface_get_extents */
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* _cairo_type3_glyph_surface_get_font_options */
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "cairo.h"
|
||||
#include "cairo-fixed-type-private.h"
|
||||
#include "cairo-list-private.h"
|
||||
#include "cairo-reference-count-private.h"
|
||||
|
||||
typedef struct _cairo_array cairo_array_t;
|
||||
|
|
@ -63,6 +64,7 @@ typedef struct _cairo_scaled_font_backend cairo_scaled_font_backend_t;
|
|||
typedef struct _cairo_scaled_font_subsets cairo_scaled_font_subsets_t;
|
||||
typedef struct _cairo_solid_pattern cairo_solid_pattern_t;
|
||||
typedef struct _cairo_surface_backend cairo_surface_backend_t;
|
||||
typedef struct _cairo_surface_wrapper cairo_surface_wrapper_t;
|
||||
typedef struct _cairo_unscaled_font_backend cairo_unscaled_font_backend_t;
|
||||
typedef struct _cairo_xlib_screen_info cairo_xlib_screen_info_t;
|
||||
|
||||
|
|
@ -167,6 +169,7 @@ typedef enum _cairo_internal_surface_type {
|
|||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_WRAPPING,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_NULL,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TYPE3_GLYPH
|
||||
} cairo_internal_surface_type_t;
|
||||
|
|
@ -237,12 +240,6 @@ typedef enum _cairo_direction {
|
|||
CAIRO_DIRECTION_REVERSE
|
||||
} cairo_direction_t;
|
||||
|
||||
typedef enum _cairo_clip_mode {
|
||||
CAIRO_CLIP_MODE_PATH,
|
||||
CAIRO_CLIP_MODE_REGION,
|
||||
CAIRO_CLIP_MODE_MASK
|
||||
} cairo_clip_mode_t;
|
||||
|
||||
typedef struct _cairo_edge {
|
||||
cairo_line_t edge;
|
||||
int dir;
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ _cairo_user_scaled_font_create_meta_context (cairo_user_scaled_font_t *scaled_fo
|
|||
CAIRO_CONTENT_COLOR_ALPHA :
|
||||
CAIRO_CONTENT_ALPHA;
|
||||
|
||||
meta_surface = cairo_meta_surface_create (content, -1, -1);
|
||||
meta_surface = cairo_meta_surface_create (content, NULL);
|
||||
cr = cairo_create (meta_surface);
|
||||
cairo_surface_destroy (meta_surface);
|
||||
|
||||
|
|
@ -114,11 +114,11 @@ _cairo_user_scaled_glyph_init (void *abstract_font,
|
|||
|
||||
cr = _cairo_user_scaled_font_create_meta_context (scaled_font);
|
||||
|
||||
if (face->scaled_font_methods.render_glyph)
|
||||
if (face->scaled_font_methods.render_glyph) {
|
||||
status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
|
||||
_cairo_scaled_glyph_index(scaled_glyph),
|
||||
cr, &extents);
|
||||
else
|
||||
} else
|
||||
status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||
|
||||
if (status == CAIRO_STATUS_SUCCESS)
|
||||
|
|
@ -141,27 +141,16 @@ _cairo_user_scaled_glyph_init (void *abstract_font,
|
|||
/* set metrics */
|
||||
|
||||
if (extents.width == 0.) {
|
||||
/* Compute extents.x/y/width/height from meta_surface, in font space */
|
||||
|
||||
cairo_box_t bbox;
|
||||
double x1, y1, x2, y2;
|
||||
double x_scale, y_scale;
|
||||
cairo_surface_t *null_surface;
|
||||
cairo_surface_t *analysis_surface;
|
||||
|
||||
null_surface = _cairo_null_surface_create (cairo_surface_get_content (meta_surface));
|
||||
analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1);
|
||||
cairo_surface_destroy (null_surface);
|
||||
status = analysis_surface->status;
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_analysis_surface_set_ctm (analysis_surface,
|
||||
&scaled_font->extent_scale);
|
||||
status = cairo_meta_surface_replay (meta_surface, analysis_surface);
|
||||
_cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
|
||||
cairo_surface_destroy (analysis_surface);
|
||||
|
||||
/* Compute extents.x/y/width/height from meta_surface,
|
||||
* in font space.
|
||||
*/
|
||||
status = _cairo_meta_surface_get_bbox ((cairo_meta_surface_t *) meta_surface,
|
||||
&bbox,
|
||||
&scaled_font->extent_scale);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
|
|
@ -231,7 +220,6 @@ _cairo_user_scaled_glyph_init (void *abstract_font,
|
|||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
status = _cairo_meta_surface_get_path (meta_surface, path);
|
||||
|
||||
if (unlikely (status)) {
|
||||
_cairo_path_fixed_destroy (path);
|
||||
return status;
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
#include "cairo-path-fixed-private.h"
|
||||
#include "cairo-meta-surface-private.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
#include "cairo-cache-private.h"
|
||||
|
||||
#include <pixman.h>
|
||||
|
|
@ -94,7 +95,7 @@ struct _cairo_vg_surface {
|
|||
|
||||
cairo_cache_entry_t snapshot_cache_entry;
|
||||
|
||||
cairo_bool_t clipped;
|
||||
cairo_surface_clipper_t clipper;
|
||||
|
||||
unsigned long target_id;
|
||||
};
|
||||
|
|
@ -397,21 +398,21 @@ _vg_surface_create_similar (void *abstract_surface,
|
|||
return cairo_vg_surface_create (surface->context, content, width, height);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_vg_surface_intersect_clip_path (void *abstract_surface,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
static cairo_status_t
|
||||
_vg_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_vg_surface_t *surface = abstract_surface;
|
||||
cairo_vg_surface_t *surface = cairo_container_of (clipper,
|
||||
cairo_vg_surface_t,
|
||||
clipper);
|
||||
cairo_vg_surface_t *mask;
|
||||
cairo_rectangle_int_t extents, clip_extents;
|
||||
cairo_solid_pattern_t white;
|
||||
cairo_status_t status;
|
||||
|
||||
if (path == NULL) {
|
||||
surface->clipped = FALSE;
|
||||
vgMask (VG_INVALID_HANDLE,
|
||||
VG_FILL_MASK, 0, 0, surface->width, surface->height);
|
||||
vgSeti (VG_MASKING, VG_FALSE);
|
||||
|
|
@ -419,16 +420,6 @@ _vg_surface_intersect_clip_path (void *abstract_surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
extents.x = extents.y = 0;
|
||||
extents.width = surface->width;
|
||||
extents.height = surface->height;
|
||||
_cairo_path_fixed_approximate_clip_extents (path, &clip_extents);
|
||||
if (! _cairo_rectangle_intersect (&clip_extents, &extents))
|
||||
surface->clipped = TRUE;
|
||||
|
||||
if (surface->clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
mask = (cairo_vg_surface_t *)
|
||||
_vg_surface_create_similar (surface, CAIRO_CONTENT_ALPHA,
|
||||
surface->width, surface->height);
|
||||
|
|
@ -456,7 +447,7 @@ _vg_surface_intersect_clip_path (void *abstract_surface,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_vg_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
|
|
@ -467,7 +458,7 @@ _vg_surface_get_extents (void *abstract_surface,
|
|||
extents->width = surface->width;
|
||||
extents->height = surface->height;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define MAX_SEG 16 /* max number of knots to upload in a batch */
|
||||
|
|
@ -589,7 +580,7 @@ _vg_close_path (void *closure)
|
|||
|
||||
static void
|
||||
_vg_path_from_cairo (vg_path_t *vg_path,
|
||||
cairo_path_fixed_t *path)
|
||||
const cairo_path_fixed_t *path)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
|
|
@ -805,7 +796,7 @@ _vg_setup_linear_source (cairo_vg_context_t *context,
|
|||
|
||||
static cairo_status_t
|
||||
_vg_setup_radial_source (cairo_vg_context_t *context,
|
||||
cairo_radial_pattern_t *rpat)
|
||||
const cairo_radial_pattern_t *rpat)
|
||||
{
|
||||
VGfloat radial[5];
|
||||
|
||||
|
|
@ -832,7 +823,7 @@ _vg_setup_radial_source (cairo_vg_context_t *context,
|
|||
|
||||
static cairo_status_t
|
||||
_vg_setup_solid_source (cairo_vg_context_t *context,
|
||||
cairo_solid_pattern_t *spat)
|
||||
const cairo_solid_pattern_t *spat)
|
||||
{
|
||||
VGfloat color[] = {
|
||||
spat->color.red,
|
||||
|
|
@ -960,7 +951,7 @@ _vg_surface_remove_from_cache (cairo_surface_t *abstract_surface)
|
|||
|
||||
static cairo_status_t
|
||||
_vg_setup_surface_source (cairo_vg_context_t *context,
|
||||
cairo_surface_pattern_t *spat)
|
||||
const cairo_surface_pattern_t *spat)
|
||||
{
|
||||
cairo_surface_t *snapshot;
|
||||
cairo_vg_surface_t *clone;
|
||||
|
|
@ -1077,7 +1068,7 @@ _vg_surface_stroke (void *abstract_surface,
|
|||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_vg_surface_t *surface = abstract_surface;
|
||||
cairo_vg_context_t *context;
|
||||
|
|
@ -1086,9 +1077,6 @@ _vg_surface_stroke (void *abstract_surface,
|
|||
VGfloat strokeTransform[9];
|
||||
vg_path_t vg_path;
|
||||
|
||||
if (surface->clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (! _vg_is_supported_operator (op))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
|
|
@ -1105,6 +1093,12 @@ _vg_surface_stroke (void *abstract_surface,
|
|||
return status;
|
||||
}
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status)) {
|
||||
_vg_context_unlock (context);
|
||||
return status;
|
||||
}
|
||||
|
||||
vg_path.path = vgCreatePath (VG_PATH_FORMAT_STANDARD,
|
||||
VG_PATH_DATATYPE_F,
|
||||
1, 0, 0, 0,
|
||||
|
|
@ -1148,16 +1142,13 @@ _vg_surface_fill (void *abstract_surface,
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_vg_surface_t *surface = abstract_surface;
|
||||
cairo_vg_context_t *context;
|
||||
cairo_status_t status;
|
||||
vg_path_t vg_path;
|
||||
|
||||
if (surface->clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (op == CAIRO_OPERATOR_DEST)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
|
@ -1177,6 +1168,12 @@ _vg_surface_fill (void *abstract_surface,
|
|||
return status;
|
||||
}
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status)) {
|
||||
_vg_context_unlock (context);
|
||||
return status;
|
||||
}
|
||||
|
||||
vg_path.path = vgCreatePath (VG_PATH_FORMAT_STANDARD,
|
||||
VG_PATH_DATATYPE_F,
|
||||
1, 0,
|
||||
|
|
@ -1208,15 +1205,12 @@ static cairo_int_status_t
|
|||
_vg_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_vg_surface_t *surface = abstract_surface;
|
||||
cairo_vg_context_t *context;
|
||||
cairo_status_t status;
|
||||
|
||||
if (surface->clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (op == CAIRO_OPERATOR_DEST)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
|
|
@ -1236,6 +1230,12 @@ _vg_surface_paint (void *abstract_surface,
|
|||
return status;
|
||||
}
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (unlikely (status)) {
|
||||
_vg_context_unlock (context);
|
||||
return status;
|
||||
}
|
||||
|
||||
vgSeti (VG_BLEND_MODE, _vg_operator (op));
|
||||
vgSetPaint (context->paint, VG_FILL_PATH);
|
||||
|
||||
|
|
@ -1273,14 +1273,11 @@ _vg_surface_mask (void *abstract_surface,
|
|||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_vg_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
if (surface->clipped)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (! _vg_is_supported_operator (op))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
|
|
@ -1291,7 +1288,7 @@ _vg_surface_mask (void *abstract_surface,
|
|||
double alpha = context->alpha;
|
||||
|
||||
context->alpha = solid->color.alpha;
|
||||
status = _vg_surface_paint (abstract_surface, op, source, extents);
|
||||
status = _vg_surface_paint (abstract_surface, op, source, clip);
|
||||
context->alpha = alpha;
|
||||
|
||||
_vg_context_unlock (context);
|
||||
|
|
@ -1312,14 +1309,14 @@ _vg_surface_get_font_options (void *abstract_surface,
|
|||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_vg_surface_show_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
int *remaining_glyphs,
|
||||
cairo_rectangle_int_t *extents)
|
||||
_vg_surface_show_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs)
|
||||
{
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_path_fixed_t path;
|
||||
|
|
@ -1342,7 +1339,7 @@ _vg_surface_show_glyphs (void *abstract_surface,
|
|||
CAIRO_FILL_RULE_WINDING,
|
||||
CAIRO_GSTATE_TOLERANCE_DEFAULT,
|
||||
CAIRO_ANTIALIAS_SUBPIXEL,
|
||||
extents);
|
||||
clip);
|
||||
BAIL:
|
||||
_cairo_path_fixed_fini (&path);
|
||||
return status;
|
||||
|
|
@ -1510,12 +1507,6 @@ _vg_surface_release_dest_image (void *abstract_surface,
|
|||
cairo_vg_surface_t *surface = abstract_surface;
|
||||
cairo_bool_t needs_unpremultiply;
|
||||
|
||||
/* XXX clipping is incorrect
|
||||
* We can either composite through the current clip mask using fill,
|
||||
* or what for the clipping overhaul patches, due to land any time
|
||||
* soon now...
|
||||
*/
|
||||
|
||||
_vg_format_to_pixman (surface->format, &needs_unpremultiply);
|
||||
if (needs_unpremultiply) {
|
||||
unpremultiply_argb (image->data,
|
||||
|
|
@ -1545,6 +1536,8 @@ _vg_surface_finish (void *abstract_surface)
|
|||
surface->snapshot_cache_entry.hash = 0;
|
||||
}
|
||||
|
||||
_cairo_surface_clipper_reset (&surface->clipper);
|
||||
|
||||
if (surface->own_image)
|
||||
vgDestroyImage (surface->image);
|
||||
|
||||
|
|
@ -1561,20 +1554,21 @@ static const cairo_surface_backend_t cairo_vg_surface_backend = {
|
|||
CAIRO_SURFACE_TYPE_VG,
|
||||
_vg_surface_create_similar,
|
||||
_vg_surface_finish,
|
||||
|
||||
_vg_surface_acquire_source_image,
|
||||
_vg_surface_release_source_image,
|
||||
_vg_surface_acquire_dest_image,
|
||||
_vg_surface_release_dest_image,
|
||||
|
||||
NULL, /* clone_similar */
|
||||
NULL, /* composite */
|
||||
NULL, /* fill_rectangles */
|
||||
NULL, /* composite_trapezoids */
|
||||
NULL, /* create_span_renderer */
|
||||
NULL, /* check_span_renderer */
|
||||
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
NULL, /* set_clip_region */
|
||||
_vg_surface_intersect_clip_path,
|
||||
_vg_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
_vg_surface_get_font_options, /* get_font_options */
|
||||
|
|
@ -1591,7 +1585,6 @@ static const cairo_surface_backend_t cairo_vg_surface_backend = {
|
|||
|
||||
NULL, /* snapshot */
|
||||
NULL, /* is_similar */
|
||||
NULL, /* reset */
|
||||
};
|
||||
|
||||
static cairo_surface_t *
|
||||
|
|
@ -1617,15 +1610,14 @@ _vg_surface_create_internal (cairo_vg_context_t *context,
|
|||
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
surface->clipped = FALSE;
|
||||
|
||||
_cairo_surface_clipper_init (&surface->clipper,
|
||||
_vg_surface_clipper_intersect_clip_path);
|
||||
|
||||
surface->snapshot_cache_entry.hash = 0;
|
||||
|
||||
surface->target_id = 0;
|
||||
|
||||
/* Force an initial "clip", that resets the mask */
|
||||
_vg_surface_intersect_clip_path (surface, NULL, 0, 0.0, 0);
|
||||
|
||||
CHECK_VG_ERRORS();
|
||||
return &surface->base;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1360,6 +1360,7 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font,
|
|||
unsigned int height,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_region_t *clip_region,
|
||||
int *remaining_glyphs)
|
||||
{
|
||||
cairo_win32_scaled_font_t *scaled_font = abstract_font;
|
||||
|
|
@ -1381,15 +1382,17 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font,
|
|||
*/
|
||||
COLORREF new_color;
|
||||
|
||||
status = _cairo_win32_surface_set_clip_region (surface, clip_region);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
new_color = RGB (((int)solid_pattern->color.red_short) >> 8,
|
||||
((int)solid_pattern->color.green_short) >> 8,
|
||||
((int)solid_pattern->color.blue_short) >> 8);
|
||||
|
||||
status = _draw_glyphs_on_surface (surface, scaled_font, new_color,
|
||||
0, 0,
|
||||
glyphs, num_glyphs);
|
||||
|
||||
return status;
|
||||
return _draw_glyphs_on_surface (surface, scaled_font, new_color,
|
||||
0, 0,
|
||||
glyphs, num_glyphs);
|
||||
} else {
|
||||
/* Otherwise, we need to draw using software fallbacks. We create a mask
|
||||
* surface by drawing the the glyphs onto a DIB, black-on-white then
|
||||
|
|
@ -1458,7 +1461,8 @@ _cairo_win32_scaled_font_show_glyphs (void *abstract_font,
|
|||
source_x, source_y,
|
||||
0, 0,
|
||||
dest_x, dest_y,
|
||||
width, height);
|
||||
width, height,
|
||||
clip_region);
|
||||
|
||||
_cairo_pattern_fini (&mask.base);
|
||||
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
#include "cairo-meta-surface-private.h"
|
||||
#include "cairo-scaled-font-subsets-private.h"
|
||||
#include "cairo-image-info-private.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
|
|
@ -128,7 +129,7 @@ analyze_surface_pattern_transparency (cairo_surface_pattern_t *pattern)
|
|||
cairo_image_surface_t *image;
|
||||
void *image_extra;
|
||||
cairo_int_status_t status;
|
||||
int x, y;
|
||||
cairo_image_transparency_t transparency;
|
||||
|
||||
status = _cairo_surface_acquire_source_image (pattern->surface,
|
||||
&image,
|
||||
|
|
@ -136,38 +137,20 @@ analyze_surface_pattern_transparency (cairo_surface_pattern_t *pattern)
|
|||
if (status)
|
||||
return status;
|
||||
|
||||
if (image->base.status)
|
||||
return image->base.status;
|
||||
|
||||
if (image->format == CAIRO_FORMAT_RGB24) {
|
||||
transparency = _cairo_image_analyze_transparency (image);
|
||||
switch (transparency) {
|
||||
case CAIRO_IMAGE_UNKNOWN:
|
||||
ASSERT_NOT_REACHED;
|
||||
case CAIRO_IMAGE_IS_OPAQUE:
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
goto RELEASE_SOURCE;
|
||||
}
|
||||
break;
|
||||
|
||||
if (image->format != CAIRO_FORMAT_ARGB32) {
|
||||
/* If the surface does not support the image format, assume
|
||||
* that it does have alpha. The image will be converted to
|
||||
* rgb24 when the surface blends the image into the page
|
||||
* color to remove the transparency. */
|
||||
case CAIRO_IMAGE_HAS_BILEVEL_ALPHA:
|
||||
case CAIRO_IMAGE_HAS_ALPHA:
|
||||
status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
|
||||
goto RELEASE_SOURCE;
|
||||
break;
|
||||
}
|
||||
|
||||
for (y = 0; y < image->height; y++) {
|
||||
int a;
|
||||
uint32_t *pixel = (uint32_t *) (image->data + y * image->stride);
|
||||
|
||||
for (x = 0; x < image->width; x++, pixel++) {
|
||||
a = (*pixel & 0xff000000) >> 24;
|
||||
if (a != 255) {
|
||||
status = CAIRO_INT_STATUS_FLATTEN_TRANSPARENCY;
|
||||
goto RELEASE_SOURCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
RELEASE_SOURCE:
|
||||
_cairo_surface_release_source_image (pattern->surface, image, image_extra);
|
||||
|
||||
return status;
|
||||
|
|
@ -176,8 +159,6 @@ RELEASE_SOURCE:
|
|||
static cairo_bool_t
|
||||
surface_pattern_supported (const cairo_surface_pattern_t *pattern)
|
||||
{
|
||||
cairo_extend_t extend;
|
||||
|
||||
if (_cairo_surface_is_meta (pattern->surface))
|
||||
return TRUE;
|
||||
|
||||
|
|
@ -187,19 +168,7 @@ surface_pattern_supported (const cairo_surface_pattern_t *pattern)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
extend = cairo_pattern_get_extend ((cairo_pattern_t*)&pattern->base);
|
||||
switch (extend) {
|
||||
case CAIRO_EXTEND_NONE:
|
||||
case CAIRO_EXTEND_REPEAT:
|
||||
case CAIRO_EXTEND_REFLECT:
|
||||
/* There's no point returning FALSE for EXTEND_PAD, as the image
|
||||
* surface does not currently implement it either */
|
||||
case CAIRO_EXTEND_PAD:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ASSERT_NOT_REACHED;
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
|
|
@ -390,7 +359,8 @@ _cairo_win32_printing_surface_paint_meta_pattern (cairo_win32_surface_t *surfa
|
|||
XFORM xform;
|
||||
int x_tile, y_tile, left, right, top, bottom;
|
||||
RECT clip;
|
||||
cairo_surface_t *meta_surface = pattern->surface;
|
||||
cairo_meta_surface_t *meta_surface = (cairo_meta_surface_t *) pattern->surface;
|
||||
cairo_box_t bbox;
|
||||
|
||||
extend = cairo_pattern_get_extend (&pattern->base);
|
||||
|
||||
|
|
@ -406,7 +376,7 @@ _cairo_win32_printing_surface_paint_meta_pattern (cairo_win32_surface_t *surfa
|
|||
SaveDC (surface->dc);
|
||||
_cairo_matrix_to_win32_xform (&p2d, &xform);
|
||||
|
||||
status = _cairo_surface_get_extents (meta_surface, &meta_extents);
|
||||
status = _cairo_meta_surface_get_bbox (meta_surface, &bbox, NULL);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
|
|
@ -415,10 +385,10 @@ _cairo_win32_printing_surface_paint_meta_pattern (cairo_win32_surface_t *surfa
|
|||
return status;
|
||||
|
||||
if (extend == CAIRO_EXTEND_REPEAT || extend == CAIRO_EXTEND_REFLECT) {
|
||||
left = (int) floor((double)clip.left/meta_extents.width);
|
||||
right = (int) ceil((double)clip.right/meta_extents.width);
|
||||
top = (int) floor((double)clip.top/meta_extents.height);
|
||||
bottom = (int) ceil((double)clip.bottom/meta_extents.height);
|
||||
left = (int) floor (clip.left / _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x));
|
||||
right = (int) ceil (clip.right / _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x));
|
||||
top = (int) floor (clip.top / _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y));
|
||||
bottom = (int) ceil (clip.bottom / _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y));
|
||||
} else {
|
||||
left = 0;
|
||||
right = 1;
|
||||
|
|
@ -427,7 +397,7 @@ _cairo_win32_printing_surface_paint_meta_pattern (cairo_win32_surface_t *surfa
|
|||
}
|
||||
|
||||
old_content = surface->content;
|
||||
if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) {
|
||||
if (meta_surface->base.content == CAIRO_CONTENT_COLOR) {
|
||||
cairo_pattern_t *source;
|
||||
cairo_solid_pattern_t black;
|
||||
|
||||
|
|
@ -490,7 +460,8 @@ _cairo_win32_printing_surface_paint_meta_pattern (cairo_win32_surface_t *surfa
|
|||
SelectClipPath (surface->dc, RGN_AND);
|
||||
|
||||
SaveDC (surface->dc); /* Allow clip path to be reset during replay */
|
||||
status = _cairo_meta_surface_replay_region (meta_surface, &surface->base,
|
||||
status = _cairo_meta_surface_replay_region (&meta_surface->base,
|
||||
&surface->base,
|
||||
CAIRO_META_REGION_NATIVE);
|
||||
assert (status != CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
/* Restore both the clip save and our earlier path SaveDC */
|
||||
|
|
@ -594,7 +565,6 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
|
|||
cairo_extend_t extend;
|
||||
cairo_image_surface_t *image;
|
||||
void *image_extra;
|
||||
cairo_surface_t *opaque_surface;
|
||||
cairo_image_surface_t *opaque_image = NULL;
|
||||
BITMAPINFO bi;
|
||||
cairo_matrix_t m;
|
||||
|
|
@ -651,13 +621,15 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
|
|||
&mime_size,
|
||||
&mime_info);
|
||||
}
|
||||
if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
if (_cairo_status_is_error (status))
|
||||
return status;
|
||||
|
||||
use_mime = (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
if (!use_mime && image->format != CAIRO_FORMAT_RGB24) {
|
||||
cairo_surface_pattern_t opaque_pattern;
|
||||
cairo_surface_t *opaque_surface;
|
||||
cairo_surface_pattern_t image_pattern;
|
||||
cairo_solid_pattern_t background_pattern;
|
||||
|
||||
opaque_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
|
||||
image->width,
|
||||
|
|
@ -667,36 +639,27 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
|
|||
goto CLEANUP_OPAQUE_IMAGE;
|
||||
}
|
||||
|
||||
_cairo_pattern_init_for_surface (&opaque_pattern, &image->base);
|
||||
|
||||
status = _cairo_surface_fill_rectangle (opaque_surface,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
background_color,
|
||||
0, 0,
|
||||
image->width, image->height);
|
||||
if (status) {
|
||||
_cairo_pattern_fini (&opaque_pattern.base);
|
||||
_cairo_pattern_init_solid (&background_pattern,
|
||||
background_color,
|
||||
CAIRO_CONTENT_COLOR);
|
||||
status = _cairo_surface_paint (opaque_surface,
|
||||
CAIRO_OPERATOR_SOURCE,
|
||||
&background_pattern.base,
|
||||
NULL);
|
||||
if (status)
|
||||
goto CLEANUP_OPAQUE_IMAGE;
|
||||
}
|
||||
|
||||
status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
|
||||
&opaque_pattern.base,
|
||||
NULL,
|
||||
opaque_surface,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
image->width,
|
||||
image->height);
|
||||
if (status) {
|
||||
_cairo_pattern_fini (&opaque_pattern.base);
|
||||
_cairo_pattern_init_for_surface (&image_pattern, &image->base);
|
||||
status = _cairo_surface_paint (opaque_surface,
|
||||
CAIRO_OPERATOR_OVER,
|
||||
&image_pattern.base,
|
||||
NULL);
|
||||
_cairo_pattern_fini (&image_pattern.base);
|
||||
if (status)
|
||||
goto CLEANUP_OPAQUE_IMAGE;
|
||||
}
|
||||
|
||||
_cairo_pattern_fini (&opaque_pattern.base);
|
||||
opaque_image = (cairo_image_surface_t *) opaque_surface;
|
||||
} else {
|
||||
opaque_surface = &image->base;
|
||||
opaque_image = image;
|
||||
}
|
||||
|
||||
|
|
@ -767,7 +730,7 @@ _cairo_win32_printing_surface_paint_image_pattern (cairo_win32_surface_t *surf
|
|||
|
||||
CLEANUP_OPAQUE_IMAGE:
|
||||
if (opaque_image != image)
|
||||
cairo_surface_destroy (opaque_surface);
|
||||
cairo_surface_destroy (&opaque_image->base);
|
||||
CLEANUP_IMAGE:
|
||||
_cairo_surface_release_source_image (pattern->surface, image, image_extra);
|
||||
|
||||
|
|
@ -1085,17 +1048,15 @@ _cairo_win32_printing_surface_emit_path (cairo_win32_surface_t *surface,
|
|||
cairo_path_fixed_t *path)
|
||||
{
|
||||
win32_path_info_t path_info;
|
||||
cairo_status_t status;
|
||||
|
||||
path_info.surface = surface;
|
||||
status = _cairo_path_fixed_interpret (path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_win32_printing_surface_path_move_to,
|
||||
_cairo_win32_printing_surface_path_line_to,
|
||||
_cairo_win32_printing_surface_path_curve_to,
|
||||
_cairo_win32_printing_surface_path_close_path,
|
||||
&path_info);
|
||||
return status;
|
||||
return _cairo_path_fixed_interpret (path,
|
||||
CAIRO_DIRECTION_FORWARD,
|
||||
_cairo_win32_printing_surface_path_move_to,
|
||||
_cairo_win32_printing_surface_path_line_to,
|
||||
_cairo_win32_printing_surface_path_curve_to,
|
||||
_cairo_win32_printing_surface_path_close_path,
|
||||
&path_info);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -1109,14 +1070,16 @@ _cairo_win32_printing_surface_show_page (void *abstract_surface)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_win32_printing_surface_intersect_clip_path (void *abstract_surface,
|
||||
static cairo_status_t
|
||||
_cairo_win32_printing_surface_clipper_intersect_clip_path (cairo_surface_clipper_t *clipper,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_win32_surface_t *surface = abstract_surface;
|
||||
cairo_win32_surface_t *surface = cairo_container_of (clipper,
|
||||
cairo_win32_surface_t,
|
||||
clipper);
|
||||
cairo_status_t status;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
|
|
@ -1164,10 +1127,15 @@ static cairo_int_status_t
|
|||
_cairo_win32_printing_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_win32_surface_t *surface = abstract_surface;
|
||||
cairo_solid_pattern_t clear;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
_cairo_win32_printing_surface_init_clear_color (surface, &clear);
|
||||
|
|
@ -1242,7 +1210,7 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface,
|
|||
cairo_matrix_t *stroke_ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_win32_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
|
|
@ -1258,6 +1226,10 @@ _cairo_win32_printing_surface_stroke (void *abstract_surface,
|
|||
cairo_matrix_t mat;
|
||||
double scale;
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
_cairo_win32_printing_surface_init_clear_color (surface, &clear);
|
||||
source = (cairo_pattern_t*) &clear;
|
||||
|
|
@ -1364,12 +1336,16 @@ _cairo_win32_printing_surface_fill (void *abstract_surface,
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
cairo_win32_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status;
|
||||
cairo_solid_pattern_t clear;
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
_cairo_win32_printing_surface_init_clear_color (surface, &clear);
|
||||
source = (cairo_pattern_t*) &clear;
|
||||
|
|
@ -1423,8 +1399,8 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
|
|||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
int *remaining_glyphs,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs)
|
||||
{
|
||||
cairo_win32_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
|
@ -1435,6 +1411,10 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
|
|||
cairo_bool_t old_has_ctm;
|
||||
cairo_solid_pattern_t clear;
|
||||
|
||||
status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
_cairo_win32_printing_surface_init_clear_color (surface, &clear);
|
||||
source = (cairo_pattern_t*) &clear;
|
||||
|
|
@ -1547,8 +1527,8 @@ _cairo_win32_printing_surface_show_glyphs (void *abstract_surfac
|
|||
status = _cairo_win32_surface_show_glyphs (surface, op,
|
||||
source, glyphs,
|
||||
num_glyphs, scaled_font,
|
||||
remaining_glyphs,
|
||||
extents);
|
||||
clip,
|
||||
remaining_glyphs);
|
||||
if (surface->has_ctm)
|
||||
cairo_scaled_font_destroy (scaled_font);
|
||||
|
||||
|
|
@ -1607,7 +1587,12 @@ _cairo_win32_printing_surface_create_similar (void *abstract_surface,
|
|||
int width,
|
||||
int height)
|
||||
{
|
||||
return cairo_meta_surface_create (content, width, height);
|
||||
cairo_rectangle_t extents;
|
||||
|
||||
extents.x = extents.y = 0;
|
||||
extents.width = width;
|
||||
extents.height = height;
|
||||
return cairo_meta_surface_create (content, &extents);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -1698,6 +1683,9 @@ cairo_win32_printing_surface_create (HDC hdc)
|
|||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
}
|
||||
|
||||
_cairo_surface_clipper_init (&surface->clipper,
|
||||
_cairo_win32_printing_surface_clipper_intersect_clip_path);
|
||||
|
||||
surface->image = NULL;
|
||||
surface->format = CAIRO_FORMAT_RGB24;
|
||||
surface->content = CAIRO_CONTENT_COLOR_ALPHA;
|
||||
|
|
@ -1725,13 +1713,12 @@ cairo_win32_printing_surface_create (HDC hdc)
|
|||
|
||||
_cairo_win32_printing_surface_init_ps_mode (surface);
|
||||
_cairo_win32_printing_surface_init_image_support (surface);
|
||||
_cairo_surface_init (&surface->base, &cairo_win32_printing_surface_backend,
|
||||
_cairo_surface_init (&surface->base,
|
||||
&cairo_win32_printing_surface_backend,
|
||||
CAIRO_CONTENT_COLOR_ALPHA);
|
||||
|
||||
paginated = _cairo_paginated_surface_create (&surface->base,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
surface->extents.width,
|
||||
surface->extents.height,
|
||||
&cairo_win32_surface_paginated_backend);
|
||||
|
||||
/* paginated keeps the only reference to surface now, drop ours */
|
||||
|
|
@ -1762,8 +1749,6 @@ static const cairo_surface_backend_t cairo_win32_printing_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* copy_page */
|
||||
_cairo_win32_printing_surface_show_page,
|
||||
NULL, /* set_clip_region */
|
||||
_cairo_win32_printing_surface_intersect_clip_path,
|
||||
_cairo_win32_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
_cairo_win32_printing_surface_get_font_options,
|
||||
|
|
@ -1779,7 +1764,6 @@ static const cairo_surface_backend_t cairo_win32_printing_surface_backend = {
|
|||
_cairo_win32_printing_surface_show_glyphs,
|
||||
NULL, /* snapshot */
|
||||
NULL, /* is_similar */
|
||||
NULL, /* reset */
|
||||
NULL, /* fill_stroke */
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@
|
|||
|
||||
#include "cairo-win32.h"
|
||||
#include "cairoint.h"
|
||||
#include "cairo-surface-clipper-private.h"
|
||||
|
||||
#ifndef SHADEBLENDCAPS
|
||||
#define SHADEBLENDCAPS 120
|
||||
|
|
@ -81,6 +82,10 @@ typedef struct _cairo_win32_surface {
|
|||
cairo_rectangle_int_t clip_rect;
|
||||
HRGN initial_clip_rgn;
|
||||
cairo_bool_t had_simple_clip;
|
||||
cairo_region_t *clip_region;
|
||||
|
||||
/* For path clipping to the printing-surface */
|
||||
cairo_surface_clipper_t clipper;
|
||||
|
||||
/* Surface DC flags */
|
||||
uint32_t flags;
|
||||
|
|
@ -137,13 +142,17 @@ _cairo_surface_is_win32_printing (cairo_surface_t *surface);
|
|||
cairo_status_t
|
||||
_cairo_win32_surface_finish (void *abstract_surface);
|
||||
|
||||
cairo_int_status_t
|
||||
cairo_bool_t
|
||||
_cairo_win32_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle);
|
||||
|
||||
uint32_t
|
||||
_cairo_win32_flags_for_dc (HDC dc);
|
||||
|
||||
cairo_status_t
|
||||
_cairo_win32_surface_set_clip_region (void *abstract_surface,
|
||||
cairo_region_t *region);
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_win32_surface_show_glyphs (void *surface,
|
||||
cairo_operator_t op,
|
||||
|
|
@ -151,8 +160,8 @@ _cairo_win32_surface_show_glyphs (void *surface,
|
|||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
int *remaining_glyphs,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs);
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_win32_surface_create_similar (void *abstract_src,
|
||||
|
|
|
|||
|
|
@ -468,7 +468,8 @@ _cairo_win32_surface_clone_similar (void *abstract_surface,
|
|||
src_x, src_y,
|
||||
0, 0,
|
||||
0, 0,
|
||||
width, height);
|
||||
width, height,
|
||||
NULL);
|
||||
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
|
||||
|
|
@ -693,6 +694,91 @@ _cairo_win32_surface_release_dest_image (void *abstract_surfa
|
|||
cairo_surface_destroy ((cairo_surface_t *)local);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_win32_surface_set_clip_region (void *abstract_surface,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
cairo_win32_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
if (surface->clip_region == region)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
cairo_region_destroy (surface->clip_region);
|
||||
surface->clip_region = cairo_region_reference (region);
|
||||
|
||||
/* The semantics we want is that any clip set by cairo combines
|
||||
* is intersected with the clip on device context that the
|
||||
* surface was created for. To implement this, we need to
|
||||
* save the original clip when first setting a clip on surface.
|
||||
*/
|
||||
|
||||
/* Clear any clip set by cairo, return to the original first */
|
||||
status = _cairo_win32_restore_initial_clip (surface);
|
||||
|
||||
/* Then combine any new region with it */
|
||||
if (region) {
|
||||
cairo_rectangle_int_t extents;
|
||||
int num_rects;
|
||||
RGNDATA *data;
|
||||
size_t data_size;
|
||||
RECT *rects;
|
||||
int i;
|
||||
HRGN gdi_region;
|
||||
|
||||
/* Create a GDI region for the cairo region */
|
||||
|
||||
cairo_region_get_extents (region, &extents);
|
||||
num_rects = cairo_region_num_rectangles (region);
|
||||
/* XXX see notes in _cairo_win32_save_initial_clip --
|
||||
* this code will interact badly with a HDC which had an initial
|
||||
* world transform -- we should probably manually transform the
|
||||
* region rects, because SelectClipRgn takes device units, not
|
||||
* logical units (unlike IntersectClipRect).
|
||||
*/
|
||||
|
||||
data_size = sizeof (RGNDATAHEADER) + num_rects * sizeof (RECT);
|
||||
data = malloc (data_size);
|
||||
if (!data)
|
||||
return _cairo_error(CAIRO_STATUS_NO_MEMORY);
|
||||
rects = (RECT *)data->Buffer;
|
||||
|
||||
data->rdh.dwSize = sizeof (RGNDATAHEADER);
|
||||
data->rdh.iType = RDH_RECTANGLES;
|
||||
data->rdh.nCount = num_rects;
|
||||
data->rdh.nRgnSize = num_rects * sizeof (RECT);
|
||||
data->rdh.rcBound.left = extents.x;
|
||||
data->rdh.rcBound.top = extents.y;
|
||||
data->rdh.rcBound.right = extents.x + extents.width;
|
||||
data->rdh.rcBound.bottom = extents.y + extents.height;
|
||||
|
||||
for (i = 0; i < num_rects; i++) {
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
|
||||
rects[i].left = rect.x;
|
||||
rects[i].top = rect.y;
|
||||
rects[i].right = rect.x + rect.width;
|
||||
rects[i].bottom = rect.y + rect.height;
|
||||
}
|
||||
|
||||
gdi_region = ExtCreateRegion (NULL, data_size, data);
|
||||
free (data);
|
||||
|
||||
if (!gdi_region)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
/* AND the new region into our DC */
|
||||
if (ExtSelectClipRgn (surface->dc, gdi_region, RGN_AND) == ERROR)
|
||||
status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region");
|
||||
|
||||
DeleteObject (gdi_region);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#if !defined(AC_SRC_OVER)
|
||||
#define AC_SRC_OVER 0x00
|
||||
#pragma pack(1)
|
||||
|
|
@ -889,7 +975,8 @@ _cairo_win32_surface_composite (cairo_operator_t op,
|
|||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height)
|
||||
unsigned int height,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_win32_surface_t *dst = abstract_dst;
|
||||
cairo_win32_surface_t *src;
|
||||
|
|
@ -1030,7 +1117,7 @@ _cairo_win32_surface_composite (cairo_operator_t op,
|
|||
fflush (stderr);
|
||||
#endif
|
||||
|
||||
/* If the src recangle doesn't wholly lie within the src extents,
|
||||
/* If the src rectangle doesn't wholly lie within the src extents,
|
||||
* fudge things. We really need to do fixup on the unpainted
|
||||
* region -- e.g. the SOURCE operator is broken for areas outside
|
||||
* of the extents, because it won't clear that area to transparent
|
||||
|
|
@ -1150,6 +1237,10 @@ _cairo_win32_surface_composite (cairo_operator_t op,
|
|||
fflush (stderr);
|
||||
#endif
|
||||
|
||||
status = _cairo_win32_surface_set_clip_region (dst, clip_region);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* If we need to repeat, we turn the repeated blit into
|
||||
* a bunch of piece-by-piece blits.
|
||||
*/
|
||||
|
|
@ -1283,7 +1374,8 @@ UNSUPPORTED:
|
|||
src_x, src_y,
|
||||
mask_x, mask_y,
|
||||
dst_x, dst_y,
|
||||
width, height);
|
||||
width, height,
|
||||
clip_region);
|
||||
}
|
||||
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
|
@ -1387,6 +1479,10 @@ _cairo_win32_surface_fill_rectangles (void *abstract_surface,
|
|||
if (surface->format != CAIRO_FORMAT_RGB24)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_win32_surface_set_clip_region (surface, NULL);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Optimize for no destination alpha (surface->pixman_image is non-NULL for all
|
||||
* surfaces with alpha.)
|
||||
*/
|
||||
|
|
@ -1432,133 +1528,20 @@ _cairo_win32_surface_fill_rectangles (void *abstract_surface,
|
|||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_win32_surface_set_clip_region (void *abstract_surface,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
cairo_win32_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
|
||||
/* If we are in-memory, then we set the clip on the image surface
|
||||
* as well as on the underlying GDI surface.
|
||||
*/
|
||||
if (surface->image) {
|
||||
unsigned int serial;
|
||||
|
||||
serial = _cairo_surface_allocate_clip_serial (surface->image);
|
||||
status = _cairo_surface_set_clip_region (surface->image, region, serial);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* The semantics we want is that any clip set by cairo combines
|
||||
* is intersected with the clip on device context that the
|
||||
* surface was created for. To implement this, we need to
|
||||
* save the original clip when first setting a clip on surface.
|
||||
*/
|
||||
|
||||
/* Clear any clip set by cairo, return to the original first */
|
||||
status = _cairo_win32_restore_initial_clip (surface);
|
||||
|
||||
/* Then combine any new region with it */
|
||||
if (region) {
|
||||
cairo_rectangle_int_t extents;
|
||||
int num_rects;
|
||||
RGNDATA *data;
|
||||
size_t data_size;
|
||||
RECT *rects;
|
||||
int i;
|
||||
HRGN gdi_region;
|
||||
cairo_rectangle_int_t rect0;
|
||||
|
||||
/* Create a GDI region for the cairo region */
|
||||
|
||||
cairo_region_get_extents (region, &extents);
|
||||
num_rects = cairo_region_num_rectangles (region);
|
||||
|
||||
if (num_rects == 1)
|
||||
cairo_region_get_rectangle (region, 0, &rect0);
|
||||
|
||||
if (num_rects == 1 &&
|
||||
rect0.x == 0 &&
|
||||
rect0.y == 0 &&
|
||||
rect0.width == surface->extents.width &&
|
||||
rect0.width == surface->extents.height)
|
||||
{
|
||||
gdi_region = NULL;
|
||||
|
||||
SelectClipRgn (surface->dc, NULL);
|
||||
IntersectClipRect (surface->dc,
|
||||
rect0.x,
|
||||
rect0.y,
|
||||
rect0.x + rect0.width,
|
||||
rect0.y + rect0.height);
|
||||
} else {
|
||||
/* XXX see notes in _cairo_win32_save_initial_clip --
|
||||
* this code will interact badly with a HDC which had an initial
|
||||
* world transform -- we should probably manually transform the
|
||||
* region rects, because SelectClipRgn takes device units, not
|
||||
* logical units (unlike IntersectClipRect).
|
||||
*/
|
||||
|
||||
data_size = sizeof (RGNDATAHEADER) + num_rects * sizeof (RECT);
|
||||
data = malloc (data_size);
|
||||
if (!data)
|
||||
return _cairo_error(CAIRO_STATUS_NO_MEMORY);
|
||||
rects = (RECT *)data->Buffer;
|
||||
|
||||
data->rdh.dwSize = sizeof (RGNDATAHEADER);
|
||||
data->rdh.iType = RDH_RECTANGLES;
|
||||
data->rdh.nCount = num_rects;
|
||||
data->rdh.nRgnSize = num_rects * sizeof (RECT);
|
||||
data->rdh.rcBound.left = extents.x;
|
||||
data->rdh.rcBound.top = extents.y;
|
||||
data->rdh.rcBound.right = extents.x + extents.width;
|
||||
data->rdh.rcBound.bottom = extents.y + extents.height;
|
||||
|
||||
for (i = 0; i < num_rects; i++) {
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
|
||||
rects[i].left = rect.x;
|
||||
rects[i].top = rect.y;
|
||||
rects[i].right = rect.x + rect.width;
|
||||
rects[i].bottom = rect.y + rect.height;
|
||||
}
|
||||
|
||||
gdi_region = ExtCreateRegion (NULL, data_size, data);
|
||||
free (data);
|
||||
|
||||
if (!gdi_region)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
/* AND the new region into our DC */
|
||||
if (ExtSelectClipRgn (surface->dc, gdi_region, RGN_AND) == ERROR)
|
||||
status = _cairo_win32_print_gdi_error ("_cairo_win32_surface_set_clip_region");
|
||||
|
||||
DeleteObject (gdi_region);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
cairo_bool_t
|
||||
_cairo_win32_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
cairo_win32_surface_t *surface = abstract_surface;
|
||||
|
||||
*rectangle = surface->extents;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_surface_flush (void *abstract_surface)
|
||||
{
|
||||
return _cairo_surface_reset_clip (abstract_surface);
|
||||
return _cairo_win32_surface_set_clip_region (abstract_surface, NULL);
|
||||
}
|
||||
|
||||
#define STACK_GLYPH_SIZE 256
|
||||
|
|
@ -1570,8 +1553,8 @@ _cairo_win32_surface_show_glyphs (void *surface,
|
|||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
int *remaining_glyphs,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs)
|
||||
{
|
||||
#if CAIRO_HAS_WIN32_FONT
|
||||
cairo_win32_surface_t *dst = surface;
|
||||
|
|
@ -1611,11 +1594,19 @@ _cairo_win32_surface_show_glyphs (void *surface,
|
|||
/* If we have a fallback mask clip set on the dst, we have
|
||||
* to go through the fallback path, but only if we're not
|
||||
* doing this for printing */
|
||||
if (dst->base.clip &&
|
||||
!(dst->flags & CAIRO_WIN32_SURFACE_FOR_PRINTING) &&
|
||||
(dst->base.clip->mode != CAIRO_CLIP_MODE_REGION ||
|
||||
dst->base.clip->surface != NULL))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (clip != NULL) {
|
||||
if ((dst->flags & CAIRO_WIN32_SURFACE_FOR_PRINTING) == 0) {
|
||||
cairo_region_t *clip_region;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_clip_get_region (clip, &clip_region);
|
||||
assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
_cairo_win32_surface_set_clip_region (surface, clip_region);
|
||||
}
|
||||
}
|
||||
|
||||
solid_pattern = (cairo_solid_pattern_t *)source;
|
||||
color = RGB(((int)solid_pattern->color.red_short) >> 8,
|
||||
|
|
@ -1957,19 +1948,6 @@ _cairo_win32_surface_is_similar (void *surface_a,
|
|||
return a->dc == b->dc;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_win32_surface_reset (void *abstract_surface)
|
||||
{
|
||||
cairo_win32_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_win32_surface_set_clip_region (surface, NULL);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
typedef struct _cairo_win32_surface_span_renderer {
|
||||
cairo_span_renderer_t base;
|
||||
|
||||
|
|
@ -1979,6 +1957,7 @@ typedef struct _cairo_win32_surface_span_renderer {
|
|||
|
||||
cairo_image_surface_t *mask;
|
||||
cairo_win32_surface_t *dst;
|
||||
cairo_region_t *clip_region;
|
||||
|
||||
cairo_composite_rectangles_t composite_rectangles;
|
||||
} cairo_win32_surface_span_renderer_t;
|
||||
|
|
@ -2031,18 +2010,20 @@ _cairo_win32_surface_span_renderer_finish (void *abstract_renderer)
|
|||
rects->src.y,
|
||||
0, 0, /* mask.x, mask.y */
|
||||
rects->dst.x, rects->dst.y,
|
||||
rects->width, rects->height);
|
||||
rects->width, rects->height,
|
||||
renderer->clip_region);
|
||||
} else {
|
||||
/* otherwise go through the fallback_composite path which
|
||||
* will do the appropriate surface acquisition */
|
||||
status = _cairo_surface_fallback_composite (
|
||||
renderer->op,
|
||||
renderer->pattern, mask_pattern, dst,
|
||||
renderer->pattern, mask_pattern, &dst->base,
|
||||
rects->src.x,
|
||||
rects->src.y,
|
||||
0, 0, /* mask.x, mask.y */
|
||||
rects->dst.x, rects->dst.y,
|
||||
rects->width, rects->height);
|
||||
rects->width, rects->height,
|
||||
renderer->clip_region);
|
||||
}
|
||||
cairo_pattern_destroy (mask_pattern);
|
||||
|
||||
|
|
@ -2073,15 +2054,16 @@ _cairo_win32_surface_create_span_renderer (cairo_operator_t op,
|
|||
const cairo_pattern_t *pattern,
|
||||
void *abstract_dst,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_composite_rectangles_t *rects)
|
||||
const cairo_composite_rectangles_t *rects,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_win32_surface_t *dst = abstract_dst;
|
||||
cairo_win32_surface_span_renderer_t *renderer
|
||||
= calloc(1, sizeof(*renderer));
|
||||
cairo_win32_surface_span_renderer_t *renderer;
|
||||
cairo_status_t status;
|
||||
int width = rects->width;
|
||||
int height = rects->height;
|
||||
|
||||
renderer = calloc(1, sizeof(*renderer));
|
||||
if (renderer == NULL)
|
||||
return _cairo_span_renderer_create_in_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
|
|
@ -2093,6 +2075,7 @@ _cairo_win32_surface_create_span_renderer (cairo_operator_t op,
|
|||
renderer->pattern = pattern;
|
||||
renderer->antialias = antialias;
|
||||
renderer->dst = dst;
|
||||
renderer->clip_region = clip_region;
|
||||
|
||||
renderer->composite_rectangles = *rects;
|
||||
|
||||
|
|
@ -2128,8 +2111,6 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
|
|||
_cairo_win32_surface_check_span_renderer,
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
_cairo_win32_surface_set_clip_region,
|
||||
NULL, /* intersect_clip_path */
|
||||
_cairo_win32_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
|
|
@ -2146,8 +2127,6 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
|
|||
|
||||
NULL, /* snapshot */
|
||||
_cairo_win32_surface_is_similar,
|
||||
|
||||
_cairo_win32_surface_reset
|
||||
};
|
||||
|
||||
/* Notes:
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ typedef struct cairo_xcb_surface {
|
|||
cairo_bool_t have_clip_rects;
|
||||
xcb_rectangle_t *clip_rects;
|
||||
int num_clip_rects;
|
||||
cairo_region_t *clip_region;
|
||||
|
||||
xcb_render_picture_t src_picture, dst_picture;
|
||||
xcb_render_pictforminfo_t xrender_format;
|
||||
|
|
@ -166,6 +167,93 @@ _xcb_render_format_to_content (xcb_render_pictforminfo_t *xrender_format)
|
|||
return CAIRO_CONTENT_COLOR;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_xcb_surface_set_gc_clip_rects (cairo_xcb_surface_t *surface)
|
||||
{
|
||||
if (surface->have_clip_rects)
|
||||
xcb_set_clip_rectangles(surface->dpy, XCB_CLIP_ORDERING_YX_SORTED, surface->gc,
|
||||
0, 0,
|
||||
surface->num_clip_rects,
|
||||
surface->clip_rects );
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_xcb_surface_set_picture_clip_rects (cairo_xcb_surface_t *surface)
|
||||
{
|
||||
if (surface->have_clip_rects)
|
||||
xcb_render_set_picture_clip_rectangles (surface->dpy, surface->dst_picture,
|
||||
0, 0,
|
||||
surface->num_clip_rects,
|
||||
surface->clip_rects);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xcb_surface_set_clip_region (void *abstract_surface,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
cairo_xcb_surface_t *surface = abstract_surface;
|
||||
|
||||
if (region == surface->clip_region)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
cairo_region_destroy (surface->clip_region);
|
||||
region = cairo_region_reference (region);
|
||||
|
||||
if (surface->clip_rects) {
|
||||
free (surface->clip_rects);
|
||||
surface->clip_rects = NULL;
|
||||
}
|
||||
|
||||
surface->have_clip_rects = FALSE;
|
||||
surface->num_clip_rects = 0;
|
||||
|
||||
if (region == NULL) {
|
||||
uint32_t none[] = { XCB_NONE };
|
||||
if (surface->gc)
|
||||
xcb_change_gc (surface->dpy, surface->gc, XCB_GC_CLIP_MASK, none);
|
||||
|
||||
if (surface->xrender_format.id != XCB_NONE && surface->dst_picture)
|
||||
xcb_render_change_picture (surface->dpy, surface->dst_picture,
|
||||
XCB_RENDER_CP_CLIP_MASK, none);
|
||||
} else {
|
||||
xcb_rectangle_t *rects = NULL;
|
||||
int n_rects, i;
|
||||
|
||||
n_rects = cairo_region_num_rectangles (region);
|
||||
|
||||
if (n_rects > 0) {
|
||||
rects = _cairo_malloc_ab (n_rects, sizeof(xcb_rectangle_t));
|
||||
if (rects == NULL)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
} else {
|
||||
rects = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_rects; i++) {
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
|
||||
rects[i].x = rect.x;
|
||||
rects[i].y = rect.y;
|
||||
rects[i].width = rect.width;
|
||||
rects[i].height = rect.height;
|
||||
}
|
||||
|
||||
surface->have_clip_rects = TRUE;
|
||||
surface->clip_rects = rects;
|
||||
surface->num_clip_rects = n_rects;
|
||||
|
||||
if (surface->gc)
|
||||
_cairo_xcb_surface_set_gc_clip_rects (surface);
|
||||
|
||||
if (surface->dst_picture)
|
||||
_cairo_xcb_surface_set_picture_clip_rects (surface);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_xcb_surface_create_similar (void *abstract_src,
|
||||
cairo_content_t content,
|
||||
|
|
@ -223,6 +311,7 @@ _cairo_xcb_surface_finish (void *abstract_surface)
|
|||
xcb_free_gc (surface->dpy, surface->gc);
|
||||
|
||||
free (surface->clip_rects);
|
||||
cairo_region_destroy (surface->clip_region);
|
||||
|
||||
surface->dpy = NULL;
|
||||
|
||||
|
|
@ -475,26 +564,6 @@ _cairo_xcb_surface_ensure_src_picture (cairo_xcb_surface_t *surface)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_xcb_surface_set_picture_clip_rects (cairo_xcb_surface_t *surface)
|
||||
{
|
||||
if (surface->have_clip_rects)
|
||||
xcb_render_set_picture_clip_rectangles (surface->dpy, surface->dst_picture,
|
||||
0, 0,
|
||||
surface->num_clip_rects,
|
||||
surface->clip_rects);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_xcb_surface_set_gc_clip_rects (cairo_xcb_surface_t *surface)
|
||||
{
|
||||
if (surface->have_clip_rects)
|
||||
xcb_set_clip_rectangles(surface->dpy, XCB_CLIP_ORDERING_YX_SORTED, surface->gc,
|
||||
0, 0,
|
||||
surface->num_clip_rects,
|
||||
surface->clip_rects );
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_xcb_surface_ensure_dst_picture (cairo_xcb_surface_t *surface)
|
||||
{
|
||||
|
|
@ -1124,7 +1193,8 @@ _cairo_xcb_surface_composite (cairo_operator_t op,
|
|||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height)
|
||||
unsigned int height,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_surface_attributes_t src_attr, mask_attr;
|
||||
cairo_xcb_surface_t *dst = abstract_dst;
|
||||
|
|
@ -1163,6 +1233,10 @@ _cairo_xcb_surface_composite (cairo_operator_t op,
|
|||
goto BAIL;
|
||||
}
|
||||
|
||||
status = _cairo_xcb_surface_set_clip_region (dst, clip_region);
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
||||
status = _cairo_xcb_surface_set_attributes (src, &src_attr);
|
||||
if (status)
|
||||
goto BAIL;
|
||||
|
|
@ -1257,7 +1331,8 @@ _cairo_xcb_surface_composite (cairo_operator_t op,
|
|||
mask ? mask->height : 0,
|
||||
src_x, src_y,
|
||||
mask_x, mask_y,
|
||||
dst_x, dst_y, width, height);
|
||||
dst_x, dst_y, width, height,
|
||||
clip_region);
|
||||
|
||||
BAIL:
|
||||
if (mask)
|
||||
|
|
@ -1279,6 +1354,7 @@ _cairo_xcb_surface_fill_rectangles (void *abstract_surface,
|
|||
xcb_render_color_t render_color;
|
||||
xcb_rectangle_t static_xrects[16];
|
||||
xcb_rectangle_t *xrects = static_xrects;
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
|
||||
if (!CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLE (surface))
|
||||
|
|
@ -1289,6 +1365,9 @@ _cairo_xcb_surface_fill_rectangles (void *abstract_surface,
|
|||
render_color.blue = color->blue_short;
|
||||
render_color.alpha = color->alpha_short;
|
||||
|
||||
status = _cairo_xcb_surface_set_clip_region (surface, NULL);
|
||||
assert (status == CAIRO_STATUS_SUCCESS);
|
||||
|
||||
if (num_rects > ARRAY_LENGTH(static_xrects)) {
|
||||
xrects = _cairo_malloc_ab (num_rects, sizeof(xcb_rectangle_t));
|
||||
if (xrects == NULL)
|
||||
|
|
@ -1415,7 +1494,8 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op,
|
|||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_trapezoid_t *traps,
|
||||
int num_traps)
|
||||
int num_traps,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
cairo_surface_attributes_t attributes;
|
||||
cairo_xcb_surface_t *dst = abstract_dst;
|
||||
|
|
@ -1475,6 +1555,11 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op,
|
|||
render_src_y = src_y + render_reference_y - dst_y;
|
||||
|
||||
_cairo_xcb_surface_ensure_dst_picture (dst);
|
||||
|
||||
status = _cairo_xcb_surface_set_clip_region (dst, clip_region);
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
||||
status = _cairo_xcb_surface_set_attributes (src, &attributes);
|
||||
if (status)
|
||||
goto BAIL;
|
||||
|
|
@ -1516,7 +1601,8 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op,
|
|||
width, height,
|
||||
src_x, src_y,
|
||||
0, 0,
|
||||
dst_x, dst_y, width, height);
|
||||
dst_x, dst_y, width, height,
|
||||
clip_region);
|
||||
|
||||
} else {
|
||||
xcb_render_trapezoid_t xtraps_stack[16];
|
||||
|
|
@ -1562,68 +1648,7 @@ _cairo_xcb_surface_composite_trapezoids (cairo_operator_t op,
|
|||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_xcb_surface_set_clip_region (void *abstract_surface,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
cairo_xcb_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->clip_rects) {
|
||||
free (surface->clip_rects);
|
||||
surface->clip_rects = NULL;
|
||||
}
|
||||
|
||||
surface->have_clip_rects = FALSE;
|
||||
surface->num_clip_rects = 0;
|
||||
|
||||
if (region == NULL) {
|
||||
uint32_t none[] = { XCB_NONE };
|
||||
if (surface->gc)
|
||||
xcb_change_gc (surface->dpy, surface->gc, XCB_GC_CLIP_MASK, none);
|
||||
|
||||
if (surface->xrender_format.id != XCB_NONE && surface->dst_picture)
|
||||
xcb_render_change_picture (surface->dpy, surface->dst_picture,
|
||||
XCB_RENDER_CP_CLIP_MASK, none);
|
||||
} else {
|
||||
xcb_rectangle_t *rects = NULL;
|
||||
int n_rects, i;
|
||||
|
||||
n_rects = cairo_region_num_rectangles (region);
|
||||
|
||||
if (n_rects > 0) {
|
||||
rects = _cairo_malloc_ab (n_rects, sizeof(xcb_rectangle_t));
|
||||
if (rects == NULL)
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
} else {
|
||||
rects = NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_rects; i++) {
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
cairo_region_get_rectangle (region, i, &rect);
|
||||
|
||||
rects[i].x = rect.x;
|
||||
rects[i].y = rect.y;
|
||||
rects[i].width = rect.width;
|
||||
rects[i].height = rect.height;
|
||||
}
|
||||
|
||||
surface->have_clip_rects = TRUE;
|
||||
surface->clip_rects = rects;
|
||||
surface->num_clip_rects = n_rects;
|
||||
|
||||
if (surface->gc)
|
||||
_cairo_xcb_surface_set_gc_clip_rects (surface);
|
||||
|
||||
if (surface->dst_picture)
|
||||
_cairo_xcb_surface_set_picture_clip_rects (surface);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_xcb_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
|
|
@ -1635,7 +1660,7 @@ _cairo_xcb_surface_get_extents (void *abstract_surface,
|
|||
rectangle->width = surface->width;
|
||||
rectangle->height = surface->height;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* XXX: _cairo_xcb_surface_get_font_options */
|
||||
|
|
@ -1654,8 +1679,8 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
|
|||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
int *remaining_glyphs,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs);
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_xcb_surface_is_similar (void *surface_a,
|
||||
|
|
@ -1682,40 +1707,29 @@ _cairo_xcb_surface_is_similar (void *surface_a,
|
|||
return a->xrender_format.id == xrender_format->id;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_xcb_surface_reset (void *abstract_surface)
|
||||
{
|
||||
cairo_xcb_surface_t *surface = abstract_surface;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_xcb_surface_set_clip_region (surface, NULL);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* XXX: move this to the bottom of the file, XCB and Xlib */
|
||||
|
||||
static const cairo_surface_backend_t cairo_xcb_surface_backend = {
|
||||
CAIRO_SURFACE_TYPE_XCB,
|
||||
|
||||
_cairo_xcb_surface_create_similar,
|
||||
_cairo_xcb_surface_finish,
|
||||
_cairo_xcb_surface_acquire_source_image,
|
||||
_cairo_xcb_surface_release_source_image,
|
||||
|
||||
_cairo_xcb_surface_acquire_dest_image,
|
||||
_cairo_xcb_surface_release_dest_image,
|
||||
|
||||
_cairo_xcb_surface_clone_similar,
|
||||
_cairo_xcb_surface_composite,
|
||||
_cairo_xcb_surface_fill_rectangles,
|
||||
_cairo_xcb_surface_composite_trapezoids,
|
||||
NULL, /* create_span_renderer */
|
||||
NULL, /* check_span_renderer */
|
||||
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
_cairo_xcb_surface_set_clip_region,
|
||||
NULL, /* intersect_clip_path */
|
||||
|
||||
_cairo_xcb_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
|
|
@ -1733,8 +1747,6 @@ static const cairo_surface_backend_t cairo_xcb_surface_backend = {
|
|||
_cairo_xcb_surface_snapshot,
|
||||
|
||||
_cairo_xcb_surface_is_similar,
|
||||
|
||||
_cairo_xcb_surface_reset
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -1853,8 +1865,9 @@ _cairo_xcb_surface_create_internal (xcb_connection_t *dpy,
|
|||
surface->have_clip_rects = FALSE;
|
||||
surface->clip_rects = NULL;
|
||||
surface->num_clip_rects = 0;
|
||||
surface->clip_region = NULL;
|
||||
|
||||
return (cairo_surface_t *) surface;
|
||||
return &surface->base;
|
||||
}
|
||||
|
||||
static xcb_screen_t *
|
||||
|
|
@ -2463,8 +2476,8 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
|
|||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
int *remaining_glyphs,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs)
|
||||
{
|
||||
cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
|
||||
cairo_xcb_surface_t *dst = abstract_dst;
|
||||
|
|
@ -2474,6 +2487,7 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
|
|||
cairo_xcb_surface_t *src = NULL;
|
||||
|
||||
cairo_solid_pattern_t solid_pattern;
|
||||
cairo_region_t *clip_region = NULL;
|
||||
|
||||
if (!CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst) || dst->xrender_format.id == XCB_NONE)
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
|
@ -2497,10 +2511,12 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
|
|||
* fallback clip masking, we have to go through the full
|
||||
* fallback path.
|
||||
*/
|
||||
if (dst->base.clip &&
|
||||
(dst->base.clip->mode != CAIRO_CLIP_MODE_REGION ||
|
||||
dst->base.clip->surface != NULL))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (clip != NULL) {
|
||||
status = _cairo_clip_get_region (clip, &clip_region);
|
||||
assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO);
|
||||
if (status)
|
||||
return status;
|
||||
}
|
||||
|
||||
operation = _categorize_composite_operation (dst, op, src_pattern, TRUE);
|
||||
if (operation == DO_UNSUPPORTED)
|
||||
|
|
@ -2564,6 +2580,10 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst,
|
|||
goto BAIL;
|
||||
}
|
||||
|
||||
status = _cairo_xcb_surface_set_clip_region (dst, clip_region);
|
||||
if (unlikely (status))
|
||||
goto BAIL;
|
||||
|
||||
status = _cairo_xcb_surface_set_attributes (src, &attributes);
|
||||
if (status)
|
||||
goto BAIL;
|
||||
|
|
|
|||
|
|
@ -85,11 +85,11 @@ struct _cairo_xlib_surface {
|
|||
Picture dst_picture, src_picture;
|
||||
|
||||
unsigned int clip_dirty;
|
||||
cairo_bool_t have_clip_rects;
|
||||
cairo_bool_t gc_has_clip_rects;
|
||||
XRectangle embedded_clip_rects[8];
|
||||
XRectangle *clip_rects;
|
||||
int num_clip_rects;
|
||||
cairo_region_t *clip_region;
|
||||
|
||||
XRenderPictFormat *xrender_format;
|
||||
cairo_filter_t filter;
|
||||
|
|
|
|||
83
src/cairo.c
|
|
@ -44,6 +44,10 @@
|
|||
|
||||
#define CAIRO_TOLERANCE_MINIMUM _cairo_fixed_to_double(1)
|
||||
|
||||
#if !defined(INFINITY)
|
||||
#define INFINITY HUGE_VAL
|
||||
#endif
|
||||
|
||||
static const cairo_t _cairo_nil = {
|
||||
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
|
||||
CAIRO_STATUS_NO_MEMORY, /* status */
|
||||
|
|
@ -57,7 +61,8 @@ static const cairo_t _cairo_nil = {
|
|||
FALSE, /* has_current_point */
|
||||
FALSE, /* has_curve_to */
|
||||
FALSE, /* is_box */
|
||||
FALSE, /* is_region */
|
||||
FALSE, /* maybe_fill_region */
|
||||
TRUE, /* is_empty_fill */
|
||||
{{{NULL,NULL}}} /* link */
|
||||
}}
|
||||
};
|
||||
|
|
@ -496,25 +501,28 @@ cairo_push_group_with_content (cairo_t *cr, cairo_content_t content)
|
|||
{
|
||||
cairo_status_t status;
|
||||
cairo_rectangle_int_t extents;
|
||||
const cairo_rectangle_int_t *clip_extents;
|
||||
cairo_surface_t *parent_surface, *group_surface = NULL;
|
||||
cairo_bool_t is_empty;
|
||||
|
||||
if (unlikely (cr->status))
|
||||
return;
|
||||
|
||||
parent_surface = _cairo_gstate_get_target (cr->gstate);
|
||||
/* Get the extents that we'll use in creating our new group surface */
|
||||
status = _cairo_surface_get_extents (parent_surface, &extents);
|
||||
if (unlikely (status))
|
||||
goto bail;
|
||||
status = _cairo_clip_intersect_to_rectangle (_cairo_gstate_get_clip (cr->gstate), &extents);
|
||||
if (unlikely (status))
|
||||
goto bail;
|
||||
|
||||
group_surface = cairo_surface_create_similar (parent_surface,
|
||||
content,
|
||||
extents.width,
|
||||
extents.height);
|
||||
status = cairo_surface_status (group_surface);
|
||||
/* Get the extents that we'll use in creating our new group surface */
|
||||
is_empty = _cairo_surface_get_extents (parent_surface, &extents);
|
||||
clip_extents = _cairo_clip_get_extents (_cairo_gstate_get_clip (cr->gstate));
|
||||
if (clip_extents != NULL)
|
||||
is_empty = _cairo_rectangle_intersect (&extents, clip_extents);
|
||||
|
||||
group_surface = _cairo_surface_create_similar_solid (parent_surface,
|
||||
content,
|
||||
extents.width,
|
||||
extents.height,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
TRUE);
|
||||
status = group_surface->status;
|
||||
if (unlikely (status))
|
||||
goto bail;
|
||||
|
||||
|
|
@ -2340,7 +2348,7 @@ cairo_in_stroke (cairo_t *cr, double x, double y)
|
|||
cairo_bool_t inside = FALSE;
|
||||
|
||||
if (unlikely (cr->status))
|
||||
return 0;
|
||||
return FALSE;
|
||||
|
||||
status = _cairo_gstate_in_stroke (cr->gstate,
|
||||
cr->path,
|
||||
|
|
@ -2370,16 +2378,10 @@ cairo_in_stroke (cairo_t *cr, double x, double y)
|
|||
cairo_bool_t
|
||||
cairo_in_fill (cairo_t *cr, double x, double y)
|
||||
{
|
||||
cairo_bool_t inside;
|
||||
|
||||
if (unlikely (cr->status))
|
||||
return 0;
|
||||
return FALSE;
|
||||
|
||||
_cairo_gstate_in_fill (cr->gstate,
|
||||
cr->path,
|
||||
x, y, &inside);
|
||||
|
||||
return inside;
|
||||
return _cairo_gstate_in_fill (cr->gstate, cr->path, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2600,8 +2602,6 @@ cairo_clip_extents (cairo_t *cr,
|
|||
double *x1, double *y1,
|
||||
double *x2, double *y2)
|
||||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (unlikely (cr->status)) {
|
||||
if (x1)
|
||||
*x1 = 0.0;
|
||||
|
|
@ -2615,9 +2615,38 @@ cairo_clip_extents (cairo_t *cr,
|
|||
return;
|
||||
}
|
||||
|
||||
status = _cairo_gstate_clip_extents (cr->gstate, x1, y1, x2, y2);
|
||||
if (unlikely (status))
|
||||
_cairo_set_error (cr, status);
|
||||
if (! _cairo_gstate_clip_extents (cr->gstate, x1, y1, x2, y2)) {
|
||||
*x1 = -INFINITY;
|
||||
*y1 = -INFINITY;
|
||||
*x2 = +INFINITY;
|
||||
*y2 = +INFINITY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cairo_in_clip:
|
||||
* @cr: a cairo context
|
||||
* @x: X coordinate of the point to test
|
||||
* @y: Y coordinate of the point to test
|
||||
*
|
||||
* Tests whether the given point is inside the area that would be
|
||||
* visible through the current clip, i.e. the area that would be filled by
|
||||
* a cairo_paint() operation.
|
||||
*
|
||||
* See cairo_clip(), and cairo_clip_preserve().
|
||||
*
|
||||
* Return value: A non-zero value if the point is inside, or zero if
|
||||
* outside.
|
||||
*
|
||||
* Since: 1.10
|
||||
**/
|
||||
cairo_bool_t
|
||||
cairo_in_clip (cairo_t *cr, double x, double y)
|
||||
{
|
||||
if (unlikely (cr->status))
|
||||
return FALSE;
|
||||
|
||||
return _cairo_gstate_in_clip (cr->gstate, x, y);
|
||||
}
|
||||
|
||||
static cairo_rectangle_list_t *
|
||||
|
|
|
|||
30
src/cairo.h
|
|
@ -788,6 +788,9 @@ cairo_in_stroke (cairo_t *cr, double x, double y);
|
|||
cairo_public cairo_bool_t
|
||||
cairo_in_fill (cairo_t *cr, double x, double y);
|
||||
|
||||
cairo_public cairo_bool_t
|
||||
cairo_in_clip (cairo_t *cr, double x, double y);
|
||||
|
||||
/* Rectangular extents */
|
||||
cairo_public void
|
||||
cairo_stroke_extents (cairo_t *cr,
|
||||
|
|
@ -2169,8 +2172,7 @@ cairo_image_surface_create_from_png_stream (cairo_read_func_t read_func,
|
|||
|
||||
cairo_public cairo_surface_t *
|
||||
cairo_meta_surface_create (cairo_content_t content,
|
||||
double width_pixels,
|
||||
double height_pixels);
|
||||
const cairo_rectangle_t *extents);
|
||||
|
||||
cairo_public void
|
||||
cairo_meta_surface_ink_extents (cairo_surface_t *surface,
|
||||
|
|
@ -2451,39 +2453,45 @@ cairo_public cairo_region_t *
|
|||
cairo_region_create_rectangle (const cairo_rectangle_int_t *rectangle);
|
||||
|
||||
cairo_public cairo_region_t *
|
||||
cairo_region_create_rectangles (cairo_rectangle_int_t *rects,
|
||||
cairo_region_create_rectangles (const cairo_rectangle_int_t *rects,
|
||||
int count);
|
||||
|
||||
cairo_public cairo_region_t *
|
||||
cairo_region_copy (cairo_region_t *original);
|
||||
cairo_region_copy (const cairo_region_t *original);
|
||||
|
||||
cairo_public cairo_region_t *
|
||||
cairo_region_reference (cairo_region_t *);
|
||||
|
||||
cairo_public void
|
||||
cairo_region_destroy (cairo_region_t *region);
|
||||
|
||||
cairo_public cairo_bool_t
|
||||
cairo_region_equal (const cairo_region_t *a, const cairo_region_t *b);
|
||||
|
||||
cairo_public cairo_status_t
|
||||
cairo_region_status (cairo_region_t *region);
|
||||
cairo_region_status (const cairo_region_t *region);
|
||||
|
||||
cairo_public void
|
||||
cairo_region_get_extents (cairo_region_t *region,
|
||||
cairo_region_get_extents (const cairo_region_t *region,
|
||||
cairo_rectangle_int_t *extents);
|
||||
|
||||
cairo_public int
|
||||
cairo_region_num_rectangles (cairo_region_t *region);
|
||||
cairo_region_num_rectangles (const cairo_region_t *region);
|
||||
|
||||
cairo_public void
|
||||
cairo_region_get_rectangle (cairo_region_t *region,
|
||||
cairo_region_get_rectangle (const cairo_region_t *region,
|
||||
int nth_rectangle,
|
||||
cairo_rectangle_int_t *rectangle);
|
||||
|
||||
cairo_public cairo_bool_t
|
||||
cairo_region_is_empty (cairo_region_t *region);
|
||||
cairo_region_is_empty (const cairo_region_t *region);
|
||||
|
||||
cairo_public cairo_region_overlap_t
|
||||
cairo_region_contains_rectangle (cairo_region_t *region,
|
||||
cairo_region_contains_rectangle (const cairo_region_t *region,
|
||||
const cairo_rectangle_int_t *rectangle);
|
||||
|
||||
cairo_public cairo_bool_t
|
||||
cairo_region_contains_point (cairo_region_t *region, int x, int y);
|
||||
cairo_region_contains_point (const cairo_region_t *region, int x, int y);
|
||||
|
||||
cairo_public void
|
||||
cairo_region_translate (cairo_region_t *region, int dx, int dy);
|
||||
|
|
|
|||
325
src/cairoint.h
|
|
@ -125,7 +125,7 @@ _cairo_win32_tmpfile (void);
|
|||
#define STRINGIFY(macro_or_string) STRINGIFY_ARG (macro_or_string)
|
||||
#define STRINGIFY_ARG(contents) #contents
|
||||
|
||||
#ifdef __GNUC__
|
||||
#if defined (__GNUC__)
|
||||
#define cairo_container_of(ptr, type, member) ({ \
|
||||
const __typeof__ (((type *) 0)->member) *mptr__ = (ptr); \
|
||||
(type *) ((char *) mptr__ - offsetof (type, member)); \
|
||||
|
|
@ -252,6 +252,15 @@ cairo_private void
|
|||
_cairo_box_round_to_rectangle (const cairo_box_t *box,
|
||||
cairo_rectangle_int_t *rectangle);
|
||||
|
||||
static inline void
|
||||
_cairo_unbounded_rectangle_init (cairo_rectangle_int_t *rect)
|
||||
{
|
||||
rect->x = CAIRO_RECT_INT_MIN;
|
||||
rect->y = CAIRO_RECT_INT_MIN;
|
||||
rect->width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
|
||||
rect->height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
|
||||
}
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_rectangle_intersect (cairo_rectangle_int_t *dst,
|
||||
const cairo_rectangle_int_t *src);
|
||||
|
|
@ -489,6 +498,7 @@ struct _cairo_scaled_font_backend {
|
|||
unsigned int height,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_region_t *clip_region,
|
||||
int *remaining_glyphs);
|
||||
|
||||
cairo_warn cairo_int_status_t
|
||||
|
|
@ -615,6 +625,7 @@ struct _cairo_surface_backend {
|
|||
int *clone_offset_y,
|
||||
cairo_surface_t **clone_out);
|
||||
|
||||
/* XXX remove to a separate cairo_surface_compositor_t */
|
||||
/* XXX: dst should be the first argument for consistency */
|
||||
cairo_warn cairo_int_status_t
|
||||
(*composite) (cairo_operator_t op,
|
||||
|
|
@ -628,7 +639,8 @@ struct _cairo_surface_backend {
|
|||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
unsigned int height,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
cairo_warn cairo_int_status_t
|
||||
(*fill_rectangles) (void *surface,
|
||||
|
|
@ -650,14 +662,16 @@ struct _cairo_surface_backend {
|
|||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_trapezoid_t *traps,
|
||||
int num_traps);
|
||||
int num_traps,
|
||||
cairo_region_t *region);
|
||||
|
||||
cairo_warn cairo_span_renderer_t *
|
||||
(*create_span_renderer) (cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern,
|
||||
void *dst,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_composite_rectangles_t *rects);
|
||||
const cairo_composite_rectangles_t *rects,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
cairo_warn cairo_bool_t
|
||||
(*check_span_renderer) (cairo_operator_t op,
|
||||
|
|
@ -672,59 +686,15 @@ struct _cairo_surface_backend {
|
|||
cairo_warn cairo_int_status_t
|
||||
(*show_page) (void *surface);
|
||||
|
||||
/* Set given region as the clip region for the surface, replacing
|
||||
* any previously set clip region. Passing in a NULL region will
|
||||
* clear the surface clip region.
|
||||
*
|
||||
* The surface is expected to store the clip region and clip all
|
||||
* following drawing operations against it until the clip region
|
||||
* is cleared of replaced by another clip region.
|
||||
*
|
||||
* Cairo will call this function whenever a clip path can be
|
||||
* represented as a device pixel aligned set of rectangles. When
|
||||
* this is not possible, cairo will use mask surfaces for
|
||||
* clipping.
|
||||
*/
|
||||
cairo_warn cairo_int_status_t
|
||||
(*set_clip_region) (void *surface,
|
||||
cairo_region_t *region);
|
||||
|
||||
/* Intersect the given path against the clip path currently set in
|
||||
* the surface, using the given fill_rule and tolerance, and set
|
||||
* the result as the new clipping path for the surface. Passing
|
||||
* in a NULL path will clear the surface clipping path.
|
||||
*
|
||||
* The surface is expected to store the resulting clip path and
|
||||
* clip all following drawing operations against it until the clip
|
||||
* path cleared or intersected with a new path.
|
||||
*
|
||||
* If a surface implements this function, set_clip_region() will
|
||||
* never be called and should not be implemented. If this
|
||||
* function is not implemented cairo will use set_clip_region()
|
||||
* (if available) and mask surfaces for clipping.
|
||||
*/
|
||||
cairo_warn cairo_int_status_t
|
||||
(*intersect_clip_path) (void *dst,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias);
|
||||
|
||||
/* Get the extents of the current surface. For many surface types
|
||||
* this will be as simple as { x=0, y=0, width=surface->width,
|
||||
* height=surface->height}.
|
||||
*
|
||||
* This function need not take account of any clipping from
|
||||
* set_clip_region since the generic version of set_clip_region
|
||||
* saves those, and the generic get_clip_extents will only call
|
||||
* into the specific surface->get_extents if there is no current
|
||||
* clip.
|
||||
*
|
||||
* If this function is not implemented, or if it returns
|
||||
* %CAIRO_INT_STATUS_UNSUPPORTED, the surface is considered to be
|
||||
* boundless and inifnite bounds are used for it.
|
||||
* FALSE the surface is considered to be
|
||||
* boundless and infinite bounds are used for it.
|
||||
*/
|
||||
cairo_warn cairo_int_status_t
|
||||
cairo_warn cairo_bool_t
|
||||
(*get_extents) (void *surface,
|
||||
cairo_rectangle_int_t *extents);
|
||||
|
||||
|
|
@ -745,7 +715,8 @@ struct _cairo_surface_backend {
|
|||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs);
|
||||
int num_glyphs,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
void
|
||||
(*get_font_options) (void *surface,
|
||||
|
|
@ -775,14 +746,14 @@ struct _cairo_surface_backend {
|
|||
(*paint) (void *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_warn cairo_int_status_t
|
||||
(*mask) (void *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_warn cairo_int_status_t
|
||||
(*stroke) (void *surface,
|
||||
|
|
@ -794,7 +765,7 @@ struct _cairo_surface_backend {
|
|||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_warn cairo_int_status_t
|
||||
(*fill) (void *surface,
|
||||
|
|
@ -804,7 +775,7 @@ struct _cairo_surface_backend {
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_warn cairo_int_status_t
|
||||
(*show_glyphs) (void *surface,
|
||||
|
|
@ -813,8 +784,8 @@ struct _cairo_surface_backend {
|
|||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
int *remaining_glyphs,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs);
|
||||
|
||||
cairo_surface_t *
|
||||
(*snapshot) (void *surface);
|
||||
|
|
@ -824,9 +795,6 @@ struct _cairo_surface_backend {
|
|||
void *surface_b,
|
||||
cairo_content_t content);
|
||||
|
||||
cairo_warn cairo_status_t
|
||||
(*reset) (void *surface);
|
||||
|
||||
cairo_warn cairo_int_status_t
|
||||
(*fill_stroke) (void *surface,
|
||||
cairo_operator_t fill_op,
|
||||
|
|
@ -842,7 +810,7 @@ struct _cairo_surface_backend {
|
|||
cairo_matrix_t *stroke_ctm_inverse,
|
||||
double stroke_tolerance,
|
||||
cairo_antialias_t stroke_antialias,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_surface_t *
|
||||
(*create_solid_pattern_surface)
|
||||
|
|
@ -869,7 +837,7 @@ struct _cairo_surface_backend {
|
|||
int num_clusters,
|
||||
cairo_text_cluster_flags_t cluster_flags,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
};
|
||||
|
||||
#include "cairo-surface-private.h"
|
||||
|
|
@ -887,9 +855,9 @@ struct _cairo_image_surface {
|
|||
int depth;
|
||||
|
||||
pixman_image_t *pixman_image;
|
||||
cairo_region_t *clip_region;
|
||||
|
||||
unsigned owns_data : 1;
|
||||
unsigned has_clip : 1;
|
||||
unsigned transparency : 2;
|
||||
};
|
||||
|
||||
|
|
@ -983,6 +951,8 @@ typedef struct _cairo_traps {
|
|||
|
||||
cairo_box_t extents;
|
||||
|
||||
unsigned int maybe_region : 1; /* hint: 0 implies that it cannot be */
|
||||
|
||||
int num_traps;
|
||||
int traps_size;
|
||||
cairo_trapezoid_t *traps;
|
||||
|
|
@ -1245,12 +1215,16 @@ _cairo_gstate_in_stroke (cairo_gstate_t *gstate,
|
|||
double y,
|
||||
cairo_bool_t *inside_ret);
|
||||
|
||||
cairo_private void
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_gstate_in_fill (cairo_gstate_t *gstate,
|
||||
cairo_path_fixed_t *path,
|
||||
double x,
|
||||
double y,
|
||||
cairo_bool_t *inside_ret);
|
||||
double y);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_gstate_in_clip (cairo_gstate_t *gstate,
|
||||
double x,
|
||||
double y);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path);
|
||||
|
|
@ -1258,12 +1232,12 @@ _cairo_gstate_clip (cairo_gstate_t *gstate, cairo_path_fixed_t *path);
|
|||
cairo_private cairo_status_t
|
||||
_cairo_gstate_reset_clip (cairo_gstate_t *gstate);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_gstate_clip_extents (cairo_gstate_t *gstate,
|
||||
double *x1,
|
||||
double *y1,
|
||||
double *x2,
|
||||
double *y2);
|
||||
double *x2,
|
||||
double *y2);
|
||||
|
||||
cairo_private cairo_rectangle_list_t*
|
||||
_cairo_gstate_copy_clip_rectangle_list (cairo_gstate_t *gstate);
|
||||
|
|
@ -1480,19 +1454,19 @@ cairo_private void
|
|||
_cairo_intern_string_reset_static_data (void);
|
||||
|
||||
/* cairo-path-fixed.c */
|
||||
cairo_private cairo_path_fixed_t *
|
||||
_cairo_path_fixed_create (void);
|
||||
|
||||
cairo_private void
|
||||
_cairo_path_fixed_init (cairo_path_fixed_t *path);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_path_fixed_init_copy (cairo_path_fixed_t *path,
|
||||
cairo_path_fixed_t *other);
|
||||
const cairo_path_fixed_t *other);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_path_fixed_is_equal (cairo_path_fixed_t *path,
|
||||
cairo_path_fixed_t *other);
|
||||
|
||||
cairo_private cairo_path_fixed_t *
|
||||
_cairo_path_fixed_create (void);
|
||||
_cairo_path_fixed_is_equal (const cairo_path_fixed_t *path,
|
||||
const cairo_path_fixed_t *other);
|
||||
|
||||
cairo_private void
|
||||
_cairo_path_fixed_fini (cairo_path_fixed_t *path);
|
||||
|
|
@ -1578,64 +1552,69 @@ _cairo_path_fixed_interpret_flat (const cairo_path_fixed_t *path,
|
|||
void *closure,
|
||||
double tolerance);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_path_fixed_append (cairo_path_fixed_t *path,
|
||||
const cairo_path_fixed_t *other,
|
||||
cairo_direction_t dir);
|
||||
|
||||
cairo_private void
|
||||
_cairo_path_fixed_approximate_clip_extents (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_approximate_clip_extents (const cairo_path_fixed_t *path,
|
||||
cairo_rectangle_int_t *extents);
|
||||
|
||||
cairo_private void
|
||||
_cairo_path_fixed_approximate_fill_extents (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_approximate_fill_extents (const cairo_path_fixed_t *path,
|
||||
cairo_rectangle_int_t *extents);
|
||||
|
||||
cairo_private void
|
||||
_cairo_path_fixed_approximate_stroke_extents (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_fill_extents (const cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_rectangle_int_t *extents);
|
||||
|
||||
cairo_private void
|
||||
_cairo_path_fixed_approximate_stroke_extents (const cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
cairo_rectangle_int_t *extents);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_path_fixed_stroke_extents (const cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_rectangle_int_t *extents);
|
||||
|
||||
cairo_private void
|
||||
_cairo_path_fixed_bounds (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_bounds (const cairo_path_fixed_t *path,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2);
|
||||
|
||||
cairo_private void
|
||||
_cairo_path_fixed_transform (cairo_path_fixed_t *path,
|
||||
cairo_matrix_t *matrix);
|
||||
const cairo_matrix_t *matrix);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_path_fixed_is_empty (cairo_path_fixed_t *path);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_path_fixed_is_box (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_is_box (const cairo_path_fixed_t *path,
|
||||
cairo_box_t *box);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_path_fixed_is_rectangle (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_is_rectangle (const cairo_path_fixed_t *path,
|
||||
cairo_box_t *box);
|
||||
|
||||
/* cairo-path-in-fill.c */
|
||||
cairo_private void
|
||||
_cairo_path_fixed_in_fill (cairo_path_fixed_t *path,
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_path_fixed_in_fill (const cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
double x,
|
||||
double y,
|
||||
cairo_bool_t *is_inside);
|
||||
double y);
|
||||
|
||||
/* cairo-path-fill.c */
|
||||
cairo_private cairo_status_t
|
||||
_cairo_path_fixed_fill_to_traps (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_fill_to_traps (const cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_traps_t *traps);
|
||||
|
||||
/* cairo-path-stroke.c */
|
||||
cairo_private cairo_status_t
|
||||
_cairo_path_fixed_stroke_to_traps (cairo_path_fixed_t *path,
|
||||
_cairo_path_fixed_stroke_to_traps (const cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *stroke_style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
|
|
@ -1707,7 +1686,8 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs);
|
||||
int num_glyphs,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
|
||||
|
|
@ -1789,11 +1769,12 @@ _cairo_surface_create_similar_scratch (cairo_surface_t *other,
|
|||
int height);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_surface_create_similar_solid (cairo_surface_t *other,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height,
|
||||
const cairo_color_t *color);
|
||||
_cairo_surface_create_similar_solid (cairo_surface_t *other,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height,
|
||||
const cairo_color_t *color,
|
||||
cairo_bool_t allow_fallback);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_surface_create_solid_pattern_surface (cairo_surface_t *other,
|
||||
|
|
@ -1813,22 +1794,20 @@ cairo_private void
|
|||
_cairo_surface_set_font_options (cairo_surface_t *surface,
|
||||
cairo_font_options_t *options);
|
||||
|
||||
cairo_private cairo_clip_mode_t
|
||||
_cairo_surface_get_clip_mode (cairo_surface_t *surface);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_composite (cairo_operator_t op,
|
||||
const cairo_pattern_t *src,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_surface_t *dst,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int mask_x,
|
||||
int mask_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
int src_x,
|
||||
int src_y,
|
||||
int mask_x,
|
||||
int mask_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_fill_rectangle (cairo_surface_t *surface,
|
||||
|
|
@ -1856,14 +1835,14 @@ cairo_private cairo_status_t
|
|||
_cairo_surface_paint (cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_mask (cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_fill_stroke (cairo_surface_t *surface,
|
||||
|
|
@ -1880,7 +1859,7 @@ _cairo_surface_fill_stroke (cairo_surface_t *surface,
|
|||
cairo_matrix_t *stroke_ctm_inverse,
|
||||
double stroke_tolerance,
|
||||
cairo_antialias_t stroke_antialias,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_stroke (cairo_surface_t *surface,
|
||||
|
|
@ -1892,7 +1871,7 @@ _cairo_surface_stroke (cairo_surface_t *surface,
|
|||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_fill (cairo_surface_t *surface,
|
||||
|
|
@ -1902,7 +1881,7 @@ _cairo_surface_fill (cairo_surface_t *surface,
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_show_text_glyphs (cairo_surface_t *surface,
|
||||
|
|
@ -1916,7 +1895,7 @@ _cairo_surface_show_text_glyphs (cairo_surface_t *surface,
|
|||
int num_clusters,
|
||||
cairo_text_cluster_flags_t cluster_flags,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_composite_trapezoids (cairo_operator_t op,
|
||||
|
|
@ -1930,23 +1909,23 @@ _cairo_surface_composite_trapezoids (cairo_operator_t op,
|
|||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_trapezoid_t *traps,
|
||||
int ntraps);
|
||||
int ntraps,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
cairo_private cairo_span_renderer_t *
|
||||
_cairo_surface_create_span_renderer (
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_surface_t *dst,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_composite_rectangles_t *rects);
|
||||
_cairo_surface_create_span_renderer (cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_surface_t *dst,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_composite_rectangles_t *rects,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_surface_check_span_renderer (
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_surface_t *dst,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_composite_rectangles_t *rects);
|
||||
_cairo_surface_check_span_renderer (cairo_operator_t op,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_surface_t *dst,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_composite_rectangles_t *rects);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_acquire_source_image (cairo_surface_t *surface,
|
||||
|
|
@ -2005,37 +1984,7 @@ _cairo_surface_is_similar (cairo_surface_t *surface_a,
|
|||
cairo_surface_t *surface_b,
|
||||
cairo_content_t content);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_reset (cairo_surface_t *surface);
|
||||
|
||||
cairo_private unsigned int
|
||||
_cairo_surface_get_current_clip_serial (cairo_surface_t *surface);
|
||||
|
||||
cairo_private unsigned int
|
||||
_cairo_surface_allocate_clip_serial (cairo_surface_t *surface);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_reset_clip (cairo_surface_t *surface);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_set_clip_region (cairo_surface_t *surface,
|
||||
cairo_region_t *region,
|
||||
unsigned int serial);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_surface_intersect_clip_path (cairo_surface_t *surface,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias);
|
||||
|
||||
cairo_private cairo_clip_t *
|
||||
_cairo_surface_get_clip (cairo_surface_t *surface);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_set_clip (cairo_surface_t *surface, cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_surface_get_extents (cairo_surface_t *surface,
|
||||
cairo_rectangle_int_t *extents);
|
||||
|
||||
|
|
@ -2051,7 +2000,8 @@ _cairo_surface_old_show_glyphs (cairo_scaled_font_t *scaled_font,
|
|||
unsigned int width,
|
||||
unsigned int height,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs);
|
||||
int num_glyphs,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst,
|
||||
|
|
@ -2068,7 +2018,8 @@ _cairo_surface_composite_fixup_unbounded (cairo_surface_t *dst,
|
|||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
unsigned int height,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
|
||||
|
|
@ -2084,7 +2035,8 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t *dst,
|
|||
int dst_x,
|
||||
int dst_y,
|
||||
unsigned int width,
|
||||
unsigned int height);
|
||||
unsigned int height,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_surface_is_opaque (const cairo_surface_t *surface);
|
||||
|
|
@ -2193,19 +2145,6 @@ _cairo_image_surface_create_for_data_with_content (unsigned char *data,
|
|||
cairo_private void
|
||||
_cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface);
|
||||
|
||||
/* XXX: It's a nasty kludge that this appears here. Backend functions
|
||||
* like this should really be static. But we're doing this to work
|
||||
* around some general defects in the backend clipping interfaces,
|
||||
* (see some notes in test-paginated-surface.c).
|
||||
*
|
||||
* I want to fix the real defects, but it's "hard" as they touch many
|
||||
* backends, so doing that will require synchronizing several backend
|
||||
* maintainers.
|
||||
*/
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_image_surface_set_clip_region (void *abstract_surface,
|
||||
cairo_region_t *region);
|
||||
|
||||
cairo_private cairo_image_surface_t *
|
||||
_cairo_image_surface_coerce (cairo_image_surface_t *surface,
|
||||
cairo_format_t format);
|
||||
|
|
@ -2439,8 +2378,8 @@ _cairo_traps_extents (const cairo_traps_t *traps,
|
|||
cairo_box_t *extents);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_traps_extract_region (const cairo_traps_t *tr,
|
||||
cairo_region_t **region);
|
||||
_cairo_traps_extract_region (cairo_traps_t *traps,
|
||||
cairo_region_t **region);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_traps_path (const cairo_traps_t *traps,
|
||||
|
|
@ -2560,7 +2499,7 @@ _cairo_pattern_acquire_surfaces (const cairo_pattern_t *src,
|
|||
cairo_surface_attributes_t *src_attributes,
|
||||
cairo_surface_attributes_t *mask_attributes);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
cairo_private void
|
||||
_cairo_pattern_get_extents (const cairo_pattern_t *pattern,
|
||||
cairo_rectangle_int_t *extents);
|
||||
|
||||
|
|
@ -2577,23 +2516,8 @@ _cairo_pattern_equal (const cairo_pattern_t *a,
|
|||
cairo_private void
|
||||
_cairo_pattern_reset_static_data (void);
|
||||
|
||||
/* cairo-region.c */
|
||||
|
||||
struct _cairo_region {
|
||||
cairo_status_t status;
|
||||
|
||||
pixman_region32_t rgn;
|
||||
};
|
||||
|
||||
cairo_private void
|
||||
_cairo_region_init (cairo_region_t *region);
|
||||
|
||||
cairo_private void
|
||||
_cairo_region_init_rectangle (cairo_region_t *region,
|
||||
const cairo_rectangle_int_t *rectangle);
|
||||
|
||||
cairo_private void
|
||||
_cairo_region_fini (cairo_region_t *region);
|
||||
_cairo_clip_reset_static_data (void);
|
||||
|
||||
/* cairo-unicode.c */
|
||||
|
||||
|
|
@ -2725,7 +2649,6 @@ slim_hidden_proto (cairo_status);
|
|||
slim_hidden_proto (cairo_stroke);
|
||||
slim_hidden_proto (cairo_stroke_preserve);
|
||||
slim_hidden_proto (cairo_surface_copy_page);
|
||||
slim_hidden_proto (cairo_surface_create_similar);
|
||||
slim_hidden_proto (cairo_surface_destroy);
|
||||
slim_hidden_proto (cairo_surface_finish);
|
||||
slim_hidden_proto (cairo_surface_flush);
|
||||
|
|
@ -2760,7 +2683,9 @@ slim_hidden_proto (cairo_region_create);
|
|||
slim_hidden_proto (cairo_region_create_rectangle);
|
||||
slim_hidden_proto (cairo_region_create_rectangles);
|
||||
slim_hidden_proto (cairo_region_copy);
|
||||
slim_hidden_proto (cairo_region_reference);
|
||||
slim_hidden_proto (cairo_region_destroy);
|
||||
slim_hidden_proto (cairo_region_equal);
|
||||
slim_hidden_proto (cairo_region_status);
|
||||
slim_hidden_proto (cairo_region_get_extents);
|
||||
slim_hidden_proto (cairo_region_num_rectangles);
|
||||
|
|
|
|||
|
|
@ -194,7 +194,7 @@ _test_fallback_surface_clone_similar (void *abstract_surface,
|
|||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_test_fallback_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
|
|
@ -219,8 +219,6 @@ static const cairo_surface_backend_t test_fallback_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
NULL, /* set_clip_region */
|
||||
NULL, /* intersect_clip_path */
|
||||
_test_fallback_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ _test_fallback16_surface_clone_similar (void *abstract_surface,
|
|||
}
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_test_fallback16_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
|
|
@ -218,8 +218,6 @@ static const cairo_surface_backend_t test_fallback16_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
NULL, /* set_clip_region */
|
||||
NULL, /* intersect_clip_path */
|
||||
_test_fallback16_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
|
|
|
|||
|
|
@ -50,26 +50,17 @@ _return_success (void)
|
|||
|
||||
/* These typedefs are just to silence the compiler... */
|
||||
typedef cairo_int_status_t
|
||||
(*_set_clip_region_func) (void *surface,
|
||||
cairo_region_t *region);
|
||||
typedef cairo_int_status_t
|
||||
(*_intersect_clip_path_func) (void *dst,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias);
|
||||
typedef cairo_int_status_t
|
||||
(*_paint_func) (void *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
typedef cairo_int_status_t
|
||||
(*_mask_func) (void *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
typedef cairo_int_status_t
|
||||
(*_stroke_func) (void *surface,
|
||||
|
|
@ -81,7 +72,7 @@ typedef cairo_int_status_t
|
|||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
typedef cairo_int_status_t
|
||||
(*_fill_func) (void *surface,
|
||||
|
|
@ -91,7 +82,7 @@ typedef cairo_int_status_t
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
typedef cairo_int_status_t
|
||||
(*_show_glyphs_func) (void *surface,
|
||||
|
|
@ -100,8 +91,8 @@ typedef cairo_int_status_t
|
|||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
int *remaining_glyphs,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip,
|
||||
int *remaining_glyphs);
|
||||
|
||||
typedef cairo_int_status_t
|
||||
(*_show_text_glyphs_func) (void *surface,
|
||||
|
|
@ -115,7 +106,7 @@ typedef cairo_int_status_t
|
|||
int num_clusters,
|
||||
cairo_text_cluster_flags_t cluster_flags,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_clip_t *clip);
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_null_surface_create_similar (void *other,
|
||||
|
|
@ -125,16 +116,11 @@ _cairo_null_surface_create_similar (void *other,
|
|||
return _cairo_test_null_surface_create (content);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_cairo_null_surface_get_extents (void *surface,
|
||||
cairo_rectangle_int_t *extents)
|
||||
{
|
||||
extents->x = 0;
|
||||
extents->y = 0;
|
||||
extents->width = 0;
|
||||
extents->height = 0;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
|
|
@ -160,8 +146,6 @@ static const cairo_surface_backend_t null_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
(_set_clip_region_func) _return_success, /* set_clip_region */
|
||||
(_intersect_clip_path_func) _return_success, /* intersect_clip_path */
|
||||
_cairo_null_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
|
|
@ -176,7 +160,6 @@ static const cairo_surface_backend_t null_surface_backend = {
|
|||
(_show_glyphs_func) _return_success, /* show_glyphs */
|
||||
NULL, /* snapshot */
|
||||
NULL, /* is_similar */
|
||||
NULL, /* reset */
|
||||
NULL, /* fill_stroke */
|
||||
NULL, /* create_solid_pattern_surface */
|
||||
NULL, /* can_repaint_solid_pattern_surface */
|
||||
|
|
|
|||
|
|
@ -61,37 +61,27 @@ static const cairo_surface_backend_t test_paginated_surface_backend;
|
|||
static const cairo_paginated_surface_backend_t test_paginated_surface_paginated_backend;
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_test_paginated_surface_create_for_data (unsigned char *data,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height,
|
||||
int stride)
|
||||
_cairo_test_paginated_surface_create (cairo_surface_t *target)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_surface_t *target;
|
||||
cairo_surface_t *paginated;
|
||||
test_paginated_surface_t *surface;
|
||||
|
||||
target = _cairo_image_surface_create_for_data_with_content (data, content,
|
||||
width, height,
|
||||
stride);
|
||||
status = cairo_surface_status (target);
|
||||
if (status)
|
||||
return target;
|
||||
if (unlikely (status))
|
||||
return _cairo_surface_create_in_error (status);
|
||||
|
||||
surface = malloc (sizeof (test_paginated_surface_t));
|
||||
if (unlikely (surface == NULL)) {
|
||||
cairo_surface_destroy (target);
|
||||
if (unlikely (surface == NULL))
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
}
|
||||
|
||||
_cairo_surface_init (&surface->base, &test_paginated_surface_backend,
|
||||
content);
|
||||
target->content);
|
||||
|
||||
surface->target = target;
|
||||
surface->target = cairo_surface_reference (target);
|
||||
|
||||
paginated = _cairo_paginated_surface_create (&surface->base,
|
||||
content, width, height,
|
||||
target->content,
|
||||
&test_paginated_surface_paginated_backend);
|
||||
status = paginated->status;
|
||||
if (status == CAIRO_STATUS_SUCCESS) {
|
||||
|
|
@ -115,49 +105,7 @@ _test_paginated_surface_finish (void *abstract_surface)
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_test_paginated_surface_set_clip_region (void *abstract_surface,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
test_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
/* XXX: The whole surface backend clipping interface is a giant
|
||||
* disaster right now. In particular, its uncleanness shows up
|
||||
* when trying to implement one surface that wraps another one (as
|
||||
* we are doing here).
|
||||
*
|
||||
* Here are two of the problems that show up:
|
||||
*
|
||||
* 1. The most critical piece of information in all this stuff,
|
||||
* the "clip" isn't getting passed to the backend
|
||||
* functions. Instead the generic surface layer is caching that as
|
||||
* surface->clip. This is a problem for surfaces like this one
|
||||
* that do wrapping. Our base surface will have the clip set, but
|
||||
* our target's surface will not.
|
||||
*
|
||||
* 2. We're here in our backend's set_clip_region function, and we
|
||||
* want to call into our target surface's set_clip_region.
|
||||
* Generally, we would do this by calling an equivalent
|
||||
* _cairo_surface function, but _cairo_surface_set_clip_region
|
||||
* does not have the same signature/semantics, (it has the
|
||||
* clip_serial stuff as well).
|
||||
*
|
||||
* We kludge around each of these by manually copying the clip
|
||||
* object from our base surface into the target's base surface
|
||||
* (yuck!) and by reaching directly into the image surface's
|
||||
* set_clip_region instead of calling into the generic
|
||||
* _cairo_surface_set_clip_region (double yuck!).
|
||||
*/
|
||||
|
||||
surface->target->clip = surface->base.clip;
|
||||
|
||||
return _cairo_image_surface_set_clip_region (surface->target, region);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
static cairo_bool_t
|
||||
_test_paginated_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
|
|
@ -170,14 +118,14 @@ static cairo_int_status_t
|
|||
_test_paginated_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
test_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return _cairo_surface_paint (surface->target, op, source, extents);
|
||||
return _cairo_surface_paint (surface->target, op, source, clip);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -185,14 +133,15 @@ _test_paginated_surface_mask (void *abstract_surface,
|
|||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
test_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return _cairo_surface_mask (surface->target, op, source, mask, extents);
|
||||
return _cairo_surface_mask (surface->target,
|
||||
op, source, mask, clip);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -205,7 +154,7 @@ _test_paginated_surface_stroke (void *abstract_surface,
|
|||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
test_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
|
|
@ -215,7 +164,8 @@ _test_paginated_surface_stroke (void *abstract_surface,
|
|||
return _cairo_surface_stroke (surface->target, op, source,
|
||||
path, style,
|
||||
ctm, ctm_inverse,
|
||||
tolerance, antialias, extents);
|
||||
tolerance, antialias,
|
||||
clip);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -226,7 +176,7 @@ _test_paginated_surface_fill (void *abstract_surface,
|
|||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
test_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
|
|
@ -235,7 +185,8 @@ _test_paginated_surface_fill (void *abstract_surface,
|
|||
|
||||
return _cairo_surface_fill (surface->target, op, source,
|
||||
path, fill_rule,
|
||||
tolerance, antialias, extents);
|
||||
tolerance, antialias,
|
||||
clip);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
|
|
@ -258,7 +209,7 @@ _test_paginated_surface_show_text_glyphs (void *abstract_surface,
|
|||
int num_clusters,
|
||||
cairo_text_cluster_flags_t cluster_flags,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
test_paginated_surface_t *surface = abstract_surface;
|
||||
|
||||
|
|
@ -268,8 +219,10 @@ _test_paginated_surface_show_text_glyphs (void *abstract_surface,
|
|||
return _cairo_surface_show_text_glyphs (surface->target, op, source,
|
||||
utf8, utf8_len,
|
||||
glyphs, num_glyphs,
|
||||
clusters, num_clusters, cluster_flags,
|
||||
scaled_font, extents);
|
||||
clusters, num_clusters,
|
||||
cluster_flags,
|
||||
scaled_font,
|
||||
clip);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -302,8 +255,6 @@ static const cairo_surface_backend_t test_paginated_surface_backend = {
|
|||
NULL, /* check_span_renderer */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
_test_paginated_surface_set_clip_region,
|
||||
NULL, /* intersect_clip_path */
|
||||
_test_paginated_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
|
|
@ -319,11 +270,10 @@ static const cairo_surface_backend_t test_paginated_surface_backend = {
|
|||
_test_paginated_surface_mask,
|
||||
_test_paginated_surface_stroke,
|
||||
_test_paginated_surface_fill,
|
||||
NULL, /* show_glyphs */
|
||||
NULL, /* replaced by show_text_glyphs */
|
||||
|
||||
NULL, /* snapshot */
|
||||
NULL, /* is_similar */
|
||||
NULL, /* reset */
|
||||
NULL, /* fill_stroke */
|
||||
NULL, /* create_solid_pattern_surface */
|
||||
NULL, /* can_repaint_solid_pattern_surface */
|
||||
|
|
|
|||
|
|
@ -41,11 +41,7 @@
|
|||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_test_paginated_surface_create_for_data (unsigned char *data,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height,
|
||||
int stride);
|
||||
_cairo_test_paginated_surface_create (cairo_surface_t *target);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
|
|
|
|||
272
src/test-wrapping-surface.c
Normal file
|
|
@ -0,0 +1,272 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2005 Red Hat, Inc
|
||||
* Copyright © Chris Wilson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
/* Another mythical surface that exists to simply wrap another - do nothing
|
||||
* itself but forward the calls onto a target surface.
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "test-wrapping-surface.h"
|
||||
|
||||
#include "cairo-surface-wrapper-private.h"
|
||||
|
||||
typedef struct _test_wrapping_surface {
|
||||
cairo_surface_t base;
|
||||
cairo_surface_wrapper_t wrapper;
|
||||
} test_wrapping_surface_t;
|
||||
|
||||
static const cairo_surface_backend_t test_wrapping_surface_backend;
|
||||
|
||||
slim_hidden_proto (_cairo_test_wrapping_surface_create);
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_test_wrapping_surface_create (cairo_surface_t *target)
|
||||
{
|
||||
test_wrapping_surface_t *surface;
|
||||
|
||||
if (unlikely (target->status))
|
||||
return _cairo_surface_create_in_error (target->status);
|
||||
|
||||
surface = malloc (sizeof (test_wrapping_surface_t));
|
||||
if (unlikely (surface == NULL))
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
||||
_cairo_surface_init (&surface->base,
|
||||
&test_wrapping_surface_backend,
|
||||
target->content);
|
||||
|
||||
_cairo_surface_wrapper_init (&surface->wrapper, target);
|
||||
|
||||
return &surface->base;
|
||||
}
|
||||
slim_hidden_def (_cairo_test_wrapping_surface_create);
|
||||
|
||||
static cairo_surface_t *
|
||||
_test_wrapping_surface_create_similar (void *abstract_surface,
|
||||
cairo_content_t content,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
|
||||
test_wrapping_surface_t *surface = abstract_surface;
|
||||
|
||||
return _cairo_test_wrapping_surface_create (
|
||||
_cairo_surface_wrapper_create_similar (&surface->wrapper,
|
||||
content, width, height));
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_test_wrapping_surface_finish (void *abstract_surface)
|
||||
{
|
||||
test_wrapping_surface_t *surface = abstract_surface;
|
||||
|
||||
_cairo_surface_wrapper_fini (&surface->wrapper);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_test_wrapping_surface_acquire_source_image (void *abstract_surface,
|
||||
cairo_image_surface_t **image_out,
|
||||
void **image_extra)
|
||||
{
|
||||
test_wrapping_surface_t *surface = abstract_surface;
|
||||
|
||||
return _cairo_surface_wrapper_acquire_source_image (&surface->wrapper,
|
||||
image_out, image_extra);
|
||||
}
|
||||
|
||||
static void
|
||||
_test_wrapping_surface_release_source_image (void *abstract_surface,
|
||||
cairo_image_surface_t *image,
|
||||
void *image_extra)
|
||||
{
|
||||
test_wrapping_surface_t *surface = abstract_surface;
|
||||
|
||||
_cairo_surface_wrapper_release_source_image (&surface->wrapper,
|
||||
image, image_extra);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_test_wrapping_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle)
|
||||
{
|
||||
test_wrapping_surface_t *surface = abstract_surface;
|
||||
|
||||
return _cairo_surface_wrapper_get_extents (&surface->wrapper, rectangle);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_test_wrapping_surface_paint (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
test_wrapping_surface_t *surface = abstract_surface;
|
||||
|
||||
return _cairo_surface_wrapper_paint (&surface->wrapper, op, source, clip);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_test_wrapping_surface_mask (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
test_wrapping_surface_t *surface = abstract_surface;
|
||||
|
||||
return _cairo_surface_wrapper_mask (&surface->wrapper,
|
||||
op, source, mask, clip);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_test_wrapping_surface_stroke (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_stroke_style_t *style,
|
||||
cairo_matrix_t *ctm,
|
||||
cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
test_wrapping_surface_t *surface = abstract_surface;
|
||||
|
||||
return _cairo_surface_wrapper_stroke (&surface->wrapper,
|
||||
op, source,
|
||||
path, style,
|
||||
ctm, ctm_inverse,
|
||||
tolerance, antialias,
|
||||
clip);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_test_wrapping_surface_fill (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
test_wrapping_surface_t *surface = abstract_surface;
|
||||
|
||||
return _cairo_surface_wrapper_fill (&surface->wrapper,
|
||||
op, source,
|
||||
path, fill_rule,
|
||||
tolerance, antialias,
|
||||
clip);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_test_wrapping_surface_has_show_text_glyphs (void *abstract_surface)
|
||||
{
|
||||
test_wrapping_surface_t *surface = abstract_surface;
|
||||
|
||||
return _cairo_surface_wrapper_has_show_text_glyphs (&surface->wrapper);
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_test_wrapping_surface_show_text_glyphs (void *abstract_surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const char *utf8,
|
||||
int utf8_len,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
const cairo_text_cluster_t *clusters,
|
||||
int num_clusters,
|
||||
cairo_text_cluster_flags_t cluster_flags,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_clip_t *clip)
|
||||
{
|
||||
test_wrapping_surface_t *surface = abstract_surface;
|
||||
|
||||
return _cairo_surface_wrapper_show_text_glyphs (&surface->wrapper,
|
||||
op, source,
|
||||
utf8, utf8_len,
|
||||
glyphs, num_glyphs,
|
||||
clusters, num_clusters,
|
||||
cluster_flags,
|
||||
scaled_font,
|
||||
clip);
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t test_wrapping_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_WRAPPING,
|
||||
_test_wrapping_surface_create_similar,
|
||||
_test_wrapping_surface_finish,
|
||||
_test_wrapping_surface_acquire_source_image,
|
||||
_test_wrapping_surface_release_source_image,
|
||||
NULL, NULL, /* dest_image */
|
||||
NULL, /* clone_similar */
|
||||
NULL, /* composite */
|
||||
NULL, /* fill_rectangles */
|
||||
NULL, /* composite_trapezoids */
|
||||
NULL, /* create_span_renderer */
|
||||
NULL, /* check_span_renderer */
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
_test_wrapping_surface_get_extents,
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
NULL, /* flush */
|
||||
NULL, /* mark_dirty_rectangle */
|
||||
NULL, /* scaled_font_fini */
|
||||
NULL, /* scaled_glyph_fini */
|
||||
|
||||
_test_wrapping_surface_paint,
|
||||
_test_wrapping_surface_mask,
|
||||
_test_wrapping_surface_stroke,
|
||||
_test_wrapping_surface_fill,
|
||||
NULL, /* replaced by show_text_glyphs */
|
||||
|
||||
NULL, /* snapshot */
|
||||
NULL, /* is_similar */
|
||||
NULL, /* fill_stroke */
|
||||
NULL, /* create_solid_pattern_surface */
|
||||
NULL, /* can_repaint_solid_pattern_surface */
|
||||
|
||||
_test_wrapping_surface_has_show_text_glyphs,
|
||||
_test_wrapping_surface_show_text_glyphs
|
||||
|
||||
/* XXX wrap fill-stroke and show_glyphs */
|
||||
};
|
||||
51
src/test-wrapping-surface.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2005 Red Hat, Inc
|
||||
* Copyright © 2009 Chris Wilson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#ifndef TEST_WRAPPING_SURFACE_H
|
||||
#define TEST_WRAPPING_SURFACE_H
|
||||
|
||||
#include "cairo.h"
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_test_wrapping_surface_create (cairo_surface_t *target);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif /* TEST_WRAPPING_SURFACE_H */
|
||||
|
||||
|
|
@ -185,8 +185,8 @@ REFERENCE_IMAGES = \
|
|||
clip-nesting.rgb24.ref.png \
|
||||
clip-nesting.test-paginated.rgb24.ref.png \
|
||||
clip-nesting.xlib.rgb24.ref.png \
|
||||
clip-operator.pdf.argb32.xfail.png \
|
||||
clip-operator.pdf.rgb24.xfail.png \
|
||||
clip-operator.pdf.argb32.ref.png \
|
||||
clip-operator.pdf.rgb24.ref.png \
|
||||
clip-operator.ps2.rgb24.ref.png \
|
||||
clip-operator.ps3.argb32.ref.png \
|
||||
clip-operator.ps3.ref.png \
|
||||
|
|
@ -198,15 +198,21 @@ REFERENCE_IMAGES = \
|
|||
clip-operator.svg12.argb32.xfail.png \
|
||||
clip-operator.svg12.rgb24.xfail.png \
|
||||
clip-operator.test-paginated.argb32.ref.png \
|
||||
clip-operator.xlib-fallback.rgb24.ref.png \
|
||||
clip-operator.xlib-fallback.ref.png \
|
||||
clip-operator.xlib.ref.png \
|
||||
clip-operator.xlib.rgb24.ref.png \
|
||||
clip-unbounded.ref.png \
|
||||
clip-unbounded.rgb24.ref.png \
|
||||
clip-unbounded.svg12.rgb24.xfail.png \
|
||||
clipped-surface.ref.png \
|
||||
clip-push-group.pdf.ref.png \
|
||||
clip-push-group.ps2.argb32.ref.png \
|
||||
clip-push-group.ps2.rgb24.ref.png \
|
||||
clip-push-group.ps3.argb32.ref.png \
|
||||
clip-push-group.ps3.rgb24.ref.png \
|
||||
clip-push-group.quartz.ref.png \
|
||||
clip-push-group.ref.png \
|
||||
clip-push-group.xlib.ref.png \
|
||||
clip-twice.pdf.argb32.ref.png \
|
||||
clip-twice.ps2.argb32.ref.png \
|
||||
clip-twice.ps2.rgb24.ref.png \
|
||||
|
|
@ -220,8 +226,7 @@ REFERENCE_IMAGES = \
|
|||
clip-twice.test-paginated.rgb24.ref.png \
|
||||
clip-twice.xlib.ref.png \
|
||||
clip-twice.xlib.rgb24.ref.png \
|
||||
clipped-group.pdf.argb32.ref.png \
|
||||
clipped-group.pdf.rgb24.ref.png \
|
||||
clipped-group.pdf.ref.png \
|
||||
clipped-group.ps2.ref.png \
|
||||
clipped-group.ps3.ref.png \
|
||||
clipped-group.ref.png \
|
||||
|
|
@ -240,6 +245,8 @@ REFERENCE_IMAGES = \
|
|||
composite-integer-translate-source.ps2.ref.png \
|
||||
composite-integer-translate-source.ps3.ref.png \
|
||||
composite-integer-translate-source.ref.png \
|
||||
composite-integer-translate-source.svg12.argb32.xfail.png \
|
||||
composite-integer-translate-source.svg12.rgb24.xfail.png \
|
||||
copy-path.ps2.ref.png \
|
||||
copy-path.ps3.ref.png \
|
||||
copy-path.ref.png \
|
||||
|
|
@ -299,7 +306,7 @@ REFERENCE_IMAGES = \
|
|||
device-offset-fractional.gl.xfail.png \
|
||||
device-offset-fractional.pdf.argb32.ref.png \
|
||||
device-offset-fractional.pdf.ref.png \
|
||||
device-offset-fractional.pdf.rgb24.ref.png \
|
||||
device-offset-fractional.pdf.xfail.png \
|
||||
device-offset-fractional.ps2.ref.png \
|
||||
device-offset-fractional.ps3.ref.png \
|
||||
device-offset-fractional.ref.png \
|
||||
|
|
@ -311,8 +318,12 @@ REFERENCE_IMAGES = \
|
|||
device-offset.rgb24.ref.png \
|
||||
extended-blend.argb32.ref.png \
|
||||
extended-blend.rgb24.ref.png \
|
||||
extended-blend.svg12.argb32.xfail.png \
|
||||
extended-blend.svg12.rgb24.xfail.png \
|
||||
extended-blend-alpha.argb32.ref.png \
|
||||
extended-blend-alpha.rgb24.ref.png \
|
||||
extended-blend-alpha.svg12.argb32.xfail.png \
|
||||
extended-blend-alpha.svg12.rgb24.xfail.png \
|
||||
extend-pad-border.ps.ref.png \
|
||||
extend-pad-border.ref.png \
|
||||
extend-pad-border.svg.xfail.png \
|
||||
|
|
@ -377,6 +388,9 @@ REFERENCE_IMAGES = \
|
|||
fill-degenerate-sort-order.rgb24.ref.png \
|
||||
fill-degenerate-sort-order.xlib.ref.png \
|
||||
fill-degenerate-sort-order.xlib.rgb24.ref.png \
|
||||
fill-empty.argb32.ref.png \
|
||||
fill-empty.rgb24.ref.png \
|
||||
fill-empty.svg12.rgb24.xfail.png \
|
||||
fill-image.ps.ref.png \
|
||||
fill-image.ref.png \
|
||||
fill-image.xlib.ref.png \
|
||||
|
|
@ -443,17 +457,13 @@ REFERENCE_IMAGES = \
|
|||
ft-text-antialias-none.ps2.argb32.ref.png \
|
||||
ft-text-antialias-none.ps3.argb32.ref.png \
|
||||
ft-text-antialias-none.ref.png \
|
||||
ft-text-vertical-layout-type1.pdf.argb32.ref.png \
|
||||
ft-text-vertical-layout-type1.pdf.ref.png \
|
||||
ft-text-vertical-layout-type1.pdf.rgb24.ref.png \
|
||||
ft-text-vertical-layout-type1.ps2.ref.png \
|
||||
ft-text-vertical-layout-type1.ps3.ref.png \
|
||||
ft-text-vertical-layout-type1.ref.png \
|
||||
ft-text-vertical-layout-type1.svg.ref.png \
|
||||
ft-text-vertical-layout-type1.xlib.ref.png \
|
||||
ft-text-vertical-layout-type3.pdf.argb32.ref.png \
|
||||
ft-text-vertical-layout-type3.pdf.ref.png \
|
||||
ft-text-vertical-layout-type3.pdf.rgb24.ref.png \
|
||||
ft-text-vertical-layout-type3.ps2.ref.png \
|
||||
ft-text-vertical-layout-type3.ps3.ref.png \
|
||||
ft-text-vertical-layout-type3.ref.png \
|
||||
|
|
@ -498,6 +508,8 @@ REFERENCE_IMAGES = \
|
|||
image-surface-source.ps2.ref.png \
|
||||
image-surface-source.ps3.ref.png \
|
||||
image-surface-source.ref.png \
|
||||
image-surface-source.svg12.argb32.xfail.png \
|
||||
image-surface-source.svg12.rgb24.xfail.png \
|
||||
infinite-join.ps2.ref.png \
|
||||
infinite-join.ps3.ref.png \
|
||||
infinite-join.ref.png \
|
||||
|
|
@ -558,15 +570,14 @@ REFERENCE_IMAGES = \
|
|||
mask-transformed-similar.pdf.ref.png \
|
||||
mask-transformed-similar.ref.png \
|
||||
mask-transformed-similar.svg.ref.png \
|
||||
mask.pdf.argb32.xfail.png \
|
||||
mask.pdf.rgb24.xfail.png \
|
||||
mask.pdf.argb32.ref.png \
|
||||
mask.pdf.rgb24.ref.png \
|
||||
mask.quartz.ref.png \
|
||||
mask.quartz.rgb24.ref.png \
|
||||
mask.ref.png \
|
||||
mask.rgb24.ref.png \
|
||||
mask.svg.argb32.xfail.png \
|
||||
mask.svg.rgb24.xfail.png \
|
||||
mask.xlib-fallback.rgb24.ref.png \
|
||||
mask.xlib.ref.png \
|
||||
mask.xlib.rgb24.ref.png \
|
||||
meta-surface-pattern.gl.argb32.ref.png \
|
||||
|
|
@ -613,15 +624,16 @@ REFERENCE_IMAGES = \
|
|||
operator-clear.rgb24.ref.png \
|
||||
operator-clear.svg12.argb32.xfail.png \
|
||||
operator-clear.svg12.rgb24.xfail.png \
|
||||
operator-clear.xlib.ref.png \
|
||||
operator-source.pdf.rgb24.xfail.png \
|
||||
operator-clear.xlib.argb32.ref.png \
|
||||
operator-clear.xlib.rgb24.ref.png \
|
||||
operator-source.pdf.rgb24.ref.png \
|
||||
operator-source.quartz.ref.png \
|
||||
operator-source.quartz.rgb24.ref.png \
|
||||
operator-source.ref.png \
|
||||
operator-source.rgb24.ref.png \
|
||||
operator-source.svg12.argb32.xfail.png \
|
||||
operator-source.svg12.rgb24.xfail.png \
|
||||
operator-source.xlib-fallback.rgb24.ref.png \
|
||||
operator-source.xlib-fallback.ref.png \
|
||||
operator-source.xlib.ref.png \
|
||||
operator-source.xlib.rgb24.ref.png \
|
||||
operator.ref.png \
|
||||
|
|
@ -682,12 +694,15 @@ REFERENCE_IMAGES = \
|
|||
path-append.xlib.ref.png \
|
||||
pattern-getters.ref.png \
|
||||
pdf-surface-source.ref.png \
|
||||
pdf-surface-source.svg12.argb32.xfail.png \
|
||||
pdf-surface-source.svg12.rgb24.xfail.png \
|
||||
pixman-rotate.ref.png \
|
||||
pixman-rotate.rgb24.ref.png \
|
||||
ps-surface-source.ref.png \
|
||||
ps-surface-source.svg12.argb32.xfail.png \
|
||||
ps-surface-source.svg12.rgb24.xfail.png \
|
||||
push-group.ref.png \
|
||||
push-group.rgb24.ref.png \
|
||||
push-group.xlib-fallback.rgb24.ref.png \
|
||||
push-group.xlib.ref.png \
|
||||
push-group.xlib.rgb24.ref.png \
|
||||
quartz-surface-source.ps2.ref.png \
|
||||
|
|
@ -727,19 +742,21 @@ REFERENCE_IMAGES = \
|
|||
rotate-image-surface-paint.svg.ref.png \
|
||||
scale-down-source-surface-paint.ref.png \
|
||||
scale-offset-image.gl.ref.png \
|
||||
scale-offset-image.pdf.argb32.ref.png \
|
||||
scale-offset-image.pdf.rgb24.ref.png \
|
||||
scale-offset-image.pdf.xfail.png \
|
||||
scale-offset-image.ps.ref.png \
|
||||
scale-offset-image.ref.png \
|
||||
scale-offset-image.xfail.png \
|
||||
scale-offset-image.meta.xfail.png \
|
||||
scale-offset-image.xlib.xfail.png \
|
||||
scale-offset-image.xlib-fallback.xfail.png \
|
||||
scale-offset-similar.gl.ref.png \
|
||||
scale-offset-similar.pdf.argb32.ref.png \
|
||||
scale-offset-similar.pdf.rgb24.ref.png \
|
||||
scale-offset-similar.pdf.xfail.png \
|
||||
scale-offset-similar.ps.ref.png \
|
||||
scale-offset-similar.ref.png \
|
||||
scale-offset-similar.xfail.png \
|
||||
scale-offset-similar.meta.xfail.png \
|
||||
scale-offset-similar.xlib.xfail.png \
|
||||
scale-offset-similar.xlib-fallback.xfail.png \
|
||||
scale-source-surface-paint.ref.png \
|
||||
scale-source-surface-paint.rgb24.ref.png \
|
||||
scale-source-surface-paint.svg.argb32.xfail.png \
|
||||
|
|
@ -773,7 +790,6 @@ REFERENCE_IMAGES = \
|
|||
skew-extreme.ref.png \
|
||||
smask-fill.ref.png \
|
||||
smask-fill.svg.ref.png \
|
||||
smask-fill.xlib-fallback.ref.png \
|
||||
smask-fill.xlib.ref.png \
|
||||
smask-image-mask.ref.png \
|
||||
smask-mask.pdf.xfail.png \
|
||||
|
|
@ -789,11 +805,13 @@ REFERENCE_IMAGES = \
|
|||
smask-text.ps3.ref.png \
|
||||
smask-text.ref.png \
|
||||
smask-text.svg.ref.png \
|
||||
smask-text.xlib.ref.png \
|
||||
smask.pdf.xfail.png \
|
||||
smask.ps2.ref.png \
|
||||
smask.ps3.ref.png \
|
||||
smask.ref.png \
|
||||
smask.svg.ref.png \
|
||||
smask.xlib.ref.png \
|
||||
solid-pattern-cache-stress.ref.png \
|
||||
source-clip-scale.gl.ref.png \
|
||||
source-clip-scale.pdf.ref.png \
|
||||
|
|
@ -821,6 +839,7 @@ REFERENCE_IMAGES = \
|
|||
stroke-image.quartz.ref.png \
|
||||
stroke-image.ref.png \
|
||||
surface-pattern-big-scale-down.ref.png \
|
||||
surface-pattern-big-scale-down.ps.xfail.png \
|
||||
surface-pattern-scale-down.pdf.ref.png \
|
||||
surface-pattern-scale-down.ps2.ref.png \
|
||||
surface-pattern-scale-down.ps3.ref.png \
|
||||
|
|
@ -835,8 +854,12 @@ REFERENCE_IMAGES = \
|
|||
surface-pattern.ref.png \
|
||||
surface-pattern.svg.xfail.png \
|
||||
svg-surface-source.ref.png \
|
||||
svg-surface-source.svg12.argb32.xfail.png \
|
||||
svg-surface-source.svg12.rgb24.xfail.png \
|
||||
test-fallback16-surface-source.ps.ref.png \
|
||||
test-fallback16-surface-source.ref.png \
|
||||
test-fallback16-surface-source.svg12.argb32.xfail.png \
|
||||
test-fallback16-surface-source.svg12.rgb24.xfail.png \
|
||||
text-antialias-gray.quartz.ref.png \
|
||||
text-antialias-gray.ref.png \
|
||||
text-antialias-none.quartz.ref.png \
|
||||
|
|
@ -846,8 +869,8 @@ REFERENCE_IMAGES = \
|
|||
text-glyph-range.ps2.ref.png \
|
||||
text-glyph-range.ps3.ref.png \
|
||||
text-glyph-range.ref.png \
|
||||
text-pattern.pdf.argb32.xfail.png \
|
||||
text-pattern.pdf.rgb24.xfail.png \
|
||||
text-pattern.pdf.argb32.ref.png \
|
||||
text-pattern.pdf.rgb24.ref.png \
|
||||
text-pattern.ps3.argb32.ref.png \
|
||||
text-pattern.ps3.rgb24.ref.png \
|
||||
text-pattern.quartz.ref.png \
|
||||
|
|
@ -924,6 +947,8 @@ REFERENCE_IMAGES = \
|
|||
xlib-surface-source.ps2.ref.png \
|
||||
xlib-surface-source.ps3.ref.png \
|
||||
xlib-surface-source.ref.png \
|
||||
xlib-surface-source.svg12.argb32.xfail.png \
|
||||
xlib-surface-source.svg12.rgb24.xfail.png \
|
||||
zero-alpha.ref.png
|
||||
|
||||
EXTRA_DIST += \
|
||||
|
|
@ -1218,7 +1243,7 @@ run:
|
|||
|
||||
# Check tests under valgrind. Saves log to valgrind-log
|
||||
check-valgrind:
|
||||
$(MAKE) $(AM_MAKEFLAGS) check TESTS_ENVIRONMENT='$(TESTS_ENVIRONMENT) CAIRO_TEST_MODE="$(MODE),foreground" $(top_builddir)/libtool --mode=execute valgrind $(VALGRIND_FLAGS)' 2>&1 | tee valgrind-log
|
||||
$(MAKE) $(AM_MAKEFLAGS) check TESTS_ENVIRONMENT='$(TESTS_ENVIRONMENT) CAIRO_TEST_MODE="$(MODE),foreground CAIRO_TEST_TIMEOUT=0" $(top_builddir)/libtool --mode=execute valgrind $(VALGRIND_FLAGS)' 2>&1 | tee valgrind-log
|
||||
|
||||
%.log: %.c cairo-test-suite
|
||||
-./cairo-test-suite $(<:.c=)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ test_sources = \
|
|||
clip-operator.c \
|
||||
clip-push-group.c \
|
||||
clip-twice.c \
|
||||
clip-unbounded.c \
|
||||
clip-zero.c \
|
||||
clipped-group.c \
|
||||
clipped-surface.c \
|
||||
|
|
@ -64,6 +65,7 @@ test_sources = \
|
|||
fill-and-stroke-alpha.c \
|
||||
fill-and-stroke-alpha-add.c \
|
||||
fill-degenerate-sort-order.c \
|
||||
fill-empty.c \
|
||||
fill-image.c \
|
||||
fill-missed-stop.c \
|
||||
fill-rule.c \
|
||||
|
|
|
|||
|
|
@ -70,13 +70,12 @@ buffer_diff_core (const unsigned char *_buf_a, int stride_a,
|
|||
stride_a /= sizeof (uint32_t);
|
||||
stride_b /= sizeof (uint32_t);
|
||||
stride_diff /= sizeof (uint32_t);
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
for (y = 0; y < height; y++) {
|
||||
const uint32_t *row_a = buf_a + y * stride_a;
|
||||
const uint32_t *row_b = buf_b + y * stride_b;
|
||||
uint32_t *row = buf_diff + y * stride_diff;
|
||||
for (x = 0; x < width; x++)
|
||||
{
|
||||
|
||||
for (x = 0; x < width; x++) {
|
||||
/* check if the pixels are the same */
|
||||
if ((row_a[x] & mask) != (row_b[x] & mask)) {
|
||||
int channel;
|
||||
|
|
@ -99,6 +98,11 @@ buffer_diff_core (const unsigned char *_buf_a, int stride_a,
|
|||
}
|
||||
|
||||
result.pixels_changed++;
|
||||
if ((diff_pixel & 0x00ffffff) == 0) {
|
||||
/* alpha only difference, convert to luminance */
|
||||
uint8_t alpha = diff_pixel >> 24;
|
||||
diff_pixel = alpha * 0x010101;
|
||||
}
|
||||
row[x] = diff_pixel;
|
||||
} else {
|
||||
row[x] = 0;
|
||||
|
|
|
|||
|
|
@ -566,7 +566,7 @@ cairo_test_file_is_older (const char *filename,
|
|||
|
||||
while (num_ref_filenames--) {
|
||||
struct stat ref;
|
||||
char *ref_filename = ref_filenames++;
|
||||
char *ref_filename = *ref_filenames++;
|
||||
|
||||
if (ref_filename == NULL)
|
||||
continue;
|
||||
|
|
@ -912,6 +912,11 @@ REPEAT:
|
|||
goto UNWIND_SURFACE;
|
||||
}
|
||||
|
||||
cairo_surface_set_user_data (surface,
|
||||
&cairo_boilerplate_output_basename_key,
|
||||
base_path,
|
||||
NULL);
|
||||
|
||||
cairo_surface_set_device_offset (surface, dev_offset, dev_offset);
|
||||
|
||||
cr = cairo_create (surface);
|
||||
|
|
@ -1080,13 +1085,17 @@ REPEAT:
|
|||
ctx->test->width,
|
||||
ctx->test->height);
|
||||
diff_status = cairo_surface_write_to_png (test_image, out_png_path);
|
||||
cairo_surface_destroy (test_image);
|
||||
if (diff_status) {
|
||||
if (cairo_surface_status (test_image) == CAIRO_STATUS_INVALID_STATUS)
|
||||
ret = CAIRO_TEST_CRASHED;
|
||||
else
|
||||
ret = CAIRO_TEST_FAILURE;
|
||||
cairo_test_log (ctx,
|
||||
"Error: Failed to write output image: %s\n",
|
||||
cairo_status_to_string (diff_status));
|
||||
}
|
||||
have_output = TRUE;
|
||||
cairo_surface_destroy (test_image);
|
||||
|
||||
ret = CAIRO_TEST_XFAILURE;
|
||||
goto UNWIND_CAIRO;
|
||||
|
|
@ -1167,8 +1176,11 @@ REPEAT:
|
|||
if (cairo_surface_status (test_image)) {
|
||||
cairo_test_log (ctx, "Error: Failed to extract image: %s\n",
|
||||
cairo_status_to_string (cairo_surface_status (test_image)));
|
||||
if (cairo_surface_status (test_image) == CAIRO_STATUS_INVALID_STATUS)
|
||||
ret = CAIRO_TEST_CRASHED;
|
||||
else
|
||||
ret = CAIRO_TEST_FAILURE;
|
||||
cairo_surface_destroy (test_image);
|
||||
ret = CAIRO_TEST_FAILURE;
|
||||
goto UNWIND_CAIRO;
|
||||
}
|
||||
|
||||
|
|
|
|||
BIN
test/clip-operator.pdf.argb32.ref.png
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 9.1 KiB |
BIN
test/clip-operator.pdf.rgb24.ref.png
Normal file
|
After Width: | Height: | Size: 5 KiB |
|
Before Width: | Height: | Size: 5 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
BIN
test/clip-operator.xlib-fallback.ref.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
BIN
test/clip-push-group.pdf.ref.png
Normal file
|
After Width: | Height: | Size: 164 B |
|
Before Width: | Height: | Size: 199 B After Width: | Height: | Size: 164 B |