mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2025-12-20 07:00:08 +01:00
Introduce a new compositor architecture
Having spent the last dev cycle looking at how we could specialize the compositors for various backends, we once again look for the commonalities in order to reduce the duplication. In part this is motivated by the idea that spans is a good interface for both the existent GL backend and pixman, and so they deserve a dedicated compositor. xcb/xlib target an identical rendering system and so they should be using the same compositor, and it should be possible to run that same compositor locally against pixman to generate reference tests. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> P.S. This brings massive upheaval (read breakage) I've tried delaying in order to fix as many things as possible but now this one patch does far, far, far too much. Apologies in advance for breaking your favourite backend, but trust me in that the end result will be much better. :)
This commit is contained in:
parent
0540bf384a
commit
af9fbd176b
225 changed files with 27561 additions and 17971 deletions
|
|
@ -30,20 +30,14 @@
|
|||
|
||||
#include <cairo-types-private.h>
|
||||
|
||||
#include <test-fallback-surface.h>
|
||||
#include <test-fallback16-surface.h>
|
||||
#include <test-compositor-surface.h>
|
||||
#include <test-null-compositor-surface.h>
|
||||
#if CAIRO_HAS_TEST_PAGINATED_SURFACE
|
||||
#include <test-paginated-surface.h>
|
||||
#endif
|
||||
#if CAIRO_HAS_TEST_NULL_SURFACE
|
||||
#include <test-null-surface.h>
|
||||
#endif
|
||||
#if CAIRO_HAS_TEST_WRAPPING_SURFACE
|
||||
#include <test-wrapping-surface.h>
|
||||
#endif
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_boilerplate_test_fallback_create_surface (const char *name,
|
||||
_cairo_boilerplate_test_base_compositor_create_surface (const char *name,
|
||||
cairo_content_t content,
|
||||
double width,
|
||||
double height,
|
||||
|
|
@ -54,12 +48,12 @@ _cairo_boilerplate_test_fallback_create_surface (const char *name,
|
|||
void **closure)
|
||||
{
|
||||
*closure = NULL;
|
||||
return _cairo_test_fallback_surface_create (content,
|
||||
ceil (width), ceil (height));
|
||||
return _cairo_test_base_compositor_surface_create (content, ceil (width), ceil (height));
|
||||
}
|
||||
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_boilerplate_test_fallback16_create_surface (const char *name,
|
||||
_cairo_boilerplate_test_fallback_compositor_create_surface (const char *name,
|
||||
cairo_content_t content,
|
||||
double width,
|
||||
double height,
|
||||
|
|
@ -70,13 +64,11 @@ _cairo_boilerplate_test_fallback16_create_surface (const char *name,
|
|||
void **closure)
|
||||
{
|
||||
*closure = NULL;
|
||||
return _cairo_test_fallback16_surface_create (content,
|
||||
ceil (width), ceil (height));
|
||||
return _cairo_test_fallback_compositor_surface_create (content, ceil (width), ceil (height));
|
||||
}
|
||||
|
||||
#if CAIRO_HAS_TEST_NULL_SURFACE
|
||||
static cairo_surface_t *
|
||||
_cairo_boilerplate_test_null_create_surface (const char *name,
|
||||
_cairo_boilerplate_test_mask_compositor_create_surface (const char *name,
|
||||
cairo_content_t content,
|
||||
double width,
|
||||
double height,
|
||||
|
|
@ -87,9 +79,84 @@ _cairo_boilerplate_test_null_create_surface (const char *name,
|
|||
void **closure)
|
||||
{
|
||||
*closure = NULL;
|
||||
return _cairo_test_null_surface_create (content);
|
||||
return _cairo_test_mask_compositor_surface_create (content, ceil (width), ceil (height));
|
||||
}
|
||||
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_boilerplate_test_traps_compositor_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)
|
||||
{
|
||||
*closure = NULL;
|
||||
return _cairo_test_traps_compositor_surface_create (content, ceil (width), ceil (height));
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_boilerplate_test_spans_compositor_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)
|
||||
{
|
||||
*closure = NULL;
|
||||
return _cairo_test_spans_compositor_surface_create (content, ceil (width), ceil (height));
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_boilerplate_test_no_fallback_compositor_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)
|
||||
{
|
||||
*closure = NULL;
|
||||
return _cairo_test_no_fallback_compositor_surface_create (content, ceil (width), ceil (height));
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_boilerplate_test_no_traps_compositor_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)
|
||||
{
|
||||
*closure = NULL;
|
||||
return _cairo_test_no_traps_compositor_surface_create (content, ceil (width), ceil (height));
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_cairo_boilerplate_test_no_spans_compositor_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)
|
||||
{
|
||||
*closure = NULL;
|
||||
return _cairo_test_no_spans_compositor_surface_create (content, ceil (width), ceil (height));
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CAIRO_HAS_TEST_PAGINATED_SURFACE
|
||||
static const cairo_user_data_key_t test_paginated_closure_key;
|
||||
|
|
@ -201,40 +268,38 @@ _cairo_boilerplate_test_paginated_cleanup (void *closure)
|
|||
}
|
||||
#endif
|
||||
|
||||
#if CAIRO_HAS_TEST_WRAPPING_SURFACE
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const cairo_boilerplate_target_t targets[] = {
|
||||
{
|
||||
"test-fallback", "image", NULL, NULL,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
|
||||
"test-base", "image", NULL, NULL,
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR_ALPHA, 0,
|
||||
"_cairo_test_fallback_surface_create",
|
||||
_cairo_boilerplate_test_fallback_create_surface,
|
||||
"_cairo_test_base_compositor_surface_create",
|
||||
_cairo_boilerplate_test_base_compositor_create_surface,
|
||||
cairo_surface_create_similar,
|
||||
NULL, NULL,
|
||||
_cairo_boilerplate_get_image_surface,
|
||||
cairo_surface_write_to_png,
|
||||
NULL, NULL, NULL, TRUE, FALSE, FALSE
|
||||
},
|
||||
{
|
||||
"test-base", "image", NULL, NULL,
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR, 0,
|
||||
"_cairo_test_base_compositor_surface_create",
|
||||
_cairo_boilerplate_test_base_compositor_create_surface,
|
||||
cairo_surface_create_similar,
|
||||
NULL, NULL,
|
||||
_cairo_boilerplate_get_image_surface,
|
||||
cairo_surface_write_to_png,
|
||||
NULL, NULL, NULL, FALSE, FALSE, FALSE
|
||||
},
|
||||
|
||||
{
|
||||
"test-fallback", "image", NULL, NULL,
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR_ALPHA, 0,
|
||||
"_cairo_test_fallback_compositor_surface_create",
|
||||
_cairo_boilerplate_test_fallback_compositor_create_surface,
|
||||
cairo_surface_create_similar,
|
||||
NULL, NULL,
|
||||
_cairo_boilerplate_get_image_surface,
|
||||
|
|
@ -243,10 +308,98 @@ static const cairo_boilerplate_target_t targets[] = {
|
|||
},
|
||||
{
|
||||
"test-fallback", "image", NULL, NULL,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR, 0,
|
||||
"_cairo_test_fallback_surface_create",
|
||||
_cairo_boilerplate_test_fallback_create_surface,
|
||||
"_cairo_test_fallback_compositor_surface_create",
|
||||
_cairo_boilerplate_test_fallback_compositor_create_surface,
|
||||
cairo_surface_create_similar,
|
||||
NULL, NULL,
|
||||
_cairo_boilerplate_get_image_surface,
|
||||
cairo_surface_write_to_png,
|
||||
NULL, NULL, NULL, FALSE, FALSE, FALSE
|
||||
},
|
||||
|
||||
{
|
||||
"test-mask", "mask", NULL, NULL,
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR_ALPHA, 0,
|
||||
"_cairo_test_traps_compositor_surface_create",
|
||||
_cairo_boilerplate_test_mask_compositor_create_surface,
|
||||
cairo_surface_create_similar,
|
||||
NULL, NULL,
|
||||
_cairo_boilerplate_get_image_surface,
|
||||
cairo_surface_write_to_png,
|
||||
NULL, NULL, NULL, TRUE, FALSE, FALSE
|
||||
},
|
||||
{
|
||||
"test-mask", "mask", NULL, NULL,
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR, 0,
|
||||
"_cairo_test_mask_compositor_surface_create",
|
||||
_cairo_boilerplate_test_mask_compositor_create_surface,
|
||||
cairo_surface_create_similar,
|
||||
NULL, NULL,
|
||||
_cairo_boilerplate_get_image_surface,
|
||||
cairo_surface_write_to_png,
|
||||
NULL, NULL, NULL, FALSE, FALSE, FALSE
|
||||
},
|
||||
|
||||
{
|
||||
"test-traps", "traps", NULL, NULL,
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR_ALPHA, 0,
|
||||
"_cairo_test_traps_compositor_surface_create",
|
||||
_cairo_boilerplate_test_traps_compositor_create_surface,
|
||||
cairo_surface_create_similar,
|
||||
NULL, NULL,
|
||||
_cairo_boilerplate_get_image_surface,
|
||||
cairo_surface_write_to_png,
|
||||
NULL, NULL, NULL, TRUE, FALSE, FALSE
|
||||
},
|
||||
{
|
||||
"test-traps", "traps", NULL, NULL,
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR, 0,
|
||||
"_cairo_test_traps_compositor_surface_create",
|
||||
_cairo_boilerplate_test_traps_compositor_create_surface,
|
||||
cairo_surface_create_similar,
|
||||
NULL, NULL,
|
||||
_cairo_boilerplate_get_image_surface,
|
||||
cairo_surface_write_to_png,
|
||||
NULL, NULL, NULL, FALSE, FALSE, FALSE
|
||||
},
|
||||
|
||||
{
|
||||
"test-spans", "spans", NULL, NULL,
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR_ALPHA, 0,
|
||||
"_cairo_test_spans_compositor_surface_create",
|
||||
_cairo_boilerplate_test_spans_compositor_create_surface,
|
||||
cairo_surface_create_similar,
|
||||
NULL, NULL,
|
||||
_cairo_boilerplate_get_image_surface,
|
||||
cairo_surface_write_to_png,
|
||||
NULL, NULL, NULL, TRUE, FALSE, FALSE
|
||||
},
|
||||
{
|
||||
"test-spans", "spans", NULL, NULL,
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR, 0,
|
||||
"_cairo_test_spans_compositor_surface_create",
|
||||
_cairo_boilerplate_test_spans_compositor_create_surface,
|
||||
cairo_surface_create_similar,
|
||||
NULL, NULL,
|
||||
_cairo_boilerplate_get_image_surface,
|
||||
cairo_surface_write_to_png,
|
||||
NULL, NULL, NULL, FALSE, FALSE, FALSE
|
||||
},
|
||||
|
||||
{
|
||||
"no-fallback", "image", NULL, NULL,
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR_ALPHA, 0,
|
||||
"_cairo_test_no_fallback_compositor_surface_create",
|
||||
_cairo_boilerplate_test_no_fallback_compositor_create_surface,
|
||||
cairo_surface_create_similar,
|
||||
NULL, NULL,
|
||||
_cairo_boilerplate_get_image_surface,
|
||||
|
|
@ -254,28 +407,28 @@ static const cairo_boilerplate_target_t targets[] = {
|
|||
NULL, NULL, NULL, FALSE, FALSE, FALSE
|
||||
},
|
||||
{
|
||||
"test-fallback16", "image", NULL, NULL,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
|
||||
"no-traps", "traps", NULL, NULL,
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR_ALPHA, 0,
|
||||
"_cairo_test_fallback16_surface_create",
|
||||
_cairo_boilerplate_test_fallback16_create_surface,
|
||||
"_cairo_test_no_traps_compositor_surface_create",
|
||||
_cairo_boilerplate_test_no_traps_compositor_create_surface,
|
||||
cairo_surface_create_similar,
|
||||
NULL, NULL,
|
||||
NULL, /* _cairo_boilerplate_get_image_surface, */
|
||||
_cairo_boilerplate_get_image_surface,
|
||||
cairo_surface_write_to_png,
|
||||
NULL, NULL, NULL, FALSE, FALSE, FALSE
|
||||
NULL, NULL, NULL, TRUE, FALSE, FALSE
|
||||
},
|
||||
{
|
||||
"test-fallback16", "image", NULL, NULL,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
|
||||
CAIRO_CONTENT_COLOR, 0,
|
||||
"_cairo_test_fallback16_surface_create",
|
||||
_cairo_boilerplate_test_fallback16_create_surface,
|
||||
"no-spans", "spans", NULL, NULL,
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
CAIRO_CONTENT_COLOR_ALPHA, 0,
|
||||
"_cairo_test_no_spans_compositor_surface_create",
|
||||
_cairo_boilerplate_test_no_spans_compositor_create_surface,
|
||||
cairo_surface_create_similar,
|
||||
NULL, NULL,
|
||||
NULL, /* _cairo_boilerplate_get_image_surface, */
|
||||
_cairo_boilerplate_get_image_surface,
|
||||
cairo_surface_write_to_png,
|
||||
NULL, NULL, NULL, FALSE, FALSE, FALSE
|
||||
NULL, NULL, NULL, TRUE, FALSE, FALSE
|
||||
},
|
||||
#if CAIRO_HAS_TEST_PAGINATED_SURFACE
|
||||
{
|
||||
|
|
@ -305,33 +458,5 @@ static const cairo_boilerplate_target_t targets[] = {
|
|||
NULL, NULL, FALSE, TRUE, FALSE
|
||||
},
|
||||
#endif
|
||||
#if CAIRO_HAS_TEST_WRAPPING_SURFACE
|
||||
{
|
||||
"test-wrapping", "image", NULL, NULL,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_TEST_WRAPPING,
|
||||
CAIRO_CONTENT_COLOR_ALPHA, 0,
|
||||
"_cairo_test_wrapping_surface_create",
|
||||
_cairo_boilerplate_test_wrapping_create_surface,
|
||||
cairo_surface_create_similar,
|
||||
NULL, NULL,
|
||||
_cairo_boilerplate_get_image_surface,
|
||||
cairo_surface_write_to_png,
|
||||
NULL, NULL, NULL, FALSE, FALSE, FALSE
|
||||
},
|
||||
#endif
|
||||
#if CAIRO_HAS_TEST_NULL_SURFACE
|
||||
{
|
||||
"null", "image", NULL, NULL,
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_NULL,
|
||||
CAIRO_CONTENT_COLOR_ALPHA, 0,
|
||||
"_cairo_test_null_surface_create",
|
||||
_cairo_boilerplate_test_null_create_surface,
|
||||
cairo_surface_create_similar,
|
||||
NULL, NULL,
|
||||
NULL, NULL, NULL,
|
||||
NULL, NULL,
|
||||
TRUE, TRUE, FALSE
|
||||
},
|
||||
#endif
|
||||
};
|
||||
CAIRO_BOILERPLATE (test, targets)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@
|
|||
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
|
||||
#include <cairo-xlib-xrender.h>
|
||||
#endif
|
||||
#include <cairo-xlib-surface-private.h>
|
||||
|
||||
#include <X11/Xutil.h> /* for XDestroyImage */
|
||||
|
||||
|
|
@ -412,6 +411,7 @@ _cairo_boilerplate_xlib_window_create_surface (const char *name,
|
|||
cairo_status_t
|
||||
cairo_boilerplate_xlib_surface_disable_render (cairo_surface_t *abstract_surface)
|
||||
{
|
||||
#if 0
|
||||
/* The following stunt doesn't work with xlib-xcb because it doesn't use
|
||||
* cairo_xlib_surface_t for its surfaces. Sadly, there is no sane
|
||||
* alternative, so we can't disable render with xlib-xcb.
|
||||
|
|
@ -439,6 +439,7 @@ cairo_boilerplate_xlib_surface_disable_render (cairo_surface_t *abstract_surface
|
|||
#if CAIRO_XLIB_SURFACE_HAS_BUGGY_REPEAT
|
||||
surface->buggy_repeat = TRUE;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
|
|
|||
|
|
@ -683,16 +683,12 @@ cairo_boilerplate_get_image_target (cairo_content_t content)
|
|||
if (cairo_boilerplate_targets == NULL)
|
||||
_cairo_boilerplate_register_all ();
|
||||
|
||||
for (list = cairo_boilerplate_targets; list != NULL; list = list->next) {
|
||||
const cairo_boilerplate_target_t *target = list->target;
|
||||
if (target->expected_type == CAIRO_SURFACE_TYPE_IMAGE &&
|
||||
target->content == content)
|
||||
{
|
||||
return target;
|
||||
switch (content) {
|
||||
default:
|
||||
case CAIRO_CONTENT_ALPHA: return NULL;
|
||||
case CAIRO_CONTENT_COLOR: return &builtin_targets[1];
|
||||
case CAIRO_CONTENT_COLOR_ALPHA: return &builtin_targets[0];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const cairo_boilerplate_target_t *
|
||||
|
|
|
|||
|
|
@ -202,11 +202,11 @@ CAIRO_ENABLE_SURFACE_BACKEND(skia, Skia, no, [
|
|||
[skia_DIR="`pwd`/../skia"])
|
||||
AC_ARG_WITH([skia-bulid],
|
||||
[AS_HELP_STRING([--with-skia-build=(Release|Debug)]
|
||||
[build of skia to link with, default is Relese])],
|
||||
[build of skia to link with, default is Release])],
|
||||
[skia_BUILD="$withval"],
|
||||
[skia_BUILD="Release"])
|
||||
skia_NONPKGCONFIG_CFLAGS="-I$skia_DIR/include/config -I$skia_DIR/include/core -I$skia_DIR/include/effects"
|
||||
if test "x$(skia_BUILD)" = x"Relese"; then
|
||||
if test "x$skia_BUILD" = x"Release"; then
|
||||
skia_NONPKGCONFIG_CFLAGS="-DSK_RELEASE -DSK_CAN_USE_FLOAT $skia_NONPKGCONFIG_CFLAGS"
|
||||
fi
|
||||
skia_NONPKGCONFIG_LIBS="--start-group $skia_DIR/out/$skia_BUILD/obj.target/gyp/libeffects.a $skia_DIR/out/$skia_BUILD/obj.target/gyp/libimages.a $skia_DIR/out/$skia_BUILD/obj.target/gyp/libutils.a $skia_DIR/out/$skia_BUILD/obj.target/gyp/libopts.a $skia_DIR/out/$skia_BUILD/obj.target/gyp/libcore.a -end-group"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
libcairoperf_sources = \
|
||||
cairo-perf.c \
|
||||
cairo-perf-report.c \
|
||||
cairo-stats.c \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ print_change_bar (double change,
|
|||
double max_change,
|
||||
int use_utf)
|
||||
{
|
||||
int units_per_cell = (int) ceil (max_change / CHANGE_BAR_WIDTH);
|
||||
int units_per_cell = ceil (max_change / CHANGE_BAR_WIDTH);
|
||||
static char const *ascii_boxes[8] = {
|
||||
"****","***" ,"***", "**",
|
||||
"**", "*", "*", ""
|
||||
|
|
@ -369,7 +369,7 @@ main (int argc,
|
|||
if (args.num_filenames) {
|
||||
reports = xcalloc (args.num_filenames, sizeof (cairo_perf_report_t));
|
||||
for (i = 0; i < args.num_filenames; i++) {
|
||||
cairo_perf_report_load (&reports[i], args.filenames[i],
|
||||
cairo_perf_report_load (&reports[i], args.filenames[i], i,
|
||||
test_report_cmp_name);
|
||||
printf ("loaded: %s, %d tests\n",
|
||||
args.filenames[i], reports[i].tests_count);
|
||||
|
|
@ -377,7 +377,7 @@ main (int argc,
|
|||
} else {
|
||||
args.num_filenames = 1;
|
||||
reports = xcalloc (args.num_filenames, sizeof (cairo_perf_report_t));
|
||||
cairo_perf_report_load (&reports[0], NULL, test_report_cmp_name);
|
||||
cairo_perf_report_load (&reports[0], NULL, 0, test_report_cmp_name);
|
||||
}
|
||||
|
||||
cairo_perf_reports_compare (reports, args.num_filenames, &args.options);
|
||||
|
|
|
|||
|
|
@ -161,7 +161,6 @@ test_diff_print_binary (test_diff_t *diff,
|
|||
else
|
||||
printf ("%5s %26s", diff->tests[0]->backend, diff->tests[0]->name);
|
||||
|
||||
if (diff->tests[0]->size) {
|
||||
printf (" %6.2f (%.2f %4.2f%%) -> %6.2f (%.2f %4.2f%%): %5.2fx ",
|
||||
diff->tests[0]->stats.min_ticks / diff->tests[0]->stats.ticks_per_ms,
|
||||
diff->tests[0]->stats.median_ticks / diff->tests[0]->stats.ticks_per_ms,
|
||||
|
|
@ -170,7 +169,6 @@ test_diff_print_binary (test_diff_t *diff,
|
|||
diff->tests[1]->stats.median_ticks / diff->tests[1]->stats.ticks_per_ms,
|
||||
diff->tests[1]->stats.std_dev * 100,
|
||||
fabs (diff->change));
|
||||
}
|
||||
|
||||
if (diff->change > 1.0)
|
||||
printf ("speedup\n");
|
||||
|
|
@ -191,24 +189,32 @@ test_diff_print_multi (test_diff_t *diff,
|
|||
double test_time;
|
||||
double change;
|
||||
|
||||
if (diff->tests[0]->size) {
|
||||
printf ("%s (backend: %s-%s, size: %d)\n",
|
||||
diff->tests[0]->name,
|
||||
diff->tests[0]->backend,
|
||||
diff->tests[0]->content,
|
||||
diff->tests[0]->size);
|
||||
} else {
|
||||
printf ("%s (backend: %s)\n",
|
||||
diff->tests[0]->name,
|
||||
diff->tests[0]->backend);
|
||||
}
|
||||
|
||||
for (i = 0; i < diff->num_tests; i++) {
|
||||
test_time = diff->tests[i]->stats.min_ticks;
|
||||
if (! options->use_ticks)
|
||||
test_time /= diff->tests[i]->stats.ticks_per_ms;
|
||||
change = diff->max / test_time;
|
||||
printf ("%8s %6.2f: %5.2fx ",
|
||||
diff->tests[i]->configuration,
|
||||
printf ("[%d] %6.2f: %5.2fx ",
|
||||
diff->tests[i]->fileno,
|
||||
diff->tests[i]->stats.min_ticks / diff->tests[i]->stats.ticks_per_ms,
|
||||
change);
|
||||
|
||||
if (options->print_change_bars)
|
||||
print_change_bar (change, max_change, options->use_utf);
|
||||
else
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
|
@ -476,8 +482,11 @@ main (int argc,
|
|||
|
||||
reports = xmalloc (args.num_filenames * sizeof (cairo_perf_report_t));
|
||||
|
||||
for (i = 0; i < args.num_filenames; i++ )
|
||||
cairo_perf_report_load (&reports[i], args.filenames[i], NULL);
|
||||
for (i = 0; i < args.num_filenames; i++ ) {
|
||||
cairo_perf_report_load (&reports[i], args.filenames[i], i, NULL);
|
||||
printf ("[%d] %s\n", i, args.filenames[i]);
|
||||
}
|
||||
printf ("\n");
|
||||
|
||||
cairo_perf_reports_compare (reports, args.num_filenames, &args.options);
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,8 @@
|
|||
#define CAIRO_PERF_ITERATION_MS_FAST 5
|
||||
|
||||
typedef struct _cairo_perf_case {
|
||||
CAIRO_PERF_DECL (*run);
|
||||
CAIRO_PERF_RUN_DECL (*run);
|
||||
cairo_bool_t (*enabled) (cairo_perf_t *perf);
|
||||
unsigned int min_size;
|
||||
unsigned int max_size;
|
||||
} cairo_perf_case_t;
|
||||
|
|
@ -251,7 +252,7 @@ cairo_perf_run (cairo_perf_t *perf,
|
|||
cairo_boilerplate_content (perf->target->content));
|
||||
else
|
||||
cairo_save (perf->cr);
|
||||
times[i] = perf_func (perf->cr, perf->size, perf->size, loops) / loops;
|
||||
times[i] = perf_func (perf->cr, perf->size, perf->size, loops) ;
|
||||
if (similar)
|
||||
cairo_pattern_destroy (cairo_pop_group (perf->cr));
|
||||
else
|
||||
|
|
@ -263,7 +264,7 @@ cairo_perf_run (cairo_perf_t *perf,
|
|||
_content_to_string (perf->target->content, similar),
|
||||
name, perf->size,
|
||||
_cairo_time_to_double (_cairo_time_from_s (1.)) / 1000.);
|
||||
printf (" %lld", (long long) times[i]);
|
||||
printf (" %lld", (long long) (times[i] / (double) loops));
|
||||
} else if (! perf->exact_iterations) {
|
||||
if (i > 0) {
|
||||
_cairo_stats_compute (&stats, times, i+1);
|
||||
|
|
@ -287,18 +288,18 @@ cairo_perf_run (cairo_perf_t *perf,
|
|||
if (count_func != NULL) {
|
||||
double count = count_func (perf->cr, perf->size, perf->size);
|
||||
fprintf (perf->summary,
|
||||
"%10lld %#8.3f %#8.3f %#5.2f%% %3d: %.2f\n",
|
||||
(long long) stats.min_ticks,
|
||||
_cairo_time_to_s (stats.min_ticks) * 1000.0,
|
||||
_cairo_time_to_s (stats.median_ticks) * 1000.0,
|
||||
"%10lld/%d %#8.3f %#8.3f %#5.2f%% %3d: %.2f\n",
|
||||
(long long) stats.min_ticks, loops,
|
||||
_cairo_time_to_s (stats.min_ticks) * 1000.0 / loops,
|
||||
_cairo_time_to_s (stats.median_ticks) * 1000.0 / loops,
|
||||
stats.std_dev * 100.0, stats.iterations,
|
||||
count / _cairo_time_to_s (stats.min_ticks));
|
||||
} else {
|
||||
fprintf (perf->summary,
|
||||
"%10lld %#8.3f %#8.3f %#5.2f%% %3d\n",
|
||||
(long long) stats.min_ticks,
|
||||
_cairo_time_to_s (stats.min_ticks) * 1000.0,
|
||||
_cairo_time_to_s (stats.median_ticks) * 1000.0,
|
||||
"%10lld/%d %#8.3f %#8.3f %#5.2f%% %3d\n",
|
||||
(long long) stats.min_ticks, loops,
|
||||
_cairo_time_to_s (stats.min_ticks) * 1000.0 / loops,
|
||||
_cairo_time_to_s (stats.median_ticks) * 1000.0 / loops,
|
||||
stats.std_dev * 100.0, stats.iterations);
|
||||
}
|
||||
fflush (perf->summary);
|
||||
|
|
@ -491,6 +492,9 @@ main (int argc,
|
|||
for (j = 0; perf_cases[j].run; j++) {
|
||||
const cairo_perf_case_t *perf_case = &perf_cases[j];
|
||||
|
||||
if (! perf_case->enabled (&perf))
|
||||
continue;
|
||||
|
||||
for (perf.size = perf_case->min_size;
|
||||
perf.size <= perf_case->max_size;
|
||||
perf.size *= 2)
|
||||
|
|
@ -536,42 +540,48 @@ main (int argc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#define FUNC(f) f, f##_enabled
|
||||
const cairo_perf_case_t perf_cases[] = {
|
||||
{ paint, 64, 512},
|
||||
{ paint_with_alpha, 64, 512},
|
||||
{ fill, 64, 512},
|
||||
{ stroke, 64, 512},
|
||||
{ text, 64, 512},
|
||||
{ glyphs, 64, 512},
|
||||
{ mask, 64, 512},
|
||||
{ line, 32, 512},
|
||||
{ curve, 32, 512},
|
||||
{ disjoint, 64, 512},
|
||||
{ hatching, 64, 512},
|
||||
{ tessellate, 100, 100},
|
||||
{ subimage_copy, 16, 512},
|
||||
{ hash_table, 16, 16},
|
||||
{ pattern_create_radial, 16, 16},
|
||||
{ zrusin, 415, 415},
|
||||
{ world_map, 800, 800},
|
||||
{ box_outline, 100, 100},
|
||||
{ mosaic, 800, 800 },
|
||||
{ long_lines, 100, 100},
|
||||
{ unaligned_clip, 100, 100},
|
||||
{ rectangles, 512, 512},
|
||||
{ rounded_rectangles, 512, 512},
|
||||
{ long_dashed_lines, 512, 512},
|
||||
{ composite_checker, 16, 512},
|
||||
{ twin, 800, 800},
|
||||
{ dragon, 1024, 1024 },
|
||||
{ pythagoras_tree, 768, 768 },
|
||||
{ intersections, 512, 512 },
|
||||
{ many_strokes, 32, 512 },
|
||||
{ wide_strokes, 32, 512 },
|
||||
{ many_fills, 32, 512 },
|
||||
{ wide_fills, 32, 512 },
|
||||
{ many_curves, 32, 512 },
|
||||
{ spiral, 512, 512 },
|
||||
{ wave, 500, 500 },
|
||||
{ FUNC(pixel), 1, 1 },
|
||||
{ FUNC(paint), 64, 512},
|
||||
{ FUNC(paint_with_alpha), 64, 512},
|
||||
{ FUNC(fill), 64, 512},
|
||||
{ FUNC(stroke), 64, 512},
|
||||
{ FUNC(text), 64, 512},
|
||||
{ FUNC(glyphs), 64, 512},
|
||||
{ FUNC(mask), 64, 512},
|
||||
{ FUNC(line), 32, 512},
|
||||
{ FUNC(a1_line), 32, 512},
|
||||
{ FUNC(curve), 32, 512},
|
||||
{ FUNC(a1_curve), 32, 512},
|
||||
{ FUNC(disjoint), 64, 512},
|
||||
{ FUNC(hatching), 64, 512},
|
||||
{ FUNC(tessellate), 100, 100},
|
||||
{ FUNC(subimage_copy), 16, 512},
|
||||
{ FUNC(hash_table), 16, 16},
|
||||
{ FUNC(pattern_create_radial), 16, 16},
|
||||
{ FUNC(zrusin), 415, 415},
|
||||
{ FUNC(world_map), 800, 800},
|
||||
{ FUNC(box_outline), 100, 100},
|
||||
{ FUNC(mosaic), 800, 800 },
|
||||
{ FUNC(long_lines), 100, 100},
|
||||
{ FUNC(unaligned_clip), 100, 100},
|
||||
{ FUNC(rectangles), 512, 512},
|
||||
{ FUNC(rounded_rectangles), 512, 512},
|
||||
{ FUNC(long_dashed_lines), 512, 512},
|
||||
{ FUNC(composite_checker), 16, 512},
|
||||
{ FUNC(twin), 800, 800},
|
||||
{ FUNC(dragon), 1024, 1024 },
|
||||
{ FUNC(sierpinski), 32, 1024 },
|
||||
{ FUNC(pythagoras_tree), 768, 768 },
|
||||
{ FUNC(intersections), 512, 512 },
|
||||
{ FUNC(many_strokes), 32, 512 },
|
||||
{ FUNC(wide_strokes), 32, 512 },
|
||||
{ FUNC(many_fills), 32, 512 },
|
||||
{ FUNC(wide_fills), 32, 512 },
|
||||
{ FUNC(many_curves), 32, 512 },
|
||||
{ FUNC(spiral), 512, 512 },
|
||||
{ FUNC(wave), 500, 500 },
|
||||
{ FUNC(fill_clip), 16, 512 },
|
||||
{ NULL }
|
||||
};
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ do { \
|
|||
|
||||
static test_report_status_t
|
||||
test_report_parse (test_report_t *report,
|
||||
int fileno,
|
||||
char *line,
|
||||
char *configuration)
|
||||
{
|
||||
|
|
@ -137,6 +138,7 @@ test_report_parse (test_report_t *report,
|
|||
|
||||
skip_space ();
|
||||
|
||||
report->fileno = fileno;
|
||||
report->configuration = configuration;
|
||||
parse_string (report->backend);
|
||||
end = strrchr (report->backend, '.');
|
||||
|
|
@ -369,7 +371,7 @@ cairo_perf_report_sort_and_compute_stats (cairo_perf_report_t *report,
|
|||
|
||||
void
|
||||
cairo_perf_report_load (cairo_perf_report_t *report,
|
||||
const char *filename,
|
||||
const char *filename, int id,
|
||||
int (*cmp) (const void *, const void *))
|
||||
{
|
||||
FILE *file;
|
||||
|
|
@ -401,6 +403,7 @@ cairo_perf_report_load (cairo_perf_report_t *report,
|
|||
report->tests_size = 16;
|
||||
report->tests = xmalloc (report->tests_size * sizeof (test_report_t));
|
||||
report->tests_count = 0;
|
||||
report->fileno = id;
|
||||
|
||||
if (filename == NULL) {
|
||||
file = stdin;
|
||||
|
|
@ -425,7 +428,7 @@ cairo_perf_report_load (cairo_perf_report_t *report,
|
|||
break;
|
||||
|
||||
status = test_report_parse (&report->tests[report->tests_count],
|
||||
line, report->configuration);
|
||||
id, line, report->configuration);
|
||||
if (status == TEST_REPORT_STATUS_ERROR)
|
||||
fprintf (stderr, "Ignoring unrecognized line %d of %s:\n%s",
|
||||
line_number, filename, line);
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ basename_no_ext (char *path)
|
|||
|
||||
name = basename (path);
|
||||
|
||||
dot = strchr (name, '.');
|
||||
dot = strrchr (name, '.');
|
||||
if (dot)
|
||||
*dot = '\0';
|
||||
|
||||
|
|
@ -108,6 +108,7 @@ struct trace {
|
|||
void *closure;
|
||||
cairo_surface_t *surface;
|
||||
cairo_bool_t observe;
|
||||
int tile_size;
|
||||
};
|
||||
|
||||
cairo_bool_t
|
||||
|
|
@ -132,7 +133,7 @@ cairo_perf_can_run (cairo_perf_t *perf,
|
|||
return TRUE;
|
||||
|
||||
copy = xstrdup (name);
|
||||
dot = strchr (copy, '.');
|
||||
dot = strrchr (copy, '.');
|
||||
if (dot != NULL)
|
||||
*dot = '\0';
|
||||
|
||||
|
|
@ -435,6 +436,7 @@ parse_options (cairo_perf_t *perf,
|
|||
perf->raw = FALSE;
|
||||
perf->observe = FALSE;
|
||||
perf->list_only = FALSE;
|
||||
perf->tile_size = 0;
|
||||
perf->names = NULL;
|
||||
perf->num_names = 0;
|
||||
perf->summary = stdout;
|
||||
|
|
@ -443,7 +445,7 @@ parse_options (cairo_perf_t *perf,
|
|||
perf->num_exclude_names = 0;
|
||||
|
||||
while (1) {
|
||||
c = _cairo_getopt (argc, argv, "i:x:lsrvc");
|
||||
c = _cairo_getopt (argc, argv, "t:i:x:lsrvc");
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
|
|
@ -457,6 +459,14 @@ parse_options (cairo_perf_t *perf,
|
|||
exit (1);
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
perf->tile_size = strtoul (optarg, &end, 10);
|
||||
if (*end != '\0') {
|
||||
fprintf (stderr, "Invalid argument for -t (not an integer): %s\n",
|
||||
optarg);
|
||||
exit (1);
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
perf->list_only = TRUE;
|
||||
break;
|
||||
|
|
@ -489,6 +499,11 @@ parse_options (cairo_perf_t *perf,
|
|||
}
|
||||
}
|
||||
|
||||
if (perf->observe && perf->tile_size) {
|
||||
fprintf (stderr, "Can't mix observer and tiling. Sorry.\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (verbose && perf->summary == NULL)
|
||||
perf->summary = stderr;
|
||||
#if HAVE_UNISTD_H
|
||||
|
|
@ -535,6 +550,79 @@ have_trace_filenames (cairo_perf_t *perf)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
_tiling_surface_finish (cairo_surface_t *observer,
|
||||
cairo_surface_t *target,
|
||||
void *closure)
|
||||
{
|
||||
struct trace *args = closure;
|
||||
cairo_surface_t *surface;
|
||||
cairo_content_t content;
|
||||
cairo_rectangle_t r;
|
||||
int width, height;
|
||||
int x, y, w, h;
|
||||
|
||||
cairo_recording_surface_get_extents (target, &r);
|
||||
w = r.width;
|
||||
h = r.height;
|
||||
|
||||
content = cairo_surface_get_content (target);
|
||||
|
||||
for (y = 0; y < h; y += args->tile_size) {
|
||||
height = args->tile_size;
|
||||
if (y + height > h)
|
||||
height = h - y;
|
||||
|
||||
for (x = 0; x < w; x += args->tile_size) {
|
||||
cairo_t *cr;
|
||||
|
||||
width = args->tile_size;
|
||||
if (x + width > w)
|
||||
width = w - x;
|
||||
|
||||
/* XXX to correctly observe the playback we would need
|
||||
* to replay the target onto the observer directly.
|
||||
*/
|
||||
surface = args->target->create_similar (args->surface,
|
||||
content, width, height);
|
||||
|
||||
cr = cairo_create (surface);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
cairo_set_source_surface (cr, target, -x, -y);
|
||||
cairo_paint (cr);
|
||||
cairo_destroy (cr);
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_surface_t *
|
||||
_tiling_surface_create (void *closure,
|
||||
cairo_content_t content,
|
||||
double width,
|
||||
double height,
|
||||
long uid)
|
||||
{
|
||||
cairo_rectangle_t r;
|
||||
cairo_surface_t *surface, *observer;
|
||||
|
||||
r.x = r.y = 0;
|
||||
r.width = width;
|
||||
r.height = height;
|
||||
|
||||
surface = cairo_recording_surface_create (content, &r);
|
||||
observer = cairo_surface_create_observer (surface,
|
||||
CAIRO_SURFACE_OBSERVER_NORMAL);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
cairo_surface_observer_add_finish_callback (observer,
|
||||
_tiling_surface_finish,
|
||||
closure);
|
||||
|
||||
return observer;
|
||||
}
|
||||
|
||||
static void
|
||||
cairo_perf_trace (cairo_perf_t *perf,
|
||||
const cairo_boilerplate_target_t *target,
|
||||
|
|
@ -549,7 +637,7 @@ cairo_perf_trace (cairo_perf_t *perf,
|
|||
char *trace_cpy, *name;
|
||||
const cairo_script_interpreter_hooks_t hooks = {
|
||||
&args,
|
||||
_similar_surface_create,
|
||||
perf->tile_size ? _tiling_surface_create : _similar_surface_create,
|
||||
NULL, /* surface_destroy */
|
||||
_context_create,
|
||||
NULL, /* context_destroy */
|
||||
|
|
@ -557,6 +645,7 @@ cairo_perf_trace (cairo_perf_t *perf,
|
|||
NULL /* copy_page */
|
||||
};
|
||||
|
||||
args.tile_size = perf->tile_size;
|
||||
args.observe = perf->observe;
|
||||
|
||||
trace_cpy = xstrdup (trace);
|
||||
|
|
@ -648,26 +737,30 @@ cairo_perf_trace (cairo_perf_t *perf,
|
|||
}
|
||||
|
||||
cairo_script_interpreter_run (csi, trace);
|
||||
line_no = cairo_script_interpreter_get_line_number (csi);
|
||||
|
||||
/* Finish before querying timings in case we are using an intermediate
|
||||
* target and so need to destroy all surfaces before rendering
|
||||
* commences.
|
||||
*/
|
||||
cairo_script_interpreter_finish (csi);
|
||||
|
||||
if (perf->observe) {
|
||||
cairo_device_t *observer = cairo_surface_get_device (args.surface);
|
||||
times[i] = _cairo_time_from_s (1.e9 * cairo_device_observer_elapsed (observer));
|
||||
paint[i] = _cairo_time_from_s (1.e9 * cairo_device_observer_paint_elapsed (observer));
|
||||
mask[i] = _cairo_time_from_s (1.e9 * cairo_device_observer_mask_elapsed (observer));
|
||||
stroke[i] = _cairo_time_from_s (1.e9 * cairo_device_observer_stroke_elapsed (observer));
|
||||
fill[i] = _cairo_time_from_s (1.e9 * cairo_device_observer_fill_elapsed (observer));
|
||||
glyphs[i] = _cairo_time_from_s (1.e9 * cairo_device_observer_glyphs_elapsed (observer));
|
||||
times[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_elapsed (observer));
|
||||
paint[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_paint_elapsed (observer));
|
||||
mask[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_mask_elapsed (observer));
|
||||
stroke[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_stroke_elapsed (observer));
|
||||
fill[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_fill_elapsed (observer));
|
||||
glyphs[i] = _cairo_time_from_s (1.e-9 * cairo_device_observer_glyphs_elapsed (observer));
|
||||
} else {
|
||||
clear_surface (args.surface); /* queue a write to the sync'ed surface */
|
||||
cairo_perf_timer_stop ();
|
||||
times[i] = cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_script_interpreter_finish (csi);
|
||||
scache_clear ();
|
||||
|
||||
line_no = cairo_script_interpreter_get_line_number (csi);
|
||||
|
||||
cairo_surface_destroy (args.surface);
|
||||
|
||||
if (target->cleanup)
|
||||
|
|
@ -766,28 +859,28 @@ cairo_perf_trace (cairo_perf_t *perf,
|
|||
fprintf (perf->summary,
|
||||
" %#9.3f", _cairo_time_to_s (stats.median_ticks));
|
||||
|
||||
_cairo_stats_compute (&stats, paint, i+1);
|
||||
_cairo_stats_compute (&stats, paint, i);
|
||||
fprintf (perf->summary,
|
||||
" %#9.3f", _cairo_time_to_s (stats.median_ticks));
|
||||
|
||||
_cairo_stats_compute (&stats, mask, i+1);
|
||||
_cairo_stats_compute (&stats, mask, i);
|
||||
fprintf (perf->summary,
|
||||
" %#9.3f", _cairo_time_to_s (stats.median_ticks));
|
||||
|
||||
_cairo_stats_compute (&stats, fill, i+1);
|
||||
_cairo_stats_compute (&stats, fill, i);
|
||||
fprintf (perf->summary,
|
||||
" %#9.3f", _cairo_time_to_s (stats.median_ticks));
|
||||
|
||||
_cairo_stats_compute (&stats, stroke, i+1);
|
||||
_cairo_stats_compute (&stats, stroke, i);
|
||||
fprintf (perf->summary,
|
||||
" %#9.3f", _cairo_time_to_s (stats.median_ticks));
|
||||
|
||||
_cairo_stats_compute (&stats, glyphs, i+1);
|
||||
_cairo_stats_compute (&stats, glyphs, i);
|
||||
fprintf (perf->summary,
|
||||
" %#9.3f", _cairo_time_to_s (stats.median_ticks));
|
||||
|
||||
fprintf (perf->summary,
|
||||
" %5d\n", i+1);
|
||||
" %5d\n", i);
|
||||
} else {
|
||||
fprintf (perf->summary,
|
||||
"%#8.3f %#8.3f %#6.2f%% %4d/%d\n",
|
||||
|
|
@ -807,11 +900,6 @@ out:
|
|||
|
||||
perf->test_number++;
|
||||
free (trace_cpy);
|
||||
|
||||
cairo_debug_reset_static_data ();
|
||||
#if HAVE_FCFINI
|
||||
FcFini ();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
|||
|
|
@ -83,6 +83,8 @@ typedef struct _cairo_perf {
|
|||
double ms_per_iteration;
|
||||
cairo_bool_t fast_and_sloppy;
|
||||
|
||||
unsigned int tile_size;
|
||||
|
||||
/* Stuff used internally */
|
||||
cairo_time_t *times;
|
||||
const cairo_boilerplate_target_t **targets;
|
||||
|
|
@ -121,6 +123,7 @@ cairo_perf_cover_sources_and_operators (cairo_perf_t *perf,
|
|||
|
||||
typedef struct _test_report {
|
||||
int id;
|
||||
int fileno;
|
||||
const char *configuration;
|
||||
char *backend;
|
||||
char *content;
|
||||
|
|
@ -149,6 +152,7 @@ typedef struct _test_diff {
|
|||
typedef struct _cairo_perf_report {
|
||||
char *configuration;
|
||||
const char *name;
|
||||
int fileno;
|
||||
test_report_t *tests;
|
||||
int tests_size;
|
||||
int tests_count;
|
||||
|
|
@ -162,7 +166,7 @@ typedef enum {
|
|||
|
||||
void
|
||||
cairo_perf_report_load (cairo_perf_report_t *report,
|
||||
const char *filename,
|
||||
const char *filename, int id,
|
||||
int (*cmp) (const void *, const void *));
|
||||
|
||||
void
|
||||
|
|
@ -177,7 +181,10 @@ int
|
|||
test_report_cmp_name (const void *a,
|
||||
const void *b);
|
||||
|
||||
#define CAIRO_PERF_DECL(func) void (func) (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
#define CAIRO_PERF_ENABLED_DECL(func) cairo_bool_t (func ## _enabled) (cairo_perf_t *perf)
|
||||
#define CAIRO_PERF_RUN_DECL(func) void (func) (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
|
||||
#define CAIRO_PERF_DECL(func) CAIRO_PERF_RUN_DECL(func); CAIRO_PERF_ENABLED_DECL(func)
|
||||
|
||||
CAIRO_PERF_DECL (fill);
|
||||
CAIRO_PERF_DECL (paint);
|
||||
|
|
@ -214,6 +221,11 @@ CAIRO_PERF_DECL (many_fills);
|
|||
CAIRO_PERF_DECL (wide_fills);
|
||||
CAIRO_PERF_DECL (many_curves);
|
||||
CAIRO_PERF_DECL (curve);
|
||||
CAIRO_PERF_DECL (a1_curve);
|
||||
CAIRO_PERF_DECL (line);
|
||||
CAIRO_PERF_DECL (a1_line);
|
||||
CAIRO_PERF_DECL (pixel);
|
||||
CAIRO_PERF_DECL (sierpinski);
|
||||
CAIRO_PERF_DECL (fill_clip);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -25,16 +25,25 @@
|
|||
|
||||
#include "cairo-stats.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
void
|
||||
_cairo_stats_compute (cairo_stats_t *stats,
|
||||
cairo_time_t *values,
|
||||
int num_values)
|
||||
{
|
||||
int i;
|
||||
cairo_time_t sumtime;
|
||||
double sum, mean, delta, q1, q3, iqr;
|
||||
double outlier_min, outlier_max;
|
||||
int min_valid, num_valid;
|
||||
cairo_time_t sum, mean, delta, q1, q3, iqr;
|
||||
cairo_time_t outlier_min, outlier_max;
|
||||
int i, min_valid, num_valid;
|
||||
|
||||
assert (num_values > 0);
|
||||
|
||||
if (num_values == 1) {
|
||||
stats->min_ticks = stats->median_ticks = values[0];
|
||||
stats->std_dev = 0;
|
||||
stats->iterations = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* First, identify any outliers, using the definition of "mild
|
||||
* outliers" from:
|
||||
|
|
@ -48,44 +57,35 @@ _cairo_stats_compute (cairo_stats_t *stats,
|
|||
*/
|
||||
qsort (values, num_values, sizeof (cairo_time_t), _cairo_time_cmp);
|
||||
|
||||
q1 = _cairo_time_to_s (values[(1*num_values)/4]);
|
||||
q3 = _cairo_time_to_s (values[(3*num_values)/4]);
|
||||
q1 = values[1*num_values/4];
|
||||
q3 = values[3*num_values/4];
|
||||
|
||||
/* XXX assumes we have native uint64_t */
|
||||
iqr = q3 - q1;
|
||||
outlier_min = q1 - 3 * iqr / 2;
|
||||
outlier_max = q3 + 3 * iqr / 2;
|
||||
|
||||
outlier_min = _cairo_time_from_s (q1 - 1.5 * iqr);
|
||||
outlier_max = _cairo_time_from_s (q3 + 1.5 * iqr);
|
||||
for (i = 0; i < num_values && values[i] < outlier_min; i++)
|
||||
;
|
||||
min_valid = i;
|
||||
|
||||
min_valid = 0;
|
||||
while (min_valid < num_values &&
|
||||
_cairo_time_to_s (values[min_valid]) < outlier_min)
|
||||
{
|
||||
min_valid++;
|
||||
}
|
||||
|
||||
i = min_valid;
|
||||
num_valid = 0;
|
||||
while (i + num_valid < num_values &&
|
||||
_cairo_time_to_s (values[i+num_valid]) <= outlier_max)
|
||||
{
|
||||
num_valid++;
|
||||
}
|
||||
for (i = 0; i < num_values && values[i] <= outlier_max; i++)
|
||||
;
|
||||
num_valid = i - min_valid;
|
||||
assert(num_valid);
|
||||
|
||||
stats->iterations = num_valid;
|
||||
stats->min_ticks = values[min_valid];
|
||||
|
||||
sumtime = _cairo_time_from_s (0);
|
||||
for (i = min_valid; i < min_valid + num_valid; i++) {
|
||||
sumtime = _cairo_time_add (sumtime, values[i]);
|
||||
stats->min_ticks = _cairo_time_min (stats->min_ticks, values[i]);
|
||||
}
|
||||
|
||||
mean = _cairo_time_to_s (sumtime) / num_valid;
|
||||
stats->median_ticks = values[min_valid + num_valid / 2];
|
||||
|
||||
sum = 0.0;
|
||||
sum = 0;
|
||||
for (i = min_valid; i < min_valid + num_valid; i++)
|
||||
sum = _cairo_time_add (sum, values[i]);
|
||||
mean = sum / num_valid;
|
||||
|
||||
sum = 0;
|
||||
for (i = min_valid; i < min_valid + num_valid; i++) {
|
||||
delta = _cairo_time_to_s (values[i]) - mean;
|
||||
delta = values[i] - mean;
|
||||
sum += delta * delta;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ libcairo_perf_micro_sources = \
|
|||
hatching.c \
|
||||
hash-table.c \
|
||||
line.c \
|
||||
a1-line.c \
|
||||
long-lines.c \
|
||||
mosaic.c \
|
||||
paint.c \
|
||||
|
|
@ -35,7 +36,11 @@ libcairo_perf_micro_sources = \
|
|||
wide-fills.c \
|
||||
many-curves.c \
|
||||
curve.c \
|
||||
a1-curve.c \
|
||||
spiral.c \
|
||||
pixel.c \
|
||||
sierpinski.c \
|
||||
fill-clip.c \
|
||||
$(NULL)
|
||||
|
||||
libcairo_perf_micro_headers = \
|
||||
|
|
|
|||
112
perf/micro/a1-curve.c
Normal file
112
perf/micro/a1-curve.c
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairo-perf.h"
|
||||
|
||||
static uint32_t state;
|
||||
|
||||
static double
|
||||
uniform_random (double minval, double maxval)
|
||||
{
|
||||
static uint32_t const poly = 0x9a795537U;
|
||||
uint32_t n = 32;
|
||||
while (n-->0)
|
||||
state = 2*state < state ? (2*state ^ poly) : 2*state;
|
||||
return minval + state * (maxval - minval) / 4294967296.0;
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
do_curve_stroke (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
state = 0xc0ffee;
|
||||
cairo_set_line_width (cr, 2.);
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--) {
|
||||
double x1 = uniform_random (0, width);
|
||||
double x2 = uniform_random (0, width);
|
||||
double x3 = uniform_random (0, width);
|
||||
double y1 = uniform_random (0, height);
|
||||
double y2 = uniform_random (0, height);
|
||||
double y3 = uniform_random (0, height);
|
||||
cairo_move_to (cr, uniform_random (0, width), uniform_random (0, height));
|
||||
cairo_curve_to (cr, x1, y1, x2, y2, x3, y3);
|
||||
cairo_stroke(cr);
|
||||
}
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
do_curve_fill (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
state = 0xc0ffee;
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--) {
|
||||
double x0 = uniform_random (0, width);
|
||||
double x1 = uniform_random (0, width);
|
||||
double x2 = uniform_random (0, width);
|
||||
double x3 = uniform_random (0, width);
|
||||
double xm = uniform_random (0, width);
|
||||
double xn = uniform_random (0, width);
|
||||
double y0 = uniform_random (0, height);
|
||||
double y1 = uniform_random (0, height);
|
||||
double y2 = uniform_random (0, height);
|
||||
double y3 = uniform_random (0, height);
|
||||
double ym = uniform_random (0, height);
|
||||
double yn = uniform_random (0, height);
|
||||
|
||||
cairo_move_to (cr, xm, ym);
|
||||
cairo_curve_to (cr, x1, y1, x2, y2, xn, yn);
|
||||
cairo_curve_to (cr, x3, y3, x0, y0, xm, ym);
|
||||
cairo_close_path (cr);
|
||||
|
||||
cairo_fill(cr);
|
||||
}
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
a1_curve_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "a1-curve", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
a1_curve (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_set_source_rgb (cr, 1., 1., 1.);
|
||||
cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
|
||||
|
||||
cairo_perf_run (perf, "a1-curve-stroked", do_curve_stroke, NULL);
|
||||
cairo_perf_run (perf, "a1-curve-filled", do_curve_fill, NULL);
|
||||
}
|
||||
223
perf/micro/a1-line.c
Normal file
223
perf/micro/a1-line.c
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairo-perf.h"
|
||||
|
||||
static cairo_time_t
|
||||
horizontal (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
double h = height/2 + .5;
|
||||
|
||||
cairo_move_to (cr, 0, h);
|
||||
cairo_line_to (cr, width, h);
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--)
|
||||
cairo_stroke_preserve (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_new_path (cr);
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
horizontal_hair (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_set_line_width (cr, 1.);
|
||||
return horizontal (cr, width, height, loops);
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
horizontal_wide (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_set_line_width (cr, 5.);
|
||||
return horizontal (cr, width, height, loops);
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
nearly_horizontal (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
double h = height/2;
|
||||
|
||||
cairo_move_to (cr, 0, h);
|
||||
cairo_line_to (cr, width, h+1);
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--)
|
||||
cairo_stroke_preserve (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_new_path (cr);
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
nearly_horizontal_hair (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_set_line_width (cr, 1.);
|
||||
return nearly_horizontal (cr, width, height, loops);
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
nearly_horizontal_wide (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_set_line_width (cr, 5.);
|
||||
return nearly_horizontal (cr, width, height, loops);
|
||||
}
|
||||
|
||||
|
||||
static cairo_time_t
|
||||
vertical (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
double w = width/2 + .5;
|
||||
|
||||
cairo_move_to (cr, w, 0);
|
||||
cairo_line_to (cr, w, height);
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--)
|
||||
cairo_stroke_preserve (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_new_path (cr);
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
vertical_hair (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_set_line_width (cr, 1.);
|
||||
return vertical (cr, width, height, loops);
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
vertical_wide (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_set_line_width (cr, 5.);
|
||||
return vertical (cr, width, height, loops);
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
nearly_vertical (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
double w = width/2;
|
||||
|
||||
cairo_move_to (cr, w, 0);
|
||||
cairo_line_to (cr, w+1, height);
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--)
|
||||
cairo_stroke_preserve (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_new_path (cr);
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
nearly_vertical_hair (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_set_line_width (cr, 1.);
|
||||
return nearly_vertical (cr, width, height, loops);
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
nearly_vertical_wide (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_set_line_width (cr, 5.);
|
||||
return nearly_vertical (cr, width, height, loops);
|
||||
}
|
||||
|
||||
|
||||
static cairo_time_t
|
||||
diagonal (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_move_to (cr, 0, 0);
|
||||
cairo_line_to (cr, width, height);
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--)
|
||||
cairo_stroke_preserve (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_new_path (cr);
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
diagonal_hair (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_set_line_width (cr, 1.);
|
||||
return diagonal (cr, width, height, loops);
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
diagonal_wide (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_set_line_width (cr, 5.);
|
||||
return diagonal (cr, width, height, loops);
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
a1_line_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "a1-line", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
a1_line (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_set_source_rgb (cr, 1., 1., 1.);
|
||||
cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
|
||||
|
||||
cairo_perf_run (perf, "a1-line-hh", horizontal_hair, NULL);
|
||||
cairo_perf_run (perf, "a1-line-hw", horizontal_wide, NULL);
|
||||
cairo_perf_run (perf, "a1-line-nhh", nearly_horizontal_hair, NULL);
|
||||
cairo_perf_run (perf, "a1-line-nhw", nearly_horizontal_wide, NULL);
|
||||
|
||||
cairo_perf_run (perf, "a1-line-vh", vertical_hair, NULL);
|
||||
cairo_perf_run (perf, "a1-line-vw", vertical_wide, NULL);
|
||||
cairo_perf_run (perf, "a1-line-nvh", nearly_vertical_hair, NULL);
|
||||
cairo_perf_run (perf, "a1-line-nvw", nearly_vertical_wide, NULL);
|
||||
|
||||
cairo_perf_run (perf, "a1-line-dh", diagonal_hair, NULL);
|
||||
cairo_perf_run (perf, "a1-line-dw", diagonal_wide, NULL);
|
||||
}
|
||||
|
|
@ -64,6 +64,55 @@ box_outline_stroke (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
box_outline_alpha_stroke (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
1.5, 1.5,
|
||||
width - 3, height - 3);
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
cairo_set_source_rgba (cr, 1, 0, 0, .5); /* red */
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--)
|
||||
cairo_stroke_preserve (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_new_path (cr);
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
box_outline_aa_stroke (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_translate (cr, .5, .5);
|
||||
cairo_rectangle (cr,
|
||||
1.5, 1.5,
|
||||
width - 3, height - 3);
|
||||
cairo_set_line_width (cr, 1.0);
|
||||
cairo_set_source_rgb (cr, 1, 0, 0); /* red */
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--)
|
||||
cairo_stroke_preserve (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_new_path (cr);
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
box_outline_fill (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
|
|
@ -91,12 +140,76 @@ box_outline_fill (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
box_outline_alpha_fill (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_rectangle (cr,
|
||||
1.0, 1.0,
|
||||
width - 2, height - 2);
|
||||
cairo_rectangle (cr,
|
||||
2.0, 2.0,
|
||||
width - 4, height - 4);
|
||||
cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
|
||||
cairo_set_source_rgba (cr, 0, 1, 0, .5); /* green */
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--)
|
||||
cairo_fill_preserve (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_new_path (cr);
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
box_outline_aa_fill (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_translate (cr, .5, .5);
|
||||
cairo_rectangle (cr,
|
||||
1.0, 1.0,
|
||||
width - 2, height - 2);
|
||||
cairo_rectangle (cr,
|
||||
2.0, 2.0,
|
||||
width - 4, height - 4);
|
||||
cairo_set_fill_rule (cr, CAIRO_FILL_RULE_EVEN_ODD);
|
||||
cairo_set_source_rgb (cr, 0, 1, 0); /* green */
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--)
|
||||
cairo_fill_preserve (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_new_path (cr);
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
box_outline_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "box-outline", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
box_outline (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "box-outline", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "box-outline-stroke", box_outline_stroke, NULL);
|
||||
cairo_perf_run (perf, "box-outline-fill", box_outline_fill, NULL);
|
||||
|
||||
cairo_perf_run (perf, "box-outline-alpha-stroke", box_outline_alpha_stroke, NULL);
|
||||
cairo_perf_run (perf, "box-outline-alpha-fill", box_outline_alpha_fill, NULL);
|
||||
|
||||
cairo_perf_run (perf, "box-outline-aa-stroke", box_outline_aa_stroke, NULL);
|
||||
cairo_perf_run (perf, "box-outline-aa-fill", box_outline_aa_fill, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,6 +75,12 @@ do_composite_checker (cairo_t *cr,
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
composite_checker_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "composite-checker", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
composite_checker (cairo_perf_t *perf,
|
||||
cairo_t *cr,
|
||||
|
|
@ -83,9 +89,6 @@ composite_checker (cairo_perf_t *perf,
|
|||
{
|
||||
cairo_surface_t *image;
|
||||
|
||||
if (! cairo_perf_can_run (perf, "composite-checker", NULL))
|
||||
return;
|
||||
|
||||
/* Create the checker pattern. We don't actually need to draw
|
||||
* anything on it since that wouldn't affect performance.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -95,12 +95,15 @@ do_curve_fill (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
curve_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "curve", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
curve (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "curve", NULL))
|
||||
return;
|
||||
|
||||
cairo_set_source_rgb (cr, 1., 1., 1.);
|
||||
|
||||
cairo_perf_run (perf, "curve-stroked", do_curve_stroke, NULL);
|
||||
|
|
|
|||
|
|
@ -85,6 +85,12 @@ draw (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
disjoint_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "disjoint", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
disjoint (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -265,12 +265,15 @@ do_dragon_solid_circle_clip (cairo_t *cr, int width, int height, int loops)
|
|||
return do_dragon_solid (cr, width, height, loops);
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
dragon_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "dragon", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
dragon (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "dragon", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "dragon-solid", do_dragon_solid, NULL);
|
||||
cairo_perf_run (perf, "dragon-unaligned-solid", do_dragon_solid_unaligned, NULL);
|
||||
cairo_perf_run (perf, "dragon-solid-aligned-clip", do_dragon_solid_aligned_clip, NULL);
|
||||
|
|
|
|||
126
perf/micro/fill-clip.c
Normal file
126
perf/micro/fill-clip.c
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
/* Compares the overhead for WebKit's drawRect() */
|
||||
|
||||
#include "cairo-perf.h"
|
||||
|
||||
#include <pixman.h>
|
||||
|
||||
static cairo_time_t
|
||||
clip_paint (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
int x = width/4, w = width/2;
|
||||
int y = height/4, h = height/2;
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--) {
|
||||
cairo_reset_clip (cr);
|
||||
cairo_rectangle (cr, x, y, w, h);
|
||||
cairo_clip (cr);
|
||||
cairo_paint (cr);
|
||||
}
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
rect_fill (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
int x = width/4, w = width/2;
|
||||
int y = height/4, h = height/2;
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--) {
|
||||
cairo_rectangle (cr, x, y, w, h);
|
||||
cairo_fill (cr);
|
||||
}
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
direct (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
int x = width/4, w = width/2;
|
||||
int y = height/4, h = height/2;
|
||||
cairo_surface_t *surface, *image;
|
||||
uint8_t *data;
|
||||
int stride, bpp;
|
||||
|
||||
|
||||
surface = cairo_get_target (cr);
|
||||
image = cairo_surface_map_to_image (surface, NULL);
|
||||
data = cairo_image_surface_get_data (image);
|
||||
stride = cairo_image_surface_get_stride (image);
|
||||
|
||||
switch (cairo_image_surface_get_format (image)) {
|
||||
default:
|
||||
case CAIRO_FORMAT_INVALID:
|
||||
case CAIRO_FORMAT_A1: bpp = 0; break;
|
||||
case CAIRO_FORMAT_A8: bpp = 8; break;
|
||||
case CAIRO_FORMAT_RGB16_565: bpp = 16; break;
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
case CAIRO_FORMAT_RGB30:
|
||||
case CAIRO_FORMAT_ARGB32: bpp = 32; break;
|
||||
}
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--) {
|
||||
pixman_fill ((uint32_t *)data, stride / sizeof(uint32_t), bpp,
|
||||
x, y, w, h,
|
||||
-1);
|
||||
}
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_surface_unmap_image (surface, image);
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
fill_clip_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "fillclip", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
fill_clip (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_set_source_rgb (cr, 1., 1., 1.);
|
||||
|
||||
cairo_perf_run (perf, "fillclip-clip", clip_paint, NULL);
|
||||
cairo_perf_run (perf, "fillclip-fill", rect_fill, NULL);
|
||||
cairo_perf_run (perf, "fillclip-direct", direct, NULL);
|
||||
}
|
||||
|
|
@ -107,12 +107,15 @@ do_fill_eo_noaa (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
fill_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "fill", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
fill (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "fill", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_cover_sources_and_operators (perf, "fill", do_fill, NULL);
|
||||
cairo_perf_cover_sources_and_operators (perf, "fill-annuli", do_fill_annuli, NULL);
|
||||
cairo_perf_cover_sources_and_operators (perf, "fill-eo-noaa", do_fill_eo_noaa, NULL);
|
||||
|
|
|
|||
|
|
@ -170,12 +170,15 @@ DECL(48ca, 48, CAIRO_ANTIALIAS_SUBPIXEL)
|
|||
DECL(8mono, 8, CAIRO_ANTIALIAS_NONE)
|
||||
DECL(48mono, 48, CAIRO_ANTIALIAS_NONE)
|
||||
|
||||
cairo_bool_t
|
||||
glyphs_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "glyphs", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
glyphs (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "glyphs", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_cover_sources_and_operators (perf, "glyphs8mono", do_glyphs8mono, count_glyphs8mono);
|
||||
cairo_perf_cover_sources_and_operators (perf, "glyphs8", do_glyphs8, count_glyphs8);
|
||||
cairo_perf_cover_sources_and_operators (perf, "glyphs8ca", do_glyphs8ca, count_glyphs8ca);
|
||||
|
|
|
|||
|
|
@ -101,12 +101,15 @@ do_hash_table (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
hash_table_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "hash-table", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
hash_table (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "hash-table", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_cover_sources_and_operators (perf, "hash-table",
|
||||
do_hash_table, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -170,12 +170,15 @@ F(clip_alpha_aligned_mono, clip_alpha, aligned, mono)
|
|||
F(clip_alpha_misaligned_mono, clip_alpha, misaligned, mono)
|
||||
F(clip_alpha_rotated_mono, clip_alpha, rotated, mono)
|
||||
|
||||
cairo_bool_t
|
||||
hatching_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "hatching", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
hatching (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "hatching", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "hatching-aligned-aa", draw_aligned_aa, NULL);
|
||||
cairo_perf_run (perf, "hatching-misaligned-aa", draw_misaligned_aa, NULL);
|
||||
cairo_perf_run (perf, "hatching-rotated-aa", draw_rotated_aa, NULL);
|
||||
|
|
|
|||
|
|
@ -143,12 +143,15 @@ random_curve_nz (cairo_t *cr, int width, int height, int loops)
|
|||
return draw_random_curve (cr, CAIRO_FILL_RULE_WINDING, width, height, loops);
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
intersections_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "intersections", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
intersections (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "intersections", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "intersections-nz-fill", random_nz, NULL);
|
||||
cairo_perf_run (perf, "intersections-eo-fill", random_eo, NULL);
|
||||
|
||||
|
|
|
|||
|
|
@ -196,12 +196,15 @@ diagonal_wide (cairo_t *cr, int width, int height, int loops)
|
|||
return diagonal (cr, width, height, loops);
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
line_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "line", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
line (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "line", NULL))
|
||||
return;
|
||||
|
||||
cairo_set_source_rgb (cr, 1., 1., 1.);
|
||||
|
||||
cairo_perf_run (perf, "line-hh", horizontal_hair, NULL);
|
||||
|
|
|
|||
|
|
@ -61,11 +61,14 @@ do_long_dashed_lines (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
long_dashed_lines_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "long-dashed-lines", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
long_dashed_lines (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "long-dashed-lines", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "long-dashed-lines", do_long_dashed_lines, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,12 +132,15 @@ long_lines_cropped_once (cairo_t *cr, int width, int height, int loops)
|
|||
return do_long_lines (cr, width, height, loops, LONG_LINES_CROPPED | LONG_LINES_ONCE);
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
long_lines_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "long-lines", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
long_lines (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "long-lines", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "long-lines-uncropped", long_lines_uncropped, NULL);
|
||||
cairo_perf_run (perf, "long-lines-uncropped-once", long_lines_uncropped_once, NULL);
|
||||
cairo_perf_run (perf, "long-lines-cropped", long_lines_cropped, NULL);
|
||||
|
|
|
|||
|
|
@ -118,12 +118,15 @@ do_many_curves_filled (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
many_curves_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "many-curves", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
many_curves (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "many-curves", NULL))
|
||||
return;
|
||||
|
||||
cairo_set_source_rgb (cr, 1., 1., 1.);
|
||||
|
||||
cairo_perf_run (perf, "many-curves-hair-stroked", do_many_curves_hair_stroked, NULL);
|
||||
|
|
|
|||
|
|
@ -170,12 +170,15 @@ do_many_fills (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
many_fills_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "many-fills", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
many_fills (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "many-fills", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "many-fills-halign", do_many_fills_ha, NULL);
|
||||
cairo_perf_run (perf, "many-fills-valign", do_many_fills_va, NULL);
|
||||
cairo_perf_run (perf, "many-fills-horizontal", do_many_fills_h, NULL);
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ do_many_strokes_ha (cairo_t *cr, int width, int height, int loops)
|
|||
|
||||
state = 0xc0ffee;
|
||||
for (count = 0; count < 1000; count++) {
|
||||
double h = floor (uniform_random (0, height));
|
||||
double h = floor (uniform_random (0, height)) + .5;
|
||||
cairo_move_to (cr, floor (uniform_random (0, width)), h);
|
||||
cairo_line_to (cr, ceil (uniform_random (0, width)), h);
|
||||
}
|
||||
|
|
@ -97,7 +97,7 @@ do_many_strokes_va (cairo_t *cr, int width, int height, int loops)
|
|||
|
||||
state = 0xc0ffee;
|
||||
for (count = 0; count < 1000; count++) {
|
||||
double v = floor (uniform_random (0, width));
|
||||
double v = floor (uniform_random (0, width)) + .5;
|
||||
cairo_move_to (cr, v, floor (uniform_random (0, height)));
|
||||
cairo_line_to (cr, v, ceil (uniform_random (0, height)));
|
||||
}
|
||||
|
|
@ -169,12 +169,15 @@ do_many_strokes (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
many_strokes_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "many-strokes", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
many_strokes (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "many-strokes", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "many-strokes-halign", do_many_strokes_ha, NULL);
|
||||
cairo_perf_run (perf, "many-strokes-valign", do_many_strokes_va, NULL);
|
||||
cairo_perf_run (perf, "many-strokes-horizontal", do_many_strokes_h, NULL);
|
||||
|
|
|
|||
|
|
@ -272,6 +272,12 @@ do_mask_radial (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
mask_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "mask", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
mask (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -160,12 +160,15 @@ mosaic_tessellate_curves (cairo_t *cr, int width, int height, int loops)
|
|||
return mosaic_perform (cr, MOSAIC_TESSELLATE | MOSAIC_CURVE_TO, width, height, loops);
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
mosaic_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "mosaic", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
mosaic (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "mosaic", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "mosaic-fill-curves", mosaic_fill_curves, NULL);
|
||||
cairo_perf_run (perf, "mosaic-fill-lines", mosaic_fill_lines, NULL);
|
||||
cairo_perf_run (perf, "mosaic-tessellate-curves", mosaic_tessellate_curves, NULL);
|
||||
|
|
|
|||
|
|
@ -44,12 +44,15 @@ count_paint_with_alpha (cairo_t *cr, int width, int height)
|
|||
return width * height / 1e6; /* Mpix/s */
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
paint_with_alpha_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "paint-with-alpha", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
paint_with_alpha (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "paint-with-alpha", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_cover_sources_and_operators (perf, "paint-with-alpha",
|
||||
do_paint_with_alpha,
|
||||
count_paint_with_alpha);
|
||||
|
|
|
|||
|
|
@ -44,11 +44,14 @@ count_paint (cairo_t *cr, int width, int height)
|
|||
return width * height / 1e6; /* Mpix/s */
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
paint_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "paint", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
paint (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "paint", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_cover_sources_and_operators (perf, "paint", do_paint, count_paint);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,14 +79,17 @@ do_pattern_create_radial (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
pattern_create_radial_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "pattern-create-radial", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
pattern_create_radial (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (! cairo_perf_can_run (perf, "pattern-create-radial", NULL))
|
||||
return;
|
||||
|
||||
srand (time (0));
|
||||
for (i = 0; i < RADIALS_COUNT; i++)
|
||||
{
|
||||
|
|
|
|||
177
perf/micro/pixel.c
Normal file
177
perf/micro/pixel.c
Normal file
|
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
/* Measure the overhead in setting a single pixel */
|
||||
|
||||
#include "cairo-perf.h"
|
||||
|
||||
static cairo_time_t
|
||||
pixel_paint (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--)
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
pixel_mask (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_surface_t *mask;
|
||||
cairo_t *cr2;
|
||||
|
||||
mask = cairo_surface_create_similar (cairo_get_target (cr),
|
||||
CAIRO_CONTENT_ALPHA,
|
||||
1, 1);
|
||||
cr2 = cairo_create (mask);
|
||||
cairo_set_source_rgb (cr2, 1,1,1);
|
||||
cairo_paint (cr2);
|
||||
cairo_destroy (cr2);
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--)
|
||||
cairo_mask_surface (cr, mask, 0, 0);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_surface_destroy (mask);
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
pixel_rectangle (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_new_path (cr);
|
||||
cairo_rectangle (cr, 0, 0, 1, 1);
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--)
|
||||
cairo_fill_preserve (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_new_path (cr);
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
pixel_subrectangle (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_new_path (cr);
|
||||
cairo_rectangle (cr, 0.1, 0.1, .8, .8);
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--)
|
||||
cairo_fill_preserve (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_new_path (cr);
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
pixel_triangle (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_new_path (cr);
|
||||
cairo_move_to (cr, 0, 0);
|
||||
cairo_line_to (cr, 1, 1);
|
||||
cairo_line_to (cr, 0, 1);
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--)
|
||||
cairo_fill_preserve (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_new_path (cr);
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
pixel_circle (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_new_path (cr);
|
||||
cairo_arc (cr, 0.5, 0.5, 0.5, 0, 2 * M_PI);
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--)
|
||||
cairo_fill_preserve (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_new_path (cr);
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
pixel_stroke (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
cairo_set_line_width (cr, 1.);
|
||||
cairo_new_path (cr);
|
||||
cairo_move_to (cr, 0, 0.5);
|
||||
cairo_line_to (cr, 1, 0.5);
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--)
|
||||
cairo_stroke_preserve (cr);
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
cairo_new_path (cr);
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
pixel_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "pixel", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
pixel (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_set_source_rgb (cr, 1., 1., 1.);
|
||||
|
||||
cairo_perf_run (perf, "pixel-paint", pixel_paint, NULL);
|
||||
cairo_perf_run (perf, "pixel-mask", pixel_mask, NULL);
|
||||
cairo_perf_run (perf, "pixel-rectangle", pixel_rectangle, NULL);
|
||||
cairo_perf_run (perf, "pixel-subrectangle", pixel_subrectangle, NULL);
|
||||
cairo_perf_run (perf, "pixel-triangle", pixel_triangle, NULL);
|
||||
cairo_perf_run (perf, "pixel-circle", pixel_circle, NULL);
|
||||
cairo_perf_run (perf, "pixel-stroke", pixel_stroke, NULL);
|
||||
}
|
||||
|
|
@ -82,11 +82,14 @@ do_pythagoras_tree (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
pythagoras_tree_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "pythagoras-tree", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
pythagoras_tree (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "pythagoras-tree", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "pythagoras-tree", do_pythagoras_tree, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,14 +95,17 @@ do_rectangle (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
rectangles_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "rectangles", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
rectangles (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (! cairo_perf_can_run (perf, "rectangles", NULL))
|
||||
return;
|
||||
|
||||
srand (8478232);
|
||||
for (i = 0; i < RECTANGLE_COUNT; i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -119,14 +119,17 @@ do_rectangles_once (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
rounded_rectangles_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "rounded-rectangles", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
rounded_rectangles (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (! cairo_perf_can_run (perf, "rounded-rectangles", NULL))
|
||||
return;
|
||||
|
||||
srand (8478232);
|
||||
for (i = 0; i < RECTANGLE_COUNT; i++) {
|
||||
rects[i].x = rand () % width;
|
||||
|
|
|
|||
94
perf/micro/sierpinski.c
Normal file
94
perf/micro/sierpinski.c
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use, copy,
|
||||
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
* Author: Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairo-perf.h"
|
||||
|
||||
static const double m_1_sqrt_3 = 0.577359269;
|
||||
|
||||
static void
|
||||
T (cairo_t *cr, int size)
|
||||
{
|
||||
cairo_move_to (cr, 0, 0);
|
||||
cairo_line_to (cr, size, 0);
|
||||
cairo_line_to (cr, size/2, size*m_1_sqrt_3);
|
||||
|
||||
size /= 2;
|
||||
if (size >= 4) {
|
||||
T (cr, size);
|
||||
cairo_save (cr); {
|
||||
cairo_translate (cr, size, 0);
|
||||
T (cr, size);
|
||||
} cairo_restore (cr);
|
||||
cairo_save (cr); {
|
||||
cairo_translate (cr, size/2, size*m_1_sqrt_3);
|
||||
T (cr, size);
|
||||
} cairo_restore (cr);
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_time_t
|
||||
draw (cairo_t *cr, int width, int height, int loops)
|
||||
{
|
||||
int t_height = height/2;
|
||||
int t_width = t_height / m_1_sqrt_3;
|
||||
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_paint (cr);
|
||||
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
cairo_set_line_width (cr, 1.);
|
||||
|
||||
cairo_perf_timer_start ();
|
||||
|
||||
while (loops--) {
|
||||
cairo_save (cr);
|
||||
T (cr, t_width);
|
||||
|
||||
cairo_translate (cr, 0, height);
|
||||
cairo_scale (cr, 1, -1);
|
||||
|
||||
T (cr, t_width);
|
||||
|
||||
cairo_stroke (cr);
|
||||
cairo_restore (cr);
|
||||
}
|
||||
|
||||
cairo_perf_timer_stop ();
|
||||
|
||||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
sierpinski_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "sierpinski", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
sierpinski (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_perf_run (perf, "sierpinski", draw, NULL);
|
||||
}
|
||||
|
|
@ -326,12 +326,15 @@ draw_spiral_stroke_na (cairo_t *cr, int width, int height, int loops)
|
|||
width, height, loops);
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
spiral_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "spiral", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
spiral (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "spiral", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "spiral-box-nonalign-evenodd-fill", draw_spiral_eo_na_box, NULL);
|
||||
cairo_perf_run (perf, "spiral-box-nonalign-nonzero-fill", draw_spiral_nz_na_box, NULL);
|
||||
cairo_perf_run (perf, "spiral-box-pixalign-evenodd-fill", draw_spiral_eo_pa_box, NULL);
|
||||
|
|
|
|||
|
|
@ -86,12 +86,15 @@ do_strokes (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
stroke_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "stroke", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
stroke (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "stroke", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_cover_sources_and_operators (perf, "stroke", do_stroke, NULL);
|
||||
cairo_perf_cover_sources_and_operators (perf, "strokes", do_strokes, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,15 +52,18 @@ do_subimage_copy (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
subimage_copy_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "subimage-copy", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
subimage_copy (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
cairo_surface_t *image;
|
||||
cairo_t *cr2;
|
||||
|
||||
if (! cairo_perf_can_run (perf, "subimage-copy", NULL))
|
||||
return;
|
||||
|
||||
cairo_set_source_rgb (cr, 0, 0, 1); /* blue */
|
||||
cairo_paint (cr);
|
||||
|
||||
|
|
|
|||
|
|
@ -141,12 +141,15 @@ tessellate_256 (cairo_t *cr, int width, int height, int loops)
|
|||
return do_tessellate (cr, 256, loops);
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
tessellate_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "tessellate", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
tessellate (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "tessellate", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "tessellate-16", tessellate_16, NULL);
|
||||
cairo_perf_run (perf, "tessellate-64", tessellate_64, NULL);
|
||||
cairo_perf_run (perf, "tessellate-256", tessellate_256, NULL);
|
||||
|
|
|
|||
|
|
@ -56,11 +56,14 @@ do_text (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
text_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "text", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
text (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "text", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_cover_sources_and_operators (perf, "text", do_text, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,14 +43,17 @@ do_twin (cairo_t *cr,
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
twin_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "twin", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
twin (cairo_perf_t *perf,
|
||||
cairo_t *cr,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "twin", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "twin", do_twin, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,11 +60,14 @@ do_unaligned_clip (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
unaligned_clip_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "unaligned-clip", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
unaligned_clip (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "unaligned-clip", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "unaligned-clip", do_unaligned_clip, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,11 +102,14 @@ do_wave (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
wave_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "wave", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
wave (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "wave", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "wave", do_wave, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -170,12 +170,15 @@ do_wide_fills (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
wide_fills_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "wide-fills", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
wide_fills (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "wide-fills", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "wide-fills-halign", do_wide_fills_ha, NULL);
|
||||
cairo_perf_run (perf, "wide-fills-valign", do_wide_fills_va, NULL);
|
||||
cairo_perf_run (perf, "wide-fills-horizontal", do_wide_fills_h, NULL);
|
||||
|
|
|
|||
|
|
@ -169,12 +169,15 @@ do_wide_strokes (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
wide_strokes_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "wide-strokes", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
wide_strokes (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "wide-strokes", NULL))
|
||||
return;
|
||||
|
||||
cairo_set_source_rgb (cr, 1., 1., 1.);
|
||||
|
||||
cairo_perf_run (perf, "wide-strokes-halign", do_wide_strokes_ha, NULL);
|
||||
|
|
|
|||
|
|
@ -134,12 +134,15 @@ do_world_map_both (cairo_t *cr, int width, int height, int loops)
|
|||
return do_world_map (cr, width, height, loops, FILL | STROKE);
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
world_map_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "world-map", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
world_map (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "world-map", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "world-map-stroke", do_world_map_stroke, NULL);
|
||||
cairo_perf_run (perf, "world-map-fill", do_world_map_fill, NULL);
|
||||
cairo_perf_run (perf, "world-map", do_world_map_both, NULL);
|
||||
|
|
|
|||
|
|
@ -84,11 +84,15 @@ zrusin_another_fill (cairo_t *cr, int width, int height, int loops)
|
|||
return cairo_perf_timer_elapsed ();
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
zrusin_enabled (cairo_perf_t *perf)
|
||||
{
|
||||
return cairo_perf_can_run (perf, "zrusin", NULL);
|
||||
}
|
||||
|
||||
void
|
||||
zrusin (cairo_perf_t *perf, cairo_t *cr, int width, int height)
|
||||
{
|
||||
if (! cairo_perf_can_run (perf, "zrusin", NULL))
|
||||
return;
|
||||
|
||||
cairo_perf_run (perf, "zrusin-another-tessellate", zrusin_another_tessellate, NULL);
|
||||
cairo_perf_run (perf, "zrusin-another-fill", zrusin_another_fill, NULL);
|
||||
|
|
|
|||
|
|
@ -54,6 +54,7 @@ cairo_private = \
|
|||
cairoint.h \
|
||||
cairo-analysis-surface-private.h \
|
||||
cairo-arc-private.h \
|
||||
cairo-array-private.h \
|
||||
cairo-atomic-private.h \
|
||||
cairo-backend-private.h \
|
||||
cairo-box-private.h \
|
||||
|
|
@ -62,6 +63,7 @@ cairo_private = \
|
|||
cairo-clip-private.h \
|
||||
cairo-combsort-private.h \
|
||||
cairo-compiler-private.h \
|
||||
cairo-compositor-private.h \
|
||||
cairo-contour-private.h \
|
||||
cairo-composite-rectangles-private.h \
|
||||
cairo-default-context-private.h \
|
||||
|
|
@ -97,10 +99,11 @@ cairo_private = \
|
|||
cairo-scaled-font-private.h \
|
||||
cairo-slope-private.h \
|
||||
cairo-spans-private.h \
|
||||
cairo-spans-compositor-private.h \
|
||||
cairo-stroke-dash-private.h \
|
||||
cairo-surface-fallback-private.h \
|
||||
cairo-surface-private.h \
|
||||
cairo-surface-clipper-private.h \
|
||||
cairo-surface-fallback-private.h \
|
||||
cairo-surface-observer-private.h \
|
||||
cairo-surface-offset-private.h \
|
||||
cairo-surface-subsurface-private.h \
|
||||
|
|
@ -108,6 +111,8 @@ cairo_private = \
|
|||
cairo-surface-wrapper-private.h \
|
||||
cairo-time-private.h \
|
||||
cairo-types-private.h \
|
||||
cairo-traps-private.h \
|
||||
cairo-tristrip-private.h \
|
||||
cairo-user-font-private.h \
|
||||
cairo-wideint-private.h \
|
||||
cairo-wideint-type-private.h \
|
||||
|
|
@ -134,11 +139,13 @@ cairo_sources = \
|
|||
cairo-clip-surface.c \
|
||||
cairo-color.c \
|
||||
cairo-composite-rectangles.c \
|
||||
cairo-compositor.c \
|
||||
cairo-contour.c \
|
||||
cairo-debug.c \
|
||||
cairo-default-context.c \
|
||||
cairo-device.c \
|
||||
cairo-error.c \
|
||||
cairo-fallback-compositor.c \
|
||||
cairo-fixed.c \
|
||||
cairo-font-face.c \
|
||||
cairo-font-face-twin.c \
|
||||
|
|
@ -149,14 +156,19 @@ cairo_sources = \
|
|||
cairo-gstate.c \
|
||||
cairo-hash.c \
|
||||
cairo-hull.c \
|
||||
cairo-image-compositor.c \
|
||||
cairo-image-info.c \
|
||||
cairo-image-source.c \
|
||||
cairo-image-surface.c \
|
||||
cairo-lzw.c \
|
||||
cairo-matrix.c \
|
||||
cairo-mask-compositor.c \
|
||||
cairo-mesh-pattern-rasterizer.c \
|
||||
cairo-mime-surface.c \
|
||||
cairo-misc.c \
|
||||
cairo-mono-scan-converter.c \
|
||||
cairo-mutex.c \
|
||||
cairo-no-compositor.c \
|
||||
cairo-observer.c \
|
||||
cairo-output-stream.c \
|
||||
cairo-paginated-surface.c \
|
||||
|
|
@ -168,6 +180,7 @@ cairo_sources = \
|
|||
cairo-path-stroke.c \
|
||||
cairo-path-stroke-boxes.c \
|
||||
cairo-path-stroke-polygon.c \
|
||||
cairo-path-stroke-tristrip.c \
|
||||
cairo-pattern.c \
|
||||
cairo-pen.c \
|
||||
cairo-polygon.c \
|
||||
|
|
@ -181,12 +194,13 @@ cairo_sources = \
|
|||
cairo-scaled-font.c \
|
||||
cairo-slope.c \
|
||||
cairo-spans.c \
|
||||
cairo-spans-compositor.c \
|
||||
cairo-spline.c \
|
||||
cairo-stroke-dash.c \
|
||||
cairo-stroke-style.c \
|
||||
cairo-surface.c \
|
||||
cairo-surface-fallback.c \
|
||||
cairo-surface-clipper.c \
|
||||
cairo-surface-fallback.c \
|
||||
cairo-surface-observer.c \
|
||||
cairo-surface-offset.c \
|
||||
cairo-surface-snapshot.c \
|
||||
|
|
@ -195,8 +209,12 @@ cairo_sources = \
|
|||
cairo-system.c \
|
||||
cairo-time.c \
|
||||
cairo-tor-scan-converter.c \
|
||||
cairo-tor22-scan-converter.c \
|
||||
cairo-clip-tor-scan-converter.c \
|
||||
cairo-toy-font-face.c \
|
||||
cairo-traps.c \
|
||||
cairo-tristrip.c \
|
||||
cairo-traps-compositor.c \
|
||||
cairo-unicode.c \
|
||||
cairo-user-font.c \
|
||||
cairo-version.c \
|
||||
|
|
@ -253,18 +271,15 @@ cairo_ft_sources = cairo-ft-font.c
|
|||
|
||||
# These are private, even though they look like public headers
|
||||
cairo_test_surfaces_private = \
|
||||
test-fallback-surface.h \
|
||||
test-fallback16-surface.h \
|
||||
test-null-surface.h \
|
||||
test-compositor-surface.h \
|
||||
test-null-compositor-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-compositor-surface.c \
|
||||
test-null-compositor-surface.c \
|
||||
test-base-compositor-surface.c \
|
||||
test-paginated-surface.c \
|
||||
test-wrapping-surface.c \
|
||||
$(NULL)
|
||||
|
||||
cairo_xlib_headers = cairo-xlib.h
|
||||
|
|
@ -275,7 +290,11 @@ cairo_xlib_private = \
|
|||
$(NULL)
|
||||
cairo_xlib_sources = \
|
||||
cairo-xlib-display.c \
|
||||
cairo-xlib-core-compositor.c \
|
||||
cairo-xlib-fallback-compositor.c \
|
||||
cairo-xlib-render-compositor.c \
|
||||
cairo-xlib-screen.c \
|
||||
cairo-xlib-source.c \
|
||||
cairo-xlib-surface.c \
|
||||
cairo-xlib-visual.c \
|
||||
cairo-xlib-xcb-surface.c \
|
||||
|
|
@ -343,7 +362,10 @@ cairo_gl_sources = cairo-gl-composite.c \
|
|||
cairo-gl-glyphs.c \
|
||||
cairo-gl-gradient.c \
|
||||
cairo-gl-info.c \
|
||||
cairo-gl-operand.c \
|
||||
cairo-gl-shaders.c \
|
||||
cairo-gl-spans-compositor.c \
|
||||
cairo-gl-traps-compositor.c \
|
||||
cairo-gl-surface.c
|
||||
|
||||
cairo_glesv2_headers = $(cairo_gl_headers)
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface,
|
|||
cairo_analysis_surface_t *tmp;
|
||||
cairo_surface_t *source, *proxy;
|
||||
cairo_matrix_t p2d;
|
||||
cairo_status_t status;
|
||||
cairo_status_t status, analysis_status;
|
||||
|
||||
assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
|
||||
surface_pattern = (const cairo_surface_pattern_t *) pattern;
|
||||
|
|
@ -175,11 +175,16 @@ _analyze_recording_surface_pattern (cairo_analysis_surface_t *surface,
|
|||
if (_cairo_surface_is_subsurface (source))
|
||||
source = _cairo_surface_subsurface_get_target (source);
|
||||
|
||||
status = _cairo_recording_surface_replay_and_create_regions (source, &tmp->base);
|
||||
status = _cairo_recording_surface_replay_and_create_regions (source,
|
||||
&tmp->base);
|
||||
analysis_status = tmp->has_unsupported ? CAIRO_INT_STATUS_IMAGE_FALLBACK : CAIRO_INT_STATUS_SUCCESS;
|
||||
detach_proxy (proxy);
|
||||
cairo_surface_destroy (&tmp->base);
|
||||
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
return analysis_status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
|
|
@ -548,8 +553,7 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface,
|
|||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
const cairo_clip_t *clip,
|
||||
int *remaining_glyphs)
|
||||
const cairo_clip_t *clip)
|
||||
{
|
||||
cairo_analysis_surface_t *surface = abstract_surface;
|
||||
cairo_int_status_t status, backend_status;
|
||||
|
|
@ -562,8 +566,7 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface,
|
|||
source,
|
||||
glyphs, num_glyphs,
|
||||
scaled_font,
|
||||
clip,
|
||||
remaining_glyphs);
|
||||
clip);
|
||||
if (_cairo_int_status_is_error (backend_status))
|
||||
return backend_status;
|
||||
}
|
||||
|
|
@ -652,21 +655,14 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface,
|
|||
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,
|
||||
clip,
|
||||
&remaining_glyphs);
|
||||
clip);
|
||||
if (_cairo_int_status_is_error (backend_status))
|
||||
return backend_status;
|
||||
|
||||
glyphs += num_glyphs - remaining_glyphs;
|
||||
num_glyphs = remaining_glyphs;
|
||||
if (remaining_glyphs == 0)
|
||||
backend_status = CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (backend_status == CAIRO_INT_STATUS_ANALYZE_RECORDING_SURFACE_PATTERN)
|
||||
|
|
@ -701,35 +697,26 @@ static const cairo_surface_backend_t cairo_analysis_surface_backend = {
|
|||
NULL, /* create_similar_image */
|
||||
NULL, /* map_to_image */
|
||||
NULL, /* unmap */
|
||||
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
NULL, /* acquire_dest_image */
|
||||
NULL, /* release_dest_image */
|
||||
NULL, /* clone_similar */
|
||||
NULL, /* composite */
|
||||
NULL, /* fill_rectangles */
|
||||
NULL, /* composite_trapezoids */
|
||||
NULL, /* create_span_renderer */
|
||||
NULL, /* check_span_renderer */
|
||||
NULL, /* snapshot */
|
||||
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
|
||||
_cairo_analysis_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 */
|
||||
|
||||
_cairo_analysis_surface_paint,
|
||||
_cairo_analysis_surface_mask,
|
||||
_cairo_analysis_surface_stroke,
|
||||
_cairo_analysis_surface_fill,
|
||||
_cairo_analysis_surface_show_glyphs,
|
||||
NULL, /* snapshot */
|
||||
NULL, /* is_similar */
|
||||
NULL, /* fill_stroke */
|
||||
NULL, /* create_solid_pattern_surface */
|
||||
NULL, /* can_repaint_solid_pattern_surface */
|
||||
_cairo_analysis_surface_show_glyphs,
|
||||
_cairo_analysis_surface_has_show_text_glyphs,
|
||||
_cairo_analysis_surface_show_text_glyphs
|
||||
};
|
||||
|
|
@ -891,48 +878,38 @@ typedef cairo_int_status_t
|
|||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
const cairo_clip_t *clip,
|
||||
int *remaining_glyphs);
|
||||
const cairo_clip_t *clip);
|
||||
|
||||
static const cairo_surface_backend_t cairo_null_surface_backend = {
|
||||
CAIRO_INTERNAL_SURFACE_TYPE_NULL,
|
||||
NULL, /* finish */
|
||||
|
||||
_cairo_default_context_create, /* XXX */
|
||||
NULL, /* only accessed through the surface functions */
|
||||
|
||||
NULL, /* create_similar */
|
||||
NULL, /* create similar image */
|
||||
NULL, /* map to image */
|
||||
NULL, /* unmap image*/
|
||||
|
||||
NULL, /* acquire_source_image */
|
||||
NULL, /* release_source_image */
|
||||
NULL, /* acquire_dest_image */
|
||||
NULL, /* release_dest_image */
|
||||
NULL, /* clone_similar */
|
||||
NULL, /* composite */
|
||||
NULL, /* fill_rectangles */
|
||||
NULL, /* composite_trapezoids */
|
||||
NULL, /* create_span_renderer */
|
||||
NULL, /* check_span_renderer */
|
||||
NULL, /* snapshot */
|
||||
|
||||
NULL, /* copy_page */
|
||||
NULL, /* show_page */
|
||||
|
||||
NULL, /* get_extents */
|
||||
NULL, /* old_show_glyphs */
|
||||
NULL, /* get_font_options */
|
||||
|
||||
NULL, /* flush */
|
||||
NULL, /* mark_dirty_rectangle */
|
||||
NULL, /* scaled_font_fini */
|
||||
NULL, /* scaled_glyph_fini */
|
||||
|
||||
(_paint_func) _return_success, /* paint */
|
||||
(_mask_func) _return_success, /* mask */
|
||||
(_stroke_func) _return_success, /* stroke */
|
||||
(_fill_func) _return_success, /* fill */
|
||||
(_show_glyphs_func) _return_success, /* show_glyphs */
|
||||
NULL, /* snapshot */
|
||||
NULL, /* is_similar */
|
||||
NULL, /* fill_stroke */
|
||||
NULL, /* create_solid_pattern_surface */
|
||||
NULL, /* can_repaint_solid_pattern_surface */
|
||||
(_show_glyphs_func) _return_success, /* show_glyphs */
|
||||
NULL, /* has_show_text_glyphs */
|
||||
NULL /* show_text_glyphs */
|
||||
};
|
||||
|
|
|
|||
90
src/cairo-array-private.h
Normal file
90
src/cairo-array-private.h
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2002 University of Southern California
|
||||
* 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_ARRAY_PRIVATE_H
|
||||
#define CAIRO_ARRAY_PRIVATE_H
|
||||
|
||||
#include "cairo-compiler-private.h"
|
||||
#include "cairo-types-private.h"
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
/* cairo-array.c structures and functions */
|
||||
|
||||
cairo_private void
|
||||
_cairo_array_init (cairo_array_t *array, unsigned int element_size);
|
||||
|
||||
cairo_private void
|
||||
_cairo_array_fini (cairo_array_t *array);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_array_grow_by (cairo_array_t *array, unsigned int additional);
|
||||
|
||||
cairo_private void
|
||||
_cairo_array_truncate (cairo_array_t *array, unsigned int num_elements);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_array_append (cairo_array_t *array, const void *element);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_array_append_multiple (cairo_array_t *array,
|
||||
const void *elements,
|
||||
unsigned int num_elements);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_array_allocate (cairo_array_t *array,
|
||||
unsigned int num_elements,
|
||||
void **elements);
|
||||
|
||||
cairo_private void *
|
||||
_cairo_array_index (cairo_array_t *array, unsigned int index);
|
||||
|
||||
cairo_private const void *
|
||||
_cairo_array_index_const (const cairo_array_t *array, unsigned int index);
|
||||
|
||||
cairo_private void
|
||||
_cairo_array_copy_element (const cairo_array_t *array, unsigned int index, void *dst);
|
||||
|
||||
cairo_private unsigned int
|
||||
_cairo_array_num_elements (const cairo_array_t *array);
|
||||
|
||||
cairo_private unsigned int
|
||||
_cairo_array_size (const cairo_array_t *array);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif /* CAIRO_ARRAY_PRIVATE_H */
|
||||
|
|
@ -37,6 +37,7 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
#include "cairo-array-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
/**
|
||||
|
|
@ -385,11 +386,11 @@ _cairo_user_data_array_fini (cairo_user_data_array_t *array)
|
|||
cairo_user_data_slot_t *slots;
|
||||
|
||||
slots = _cairo_array_index (array, 0);
|
||||
do {
|
||||
if (slots->user_data != NULL && slots->destroy != NULL)
|
||||
slots->destroy (slots->user_data);
|
||||
slots++;
|
||||
} while (--num_slots);
|
||||
while (num_slots--) {
|
||||
cairo_user_data_slot_t *s = &slots[num_slots];
|
||||
if (s->user_data != NULL && s->destroy != NULL)
|
||||
s->destroy (s->user_data);
|
||||
}
|
||||
}
|
||||
|
||||
_cairo_array_fini (array);
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ _cairo_atomic_ptr_get (void **x)
|
|||
#endif
|
||||
|
||||
# define _cairo_atomic_int_inc(x) ((void) __sync_fetch_and_add(x, 1))
|
||||
# define _cairo_atomic_int_dec(x) ((void) __sync_fetch_and_add(x, -1))
|
||||
# define _cairo_atomic_int_dec_and_test(x) (__sync_fetch_and_add(x, -1) == 1)
|
||||
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) __sync_bool_compare_and_swap (x, oldv, newv)
|
||||
# define _cairo_atomic_int_cmpxchg_return_old(x, oldv, newv) __sync_val_compare_and_swap (x, oldv, newv)
|
||||
|
|
@ -111,6 +112,7 @@ typedef AO_t cairo_atomic_int_t;
|
|||
# define _cairo_atomic_int_get(x) (AO_load_full (x))
|
||||
|
||||
# define _cairo_atomic_int_inc(x) ((void) AO_fetch_and_add1_full(x))
|
||||
# define _cairo_atomic_int_dec(x) ((void) AO_fetch_and_sub1_full(x))
|
||||
# define _cairo_atomic_int_dec_and_test(x) (AO_fetch_and_sub1_full(x) == 1)
|
||||
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) AO_compare_and_swap_full(x, oldv, newv)
|
||||
|
||||
|
|
@ -140,6 +142,7 @@ typedef int32_t cairo_atomic_int_t;
|
|||
# define _cairo_atomic_int_get(x) (OSMemoryBarrier(), *(x))
|
||||
|
||||
# define _cairo_atomic_int_inc(x) ((void) OSAtomicIncrement32Barrier (x))
|
||||
# define _cairo_atomic_int_dec(x) ((void) OSAtomicDecrement32Barrier (x))
|
||||
# define _cairo_atomic_int_dec_and_test(x) (OSAtomicDecrement32Barrier (x) == 0)
|
||||
# define _cairo_atomic_int_cmpxchg(x, oldv, newv) OSAtomicCompareAndSwap32Barrier(oldv, newv, x)
|
||||
|
||||
|
|
@ -178,6 +181,8 @@ typedef cairo_atomic_intptr_t cairo_atomic_int_t;
|
|||
cairo_private void
|
||||
_cairo_atomic_int_inc (cairo_atomic_int_t *x);
|
||||
|
||||
#define _cairo_atomic_int_dec(x) _cairo_atomic_int_dec_and_test(x)
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_atomic_int_dec_and_test (cairo_atomic_int_t *x);
|
||||
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "cairo-error-private.h"
|
||||
#include "cairo-combsort-private.h"
|
||||
#include "cairo-list-private.h"
|
||||
#include "cairo-traps-private.h"
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
|
|
@ -740,7 +741,7 @@ _cairo_bentley_ottmann_tessellate_boxes (const cairo_boxes_t *in,
|
|||
rectangle_t *stack_rectangles_ptrs[ARRAY_LENGTH (stack_rectangles) + 3];
|
||||
rectangle_t *rectangles, **rectangles_ptrs;
|
||||
rectangle_t *stack_rectangles_chain[CAIRO_STACK_ARRAY_LENGTH (rectangle_t *) ];
|
||||
rectangle_t **rectangles_chain;
|
||||
rectangle_t **rectangles_chain = NULL;
|
||||
const struct _cairo_boxes_chunk *chunk;
|
||||
cairo_status_t status;
|
||||
int i, j, y_min, y_max;
|
||||
|
|
@ -789,6 +790,7 @@ _cairo_bentley_ottmann_tessellate_boxes (const cairo_boxes_t *in,
|
|||
y_max = _cairo_fixed_integer_floor (y_max) + 1;
|
||||
y_max -= y_min;
|
||||
|
||||
if (y_max < in->num_boxes) {
|
||||
rectangles_chain = stack_rectangles_chain;
|
||||
if (y_max > ARRAY_LENGTH (stack_rectangles_chain)) {
|
||||
rectangles_chain = _cairo_malloc_ab (y_max, sizeof (rectangle_t *));
|
||||
|
|
@ -796,6 +798,7 @@ _cairo_bentley_ottmann_tessellate_boxes (const cairo_boxes_t *in,
|
|||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
memset (rectangles_chain, 0, y_max * sizeof (rectangle_t*));
|
||||
}
|
||||
|
||||
rectangles = stack_rectangles;
|
||||
rectangles_ptrs = stack_rectangles_ptrs;
|
||||
|
|
@ -839,13 +842,18 @@ _cairo_bentley_ottmann_tessellate_boxes (const cairo_boxes_t *in,
|
|||
rectangles[j].top = box[i].p1.y;
|
||||
rectangles[j].bottom = box[i].p2.y;
|
||||
|
||||
if (rectangles_chain) {
|
||||
h = _cairo_fixed_integer_floor (box[i].p1.y) - y_min;
|
||||
rectangles[j].left.next = (edge_t *)rectangles_chain[h];
|
||||
rectangles_chain[h] = &rectangles[j];
|
||||
} else {
|
||||
rectangles_ptrs[j+2] = &rectangles[j];
|
||||
}
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
if (rectangles_chain) {
|
||||
j = 2;
|
||||
for (y_min = 0; y_min < y_max; y_min++) {
|
||||
rectangle_t *r;
|
||||
|
|
@ -859,8 +867,13 @@ _cairo_bentley_ottmann_tessellate_boxes (const cairo_boxes_t *in,
|
|||
if (rectangles_chain != stack_rectangles_chain)
|
||||
free (rectangles_chain);
|
||||
|
||||
j -= 2;
|
||||
} else {
|
||||
_rectangle_sort (rectangles_ptrs + 2, j);
|
||||
}
|
||||
|
||||
_cairo_boxes_clear (out);
|
||||
status = _cairo_bentley_ottmann_tessellate_rectangular (rectangles_ptrs+2, j-2,
|
||||
status = _cairo_bentley_ottmann_tessellate_rectangular (rectangles_ptrs+2, j,
|
||||
fill_rule,
|
||||
FALSE, out);
|
||||
if (rectangles != stack_rectangles)
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "cairo-boxes-private.h"
|
||||
#include "cairo-combsort-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-traps-private.h"
|
||||
|
||||
typedef struct _cairo_bo_edge cairo_bo_edge_t;
|
||||
typedef struct _cairo_bo_trap cairo_bo_trap_t;
|
||||
|
|
@ -436,74 +437,6 @@ _cairo_bentley_ottmann_tessellate_rectilinear (cairo_bo_event_t **start_events
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_bentley_ottmann_tessellate_rectilinear_polygon (cairo_traps_t *traps,
|
||||
const cairo_polygon_t *polygon,
|
||||
cairo_fill_rule_t fill_rule)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_bo_event_t stack_events[CAIRO_STACK_ARRAY_LENGTH (cairo_bo_event_t)];
|
||||
cairo_bo_event_t *events;
|
||||
cairo_bo_event_t *stack_event_ptrs[ARRAY_LENGTH (stack_events) + 1];
|
||||
cairo_bo_event_t **event_ptrs;
|
||||
cairo_bo_edge_t stack_edges[ARRAY_LENGTH (stack_events)];
|
||||
cairo_bo_edge_t *edges;
|
||||
int num_events;
|
||||
int i, j;
|
||||
|
||||
if (unlikely (polygon->num_edges == 0))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
num_events = 2 * polygon->num_edges;
|
||||
|
||||
events = stack_events;
|
||||
event_ptrs = stack_event_ptrs;
|
||||
edges = stack_edges;
|
||||
if (num_events > ARRAY_LENGTH (stack_events)) {
|
||||
events = _cairo_malloc_ab_plus_c (num_events,
|
||||
sizeof (cairo_bo_event_t) +
|
||||
sizeof (cairo_bo_edge_t) +
|
||||
sizeof (cairo_bo_event_t *),
|
||||
sizeof (cairo_bo_event_t *));
|
||||
if (unlikely (events == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
event_ptrs = (cairo_bo_event_t **) (events + num_events);
|
||||
edges = (cairo_bo_edge_t *) (event_ptrs + num_events + 1);
|
||||
}
|
||||
|
||||
for (i = j = 0; i < polygon->num_edges; i++) {
|
||||
edges[i].edge = polygon->edges[i];
|
||||
edges[i].deferred_trap.right = NULL;
|
||||
edges[i].prev = NULL;
|
||||
edges[i].next = NULL;
|
||||
|
||||
event_ptrs[j] = &events[j];
|
||||
events[j].type = CAIRO_BO_EVENT_TYPE_START;
|
||||
events[j].point.y = polygon->edges[i].top;
|
||||
events[j].point.x = polygon->edges[i].line.p1.x;
|
||||
events[j].edge = &edges[i];
|
||||
j++;
|
||||
|
||||
event_ptrs[j] = &events[j];
|
||||
events[j].type = CAIRO_BO_EVENT_TYPE_STOP;
|
||||
events[j].point.y = polygon->edges[i].bottom;
|
||||
events[j].point.x = polygon->edges[i].line.p1.x;
|
||||
events[j].edge = &edges[i];
|
||||
j++;
|
||||
}
|
||||
|
||||
status = _cairo_bentley_ottmann_tessellate_rectilinear (event_ptrs, j,
|
||||
fill_rule,
|
||||
TRUE, traps);
|
||||
if (events != stack_events)
|
||||
free (events);
|
||||
|
||||
traps->is_rectilinear = TRUE;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_bentley_ottmann_tessellate_rectilinear_polygon_to_boxes (const cairo_polygon_t *polygon,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "cairo-error-private.h"
|
||||
#include "cairo-freelist-private.h"
|
||||
#include "cairo-combsort-private.h"
|
||||
#include "cairo-traps-private.h"
|
||||
|
||||
#define DEBUG_PRINT_STATE 0
|
||||
#define DEBUG_EVENTS 0
|
||||
|
|
@ -1301,7 +1302,14 @@ event_log (const char *fmt, ...)
|
|||
static inline cairo_bool_t
|
||||
edges_colinear (const cairo_bo_edge_t *a, const cairo_bo_edge_t *b)
|
||||
{
|
||||
if (_line_equal (&a->edge.line, &b->edge.line))
|
||||
unsigned p;
|
||||
|
||||
p = 0;
|
||||
p |= (a->edge.line.p1.x == b->edge.line.p1.x) << 0;
|
||||
p |= (a->edge.line.p1.y == b->edge.line.p1.y) << 1;
|
||||
p |= (a->edge.line.p2.x == b->edge.line.p2.x) << 3;
|
||||
p |= (a->edge.line.p2.y == b->edge.line.p2.y) << 4;
|
||||
if (p == ((1 << 0) | (1 << 1) | (1 << 3) | (1 << 4)))
|
||||
return TRUE;
|
||||
|
||||
if (_slope_compare (a, b))
|
||||
|
|
@ -1310,8 +1318,9 @@ edges_colinear (const cairo_bo_edge_t *a, const cairo_bo_edge_t *b)
|
|||
/* The choice of y is not truly arbitrary since we must guarantee that it
|
||||
* is greater than the start of either line.
|
||||
*/
|
||||
if (a->edge.line.p1.y == b->edge.line.p1.y) {
|
||||
return a->edge.line.p1.x == b->edge.line.p1.x;
|
||||
if (p != 0) {
|
||||
/* colinear if either end-point are coincident */
|
||||
return ((p >> 1) & p) != 0;
|
||||
} else if (a->edge.line.p1.y < b->edge.line.p1.y) {
|
||||
return edge_compare_for_y_against_x (b,
|
||||
a->edge.line.p1.y,
|
||||
|
|
@ -1377,8 +1386,9 @@ _cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t *left,
|
|||
if (left->deferred_trap.right == right)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
assert (right);
|
||||
if (left->deferred_trap.right != NULL) {
|
||||
if (right != NULL && edges_colinear (left->deferred_trap.right, right))
|
||||
if (edges_colinear (left->deferred_trap.right, right))
|
||||
{
|
||||
/* continuation on right, so just swap edges */
|
||||
left->deferred_trap.right = right;
|
||||
|
|
@ -1390,7 +1400,7 @@ _cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t *left,
|
|||
return status;
|
||||
}
|
||||
|
||||
if (right != NULL && ! edges_colinear (left, right)) {
|
||||
if (! edges_colinear (left, right)) {
|
||||
left->deferred_trap.top = top;
|
||||
left->deferred_trap.right = right;
|
||||
|
||||
|
|
@ -1406,114 +1416,52 @@ _cairo_bo_edge_start_or_continue_trap (cairo_bo_edge_t *left,
|
|||
}
|
||||
|
||||
static inline cairo_status_t
|
||||
_active_edges_to_traps (cairo_bo_edge_t *left,
|
||||
_active_edges_to_traps (cairo_bo_edge_t *pos,
|
||||
int32_t top,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
unsigned mask,
|
||||
cairo_traps_t *traps)
|
||||
{
|
||||
cairo_bo_edge_t *right;
|
||||
cairo_bo_edge_t *left;
|
||||
cairo_status_t status;
|
||||
int in_out;
|
||||
|
||||
|
||||
#if DEBUG_PRINT_STATE
|
||||
printf ("Processing active edges for %x\n", top);
|
||||
#endif
|
||||
|
||||
if (fill_rule == CAIRO_FILL_RULE_WINDING) {
|
||||
while (left != NULL) {
|
||||
int in_out;
|
||||
|
||||
/* Greedily search for the closing edge, so that we generate the
|
||||
* maximal span width with the minimal number of trapezoids.
|
||||
*/
|
||||
in_out = left->edge.dir;
|
||||
|
||||
/* Check if there is a co-linear edge with an existing trap */
|
||||
right = left->next;
|
||||
if (left->deferred_trap.right == NULL) {
|
||||
while (right != NULL && right->deferred_trap.right == NULL)
|
||||
right = right->next;
|
||||
|
||||
if (right != NULL && edges_colinear (left, right)) {
|
||||
in_out = 0;
|
||||
left = pos;
|
||||
while (pos != NULL) {
|
||||
if (pos != left && pos->deferred_trap.right) {
|
||||
if (edges_colinear (left, pos)) {
|
||||
/* continuation on left */
|
||||
left->deferred_trap = right->deferred_trap;
|
||||
right->deferred_trap.right = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* End all subsumed traps */
|
||||
right = left->next;
|
||||
while (right != NULL) {
|
||||
if (right->deferred_trap.right != NULL) {
|
||||
status = _cairo_bo_edge_end_trap (right, top, traps);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
|
||||
in_out += right->edge.dir;
|
||||
if (in_out == 0) {
|
||||
cairo_bo_edge_t *next;
|
||||
cairo_bool_t skip = FALSE;
|
||||
|
||||
/* skip co-linear edges */
|
||||
next = right->next;
|
||||
if (next != NULL)
|
||||
skip = edges_colinear (right, next);
|
||||
|
||||
if (! skip)
|
||||
break;
|
||||
}
|
||||
|
||||
right = right->next;
|
||||
}
|
||||
|
||||
status = _cairo_bo_edge_start_or_continue_trap (left, right,
|
||||
top, traps);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
left = right;
|
||||
if (left != NULL)
|
||||
left = left->next;
|
||||
}
|
||||
assert (left->deferred_trap.right == NULL);
|
||||
left->deferred_trap = pos->deferred_trap;
|
||||
pos->deferred_trap.right = NULL;
|
||||
} else {
|
||||
while (left != NULL) {
|
||||
int in_out = 0;
|
||||
|
||||
right = left->next;
|
||||
while (right != NULL) {
|
||||
if (right->deferred_trap.right != NULL) {
|
||||
status = _cairo_bo_edge_end_trap (right, top, traps);
|
||||
status = _cairo_bo_edge_end_trap (pos, top, traps);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if ((in_out++ & 1) == 0) {
|
||||
cairo_bo_edge_t *next;
|
||||
cairo_bool_t skip = FALSE;
|
||||
|
||||
in_out += pos->edge.dir;
|
||||
if ((in_out & mask) == 0) {
|
||||
/* skip co-linear edges */
|
||||
next = right->next;
|
||||
if (next != NULL)
|
||||
skip = edges_colinear (right, next);
|
||||
|
||||
if (! skip)
|
||||
break;
|
||||
}
|
||||
|
||||
right = right->next;
|
||||
}
|
||||
|
||||
status = _cairo_bo_edge_start_or_continue_trap (left, right,
|
||||
if (pos->next == NULL || ! edges_colinear (pos, pos->next)) {
|
||||
status = _cairo_bo_edge_start_or_continue_trap (left, pos,
|
||||
top, traps);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
left = right;
|
||||
if (left != NULL)
|
||||
left = left->next;
|
||||
left = pos->next;
|
||||
}
|
||||
}
|
||||
|
||||
pos = pos->next;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -1524,7 +1472,7 @@ _active_edges_to_traps (cairo_bo_edge_t *left,
|
|||
static cairo_status_t
|
||||
_cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t **start_events,
|
||||
int num_events,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
unsigned fill_rule,
|
||||
cairo_traps_t *traps,
|
||||
int *num_intersections)
|
||||
{
|
||||
|
|
@ -1536,6 +1484,12 @@ _cairo_bentley_ottmann_tessellate_bo_edges (cairo_bo_event_t **start_events,
|
|||
cairo_bo_edge_t *left, *right;
|
||||
cairo_bo_edge_t *e1, *e2;
|
||||
|
||||
/* convert the fill_rule into a winding mask */
|
||||
if (fill_rule == CAIRO_FILL_RULE_WINDING)
|
||||
fill_rule = (unsigned) -1;
|
||||
else
|
||||
fill_rule = 1;
|
||||
|
||||
#if DEBUG_EVENTS
|
||||
{
|
||||
int i;
|
||||
|
|
|
|||
|
|
@ -1397,6 +1397,7 @@ render_rows (cairo_botor_scan_converter_t *self,
|
|||
|
||||
if (x > prev_x) {
|
||||
spans[num_spans].x = prev_x;
|
||||
spans[num_spans].inverse = 0;
|
||||
spans[num_spans].coverage = AREA_TO_ALPHA (cover);
|
||||
++num_spans;
|
||||
}
|
||||
|
|
@ -1413,12 +1414,14 @@ render_rows (cairo_botor_scan_converter_t *self,
|
|||
|
||||
if (prev_x <= self->xmax) {
|
||||
spans[num_spans].x = prev_x;
|
||||
spans[num_spans].inverse = 0;
|
||||
spans[num_spans].coverage = AREA_TO_ALPHA (cover);
|
||||
++num_spans;
|
||||
}
|
||||
|
||||
if (cover && prev_x < self->xmax) {
|
||||
spans[num_spans].x = self->xmax;
|
||||
spans[num_spans].inverse = 1;
|
||||
spans[num_spans].coverage = 0;
|
||||
++num_spans;
|
||||
}
|
||||
|
|
@ -2179,8 +2182,6 @@ _cairo_botor_scan_converter_init (cairo_botor_scan_converter_t *self,
|
|||
cairo_fill_rule_t fill_rule)
|
||||
{
|
||||
self->base.destroy = _cairo_botor_scan_converter_destroy;
|
||||
self->base.add_edge = _cairo_botor_scan_converter_add_edge;
|
||||
self->base.add_polygon = _cairo_botor_scan_converter_add_polygon;
|
||||
self->base.generate = _cairo_botor_scan_converter_generate;
|
||||
|
||||
self->extents = *extents;
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include "cairo-types-private.h"
|
||||
#include "cairo-compiler-private.h"
|
||||
#include "cairo-fixed-private.h"
|
||||
|
||||
static inline void
|
||||
_cairo_box_set (cairo_box_t *box,
|
||||
|
|
@ -47,6 +48,15 @@ _cairo_box_set (cairo_box_t *box,
|
|||
box->p2 = *p2;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_cairo_box_from_integers (cairo_box_t *box, int x, int y, int w, int h)
|
||||
{
|
||||
box->p1.x = _cairo_fixed_from_int (x);
|
||||
box->p1.y = _cairo_fixed_from_int (y);
|
||||
box->p2.x = _cairo_fixed_from_int (x + w);
|
||||
box->p2.y = _cairo_fixed_from_int (y + h);
|
||||
}
|
||||
|
||||
/* assumes box->p1 is top-left, p2 bottom-right */
|
||||
static inline void
|
||||
_cairo_box_add_point (cairo_box_t *box,
|
||||
|
|
@ -63,13 +73,49 @@ _cairo_box_add_point (cairo_box_t *box,
|
|||
box->p2.y = point->y;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_cairo_box_add_box (cairo_box_t *box,
|
||||
const cairo_box_t *add)
|
||||
{
|
||||
if (add->p1.x < box->p1.x)
|
||||
box->p1.x = add->p1.x;
|
||||
if (add->p2.x > box->p2.x)
|
||||
box->p2.x = add->p2.x;
|
||||
|
||||
if (add->p1.y < box->p1.y)
|
||||
box->p1.y = add->p1.y;
|
||||
if (add->p2.y > box->p2.y)
|
||||
box->p2.y = add->p2.y;
|
||||
}
|
||||
|
||||
/* assumes box->p1 is top-left, p2 bottom-right */
|
||||
static inline cairo_bool_t
|
||||
_cairo_box_contains_point (cairo_box_t *box,
|
||||
_cairo_box_contains_point (const cairo_box_t *box,
|
||||
const cairo_point_t *point)
|
||||
{
|
||||
return box->p1.x <= point->x && point->x <= box->p2.x &&
|
||||
box->p1.y <= point->y && point->y <= box->p2.y;
|
||||
}
|
||||
|
||||
static inline cairo_bool_t
|
||||
_cairo_box_is_pixel_aligned (const cairo_box_t *box)
|
||||
{
|
||||
#if CAIRO_FIXED_FRAC_BITS <= 8 && 0
|
||||
return ((box->p1.x & CAIRO_FIXED_FRAC_MASK) << 24 |
|
||||
(box->p1.y & CAIRO_FIXED_FRAC_MASK) << 16 |
|
||||
(box->p2.x & CAIRO_FIXED_FRAC_MASK) << 8 |
|
||||
(box->p2.y & CAIRO_FIXED_FRAC_MASK) << 0) == 0;
|
||||
#else /* GCC on i7 prefers this variant (bizarrely according to the profiler) */
|
||||
cairo_fixed_t f;
|
||||
|
||||
f = 0;
|
||||
f |= box->p1.x & CAIRO_FIXED_FRAC_MASK;
|
||||
f |= box->p1.y & CAIRO_FIXED_FRAC_MASK;
|
||||
f |= box->p2.x & CAIRO_FIXED_FRAC_MASK;
|
||||
f |= box->p2.y & CAIRO_FIXED_FRAC_MASK;
|
||||
|
||||
return f == 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* CAIRO_BOX_H */
|
||||
|
|
|
|||
|
|
@ -535,9 +535,33 @@ _cairo_boxes_intersect_with_box (const cairo_boxes_t *boxes,
|
|||
const cairo_box_t *box,
|
||||
cairo_boxes_t *out)
|
||||
{
|
||||
const struct _cairo_boxes_chunk *chunk;
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
int i, j;
|
||||
|
||||
if (out == boxes) { /* inplace update */
|
||||
struct _cairo_boxes_chunk *chunk;
|
||||
|
||||
out->num_boxes = 0;
|
||||
for (chunk = &out->chunks; chunk != NULL; chunk = chunk->next) {
|
||||
for (i = j = 0; i < chunk->count; i++) {
|
||||
cairo_box_t *b = &chunk->base[i];
|
||||
|
||||
b->p1.x = MAX (b->p1.x, box->p1.x);
|
||||
b->p1.y = MAX (b->p1.y, box->p1.y);
|
||||
b->p2.x = MIN (b->p2.x, box->p2.x);
|
||||
b->p2.y = MIN (b->p2.y, box->p2.y);
|
||||
if (b->p1.x < b->p2.x && b->p1.y < b->p2.y) {
|
||||
if (i != j)
|
||||
chunk->base[j] = *b;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
/* XXX unlink empty chains? */
|
||||
chunk->count = j;
|
||||
out->num_boxes += j;
|
||||
}
|
||||
} else {
|
||||
const struct _cairo_boxes_chunk *chunk;
|
||||
|
||||
_cairo_boxes_clear (out);
|
||||
_cairo_boxes_limit (out, box, 1);
|
||||
|
|
@ -550,6 +574,7 @@ _cairo_boxes_intersect_with_box (const cairo_boxes_t *boxes,
|
|||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,11 +42,14 @@
|
|||
|
||||
struct _cairo_boxes_t {
|
||||
cairo_status_t status;
|
||||
|
||||
cairo_box_t limit;
|
||||
const cairo_box_t *limits;
|
||||
int num_limits;
|
||||
|
||||
int num_boxes;
|
||||
unsigned int is_pixel_aligned : 1;
|
||||
|
||||
unsigned int is_pixel_aligned;
|
||||
|
||||
struct _cairo_boxes_chunk {
|
||||
struct _cairo_boxes_chunk *next;
|
||||
|
|
@ -69,6 +72,10 @@ _cairo_boxes_init_for_array (cairo_boxes_t *boxes,
|
|||
cairo_box_t *array,
|
||||
int num_boxes);
|
||||
|
||||
cairo_private void
|
||||
_cairo_boxes_init_from_rectangle (cairo_boxes_t *boxes,
|
||||
int x, int y, int w, int h);
|
||||
|
||||
cairo_private void
|
||||
_cairo_boxes_limit (cairo_boxes_t *boxes,
|
||||
const cairo_box_t *limits,
|
||||
|
|
@ -81,7 +88,7 @@ _cairo_boxes_add (cairo_boxes_t *boxes,
|
|||
|
||||
cairo_private void
|
||||
_cairo_boxes_extents (const cairo_boxes_t *boxes,
|
||||
cairo_rectangle_int_t *extents);
|
||||
cairo_box_t *box);
|
||||
|
||||
cairo_private cairo_box_t *
|
||||
_cairo_boxes_to_array (const cairo_boxes_t *boxes,
|
||||
|
|
@ -104,6 +111,11 @@ _cairo_boxes_intersect (const cairo_boxes_t *a,
|
|||
cairo_private void
|
||||
_cairo_boxes_clear (cairo_boxes_t *boxes);
|
||||
|
||||
cairo_private_no_warn cairo_bool_t
|
||||
_cairo_boxes_for_each_box (cairo_boxes_t *boxes,
|
||||
cairo_bool_t (*func) (cairo_box_t *box, void *data),
|
||||
void *data);
|
||||
|
||||
cairo_private void
|
||||
_cairo_boxes_fini (cairo_boxes_t *boxes);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-box-private.h"
|
||||
#include "cairo-boxes-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
|
|
@ -52,6 +53,16 @@ _cairo_boxes_init (cairo_boxes_t *boxes)
|
|||
boxes->is_pixel_aligned = TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_boxes_init_from_rectangle (cairo_boxes_t *boxes,
|
||||
int x, int y, int w, int h)
|
||||
{
|
||||
_cairo_boxes_init (boxes);
|
||||
|
||||
_cairo_box_from_integers (&boxes->chunks.base[0], x, y, w, h);
|
||||
boxes->num_boxes = 1;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_boxes_init_with_clip (cairo_boxes_t *boxes,
|
||||
cairo_clip_t *clip)
|
||||
|
|
@ -154,13 +165,8 @@ _cairo_boxes_add_internal (cairo_boxes_t *boxes,
|
|||
chunk->base[chunk->count++] = *box;
|
||||
boxes->num_boxes++;
|
||||
|
||||
if (boxes->is_pixel_aligned) {
|
||||
boxes->is_pixel_aligned =
|
||||
_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);
|
||||
}
|
||||
if (boxes->is_pixel_aligned)
|
||||
boxes->is_pixel_aligned = _cairo_box_is_pixel_aligned (box);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
|
|
@ -261,38 +267,34 @@ _cairo_boxes_add (cairo_boxes_t *boxes,
|
|||
|
||||
void
|
||||
_cairo_boxes_extents (const cairo_boxes_t *boxes,
|
||||
cairo_rectangle_int_t *extents)
|
||||
cairo_box_t *box)
|
||||
{
|
||||
const struct _cairo_boxes_chunk *chunk;
|
||||
cairo_box_t box;
|
||||
cairo_box_t b;
|
||||
int i;
|
||||
|
||||
if (boxes->num_boxes == 0) {
|
||||
extents->x = extents->y = extents->width = extents->height = 0;
|
||||
box->p1.x = box->p1.y = box->p2.x = box->p2.y = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
box.p1.y = box.p1.x = INT_MAX;
|
||||
box.p2.y = box.p2.x = INT_MIN;
|
||||
|
||||
b = boxes->chunks.base[0];
|
||||
for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
|
||||
const cairo_box_t *b = chunk->base;
|
||||
for (i = 0; i < chunk->count; i++) {
|
||||
if (b[i].p1.x < box.p1.x)
|
||||
box.p1.x = b[i].p1.x;
|
||||
if (chunk->base[i].p1.x < b.p1.x)
|
||||
b.p1.x = chunk->base[i].p1.x;
|
||||
|
||||
if (b[i].p1.y < box.p1.y)
|
||||
box.p1.y = b[i].p1.y;
|
||||
if (chunk->base[i].p1.y < b.p1.y)
|
||||
b.p1.y = chunk->base[i].p1.y;
|
||||
|
||||
if (b[i].p2.x > box.p2.x)
|
||||
box.p2.x = b[i].p2.x;
|
||||
if (chunk->base[i].p2.x > b.p2.x)
|
||||
b.p2.x = chunk->base[i].p2.x;
|
||||
|
||||
if (b[i].p2.y > box.p2.y)
|
||||
box.p2.y = b[i].p2.y;
|
||||
if (chunk->base[i].p2.y > b.p2.y)
|
||||
b.p2.y = chunk->base[i].p2.y;
|
||||
}
|
||||
}
|
||||
|
||||
_cairo_box_round_to_rectangle (&box, extents);
|
||||
*box = b;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -354,17 +356,38 @@ _cairo_boxes_fini (cairo_boxes_t *boxes)
|
|||
}
|
||||
}
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_boxes_for_each_box (cairo_boxes_t *boxes,
|
||||
cairo_bool_t (*func) (cairo_box_t *box, void *data),
|
||||
void *data)
|
||||
{
|
||||
struct _cairo_boxes_chunk *chunk;
|
||||
int i;
|
||||
|
||||
for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
|
||||
for (i = 0; i < chunk->count; i++)
|
||||
if (! func (&chunk->base[i], data))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_cairo_debug_print_boxes (FILE *stream, const cairo_boxes_t *boxes)
|
||||
{
|
||||
cairo_rectangle_int_t extents;
|
||||
const struct _cairo_boxes_chunk *chunk;
|
||||
cairo_box_t extents;
|
||||
int i;
|
||||
|
||||
_cairo_boxes_extents (boxes, &extents);
|
||||
fprintf (stream, "boxes x %d: (%d, %d) x (%d, %d)\n",
|
||||
fprintf (stream, "boxes x %d: (%f, %f) x (%f, %f)\n",
|
||||
boxes->num_boxes,
|
||||
extents.x, extents.y, extents.width, extents.height);
|
||||
_cairo_fixed_to_double (extents.p1.x),
|
||||
_cairo_fixed_to_double (extents.p1.y),
|
||||
_cairo_fixed_to_double (extents.p2.x),
|
||||
_cairo_fixed_to_double (extents.p2.y));
|
||||
|
||||
for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
|
||||
for (i = 0; i < chunk->count; i++) {
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@
|
|||
|
||||
#define _BSD_SOURCE /* for snprintf(), strdup() */
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-array-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
#if CAIRO_HAS_FONT_SUBSET
|
||||
|
|
@ -2897,7 +2899,7 @@ cairo_bool_t
|
|||
_cairo_cff_scaled_font_is_cid_cff (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
const cairo_scaled_font_backend_t *backend;
|
||||
cairo_status_t status;
|
||||
cairo_int_status_t status;
|
||||
unsigned char *data;
|
||||
unsigned long data_length;
|
||||
unsigned char *current_ptr;
|
||||
|
|
@ -2916,7 +2918,7 @@ _cairo_cff_scaled_font_is_cid_cff (cairo_scaled_font_t *scaled_font)
|
|||
/* Try to load an OpenType/CFF font */
|
||||
if (backend->load_truetype_table &&
|
||||
(status = backend->load_truetype_table (scaled_font, TT_TAG_CFF,
|
||||
0, NULL, &data_length)) == CAIRO_STATUS_SUCCESS)
|
||||
0, NULL, &data_length)) == CAIRO_INT_STATUS_SUCCESS)
|
||||
{
|
||||
data = malloc (data_length);
|
||||
if (unlikely (data == NULL)) {
|
||||
|
|
@ -2933,7 +2935,7 @@ _cairo_cff_scaled_font_is_cid_cff (cairo_scaled_font_t *scaled_font)
|
|||
if (status == CAIRO_INT_STATUS_UNSUPPORTED &&
|
||||
backend->load_type1_data &&
|
||||
(status = backend->load_type1_data (scaled_font,
|
||||
0, NULL, &data_length)) == CAIRO_STATUS_SUCCESS)
|
||||
0, NULL, &data_length)) == CAIRO_INT_STATUS_SUCCESS)
|
||||
{
|
||||
data = malloc (data_length);
|
||||
if (unlikely (data == NULL)) {
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@
|
|||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-box-private.h"
|
||||
#include "cairo-clip-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-freed-pool-private.h"
|
||||
|
|
@ -62,7 +64,6 @@ pot (int v)
|
|||
return v;
|
||||
}
|
||||
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_clip_contains_rectangle_box (const cairo_clip_t *clip,
|
||||
const cairo_rectangle_int_t *rect,
|
||||
|
|
@ -90,7 +91,6 @@ _cairo_clip_contains_rectangle_box (const cairo_clip_t *clip,
|
|||
}
|
||||
|
||||
/* Check for a clip-box that wholly contains the rectangle */
|
||||
assert (clip->num_boxes);
|
||||
for (i = 0; i < clip->num_boxes; i++) {
|
||||
if (box->p1.x >= clip->boxes[i].p1.x &&
|
||||
box->p1.y >= clip->boxes[i].p1.y &&
|
||||
|
|
@ -176,6 +176,8 @@ _cairo_clip_intersect_rectangle_box (cairo_clip_t *clip,
|
|||
if (! _cairo_rectangle_intersect (&clip->extents, r))
|
||||
clip = _cairo_clip_set_all_clipped (clip);
|
||||
}
|
||||
if (clip->path == NULL)
|
||||
clip->is_region = _cairo_box_is_pixel_aligned (box);
|
||||
return clip;
|
||||
}
|
||||
|
||||
|
|
@ -269,6 +271,7 @@ _cairo_clip_intersect_boxes (cairo_clip_t *clip,
|
|||
const cairo_boxes_t *boxes)
|
||||
{
|
||||
cairo_boxes_t clip_boxes;
|
||||
cairo_box_t limits;
|
||||
cairo_rectangle_int_t extents;
|
||||
|
||||
if (_cairo_clip_is_all_clipped (clip))
|
||||
|
|
@ -301,10 +304,11 @@ _cairo_clip_intersect_boxes (cairo_clip_t *clip,
|
|||
} else {
|
||||
clip->boxes = _cairo_boxes_to_array (boxes, &clip->num_boxes, TRUE);
|
||||
}
|
||||
_cairo_boxes_extents (boxes, &extents);
|
||||
_cairo_boxes_extents (boxes, &limits);
|
||||
if (boxes == &clip_boxes)
|
||||
_cairo_boxes_fini (&clip_boxes);
|
||||
|
||||
_cairo_box_round_to_rectangle (&limits, &extents);
|
||||
if (clip->path == NULL)
|
||||
clip->extents = extents;
|
||||
else if (! _cairo_rectangle_intersect (&clip->extents, &extents))
|
||||
|
|
@ -557,37 +561,10 @@ _cairo_clip_reduce_for_composite (const cairo_clip_t *clip,
|
|||
return _cairo_clip_reduce_to_rectangle (clip, r);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_clip_to_boxes (cairo_clip_t *clip,
|
||||
cairo_boxes_t *boxes)
|
||||
{
|
||||
_cairo_boxes_init_for_array (boxes, clip->boxes, clip->num_boxes);
|
||||
|
||||
if (clip->path == NULL) {
|
||||
cairo_box_t *src = clip->boxes;
|
||||
int i;
|
||||
|
||||
clip->boxes = _cairo_malloc_ab (clip->num_boxes, sizeof (cairo_box_t));
|
||||
if (clip->boxes == NULL) {
|
||||
clip->boxes = src;
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
for (i = 0; i < clip->num_boxes; i++) {
|
||||
clip->boxes[i].p1.x = _cairo_fixed_floor (src[i].p1.x);
|
||||
clip->boxes[i].p1.y = _cairo_fixed_floor (src[i].p1.y);
|
||||
clip->boxes[i].p2.x = _cairo_fixed_ceil (src[i].p2.x);
|
||||
clip->boxes[i].p2.y = _cairo_fixed_ceil (src[i].p2.y);
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
cairo_clip_t *
|
||||
_cairo_clip_from_boxes (const cairo_boxes_t *boxes)
|
||||
{
|
||||
cairo_box_t extents;
|
||||
cairo_clip_t *clip = _cairo_clip_create ();
|
||||
if (clip == NULL)
|
||||
return _cairo_clip_set_all_clipped (clip);
|
||||
|
|
@ -603,7 +580,8 @@ _cairo_clip_from_boxes (const cairo_boxes_t *boxes)
|
|||
return _cairo_clip_set_all_clipped (clip);
|
||||
}
|
||||
|
||||
_cairo_boxes_extents (boxes, &clip->extents);
|
||||
_cairo_boxes_extents (boxes, &extents);
|
||||
_cairo_box_round_to_rectangle (&extents, &clip->extents);
|
||||
|
||||
return clip;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
#include "cairo-types-private.h"
|
||||
|
||||
#include "cairo-boxes-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-compiler-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-path-fixed-private.h"
|
||||
|
|
@ -160,14 +161,30 @@ _cairo_clip_get_extents (const cairo_clip_t *clip);
|
|||
cairo_private cairo_surface_t *
|
||||
_cairo_clip_get_surface (const cairo_clip_t *clip, cairo_surface_t *dst, int *tx, int *ty);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_clip_get_image (const cairo_clip_t *clip,
|
||||
cairo_surface_t *target,
|
||||
const cairo_rectangle_int_t *extents);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_clip_combine_with_surface (const cairo_clip_t *clip,
|
||||
cairo_surface_t *dst,
|
||||
int dst_x, int dst_y);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_clip_to_boxes (cairo_clip_t *clip,
|
||||
cairo_boxes_t *boxes);
|
||||
static inline void
|
||||
_cairo_clip_steal_boxes (cairo_clip_t *clip, cairo_boxes_t *boxes)
|
||||
{
|
||||
_cairo_boxes_init_for_array (boxes, clip->boxes, clip->num_boxes);
|
||||
clip->boxes = NULL;
|
||||
clip->num_boxes = 0;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_cairo_clip_unsteal_boxes (cairo_clip_t *clip, cairo_boxes_t *boxes)
|
||||
{
|
||||
clip->boxes = boxes->chunks.base;
|
||||
clip->num_boxes = boxes->num_boxes;
|
||||
}
|
||||
|
||||
cairo_private cairo_clip_t *
|
||||
_cairo_clip_from_boxes (const cairo_boxes_t *boxes);
|
||||
|
|
|
|||
|
|
@ -105,11 +105,17 @@ _cairo_clip_is_region (const cairo_clip_t *clip)
|
|||
if (clip == NULL)
|
||||
return TRUE;
|
||||
|
||||
if (clip->is_region)
|
||||
return TRUE;
|
||||
|
||||
/* XXX Geometric reduction? */
|
||||
|
||||
if (clip->path)
|
||||
return FALSE;
|
||||
|
||||
if (clip->num_boxes == 0)
|
||||
return TRUE;
|
||||
|
||||
if (clip->region == NULL)
|
||||
_cairo_clip_extract_region ((cairo_clip_t *) clip);
|
||||
|
||||
|
|
|
|||
|
|
@ -103,8 +103,7 @@ _cairo_clip_get_surface (const cairo_clip_t *clip,
|
|||
CAIRO_CONTENT_ALPHA,
|
||||
clip->extents.width,
|
||||
clip->extents.height,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
TRUE);
|
||||
CAIRO_COLOR_WHITE);
|
||||
if (unlikely (surface->status))
|
||||
return surface;
|
||||
|
||||
|
|
@ -114,12 +113,7 @@ _cairo_clip_get_surface (const cairo_clip_t *clip,
|
|||
copy_path = copy->path;
|
||||
copy->path = NULL;
|
||||
|
||||
assert (copy->num_boxes);
|
||||
status = _cairo_surface_paint (surface,
|
||||
CAIRO_OPERATOR_ADD,
|
||||
&_cairo_pattern_white.base,
|
||||
copy);
|
||||
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
clip_path = copy_path;
|
||||
while (status == CAIRO_STATUS_SUCCESS && clip_path) {
|
||||
status = _cairo_surface_fill (surface,
|
||||
|
|
@ -140,3 +134,32 @@ _cairo_clip_get_surface (const cairo_clip_t *clip,
|
|||
*ty = clip->extents.y;
|
||||
return surface;
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_clip_get_image (const cairo_clip_t *clip,
|
||||
cairo_surface_t *target,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_status_t status;
|
||||
|
||||
surface = cairo_surface_create_similar_image (target,
|
||||
CAIRO_FORMAT_A8,
|
||||
extents->width,
|
||||
extents->height);
|
||||
if (unlikely (surface->status))
|
||||
return surface;
|
||||
|
||||
status = _cairo_surface_paint (surface, CAIRO_OPERATOR_SOURCE,
|
||||
&_cairo_pattern_white.base, NULL);
|
||||
if (likely (status == CAIRO_STATUS_SUCCESS))
|
||||
status = _cairo_clip_combine_with_surface (clip, surface,
|
||||
extents->x, extents->y);
|
||||
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (surface);
|
||||
surface = _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
|
|
|||
1845
src/cairo-clip-tor-scan-converter.c
Normal file
1845
src/cairo-clip-tor-scan-converter.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -246,16 +246,9 @@ _cairo_clip_intersect_path (cairo_clip_t *clip,
|
|||
if (extents.width == 0 || extents.height == 0)
|
||||
return _cairo_clip_set_all_clipped (clip);
|
||||
|
||||
if (clip && ! _cairo_rectangle_intersect (&clip->extents, &extents))
|
||||
return _cairo_clip_set_all_clipped (clip);
|
||||
|
||||
if (clip == NULL) {
|
||||
clip = _cairo_clip_create ();
|
||||
if (unlikely (clip == NULL))
|
||||
return _cairo_clip_set_all_clipped (clip);
|
||||
|
||||
clip->extents = extents;
|
||||
}
|
||||
clip = _cairo_clip_intersect_rectangle (clip, &extents);
|
||||
if (_cairo_clip_is_all_clipped (clip))
|
||||
return clip;
|
||||
|
||||
clip_path = _cairo_clip_path_create (clip);
|
||||
if (unlikely (clip_path == NULL))
|
||||
|
|
@ -532,9 +525,10 @@ _cairo_debug_print_clip (FILE *stream, const cairo_clip_t *clip)
|
|||
}
|
||||
|
||||
fprintf (stream, "clip:\n");
|
||||
fprintf (stream, " extents: (%d, %d) x (%d, %d)",
|
||||
fprintf (stream, " extents: (%d, %d) x (%d, %d), is-region? %d",
|
||||
clip->extents.x, clip->extents.y,
|
||||
clip->extents.width, clip->extents.height);
|
||||
clip->extents.width, clip->extents.height,
|
||||
clip->is_region);
|
||||
|
||||
fprintf (stream, " num_boxes = %d\n", clip->num_boxes);
|
||||
for (i = 0; i < clip->num_boxes; i++) {
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#include "cairo-types-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-pattern-private.h"
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
|
|
@ -52,6 +53,9 @@ CAIRO_BEGIN_DECLS
|
|||
*
|
||||
*/
|
||||
struct _cairo_composite_rectangles {
|
||||
cairo_surface_t *surface;
|
||||
cairo_operator_t op;
|
||||
|
||||
cairo_rectangle_int_t source;
|
||||
cairo_rectangle_int_t mask;
|
||||
cairo_rectangle_int_t destination;
|
||||
|
|
@ -60,19 +64,27 @@ struct _cairo_composite_rectangles {
|
|||
cairo_rectangle_int_t unbounded; /* destination IN clip */
|
||||
uint32_t is_bounded;
|
||||
|
||||
cairo_rectangle_int_t source_sample_area;
|
||||
cairo_rectangle_int_t mask_sample_area;
|
||||
|
||||
cairo_pattern_union_t source_pattern;
|
||||
cairo_pattern_union_t mask_pattern;
|
||||
const cairo_pattern_t *original_source_pattern;
|
||||
const cairo_pattern_t *original_mask_pattern;
|
||||
|
||||
cairo_clip_t *clip; /* clip will be reduced to the minimal container */
|
||||
};
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *unbounded,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *unbounded,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
|
|
@ -80,7 +92,7 @@ _cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents
|
|||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *unbounded,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_path_fixed_t *path,
|
||||
|
|
@ -90,15 +102,31 @@ _cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *exten
|
|||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_fill (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *unbounded,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_path_fixed_t *path,
|
||||
const cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_boxes (cairo_composite_rectangles_t *extents,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_boxes_t *boxes,
|
||||
const cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_polygon (cairo_composite_rectangles_t *extents,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_polygon_t *polygon,
|
||||
const cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *unbounded,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
|
|
|
|||
|
|
@ -46,57 +46,93 @@ void _cairo_composite_rectangles_fini (cairo_composite_rectangles_t *extents)
|
|||
_cairo_clip_destroy (extents->clip);
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_composite_reduce_pattern (const cairo_pattern_t *src,
|
||||
cairo_pattern_union_t *dst)
|
||||
{
|
||||
int tx, ty;
|
||||
|
||||
_cairo_pattern_init_static_copy (&dst->base, src);
|
||||
if (dst->base.type == CAIRO_PATTERN_TYPE_SOLID)
|
||||
return;
|
||||
|
||||
dst->base.filter = _cairo_pattern_analyze_filter (&dst->base, NULL),
|
||||
|
||||
tx = ty = 0;
|
||||
if (_cairo_matrix_is_pixman_translation (&dst->base.matrix,
|
||||
dst->base.filter,
|
||||
&tx, &ty))
|
||||
{
|
||||
dst->base.matrix.x0 = tx;
|
||||
dst->base.matrix.y0 = ty;
|
||||
}
|
||||
}
|
||||
|
||||
static inline cairo_bool_t
|
||||
_cairo_composite_rectangles_init (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *unbounded,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_clip_t *clip)
|
||||
{
|
||||
extents->clip = NULL;
|
||||
extents->destination = *unbounded;
|
||||
|
||||
if (_cairo_clip_is_all_clipped (clip))
|
||||
return FALSE;
|
||||
|
||||
extents->surface = surface;
|
||||
extents->op = op;
|
||||
|
||||
_cairo_surface_get_extents (surface, &extents->destination);
|
||||
extents->clip = NULL;
|
||||
|
||||
extents->unbounded = extents->destination;
|
||||
if (clip != NULL) {
|
||||
if (! _cairo_rectangle_intersect (&extents->unbounded,
|
||||
if (clip && ! _cairo_rectangle_intersect (&extents->unbounded,
|
||||
_cairo_clip_get_extents (clip)))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
extents->bounded = extents->unbounded;
|
||||
extents->is_bounded = _cairo_operator_bounded_by_either (op);
|
||||
|
||||
_cairo_pattern_get_extents (source, &extents->source);
|
||||
extents->original_source_pattern = source;
|
||||
_cairo_composite_reduce_pattern (source, &extents->source_pattern);
|
||||
|
||||
_cairo_pattern_get_extents (&extents->source_pattern.base,
|
||||
&extents->source);
|
||||
if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_SOURCE) {
|
||||
if (! _cairo_rectangle_intersect (&extents->bounded, &extents->source))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
extents->original_mask_pattern = NULL;
|
||||
extents->mask_pattern.base.type = CAIRO_PATTERN_TYPE_SOLID;
|
||||
extents->mask_pattern.solid.color.alpha = 1.; /* XXX full initialisation? */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_paint (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *unbounded,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_clip_t *clip)
|
||||
{
|
||||
if (! _cairo_composite_rectangles_init (extents, unbounded,
|
||||
op, source, clip))
|
||||
if (! _cairo_composite_rectangles_init (extents,
|
||||
surface, op, source, clip))
|
||||
{
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
extents->mask = *unbounded;
|
||||
extents->mask = extents->destination;
|
||||
|
||||
extents->clip = _cairo_clip_reduce_for_composite (clip, extents);
|
||||
if (_cairo_clip_is_all_clipped (extents->clip))
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
|
||||
if (extents->source_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID)
|
||||
_cairo_pattern_sampled_area (&extents->source_pattern.base,
|
||||
&extents->bounded,
|
||||
&extents->source_sample_area);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -117,6 +153,21 @@ _cairo_composite_rectangles_intersect (cairo_composite_rectangles_t *extents,
|
|||
if (_cairo_clip_is_all_clipped (extents->clip))
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
|
||||
if (extents->source_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID)
|
||||
_cairo_pattern_sampled_area (&extents->source_pattern.base,
|
||||
&extents->bounded,
|
||||
&extents->source_sample_area);
|
||||
if (extents->mask_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID) {
|
||||
_cairo_pattern_sampled_area (&extents->mask_pattern.base,
|
||||
&extents->bounded,
|
||||
&extents->mask_sample_area);
|
||||
if (extents->mask_sample_area.width == 0 ||
|
||||
extents->mask_sample_area.height == 0) {
|
||||
_cairo_composite_rectangles_fini (extents);
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -125,7 +176,6 @@ _cairo_composite_rectangles_intersect_mask_extents (cairo_composite_rectangles_t
|
|||
const cairo_box_t *box)
|
||||
{
|
||||
cairo_rectangle_int_t mask;
|
||||
cairo_int_status_t status;
|
||||
cairo_clip_t *clip;
|
||||
|
||||
_cairo_box_round_to_rectangle (box, &mask);
|
||||
|
|
@ -139,39 +189,70 @@ _cairo_composite_rectangles_intersect_mask_extents (cairo_composite_rectangles_t
|
|||
|
||||
_cairo_rectangle_intersect (&extents->mask, &mask);
|
||||
|
||||
mask = extents->bounded;
|
||||
if (! _cairo_rectangle_intersect (&extents->bounded, &extents->mask) &&
|
||||
extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK)
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
|
||||
if (mask.width == extents->bounded.width &&
|
||||
mask.height == extents->bounded.height)
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
|
||||
if (extents->is_bounded == (CAIRO_OPERATOR_BOUND_BY_MASK | CAIRO_OPERATOR_BOUND_BY_SOURCE))
|
||||
extents->unbounded = extents->bounded;
|
||||
|
||||
extents->mask = mask;
|
||||
clip = extents->clip;
|
||||
|
||||
status = _cairo_composite_rectangles_intersect (extents, clip);
|
||||
extents->clip = _cairo_clip_reduce_for_composite (clip, extents);
|
||||
|
||||
if (clip != extents->clip)
|
||||
_cairo_clip_destroy (clip);
|
||||
|
||||
return status;
|
||||
if (_cairo_clip_is_all_clipped (extents->clip))
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
|
||||
if (extents->source_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID)
|
||||
_cairo_pattern_sampled_area (&extents->source_pattern.base,
|
||||
&extents->bounded,
|
||||
&extents->source_sample_area);
|
||||
if (extents->mask_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID) {
|
||||
_cairo_pattern_sampled_area (&extents->mask_pattern.base,
|
||||
&extents->bounded,
|
||||
&extents->mask_sample_area);
|
||||
if (extents->mask_sample_area.width == 0 ||
|
||||
extents->mask_sample_area.height == 0)
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
return CAIRO_INT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_mask (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *unbounded,
|
||||
cairo_surface_t*surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
const cairo_clip_t *clip)
|
||||
{
|
||||
if (! _cairo_composite_rectangles_init (extents, unbounded,
|
||||
op, source, clip))
|
||||
if (! _cairo_composite_rectangles_init (extents,
|
||||
surface, op, source, clip))
|
||||
{
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
_cairo_pattern_get_extents (mask, &extents->mask);
|
||||
|
||||
extents->original_mask_pattern = mask;
|
||||
_cairo_composite_reduce_pattern (mask, &extents->mask_pattern);
|
||||
_cairo_pattern_get_extents (&extents->mask_pattern.base, &extents->mask);
|
||||
|
||||
return _cairo_composite_rectangles_intersect (extents, clip);
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *unbounded,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_path_fixed_t *path,
|
||||
|
|
@ -179,8 +260,8 @@ _cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *exten
|
|||
const cairo_matrix_t *ctm,
|
||||
const cairo_clip_t *clip)
|
||||
{
|
||||
if (! _cairo_composite_rectangles_init (extents, unbounded,
|
||||
op, source, clip))
|
||||
if (! _cairo_composite_rectangles_init (extents,
|
||||
surface, op, source, clip))
|
||||
{
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
|
@ -192,14 +273,14 @@ _cairo_composite_rectangles_init_for_stroke (cairo_composite_rectangles_t *exten
|
|||
|
||||
cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_fill (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *unbounded,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_path_fixed_t *path,
|
||||
const cairo_clip_t *clip)
|
||||
{
|
||||
if (! _cairo_composite_rectangles_init (extents, unbounded,
|
||||
op, source, clip))
|
||||
if (! _cairo_composite_rectangles_init (extents,
|
||||
surface, op, source, clip))
|
||||
{
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
|
@ -209,9 +290,48 @@ _cairo_composite_rectangles_init_for_fill (cairo_composite_rectangles_t *extents
|
|||
return _cairo_composite_rectangles_intersect (extents, clip);
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_polygon (cairo_composite_rectangles_t *extents,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_polygon_t *polygon,
|
||||
const cairo_clip_t *clip)
|
||||
{
|
||||
if (! _cairo_composite_rectangles_init (extents,
|
||||
surface, op, source, clip))
|
||||
{
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
_cairo_box_round_to_rectangle (&polygon->extents, &extents->mask);
|
||||
return _cairo_composite_rectangles_intersect (extents, clip);
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_boxes (cairo_composite_rectangles_t *extents,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_boxes_t *boxes,
|
||||
const cairo_clip_t *clip)
|
||||
{
|
||||
cairo_box_t box;
|
||||
|
||||
if (! _cairo_composite_rectangles_init (extents,
|
||||
surface, op, source, clip))
|
||||
{
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
}
|
||||
|
||||
_cairo_boxes_extents (boxes, &box);
|
||||
_cairo_box_round_to_rectangle (&box, &extents->mask);
|
||||
return _cairo_composite_rectangles_intersect (extents, clip);
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *extents,
|
||||
const cairo_rectangle_int_t *unbounded,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
|
|
@ -222,8 +342,7 @@ _cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *exten
|
|||
{
|
||||
cairo_status_t status;
|
||||
|
||||
if (! _cairo_composite_rectangles_init (extents, unbounded,
|
||||
op, source, clip))
|
||||
if (! _cairo_composite_rectangles_init (extents, surface, op, source, clip))
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
|
||||
/* Computing the exact bbox and the overlap is expensive.
|
||||
|
|
|
|||
355
src/cairo-compositor-private.h
Normal file
355
src/cairo-compositor-private.h
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#ifndef CAIRO_COMPOSITOR_PRIVATE_H
|
||||
#define CAIRO_COMPOSITOR_PRIVATE_H
|
||||
|
||||
#include "cairo-composite-rectangles-private.h"
|
||||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
typedef struct {
|
||||
cairo_scaled_font_t *font;
|
||||
cairo_glyph_t *glyphs;
|
||||
int num_glyphs;
|
||||
cairo_bool_t use_mask;
|
||||
cairo_rectangle_int_t extents;
|
||||
} cairo_composite_glyphs_info_t;
|
||||
|
||||
struct cairo_compositor {
|
||||
const cairo_compositor_t *delegate;
|
||||
|
||||
cairo_warn cairo_int_status_t
|
||||
(*paint) (const cairo_compositor_t *compositor,
|
||||
cairo_composite_rectangles_t *extents);
|
||||
|
||||
cairo_warn cairo_int_status_t
|
||||
(*mask) (const cairo_compositor_t *compositor,
|
||||
cairo_composite_rectangles_t *extents);
|
||||
|
||||
cairo_warn cairo_int_status_t
|
||||
(*stroke) (const cairo_compositor_t *compositor,
|
||||
cairo_composite_rectangles_t *extents,
|
||||
const cairo_path_fixed_t *path,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias);
|
||||
|
||||
cairo_warn cairo_int_status_t
|
||||
(*fill) (const cairo_compositor_t *compositor,
|
||||
cairo_composite_rectangles_t *extents,
|
||||
const cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias);
|
||||
|
||||
cairo_warn cairo_int_status_t
|
||||
(*glyphs) (const cairo_compositor_t *compositor,
|
||||
cairo_composite_rectangles_t *extents,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_bool_t overlap);
|
||||
};
|
||||
|
||||
struct cairo_mask_compositor {
|
||||
cairo_compositor_t base;
|
||||
|
||||
cairo_int_status_t (*acquire) (void *surface);
|
||||
cairo_int_status_t (*release) (void *surface);
|
||||
|
||||
cairo_int_status_t (*set_clip_region) (void *surface,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
cairo_surface_t * (*pattern_to_surface) (cairo_surface_t *dst,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_bool_t is_mask,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
const cairo_rectangle_int_t *sample,
|
||||
int *src_x, int *src_y);
|
||||
|
||||
cairo_int_status_t (*draw_image_boxes) (void *surface,
|
||||
cairo_image_surface_t *image,
|
||||
cairo_boxes_t *boxes,
|
||||
int dx, int dy);
|
||||
|
||||
cairo_int_status_t (*copy_boxes) (void *surface,
|
||||
cairo_surface_t *src,
|
||||
cairo_boxes_t *boxes,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
int dx, int dy);
|
||||
|
||||
cairo_int_status_t
|
||||
(*fill_rectangles) (void *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_color_t *color,
|
||||
cairo_rectangle_int_t *rectangles,
|
||||
int num_rects);
|
||||
|
||||
cairo_int_status_t
|
||||
(*fill_boxes) (void *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_color_t *color,
|
||||
cairo_boxes_t *boxes);
|
||||
|
||||
cairo_int_status_t
|
||||
(*composite) (void *dst,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *src,
|
||||
cairo_surface_t *mask,
|
||||
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_int_status_t
|
||||
(*composite_boxes) (void *surface,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *source,
|
||||
cairo_surface_t *mask,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int mask_x,
|
||||
int mask_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
cairo_boxes_t *boxes,
|
||||
const cairo_rectangle_int_t *extents);
|
||||
|
||||
cairo_int_status_t
|
||||
(*check_composite_glyphs) (const cairo_composite_rectangles_t *extents,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int *num_glyphs);
|
||||
cairo_int_status_t
|
||||
(*composite_glyphs) (void *surface,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
cairo_composite_glyphs_info_t *info);
|
||||
};
|
||||
|
||||
struct cairo_traps_compositor {
|
||||
cairo_compositor_t base;
|
||||
|
||||
cairo_int_status_t
|
||||
(*acquire) (void *surface);
|
||||
|
||||
cairo_int_status_t
|
||||
(*release) (void *surface);
|
||||
|
||||
cairo_int_status_t
|
||||
(*set_clip_region) (void *surface,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
cairo_surface_t *
|
||||
(*pattern_to_surface) (cairo_surface_t *dst,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_bool_t is_mask,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
const cairo_rectangle_int_t *sample,
|
||||
int *src_x, int *src_y);
|
||||
|
||||
cairo_int_status_t (*draw_image_boxes) (void *surface,
|
||||
cairo_image_surface_t *image,
|
||||
cairo_boxes_t *boxes,
|
||||
int dx, int dy);
|
||||
|
||||
cairo_int_status_t (*copy_boxes) (void *surface,
|
||||
cairo_surface_t *src,
|
||||
cairo_boxes_t *boxes,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
int dx, int dy);
|
||||
|
||||
cairo_int_status_t
|
||||
(*fill_boxes) (void *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_color_t *color,
|
||||
cairo_boxes_t *boxes);
|
||||
|
||||
cairo_int_status_t
|
||||
(*composite) (void *dst,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *src,
|
||||
cairo_surface_t *mask,
|
||||
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_int_status_t
|
||||
(*lerp) (void *_dst,
|
||||
cairo_surface_t *abstract_src,
|
||||
cairo_surface_t *abstract_mask,
|
||||
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_int_status_t
|
||||
(*composite_boxes) (void *surface,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *source,
|
||||
cairo_surface_t *mask,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int mask_x,
|
||||
int mask_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
cairo_boxes_t *boxes,
|
||||
const cairo_rectangle_int_t *extents);
|
||||
|
||||
cairo_int_status_t
|
||||
(*composite_traps) (void *dst,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *source,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_traps_t *traps);
|
||||
|
||||
cairo_int_status_t
|
||||
(*composite_tristrip) (void *dst,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *source,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_tristrip_t *tristrip);
|
||||
|
||||
cairo_int_status_t
|
||||
(*check_composite_glyphs) (const cairo_composite_rectangles_t *extents,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int *num_glyphs);
|
||||
cairo_int_status_t
|
||||
(*composite_glyphs) (void *surface,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
cairo_composite_glyphs_info_t *info);
|
||||
};
|
||||
|
||||
cairo_private extern const cairo_compositor_t __cairo_no_compositor;
|
||||
cairo_private extern const cairo_compositor_t _cairo_fallback_compositor;
|
||||
|
||||
cairo_private void
|
||||
_cairo_mask_compositor_init (cairo_mask_compositor_t *compositor,
|
||||
const cairo_compositor_t *delegate);
|
||||
|
||||
cairo_private void
|
||||
_cairo_traps_compositor_init (cairo_traps_compositor_t *compositor,
|
||||
const cairo_compositor_t *delegate);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_compositor_paint (const cairo_compositor_t *compositor,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_compositor_mask (const cairo_compositor_t *compositor,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
const cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_compositor_stroke (const cairo_compositor_t *compositor,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_path_fixed_t *path,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_compositor_fill (const cairo_compositor_t *compositor,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_clip_t *clip);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_compositor_glyphs (const cairo_compositor_t *compositor,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
const cairo_clip_t *clip);
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif /* CAIRO_COMPOSITOR_PRIVATE_H */
|
||||
213
src/cairo-compositor.c
Normal file
213
src/cairo-compositor.c
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-compositor-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_compositor_paint (const cairo_compositor_t *compositor,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_clip_t *clip)
|
||||
{
|
||||
cairo_composite_rectangles_t extents;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_composite_rectangles_init_for_paint (&extents, surface,
|
||||
op, source,
|
||||
clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
do {
|
||||
while (compositor->paint == NULL)
|
||||
compositor = compositor->delegate;
|
||||
|
||||
status = compositor->paint (compositor, &extents);
|
||||
|
||||
compositor = compositor->delegate;
|
||||
} while (status == CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
|
||||
_cairo_composite_rectangles_fini (&extents);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_compositor_mask (const cairo_compositor_t *compositor,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_pattern_t *mask,
|
||||
const cairo_clip_t *clip)
|
||||
{
|
||||
cairo_composite_rectangles_t extents;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_composite_rectangles_init_for_mask (&extents, surface,
|
||||
op, source, mask,
|
||||
clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
do {
|
||||
while (compositor->mask == NULL)
|
||||
compositor = compositor->delegate;
|
||||
|
||||
status = compositor->mask (compositor, &extents);
|
||||
|
||||
compositor = compositor->delegate;
|
||||
} while (status == CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
|
||||
_cairo_composite_rectangles_fini (&extents);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_compositor_stroke (const cairo_compositor_t *compositor,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_path_fixed_t *path,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_clip_t *clip)
|
||||
{
|
||||
cairo_composite_rectangles_t extents;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_composite_rectangles_init_for_stroke (&extents, surface,
|
||||
op, source,
|
||||
path, style, ctm,
|
||||
clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
do {
|
||||
while (compositor->stroke == NULL)
|
||||
compositor = compositor->delegate;
|
||||
|
||||
status = compositor->stroke (compositor, &extents,
|
||||
path, style, ctm, ctm_inverse,
|
||||
tolerance, antialias);
|
||||
|
||||
compositor = compositor->delegate;
|
||||
} while (status == CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
|
||||
_cairo_composite_rectangles_fini (&extents);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_compositor_fill (const cairo_compositor_t *compositor,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
const cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_clip_t *clip)
|
||||
{
|
||||
cairo_composite_rectangles_t extents;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_composite_rectangles_init_for_fill (&extents, surface,
|
||||
op, source, path,
|
||||
clip);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
do {
|
||||
while (compositor->fill == NULL)
|
||||
compositor = compositor->delegate;
|
||||
|
||||
status = compositor->fill (compositor, &extents,
|
||||
path, fill_rule, tolerance, antialias);
|
||||
|
||||
compositor = compositor->delegate;
|
||||
} while (status == CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
|
||||
_cairo_composite_rectangles_fini (&extents);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_compositor_glyphs (const cairo_compositor_t *compositor,
|
||||
cairo_surface_t *surface,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
const cairo_clip_t *clip)
|
||||
{
|
||||
cairo_composite_rectangles_t extents;
|
||||
cairo_bool_t overlap;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_composite_rectangles_init_for_glyphs (&extents, surface,
|
||||
op, source,
|
||||
scaled_font,
|
||||
glyphs, num_glyphs,
|
||||
clip, &overlap);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
do {
|
||||
while (compositor->glyphs == NULL)
|
||||
compositor = compositor->delegate;
|
||||
|
||||
status = compositor->glyphs (compositor, &extents,
|
||||
scaled_font, glyphs, num_glyphs, overlap);
|
||||
|
||||
compositor = compositor->delegate;
|
||||
} while (status == CAIRO_INT_STATUS_UNSUPPORTED);
|
||||
|
||||
_cairo_composite_rectangles_fini (&extents);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
@ -158,8 +158,7 @@ _cairo_default_context_push_group (void *abstract_cr, cairo_content_t content)
|
|||
content,
|
||||
extents.width,
|
||||
extents.height,
|
||||
CAIRO_COLOR_TRANSPARENT,
|
||||
TRUE);
|
||||
CAIRO_COLOR_TRANSPARENT);
|
||||
status = group_surface->status;
|
||||
if (unlikely (status))
|
||||
goto bail;
|
||||
|
|
|
|||
174
src/cairo-fallback-compositor.c
Normal file
174
src/cairo-fallback-compositor.c
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2002 University of Southern California
|
||||
* Copyright © 2005 Red Hat, Inc.
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
* Joonas Pihlaja <jpihlaja@cc.helsinki.fi>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-compositor-private.h"
|
||||
#include "cairo-surface-offset-private.h"
|
||||
|
||||
/* high-level compositor interface */
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_fallback_compositor_paint (const cairo_compositor_t *_compositor,
|
||||
cairo_composite_rectangles_t *extents)
|
||||
{
|
||||
cairo_surface_t *image;
|
||||
cairo_int_status_t status;
|
||||
|
||||
image = cairo_surface_map_to_image (extents->surface, &extents->unbounded);
|
||||
status = _cairo_surface_offset_paint (image,
|
||||
-extents->unbounded.x,
|
||||
-extents->unbounded.y,
|
||||
extents->op,
|
||||
&extents->source_pattern.base,
|
||||
extents->clip);
|
||||
cairo_surface_unmap_image (extents->surface, image);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_fallback_compositor_mask (const cairo_compositor_t *_compositor,
|
||||
cairo_composite_rectangles_t *extents)
|
||||
{
|
||||
cairo_surface_t *image;
|
||||
cairo_int_status_t status;
|
||||
|
||||
image = cairo_surface_map_to_image (extents->surface, &extents->unbounded);
|
||||
status = _cairo_surface_offset_mask (image,
|
||||
extents->unbounded.x,
|
||||
extents->unbounded.y,
|
||||
extents->op,
|
||||
&extents->source_pattern.base,
|
||||
&extents->mask_pattern.base,
|
||||
extents->clip);
|
||||
cairo_surface_unmap_image (extents->surface, image);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_fallback_compositor_stroke (const cairo_compositor_t *_compositor,
|
||||
cairo_composite_rectangles_t *extents,
|
||||
const cairo_path_fixed_t *path,
|
||||
const cairo_stroke_style_t *style,
|
||||
const cairo_matrix_t *ctm,
|
||||
const cairo_matrix_t *ctm_inverse,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_surface_t *image;
|
||||
cairo_int_status_t status;
|
||||
|
||||
image = cairo_surface_map_to_image (extents->surface, &extents->unbounded);
|
||||
status = _cairo_surface_offset_stroke (image,
|
||||
extents->unbounded.x,
|
||||
extents->unbounded.y,
|
||||
extents->op,
|
||||
&extents->source_pattern.base,
|
||||
path, style,
|
||||
ctm, ctm_inverse,
|
||||
tolerance,
|
||||
antialias,
|
||||
extents->clip);
|
||||
cairo_surface_unmap_image (extents->surface, image);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_fallback_compositor_fill (const cairo_compositor_t *_compositor,
|
||||
cairo_composite_rectangles_t *extents,
|
||||
const cairo_path_fixed_t *path,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
double tolerance,
|
||||
cairo_antialias_t antialias)
|
||||
{
|
||||
cairo_surface_t *image;
|
||||
cairo_int_status_t status;
|
||||
|
||||
image = cairo_surface_map_to_image (extents->surface, &extents->unbounded);
|
||||
status = _cairo_surface_offset_fill (image,
|
||||
extents->unbounded.x,
|
||||
extents->unbounded.y,
|
||||
extents->op,
|
||||
&extents->source_pattern.base,
|
||||
path,
|
||||
fill_rule, tolerance, antialias,
|
||||
extents->clip);
|
||||
cairo_surface_unmap_image (extents->surface, image);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_fallback_compositor_glyphs (const cairo_compositor_t *_compositor,
|
||||
cairo_composite_rectangles_t *extents,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_bool_t overlap)
|
||||
{
|
||||
cairo_surface_t *image;
|
||||
cairo_int_status_t status;
|
||||
|
||||
image = cairo_surface_map_to_image (extents->surface, &extents->unbounded);
|
||||
status = _cairo_surface_offset_glyphs (image,
|
||||
extents->unbounded.x,
|
||||
extents->unbounded.y,
|
||||
extents->op,
|
||||
&extents->source_pattern.base,
|
||||
scaled_font, glyphs, num_glyphs,
|
||||
extents->clip);
|
||||
cairo_surface_unmap_image (extents->surface, image);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
const cairo_compositor_t _cairo_fallback_compositor = {
|
||||
&__cairo_no_compositor,
|
||||
|
||||
_cairo_fallback_compositor_paint,
|
||||
_cairo_fallback_compositor_mask,
|
||||
_cairo_fallback_compositor_stroke,
|
||||
_cairo_fallback_compositor_fill,
|
||||
_cairo_fallback_compositor_glyphs,
|
||||
};
|
||||
|
|
@ -42,7 +42,9 @@
|
|||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
#if HAS_ATOMIC_OPS
|
||||
#define DISABLE_FREED_POOLS 0
|
||||
|
||||
#if HAS_ATOMIC_OPS && ! DISABLE_FREED_POOLS
|
||||
/* Keep a stash of recently freed clip_paths, since we need to
|
||||
* reallocate them frequently.
|
||||
*/
|
||||
|
|
@ -128,7 +130,7 @@ typedef int freed_pool_t;
|
|||
|
||||
#define _freed_pool_get(pool) NULL
|
||||
#define _freed_pool_put(pool, ptr) free(ptr)
|
||||
#define _freed_pool_reset(ptr) assert((ptr) != NULL)
|
||||
#define _freed_pool_reset(ptr)
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -2586,7 +2586,6 @@ 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 */
|
||||
_cairo_ft_load_truetype_table,
|
||||
_cairo_ft_index_to_ucs4,
|
||||
_cairo_ft_is_synthetic,
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -113,18 +113,20 @@ static void
|
|||
_gl_destroy (void *device)
|
||||
{
|
||||
cairo_gl_context_t *ctx = device;
|
||||
cairo_scaled_font_t *scaled_font, *next_scaled_font;
|
||||
int n;
|
||||
|
||||
ctx->acquire (ctx);
|
||||
|
||||
cairo_list_foreach_entry_safe (scaled_font,
|
||||
next_scaled_font,
|
||||
cairo_scaled_font_t,
|
||||
&ctx->fonts,
|
||||
link)
|
||||
{
|
||||
_cairo_scaled_font_revoke_ownership (scaled_font);
|
||||
while (! cairo_list_is_empty (&ctx->fonts)) {
|
||||
cairo_gl_font_t *font;
|
||||
|
||||
font = cairo_list_first_entry (&ctx->fonts,
|
||||
cairo_gl_font_t,
|
||||
link);
|
||||
|
||||
cairo_list_del (&font->base.link);
|
||||
cairo_list_del (&font->link);
|
||||
free (font);
|
||||
}
|
||||
|
||||
for (n = 0; n < ARRAY_LENGTH (ctx->glyph_cache); n++)
|
||||
|
|
@ -161,6 +163,8 @@ _cairo_gl_context_init (cairo_gl_context_t *ctx)
|
|||
|
||||
_cairo_device_init (&ctx->base, &_cairo_gl_device_backend);
|
||||
|
||||
ctx->compositor = _cairo_gl_span_compositor_get ();
|
||||
|
||||
memset (ctx->glyph_cache, 0, sizeof (ctx->glyph_cache));
|
||||
cairo_list_init (&ctx->fonts);
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@
|
|||
|
||||
#include "cairo-gl-private.h"
|
||||
|
||||
#include "cairo-compositor-private.h"
|
||||
#include "cairo-composite-rectangles-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-image-surface-private.h"
|
||||
|
|
@ -50,11 +51,26 @@
|
|||
#define GLYPH_CACHE_MIN_SIZE 4
|
||||
#define GLYPH_CACHE_MAX_SIZE 128
|
||||
|
||||
typedef struct _cairo_gl_glyph_private {
|
||||
typedef struct _cairo_gl_glyph {
|
||||
cairo_rtree_node_t node;
|
||||
cairo_scaled_glyph_private_t base;
|
||||
cairo_gl_glyph_cache_t *cache;
|
||||
struct { float x, y; } p1, p2;
|
||||
} cairo_gl_glyph_private_t;
|
||||
} cairo_gl_glyph_t;
|
||||
|
||||
static void
|
||||
_cairo_gl_glyph_fini (cairo_scaled_glyph_private_t *_priv,
|
||||
cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_gl_glyph_t *priv = cairo_container_of (_priv, cairo_gl_glyph_t, base);
|
||||
|
||||
priv->node.owner = NULL;
|
||||
if (! priv->node.pinned) {
|
||||
/* XXX thread-safety? Probably ok due to the frozen scaled-font. */
|
||||
_cairo_rtree_node_remove (&priv->cache->rtree, &priv->node);
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
|
||||
|
|
@ -63,7 +79,7 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
|
|||
{
|
||||
cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
|
||||
cairo_gl_surface_t *cache_surface;
|
||||
cairo_gl_glyph_private_t *glyph_private;
|
||||
cairo_gl_glyph_t *glyph_private;
|
||||
cairo_rtree_node_t *node = NULL;
|
||||
cairo_int_status_t status;
|
||||
int width, height;
|
||||
|
|
@ -101,11 +117,15 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
scaled_glyph->surface_private = node;
|
||||
node->owner = &scaled_glyph->surface_private;
|
||||
|
||||
glyph_private = (cairo_gl_glyph_private_t *) node;
|
||||
glyph_private = (cairo_gl_glyph_t *) node;
|
||||
glyph_private->cache = cache;
|
||||
_cairo_scaled_glyph_attach_private (scaled_glyph,
|
||||
&glyph_private->base,
|
||||
cache,
|
||||
_cairo_gl_glyph_fini);
|
||||
|
||||
scaled_glyph->dev_private = glyph_private;
|
||||
scaled_glyph->dev_private_key = cache;
|
||||
|
||||
/* compute tex coords */
|
||||
glyph_private->p1.x = node->x;
|
||||
|
|
@ -122,11 +142,11 @@ _cairo_gl_glyph_cache_add_glyph (cairo_gl_context_t *ctx,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_gl_glyph_private_t *
|
||||
static cairo_gl_glyph_t *
|
||||
_cairo_gl_glyph_cache_lock (cairo_gl_glyph_cache_t *cache,
|
||||
cairo_scaled_glyph_t *scaled_glyph)
|
||||
{
|
||||
return _cairo_rtree_pin (&cache->rtree, scaled_glyph->surface_private);
|
||||
return _cairo_rtree_pin (&cache->rtree, scaled_glyph->dev_private);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
|
|
@ -183,63 +203,29 @@ _cairo_gl_glyph_cache_unlock (cairo_gl_glyph_cache_t *cache)
|
|||
_cairo_rtree_unpin (&cache->rtree);
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_cairo_gl_surface_owns_font (cairo_gl_surface_t *surface,
|
||||
static void
|
||||
_cairo_gl_font_fini (cairo_scaled_font_private_t *_priv,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_device_t *font_private;
|
||||
cairo_gl_font_t *priv = (cairo_gl_font_t *)_priv;
|
||||
|
||||
font_private = scaled_font->surface_private;
|
||||
if ((scaled_font->surface_backend != NULL &&
|
||||
scaled_font->surface_backend != &_cairo_gl_surface_backend) ||
|
||||
(font_private != NULL && font_private != surface->base.device))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_gl_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_list_del (&scaled_font->link);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_gl_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_scaled_font_t *scaled_font)
|
||||
{
|
||||
cairo_gl_glyph_private_t *glyph_private;
|
||||
|
||||
glyph_private = scaled_glyph->surface_private;
|
||||
if (glyph_private != NULL) {
|
||||
glyph_private->node.owner = NULL;
|
||||
if (! glyph_private->node.pinned) {
|
||||
/* XXX thread-safety? Probably ok due to the frozen scaled-font. */
|
||||
_cairo_rtree_node_remove (&glyph_private->cache->rtree,
|
||||
&glyph_private->node);
|
||||
}
|
||||
}
|
||||
cairo_list_del (&priv->link);
|
||||
free (priv);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_render_glyphs (cairo_gl_surface_t *dst,
|
||||
render_glyphs (cairo_gl_surface_t *dst,
|
||||
int dst_x, int dst_y,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
const cairo_composite_rectangles_t *extents,
|
||||
cairo_bool_t *has_component_alpha,
|
||||
int *remaining_glyphs)
|
||||
cairo_composite_glyphs_info_t *info,
|
||||
cairo_bool_t *has_component_alpha)
|
||||
{
|
||||
cairo_format_t last_format = CAIRO_FORMAT_INVALID;
|
||||
cairo_gl_glyph_cache_t *cache = NULL;
|
||||
cairo_gl_context_t *ctx;
|
||||
cairo_gl_composite_t setup;
|
||||
cairo_status_t status;
|
||||
cairo_int_status_t status;
|
||||
int i = 0;
|
||||
|
||||
*has_component_alpha = FALSE;
|
||||
|
|
@ -248,45 +234,30 @@ _render_glyphs (cairo_gl_surface_t *dst,
|
|||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
_cairo_scaled_font_freeze_cache (scaled_font);
|
||||
|
||||
status = _cairo_gl_composite_init (&setup, op, dst,
|
||||
TRUE, &extents->bounded);
|
||||
|
||||
status = _cairo_gl_composite_init (&setup, op, dst, TRUE, &info->extents);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
if (! _cairo_gl_surface_owns_font (dst, scaled_font)) {
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
status = _cairo_gl_composite_set_source (&setup, source,
|
||||
extents->bounded.x,
|
||||
extents->bounded.y,
|
||||
info->extents.x,
|
||||
info->extents.y,
|
||||
dst_x, dst_y,
|
||||
extents->bounded.width,
|
||||
extents->bounded.height);
|
||||
info->extents.width,
|
||||
info->extents.height);
|
||||
if (unlikely (status))
|
||||
goto FINISH;
|
||||
|
||||
if (scaled_font->surface_private == NULL) {
|
||||
scaled_font->surface_private = ctx;
|
||||
scaled_font->surface_backend = &_cairo_gl_surface_backend;
|
||||
cairo_list_add (&scaled_font->link, &ctx->fonts);
|
||||
}
|
||||
|
||||
_cairo_gl_composite_set_clip_region (&setup,
|
||||
_cairo_clip_get_region (extents->clip));
|
||||
//_cairo_gl_composite_set_clip_region (&setup, _cairo_clip_get_region (extents->clip));
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
for (i = 0; i < info->num_glyphs; i++) {
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
cairo_gl_glyph_private_t *glyph;
|
||||
cairo_gl_glyph_t *glyph;
|
||||
double x_offset, y_offset;
|
||||
double x1, x2, y1, y2;
|
||||
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
glyphs[i].index,
|
||||
status = _cairo_scaled_glyph_lookup (info->font,
|
||||
info->glyphs[i].index,
|
||||
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
||||
&scaled_glyph);
|
||||
if (unlikely (status))
|
||||
|
|
@ -297,13 +268,6 @@ _render_glyphs (cairo_gl_surface_t *dst,
|
|||
{
|
||||
continue;
|
||||
}
|
||||
if (scaled_glyph->surface->width > GLYPH_CACHE_MAX_SIZE ||
|
||||
scaled_glyph->surface->height > GLYPH_CACHE_MAX_SIZE)
|
||||
{
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
if (scaled_glyph->surface->format != last_format) {
|
||||
status = cairo_gl_context_get_glyph_cache (ctx,
|
||||
scaled_glyph->surface->format,
|
||||
|
|
@ -331,7 +295,16 @@ _render_glyphs (cairo_gl_surface_t *dst,
|
|||
goto FINISH;
|
||||
}
|
||||
|
||||
if (scaled_glyph->surface_private == NULL) {
|
||||
if (scaled_glyph->dev_private_key != cache) {
|
||||
cairo_scaled_glyph_private_t *priv;
|
||||
|
||||
priv = _cairo_scaled_glyph_find_private (scaled_glyph, cache);
|
||||
if (priv) {
|
||||
scaled_glyph->dev_private_key = cache;
|
||||
scaled_glyph->dev_private = cairo_container_of (priv,
|
||||
cairo_gl_glyph_t,
|
||||
base);;
|
||||
} else {
|
||||
status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph);
|
||||
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
|
|
@ -341,15 +314,16 @@ _render_glyphs (cairo_gl_surface_t *dst,
|
|||
status = _cairo_gl_glyph_cache_add_glyph (ctx, cache, scaled_glyph);
|
||||
}
|
||||
|
||||
if (unlikely (_cairo_status_is_error (status)))
|
||||
if (unlikely (_cairo_int_status_is_error (status)))
|
||||
goto FINISH;
|
||||
}
|
||||
}
|
||||
|
||||
x_offset = scaled_glyph->surface->base.device_transform.x0;
|
||||
y_offset = scaled_glyph->surface->base.device_transform.y0;
|
||||
|
||||
x1 = _cairo_lround (glyphs[i].x - x_offset);
|
||||
y1 = _cairo_lround (glyphs[i].y - y_offset);
|
||||
x1 = _cairo_lround (info->glyphs[i].x - x_offset);
|
||||
y1 = _cairo_lround (info->glyphs[i].y - y_offset);
|
||||
x2 = x1 + scaled_glyph->surface->width;
|
||||
y2 = y1 + scaled_glyph->surface->height;
|
||||
|
||||
|
|
@ -362,75 +336,59 @@ _render_glyphs (cairo_gl_surface_t *dst,
|
|||
|
||||
status = CAIRO_STATUS_SUCCESS;
|
||||
FINISH:
|
||||
_cairo_scaled_font_thaw_cache (scaled_font);
|
||||
|
||||
status = _cairo_gl_context_release (ctx, status);
|
||||
|
||||
_cairo_gl_composite_fini (&setup);
|
||||
|
||||
*remaining_glyphs = num_glyphs - i;
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t *dst,
|
||||
render_glyphs_via_mask (cairo_gl_surface_t *dst,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_composite_rectangles_t *extents,
|
||||
int *remaining_glyphs)
|
||||
const cairo_surface_t *source,
|
||||
cairo_composite_glyphs_info_t *info)
|
||||
{
|
||||
cairo_surface_t *mask;
|
||||
cairo_status_t status;
|
||||
cairo_bool_t has_component_alpha;
|
||||
cairo_clip_t *saved_clip;
|
||||
int i;
|
||||
|
||||
/* XXX: For non-CA, this should be CAIRO_CONTENT_ALPHA to save memory */
|
||||
mask = cairo_gl_surface_create (dst->base.device,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
extents->bounded.width,
|
||||
extents->bounded.height);
|
||||
info->extents.width,
|
||||
info->extents.height);
|
||||
if (unlikely (mask->status))
|
||||
return mask->status;
|
||||
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
glyphs[i].x -= extents->bounded.x;
|
||||
glyphs[i].y -= extents->bounded.y;
|
||||
for (i = 0; i < info->num_glyphs; i++) {
|
||||
info->glyphs[i].x -= info->extents.x;
|
||||
info->glyphs[i].y -= info->extents.y;
|
||||
}
|
||||
|
||||
|
||||
saved_clip = extents->clip;
|
||||
extents->clip = NULL;
|
||||
status = _render_glyphs ((cairo_gl_surface_t *) mask, 0, 0,
|
||||
status = render_glyphs ((cairo_gl_surface_t *) mask, 0, 0,
|
||||
CAIRO_OPERATOR_ADD,
|
||||
&_cairo_pattern_white.base,
|
||||
glyphs, num_glyphs, scaled_font,
|
||||
extents,
|
||||
&has_component_alpha,
|
||||
remaining_glyphs);
|
||||
extents->clip = saved_clip;
|
||||
|
||||
info, &has_component_alpha);
|
||||
if (likely (status == CAIRO_STATUS_SUCCESS)) {
|
||||
/* XXX composite */
|
||||
#if 0
|
||||
cairo_surface_pattern_t mask_pattern;
|
||||
|
||||
mask->is_clear = FALSE;
|
||||
_cairo_pattern_init_for_surface (&mask_pattern, mask);
|
||||
mask_pattern.base.has_component_alpha = has_component_alpha;
|
||||
cairo_matrix_init_translate (&mask_pattern.base.matrix,
|
||||
-extents->bounded.x, -extents->bounded.y);
|
||||
-info->extents.x, -info->extents.y);
|
||||
status = _cairo_surface_mask (&dst->base, op,
|
||||
source, &mask_pattern.base,
|
||||
extents->clip);
|
||||
NULL);
|
||||
_cairo_pattern_fini (&mask_pattern.base);
|
||||
#endif
|
||||
} else {
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
glyphs[i].x += extents->bounded.x;
|
||||
glyphs[i].y += extents->bounded.y;
|
||||
for (i = 0; i < info->num_glyphs; i++) {
|
||||
info->glyphs[i].x += info->extents.x;
|
||||
info->glyphs[i].y += info->extents.y;
|
||||
}
|
||||
*remaining_glyphs = num_glyphs;
|
||||
}
|
||||
|
||||
cairo_surface_destroy (mask);
|
||||
|
|
@ -438,143 +396,62 @@ _cairo_gl_surface_show_glyphs_via_mask (cairo_gl_surface_t *dst,
|
|||
return status;
|
||||
}
|
||||
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_gl_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle);
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_gl_surface_show_glyphs (void *abstract_dst,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *source,
|
||||
cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
_cairo_gl_check_composite_glyphs (const cairo_composite_rectangles_t *extents,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
const cairo_clip_t *clip,
|
||||
int *remaining_glyphs)
|
||||
cairo_glyph_t *glyphs,
|
||||
int *num_glyphs)
|
||||
{
|
||||
cairo_gl_surface_t *dst = abstract_dst;
|
||||
cairo_composite_rectangles_t extents;
|
||||
cairo_rectangle_int_t unbounded;
|
||||
cairo_bool_t overlap, use_mask = FALSE;
|
||||
cairo_bool_t has_component_alpha;
|
||||
cairo_status_t status;
|
||||
int i;
|
||||
|
||||
if (! _cairo_gl_operator_is_supported (op))
|
||||
if (! _cairo_gl_operator_is_supported (extents->op))
|
||||
return UNSUPPORTED ("unsupported operator");
|
||||
|
||||
if (! _cairo_operator_bounded_by_mask (op))
|
||||
use_mask |= TRUE;
|
||||
/* XXX use individual masks for large glyphs? */
|
||||
if (ceil (scaled_font->max_scale) >= GLYPH_CACHE_MAX_SIZE)
|
||||
return UNSUPPORTED ("glyphs too large");
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_gl_composite_glyphs (void *_dst,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *_src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
cairo_composite_glyphs_info_t *info)
|
||||
{
|
||||
cairo_gl_surface_t *dst = _dst;
|
||||
cairo_bool_t has_component_alpha;
|
||||
int i;
|
||||
|
||||
/* If any of the glyphs are component alpha, we have to go through a mask,
|
||||
* since only _cairo_gl_surface_composite() currently supports component
|
||||
* alpha.
|
||||
*/
|
||||
if (!use_mask && op != CAIRO_OPERATOR_OVER) {
|
||||
for (i = 0; i < num_glyphs; i++) {
|
||||
if (!dst->base.is_clear && ! info->use_mask && op != CAIRO_OPERATOR_OVER) {
|
||||
for (i = 0; i < info->num_glyphs; i++) {
|
||||
cairo_scaled_glyph_t *scaled_glyph;
|
||||
|
||||
status = _cairo_scaled_glyph_lookup (scaled_font,
|
||||
glyphs[i].index,
|
||||
if (_cairo_scaled_glyph_lookup (info->font, info->glyphs[i].index,
|
||||
CAIRO_SCALED_GLYPH_INFO_SURFACE,
|
||||
&scaled_glyph);
|
||||
if (!_cairo_status_is_error (status) &&
|
||||
&scaled_glyph) == CAIRO_INT_STATUS_SUCCESS &&
|
||||
scaled_glyph->surface->format == CAIRO_FORMAT_ARGB32)
|
||||
{
|
||||
use_mask = TRUE;
|
||||
info->use_mask = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* For CLEAR, cairo's rendering equation (quoting Owen's description in:
|
||||
* http://lists.cairographics.org/archives/cairo/2005-August/004992.html)
|
||||
* is:
|
||||
* mask IN clip ? src OP dest : dest
|
||||
* or more simply:
|
||||
* mask IN CLIP ? 0 : dest
|
||||
*
|
||||
* where the ternary operator A ? B : C is (A * B) + ((1 - A) * C).
|
||||
*
|
||||
* The model we use in _cairo_gl_set_operator() is Render's:
|
||||
* src IN mask IN clip OP dest
|
||||
* which would boil down to:
|
||||
* 0 (bounded by the extents of the drawing).
|
||||
*
|
||||
* However, we can do a Render operation using an opaque source
|
||||
* and DEST_OUT to produce:
|
||||
* 1 IN mask IN clip DEST_OUT dest
|
||||
* which is
|
||||
* mask IN clip ? 0 : dest
|
||||
*/
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
source = &_cairo_pattern_white.base;
|
||||
op = CAIRO_OPERATOR_DEST_OUT;
|
||||
}
|
||||
|
||||
/* For SOURCE, cairo's rendering equation is:
|
||||
* (mask IN clip) ? src OP dest : dest
|
||||
* or more simply:
|
||||
* (mask IN clip) ? src : dest.
|
||||
*
|
||||
* If we just used the Render equation, we would get:
|
||||
* (src IN mask IN clip) OP dest
|
||||
* or:
|
||||
* (src IN mask IN clip) bounded by extents of the drawing.
|
||||
*
|
||||
* The trick is that for GL blending, we only get our 4 source values
|
||||
* into the blender, and since we need all 4 components of source, we
|
||||
* can't also get the mask IN clip into the blender. But if we did
|
||||
* two passes we could make it work:
|
||||
* dest = (mask IN clip) DEST_OUT dest
|
||||
* dest = src IN mask IN clip ADD dest
|
||||
*
|
||||
* But for now, composite via an intermediate mask.
|
||||
*/
|
||||
if (op == CAIRO_OPERATOR_SOURCE)
|
||||
use_mask |= TRUE;
|
||||
|
||||
/* XXX we don't need ownership of the font as we use a global
|
||||
* glyph cache -- but we do need scaled_glyph eviction notification. :-(
|
||||
*/
|
||||
if (! _cairo_gl_surface_owns_font (dst, scaled_font))
|
||||
return UNSUPPORTED ("do not control font");
|
||||
|
||||
_cairo_gl_surface_get_extents (dst, &unbounded);
|
||||
status = _cairo_composite_rectangles_init_for_glyphs (&extents,
|
||||
&unbounded,
|
||||
op, source,
|
||||
scaled_font,
|
||||
glyphs, num_glyphs,
|
||||
clip, &overlap);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
/* If the glyphs overlap, we need to build an intermediate mask rather
|
||||
* then perform the compositing directly.
|
||||
*/
|
||||
use_mask |= overlap;
|
||||
use_mask |= ! _cairo_clip_is_region (extents.clip);
|
||||
|
||||
if (use_mask) {
|
||||
status = _cairo_gl_surface_show_glyphs_via_mask (dst, op,
|
||||
source,
|
||||
glyphs, num_glyphs,
|
||||
scaled_font,
|
||||
&extents,
|
||||
remaining_glyphs);
|
||||
if (info->use_mask) {
|
||||
return render_glyphs_via_mask (dst, op, _src, info);
|
||||
} else {
|
||||
status = _render_glyphs (dst, extents.bounded.x, extents.bounded.y,
|
||||
op, source,
|
||||
glyphs, num_glyphs, scaled_font,
|
||||
&extents,
|
||||
&has_component_alpha,
|
||||
remaining_glyphs);
|
||||
return render_glyphs (dst, dst_x, dst_y,
|
||||
op, _src, info,
|
||||
&has_component_alpha);
|
||||
}
|
||||
|
||||
_cairo_composite_rectangles_fini (&extents);
|
||||
return status;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -584,7 +461,7 @@ _cairo_gl_glyph_cache_init (cairo_gl_glyph_cache_t *cache)
|
|||
GLYPH_CACHE_WIDTH,
|
||||
GLYPH_CACHE_HEIGHT,
|
||||
GLYPH_CACHE_MIN_SIZE,
|
||||
sizeof (cairo_gl_glyph_private_t));
|
||||
sizeof (cairo_gl_glyph_t));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -598,4 +475,3 @@ _cairo_gl_glyph_cache_fini (cairo_gl_context_t *ctx,
|
|||
cache->pattern.surface = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
538
src/cairo-gl-operand.c
Normal file
538
src/cairo-gl-operand.c
Normal file
|
|
@ -0,0 +1,538 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Eric Anholt
|
||||
* Copyright © 2009 Chris Wilson
|
||||
* Copyright © 2005,2010 Red Hat, Inc
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benjamin Otte <otte@gnome.org>
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-gl-private.h"
|
||||
|
||||
#include "cairo-composite-rectangles-private.h"
|
||||
#include "cairo-compositor-private.h"
|
||||
#include "cairo-default-context-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-image-surface-private.h"
|
||||
#include "cairo-surface-backend-private.h"
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_gl_create_gradient_texture (cairo_gl_surface_t *dst,
|
||||
const cairo_gradient_pattern_t *pattern,
|
||||
cairo_gl_gradient_t **gradient)
|
||||
{
|
||||
cairo_gl_context_t *ctx;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_gl_context_acquire (dst->base.device, &ctx);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = _cairo_gl_gradient_create (ctx, pattern->n_stops, pattern->stops, gradient);
|
||||
|
||||
return _cairo_gl_context_release (ctx, status);
|
||||
}
|
||||
|
||||
/*
|
||||
* Like cairo_pattern_acquire_surface(), but returns a matrix that transforms
|
||||
* from dest to src coords.
|
||||
*/
|
||||
static cairo_status_t
|
||||
_cairo_gl_pattern_texture_setup (cairo_gl_operand_t *operand,
|
||||
const cairo_pattern_t *src,
|
||||
cairo_gl_surface_t *dst,
|
||||
int src_x, int src_y,
|
||||
int dst_x, int dst_y,
|
||||
int width, int height)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_matrix_t m;
|
||||
cairo_gl_surface_t *surface;
|
||||
cairo_surface_attributes_t *attributes;
|
||||
|
||||
attributes = &operand->texture.attributes;
|
||||
|
||||
#if 0
|
||||
status = _cairo_pattern_acquire_surface (src, &dst->base,
|
||||
src_x, src_y,
|
||||
width, height,
|
||||
CAIRO_PATTERN_ACQUIRE_NONE,
|
||||
(cairo_surface_t **)
|
||||
&surface,
|
||||
attributes);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
#endif
|
||||
|
||||
if (_cairo_gl_device_requires_power_of_two_textures (dst->base.device) &&
|
||||
(attributes->extend == CAIRO_EXTEND_REPEAT ||
|
||||
attributes->extend == CAIRO_EXTEND_REFLECT))
|
||||
{
|
||||
return UNSUPPORTED ("EXT_texture_rectangle with repeat/reflect");
|
||||
}
|
||||
|
||||
assert (_cairo_gl_surface_is_texture (surface));
|
||||
|
||||
operand->type = CAIRO_GL_OPERAND_TEXTURE;
|
||||
operand->texture.surface = surface;
|
||||
operand->texture.tex = surface->tex;
|
||||
/* Translate the matrix from
|
||||
* (unnormalized src -> unnormalized src) to
|
||||
* (unnormalized dst -> unnormalized src)
|
||||
*/
|
||||
cairo_matrix_init_translate (&m,
|
||||
src_x - dst_x + attributes->x_offset,
|
||||
src_y - dst_y + attributes->y_offset);
|
||||
cairo_matrix_multiply (&attributes->matrix,
|
||||
&m,
|
||||
&attributes->matrix);
|
||||
|
||||
|
||||
/* Translate the matrix from
|
||||
* (unnormalized dst -> unnormalized src) to
|
||||
* (unnormalized dst -> normalized src)
|
||||
*/
|
||||
if (_cairo_gl_device_requires_power_of_two_textures (dst->base.device)) {
|
||||
cairo_matrix_init_scale (&m,
|
||||
1.0,
|
||||
1.0);
|
||||
} else {
|
||||
cairo_matrix_init_scale (&m,
|
||||
1.0 / surface->width,
|
||||
1.0 / surface->height);
|
||||
}
|
||||
cairo_matrix_multiply (&attributes->matrix,
|
||||
&attributes->matrix,
|
||||
&m);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_gl_solid_operand_init (cairo_gl_operand_t *operand,
|
||||
const cairo_color_t *color)
|
||||
{
|
||||
operand->type = CAIRO_GL_OPERAND_CONSTANT;
|
||||
operand->constant.color[0] = color->red * color->alpha;
|
||||
operand->constant.color[1] = color->green * color->alpha;
|
||||
operand->constant.color[2] = color->blue * color->alpha;
|
||||
operand->constant.color[3] = color->alpha;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gl_gradient_operand_init (cairo_gl_operand_t *operand,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_gl_surface_t *dst,
|
||||
int src_x, int src_y,
|
||||
int dst_x, int dst_y)
|
||||
{
|
||||
const cairo_gradient_pattern_t *gradient = (const cairo_gradient_pattern_t *)pattern;
|
||||
cairo_status_t status;
|
||||
|
||||
assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
|
||||
gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
|
||||
|
||||
if (! _cairo_gl_device_has_glsl (dst->base.device))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_gl_create_gradient_texture (dst,
|
||||
gradient,
|
||||
&operand->gradient.gradient);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
|
||||
cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
|
||||
double x0, y0, dx, dy, sf, offset;
|
||||
|
||||
dx = linear->pd2.x - linear->pd1.x;
|
||||
dy = linear->pd2.y - linear->pd1.y;
|
||||
sf = 1.0 / (dx * dx + dy * dy);
|
||||
dx *= sf;
|
||||
dy *= sf;
|
||||
|
||||
x0 = linear->pd1.x;
|
||||
y0 = linear->pd1.y;
|
||||
offset = dx * x0 + dy * y0;
|
||||
|
||||
operand->type = CAIRO_GL_OPERAND_LINEAR_GRADIENT;
|
||||
|
||||
cairo_matrix_init (&operand->gradient.m, dx, 0, dy, 1, -offset, 0);
|
||||
if (! _cairo_matrix_is_identity (&pattern->matrix)) {
|
||||
cairo_matrix_multiply (&operand->gradient.m,
|
||||
&pattern->matrix,
|
||||
&operand->gradient.m);
|
||||
}
|
||||
} else {
|
||||
cairo_matrix_t m;
|
||||
cairo_circle_double_t circles[2];
|
||||
double x0, y0, r0, dx, dy, dr;
|
||||
|
||||
/*
|
||||
* Some fragment shader implementations use half-floats to
|
||||
* represent numbers, so the maximum number they can represent
|
||||
* is about 2^14. Some intermediate computations used in the
|
||||
* radial gradient shaders can produce results of up to 2*k^4.
|
||||
* Setting k=8 makes the maximum result about 8192 (assuming
|
||||
* that the extreme circles are not much smaller than the
|
||||
* destination image).
|
||||
*/
|
||||
_cairo_gradient_pattern_fit_to_range (gradient, 8.,
|
||||
&operand->gradient.m, circles);
|
||||
|
||||
x0 = circles[0].center.x;
|
||||
y0 = circles[0].center.y;
|
||||
r0 = circles[0].radius;
|
||||
dx = circles[1].center.x - x0;
|
||||
dy = circles[1].center.y - y0;
|
||||
dr = circles[1].radius - r0;
|
||||
|
||||
operand->gradient.a = dx * dx + dy * dy - dr * dr;
|
||||
operand->gradient.radius_0 = r0;
|
||||
operand->gradient.circle_d.center.x = dx;
|
||||
operand->gradient.circle_d.center.y = dy;
|
||||
operand->gradient.circle_d.radius = dr;
|
||||
|
||||
if (operand->gradient.a == 0)
|
||||
operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0;
|
||||
else if (pattern->extend == CAIRO_EXTEND_NONE)
|
||||
operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE;
|
||||
else
|
||||
operand->type = CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT;
|
||||
|
||||
cairo_matrix_init_translate (&m, -x0, -y0);
|
||||
cairo_matrix_multiply (&operand->gradient.m,
|
||||
&operand->gradient.m,
|
||||
&m);
|
||||
}
|
||||
|
||||
cairo_matrix_translate (&operand->gradient.m, src_x - dst_x, src_y - dst_y);
|
||||
|
||||
operand->gradient.extend = pattern->extend;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_gl_operand_destroy (cairo_gl_operand_t *operand)
|
||||
{
|
||||
switch (operand->type) {
|
||||
case CAIRO_GL_OPERAND_CONSTANT:
|
||||
break;
|
||||
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
|
||||
_cairo_gl_gradient_destroy (operand->gradient.gradient);
|
||||
break;
|
||||
case CAIRO_GL_OPERAND_TEXTURE:
|
||||
break;
|
||||
default:
|
||||
case CAIRO_GL_OPERAND_COUNT:
|
||||
ASSERT_NOT_REACHED;
|
||||
case CAIRO_GL_OPERAND_NONE:
|
||||
break;
|
||||
}
|
||||
|
||||
operand->type = CAIRO_GL_OPERAND_NONE;
|
||||
}
|
||||
|
||||
cairo_int_status_t
|
||||
_cairo_gl_operand_init (cairo_gl_operand_t *operand,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_gl_surface_t *dst,
|
||||
int src_x, int src_y,
|
||||
int dst_x, int dst_y,
|
||||
int width, int height)
|
||||
{
|
||||
cairo_int_status_t status;
|
||||
|
||||
switch (pattern->type) {
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
_cairo_gl_solid_operand_init (operand,
|
||||
&((cairo_solid_pattern_t *) pattern)->color);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
status = _cairo_gl_gradient_operand_init (operand,
|
||||
pattern, dst,
|
||||
src_x, src_y,
|
||||
dst_x, dst_y);
|
||||
if (status != CAIRO_INT_STATUS_UNSUPPORTED)
|
||||
return status;
|
||||
|
||||
/* fall through */
|
||||
|
||||
default:
|
||||
case CAIRO_PATTERN_TYPE_MESH:
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
return _cairo_gl_pattern_texture_setup (operand,
|
||||
pattern, dst,
|
||||
src_x, src_y,
|
||||
dst_x, dst_y,
|
||||
width, height);
|
||||
}
|
||||
}
|
||||
|
||||
cairo_filter_t
|
||||
_cairo_gl_operand_get_filter (cairo_gl_operand_t *operand)
|
||||
{
|
||||
cairo_filter_t filter;
|
||||
|
||||
switch ((int) operand->type) {
|
||||
case CAIRO_GL_OPERAND_TEXTURE:
|
||||
filter = operand->texture.attributes.filter;
|
||||
break;
|
||||
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
|
||||
filter = CAIRO_FILTER_BILINEAR;
|
||||
break;
|
||||
default:
|
||||
filter = CAIRO_FILTER_DEFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
GLint
|
||||
_cairo_gl_operand_get_gl_filter (cairo_gl_operand_t *operand)
|
||||
{
|
||||
cairo_filter_t filter = _cairo_gl_operand_get_filter (operand);
|
||||
|
||||
return filter != CAIRO_FILTER_FAST && filter != CAIRO_FILTER_NEAREST ?
|
||||
GL_LINEAR :
|
||||
GL_NEAREST;
|
||||
}
|
||||
|
||||
cairo_extend_t
|
||||
_cairo_gl_operand_get_extend (cairo_gl_operand_t *operand)
|
||||
{
|
||||
cairo_extend_t extend;
|
||||
|
||||
switch ((int) operand->type) {
|
||||
case CAIRO_GL_OPERAND_TEXTURE:
|
||||
extend = operand->texture.attributes.extend;
|
||||
break;
|
||||
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
|
||||
extend = operand->gradient.extend;
|
||||
break;
|
||||
default:
|
||||
extend = CAIRO_EXTEND_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
return extend;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
|
||||
cairo_gl_operand_t *operand,
|
||||
cairo_gl_tex_t tex_unit)
|
||||
{
|
||||
char uniform_name[50];
|
||||
char *custom_part;
|
||||
static const char *names[] = { "source", "mask" };
|
||||
|
||||
strcpy (uniform_name, names[tex_unit]);
|
||||
custom_part = uniform_name + strlen (names[tex_unit]);
|
||||
|
||||
switch (operand->type) {
|
||||
default:
|
||||
case CAIRO_GL_OPERAND_COUNT:
|
||||
ASSERT_NOT_REACHED;
|
||||
case CAIRO_GL_OPERAND_NONE:
|
||||
break;
|
||||
case CAIRO_GL_OPERAND_CONSTANT:
|
||||
strcpy (custom_part, "_constant");
|
||||
_cairo_gl_shader_bind_vec4 (ctx,
|
||||
uniform_name,
|
||||
operand->constant.color[0],
|
||||
operand->constant.color[1],
|
||||
operand->constant.color[2],
|
||||
operand->constant.color[3]);
|
||||
break;
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
|
||||
strcpy (custom_part, "_a");
|
||||
_cairo_gl_shader_bind_float (ctx,
|
||||
uniform_name,
|
||||
operand->gradient.a);
|
||||
/* fall through */
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
|
||||
strcpy (custom_part, "_circle_d");
|
||||
_cairo_gl_shader_bind_vec3 (ctx,
|
||||
uniform_name,
|
||||
operand->gradient.circle_d.center.x,
|
||||
operand->gradient.circle_d.center.y,
|
||||
operand->gradient.circle_d.radius);
|
||||
strcpy (custom_part, "_radius_0");
|
||||
_cairo_gl_shader_bind_float (ctx,
|
||||
uniform_name,
|
||||
operand->gradient.radius_0);
|
||||
/* fall through */
|
||||
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
|
||||
case CAIRO_GL_OPERAND_TEXTURE:
|
||||
/*
|
||||
* For GLES2 we use shaders to implement GL_CLAMP_TO_BORDER (used
|
||||
* with CAIRO_EXTEND_NONE). When bilinear filtering is enabled,
|
||||
* these shaders need the texture dimensions for their calculations.
|
||||
*/
|
||||
if (ctx->gl_flavor == CAIRO_GL_FLAVOR_ES &&
|
||||
_cairo_gl_operand_get_extend (operand) == CAIRO_EXTEND_NONE &&
|
||||
_cairo_gl_operand_get_gl_filter (operand) == GL_LINEAR)
|
||||
{
|
||||
float width, height;
|
||||
if (operand->type == CAIRO_GL_OPERAND_TEXTURE) {
|
||||
width = operand->texture.surface->width;
|
||||
height = operand->texture.surface->height;
|
||||
}
|
||||
else {
|
||||
width = operand->gradient.gradient->cache_entry.size,
|
||||
height = 1;
|
||||
}
|
||||
strcpy (custom_part, "_texdims");
|
||||
_cairo_gl_shader_bind_vec2 (ctx, uniform_name, width, height);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cairo_bool_t
|
||||
_cairo_gl_operand_needs_setup (cairo_gl_operand_t *dest,
|
||||
cairo_gl_operand_t *source,
|
||||
unsigned int vertex_offset)
|
||||
{
|
||||
if (dest->type != source->type)
|
||||
return TRUE;
|
||||
if (dest->vertex_offset != vertex_offset)
|
||||
return TRUE;
|
||||
|
||||
switch (source->type) {
|
||||
case CAIRO_GL_OPERAND_NONE:
|
||||
return FALSE;
|
||||
case CAIRO_GL_OPERAND_CONSTANT:
|
||||
return dest->constant.color[0] != source->constant.color[0] ||
|
||||
dest->constant.color[1] != source->constant.color[1] ||
|
||||
dest->constant.color[2] != source->constant.color[2] ||
|
||||
dest->constant.color[3] != source->constant.color[3];
|
||||
case CAIRO_GL_OPERAND_TEXTURE:
|
||||
return dest->texture.surface != source->texture.surface ||
|
||||
dest->texture.attributes.extend != source->texture.attributes.extend ||
|
||||
dest->texture.attributes.filter != source->texture.attributes.filter ||
|
||||
dest->texture.attributes.has_component_alpha != source->texture.attributes.has_component_alpha;
|
||||
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
|
||||
/* XXX: improve this */
|
||||
return TRUE;
|
||||
default:
|
||||
case CAIRO_GL_OPERAND_COUNT:
|
||||
ASSERT_NOT_REACHED;
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
_cairo_gl_operand_get_vertex_size (cairo_gl_operand_type_t type)
|
||||
{
|
||||
switch (type) {
|
||||
default:
|
||||
case CAIRO_GL_OPERAND_COUNT:
|
||||
ASSERT_NOT_REACHED;
|
||||
case CAIRO_GL_OPERAND_NONE:
|
||||
case CAIRO_GL_OPERAND_CONSTANT:
|
||||
return 0;
|
||||
case CAIRO_GL_OPERAND_TEXTURE:
|
||||
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
|
||||
return 2 * sizeof (GLfloat);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_gl_operand_emit (cairo_gl_operand_t *operand,
|
||||
GLfloat ** vb,
|
||||
GLfloat x,
|
||||
GLfloat y,
|
||||
uint8_t alpha)
|
||||
{
|
||||
switch (operand->type) {
|
||||
default:
|
||||
case CAIRO_GL_OPERAND_COUNT:
|
||||
ASSERT_NOT_REACHED;
|
||||
case CAIRO_GL_OPERAND_NONE:
|
||||
case CAIRO_GL_OPERAND_CONSTANT:
|
||||
break;
|
||||
case CAIRO_GL_OPERAND_LINEAR_GRADIENT:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE:
|
||||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
|
||||
{
|
||||
double s = x;
|
||||
double t = y;
|
||||
|
||||
cairo_matrix_transform_point (&operand->gradient.m, &s, &t);
|
||||
|
||||
*(*vb)++ = s;
|
||||
*(*vb)++ = t;
|
||||
}
|
||||
break;
|
||||
case CAIRO_GL_OPERAND_TEXTURE:
|
||||
{
|
||||
cairo_surface_attributes_t *src_attributes = &operand->texture.attributes;
|
||||
double s = x;
|
||||
double t = y;
|
||||
|
||||
cairo_matrix_transform_point (&src_attributes->matrix, &s, &t);
|
||||
*(*vb)++ = s;
|
||||
*(*vb)++ = t;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -48,16 +48,17 @@
|
|||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-gl.h"
|
||||
#include "cairo-gl-gradient-private.h"
|
||||
|
||||
#include "cairo-device-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-rtree-private.h"
|
||||
#include "cairo-scaled-font-private.h"
|
||||
#include "cairo-spans-compositor-private.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "cairo-gl.h"
|
||||
|
||||
#if CAIRO_HAS_GL_SURFACE
|
||||
#include <GL/gl.h>
|
||||
#include <GL/glext.h>
|
||||
|
|
@ -138,7 +139,6 @@ typedef enum cairo_gl_operand_type {
|
|||
CAIRO_GL_OPERAND_RADIAL_GRADIENT_A0,
|
||||
CAIRO_GL_OPERAND_RADIAL_GRADIENT_NONE,
|
||||
CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT,
|
||||
CAIRO_GL_OPERAND_SPANS,
|
||||
|
||||
CAIRO_GL_OPERAND_COUNT
|
||||
} cairo_gl_operand_type_t;
|
||||
|
|
@ -161,11 +161,10 @@ typedef enum cairo_gl_shader_in {
|
|||
typedef enum cairo_gl_var_type {
|
||||
CAIRO_GL_VAR_NONE,
|
||||
CAIRO_GL_VAR_TEXCOORDS,
|
||||
CAIRO_GL_VAR_COVERAGE
|
||||
} cairo_gl_var_type_t;
|
||||
|
||||
#define cairo_gl_var_type_hash(src,mask,dest) ((mask) << 2 | (src << 1) | (dest))
|
||||
#define CAIRO_GL_VAR_TYPE_MAX ((CAIRO_GL_VAR_COVERAGE << 2) | (CAIRO_GL_VAR_TEXCOORDS << 1) | CAIRO_GL_VAR_TEXCOORDS)
|
||||
#define cairo_gl_var_type_hash(src,mask,spans,dest) ((spans) << 3) | ((mask) << 2 | (src << 1) | (dest))
|
||||
#define CAIRO_GL_VAR_TYPE_MAX ((CAIRO_GL_VAR_TEXCOORDS << 3) | (CAIRO_GL_VAR_TEXCOORDS << 2) | (CAIRO_GL_VAR_TEXCOORDS << 1) | CAIRO_GL_VAR_TEXCOORDS)
|
||||
|
||||
/* This union structure describes a potential source or mask operand to the
|
||||
* compositing equation.
|
||||
|
|
@ -259,6 +258,8 @@ typedef struct _cairo_gl_dispatch {
|
|||
struct _cairo_gl_context {
|
||||
cairo_device_t base;
|
||||
|
||||
const cairo_compositor_t *compositor;
|
||||
|
||||
GLuint texture_load_pbo;
|
||||
GLuint vbo;
|
||||
GLint max_framebuffer_size;
|
||||
|
|
@ -283,6 +284,7 @@ struct _cairo_gl_context {
|
|||
cairo_gl_shader_t *current_shader;
|
||||
|
||||
cairo_gl_operand_t operands[2];
|
||||
cairo_bool_t spans;
|
||||
|
||||
char *vb;
|
||||
char *vb_mem;
|
||||
|
|
@ -311,8 +313,15 @@ typedef struct _cairo_gl_composite {
|
|||
|
||||
cairo_gl_operand_t src;
|
||||
cairo_gl_operand_t mask;
|
||||
cairo_bool_t spans;
|
||||
} cairo_gl_composite_t;
|
||||
|
||||
typedef struct _cairo_gl_font {
|
||||
cairo_scaled_font_private_t base;
|
||||
cairo_device_t *device;
|
||||
cairo_list_t link;
|
||||
} cairo_gl_font_t;
|
||||
|
||||
cairo_private extern const cairo_surface_backend_t _cairo_gl_surface_backend;
|
||||
|
||||
static cairo_always_inline GLenum
|
||||
|
|
@ -432,6 +441,13 @@ _cairo_gl_composite_set_source (cairo_gl_composite_t *setup,
|
|||
int src_x, int src_y,
|
||||
int dst_x, int dst_y,
|
||||
int width, int height);
|
||||
cairo_private void
|
||||
_cairo_gl_composite_set_solid_source (cairo_gl_composite_t *setup,
|
||||
const cairo_color_t *color);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_composite_set_source_operand (cairo_gl_composite_t *setup,
|
||||
const cairo_gl_operand_t *source);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_gl_composite_set_mask (cairo_gl_composite_t *setup,
|
||||
|
|
@ -441,7 +457,11 @@ _cairo_gl_composite_set_mask (cairo_gl_composite_t *setup,
|
|||
int width, int height);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_composite_set_mask_spans (cairo_gl_composite_t *setup);
|
||||
_cairo_gl_composite_set_mask_operand (cairo_gl_composite_t *setup,
|
||||
const cairo_gl_operand_t *mask);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_composite_set_spans (cairo_gl_composite_t *setup);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_gl_composite_begin (cairo_gl_composite_t *setup,
|
||||
|
|
@ -480,13 +500,6 @@ _cairo_gl_get_image_format_and_type (cairo_gl_flavor_t flavor,
|
|||
GLenum *type, cairo_bool_t *has_alpha,
|
||||
cairo_bool_t *needs_swap);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_surface_scaled_font_fini ( cairo_scaled_font_t *scaled_font);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
|
||||
cairo_scaled_font_t *scaled_font);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_glyph_cache_init (cairo_gl_glyph_cache_t *cache);
|
||||
|
||||
|
|
@ -529,6 +542,7 @@ cairo_private cairo_status_t
|
|||
_cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx,
|
||||
cairo_gl_operand_t *source,
|
||||
cairo_gl_operand_t *mask,
|
||||
cairo_bool_t use_coverage,
|
||||
cairo_gl_shader_in_t in,
|
||||
cairo_gl_shader_t **shader);
|
||||
|
||||
|
|
@ -585,6 +599,17 @@ cairo_private cairo_status_t
|
|||
_cairo_gl_dispatch_init(cairo_gl_dispatch_t *dispatch,
|
||||
cairo_gl_get_proc_addr_func_t get_proc_addr);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_gl_operand_init (cairo_gl_operand_t *operand,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_gl_surface_t *dst,
|
||||
int src_x, int src_y,
|
||||
int dst_x, int dst_y,
|
||||
int width, int height);
|
||||
cairo_private void
|
||||
_cairo_gl_solid_operand_init (cairo_gl_operand_t *operand,
|
||||
const cairo_color_t *color);
|
||||
|
||||
cairo_private cairo_filter_t
|
||||
_cairo_gl_operand_get_filter (cairo_gl_operand_t *operand);
|
||||
|
||||
|
|
@ -594,25 +619,50 @@ _cairo_gl_operand_get_gl_filter (cairo_gl_operand_t *operand);
|
|||
cairo_private cairo_extend_t
|
||||
_cairo_gl_operand_get_extend (cairo_gl_operand_t *operand);
|
||||
|
||||
cairo_private unsigned int
|
||||
_cairo_gl_operand_get_vertex_size (cairo_gl_operand_type_t type);
|
||||
|
||||
cairo_private cairo_bool_t
|
||||
_cairo_gl_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle);
|
||||
_cairo_gl_operand_needs_setup (cairo_gl_operand_t *dest,
|
||||
cairo_gl_operand_t *source,
|
||||
unsigned int vertex_offset);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_operand_bind_to_shader (cairo_gl_context_t *ctx,
|
||||
cairo_gl_operand_t *operand,
|
||||
cairo_gl_tex_t tex_unit);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_operand_emit (cairo_gl_operand_t *operand,
|
||||
GLfloat ** vb,
|
||||
GLfloat x,
|
||||
GLfloat y,
|
||||
uint8_t alpha);
|
||||
|
||||
cairo_private void
|
||||
_cairo_gl_operand_destroy (cairo_gl_operand_t *operand);
|
||||
|
||||
cairo_private const cairo_compositor_t *
|
||||
_cairo_gl_span_compositor_get (void);
|
||||
|
||||
cairo_private const cairo_compositor_t *
|
||||
_cairo_gl_traps_compositor_get (void);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_gl_surface_polygon (cairo_gl_surface_t *dst,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *src,
|
||||
cairo_polygon_t *polygon,
|
||||
cairo_fill_rule_t fill_rule,
|
||||
cairo_antialias_t antialias,
|
||||
const cairo_composite_rectangles_t *extents);
|
||||
_cairo_gl_check_composite_glyphs (const cairo_composite_rectangles_t *extents,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
cairo_glyph_t *glyphs,
|
||||
int *num_glyphs);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_gl_clip_and_composite_boxes (cairo_gl_surface_t *dst,
|
||||
_cairo_gl_composite_glyphs (void *_dst,
|
||||
cairo_operator_t op,
|
||||
const cairo_pattern_t *src,
|
||||
cairo_boxes_t *boxes,
|
||||
cairo_composite_rectangles_t *extents);
|
||||
cairo_surface_t *_src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
cairo_composite_glyphs_info_t *info);
|
||||
|
||||
slim_hidden_proto (cairo_gl_surface_create);
|
||||
slim_hidden_proto (cairo_gl_surface_create_for_texture);
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ _cairo_gl_shader_compile (cairo_gl_context_t *ctx,
|
|||
cairo_gl_shader_t *shader,
|
||||
cairo_gl_var_type_t src,
|
||||
cairo_gl_var_type_t mask,
|
||||
cairo_bool_t use_coverage,
|
||||
const char *fragment_text);
|
||||
|
||||
/* OpenGL Core 2.0 API. */
|
||||
|
|
@ -426,6 +427,7 @@ _cairo_gl_context_init_shaders (cairo_gl_context_t *ctx)
|
|||
&ctx->fill_rectangles_shader,
|
||||
CAIRO_GL_VAR_NONE,
|
||||
CAIRO_GL_VAR_NONE,
|
||||
FALSE,
|
||||
fill_fs_source);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
|
@ -475,8 +477,6 @@ cairo_gl_operand_get_var_type (cairo_gl_operand_type_t type)
|
|||
case CAIRO_GL_OPERAND_RADIAL_GRADIENT_EXT:
|
||||
case CAIRO_GL_OPERAND_TEXTURE:
|
||||
return CAIRO_GL_VAR_TEXCOORDS;
|
||||
case CAIRO_GL_OPERAND_SPANS:
|
||||
return CAIRO_GL_VAR_COVERAGE;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -495,11 +495,6 @@ cairo_gl_shader_emit_variable (cairo_output_stream_t *stream,
|
|||
"varying vec2 %s_texcoords;\n",
|
||||
operand_names[name]);
|
||||
break;
|
||||
case CAIRO_GL_VAR_COVERAGE:
|
||||
_cairo_output_stream_printf (stream,
|
||||
"varying float %s_coverage;\n",
|
||||
operand_names[name]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -518,17 +513,25 @@ cairo_gl_shader_emit_vertex (cairo_output_stream_t *stream,
|
|||
" %s_texcoords = MultiTexCoord%d.xy;\n",
|
||||
operand_names[name], name);
|
||||
break;
|
||||
case CAIRO_GL_VAR_COVERAGE:
|
||||
_cairo_output_stream_printf (stream,
|
||||
" %s_coverage = Color.a;\n",
|
||||
operand_names[name]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cairo_gl_shader_dcl_coverage (cairo_output_stream_t *stream)
|
||||
{
|
||||
_cairo_output_stream_printf (stream, "varying float coverage;\n");
|
||||
}
|
||||
|
||||
static void
|
||||
cairo_gl_shader_def_coverage (cairo_output_stream_t *stream)
|
||||
{
|
||||
_cairo_output_stream_printf (stream, " coverage = Color.a;\n");
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src,
|
||||
cairo_gl_var_type_t mask,
|
||||
cairo_bool_t use_coverage,
|
||||
cairo_gl_var_type_t dest,
|
||||
char **out)
|
||||
{
|
||||
|
|
@ -539,6 +542,8 @@ cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src,
|
|||
|
||||
cairo_gl_shader_emit_variable (stream, src, CAIRO_GL_TEX_SOURCE);
|
||||
cairo_gl_shader_emit_variable (stream, mask, CAIRO_GL_TEX_MASK);
|
||||
if (use_coverage)
|
||||
cairo_gl_shader_dcl_coverage (stream);
|
||||
|
||||
_cairo_output_stream_printf (stream,
|
||||
"attribute vec4 Vertex;\n"
|
||||
|
|
@ -552,6 +557,8 @@ cairo_gl_shader_get_vertex_source (cairo_gl_var_type_t src,
|
|||
|
||||
cairo_gl_shader_emit_vertex (stream, src, CAIRO_GL_TEX_SOURCE);
|
||||
cairo_gl_shader_emit_vertex (stream, mask, CAIRO_GL_TEX_MASK);
|
||||
if (use_coverage)
|
||||
cairo_gl_shader_def_coverage (stream);
|
||||
|
||||
_cairo_output_stream_write (stream,
|
||||
"}\n\0", 3);
|
||||
|
|
@ -774,15 +781,6 @@ cairo_gl_shader_emit_color (cairo_output_stream_t *stream,
|
|||
namestr, namestr, namestr, namestr, namestr,
|
||||
namestr, namestr, namestr, rectstr, namestr);
|
||||
break;
|
||||
case CAIRO_GL_OPERAND_SPANS:
|
||||
_cairo_output_stream_printf (stream,
|
||||
"varying float %s_coverage;\n"
|
||||
"vec4 get_%s()\n"
|
||||
"{\n"
|
||||
" return vec4(0, 0, 0, %s_coverage);\n"
|
||||
"}\n",
|
||||
namestr, namestr, namestr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -842,6 +840,7 @@ cairo_gl_shader_get_fragment_source (cairo_gl_context_t *ctx,
|
|||
cairo_gl_shader_in_t in,
|
||||
cairo_gl_operand_t *src,
|
||||
cairo_gl_operand_t *mask,
|
||||
cairo_bool_t use_coverage,
|
||||
cairo_gl_operand_type_t dest_type,
|
||||
char **out)
|
||||
{
|
||||
|
|
@ -849,6 +848,7 @@ cairo_gl_shader_get_fragment_source (cairo_gl_context_t *ctx,
|
|||
unsigned char *source;
|
||||
unsigned long length;
|
||||
cairo_status_t status;
|
||||
const char *coverage_str;
|
||||
|
||||
_cairo_output_stream_printf (stream,
|
||||
"#ifdef GL_ES\n"
|
||||
|
|
@ -865,6 +865,10 @@ cairo_gl_shader_get_fragment_source (cairo_gl_context_t *ctx,
|
|||
cairo_gl_shader_emit_color (stream, ctx, src, CAIRO_GL_TEX_SOURCE);
|
||||
cairo_gl_shader_emit_color (stream, ctx, mask, CAIRO_GL_TEX_MASK);
|
||||
|
||||
coverage_str = "";
|
||||
if (use_coverage)
|
||||
coverage_str = " * coverage.a";
|
||||
|
||||
_cairo_output_stream_printf (stream,
|
||||
"void main()\n"
|
||||
"{\n");
|
||||
|
|
@ -874,15 +878,18 @@ cairo_gl_shader_get_fragment_source (cairo_gl_context_t *ctx,
|
|||
ASSERT_NOT_REACHED;
|
||||
case CAIRO_GL_SHADER_IN_NORMAL:
|
||||
_cairo_output_stream_printf (stream,
|
||||
" gl_FragColor = get_source() * get_mask().a;\n");
|
||||
" gl_FragColor = get_source() * get_mask().a%s;\n",
|
||||
coverage_str);
|
||||
break;
|
||||
case CAIRO_GL_SHADER_IN_CA_SOURCE:
|
||||
_cairo_output_stream_printf (stream,
|
||||
" gl_FragColor = get_source() * get_mask();\n");
|
||||
" gl_FragColor = get_source() * get_mask()%s;\n",
|
||||
coverage_str);
|
||||
break;
|
||||
case CAIRO_GL_SHADER_IN_CA_SOURCE_ALPHA:
|
||||
_cairo_output_stream_printf (stream,
|
||||
" gl_FragColor = get_source().a * get_mask();\n");
|
||||
" gl_FragColor = get_source().a * get_mask()%s;\n",
|
||||
coverage_str);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -902,6 +909,7 @@ _cairo_gl_shader_compile (cairo_gl_context_t *ctx,
|
|||
cairo_gl_shader_t *shader,
|
||||
cairo_gl_var_type_t src,
|
||||
cairo_gl_var_type_t mask,
|
||||
cairo_bool_t use_coverage,
|
||||
const char *fragment_text)
|
||||
{
|
||||
unsigned int vertex_shader;
|
||||
|
|
@ -909,12 +917,14 @@ _cairo_gl_shader_compile (cairo_gl_context_t *ctx,
|
|||
|
||||
assert (shader->program == 0);
|
||||
|
||||
vertex_shader = cairo_gl_var_type_hash (src, mask, CAIRO_GL_VAR_NONE);
|
||||
vertex_shader = cairo_gl_var_type_hash (src, mask, use_coverage,
|
||||
CAIRO_GL_VAR_NONE);
|
||||
if (ctx->vertex_shaders[vertex_shader] == 0) {
|
||||
char *source;
|
||||
|
||||
status = cairo_gl_shader_get_vertex_source (src,
|
||||
mask,
|
||||
use_coverage,
|
||||
CAIRO_GL_VAR_NONE,
|
||||
&source);
|
||||
if (unlikely (status))
|
||||
|
|
@ -1042,6 +1052,7 @@ cairo_status_t
|
|||
_cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx,
|
||||
cairo_gl_operand_t *source,
|
||||
cairo_gl_operand_t *mask,
|
||||
cairo_bool_t use_coverage,
|
||||
cairo_gl_shader_in_t in,
|
||||
cairo_gl_shader_t **shader)
|
||||
{
|
||||
|
|
@ -1071,6 +1082,7 @@ _cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx,
|
|||
in,
|
||||
source,
|
||||
mask,
|
||||
use_coverage,
|
||||
CAIRO_GL_OPERAND_NONE,
|
||||
&fs_source);
|
||||
if (unlikely (status))
|
||||
|
|
@ -1090,6 +1102,7 @@ _cairo_gl_get_shader_by_type (cairo_gl_context_t *ctx,
|
|||
&entry->shader,
|
||||
cairo_gl_operand_get_var_type (source->type),
|
||||
cairo_gl_operand_get_var_type (mask->type),
|
||||
use_coverage,
|
||||
fs_source);
|
||||
free (fs_source);
|
||||
|
||||
|
|
|
|||
502
src/cairo-gl-spans-compositor.c
Normal file
502
src/cairo-gl-spans-compositor.c
Normal file
|
|
@ -0,0 +1,502 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Eric Anholt
|
||||
* Copyright © 2009 Chris Wilson
|
||||
* Copyright © 2005,2010 Red Hat, Inc
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benjamin Otte <otte@gnome.org>
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-gl-private.h"
|
||||
|
||||
#include "cairo-composite-rectangles-private.h"
|
||||
#include "cairo-compositor-private.h"
|
||||
#include "cairo-default-context-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-image-surface-private.h"
|
||||
#include "cairo-spans-compositor-private.h"
|
||||
#include "cairo-surface-backend-private.h"
|
||||
|
||||
typedef struct _cairo_gl_span_renderer {
|
||||
cairo_span_renderer_t base;
|
||||
|
||||
cairo_gl_composite_t setup;
|
||||
double opacity;
|
||||
|
||||
int xmin, xmax;
|
||||
int ymin, ymax;
|
||||
|
||||
cairo_gl_context_t *ctx;
|
||||
} cairo_gl_span_renderer_t;
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gl_bounded_opaque_spans (void *abstract_renderer,
|
||||
int y, int height,
|
||||
const cairo_half_open_span_t *spans,
|
||||
unsigned num_spans)
|
||||
{
|
||||
cairo_gl_span_renderer_t *r = abstract_renderer;
|
||||
|
||||
if (num_spans == 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
do {
|
||||
if (spans[0].coverage) {
|
||||
_cairo_gl_composite_emit_rect (r->ctx,
|
||||
spans[0].x, y,
|
||||
spans[1].x, y + height,
|
||||
spans[0].coverage);
|
||||
}
|
||||
|
||||
spans++;
|
||||
} while (--num_spans > 1);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gl_bounded_spans (void *abstract_renderer,
|
||||
int y, int height,
|
||||
const cairo_half_open_span_t *spans,
|
||||
unsigned num_spans)
|
||||
{
|
||||
cairo_gl_span_renderer_t *r = abstract_renderer;
|
||||
|
||||
if (num_spans == 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
do {
|
||||
if (spans[0].coverage) {
|
||||
_cairo_gl_composite_emit_rect (r->ctx,
|
||||
spans[0].x, y,
|
||||
spans[1].x, y + height,
|
||||
r->opacity * spans[0].coverage);
|
||||
}
|
||||
|
||||
spans++;
|
||||
} while (--num_spans > 1);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gl_unbounded_spans (void *abstract_renderer,
|
||||
int y, int height,
|
||||
const cairo_half_open_span_t *spans,
|
||||
unsigned num_spans)
|
||||
{
|
||||
cairo_gl_span_renderer_t *r = abstract_renderer;
|
||||
|
||||
if (y > r->ymin) {
|
||||
_cairo_gl_composite_emit_rect (r->ctx,
|
||||
r->xmin, r->ymin,
|
||||
r->xmax, y,
|
||||
0);
|
||||
}
|
||||
|
||||
if (num_spans == 0) {
|
||||
_cairo_gl_composite_emit_rect (r->ctx,
|
||||
r->xmin, y,
|
||||
r->xmax, y + height,
|
||||
0);
|
||||
} else {
|
||||
if (spans[0].x != r->xmin) {
|
||||
_cairo_gl_composite_emit_rect (r->ctx,
|
||||
r->xmin, y,
|
||||
spans[0].x, y + height,
|
||||
0);
|
||||
}
|
||||
|
||||
do {
|
||||
_cairo_gl_composite_emit_rect (r->ctx,
|
||||
spans[0].x, y,
|
||||
spans[1].x, y + height,
|
||||
r->opacity * spans[0].coverage);
|
||||
spans++;
|
||||
} while (--num_spans > 1);
|
||||
|
||||
if (spans[0].x != r->xmax) {
|
||||
_cairo_gl_composite_emit_rect (r->ctx,
|
||||
spans[0].x, y,
|
||||
r->xmax, y + height,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
r->ymin = y + height;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* XXX */
|
||||
static cairo_status_t
|
||||
_cairo_gl_clipped_spans (void *abstract_renderer,
|
||||
int y, int height,
|
||||
const cairo_half_open_span_t *spans,
|
||||
unsigned num_spans)
|
||||
{
|
||||
cairo_gl_span_renderer_t *r = abstract_renderer;
|
||||
|
||||
if (y > r->ymin) {
|
||||
_cairo_gl_composite_emit_rect (r->ctx,
|
||||
r->xmin, r->ymin,
|
||||
r->xmax, y,
|
||||
0);
|
||||
}
|
||||
|
||||
if (num_spans == 0) {
|
||||
_cairo_gl_composite_emit_rect (r->ctx,
|
||||
r->xmin, y,
|
||||
r->xmax, y + height,
|
||||
0);
|
||||
} else {
|
||||
if (spans[0].x != r->xmin) {
|
||||
_cairo_gl_composite_emit_rect (r->ctx,
|
||||
r->xmin, y,
|
||||
spans[0].x, y + height,
|
||||
0);
|
||||
}
|
||||
|
||||
do {
|
||||
_cairo_gl_composite_emit_rect (r->ctx,
|
||||
spans[0].x, y,
|
||||
spans[1].x, y + height,
|
||||
r->opacity * spans[0].coverage);
|
||||
spans++;
|
||||
} while (--num_spans > 1);
|
||||
|
||||
if (spans[0].x != r->xmax) {
|
||||
_cairo_gl_composite_emit_rect (r->ctx,
|
||||
spans[0].x, y,
|
||||
r->xmax, y + height,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
r->ymin = y + height;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gl_finish_unbounded_spans (void *abstract_renderer)
|
||||
{
|
||||
cairo_gl_span_renderer_t *r = abstract_renderer;
|
||||
|
||||
if (r->ymax > r->ymin) {
|
||||
_cairo_gl_composite_emit_rect (r->ctx,
|
||||
r->xmin, r->ymin,
|
||||
r->xmax, r->ymax,
|
||||
0);
|
||||
}
|
||||
|
||||
return _cairo_gl_context_release (r->ctx, CAIRO_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gl_finish_bounded_spans (void *abstract_renderer)
|
||||
{
|
||||
cairo_gl_span_renderer_t *r = abstract_renderer;
|
||||
|
||||
return _cairo_gl_context_release (r->ctx, CAIRO_STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_aligned_boxes (cairo_gl_context_t *ctx,
|
||||
const cairo_boxes_t *boxes)
|
||||
{
|
||||
const struct _cairo_boxes_chunk *chunk;
|
||||
int i;
|
||||
|
||||
for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
|
||||
for (i = 0; i < chunk->count; i++) {
|
||||
int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x);
|
||||
int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
|
||||
int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
|
||||
int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
|
||||
_cairo_gl_composite_emit_rect (ctx, x1, y1, x2, y2, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
fill_boxes (void *_dst,
|
||||
cairo_operator_t op,
|
||||
const cairo_color_t *color,
|
||||
cairo_boxes_t *boxes)
|
||||
{
|
||||
cairo_gl_composite_t setup;
|
||||
cairo_gl_context_t *ctx;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_gl_composite_init (&setup, op, _dst, FALSE, NULL);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
_cairo_gl_composite_set_solid_source (&setup, color);
|
||||
|
||||
status = _cairo_gl_composite_begin (&setup, &ctx);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
emit_aligned_boxes (ctx, boxes);
|
||||
status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS);
|
||||
|
||||
FAIL:
|
||||
_cairo_gl_composite_fini (&setup);
|
||||
return status;
|
||||
}
|
||||
|
||||
typedef struct cairo_gl_source {
|
||||
cairo_surface_t base;
|
||||
|
||||
cairo_gl_operand_t operand;
|
||||
} cairo_gl_source_t;
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gl_source_finish (void *abstract_surface)
|
||||
{
|
||||
cairo_gl_source_t *source = abstract_surface;
|
||||
|
||||
_cairo_gl_operand_destroy (&source->operand);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_gl_source_backend = {
|
||||
CAIRO_SURFACE_TYPE_GL,
|
||||
_cairo_gl_source_finish,
|
||||
NULL, /* read-only wrapper */
|
||||
};
|
||||
|
||||
static cairo_surface_t *
|
||||
pattern_to_surface (cairo_surface_t *dst,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_bool_t is_mask,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
const cairo_rectangle_int_t *sample,
|
||||
int *src_x, int *src_y)
|
||||
{
|
||||
cairo_gl_source_t *source;
|
||||
cairo_int_status_t status;
|
||||
|
||||
source = malloc (sizeof (*source));
|
||||
if (unlikely (source == NULL))
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
||||
_cairo_surface_init (&source->base,
|
||||
&cairo_gl_source_backend,
|
||||
NULL, /* device */
|
||||
CAIRO_CONTENT_COLOR_ALPHA);
|
||||
|
||||
*src_x = *src_y = 0;
|
||||
status = _cairo_gl_operand_init (&source->operand, pattern, (cairo_gl_surface_t *)dst,
|
||||
extents->x, extents->y,
|
||||
extents->x, extents->y,
|
||||
extents->width, extents->height);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (&source->base);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
return &source->base;
|
||||
}
|
||||
|
||||
static inline cairo_gl_operand_t *
|
||||
source_to_operand (cairo_surface_t *surface)
|
||||
{
|
||||
cairo_gl_source_t *source = (cairo_gl_source_t *)surface;
|
||||
return &source->operand;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
composite_boxes (void *_dst,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *abstract_src,
|
||||
cairo_surface_t *abstract_mask,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int mask_x,
|
||||
int mask_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
cairo_boxes_t *boxes,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_gl_composite_t setup;
|
||||
cairo_gl_context_t *ctx;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_gl_composite_init (&setup, op, _dst, FALSE, extents);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
_cairo_gl_composite_set_source_operand (&setup,
|
||||
source_to_operand (abstract_src));
|
||||
|
||||
_cairo_gl_composite_set_mask_operand (&setup,
|
||||
source_to_operand (abstract_mask));
|
||||
|
||||
status = _cairo_gl_composite_begin (&setup, &ctx);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
emit_aligned_boxes (ctx, boxes);
|
||||
status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS);
|
||||
|
||||
FAIL:
|
||||
_cairo_gl_composite_fini (&setup);
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
_cairo_gl_span_renderer_init (cairo_abstract_span_renderer_t *_r,
|
||||
const cairo_composite_rectangles_t *composite,
|
||||
cairo_bool_t needs_clip)
|
||||
{
|
||||
cairo_gl_span_renderer_t *r = (cairo_gl_span_renderer_t *)_r;
|
||||
const cairo_pattern_t *source = &composite->source_pattern.base;
|
||||
cairo_operator_t op = composite->op;
|
||||
cairo_int_status_t status;
|
||||
|
||||
/* XXX earlier! */
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
source = &_cairo_pattern_white.base;
|
||||
op = CAIRO_OPERATOR_DEST_OUT;
|
||||
} else if (composite->surface->is_clear &&
|
||||
(op == CAIRO_OPERATOR_SOURCE ||
|
||||
op == CAIRO_OPERATOR_OVER ||
|
||||
op == CAIRO_OPERATOR_ADD)) {
|
||||
op = CAIRO_OPERATOR_SOURCE;
|
||||
} else if (op == CAIRO_OPERATOR_SOURCE) {
|
||||
/* no lerp equivalent without some major PITA */
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
} else if (! _cairo_gl_operator_is_supported (op))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
status = _cairo_gl_composite_init (&r->setup,
|
||||
op, (cairo_gl_surface_t *)composite->surface,
|
||||
FALSE, &composite->unbounded);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
status = _cairo_gl_composite_set_source (&r->setup, source,
|
||||
composite->unbounded.x,
|
||||
composite->unbounded.y,
|
||||
composite->unbounded.x,
|
||||
composite->unbounded.y,
|
||||
composite->unbounded.width,
|
||||
composite->unbounded.height);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
r->opacity = 1.0;
|
||||
if (composite->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID) {
|
||||
r->opacity = composite->mask_pattern.solid.color.alpha;
|
||||
} else {
|
||||
status = _cairo_gl_composite_set_mask (&r->setup,
|
||||
&composite->mask_pattern.base,
|
||||
composite->unbounded.x,
|
||||
composite->unbounded.y,
|
||||
composite->unbounded.x,
|
||||
composite->unbounded.y,
|
||||
composite->unbounded.width,
|
||||
composite->unbounded.height);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
}
|
||||
|
||||
_cairo_gl_composite_set_spans (&r->setup);
|
||||
|
||||
status = _cairo_gl_composite_begin (&r->setup, &r->ctx);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
if (composite->is_bounded) {
|
||||
if (r->opacity == 1.)
|
||||
r->base.render_rows = _cairo_gl_bounded_opaque_spans;
|
||||
else
|
||||
r->base.render_rows = _cairo_gl_bounded_spans;
|
||||
r->base.finish = _cairo_gl_finish_bounded_spans;
|
||||
} else {
|
||||
if (needs_clip)
|
||||
r->base.render_rows = _cairo_gl_clipped_spans;
|
||||
else
|
||||
r->base.render_rows = _cairo_gl_unbounded_spans;
|
||||
r->base.finish = _cairo_gl_finish_unbounded_spans;
|
||||
r->xmin = composite->unbounded.x;
|
||||
r->xmax = composite->unbounded.x + composite->unbounded.width;
|
||||
r->ymin = composite->unbounded.y;
|
||||
r->ymax = composite->unbounded.y + composite->unbounded.height;
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
FAIL:
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_gl_span_renderer_fini (cairo_abstract_span_renderer_t *_r,
|
||||
cairo_int_status_t status)
|
||||
{
|
||||
cairo_gl_span_renderer_t *r = (cairo_gl_span_renderer_t *) _r;
|
||||
|
||||
if (status == CAIRO_INT_STATUS_SUCCESS)
|
||||
r->base.finish (r);
|
||||
|
||||
_cairo_gl_composite_fini (&r->setup);
|
||||
}
|
||||
|
||||
const cairo_compositor_t *
|
||||
_cairo_gl_span_compositor_get (void)
|
||||
{
|
||||
static cairo_spans_compositor_t compositor;
|
||||
|
||||
if (compositor.base.delegate == NULL) {
|
||||
/* The fallback to traps here is essentially just for glyphs... */
|
||||
_cairo_spans_compositor_init (&compositor,
|
||||
_cairo_gl_traps_compositor_get());
|
||||
|
||||
compositor.fill_boxes = fill_boxes;
|
||||
//compositor.check_composite_boxes = check_composite_boxes;
|
||||
compositor.pattern_to_surface = pattern_to_surface;
|
||||
compositor.composite_boxes = composite_boxes;
|
||||
//compositor.check_span_renderer = check_span_renderer;
|
||||
compositor.renderer_init = _cairo_gl_span_renderer_init;
|
||||
compositor.renderer_fini = _cairo_gl_span_renderer_fini;
|
||||
}
|
||||
|
||||
return &compositor.base;
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
550
src/cairo-gl-traps-compositor.c
Normal file
550
src/cairo-gl-traps-compositor.c
Normal file
|
|
@ -0,0 +1,550 @@
|
|||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2009 Eric Anholt
|
||||
* Copyright © 2009 Chris Wilson
|
||||
* Copyright © 2005,2010 Red Hat, Inc
|
||||
* Copyright © 2011 Intel Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Red Hat, Inc.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Benjamin Otte <otte@gnome.org>
|
||||
* Carl Worth <cworth@cworth.org>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
* Eric Anholt <eric@anholt.net>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-gl-private.h"
|
||||
|
||||
#include "cairo-composite-rectangles-private.h"
|
||||
#include "cairo-compositor-private.h"
|
||||
#include "cairo-default-context-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-image-surface-private.h"
|
||||
#include "cairo-spans-compositor-private.h"
|
||||
#include "cairo-surface-backend-private.h"
|
||||
|
||||
static cairo_int_status_t
|
||||
acquire (void *abstract_dst)
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
release (void *abstract_dst)
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
set_clip_region (void *_surface,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
cairo_gl_surface_t *surface = _surface;
|
||||
|
||||
//surface->clip_region = region;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
draw_image_boxes (void *_dst,
|
||||
cairo_image_surface_t *image,
|
||||
cairo_boxes_t *boxes,
|
||||
int dx, int dy)
|
||||
{
|
||||
cairo_gl_surface_t *dst = _dst;
|
||||
struct _cairo_boxes_chunk *chunk;
|
||||
int i;
|
||||
|
||||
for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
|
||||
for (i = 0; i < chunk->count; i++) {
|
||||
cairo_box_t *b = &chunk->base[i];
|
||||
int x = _cairo_fixed_integer_part (b->p1.x);
|
||||
int y = _cairo_fixed_integer_part (b->p1.y);
|
||||
int w = _cairo_fixed_integer_part (b->p2.x) - x;
|
||||
int h = _cairo_fixed_integer_part (b->p2.y) - y;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_gl_surface_draw_image (dst, image,
|
||||
x + dx, y + dy,
|
||||
w, h,
|
||||
x, y);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
emit_aligned_boxes (cairo_gl_context_t *ctx,
|
||||
const cairo_boxes_t *boxes)
|
||||
{
|
||||
const struct _cairo_boxes_chunk *chunk;
|
||||
int i;
|
||||
|
||||
for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
|
||||
for (i = 0; i < chunk->count; i++) {
|
||||
int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x);
|
||||
int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
|
||||
int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
|
||||
int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
|
||||
_cairo_gl_composite_emit_rect (ctx, x1, y1, x2, y2, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
fill_boxes (void *_dst,
|
||||
cairo_operator_t op,
|
||||
const cairo_color_t *color,
|
||||
cairo_boxes_t *boxes)
|
||||
{
|
||||
cairo_gl_composite_t setup;
|
||||
cairo_gl_context_t *ctx;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_gl_composite_init (&setup, op, _dst, FALSE, NULL);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
_cairo_gl_composite_set_solid_source (&setup, color);
|
||||
|
||||
status = _cairo_gl_composite_begin (&setup, &ctx);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
emit_aligned_boxes (ctx, boxes);
|
||||
status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS);
|
||||
|
||||
FAIL:
|
||||
_cairo_gl_composite_fini (&setup);
|
||||
return status;
|
||||
}
|
||||
|
||||
typedef struct cairo_gl_source {
|
||||
cairo_surface_t base;
|
||||
|
||||
cairo_gl_operand_t operand;
|
||||
} cairo_gl_source_t;
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_gl_source_finish (void *abstract_surface)
|
||||
{
|
||||
cairo_gl_source_t *source = abstract_surface;
|
||||
|
||||
_cairo_gl_operand_destroy (&source->operand);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_gl_source_backend = {
|
||||
CAIRO_SURFACE_TYPE_GL,
|
||||
_cairo_gl_source_finish,
|
||||
NULL, /* read-only wrapper */
|
||||
};
|
||||
|
||||
static cairo_surface_t *
|
||||
pattern_to_surface (cairo_surface_t *dst,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_bool_t is_mask,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
const cairo_rectangle_int_t *sample,
|
||||
int *src_x, int *src_y)
|
||||
{
|
||||
cairo_gl_source_t *source;
|
||||
cairo_int_status_t status;
|
||||
|
||||
source = malloc (sizeof (*source));
|
||||
if (unlikely (source == NULL))
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
||||
_cairo_surface_init (&source->base,
|
||||
&cairo_gl_source_backend,
|
||||
NULL, /* device */
|
||||
CAIRO_CONTENT_COLOR_ALPHA);
|
||||
|
||||
*src_x = *src_y = 0;
|
||||
status = _cairo_gl_operand_init (&source->operand, pattern, (cairo_gl_surface_t *)dst,
|
||||
extents->x, extents->y,
|
||||
extents->x, extents->y,
|
||||
extents->width, extents->height);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (&source->base);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
return &source->base;
|
||||
}
|
||||
|
||||
static inline cairo_gl_operand_t *
|
||||
source_to_operand (cairo_surface_t *surface)
|
||||
{
|
||||
cairo_gl_source_t *source = (cairo_gl_source_t *)surface;
|
||||
return &source->operand;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
composite_boxes (void *_dst,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *abstract_src,
|
||||
cairo_surface_t *abstract_mask,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int mask_x,
|
||||
int mask_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
cairo_boxes_t *boxes,
|
||||
const cairo_rectangle_int_t *extents)
|
||||
{
|
||||
cairo_gl_composite_t setup;
|
||||
cairo_gl_context_t *ctx;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_gl_composite_init (&setup, op, _dst, FALSE, extents);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
_cairo_gl_composite_set_source_operand (&setup,
|
||||
source_to_operand (abstract_src));
|
||||
|
||||
_cairo_gl_composite_set_mask_operand (&setup,
|
||||
source_to_operand (abstract_mask));
|
||||
|
||||
status = _cairo_gl_composite_begin (&setup, &ctx);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
emit_aligned_boxes (ctx, boxes);
|
||||
status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS);
|
||||
|
||||
FAIL:
|
||||
_cairo_gl_composite_fini (&setup);
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
composite (void *_dst,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *abstract_src,
|
||||
cairo_surface_t *abstract_mask,
|
||||
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_gl_composite_t setup;
|
||||
cairo_gl_context_t *ctx;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_gl_composite_init (&setup, op, _dst, FALSE, NULL);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
_cairo_gl_composite_set_source_operand (&setup,
|
||||
source_to_operand (abstract_src));
|
||||
|
||||
_cairo_gl_composite_set_mask_operand (&setup,
|
||||
source_to_operand (abstract_mask));
|
||||
|
||||
status = _cairo_gl_composite_begin (&setup, &ctx);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
/* XXX clip */
|
||||
_cairo_gl_composite_emit_rect (ctx, dst_x, dst_y, dst_x+width, dst_y+height, 0);
|
||||
status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS);
|
||||
|
||||
FAIL:
|
||||
_cairo_gl_composite_fini (&setup);
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
lerp (void *dst,
|
||||
cairo_surface_t *src,
|
||||
cairo_surface_t *mask,
|
||||
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_int_status_t status;
|
||||
|
||||
/* we could avoid some repetition... */
|
||||
status = composite (dst, CAIRO_OPERATOR_DEST_OUT, src, mask,
|
||||
src_x, src_y,
|
||||
mask_x, mask_y,
|
||||
dst_x, dst_y,
|
||||
width, height);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
status = composite (dst, CAIRO_OPERATOR_ADD, src, mask,
|
||||
src_x, src_y,
|
||||
mask_x, mask_y,
|
||||
dst_x, dst_y,
|
||||
width, height);
|
||||
if (unlikely (status))
|
||||
return status;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_gl_surface_t *
|
||||
traps_to_surface (void *_dst,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_traps_t *traps)
|
||||
{
|
||||
pixman_format_code_t pixman_format;
|
||||
pixman_image_t *pixman_image;
|
||||
cairo_surface_t *image, *mask;
|
||||
cairo_status_t status;
|
||||
|
||||
pixman_format = antialias != CAIRO_ANTIALIAS_NONE ? PIXMAN_a8 : PIXMAN_a1,
|
||||
pixman_image = pixman_image_create_bits (pixman_format,
|
||||
extents->width,
|
||||
extents->height,
|
||||
NULL, 0);
|
||||
if (unlikely (pixman_image == NULL))
|
||||
return (cairo_gl_surface_t *)_cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
||||
_pixman_image_add_traps (pixman_image, extents->x, extents->y, traps);
|
||||
image = _cairo_image_surface_create_for_pixman_image (pixman_image,
|
||||
pixman_format);
|
||||
if (unlikely (image->status)) {
|
||||
pixman_image_unref (pixman_image);
|
||||
return (cairo_gl_surface_t *)image;
|
||||
}
|
||||
|
||||
mask = _cairo_surface_create_similar_scratch (_dst, CAIRO_CONTENT_ALPHA,
|
||||
extents->width,
|
||||
extents->height);
|
||||
if (unlikely (mask->status)) {
|
||||
cairo_surface_destroy (image);
|
||||
return (cairo_gl_surface_t *)mask;
|
||||
}
|
||||
|
||||
status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *)mask,
|
||||
(cairo_image_surface_t *)image,
|
||||
0, 0,
|
||||
extents->width, extents->height,
|
||||
0, 0);
|
||||
cairo_surface_destroy (image);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (mask);
|
||||
return (cairo_gl_surface_t*)_cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
return (cairo_gl_surface_t*)mask;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
composite_traps (void *_dst,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *abstract_src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_traps_t *traps)
|
||||
{
|
||||
cairo_gl_composite_t setup;
|
||||
cairo_gl_context_t *ctx;
|
||||
cairo_gl_surface_t *mask;
|
||||
cairo_int_status_t status;
|
||||
|
||||
mask = traps_to_surface (_dst, extents, antialias, traps);
|
||||
if (unlikely (mask->base.status))
|
||||
return mask->base.status;
|
||||
|
||||
status = _cairo_gl_composite_init (&setup, op, _dst, FALSE, NULL);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
_cairo_gl_composite_set_source_operand (&setup,
|
||||
source_to_operand (abstract_src));
|
||||
|
||||
//_cairo_gl_composite_set_mask_surface (&setup, mask, 0, 0);
|
||||
|
||||
status = _cairo_gl_composite_begin (&setup, &ctx);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
/* XXX clip */
|
||||
_cairo_gl_composite_emit_rect (ctx,
|
||||
dst_x, dst_y,
|
||||
dst_x+extents->width,
|
||||
dst_y+extents->height, 0);
|
||||
status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS);
|
||||
|
||||
FAIL:
|
||||
_cairo_gl_composite_fini (&setup);
|
||||
cairo_surface_destroy (&mask->base);
|
||||
return status;
|
||||
}
|
||||
|
||||
static cairo_gl_surface_t *
|
||||
tristrip_to_surface (void *_dst,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_tristrip_t *strip)
|
||||
{
|
||||
pixman_format_code_t pixman_format;
|
||||
pixman_image_t *pixman_image;
|
||||
cairo_surface_t *image, *mask;
|
||||
cairo_status_t status;
|
||||
|
||||
pixman_format = antialias != CAIRO_ANTIALIAS_NONE ? PIXMAN_a8 : PIXMAN_a1,
|
||||
pixman_image = pixman_image_create_bits (pixman_format,
|
||||
extents->width,
|
||||
extents->height,
|
||||
NULL, 0);
|
||||
if (unlikely (pixman_image == NULL))
|
||||
return (cairo_gl_surface_t *)_cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
||||
_pixman_image_add_tristrip (pixman_image, extents->x, extents->y, strip);
|
||||
image = _cairo_image_surface_create_for_pixman_image (pixman_image,
|
||||
pixman_format);
|
||||
if (unlikely (image->status)) {
|
||||
pixman_image_unref (pixman_image);
|
||||
return (cairo_gl_surface_t *)image;
|
||||
}
|
||||
|
||||
mask = _cairo_surface_create_similar_scratch (_dst, CAIRO_CONTENT_ALPHA,
|
||||
extents->width,
|
||||
extents->height);
|
||||
if (unlikely (mask->status)) {
|
||||
cairo_surface_destroy (image);
|
||||
return (cairo_gl_surface_t *)mask;
|
||||
}
|
||||
|
||||
status = _cairo_gl_surface_draw_image ((cairo_gl_surface_t *)mask,
|
||||
(cairo_image_surface_t *)image,
|
||||
0, 0,
|
||||
extents->width, extents->height,
|
||||
0, 0);
|
||||
cairo_surface_destroy (image);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (mask);
|
||||
return (cairo_gl_surface_t*)_cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
return (cairo_gl_surface_t*)mask;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
composite_tristrip (void *_dst,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *abstract_src,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
cairo_antialias_t antialias,
|
||||
cairo_tristrip_t *strip)
|
||||
{
|
||||
cairo_gl_composite_t setup;
|
||||
cairo_gl_context_t *ctx;
|
||||
cairo_gl_surface_t *mask;
|
||||
cairo_int_status_t status;
|
||||
|
||||
mask = tristrip_to_surface (_dst, extents, antialias, strip);
|
||||
if (unlikely (mask->base.status))
|
||||
return mask->base.status;
|
||||
|
||||
status = _cairo_gl_composite_init (&setup, op, _dst, FALSE, NULL);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
_cairo_gl_composite_set_source_operand (&setup,
|
||||
source_to_operand (abstract_src));
|
||||
|
||||
//_cairo_gl_composite_set_mask_surface (&setup, mask, 0, 0);
|
||||
|
||||
status = _cairo_gl_composite_begin (&setup, &ctx);
|
||||
if (unlikely (status))
|
||||
goto FAIL;
|
||||
|
||||
/* XXX clip */
|
||||
_cairo_gl_composite_emit_rect (ctx,
|
||||
dst_x, dst_y,
|
||||
dst_x+extents->width,
|
||||
dst_y+extents->height, 0);
|
||||
status = _cairo_gl_context_release (ctx, CAIRO_STATUS_SUCCESS);
|
||||
|
||||
FAIL:
|
||||
_cairo_gl_composite_fini (&setup);
|
||||
cairo_surface_destroy (&mask->base);
|
||||
return status;
|
||||
}
|
||||
|
||||
const cairo_compositor_t *
|
||||
_cairo_gl_traps_compositor_get (void)
|
||||
{
|
||||
static cairo_traps_compositor_t compositor;
|
||||
|
||||
if (compositor.base.delegate == NULL) {
|
||||
_cairo_traps_compositor_init (&compositor, &_cairo_fallback_compositor);
|
||||
compositor.acquire = acquire;
|
||||
compositor.release = release;
|
||||
compositor.set_clip_region = set_clip_region;
|
||||
compositor.pattern_to_surface = pattern_to_surface;
|
||||
compositor.draw_image_boxes = draw_image_boxes;
|
||||
//compositor.copy_boxes = copy_boxes;
|
||||
compositor.fill_boxes = fill_boxes;
|
||||
//compositor.check_composite = check_composite;
|
||||
compositor.composite = composite;
|
||||
compositor.lerp = lerp;
|
||||
//compositor.check_composite_boxes = check_composite_boxes;
|
||||
compositor.composite_boxes = composite_boxes;
|
||||
//compositor.check_composite_traps = check_composite_traps;
|
||||
compositor.composite_traps = composite_traps;
|
||||
//compositor.check_composite_tristrip = check_composite_traps;
|
||||
compositor.composite_tristrip = composite_tristrip;
|
||||
compositor.check_composite_glyphs = _cairo_gl_check_composite_glyphs;
|
||||
compositor.composite_glyphs = _cairo_gl_composite_glyphs;
|
||||
}
|
||||
|
||||
return &compositor.base;
|
||||
}
|
||||
|
|
@ -41,6 +41,7 @@
|
|||
#include "cairo-error-private.h"
|
||||
#include "cairo-gstate-private.h"
|
||||
#include "cairo-pattern-private.h"
|
||||
#include "cairo-traps-private.h"
|
||||
|
||||
#if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE)
|
||||
#define ISFINITE(x) isfinite (x)
|
||||
|
|
@ -60,7 +61,7 @@ _cairo_gstate_ensure_scaled_font (cairo_gstate_t *gstate);
|
|||
static void
|
||||
_cairo_gstate_unset_scaled_font (cairo_gstate_t *gstate);
|
||||
|
||||
static cairo_status_t
|
||||
static void
|
||||
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
|
|
@ -800,11 +801,21 @@ _cairo_gstate_backend_to_user_rectangle (cairo_gstate_t *gstate,
|
|||
{
|
||||
cairo_matrix_t matrix_inverse;
|
||||
|
||||
if (! _cairo_matrix_is_identity (&gstate->target->device_transform_inverse) ||
|
||||
! _cairo_matrix_is_identity (&gstate->ctm_inverse))
|
||||
{
|
||||
cairo_matrix_multiply (&matrix_inverse,
|
||||
&gstate->target->device_transform_inverse,
|
||||
&gstate->ctm_inverse);
|
||||
_cairo_matrix_transform_bounding_box (&matrix_inverse,
|
||||
x1, y1, x2, y2, is_tight);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (is_tight)
|
||||
*is_tight = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* XXX: NYI
|
||||
|
|
@ -1346,32 +1357,17 @@ _cairo_gstate_show_page (cairo_gstate_t *gstate)
|
|||
}
|
||||
|
||||
static void
|
||||
_cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t *gstate,
|
||||
cairo_traps_t *traps,
|
||||
_cairo_gstate_extents_to_user_rectangle (cairo_gstate_t *gstate,
|
||||
const cairo_box_t *extents,
|
||||
double *x1, double *y1,
|
||||
double *x2, double *y2)
|
||||
{
|
||||
cairo_box_t extents;
|
||||
|
||||
if (traps->num_traps == 0) {
|
||||
/* no traps, so we actually won't draw anything */
|
||||
if (x1)
|
||||
*x1 = 0.0;
|
||||
if (y1)
|
||||
*y1 = 0.0;
|
||||
if (x2)
|
||||
*x2 = 0.0;
|
||||
if (y2)
|
||||
*y2 = 0.0;
|
||||
} else {
|
||||
double px1, py1, px2, py2;
|
||||
|
||||
_cairo_traps_extents (traps, &extents);
|
||||
|
||||
px1 = _cairo_fixed_to_double (extents.p1.x);
|
||||
py1 = _cairo_fixed_to_double (extents.p1.y);
|
||||
px2 = _cairo_fixed_to_double (extents.p2.x);
|
||||
py2 = _cairo_fixed_to_double (extents.p2.y);
|
||||
px1 = _cairo_fixed_to_double (extents->p1.x);
|
||||
py1 = _cairo_fixed_to_double (extents->p1.y);
|
||||
px2 = _cairo_fixed_to_double (extents->p2.x);
|
||||
py2 = _cairo_fixed_to_double (extents->p2.y);
|
||||
|
||||
_cairo_gstate_backend_to_user_rectangle (gstate,
|
||||
&px1, &py1, &px2, &py2,
|
||||
|
|
@ -1384,7 +1380,6 @@ _cairo_gstate_traps_extents_to_user_rectangle (cairo_gstate_t *gstate,
|
|||
*x2 = px2;
|
||||
if (y2)
|
||||
*y2 = py2;
|
||||
}
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
|
|
@ -1393,10 +1388,10 @@ _cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
|
|||
double *x1, double *y1,
|
||||
double *x2, double *y2)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_traps_t traps;
|
||||
cairo_int_status_t status;
|
||||
cairo_box_t extents;
|
||||
cairo_bool_t empty;
|
||||
|
||||
if (gstate->stroke_style.line_width <= 0.0) {
|
||||
if (x1)
|
||||
*x1 = 0.0;
|
||||
if (y1)
|
||||
|
|
@ -1405,24 +1400,46 @@ _cairo_gstate_stroke_extents (cairo_gstate_t *gstate,
|
|||
*x2 = 0.0;
|
||||
if (y2)
|
||||
*y2 = 0.0;
|
||||
|
||||
if (gstate->stroke_style.line_width <= 0.0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
status = CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
|
||||
cairo_boxes_t boxes;
|
||||
|
||||
_cairo_boxes_init (&boxes);
|
||||
status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
|
||||
&gstate->stroke_style,
|
||||
&gstate->ctm,
|
||||
gstate->antialias,
|
||||
&boxes);
|
||||
empty = boxes.num_boxes == 0;
|
||||
if (! empty)
|
||||
_cairo_boxes_extents (&boxes, &extents);
|
||||
_cairo_boxes_fini (&boxes);
|
||||
}
|
||||
|
||||
_cairo_traps_init (&traps);
|
||||
if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
|
||||
cairo_traps_t traps;
|
||||
|
||||
_cairo_traps_init (&traps);
|
||||
status = _cairo_path_fixed_stroke_to_traps (path,
|
||||
&gstate->stroke_style,
|
||||
&gstate->ctm,
|
||||
&gstate->ctm_inverse,
|
||||
gstate->tolerance,
|
||||
&traps);
|
||||
if (likely (status == CAIRO_STATUS_SUCCESS)) {
|
||||
_cairo_gstate_traps_extents_to_user_rectangle (gstate, &traps,
|
||||
empty = traps.num_traps == 0;
|
||||
if (! empty)
|
||||
_cairo_traps_extents (&traps, &extents);
|
||||
_cairo_traps_fini (&traps);
|
||||
}
|
||||
if (! empty) {
|
||||
_cairo_gstate_extents_to_user_rectangle (gstate, &extents,
|
||||
x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
_cairo_traps_fini (&traps);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
|
@ -1433,9 +1450,9 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate,
|
|||
double *x2, double *y2)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_traps_t traps;
|
||||
cairo_box_t extents;
|
||||
cairo_bool_t empty;
|
||||
|
||||
if (_cairo_path_fixed_fill_is_empty (path)) {
|
||||
if (x1)
|
||||
*x1 = 0.0;
|
||||
if (y1)
|
||||
|
|
@ -1444,8 +1461,25 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate,
|
|||
*x2 = 0.0;
|
||||
if (y2)
|
||||
*y2 = 0.0;
|
||||
|
||||
if (_cairo_path_fixed_fill_is_empty (path))
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (_cairo_path_fixed_fill_is_rectilinear (path)) {
|
||||
cairo_boxes_t boxes;
|
||||
|
||||
_cairo_boxes_init (&boxes);
|
||||
status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
|
||||
gstate->fill_rule,
|
||||
gstate->antialias,
|
||||
&boxes);
|
||||
empty = boxes.num_boxes == 0;
|
||||
if (! empty)
|
||||
_cairo_boxes_extents (&boxes, &extents);
|
||||
|
||||
_cairo_boxes_fini (&boxes);
|
||||
} else {
|
||||
cairo_traps_t traps;
|
||||
|
||||
_cairo_traps_init (&traps);
|
||||
|
||||
|
|
@ -1453,12 +1487,17 @@ _cairo_gstate_fill_extents (cairo_gstate_t *gstate,
|
|||
gstate->fill_rule,
|
||||
gstate->tolerance,
|
||||
&traps);
|
||||
if (likely (status == CAIRO_STATUS_SUCCESS)) {
|
||||
_cairo_gstate_traps_extents_to_user_rectangle (gstate, &traps,
|
||||
x1, y1, x2, y2);
|
||||
}
|
||||
empty = traps.num_traps == 0;
|
||||
if (! empty)
|
||||
_cairo_traps_extents (&traps, &extents);
|
||||
|
||||
_cairo_traps_fini (&traps);
|
||||
}
|
||||
|
||||
if (! empty) {
|
||||
_cairo_gstate_extents_to_user_rectangle (gstate, &extents,
|
||||
x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
@ -1834,12 +1873,12 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
|||
int num_glyphs,
|
||||
cairo_glyph_text_info_t *info)
|
||||
{
|
||||
cairo_pattern_union_t source_pattern;
|
||||
const cairo_pattern_t *pattern;
|
||||
cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
|
||||
cairo_glyph_t *transformed_glyphs;
|
||||
cairo_text_cluster_t stack_transformed_clusters[CAIRO_STACK_ARRAY_LENGTH (cairo_text_cluster_t)];
|
||||
cairo_text_cluster_t *transformed_clusters = NULL;
|
||||
cairo_pattern_union_t source_pattern;
|
||||
cairo_glyph_t *transformed_glyphs;
|
||||
const cairo_pattern_t *pattern;
|
||||
cairo_text_cluster_t *transformed_clusters;
|
||||
cairo_operator_t op;
|
||||
cairo_status_t status;
|
||||
|
||||
|
|
@ -1858,16 +1897,15 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
|||
return status;
|
||||
|
||||
transformed_glyphs = stack_transformed_glyphs;
|
||||
transformed_clusters = stack_transformed_clusters;
|
||||
|
||||
if (num_glyphs > ARRAY_LENGTH (stack_transformed_glyphs)) {
|
||||
transformed_glyphs = cairo_glyph_allocate (num_glyphs);
|
||||
if (unlikely (transformed_glyphs == NULL)) {
|
||||
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
goto CLEANUP_GLYPHS;
|
||||
}
|
||||
if (unlikely (transformed_glyphs == NULL))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
if (info != NULL) {
|
||||
transformed_clusters = stack_transformed_clusters;
|
||||
if (info->num_clusters > ARRAY_LENGTH (stack_transformed_clusters)) {
|
||||
transformed_clusters = cairo_text_cluster_allocate (info->num_clusters);
|
||||
if (unlikely (transformed_clusters == NULL)) {
|
||||
|
|
@ -1876,7 +1914,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
|||
}
|
||||
}
|
||||
|
||||
status = _cairo_gstate_transform_glyphs_to_backend (gstate,
|
||||
_cairo_gstate_transform_glyphs_to_backend (gstate,
|
||||
glyphs, num_glyphs,
|
||||
info->clusters,
|
||||
info->num_clusters,
|
||||
|
|
@ -1885,7 +1923,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
|||
&num_glyphs,
|
||||
transformed_clusters);
|
||||
} else {
|
||||
status = _cairo_gstate_transform_glyphs_to_backend (gstate,
|
||||
_cairo_gstate_transform_glyphs_to_backend (gstate,
|
||||
glyphs, num_glyphs,
|
||||
NULL, 0, 0,
|
||||
transformed_glyphs,
|
||||
|
|
@ -1893,7 +1931,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
|
|||
NULL);
|
||||
}
|
||||
|
||||
if (status || num_glyphs == 0)
|
||||
if (num_glyphs == 0)
|
||||
goto CLEANUP_GLYPHS;
|
||||
|
||||
op = _reduce_op (gstate);
|
||||
|
|
@ -1971,9 +2009,9 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
|
|||
int num_glyphs,
|
||||
cairo_path_fixed_t *path)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_glyph_t *transformed_glyphs;
|
||||
cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
|
||||
cairo_glyph_t *transformed_glyphs;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_gstate_ensure_scaled_font (gstate);
|
||||
if (unlikely (status))
|
||||
|
|
@ -1987,19 +2025,16 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
|
|||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
status = _cairo_gstate_transform_glyphs_to_backend (gstate,
|
||||
_cairo_gstate_transform_glyphs_to_backend (gstate,
|
||||
glyphs, num_glyphs,
|
||||
NULL, 0, 0,
|
||||
transformed_glyphs,
|
||||
&num_glyphs, NULL);
|
||||
if (unlikely (status))
|
||||
goto CLEANUP_GLYPHS;
|
||||
|
||||
status = _cairo_scaled_font_glyph_path (gstate->scaled_font,
|
||||
transformed_glyphs, num_glyphs,
|
||||
path);
|
||||
|
||||
CLEANUP_GLYPHS:
|
||||
if (transformed_glyphs != stack_transformed_glyphs)
|
||||
cairo_glyph_free (transformed_glyphs);
|
||||
|
||||
|
|
@ -2039,7 +2074,7 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate)
|
|||
* This also uses information from the scaled font and the surface to
|
||||
* cull/drop glyphs that will not be visible.
|
||||
**/
|
||||
static cairo_status_t
|
||||
static void
|
||||
_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
||||
const cairo_glyph_t *glyphs,
|
||||
int num_glyphs,
|
||||
|
|
@ -2050,15 +2085,13 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
|||
int *num_transformed_glyphs,
|
||||
cairo_text_cluster_t *transformed_clusters)
|
||||
{
|
||||
int i, j, k;
|
||||
cairo_rectangle_int_t surface_extents;
|
||||
cairo_matrix_t *ctm = &gstate->ctm;
|
||||
cairo_matrix_t *font_matrix = &gstate->font_matrix;
|
||||
cairo_matrix_t *device_transform = &gstate->target->device_transform;
|
||||
cairo_bool_t drop = FALSE;
|
||||
double x1 = 0, x2 = 0, y1 = 0, y2 = 0;
|
||||
|
||||
if (num_transformed_glyphs != NULL) {
|
||||
cairo_rectangle_int_t surface_extents;
|
||||
int i, j, k;
|
||||
|
||||
drop = TRUE;
|
||||
if (! _cairo_gstate_int_clip_extents (gstate, &surface_extents)) {
|
||||
|
|
@ -2068,7 +2101,7 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
|||
if (surface_extents.width == 0 || surface_extents.height == 0) {
|
||||
/* No visible area. Don't draw anything */
|
||||
*num_transformed_glyphs = 0;
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
return;
|
||||
}
|
||||
/* XXX We currently drop any glyphs that has its position outside
|
||||
* of the surface boundaries by a safety margin depending on the
|
||||
|
|
@ -2086,8 +2119,6 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
|||
|
||||
if (!drop)
|
||||
*num_transformed_glyphs = num_glyphs;
|
||||
} else
|
||||
num_transformed_glyphs = &j;
|
||||
|
||||
#define KEEP_GLYPH(glyph) (x1 <= glyph.x && glyph.x <= x2 && y1 <= glyph.y && glyph.y <= y2)
|
||||
|
||||
|
|
@ -2156,6 +2187,8 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
|||
if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
|
||||
j++;
|
||||
}
|
||||
memcpy (transformed_clusters, clusters,
|
||||
num_clusters * sizeof (cairo_text_cluster_t));
|
||||
} else {
|
||||
const cairo_glyph_t *cur_glyph;
|
||||
|
||||
|
|
@ -2209,6 +2242,8 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
|||
if (! drop || KEEP_GLYPH (transformed_glyphs[j]))
|
||||
j++;
|
||||
}
|
||||
memcpy (transformed_clusters, clusters,
|
||||
num_clusters * sizeof (cairo_text_cluster_t));
|
||||
} else {
|
||||
const cairo_glyph_t *cur_glyph;
|
||||
|
||||
|
|
@ -2252,6 +2287,4 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t *gstate,
|
|||
transformed_glyphs[j] = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
1545
src/cairo-image-compositor.c
Normal file
1545
src/cairo-image-compositor.c
Normal file
File diff suppressed because it is too large
Load diff
408
src/cairo-image-mask-compositor.c
Normal file
408
src/cairo-image-mask-compositor.c
Normal file
|
|
@ -0,0 +1,408 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2003 University of Southern California
|
||||
* Copyright © 2009,2010,2011 Intel Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
/* This compositor is slightly pointless. Just exists for testing
|
||||
* and as skeleton code.
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-image-surface-private.h"
|
||||
|
||||
#include "cairo-compositor-private.h"
|
||||
#include "cairo-region-private.h"
|
||||
|
||||
static cairo_int_status_t
|
||||
acquire (void *abstract_dst)
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
release (void *abstract_dst)
|
||||
{
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
set_clip_region (void *_surface,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
cairo_image_surface_t *surface = _surface;
|
||||
pixman_region32_t *rgn = region ? ®ion->rgn : NULL;
|
||||
|
||||
if (! pixman_image_set_clip_region32 (surface->pixman_image, rgn))
|
||||
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
has_snapshot (void *_dst,
|
||||
const cairo_pattern_t *pattern)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
draw_image (void *_dst,
|
||||
cairo_image_surface_t *image,
|
||||
int src_x, int src_y,
|
||||
int width, int height,
|
||||
int dst_x, int dst_y)
|
||||
{
|
||||
cairo_image_surface_t *dst = (cairo_image_surface_t *)_dst;
|
||||
|
||||
pixman_image_composite32 (PIXMAN_OP_SRC,
|
||||
image->pixman_image, NULL, dst->pixman_image,
|
||||
src_x, src_y,
|
||||
0, 0,
|
||||
dst_x, dst_y,
|
||||
width, height);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
color_to_uint32 (const cairo_color_t *color)
|
||||
{
|
||||
return
|
||||
(color->alpha_short >> 8 << 24) |
|
||||
(color->red_short >> 8 << 16) |
|
||||
(color->green_short & 0xff00) |
|
||||
(color->blue_short >> 8);
|
||||
}
|
||||
|
||||
static inline cairo_bool_t
|
||||
color_to_pixel (const cairo_color_t *color,
|
||||
double opacity,
|
||||
pixman_format_code_t format,
|
||||
uint32_t *pixel)
|
||||
{
|
||||
cairo_color_t opacity_color;
|
||||
uint32_t c;
|
||||
|
||||
if (!(format == PIXMAN_a8r8g8b8 ||
|
||||
format == PIXMAN_x8r8g8b8 ||
|
||||
format == PIXMAN_a8b8g8r8 ||
|
||||
format == PIXMAN_x8b8g8r8 ||
|
||||
format == PIXMAN_b8g8r8a8 ||
|
||||
format == PIXMAN_b8g8r8x8 ||
|
||||
format == PIXMAN_r5g6b5 ||
|
||||
format == PIXMAN_b5g6r5 ||
|
||||
format == PIXMAN_a8))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (opacity != 1.0) {
|
||||
_cairo_color_init_rgba (&opacity_color,
|
||||
color->red,
|
||||
color->green,
|
||||
color->blue,
|
||||
color->alpha * opacity);
|
||||
color = &opacity_color;
|
||||
}
|
||||
c = color_to_uint32 (color);
|
||||
|
||||
if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR) {
|
||||
c = ((c & 0xff000000) >> 0) |
|
||||
((c & 0x00ff0000) >> 16) |
|
||||
((c & 0x0000ff00) >> 0) |
|
||||
((c & 0x000000ff) << 16);
|
||||
}
|
||||
|
||||
if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA) {
|
||||
c = ((c & 0xff000000) >> 24) |
|
||||
((c & 0x00ff0000) >> 8) |
|
||||
((c & 0x0000ff00) << 8) |
|
||||
((c & 0x000000ff) << 24);
|
||||
}
|
||||
|
||||
if (format == PIXMAN_a8) {
|
||||
c = c >> 24;
|
||||
} else if (format == PIXMAN_r5g6b5 || format == PIXMAN_b5g6r5) {
|
||||
c = ((((c) >> 3) & 0x001f) |
|
||||
(((c) >> 5) & 0x07e0) |
|
||||
(((c) >> 8) & 0xf800));
|
||||
}
|
||||
|
||||
*pixel = c;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
fill_rectangles (void *_dst,
|
||||
cairo_operator_t op,
|
||||
const cairo_color_t *color,
|
||||
cairo_rectangle_int_t *rects,
|
||||
int num_rects)
|
||||
{
|
||||
cairo_image_surface_t *dst = _dst;
|
||||
uint32_t pixel;
|
||||
int i;
|
||||
|
||||
if (! color_to_pixel (color, 1.0, dst->pixman_format, &pixel))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
for (i = 0; i < num_rects; i++) {
|
||||
pixman_fill ((uint32_t *) dst->data, dst->stride / sizeof (uint32_t),
|
||||
PIXMAN_FORMAT_BPP (dst->pixman_format),
|
||||
rects[i].x, rects[i].y,
|
||||
rects[i].width, rects[i].height,
|
||||
pixel);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
fill_boxes (void *_dst,
|
||||
cairo_operator_t op,
|
||||
const cairo_color_t *color,
|
||||
cairo_boxes_t *boxes)
|
||||
{
|
||||
cairo_image_surface_t *dst = _dst;
|
||||
struct _cairo_boxes_chunk *chunk;
|
||||
uint32_t pixel;
|
||||
int i;
|
||||
|
||||
assert (boxes->is_pixel_aligned);
|
||||
|
||||
if (! color_to_pixel (color, 1.0, dst->pixman_format, &pixel))
|
||||
return CAIRO_INT_STATUS_UNSUPPORTED;
|
||||
|
||||
for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
|
||||
for (i = 0; i < chunk->count; i++) {
|
||||
int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x);
|
||||
int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
|
||||
int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
|
||||
int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
|
||||
pixman_fill ((uint32_t *) dst->data, dst->stride / sizeof (uint32_t),
|
||||
PIXMAN_FORMAT_BPP (dst->pixman_format),
|
||||
x1, y1, x2 - x1, y2 - y1,
|
||||
pixel);
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static pixman_op_t
|
||||
_pixman_operator (cairo_operator_t op)
|
||||
{
|
||||
switch ((int) op) {
|
||||
case CAIRO_OPERATOR_CLEAR:
|
||||
return PIXMAN_OP_CLEAR;
|
||||
|
||||
case CAIRO_OPERATOR_SOURCE:
|
||||
return PIXMAN_OP_SRC;
|
||||
case CAIRO_OPERATOR_OVER:
|
||||
return PIXMAN_OP_OVER;
|
||||
case CAIRO_OPERATOR_IN:
|
||||
return PIXMAN_OP_IN;
|
||||
case CAIRO_OPERATOR_OUT:
|
||||
return PIXMAN_OP_OUT;
|
||||
case CAIRO_OPERATOR_ATOP:
|
||||
return PIXMAN_OP_ATOP;
|
||||
|
||||
case CAIRO_OPERATOR_DEST:
|
||||
return PIXMAN_OP_DST;
|
||||
case CAIRO_OPERATOR_DEST_OVER:
|
||||
return PIXMAN_OP_OVER_REVERSE;
|
||||
case CAIRO_OPERATOR_DEST_IN:
|
||||
return PIXMAN_OP_IN_REVERSE;
|
||||
case CAIRO_OPERATOR_DEST_OUT:
|
||||
return PIXMAN_OP_OUT_REVERSE;
|
||||
case CAIRO_OPERATOR_DEST_ATOP:
|
||||
return PIXMAN_OP_ATOP_REVERSE;
|
||||
|
||||
case CAIRO_OPERATOR_XOR:
|
||||
return PIXMAN_OP_XOR;
|
||||
case CAIRO_OPERATOR_ADD:
|
||||
return PIXMAN_OP_ADD;
|
||||
case CAIRO_OPERATOR_SATURATE:
|
||||
return PIXMAN_OP_SATURATE;
|
||||
|
||||
case CAIRO_OPERATOR_MULTIPLY:
|
||||
return PIXMAN_OP_MULTIPLY;
|
||||
case CAIRO_OPERATOR_SCREEN:
|
||||
return PIXMAN_OP_SCREEN;
|
||||
case CAIRO_OPERATOR_OVERLAY:
|
||||
return PIXMAN_OP_OVERLAY;
|
||||
case CAIRO_OPERATOR_DARKEN:
|
||||
return PIXMAN_OP_DARKEN;
|
||||
case CAIRO_OPERATOR_LIGHTEN:
|
||||
return PIXMAN_OP_LIGHTEN;
|
||||
case CAIRO_OPERATOR_COLOR_DODGE:
|
||||
return PIXMAN_OP_COLOR_DODGE;
|
||||
case CAIRO_OPERATOR_COLOR_BURN:
|
||||
return PIXMAN_OP_COLOR_BURN;
|
||||
case CAIRO_OPERATOR_HARD_LIGHT:
|
||||
return PIXMAN_OP_HARD_LIGHT;
|
||||
case CAIRO_OPERATOR_SOFT_LIGHT:
|
||||
return PIXMAN_OP_SOFT_LIGHT;
|
||||
case CAIRO_OPERATOR_DIFFERENCE:
|
||||
return PIXMAN_OP_DIFFERENCE;
|
||||
case CAIRO_OPERATOR_EXCLUSION:
|
||||
return PIXMAN_OP_EXCLUSION;
|
||||
case CAIRO_OPERATOR_HSL_HUE:
|
||||
return PIXMAN_OP_HSL_HUE;
|
||||
case CAIRO_OPERATOR_HSL_SATURATION:
|
||||
return PIXMAN_OP_HSL_SATURATION;
|
||||
case CAIRO_OPERATOR_HSL_COLOR:
|
||||
return PIXMAN_OP_HSL_COLOR;
|
||||
case CAIRO_OPERATOR_HSL_LUMINOSITY:
|
||||
return PIXMAN_OP_HSL_LUMINOSITY;
|
||||
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
return PIXMAN_OP_OVER;
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
composite (void *_dst,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *abstract_src,
|
||||
cairo_surface_t *abstract_mask,
|
||||
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_image_surface_t *dst = _dst;
|
||||
cairo_pixman_source_t *src = (cairo_pixman_source_t *)abstract_src;
|
||||
cairo_pixman_source_t *mask = (cairo_pixman_source_t *)abstract_mask;
|
||||
if (mask) {
|
||||
pixman_image_composite32 (_pixman_operator (op),
|
||||
src->pixman_image, mask->pixman_image, dst->pixman_image,
|
||||
src_x, src_y,
|
||||
mask_x, mask_y,
|
||||
dst_x, dst_y,
|
||||
width, height);
|
||||
} else {
|
||||
pixman_image_composite32 (_pixman_operator (op),
|
||||
src->pixman_image, NULL, dst->pixman_image,
|
||||
src_x, src_y,
|
||||
0, 0,
|
||||
dst_x, dst_y,
|
||||
width, height);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_int_status_t
|
||||
composite_boxes (void *_dst,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *abstract_src,
|
||||
cairo_surface_t *abstract_mask,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int mask_x,
|
||||
int mask_y,
|
||||
int dst_x,
|
||||
int dst_y,
|
||||
cairo_boxes_t *boxes)
|
||||
{
|
||||
cairo_image_surface_t *dst = _dst;
|
||||
cairo_pixman_source_t *src = (cairo_pixman_source_t *)abstract_src;
|
||||
cairo_pixman_source_t *mask = (cairo_pixman_source_t *)abstract_mask;
|
||||
struct _cairo_boxes_chunk *chunk;
|
||||
int i;
|
||||
|
||||
assert (boxes->is_pixel_aligned);
|
||||
|
||||
op = _pixman_operator (op);
|
||||
for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
|
||||
for (i = 0; i < chunk->count; i++) {
|
||||
int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x);
|
||||
int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
|
||||
int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
|
||||
int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
|
||||
|
||||
if (mask) {
|
||||
pixman_image_composite32 (op,
|
||||
src->pixman_image, mask->pixman_image, dst->pixman_image,
|
||||
x1 + src_x, y1 + src_y,
|
||||
x1 + mask_x, y1 + mask_y,
|
||||
x1 + dst_x, y1 + dst_y,
|
||||
x2 - x1, y2 - y1);
|
||||
} else {
|
||||
pixman_image_composite32 (op,
|
||||
src->pixman_image, NULL, dst->pixman_image,
|
||||
x1 + src_x, y1 + src_y,
|
||||
0, 0,
|
||||
x1 + dst_x, y1 + dst_y,
|
||||
x2 - x1, y2 - y1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
const cairo_compositor_t *
|
||||
_cairo_image_mask_compositor_get (void)
|
||||
{
|
||||
static cairo_mask_compositor_t compositor;
|
||||
|
||||
if (compositor.base.delegate == NULL) {
|
||||
_cairo_mask_compositor_init (&compositor,
|
||||
_cairo_image_traps_compositor_get ());
|
||||
compositor.acquire = acquire;
|
||||
compositor.release = release;
|
||||
compositor.set_clip_region = set_clip_region;
|
||||
compositor.pattern_to_surface = _cairo_pixman_source_create_for_pattern;
|
||||
compositor.has_snapshot = has_snapshot;
|
||||
compositor.draw_image = draw_image;
|
||||
compositor.fill_rectangles = fill_rectangles;
|
||||
compositor.fill_boxes = fill_boxes;
|
||||
//compositor.check_composite = check_composite;
|
||||
compositor.composite = composite;
|
||||
//compositor.check_composite_boxes = check_composite_boxes;
|
||||
compositor.composite_boxes = composite_boxes;
|
||||
}
|
||||
|
||||
return &compositor.base;
|
||||
}
|
||||
975
src/cairo-image-source.c
Normal file
975
src/cairo-image-source.c
Normal file
|
|
@ -0,0 +1,975 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2003 University of Southern California
|
||||
* Copyright © 2009,2010,2011 Intel Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
/* The purpose of this file/surface is to simply translate a pattern
|
||||
* to a pixman_image_t and thence to feed it back to the general
|
||||
* compositor interface.
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-image-surface-private.h"
|
||||
|
||||
#include "cairo-compositor-private.h"
|
||||
#include "cairo-error-private.h"
|
||||
#include "cairo-pattern-private.h"
|
||||
#include "cairo-paginated-private.h"
|
||||
#include "cairo-recording-surface-private.h"
|
||||
#include "cairo-surface-observer-private.h"
|
||||
#include "cairo-surface-snapshot-private.h"
|
||||
#include "cairo-surface-subsurface-private.h"
|
||||
|
||||
#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
|
||||
|
||||
#if CAIRO_NO_MUTEX
|
||||
#define PIXMAN_HAS_ATOMIC_OPS 1
|
||||
#endif
|
||||
|
||||
#if PIXMAN_HAS_ATOMIC_OPS
|
||||
static pixman_image_t *__pixman_transparent_image;
|
||||
static pixman_image_t *__pixman_black_image;
|
||||
static pixman_image_t *__pixman_white_image;
|
||||
|
||||
static pixman_image_t *
|
||||
_pixman_transparent_image (void)
|
||||
{
|
||||
pixman_image_t *image;
|
||||
|
||||
image = __pixman_transparent_image;
|
||||
if (unlikely (image == NULL)) {
|
||||
pixman_color_t color;
|
||||
|
||||
color.red = 0x00;
|
||||
color.green = 0x00;
|
||||
color.blue = 0x00;
|
||||
color.alpha = 0x00;
|
||||
|
||||
image = pixman_image_create_solid_fill (&color);
|
||||
if (unlikely (image == NULL))
|
||||
return NULL;
|
||||
|
||||
if (_cairo_atomic_ptr_cmpxchg (&__pixman_transparent_image,
|
||||
NULL, image))
|
||||
{
|
||||
pixman_image_ref (image);
|
||||
}
|
||||
} else {
|
||||
pixman_image_ref (image);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
static pixman_image_t *
|
||||
_pixman_black_image (void)
|
||||
{
|
||||
pixman_image_t *image;
|
||||
|
||||
image = __pixman_black_image;
|
||||
if (unlikely (image == NULL)) {
|
||||
pixman_color_t color;
|
||||
|
||||
color.red = 0x00;
|
||||
color.green = 0x00;
|
||||
color.blue = 0x00;
|
||||
color.alpha = 0xffff;
|
||||
|
||||
image = pixman_image_create_solid_fill (&color);
|
||||
if (unlikely (image == NULL))
|
||||
return NULL;
|
||||
|
||||
if (_cairo_atomic_ptr_cmpxchg (&__pixman_black_image,
|
||||
NULL, image))
|
||||
{
|
||||
pixman_image_ref (image);
|
||||
}
|
||||
} else {
|
||||
pixman_image_ref (image);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
static pixman_image_t *
|
||||
_pixman_white_image (void)
|
||||
{
|
||||
pixman_image_t *image;
|
||||
|
||||
image = __pixman_white_image;
|
||||
if (unlikely (image == NULL)) {
|
||||
pixman_color_t color;
|
||||
|
||||
color.red = 0xffff;
|
||||
color.green = 0xffff;
|
||||
color.blue = 0xffff;
|
||||
color.alpha = 0xffff;
|
||||
|
||||
image = pixman_image_create_solid_fill (&color);
|
||||
if (unlikely (image == NULL))
|
||||
return NULL;
|
||||
|
||||
if (_cairo_atomic_ptr_cmpxchg (&__pixman_white_image,
|
||||
NULL, image))
|
||||
{
|
||||
pixman_image_ref (image);
|
||||
}
|
||||
} else {
|
||||
pixman_image_ref (image);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
hars_petruska_f54_1_random (void)
|
||||
{
|
||||
#define rol(x,k) ((x << k) | (x >> (32-k)))
|
||||
static uint32_t x;
|
||||
return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
|
||||
#undef rol
|
||||
}
|
||||
|
||||
static struct {
|
||||
cairo_color_t color;
|
||||
pixman_image_t *image;
|
||||
} cache[16];
|
||||
static int n_cached;
|
||||
|
||||
#else /* !PIXMAN_HAS_ATOMIC_OPS */
|
||||
static pixman_image_t *
|
||||
_pixman_transparent_image (void)
|
||||
{
|
||||
return _pixman_image_for_color (CAIRO_COLOR_TRANSPARENT);
|
||||
}
|
||||
|
||||
static pixman_image_t *
|
||||
_pixman_black_image (void)
|
||||
{
|
||||
return _pixman_image_for_color (CAIRO_COLOR_BLACK);
|
||||
}
|
||||
|
||||
static pixman_image_t *
|
||||
_pixman_white_image (void)
|
||||
{
|
||||
return _pixman_image_for_color (CAIRO_COLOR_WHITE);
|
||||
}
|
||||
#endif /* !PIXMAN_HAS_ATOMIC_OPS */
|
||||
|
||||
|
||||
pixman_image_t *
|
||||
_pixman_image_for_color (const cairo_color_t *cairo_color)
|
||||
{
|
||||
pixman_color_t color;
|
||||
pixman_image_t *image;
|
||||
|
||||
#if PIXMAN_HAS_ATOMIC_OPS
|
||||
int i;
|
||||
|
||||
if (CAIRO_COLOR_IS_CLEAR (cairo_color))
|
||||
return _pixman_transparent_image ();
|
||||
|
||||
if (CAIRO_COLOR_IS_OPAQUE (cairo_color)) {
|
||||
if (cairo_color->red_short <= 0x00ff &&
|
||||
cairo_color->green_short <= 0x00ff &&
|
||||
cairo_color->blue_short <= 0x00ff)
|
||||
{
|
||||
return _pixman_black_image ();
|
||||
}
|
||||
|
||||
if (cairo_color->red_short >= 0xff00 &&
|
||||
cairo_color->green_short >= 0xff00 &&
|
||||
cairo_color->blue_short >= 0xff00)
|
||||
{
|
||||
return _pixman_white_image ();
|
||||
}
|
||||
}
|
||||
|
||||
CAIRO_MUTEX_LOCK (_cairo_image_solid_cache_mutex);
|
||||
for (i = 0; i < n_cached; i++) {
|
||||
if (_cairo_color_equal (&cache[i].color, cairo_color)) {
|
||||
image = pixman_image_ref (cache[i].image);
|
||||
goto UNLOCK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
color.red = cairo_color->red_short;
|
||||
color.green = cairo_color->green_short;
|
||||
color.blue = cairo_color->blue_short;
|
||||
color.alpha = cairo_color->alpha_short;
|
||||
|
||||
image = pixman_image_create_solid_fill (&color);
|
||||
#if PIXMAN_HAS_ATOMIC_OPS
|
||||
if (image == NULL)
|
||||
goto UNLOCK;
|
||||
|
||||
if (n_cached < ARRAY_LENGTH (cache)) {
|
||||
i = n_cached++;
|
||||
} else {
|
||||
i = hars_petruska_f54_1_random () % ARRAY_LENGTH (cache);
|
||||
pixman_image_unref (cache[i].image);
|
||||
}
|
||||
cache[i].image = pixman_image_ref (image);
|
||||
cache[i].color = *cairo_color;
|
||||
|
||||
UNLOCK:
|
||||
CAIRO_MUTEX_UNLOCK (_cairo_image_solid_cache_mutex);
|
||||
#endif
|
||||
return image;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_cairo_image_reset_static_data (void)
|
||||
{
|
||||
#if PIXMAN_HAS_ATOMIC_OPS
|
||||
while (n_cached)
|
||||
pixman_image_unref (cache[--n_cached].image);
|
||||
|
||||
if (__pixman_transparent_image) {
|
||||
pixman_image_unref (__pixman_transparent_image);
|
||||
__pixman_transparent_image = NULL;
|
||||
}
|
||||
|
||||
if (__pixman_black_image) {
|
||||
pixman_image_unref (__pixman_black_image);
|
||||
__pixman_black_image = NULL;
|
||||
}
|
||||
|
||||
if (__pixman_white_image) {
|
||||
pixman_image_unref (__pixman_white_image);
|
||||
__pixman_white_image = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static pixman_image_t *
|
||||
_pixman_image_for_gradient (const cairo_gradient_pattern_t *pattern,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
int *ix, int *iy)
|
||||
{
|
||||
pixman_image_t *pixman_image;
|
||||
pixman_gradient_stop_t pixman_stops_static[2];
|
||||
pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
|
||||
pixman_transform_t pixman_transform;
|
||||
cairo_matrix_t matrix;
|
||||
cairo_circle_double_t extremes[2];
|
||||
pixman_point_fixed_t p1, p2;
|
||||
unsigned int i;
|
||||
cairo_int_status_t status;
|
||||
|
||||
if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
|
||||
pixman_stops = _cairo_malloc_ab (pattern->n_stops,
|
||||
sizeof(pixman_gradient_stop_t));
|
||||
if (unlikely (pixman_stops == NULL))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < pattern->n_stops; i++) {
|
||||
pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
|
||||
pixman_stops[i].color.red = pattern->stops[i].color.red_short;
|
||||
pixman_stops[i].color.green = pattern->stops[i].color.green_short;
|
||||
pixman_stops[i].color.blue = pattern->stops[i].color.blue_short;
|
||||
pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
|
||||
}
|
||||
|
||||
_cairo_gradient_pattern_fit_to_range (pattern, PIXMAN_MAX_INT >> 1, &matrix, extremes);
|
||||
|
||||
p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
|
||||
p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
|
||||
p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
|
||||
p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
|
||||
|
||||
if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
|
||||
pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
|
||||
pixman_stops,
|
||||
pattern->n_stops);
|
||||
} else {
|
||||
pixman_fixed_t r1, r2;
|
||||
|
||||
r1 = _cairo_fixed_16_16_from_double (extremes[0].radius);
|
||||
r2 = _cairo_fixed_16_16_from_double (extremes[1].radius);
|
||||
|
||||
pixman_image = pixman_image_create_radial_gradient (&p1, &p2, r1, r2,
|
||||
pixman_stops,
|
||||
pattern->n_stops);
|
||||
}
|
||||
|
||||
if (pixman_stops != pixman_stops_static)
|
||||
free (pixman_stops);
|
||||
|
||||
if (unlikely (pixman_image == NULL))
|
||||
return NULL;
|
||||
|
||||
*ix = *iy = 0;
|
||||
status = _cairo_matrix_to_pixman_matrix_offset (&matrix, pattern->base.filter,
|
||||
extents->x + extents->width/2.,
|
||||
extents->y + extents->height/2.,
|
||||
&pixman_transform, ix, iy);
|
||||
if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
|
||||
if (unlikely (status != CAIRO_INT_STATUS_SUCCESS) ||
|
||||
! pixman_image_set_transform (pixman_image, &pixman_transform))
|
||||
{
|
||||
pixman_image_unref (pixman_image);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
pixman_repeat_t pixman_repeat;
|
||||
|
||||
switch (pattern->base.extend) {
|
||||
default:
|
||||
case CAIRO_EXTEND_NONE:
|
||||
pixman_repeat = PIXMAN_REPEAT_NONE;
|
||||
break;
|
||||
case CAIRO_EXTEND_REPEAT:
|
||||
pixman_repeat = PIXMAN_REPEAT_NORMAL;
|
||||
break;
|
||||
case CAIRO_EXTEND_REFLECT:
|
||||
pixman_repeat = PIXMAN_REPEAT_REFLECT;
|
||||
break;
|
||||
case CAIRO_EXTEND_PAD:
|
||||
pixman_repeat = PIXMAN_REPEAT_PAD;
|
||||
break;
|
||||
}
|
||||
|
||||
pixman_image_set_repeat (pixman_image, pixman_repeat);
|
||||
}
|
||||
|
||||
return pixman_image;
|
||||
}
|
||||
|
||||
static pixman_image_t *
|
||||
_pixman_image_for_mesh (const cairo_mesh_pattern_t *pattern,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
int *tx, int *ty)
|
||||
{
|
||||
pixman_image_t *image;
|
||||
int width, height;
|
||||
|
||||
*tx = -extents->x;
|
||||
*ty = -extents->y;
|
||||
width = extents->width;
|
||||
height = extents->height;
|
||||
|
||||
image = pixman_image_create_bits (PIXMAN_a8r8g8b8, width, height, NULL, 0);
|
||||
if (unlikely (image == NULL))
|
||||
return NULL;
|
||||
|
||||
_cairo_mesh_pattern_rasterize (pattern,
|
||||
pixman_image_get_data (image),
|
||||
width, height,
|
||||
pixman_image_get_stride (image),
|
||||
*tx, *ty);
|
||||
return image;
|
||||
}
|
||||
|
||||
struct acquire_source_cleanup {
|
||||
cairo_surface_t *surface;
|
||||
cairo_image_surface_t *image;
|
||||
void *image_extra;
|
||||
};
|
||||
|
||||
static void
|
||||
_acquire_source_cleanup (pixman_image_t *pixman_image,
|
||||
void *closure)
|
||||
{
|
||||
struct acquire_source_cleanup *data = closure;
|
||||
|
||||
_cairo_surface_release_source_image (data->surface,
|
||||
data->image,
|
||||
data->image_extra);
|
||||
free (data);
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
expand_channel (uint16_t v, uint32_t bits)
|
||||
{
|
||||
int offset = 16 - bits;
|
||||
while (offset > 0) {
|
||||
v |= v >> bits;
|
||||
offset -= bits;
|
||||
bits += bits;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static pixman_image_t *
|
||||
_pixel_to_solid (cairo_image_surface_t *image, int x, int y)
|
||||
{
|
||||
uint32_t pixel;
|
||||
pixman_color_t color;
|
||||
|
||||
switch (image->format) {
|
||||
default:
|
||||
case CAIRO_FORMAT_INVALID:
|
||||
ASSERT_NOT_REACHED;
|
||||
return NULL;
|
||||
|
||||
case CAIRO_FORMAT_A1:
|
||||
pixel = *(uint8_t *) (image->data + y * image->stride + x/8);
|
||||
return pixel & (1 << (x&7)) ? _pixman_black_image () : _pixman_transparent_image ();
|
||||
|
||||
case CAIRO_FORMAT_A8:
|
||||
color.alpha = *(uint8_t *) (image->data + y * image->stride + x);
|
||||
color.alpha |= color.alpha << 8;
|
||||
if (color.alpha == 0)
|
||||
return _pixman_transparent_image ();
|
||||
if (color.alpha == 0xffff)
|
||||
return _pixman_black_image ();
|
||||
|
||||
color.red = color.green = color.blue = 0;
|
||||
return pixman_image_create_solid_fill (&color);
|
||||
|
||||
case CAIRO_FORMAT_RGB16_565:
|
||||
pixel = *(uint16_t *) (image->data + y * image->stride + 2 * x);
|
||||
if (pixel == 0)
|
||||
return _pixman_black_image ();
|
||||
if (pixel == 0xffff)
|
||||
return _pixman_white_image ();
|
||||
|
||||
color.alpha = 0xffff;
|
||||
color.red = expand_channel ((pixel >> 11 & 0x1f) << 11, 5);
|
||||
color.green = expand_channel ((pixel >> 5 & 0x3f) << 10, 6);
|
||||
color.blue = expand_channel ((pixel & 0x1f) << 11, 5);
|
||||
return pixman_image_create_solid_fill (&color);
|
||||
|
||||
case CAIRO_FORMAT_RGB30:
|
||||
pixel = *(uint32_t *) (image->data + y * image->stride + 4 * x);
|
||||
pixel &= 0x3fffffff; /* ignore alpha bits */
|
||||
if (pixel == 0)
|
||||
return _pixman_black_image ();
|
||||
if (pixel == 0x3fffffff)
|
||||
return _pixman_white_image ();
|
||||
|
||||
/* convert 10bpc to 16bpc */
|
||||
color.alpha = 0xffff;
|
||||
color.red = expand_channel((pixel >> 20) & 0x3fff, 10);
|
||||
color.green = expand_channel((pixel >> 10) & 0x3fff, 10);
|
||||
color.blue = expand_channel(pixel & 0x3fff, 10);
|
||||
return pixman_image_create_solid_fill (&color);
|
||||
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
pixel = *(uint32_t *) (image->data + y * image->stride + 4 * x);
|
||||
color.alpha = image->format == CAIRO_FORMAT_ARGB32 ? (pixel >> 24) | (pixel >> 16 & 0xff00) : 0xffff;
|
||||
if (color.alpha == 0)
|
||||
return _pixman_transparent_image ();
|
||||
if (pixel == 0xffffffff)
|
||||
return _pixman_white_image ();
|
||||
if (color.alpha == 0xffff && (pixel & 0xffffff) == 0)
|
||||
return _pixman_black_image ();
|
||||
|
||||
color.red = (pixel >> 16 & 0xff) | (pixel >> 8 & 0xff00);
|
||||
color.green = (pixel >> 8 & 0xff) | (pixel & 0xff00);
|
||||
color.blue = (pixel & 0xff) | (pixel << 8 & 0xff00);
|
||||
return pixman_image_create_solid_fill (&color);
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_bool_t
|
||||
_pixman_image_set_properties (pixman_image_t *pixman_image,
|
||||
const cairo_pattern_t *pattern,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
int *ix,int *iy)
|
||||
{
|
||||
pixman_transform_t pixman_transform;
|
||||
cairo_int_status_t status;
|
||||
|
||||
status = _cairo_matrix_to_pixman_matrix_offset (&pattern->matrix,
|
||||
pattern->filter,
|
||||
extents->x + extents->width/2.,
|
||||
extents->y + extents->height/2.,
|
||||
&pixman_transform, ix, iy);
|
||||
if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
|
||||
{
|
||||
/* If the transform is an identity, we don't need to set it
|
||||
* and we can use any filtering, so choose the fastest one. */
|
||||
pixman_image_set_filter (pixman_image, PIXMAN_FILTER_NEAREST, NULL, 0);
|
||||
}
|
||||
else if (unlikely (status != CAIRO_INT_STATUS_SUCCESS ||
|
||||
! pixman_image_set_transform (pixman_image,
|
||||
&pixman_transform)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
pixman_filter_t pixman_filter;
|
||||
|
||||
switch (pattern->filter) {
|
||||
case CAIRO_FILTER_FAST:
|
||||
pixman_filter = PIXMAN_FILTER_FAST;
|
||||
break;
|
||||
case CAIRO_FILTER_GOOD:
|
||||
pixman_filter = PIXMAN_FILTER_GOOD;
|
||||
break;
|
||||
case CAIRO_FILTER_BEST:
|
||||
pixman_filter = PIXMAN_FILTER_BEST;
|
||||
break;
|
||||
case CAIRO_FILTER_NEAREST:
|
||||
pixman_filter = PIXMAN_FILTER_NEAREST;
|
||||
break;
|
||||
case CAIRO_FILTER_BILINEAR:
|
||||
pixman_filter = PIXMAN_FILTER_BILINEAR;
|
||||
break;
|
||||
case CAIRO_FILTER_GAUSSIAN:
|
||||
/* XXX: The GAUSSIAN value has no implementation in cairo
|
||||
* whatsoever, so it was really a mistake to have it in the
|
||||
* API. We could fix this by officially deprecating it, or
|
||||
* else inventing semantics and providing an actual
|
||||
* implementation for it. */
|
||||
default:
|
||||
pixman_filter = PIXMAN_FILTER_BEST;
|
||||
}
|
||||
|
||||
pixman_image_set_filter (pixman_image, pixman_filter, NULL, 0);
|
||||
}
|
||||
|
||||
{
|
||||
pixman_repeat_t pixman_repeat;
|
||||
|
||||
switch (pattern->extend) {
|
||||
default:
|
||||
case CAIRO_EXTEND_NONE:
|
||||
pixman_repeat = PIXMAN_REPEAT_NONE;
|
||||
break;
|
||||
case CAIRO_EXTEND_REPEAT:
|
||||
pixman_repeat = PIXMAN_REPEAT_NORMAL;
|
||||
break;
|
||||
case CAIRO_EXTEND_REFLECT:
|
||||
pixman_repeat = PIXMAN_REPEAT_REFLECT;
|
||||
break;
|
||||
case CAIRO_EXTEND_PAD:
|
||||
pixman_repeat = PIXMAN_REPEAT_PAD;
|
||||
break;
|
||||
}
|
||||
|
||||
pixman_image_set_repeat (pixman_image, pixman_repeat);
|
||||
}
|
||||
|
||||
if (pattern->has_component_alpha)
|
||||
pixman_image_set_component_alpha (pixman_image, TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static pixman_image_t *
|
||||
_pixman_image_for_recording (cairo_image_surface_t *dst,
|
||||
const cairo_surface_pattern_t *pattern,
|
||||
cairo_bool_t is_mask,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
const cairo_rectangle_int_t *sample,
|
||||
int *ix, int *iy)
|
||||
{
|
||||
cairo_surface_t *source, *clone;
|
||||
cairo_rectangle_int_t limit;
|
||||
pixman_image_t *pixman_image;
|
||||
cairo_status_t status;
|
||||
cairo_extend_t extend;
|
||||
cairo_matrix_t *m, matrix;
|
||||
int tx = 0, ty = 0;
|
||||
|
||||
*ix = *iy = 0;
|
||||
|
||||
source = pattern->surface;
|
||||
if (_cairo_surface_is_subsurface (source))
|
||||
source = _cairo_surface_subsurface_get_target_with_offset (source, &tx, &ty);
|
||||
if (_cairo_surface_is_snapshot (source))
|
||||
source = _cairo_surface_snapshot_get_target (source);
|
||||
if (_cairo_surface_is_observer (source))
|
||||
source = _cairo_surface_observer_get_target (source);
|
||||
if (_cairo_surface_is_paginated (source))
|
||||
source = _cairo_paginated_surface_get_target (source);
|
||||
|
||||
extend = pattern->base.extend;
|
||||
if (_cairo_surface_get_extents (source, &limit)) {
|
||||
if (sample->x >= limit.x &&
|
||||
sample->y >= limit.y &&
|
||||
sample->x + sample->width <= limit.x + limit.width &&
|
||||
sample->y + sample->height <= limit.y + limit.height)
|
||||
{
|
||||
extend = CAIRO_EXTEND_NONE;
|
||||
}
|
||||
else if (extend == CAIRO_EXTEND_NONE &&
|
||||
(sample->x + sample->width <= limit.x ||
|
||||
sample->x >= limit.x + limit.width ||
|
||||
sample->y + sample->height <= limit.y ||
|
||||
sample->y >= limit.y + limit.height))
|
||||
{
|
||||
return _pixman_transparent_image ();
|
||||
}
|
||||
} else
|
||||
extend = CAIRO_EXTEND_NONE;
|
||||
|
||||
if (extents == CAIRO_EXTEND_NONE)
|
||||
limit = *extents;
|
||||
|
||||
clone = cairo_image_surface_create (dst->format, limit.width, limit.height);
|
||||
cairo_surface_set_device_offset (clone, limit.x, limit.y);
|
||||
|
||||
m = NULL;
|
||||
if (extend == CAIRO_EXTEND_NONE) {
|
||||
m = &matrix;
|
||||
cairo_matrix_multiply (m,
|
||||
&dst->base.device_transform,
|
||||
&pattern->base.matrix);
|
||||
if (tx | ty)
|
||||
cairo_matrix_translate (m, tx, ty);
|
||||
} else {
|
||||
/* XXX extract scale factor for repeating patterns */
|
||||
}
|
||||
|
||||
status = _cairo_recording_surface_replay_with_clip (source, m, clone, NULL);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (clone);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pixman_image = pixman_image_ref (((cairo_image_surface_t *)clone)->pixman_image);
|
||||
cairo_surface_destroy (clone);
|
||||
|
||||
if (extend != CAIRO_EXTEND_NONE) {
|
||||
if (! _pixman_image_set_properties (pixman_image,
|
||||
&pattern->base, extents,
|
||||
ix, iy)) {
|
||||
pixman_image_unref (pixman_image);
|
||||
pixman_image= NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return pixman_image;
|
||||
}
|
||||
|
||||
static pixman_image_t *
|
||||
_pixman_image_for_surface (cairo_image_surface_t *dst,
|
||||
const cairo_surface_pattern_t *pattern,
|
||||
cairo_bool_t is_mask,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
const cairo_rectangle_int_t *sample,
|
||||
int *ix, int *iy)
|
||||
{
|
||||
cairo_extend_t extend = pattern->base.extend;
|
||||
pixman_image_t *pixman_image;
|
||||
|
||||
*ix = *iy = 0;
|
||||
pixman_image = NULL;
|
||||
if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
|
||||
return _pixman_image_for_recording(dst, pattern,
|
||||
is_mask, extents, sample,
|
||||
ix, iy);
|
||||
|
||||
if (pattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE &&
|
||||
(! is_mask || ! pattern->base.has_component_alpha ||
|
||||
(pattern->surface->content & CAIRO_CONTENT_COLOR) == 0))
|
||||
{
|
||||
cairo_image_surface_t *source = (cairo_image_surface_t *) pattern->surface;
|
||||
cairo_surface_type_t type;
|
||||
|
||||
if (_cairo_surface_is_snapshot (&source->base))
|
||||
source = (cairo_image_surface_t *) _cairo_surface_snapshot_get_target (&source->base);
|
||||
|
||||
type = source->base.backend->type;
|
||||
if (type == CAIRO_SURFACE_TYPE_IMAGE) {
|
||||
if (extend != CAIRO_EXTEND_NONE &&
|
||||
sample->x >= 0 &&
|
||||
sample->y >= 0 &&
|
||||
sample->x + sample->width <= source->width &&
|
||||
sample->y + sample->height <= source->height)
|
||||
{
|
||||
extend = CAIRO_EXTEND_NONE;
|
||||
}
|
||||
|
||||
if (sample->width == 1 && sample->height == 1) {
|
||||
if (sample->x < 0 ||
|
||||
sample->y < 0 ||
|
||||
sample->x >= source->width ||
|
||||
sample->y >= source->height)
|
||||
{
|
||||
if (extend == CAIRO_EXTEND_NONE)
|
||||
return _pixman_transparent_image ();
|
||||
}
|
||||
else
|
||||
{
|
||||
pixman_image = _pixel_to_solid (source,
|
||||
sample->x, sample->y);
|
||||
if (pixman_image)
|
||||
return pixman_image;
|
||||
}
|
||||
}
|
||||
|
||||
#if PIXMAN_HAS_ATOMIC_OPS
|
||||
/* avoid allocating a 'pattern' image if we can reuse the original */
|
||||
*ix = *iy = 0;
|
||||
if (extend == CAIRO_EXTEND_NONE &&
|
||||
_cairo_matrix_is_pixman_translation (&pattern->base.matrix,
|
||||
pattern->base.filter,
|
||||
ix, iy))
|
||||
{
|
||||
return pixman_image_ref (source->pixman_image);
|
||||
}
|
||||
#endif
|
||||
|
||||
pixman_image = pixman_image_create_bits (source->pixman_format,
|
||||
source->width,
|
||||
source->height,
|
||||
(uint32_t *) source->data,
|
||||
source->stride);
|
||||
if (unlikely (pixman_image == NULL))
|
||||
return NULL;
|
||||
} else if (type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
|
||||
cairo_surface_subsurface_t *sub;
|
||||
cairo_bool_t is_contained = FALSE;
|
||||
|
||||
sub = (cairo_surface_subsurface_t *) source;
|
||||
source = (cairo_image_surface_t *) sub->target;
|
||||
|
||||
if (sample->x >= 0 &&
|
||||
sample->y >= 0 &&
|
||||
sample->x + sample->width <= sub->extents.width &&
|
||||
sample->y + sample->height <= sub->extents.height)
|
||||
{
|
||||
is_contained = TRUE;
|
||||
}
|
||||
|
||||
if (sample->width == 1 && sample->height == 1) {
|
||||
if (is_contained) {
|
||||
pixman_image = _pixel_to_solid (source,
|
||||
sub->extents.x + sample->x,
|
||||
sub->extents.y + sample->y);
|
||||
if (pixman_image)
|
||||
return pixman_image;
|
||||
} else {
|
||||
if (extend == CAIRO_EXTEND_NONE)
|
||||
return _pixman_transparent_image ();
|
||||
}
|
||||
}
|
||||
|
||||
#if PIXMAN_HAS_ATOMIC_OPS
|
||||
*ix = sub->extents.x;
|
||||
*iy = sub->extents.y;
|
||||
if (is_contained &&
|
||||
_cairo_matrix_is_pixman_translation (&pattern->base.matrix,
|
||||
pattern->base.filter,
|
||||
ix, iy))
|
||||
{
|
||||
return pixman_image_ref (source->pixman_image);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Avoid sub-byte offsets, force a copy in that case. */
|
||||
if (PIXMAN_FORMAT_BPP (source->pixman_format) >= 8) {
|
||||
void *data = source->data
|
||||
+ sub->extents.x * PIXMAN_FORMAT_BPP(source->pixman_format)/8
|
||||
+ sub->extents.y * source->stride;
|
||||
pixman_image = pixman_image_create_bits (source->pixman_format,
|
||||
sub->extents.width,
|
||||
sub->extents.height,
|
||||
data,
|
||||
source->stride);
|
||||
if (unlikely (pixman_image == NULL))
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if PIXMAN_HAS_ATOMIC_OPS
|
||||
*ix = *iy = 0;
|
||||
#endif
|
||||
if (pixman_image == NULL) {
|
||||
struct acquire_source_cleanup *cleanup;
|
||||
cairo_image_surface_t *image;
|
||||
void *extra;
|
||||
cairo_status_t status;
|
||||
|
||||
status = _cairo_surface_acquire_source_image (pattern->surface, &image, &extra);
|
||||
if (unlikely (status))
|
||||
return NULL;
|
||||
|
||||
if (sample->x >= 0 && sample->y >= 0 &&
|
||||
sample->x + sample->width <= image->width &&
|
||||
sample->y + sample->height <= image->height)
|
||||
{
|
||||
extend = CAIRO_EXTEND_NONE;
|
||||
}
|
||||
|
||||
if (sample->width == 1 && sample->height == 1) {
|
||||
if (sample->x < 0 ||
|
||||
sample->y < 0 ||
|
||||
sample->x >= image->width ||
|
||||
sample->y >= image->height)
|
||||
{
|
||||
if (extend == CAIRO_EXTEND_NONE) {
|
||||
pixman_image = _pixman_transparent_image ();
|
||||
_cairo_surface_release_source_image (pattern->surface, image, extra);
|
||||
return pixman_image;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pixman_image = _pixel_to_solid (image, sample->x, sample->y);
|
||||
if (pixman_image) {
|
||||
_cairo_surface_release_source_image (pattern->surface, image, extra);
|
||||
return pixman_image;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pixman_image = pixman_image_create_bits (image->pixman_format,
|
||||
image->width,
|
||||
image->height,
|
||||
(uint32_t *) image->data,
|
||||
image->stride);
|
||||
if (unlikely (pixman_image == NULL)) {
|
||||
_cairo_surface_release_source_image (pattern->surface, image, extra);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cleanup = malloc (sizeof (*cleanup));
|
||||
if (unlikely (cleanup == NULL)) {
|
||||
_cairo_surface_release_source_image (pattern->surface, image, extra);
|
||||
pixman_image_unref (pixman_image);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cleanup->surface = pattern->surface;
|
||||
cleanup->image = image;
|
||||
cleanup->image_extra = extra;
|
||||
pixman_image_set_destroy_function (pixman_image,
|
||||
_acquire_source_cleanup, cleanup);
|
||||
}
|
||||
|
||||
if (! _pixman_image_set_properties (pixman_image,
|
||||
&pattern->base, extents,
|
||||
ix, iy)) {
|
||||
pixman_image_unref (pixman_image);
|
||||
pixman_image= NULL;
|
||||
}
|
||||
|
||||
return pixman_image;
|
||||
}
|
||||
|
||||
pixman_image_t *
|
||||
_pixman_image_for_pattern (cairo_image_surface_t *dst,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_bool_t is_mask,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
const cairo_rectangle_int_t *sample,
|
||||
int *tx, int *ty)
|
||||
{
|
||||
*tx = *ty = 0;
|
||||
|
||||
if (pattern == NULL)
|
||||
return _pixman_white_image ();
|
||||
|
||||
switch (pattern->type) {
|
||||
default:
|
||||
ASSERT_NOT_REACHED;
|
||||
case CAIRO_PATTERN_TYPE_SOLID:
|
||||
return _pixman_image_for_color (&((const cairo_solid_pattern_t *) pattern)->color);
|
||||
|
||||
case CAIRO_PATTERN_TYPE_RADIAL:
|
||||
case CAIRO_PATTERN_TYPE_LINEAR:
|
||||
return _pixman_image_for_gradient ((const cairo_gradient_pattern_t *) pattern,
|
||||
extents, tx, ty);
|
||||
|
||||
case CAIRO_PATTERN_TYPE_MESH:
|
||||
return _pixman_image_for_mesh ((const cairo_mesh_pattern_t *) pattern,
|
||||
extents, tx, ty);
|
||||
|
||||
case CAIRO_PATTERN_TYPE_SURFACE:
|
||||
return _pixman_image_for_surface (dst,
|
||||
(const cairo_surface_pattern_t *) pattern,
|
||||
is_mask, extents, sample,
|
||||
tx, ty);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_image_source_finish (void *abstract_surface)
|
||||
{
|
||||
cairo_image_source_t *source = abstract_surface;
|
||||
|
||||
pixman_image_unref (source->pixman_image);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static const cairo_surface_backend_t cairo_image_source_backend = {
|
||||
CAIRO_SURFACE_TYPE_IMAGE,
|
||||
_cairo_image_source_finish,
|
||||
NULL, /* read-only wrapper */
|
||||
};
|
||||
|
||||
cairo_surface_t *
|
||||
_cairo_image_source_create_for_pattern (cairo_surface_t *dst,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_bool_t is_mask,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
const cairo_rectangle_int_t *sample,
|
||||
int *src_x, int *src_y)
|
||||
{
|
||||
cairo_image_source_t *source;
|
||||
|
||||
source = malloc (sizeof (cairo_image_source_t));
|
||||
if (unlikely (source == NULL))
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
||||
source->pixman_image =
|
||||
_pixman_image_for_pattern ((cairo_image_surface_t *)dst,
|
||||
pattern, is_mask,
|
||||
extents, sample,
|
||||
src_x, src_y);
|
||||
if (unlikely (source->pixman_image == NULL)) {
|
||||
free (source);
|
||||
return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
_cairo_surface_init (&source->base,
|
||||
&cairo_image_source_backend,
|
||||
NULL, /* device */
|
||||
CAIRO_CONTENT_COLOR_ALPHA);
|
||||
|
||||
source->is_opaque_solid =
|
||||
pattern == NULL || _cairo_pattern_is_opaque_solid (pattern);
|
||||
|
||||
return &source->base;
|
||||
}
|
||||
131
src/cairo-image-spans-compositor.c
Normal file
131
src/cairo-image-spans-compositor.c
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
|
||||
/* cairo - a vector graphics library with display and print output
|
||||
*
|
||||
* Copyright © 2003 University of Southern California
|
||||
* Copyright © 2009,2010,2011 Intel Corporation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it either under the terms of the GNU Lesser General Public
|
||||
* License version 2.1 as published by the Free Software Foundation
|
||||
* (the "LGPL") or, at your option, under the terms of the Mozilla
|
||||
* Public License Version 1.1 (the "MPL"). If you do not alter this
|
||||
* notice, a recipient may use your version of this file under either
|
||||
* the MPL or the LGPL.
|
||||
*
|
||||
* You should have received a copy of the LGPL along with this library
|
||||
* in the file COPYING-LGPL-2.1; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
|
||||
* You should have received a copy of the MPL along with this library
|
||||
* in the file COPYING-MPL-1.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
|
||||
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
|
||||
* the specific language governing rights and limitations.
|
||||
*
|
||||
* The Original Code is the cairo graphics library.
|
||||
*
|
||||
* The Initial Developer of the Original Code is University of Southern
|
||||
* California.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Carl D. Worth <cworth@cworth.org>
|
||||
* Chris Wilson <chris@chris-wilson.co.uk>
|
||||
*/
|
||||
|
||||
#include "cairoint.h"
|
||||
|
||||
#include "cairo-compositor-private.h"
|
||||
#include "cairo-image-surface-private.h"
|
||||
#include "cairo-spans-compositor-private.h"
|
||||
|
||||
typedef struct _cairo_image_span_renderer {
|
||||
cairo_span_renderer_t base;
|
||||
|
||||
pixman_image_compositor_t *compositor;
|
||||
pixman_image_t *src;
|
||||
float opacity;
|
||||
cairo_rectangle_int_t extents;
|
||||
} cairo_image_span_renderer_t;
|
||||
|
||||
static cairo_status_t
|
||||
_cairo_image_span_renderer_init (cairo_abstract_span_renderer_t *_r,
|
||||
cairo_surface_t *dst,
|
||||
cairo_operator_t op,
|
||||
cairo_surface_t *src,
|
||||
int src_x, int src_y;
|
||||
float opacity,
|
||||
const cairo_composite_rectangles_t *composite,
|
||||
cairo_bool_t needs_clip)
|
||||
{
|
||||
cairo_image_span_renderer_t *r = (cairo_image_span_renderer_t *)_r;
|
||||
cairo_pixman_source_t *src = (cairo_pixman_source_t *)_src;
|
||||
int src_x, src_y;
|
||||
|
||||
if (op == CAIRO_OPERATOR_CLEAR) {
|
||||
op = CAIRO_OPERATOR_DEST_OUT;
|
||||
pattern = NULL;
|
||||
}
|
||||
|
||||
r->src = ((cairo_pixman_source_t *) src)->pixman_image;
|
||||
r->opacity = opacity;
|
||||
|
||||
if (composite->is_bounded) {
|
||||
if (opacity == 1.)
|
||||
r->base.render_rows = _cairo_image_bounded_opaque_spans;
|
||||
else
|
||||
r->base.render_rows = _cairo_image_bounded_spans;
|
||||
r->base.finish = NULL;
|
||||
} else {
|
||||
if (needs_clip)
|
||||
r->base.render_rows = _cairo_image_clipped_spans;
|
||||
else
|
||||
r->base.render_rows = _cairo_image_unbounded_spans;
|
||||
r->base.finish = _cairo_image_finish_unbounded_spans;
|
||||
r->extents = composite->unbounded;
|
||||
r->extents.height += r->extents.y;
|
||||
|
||||
}
|
||||
r->compositor =
|
||||
pixman_image_create_compositor (_pixman_operator (op),
|
||||
r->src, NULL, dst->pixman_image,
|
||||
composite->bounded.x + src_x,
|
||||
composite->bounded.y + src_y,
|
||||
0, 0,
|
||||
composite->bounded.x,
|
||||
composite->bounded.y,
|
||||
composite->bounded.width,
|
||||
composite->bounded.height);
|
||||
if (unlikely (r->compositor == NULL))
|
||||
return CAIRO_INT_STATUS_NOTHING_TO_DO;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void
|
||||
_cairo_image_span_renderer_fini (cairo_abstract_span_renderer_t *_r)
|
||||
{
|
||||
cairo_image_span_renderer_t *r = (cairo_image_span_renderer_t *) r;
|
||||
pixman_image_compositor_destroy (r->compositor);
|
||||
}
|
||||
|
||||
const cairo_compositor_t *
|
||||
_cairo_image_spans_compositor_get (void)
|
||||
{
|
||||
static cairo_spans_compositor_t compositor;
|
||||
|
||||
if (compositor.base.delegate == NULL) {
|
||||
/* Can't fallback to the mask compositor as that will simply
|
||||
* call the spans-compositor again to render the mask!
|
||||
*/
|
||||
_cairo_spans_compositor_init (&compositor,
|
||||
_cairo_image_traps_compositor_get());
|
||||
|
||||
}
|
||||
|
||||
return &compositor.base;
|
||||
}
|
||||
|
|
@ -44,9 +44,13 @@
|
|||
|
||||
CAIRO_BEGIN_DECLS
|
||||
|
||||
/* The canonical image backend */
|
||||
struct _cairo_image_surface {
|
||||
cairo_surface_t base;
|
||||
|
||||
pixman_image_t *pixman_image;
|
||||
const cairo_compositor_t *compositor;
|
||||
|
||||
pixman_format_code_t pixman_format;
|
||||
cairo_format_t format;
|
||||
unsigned char *data;
|
||||
|
|
@ -56,20 +60,55 @@ struct _cairo_image_surface {
|
|||
int stride;
|
||||
int depth;
|
||||
|
||||
pixman_image_t *pixman_image;
|
||||
|
||||
unsigned owns_data : 1;
|
||||
unsigned transparency : 2;
|
||||
unsigned color : 2;
|
||||
};
|
||||
|
||||
extern const cairo_private cairo_surface_backend_t _cairo_image_surface_backend;
|
||||
/* A wrapper for holding pixman images returned by create_for_pattern */
|
||||
typedef struct _cairo_image_source {
|
||||
cairo_surface_t base;
|
||||
|
||||
pixman_image_t *pixman_image;
|
||||
unsigned is_opaque_solid : 1;
|
||||
} cairo_image_source_t;
|
||||
|
||||
cairo_private extern const cairo_surface_backend_t _cairo_image_surface_backend;
|
||||
|
||||
cairo_private const cairo_compositor_t *
|
||||
_cairo_image_mask_compositor_get (void);
|
||||
|
||||
cairo_private const cairo_compositor_t *
|
||||
_cairo_image_traps_compositor_get (void);
|
||||
|
||||
cairo_private const cairo_compositor_t *
|
||||
_cairo_image_spans_compositor_get (void);
|
||||
|
||||
cairo_private void
|
||||
_cairo_image_surface_init (cairo_image_surface_t *surface,
|
||||
pixman_image_t *pixman_image,
|
||||
pixman_format_code_t pixman_format);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_image_surface_map_to_image (void *abstract_other,
|
||||
const cairo_rectangle_int_t *extents);
|
||||
|
||||
cairo_private cairo_int_status_t
|
||||
_cairo_image_surface_unmap_image (void *abstract_surface,
|
||||
cairo_image_surface_t *image);
|
||||
cairo_private cairo_status_t
|
||||
_cairo_image_surface_acquire_source_image (void *abstract_surface,
|
||||
cairo_image_surface_t **image_out,
|
||||
void **image_extra);
|
||||
|
||||
cairo_private void
|
||||
_cairo_image_surface_release_source_image (void *abstract_surface,
|
||||
cairo_image_surface_t *image,
|
||||
void *image_extra);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_image_surface_snapshot (void *abstract_surface);
|
||||
|
||||
cairo_private_no_warn cairo_bool_t
|
||||
_cairo_image_surface_get_extents (void *abstract_surface,
|
||||
cairo_rectangle_int_t *rectangle);
|
||||
|
|
@ -78,9 +117,52 @@ cairo_private void
|
|||
_cairo_image_surface_get_font_options (void *abstract_surface,
|
||||
cairo_font_options_t *options);
|
||||
|
||||
cairo_private cairo_surface_t *
|
||||
_cairo_image_source_create_for_pattern (cairo_surface_t *dst,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_bool_t is_mask,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
const cairo_rectangle_int_t *sample,
|
||||
int *src_x, int *src_y);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_image_surface_finish (void *abstract_surface);
|
||||
|
||||
cairo_private pixman_image_t *
|
||||
_pixman_image_for_color (const cairo_color_t *cairo_color);
|
||||
|
||||
cairo_private pixman_image_t *
|
||||
_pixman_image_for_pattern (cairo_image_surface_t *dst,
|
||||
const cairo_pattern_t *pattern,
|
||||
cairo_bool_t is_mask,
|
||||
const cairo_rectangle_int_t *extents,
|
||||
const cairo_rectangle_int_t *sample,
|
||||
int *tx, int *ty);
|
||||
|
||||
cairo_private void
|
||||
_pixman_image_add_traps (pixman_image_t *image,
|
||||
int dst_x, int dst_y,
|
||||
cairo_traps_t *traps);
|
||||
|
||||
cairo_private void
|
||||
_pixman_image_add_tristrip (pixman_image_t *image,
|
||||
int dst_x, int dst_y,
|
||||
cairo_tristrip_t *strip);
|
||||
|
||||
/**
|
||||
* _cairo_surface_is_image:
|
||||
* @surface: a #cairo_surface_t
|
||||
*
|
||||
* Checks if a surface is an #cairo_image_surface_t
|
||||
*
|
||||
* Return value: %TRUE if the surface is an image surface
|
||||
**/
|
||||
static inline cairo_bool_t
|
||||
_cairo_surface_is_image (const cairo_surface_t *surface)
|
||||
{
|
||||
return surface->backend == &_cairo_image_surface_backend;
|
||||
}
|
||||
|
||||
CAIRO_END_DECLS
|
||||
|
||||
#endif /* CAIRO_IMAGE_SURFACE_PRIVATE_H */
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
1412
src/cairo-mask-compositor.c
Normal file
1412
src/cairo-mask-compositor.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -889,6 +889,9 @@ _cairo_matrix_transformed_circle_major_axis (const cairo_matrix_t *matrix,
|
|||
{
|
||||
double a, b, c, d, f, g, h, i, j;
|
||||
|
||||
if (_cairo_matrix_has_unity_scale (matrix))
|
||||
return radius;
|
||||
|
||||
_cairo_matrix_get_affine (matrix,
|
||||
&a, &b,
|
||||
&c, &d,
|
||||
|
|
@ -1043,6 +1046,9 @@ _cairo_matrix_is_pixman_translation (const cairo_matrix_t *matrix,
|
|||
if (!_cairo_matrix_is_translation (matrix))
|
||||
return FALSE;
|
||||
|
||||
if (matrix->x0 == 0. && matrix->y0 == 0.)
|
||||
return TRUE;
|
||||
|
||||
tx = matrix->x0 + *x_offset;
|
||||
ty = matrix->y0 + *y_offset;
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue