summaryrefslogtreecommitdiff
path: root/libs/cairo-1.16.0/src/cairo-image-compositor.c
diff options
context:
space:
mode:
Diffstat (limited to 'libs/cairo-1.16.0/src/cairo-image-compositor.c')
-rw-r--r--libs/cairo-1.16.0/src/cairo-image-compositor.c3163
1 files changed, 0 insertions, 3163 deletions
diff --git a/libs/cairo-1.16.0/src/cairo-image-compositor.c b/libs/cairo-1.16.0/src/cairo-image-compositor.c
deleted file mode 100644
index bbf4cf2..0000000
--- a/libs/cairo-1.16.0/src/cairo-image-compositor.c
+++ /dev/null
@@ -1,3163 +0,0 @@
-/* -*- 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 primarily reason for keeping a traps-compositor around is
- * for validating cairo-xlib (which currently also uses traps).
- */
-
-#include "cairoint.h"
-
-#include "cairo-image-surface-private.h"
-
-#include "cairo-compositor-private.h"
-#include "cairo-spans-compositor-private.h"
-
-#include "cairo-region-private.h"
-#include "cairo-traps-private.h"
-#include "cairo-tristrip-private.h"
-
-#include "cairo-pixman-private.h"
-
-static pixman_image_t *
-to_pixman_image (cairo_surface_t *s)
-{
- return ((cairo_image_surface_t *)s)->pixman_image;
-}
-
-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 ? &region->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_int_status_t
-draw_image_boxes (void *_dst,
- cairo_image_surface_t *image,
- cairo_boxes_t *boxes,
- int dx, int dy)
-{
- cairo_image_surface_t *dst = _dst;
- struct _cairo_boxes_chunk *chunk;
- int i;
-
- TRACE ((stderr, "%s x %d\n", __FUNCTION__, boxes->num_boxes));
-
- 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;
- if (dst->pixman_format != image->pixman_format ||
- ! pixman_blt ((uint32_t *)image->data, (uint32_t *)dst->data,
- image->stride / sizeof (uint32_t),
- dst->stride / sizeof (uint32_t),
- PIXMAN_FORMAT_BPP (image->pixman_format),
- PIXMAN_FORMAT_BPP (dst->pixman_format),
- x + dx, y + dy,
- x, y,
- w, h))
- {
- pixman_image_composite32 (PIXMAN_OP_SRC,
- image->pixman_image, NULL, dst->pixman_image,
- x + dx, y + dy,
- 0, 0,
- x, y,
- w, h);
- }
- }
- }
- 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,
- pixman_format_code_t format,
- uint32_t *pixel)
-{
- 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;
- }
-
- 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 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_bool_t
-__fill_reduces_to_source (cairo_operator_t op,
- const cairo_color_t *color,
- const cairo_image_surface_t *dst)
-{
- if (op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_CLEAR)
- return TRUE;
- if (op == CAIRO_OPERATOR_OVER && CAIRO_COLOR_IS_OPAQUE (color))
- return TRUE;
- if (dst->base.is_clear)
- return op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD;
-
- return FALSE;
-}
-
-static cairo_bool_t
-fill_reduces_to_source (cairo_operator_t op,
- const cairo_color_t *color,
- const cairo_image_surface_t *dst,
- uint32_t *pixel)
-{
- if (__fill_reduces_to_source (op, color, dst)) {
- return color_to_pixel (color, dst->pixman_format, pixel);
- }
-
- return FALSE;
-}
-
-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;
-
- TRACE ((stderr, "%s\n", __FUNCTION__));
-
- if (fill_reduces_to_source (op, color, dst, &pixel)) {
- 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);
- }
- } else {
- pixman_image_t *src = _pixman_image_for_color (color);
- if (unlikely (src == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- op = _pixman_operator (op);
- for (i = 0; i < num_rects; i++) {
- pixman_image_composite32 (op,
- src, NULL, dst->pixman_image,
- 0, 0,
- 0, 0,
- rects[i].x, rects[i].y,
- rects[i].width, rects[i].height);
- }
-
- pixman_image_unref (src);
- }
-
- 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;
-
- TRACE ((stderr, "%s x %d\n", __FUNCTION__, boxes->num_boxes));
-
- if (fill_reduces_to_source (op, color, dst, &pixel)) {
- for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
- for (i = 0; i < chunk->count; i++) {
- int x = _cairo_fixed_integer_part (chunk->base[i].p1.x);
- int y = _cairo_fixed_integer_part (chunk->base[i].p1.y);
- int w = _cairo_fixed_integer_part (chunk->base[i].p2.x) - x;
- int h = _cairo_fixed_integer_part (chunk->base[i].p2.y) - y;
- pixman_fill ((uint32_t *) dst->data,
- dst->stride / sizeof (uint32_t),
- PIXMAN_FORMAT_BPP (dst->pixman_format),
- x, y, w, h, pixel);
- }
- }
- }
- else
- {
- pixman_image_t *src = _pixman_image_for_color (color);
- if (unlikely (src == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- 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);
- pixman_image_composite32 (op,
- src, NULL, dst->pixman_image,
- 0, 0,
- 0, 0,
- x1, y1,
- x2-x1, y2-y1);
- }
- }
-
- pixman_image_unref (src);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-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_source_t *src = (cairo_image_source_t *)abstract_src;
- cairo_image_source_t *mask = (cairo_image_source_t *)abstract_mask;
-
- TRACE ((stderr, "%s\n", __FUNCTION__));
-
- if (mask) {
- pixman_image_composite32 (_pixman_operator (op),
- src->pixman_image, mask->pixman_image, to_pixman_image (_dst),
- 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, to_pixman_image (_dst),
- src_x, src_y,
- 0, 0,
- dst_x, dst_y,
- width, height);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static 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_image_surface_t *dst = _dst;
- cairo_image_source_t *src = (cairo_image_source_t *)abstract_src;
- cairo_image_source_t *mask = (cairo_image_source_t *)abstract_mask;
-
- TRACE ((stderr, "%s\n", __FUNCTION__));
-
-#if PIXMAN_HAS_OP_LERP
- pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
- src->pixman_image, mask->pixman_image, dst->pixman_image,
- src_x, src_y,
- mask_x, mask_y,
- dst_x, dst_y,
- width, height);
-#else
- /* Punch the clip out of the destination */
- TRACE ((stderr, "%s - OUT_REVERSE (mask=%d/%p, dst=%d/%p)\n",
- __FUNCTION__,
- mask->base.unique_id, mask->pixman_image,
- dst->base.unique_id, dst->pixman_image));
- pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
- mask->pixman_image, NULL, dst->pixman_image,
- mask_x, mask_y,
- 0, 0,
- dst_x, dst_y,
- width, height);
-
- /* Now add the two results together */
- TRACE ((stderr, "%s - ADD (src=%d/%p, mask=%d/%p, dst=%d/%p)\n",
- __FUNCTION__,
- src->base.unique_id, src->pixman_image,
- mask->base.unique_id, mask->pixman_image,
- dst->base.unique_id, dst->pixman_image));
- pixman_image_composite32 (PIXMAN_OP_ADD,
- src->pixman_image, mask->pixman_image, dst->pixman_image,
- src_x, src_y,
- mask_x, mask_y,
- dst_x, dst_y,
- width, height);
-#endif
-
- 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,
- const cairo_rectangle_int_t *extents)
-{
- pixman_image_t *dst = to_pixman_image (_dst);
- pixman_image_t *src = ((cairo_image_source_t *)abstract_src)->pixman_image;
- pixman_image_t *mask = abstract_mask ? ((cairo_image_source_t *)abstract_mask)->pixman_image : NULL;
- pixman_image_t *free_src = NULL;
- struct _cairo_boxes_chunk *chunk;
- int i;
-
- /* XXX consider using a region? saves multiple prepare-composite */
- TRACE ((stderr, "%s x %d\n", __FUNCTION__, boxes->num_boxes));
-
- if (((cairo_surface_t *)_dst)->is_clear &&
- (op == CAIRO_OPERATOR_SOURCE ||
- op == CAIRO_OPERATOR_OVER ||
- op == CAIRO_OPERATOR_ADD)) {
- op = PIXMAN_OP_SRC;
- } else if (mask) {
- if (op == CAIRO_OPERATOR_CLEAR) {
-#if PIXMAN_HAS_OP_LERP
- op = PIXMAN_OP_LERP_CLEAR;
-#else
- free_src = src = _pixman_image_for_color (CAIRO_COLOR_WHITE);
- if (unlikely (src == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- op = PIXMAN_OP_OUT_REVERSE;
-#endif
- } else if (op == CAIRO_OPERATOR_SOURCE) {
-#if PIXMAN_HAS_OP_LERP
- op = PIXMAN_OP_LERP_SRC;
-#else
- return CAIRO_INT_STATUS_UNSUPPORTED;
-#endif
- } else {
- op = _pixman_operator (op);
- }
- } else {
- 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);
-
- pixman_image_composite32 (op, src, mask, dst,
- x1 + src_x, y1 + src_y,
- x1 + mask_x, y1 + mask_y,
- x1 + dst_x, y1 + dst_y,
- x2 - x1, y2 - y1);
- }
- }
-
- if (free_src)
- pixman_image_unref (free_src);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-#define CAIRO_FIXED_16_16_MIN _cairo_fixed_from_int (-32768)
-#define CAIRO_FIXED_16_16_MAX _cairo_fixed_from_int (32767)
-
-static cairo_bool_t
-line_exceeds_16_16 (const cairo_line_t *line)
-{
- return
- line->p1.x <= CAIRO_FIXED_16_16_MIN ||
- line->p1.x >= CAIRO_FIXED_16_16_MAX ||
-
- line->p2.x <= CAIRO_FIXED_16_16_MIN ||
- line->p2.x >= CAIRO_FIXED_16_16_MAX ||
-
- line->p1.y <= CAIRO_FIXED_16_16_MIN ||
- line->p1.y >= CAIRO_FIXED_16_16_MAX ||
-
- line->p2.y <= CAIRO_FIXED_16_16_MIN ||
- line->p2.y >= CAIRO_FIXED_16_16_MAX;
-}
-
-static void
-project_line_x_onto_16_16 (const cairo_line_t *line,
- cairo_fixed_t top,
- cairo_fixed_t bottom,
- pixman_line_fixed_t *out)
-{
- /* XXX use fixed-point arithmetic? */
- cairo_point_double_t p1, p2;
- double m;
-
- p1.x = _cairo_fixed_to_double (line->p1.x);
- p1.y = _cairo_fixed_to_double (line->p1.y);
-
- p2.x = _cairo_fixed_to_double (line->p2.x);
- p2.y = _cairo_fixed_to_double (line->p2.y);
-
- m = (p2.x - p1.x) / (p2.y - p1.y);
- out->p1.x = _cairo_fixed_16_16_from_double (p1.x + m * _cairo_fixed_to_double (top - line->p1.y));
- out->p2.x = _cairo_fixed_16_16_from_double (p1.x + m * _cairo_fixed_to_double (bottom - line->p1.y));
-}
-
-void
-_pixman_image_add_traps (pixman_image_t *image,
- int dst_x, int dst_y,
- cairo_traps_t *traps)
-{
- cairo_trapezoid_t *t = traps->traps;
- int num_traps = traps->num_traps;
- while (num_traps--) {
- pixman_trapezoid_t trap;
-
- /* top/bottom will be clamped to surface bounds */
- trap.top = _cairo_fixed_to_16_16 (t->top);
- trap.bottom = _cairo_fixed_to_16_16 (t->bottom);
-
- /* However, all the other coordinates will have been left untouched so
- * as not to introduce numerical error. Recompute them if they
- * exceed the 16.16 limits.
- */
- if (unlikely (line_exceeds_16_16 (&t->left))) {
- project_line_x_onto_16_16 (&t->left, t->top, t->bottom, &trap.left);
- trap.left.p1.y = trap.top;
- trap.left.p2.y = trap.bottom;
- } else {
- trap.left.p1.x = _cairo_fixed_to_16_16 (t->left.p1.x);
- trap.left.p1.y = _cairo_fixed_to_16_16 (t->left.p1.y);
- trap.left.p2.x = _cairo_fixed_to_16_16 (t->left.p2.x);
- trap.left.p2.y = _cairo_fixed_to_16_16 (t->left.p2.y);
- }
-
- if (unlikely (line_exceeds_16_16 (&t->right))) {
- project_line_x_onto_16_16 (&t->right, t->top, t->bottom, &trap.right);
- trap.right.p1.y = trap.top;
- trap.right.p2.y = trap.bottom;
- } else {
- trap.right.p1.x = _cairo_fixed_to_16_16 (t->right.p1.x);
- trap.right.p1.y = _cairo_fixed_to_16_16 (t->right.p1.y);
- trap.right.p2.x = _cairo_fixed_to_16_16 (t->right.p2.x);
- trap.right.p2.y = _cairo_fixed_to_16_16 (t->right.p2.y);
- }
-
- pixman_rasterize_trapezoid (image, &trap, -dst_x, -dst_y);
- t++;
- }
-}
-
-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_image_surface_t *dst = (cairo_image_surface_t *) _dst;
- cairo_image_source_t *src = (cairo_image_source_t *) abstract_src;
- cairo_int_status_t status;
- pixman_image_t *mask;
- pixman_format_code_t format;
-
- TRACE ((stderr, "%s\n", __FUNCTION__));
-
- /* pixman doesn't eliminate self-intersecting trapezoids/edges */
- status = _cairo_bentley_ottmann_tessellate_traps (traps,
- CAIRO_FILL_RULE_WINDING);
- if (status != CAIRO_INT_STATUS_SUCCESS)
- return status;
-
- /* Special case adding trapezoids onto a mask surface; we want to avoid
- * creating an intermediate temporary mask unnecessarily.
- *
- * We make the assumption here that the portion of the trapezoids
- * contained within the surface is bounded by [dst_x,dst_y,width,height];
- * the Cairo core code passes bounds based on the trapezoid extents.
- */
- format = antialias == CAIRO_ANTIALIAS_NONE ? PIXMAN_a1 : PIXMAN_a8;
- if (dst->pixman_format == format &&
- (abstract_src == NULL ||
- (op == CAIRO_OPERATOR_ADD && src->is_opaque_solid)))
- {
- _pixman_image_add_traps (dst->pixman_image, dst_x, dst_y, traps);
- return CAIRO_STATUS_SUCCESS;
- }
-
- mask = pixman_image_create_bits (format,
- extents->width, extents->height,
- NULL, 0);
- if (unlikely (mask == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- _pixman_image_add_traps (mask, extents->x, extents->y, traps);
- pixman_image_composite32 (_pixman_operator (op),
- src->pixman_image, mask, dst->pixman_image,
- extents->x + src_x, extents->y + src_y,
- 0, 0,
- extents->x - dst_x, extents->y - dst_y,
- extents->width, extents->height);
-
- pixman_image_unref (mask);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,22,0)
-static void
-set_point (pixman_point_fixed_t *p, cairo_point_t *c)
-{
- p->x = _cairo_fixed_to_16_16 (c->x);
- p->y = _cairo_fixed_to_16_16 (c->y);
-}
-
-void
-_pixman_image_add_tristrip (pixman_image_t *image,
- int dst_x, int dst_y,
- cairo_tristrip_t *strip)
-{
- pixman_triangle_t tri;
- pixman_point_fixed_t *p[3] = {&tri.p1, &tri.p2, &tri.p3 };
- int n;
-
- set_point (p[0], &strip->points[0]);
- set_point (p[1], &strip->points[1]);
- set_point (p[2], &strip->points[2]);
- pixman_add_triangles (image, -dst_x, -dst_y, 1, &tri);
- for (n = 3; n < strip->num_points; n++) {
- set_point (p[n%3], &strip->points[n]);
- pixman_add_triangles (image, -dst_x, -dst_y, 1, &tri);
- }
-}
-
-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_image_surface_t *dst = (cairo_image_surface_t *) _dst;
- cairo_image_source_t *src = (cairo_image_source_t *) abstract_src;
- pixman_image_t *mask;
- pixman_format_code_t format;
-
- TRACE ((stderr, "%s\n", __FUNCTION__));
-
- if (strip->num_points < 3)
- return CAIRO_STATUS_SUCCESS;
-
- if (1) { /* pixman doesn't eliminate self-intersecting triangles/edges */
- cairo_int_status_t status;
- cairo_traps_t traps;
- int n;
-
- _cairo_traps_init (&traps);
- for (n = 0; n < strip->num_points; n++) {
- cairo_point_t p[4];
-
- p[0] = strip->points[0];
- p[1] = strip->points[1];
- p[2] = strip->points[2];
- p[3] = strip->points[0];
-
- _cairo_traps_tessellate_convex_quad (&traps, p);
- }
- status = composite_traps (_dst, op, abstract_src,
- src_x, src_y,
- dst_x, dst_y,
- extents, antialias, &traps);
- _cairo_traps_fini (&traps);
-
- return status;
- }
-
- format = antialias == CAIRO_ANTIALIAS_NONE ? PIXMAN_a1 : PIXMAN_a8;
- if (dst->pixman_format == format &&
- (abstract_src == NULL ||
- (op == CAIRO_OPERATOR_ADD && src->is_opaque_solid)))
- {
- _pixman_image_add_tristrip (dst->pixman_image, dst_x, dst_y, strip);
- return CAIRO_STATUS_SUCCESS;
- }
-
- mask = pixman_image_create_bits (format,
- extents->width, extents->height,
- NULL, 0);
- if (unlikely (mask == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- _pixman_image_add_tristrip (mask, extents->x, extents->y, strip);
- pixman_image_composite32 (_pixman_operator (op),
- src->pixman_image, mask, dst->pixman_image,
- extents->x + src_x, extents->y + src_y,
- 0, 0,
- extents->x - dst_x, extents->y - dst_y,
- extents->width, extents->height);
-
- pixman_image_unref (mask);
-
- return CAIRO_STATUS_SUCCESS;
-}
-#endif
-
-static 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)
-{
- return CAIRO_STATUS_SUCCESS;
-}
-
-#if HAS_PIXMAN_GLYPHS
-static pixman_glyph_cache_t *global_glyph_cache;
-
-static inline pixman_glyph_cache_t *
-get_glyph_cache (void)
-{
- if (!global_glyph_cache)
- global_glyph_cache = pixman_glyph_cache_create ();
-
- return global_glyph_cache;
-}
-
-void
-_cairo_image_compositor_reset_static_data (void)
-{
- CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex);
-
- if (global_glyph_cache)
- pixman_glyph_cache_destroy (global_glyph_cache);
- global_glyph_cache = NULL;
-
- CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex);
-}
-
-void
-_cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
- cairo_scaled_glyph_t *scaled_glyph)
-{
- CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex);
-
- if (global_glyph_cache) {
- pixman_glyph_cache_remove (
- global_glyph_cache, scaled_font,
- (void *)_cairo_scaled_glyph_index (scaled_glyph));
- }
-
- CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex);
-}
-
-static cairo_int_status_t
-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_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
- pixman_glyph_cache_t *glyph_cache;
- pixman_glyph_t pglyphs_stack[CAIRO_STACK_ARRAY_LENGTH (pixman_glyph_t)];
- pixman_glyph_t *pglyphs = pglyphs_stack;
- pixman_glyph_t *pg;
- int i;
-
- TRACE ((stderr, "%s\n", __FUNCTION__));
-
- CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex);
-
- glyph_cache = get_glyph_cache();
- if (unlikely (glyph_cache == NULL)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto out_unlock;
- }
-
- pixman_glyph_cache_freeze (glyph_cache);
-
- if (info->num_glyphs > ARRAY_LENGTH (pglyphs_stack)) {
- pglyphs = _cairo_malloc_ab (info->num_glyphs, sizeof (pixman_glyph_t));
- if (unlikely (pglyphs == NULL)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto out_thaw;
- }
- }
-
- pg = pglyphs;
- for (i = 0; i < info->num_glyphs; i++) {
- unsigned long index = info->glyphs[i].index;
- const void *glyph;
-
- glyph = pixman_glyph_cache_lookup (glyph_cache, info->font, (void *)index);
- if (!glyph) {
- cairo_scaled_glyph_t *scaled_glyph;
- cairo_image_surface_t *glyph_surface;
-
- /* This call can actually end up recursing, so we have to
- * drop the mutex around it.
- */
- CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex);
- status = _cairo_scaled_glyph_lookup (info->font, index,
- CAIRO_SCALED_GLYPH_INFO_SURFACE,
- &scaled_glyph);
- CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex);
-
- if (unlikely (status))
- goto out_thaw;
-
- glyph_surface = scaled_glyph->surface;
- glyph = pixman_glyph_cache_insert (glyph_cache, info->font, (void *)index,
- glyph_surface->base.device_transform.x0,
- glyph_surface->base.device_transform.y0,
- glyph_surface->pixman_image);
- if (unlikely (!glyph)) {
- status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
- goto out_thaw;
- }
- }
-
- pg->x = _cairo_lround (info->glyphs[i].x);
- pg->y = _cairo_lround (info->glyphs[i].y);
- pg->glyph = glyph;
- pg++;
- }
-
- if (info->use_mask) {
- pixman_format_code_t mask_format;
-
- mask_format = pixman_glyph_get_mask_format (glyph_cache, pg - pglyphs, pglyphs);
-
- pixman_composite_glyphs (_pixman_operator (op),
- ((cairo_image_source_t *)_src)->pixman_image,
- to_pixman_image (_dst),
- mask_format,
- info->extents.x + src_x, info->extents.y + src_y,
- info->extents.x, info->extents.y,
- info->extents.x - dst_x, info->extents.y - dst_y,
- info->extents.width, info->extents.height,
- glyph_cache, pg - pglyphs, pglyphs);
- } else {
- pixman_composite_glyphs_no_mask (_pixman_operator (op),
- ((cairo_image_source_t *)_src)->pixman_image,
- to_pixman_image (_dst),
- src_x, src_y,
- - dst_x, - dst_y,
- glyph_cache, pg - pglyphs, pglyphs);
- }
-
-out_thaw:
- pixman_glyph_cache_thaw (glyph_cache);
-
- if (pglyphs != pglyphs_stack)
- free(pglyphs);
-
-out_unlock:
- CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex);
- return status;
-}
-#else
-void
-_cairo_image_compositor_reset_static_data (void)
-{
-}
-
-void
-_cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
- cairo_scaled_glyph_t *scaled_glyph)
-{
-}
-
-static cairo_int_status_t
-composite_one_glyph (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_image_surface_t *glyph_surface;
- cairo_scaled_glyph_t *scaled_glyph;
- cairo_status_t status;
- int x, y;
-
- TRACE ((stderr, "%s\n", __FUNCTION__));
-
- status = _cairo_scaled_glyph_lookup (info->font,
- info->glyphs[0].index,
- CAIRO_SCALED_GLYPH_INFO_SURFACE,
- &scaled_glyph);
-
- if (unlikely (status))
- return status;
-
- glyph_surface = scaled_glyph->surface;
- if (glyph_surface->width == 0 || glyph_surface->height == 0)
- return CAIRO_INT_STATUS_NOTHING_TO_DO;
-
- /* round glyph locations to the nearest pixel */
- /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
- x = _cairo_lround (info->glyphs[0].x -
- glyph_surface->base.device_transform.x0);
- y = _cairo_lround (info->glyphs[0].y -
- glyph_surface->base.device_transform.y0);
-
- pixman_image_composite32 (_pixman_operator (op),
- ((cairo_image_source_t *)_src)->pixman_image,
- glyph_surface->pixman_image,
- to_pixman_image (_dst),
- x + src_x, y + src_y,
- 0, 0,
- x - dst_x, y - dst_y,
- glyph_surface->width,
- glyph_surface->height);
-
- return CAIRO_INT_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-composite_glyphs_via_mask (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_scaled_glyph_t *glyph_cache[64];
- pixman_image_t *white = _pixman_image_for_color (CAIRO_COLOR_WHITE);
- cairo_scaled_glyph_t *scaled_glyph;
- uint8_t buf[2048];
- pixman_image_t *mask;
- pixman_format_code_t format;
- cairo_status_t status;
- int i;
-
- TRACE ((stderr, "%s\n", __FUNCTION__));
-
- if (unlikely (white == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- /* XXX convert the glyphs to common formats a8/a8r8g8b8 to hit
- * optimised paths through pixman. Should we increase the bit
- * depth of the target surface, we should reconsider the appropriate
- * mask formats.
- */
-
- status = _cairo_scaled_glyph_lookup (info->font,
- info->glyphs[0].index,
- CAIRO_SCALED_GLYPH_INFO_SURFACE,
- &scaled_glyph);
- if (unlikely (status)) {
- pixman_image_unref (white);
- return status;
- }
-
- memset (glyph_cache, 0, sizeof (glyph_cache));
- glyph_cache[info->glyphs[0].index % ARRAY_LENGTH (glyph_cache)] = scaled_glyph;
-
- format = PIXMAN_a8;
- i = (info->extents.width + 3) & ~3;
- if (scaled_glyph->surface->base.content & CAIRO_CONTENT_COLOR) {
- format = PIXMAN_a8r8g8b8;
- i = info->extents.width * 4;
- }
-
- if (i * info->extents.height > (int) sizeof (buf)) {
- mask = pixman_image_create_bits (format,
- info->extents.width,
- info->extents.height,
- NULL, 0);
- } else {
- memset (buf, 0, i * info->extents.height);
- mask = pixman_image_create_bits (format,
- info->extents.width,
- info->extents.height,
- (uint32_t *)buf, i);
- }
- if (unlikely (mask == NULL)) {
- pixman_image_unref (white);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
-
- status = CAIRO_STATUS_SUCCESS;
- for (i = 0; i < info->num_glyphs; i++) {
- unsigned long glyph_index = info->glyphs[i].index;
- int cache_index = glyph_index % ARRAY_LENGTH (glyph_cache);
- cairo_image_surface_t *glyph_surface;
- int x, y;
-
- scaled_glyph = glyph_cache[cache_index];
- if (scaled_glyph == NULL ||
- _cairo_scaled_glyph_index (scaled_glyph) != glyph_index)
- {
- status = _cairo_scaled_glyph_lookup (info->font, glyph_index,
- CAIRO_SCALED_GLYPH_INFO_SURFACE,
- &scaled_glyph);
-
- if (unlikely (status)) {
- pixman_image_unref (mask);
- pixman_image_unref (white);
- return status;
- }
-
- glyph_cache[cache_index] = scaled_glyph;
- }
-
- glyph_surface = scaled_glyph->surface;
- if (glyph_surface->width && glyph_surface->height) {
- if (glyph_surface->base.content & CAIRO_CONTENT_COLOR &&
- format == PIXMAN_a8) {
- pixman_image_t *ca_mask;
-
- format = PIXMAN_a8r8g8b8;
- ca_mask = pixman_image_create_bits (format,
- info->extents.width,
- info->extents.height,
- NULL, 0);
- if (unlikely (ca_mask == NULL)) {
- pixman_image_unref (mask);
- pixman_image_unref (white);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
-
- pixman_image_composite32 (PIXMAN_OP_SRC,
- white, mask, ca_mask,
- 0, 0,
- 0, 0,
- 0, 0,
- info->extents.width,
- info->extents.height);
- pixman_image_unref (mask);
- mask = ca_mask;
- }
-
- /* round glyph locations to the nearest pixel */
- /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
- x = _cairo_lround (info->glyphs[i].x -
- glyph_surface->base.device_transform.x0);
- y = _cairo_lround (info->glyphs[i].y -
- glyph_surface->base.device_transform.y0);
-
- if (glyph_surface->pixman_format == format) {
- pixman_image_composite32 (PIXMAN_OP_ADD,
- glyph_surface->pixman_image, NULL, mask,
- 0, 0,
- 0, 0,
- x - info->extents.x, y - info->extents.y,
- glyph_surface->width,
- glyph_surface->height);
- } else {
- pixman_image_composite32 (PIXMAN_OP_ADD,
- white, glyph_surface->pixman_image, mask,
- 0, 0,
- 0, 0,
- x - info->extents.x, y - info->extents.y,
- glyph_surface->width,
- glyph_surface->height);
- }
- }
- }
-
- if (format == PIXMAN_a8r8g8b8)
- pixman_image_set_component_alpha (mask, TRUE);
-
- pixman_image_composite32 (_pixman_operator (op),
- ((cairo_image_source_t *)_src)->pixman_image,
- mask,
- to_pixman_image (_dst),
- info->extents.x + src_x, info->extents.y + src_y,
- 0, 0,
- info->extents.x - dst_x, info->extents.y - dst_y,
- info->extents.width, info->extents.height);
- pixman_image_unref (mask);
- pixman_image_unref (white);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-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_scaled_glyph_t *glyph_cache[64];
- pixman_image_t *dst, *src;
- cairo_status_t status;
- int i;
-
- TRACE ((stderr, "%s\n", __FUNCTION__));
-
- if (info->num_glyphs == 1)
- return composite_one_glyph(_dst, op, _src, src_x, src_y, dst_x, dst_y, info);
-
- if (info->use_mask)
- return composite_glyphs_via_mask(_dst, op, _src, src_x, src_y, dst_x, dst_y, info);
-
- op = _pixman_operator (op);
- dst = to_pixman_image (_dst);
- src = ((cairo_image_source_t *)_src)->pixman_image;
-
- memset (glyph_cache, 0, sizeof (glyph_cache));
- status = CAIRO_STATUS_SUCCESS;
-
- for (i = 0; i < info->num_glyphs; i++) {
- int x, y;
- cairo_image_surface_t *glyph_surface;
- cairo_scaled_glyph_t *scaled_glyph;
- unsigned long glyph_index = info->glyphs[i].index;
- int cache_index = glyph_index % ARRAY_LENGTH (glyph_cache);
-
- scaled_glyph = glyph_cache[cache_index];
- if (scaled_glyph == NULL ||
- _cairo_scaled_glyph_index (scaled_glyph) != glyph_index)
- {
- status = _cairo_scaled_glyph_lookup (info->font, glyph_index,
- CAIRO_SCALED_GLYPH_INFO_SURFACE,
- &scaled_glyph);
-
- if (unlikely (status))
- break;
-
- glyph_cache[cache_index] = scaled_glyph;
- }
-
- glyph_surface = scaled_glyph->surface;
- if (glyph_surface->width && glyph_surface->height) {
- /* round glyph locations to the nearest pixel */
- /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
- x = _cairo_lround (info->glyphs[i].x -
- glyph_surface->base.device_transform.x0);
- y = _cairo_lround (info->glyphs[i].y -
- glyph_surface->base.device_transform.y0);
-
- pixman_image_composite32 (op, src, glyph_surface->pixman_image, dst,
- x + src_x, y + src_y,
- 0, 0,
- x - dst_x, y - dst_y,
- glyph_surface->width,
- glyph_surface->height);
- }
- }
-
- return status;
-}
-#endif
-
-static cairo_int_status_t
-check_composite (const cairo_composite_rectangles_t *extents)
-{
- return CAIRO_STATUS_SUCCESS;
-}
-
-const cairo_compositor_t *
-_cairo_image_traps_compositor_get (void)
-{
- static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT;
- static cairo_traps_compositor_t compositor;
-
- if (_cairo_atomic_init_once_enter(&once)) {
- _cairo_traps_compositor_init(&compositor,
- &__cairo_no_compositor);
- compositor.acquire = acquire;
- compositor.release = release;
- compositor.set_clip_region = set_clip_region;
- compositor.pattern_to_surface = _cairo_image_source_create_for_pattern;
- 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;
-#if PIXMAN_VERSION >= PIXMAN_VERSION_ENCODE(0,22,0)
- compositor.composite_tristrip = composite_tristrip;
-#endif
- compositor.check_composite_glyphs = check_composite_glyphs;
- compositor.composite_glyphs = composite_glyphs;
-
- _cairo_atomic_init_once_leave(&once);
- }
-
- return &compositor.base;
-}
-
-const cairo_compositor_t *
-_cairo_image_mask_compositor_get (void)
-{
- static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT;
- static cairo_mask_compositor_t compositor;
-
- if (_cairo_atomic_init_once_enter(&once)) {
- _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_image_source_create_for_pattern;
- compositor.draw_image_boxes = draw_image_boxes;
- compositor.fill_rectangles = fill_rectangles;
- 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_glyphs = check_composite_glyphs;
- compositor.composite_glyphs = composite_glyphs;
-
- _cairo_atomic_init_once_leave(&once);
- }
-
- return &compositor.base;
-}
-
-#if PIXMAN_HAS_COMPOSITOR
-typedef struct _cairo_image_span_renderer {
- cairo_span_renderer_t base;
-
- pixman_image_compositor_t *compositor;
- pixman_image_t *src, *mask;
- float opacity;
- cairo_rectangle_int_t extents;
-} cairo_image_span_renderer_t;
-COMPILE_TIME_ASSERT (sizeof (cairo_image_span_renderer_t) <= sizeof (cairo_abstract_span_renderer_t));
-
-static cairo_status_t
-_cairo_image_bounded_opaque_spans (void *abstract_renderer,
- int y, int height,
- const cairo_half_open_span_t *spans,
- unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- do {
- if (spans[0].coverage)
- pixman_image_compositor_blt (r->compositor,
- spans[0].x, y,
- spans[1].x - spans[0].x, height,
- spans[0].coverage);
- spans++;
- } while (--num_spans > 1);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_image_bounded_spans (void *abstract_renderer,
- int y, int height,
- const cairo_half_open_span_t *spans,
- unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- do {
- if (spans[0].coverage) {
- pixman_image_compositor_blt (r->compositor,
- spans[0].x, y,
- spans[1].x - spans[0].x, height,
- r->opacity * spans[0].coverage);
- }
- spans++;
- } while (--num_spans > 1);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_image_unbounded_spans (void *abstract_renderer,
- int y, int height,
- const cairo_half_open_span_t *spans,
- unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- assert (y + height <= r->extents.height);
- if (y > r->extents.y) {
- pixman_image_compositor_blt (r->compositor,
- r->extents.x, r->extents.y,
- r->extents.width, y - r->extents.y,
- 0);
- }
-
- if (num_spans == 0) {
- pixman_image_compositor_blt (r->compositor,
- r->extents.x, y,
- r->extents.width, height,
- 0);
- } else {
- if (spans[0].x != r->extents.x) {
- pixman_image_compositor_blt (r->compositor,
- r->extents.x, y,
- spans[0].x - r->extents.x,
- height,
- 0);
- }
-
- do {
- assert (spans[0].x < r->extents.x + r->extents.width);
- pixman_image_compositor_blt (r->compositor,
- spans[0].x, y,
- spans[1].x - spans[0].x, height,
- r->opacity * spans[0].coverage);
- spans++;
- } while (--num_spans > 1);
-
- if (spans[0].x != r->extents.x + r->extents.width) {
- assert (spans[0].x < r->extents.x + r->extents.width);
- pixman_image_compositor_blt (r->compositor,
- spans[0].x, y,
- r->extents.x + r->extents.width - spans[0].x, height,
- 0);
- }
- }
-
- r->extents.y = y + height;
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_image_clipped_spans (void *abstract_renderer,
- int y, int height,
- const cairo_half_open_span_t *spans,
- unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- assert (num_spans);
-
- do {
- if (! spans[0].inverse)
- pixman_image_compositor_blt (r->compositor,
- spans[0].x, y,
- spans[1].x - spans[0].x, height,
- r->opacity * spans[0].coverage);
- spans++;
- } while (--num_spans > 1);
-
- r->extents.y = y + height;
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_image_finish_unbounded_spans (void *abstract_renderer)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- if (r->extents.y < r->extents.height) {
- pixman_image_compositor_blt (r->compositor,
- r->extents.x, r->extents.y,
- r->extents.width,
- r->extents.height - r->extents.y,
- 0);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-span_renderer_init (cairo_abstract_span_renderer_t *_r,
- const cairo_composite_rectangles_t *composite,
- cairo_bool_t needs_clip)
-{
- cairo_image_span_renderer_t *r = (cairo_image_span_renderer_t *)_r;
- cairo_image_surface_t *dst = (cairo_image_surface_t *)composite->surface;
- const cairo_pattern_t *source = &composite->source_pattern.base;
- cairo_operator_t op = composite->op;
- int src_x, src_y;
- int mask_x, mask_y;
-
- TRACE ((stderr, "%s\n", __FUNCTION__));
-
- if (op == CAIRO_OPERATOR_CLEAR) {
- op = PIXMAN_OP_LERP_CLEAR;
- } else if (dst->base.is_clear &&
- (op == CAIRO_OPERATOR_SOURCE ||
- op == CAIRO_OPERATOR_OVER ||
- op == CAIRO_OPERATOR_ADD)) {
- op = PIXMAN_OP_SRC;
- } else if (op == CAIRO_OPERATOR_SOURCE) {
- op = PIXMAN_OP_LERP_SRC;
- } else {
- op = _pixman_operator (op);
- }
-
- r->compositor = NULL;
- r->mask = NULL;
- r->src = _pixman_image_for_pattern (dst, source, FALSE,
- &composite->unbounded,
- &composite->source_sample_area,
- &src_x, &src_y);
- if (unlikely (r->src == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- r->opacity = 1.0;
- if (composite->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID) {
- r->opacity = composite->mask_pattern.solid.color.alpha;
- } else {
- r->mask = _pixman_image_for_pattern (dst,
- &composite->mask_pattern.base,
- TRUE,
- &composite->unbounded,
- &composite->mask_sample_area,
- &mask_x, &mask_y);
- if (unlikely (r->mask == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- /* XXX Component-alpha? */
- if ((dst->base.content & CAIRO_CONTENT_COLOR) == 0 &&
- _cairo_pattern_is_opaque (source, &composite->source_sample_area))
- {
- pixman_image_unref (r->src);
- r->src = r->mask;
- src_x = mask_x;
- src_y = mask_y;
- r->mask = NULL;
- }
- }
-
- if (composite->is_bounded) {
- if (r->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 (op, r->src, r->mask, dst->pixman_image,
- composite->unbounded.x + src_x,
- composite->unbounded.y + src_y,
- composite->unbounded.x + mask_x,
- composite->unbounded.y + mask_y,
- composite->unbounded.x,
- composite->unbounded.y,
- composite->unbounded.width,
- composite->unbounded.height);
- if (unlikely (r->compositor == NULL))
- return CAIRO_INT_STATUS_NOTHING_TO_DO;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-span_renderer_fini (cairo_abstract_span_renderer_t *_r,
- cairo_int_status_t status)
-{
- cairo_image_span_renderer_t *r = (cairo_image_span_renderer_t *) _r;
-
- TRACE ((stderr, "%s\n", __FUNCTION__));
-
- if (status == CAIRO_INT_STATUS_SUCCESS && r->base.finish)
- r->base.finish (r);
-
- if (r->compositor)
- pixman_image_compositor_destroy (r->compositor);
-
- if (r->src)
- pixman_image_unref (r->src);
- if (r->mask)
- pixman_image_unref (r->mask);
-}
-#else
-typedef struct _cairo_image_span_renderer {
- cairo_span_renderer_t base;
-
- const cairo_composite_rectangles_t *composite;
-
- float opacity;
- uint8_t op;
- int bpp;
-
- pixman_image_t *src, *mask;
- union {
- struct fill {
- ptrdiff_t stride;
- uint8_t *data;
- uint32_t pixel;
- } fill;
- struct blit {
- int stride;
- uint8_t *data;
- int src_stride;
- uint8_t *src_data;
- } blit;
- struct composite {
- pixman_image_t *dst;
- int src_x, src_y;
- int mask_x, mask_y;
- int run_length;
- } composite;
- struct finish {
- cairo_rectangle_int_t extents;
- int src_x, src_y;
- ptrdiff_t stride;
- uint8_t *data;
- } mask;
- } u;
- uint8_t _buf[0];
-#define SZ_BUF (int)(sizeof (cairo_abstract_span_renderer_t) - sizeof (cairo_image_span_renderer_t))
-} cairo_image_span_renderer_t;
-COMPILE_TIME_ASSERT (sizeof (cairo_image_span_renderer_t) <= sizeof (cairo_abstract_span_renderer_t));
-
-static cairo_status_t
-_cairo_image_spans (void *abstract_renderer,
- int y, int height,
- const cairo_half_open_span_t *spans,
- unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
- uint8_t *mask, *row;
- int len;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- mask = r->u.mask.data + (y - r->u.mask.extents.y) * r->u.mask.stride;
- mask += spans[0].x - r->u.mask.extents.x;
- row = mask;
-
- do {
- len = spans[1].x - spans[0].x;
- if (spans[0].coverage) {
- *row++ = r->opacity * spans[0].coverage;
- if (--len)
- memset (row, row[-1], len);
- }
- row += len;
- spans++;
- } while (--num_spans > 1);
-
- len = row - mask;
- row = mask;
- while (--height) {
- mask += r->u.mask.stride;
- memcpy (mask, row, len);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_image_spans_and_zero (void *abstract_renderer,
- int y, int height,
- const cairo_half_open_span_t *spans,
- unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
- uint8_t *mask;
- int len;
-
- mask = r->u.mask.data;
- if (y > r->u.mask.extents.y) {
- len = (y - r->u.mask.extents.y) * r->u.mask.stride;
- memset (mask, 0, len);
- mask += len;
- }
-
- r->u.mask.extents.y = y + height;
- r->u.mask.data = mask + height * r->u.mask.stride;
- if (num_spans == 0) {
- memset (mask, 0, height * r->u.mask.stride);
- } else {
- uint8_t *row = mask;
-
- if (spans[0].x != r->u.mask.extents.x) {
- len = spans[0].x - r->u.mask.extents.x;
- memset (row, 0, len);
- row += len;
- }
-
- do {
- len = spans[1].x - spans[0].x;
- *row++ = r->opacity * spans[0].coverage;
- if (len > 1) {
- memset (row, row[-1], --len);
- row += len;
- }
- spans++;
- } while (--num_spans > 1);
-
- if (spans[0].x != r->u.mask.extents.x + r->u.mask.extents.width) {
- len = r->u.mask.extents.x + r->u.mask.extents.width - spans[0].x;
- memset (row, 0, len);
- }
-
- row = mask;
- while (--height) {
- mask += r->u.mask.stride;
- memcpy (mask, row, r->u.mask.extents.width);
- }
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_image_finish_spans_and_zero (void *abstract_renderer)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- if (r->u.mask.extents.y < r->u.mask.extents.height)
- memset (r->u.mask.data, 0, (r->u.mask.extents.height - r->u.mask.extents.y) * r->u.mask.stride);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_fill8_spans (void *abstract_renderer, int y, int h,
- const cairo_half_open_span_t *spans, unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- if (likely(h == 1)) {
- do {
- if (spans[0].coverage) {
- int len = spans[1].x - spans[0].x;
- uint8_t *d = r->u.fill.data + r->u.fill.stride*y + spans[0].x;
- if (len == 1)
- *d = r->u.fill.pixel;
- else
- memset(d, r->u.fill.pixel, len);
- }
- spans++;
- } while (--num_spans > 1);
- } else {
- do {
- if (spans[0].coverage) {
- int yy = y, hh = h;
- do {
- int len = spans[1].x - spans[0].x;
- uint8_t *d = r->u.fill.data + r->u.fill.stride*yy + spans[0].x;
- if (len == 1)
- *d = r->u.fill.pixel;
- else
- memset(d, r->u.fill.pixel, len);
- yy++;
- } while (--hh);
- }
- spans++;
- } while (--num_spans > 1);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_fill16_spans (void *abstract_renderer, int y, int h,
- const cairo_half_open_span_t *spans, unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- if (likely(h == 1)) {
- do {
- if (spans[0].coverage) {
- int len = spans[1].x - spans[0].x;
- uint16_t *d = (uint16_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*2);
- while (len-- > 0)
- *d++ = r->u.fill.pixel;
- }
- spans++;
- } while (--num_spans > 1);
- } else {
- do {
- if (spans[0].coverage) {
- int yy = y, hh = h;
- do {
- int len = spans[1].x - spans[0].x;
- uint16_t *d = (uint16_t*)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*2);
- while (len-- > 0)
- *d++ = r->u.fill.pixel;
- yy++;
- } while (--hh);
- }
- spans++;
- } while (--num_spans > 1);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_fill32_spans (void *abstract_renderer, int y, int h,
- const cairo_half_open_span_t *spans, unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- if (likely(h == 1)) {
- do {
- if (spans[0].coverage) {
- int len = spans[1].x - spans[0].x;
- if (len > 32) {
- pixman_fill ((uint32_t *)r->u.fill.data, r->u.fill.stride / sizeof(uint32_t), r->bpp,
- spans[0].x, y, len, 1, r->u.fill.pixel);
- } else {
- uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*4);
- while (len-- > 0)
- *d++ = r->u.fill.pixel;
- }
- }
- spans++;
- } while (--num_spans > 1);
- } else {
- do {
- if (spans[0].coverage) {
- if (spans[1].x - spans[0].x > 16) {
- pixman_fill ((uint32_t *)r->u.fill.data, r->u.fill.stride / sizeof(uint32_t), r->bpp,
- spans[0].x, y, spans[1].x - spans[0].x, h,
- r->u.fill.pixel);
- } else {
- int yy = y, hh = h;
- do {
- int len = spans[1].x - spans[0].x;
- uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*4);
- while (len-- > 0)
- *d++ = r->u.fill.pixel;
- yy++;
- } while (--hh);
- }
- }
- spans++;
- } while (--num_spans > 1);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-#if 0
-static cairo_status_t
-_fill_spans (void *abstract_renderer, int y, int h,
- const cairo_half_open_span_t *spans, unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- do {
- if (spans[0].coverage) {
- pixman_fill ((uint32_t *) r->data, r->stride, r->bpp,
- spans[0].x, y,
- spans[1].x - spans[0].x, h,
- r->pixel);
- }
- spans++;
- } while (--num_spans > 1);
-
- return CAIRO_STATUS_SUCCESS;
-}
-#endif
-
-static cairo_status_t
-_blit_spans (void *abstract_renderer, int y, int h,
- const cairo_half_open_span_t *spans, unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
- int cpp;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- cpp = r->bpp/8;
- if (likely (h == 1)) {
- uint8_t *src = r->u.blit.src_data + y*r->u.blit.src_stride;
- uint8_t *dst = r->u.blit.data + y*r->u.blit.stride;
- do {
- if (spans[0].coverage) {
- void *s = src + spans[0].x*cpp;
- void *d = dst + spans[0].x*cpp;
- int len = (spans[1].x - spans[0].x) * cpp;
- switch (len) {
- case 1:
- *(uint8_t *)d = *(uint8_t *)s;
- break;
- case 2:
- *(uint16_t *)d = *(uint16_t *)s;
- break;
- case 4:
- *(uint32_t *)d = *(uint32_t *)s;
- break;
-#if HAVE_UINT64_T
- case 8:
- *(uint64_t *)d = *(uint64_t *)s;
- break;
-#endif
- default:
- memcpy(d, s, len);
- break;
- }
- }
- spans++;
- } while (--num_spans > 1);
- } else {
- do {
- if (spans[0].coverage) {
- int yy = y, hh = h;
- do {
- void *src = r->u.blit.src_data + yy*r->u.blit.src_stride + spans[0].x*cpp;
- void *dst = r->u.blit.data + yy*r->u.blit.stride + spans[0].x*cpp;
- int len = (spans[1].x - spans[0].x) * cpp;
- switch (len) {
- case 1:
- *(uint8_t *)dst = *(uint8_t *)src;
- break;
- case 2:
- *(uint16_t *)dst = *(uint16_t *)src;
- break;
- case 4:
- *(uint32_t *)dst = *(uint32_t *)src;
- break;
-#if HAVE_UINT64_T
- case 8:
- *(uint64_t *)dst = *(uint64_t *)src;
- break;
-#endif
- default:
- memcpy(dst, src, len);
- break;
- }
- yy++;
- } while (--hh);
- }
- spans++;
- } while (--num_spans > 1);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_mono_spans (void *abstract_renderer, int y, int h,
- const cairo_half_open_span_t *spans, unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- do {
- if (spans[0].coverage) {
- pixman_image_composite32 (r->op,
- r->src, NULL, r->u.composite.dst,
- spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
- 0, 0,
- spans[0].x, y,
- spans[1].x - spans[0].x, h);
- }
- spans++;
- } while (--num_spans > 1);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_mono_unbounded_spans (void *abstract_renderer, int y, int h,
- const cairo_half_open_span_t *spans, unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- if (num_spans == 0) {
- pixman_image_composite32 (PIXMAN_OP_CLEAR,
- r->src, NULL, r->u.composite.dst,
- spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
- 0, 0,
- r->composite->unbounded.x, y,
- r->composite->unbounded.width, h);
- r->u.composite.mask_y = y + h;
- return CAIRO_STATUS_SUCCESS;
- }
-
- if (y != r->u.composite.mask_y) {
- pixman_image_composite32 (PIXMAN_OP_CLEAR,
- r->src, NULL, r->u.composite.dst,
- spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
- 0, 0,
- r->composite->unbounded.x, r->u.composite.mask_y,
- r->composite->unbounded.width, y - r->u.composite.mask_y);
- }
-
- if (spans[0].x != r->composite->unbounded.x) {
- pixman_image_composite32 (PIXMAN_OP_CLEAR,
- r->src, NULL, r->u.composite.dst,
- spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
- 0, 0,
- r->composite->unbounded.x, y,
- spans[0].x - r->composite->unbounded.x, h);
- }
-
- do {
- int op = spans[0].coverage ? r->op : PIXMAN_OP_CLEAR;
- pixman_image_composite32 (op,
- r->src, NULL, r->u.composite.dst,
- spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
- 0, 0,
- spans[0].x, y,
- spans[1].x - spans[0].x, h);
- spans++;
- } while (--num_spans > 1);
-
- if (spans[0].x != r->composite->unbounded.x + r->composite->unbounded.width) {
- pixman_image_composite32 (PIXMAN_OP_CLEAR,
- r->src, NULL, r->u.composite.dst,
- spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
- 0, 0,
- spans[0].x, y,
- r->composite->unbounded.x + r->composite->unbounded.width - spans[0].x, h);
- }
-
- r->u.composite.mask_y = y + h;
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_mono_finish_unbounded_spans (void *abstract_renderer)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- if (r->u.composite.mask_y < r->composite->unbounded.y + r->composite->unbounded.height) {
- pixman_image_composite32 (PIXMAN_OP_CLEAR,
- r->src, NULL, r->u.composite.dst,
- r->composite->unbounded.x + r->u.composite.src_x, r->u.composite.mask_y + r->u.composite.src_y,
- 0, 0,
- r->composite->unbounded.x, r->u.composite.mask_y,
- r->composite->unbounded.width,
- r->composite->unbounded.y + r->composite->unbounded.height - r->u.composite.mask_y);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-mono_renderer_init (cairo_image_span_renderer_t *r,
- const cairo_composite_rectangles_t *composite,
- cairo_antialias_t antialias,
- cairo_bool_t needs_clip)
-{
- cairo_image_surface_t *dst = (cairo_image_surface_t *)composite->surface;
-
- if (antialias != CAIRO_ANTIALIAS_NONE)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- if (!_cairo_pattern_is_opaque_solid (&composite->mask_pattern.base))
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- r->base.render_rows = NULL;
- if (composite->source_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID) {
- const cairo_color_t *color;
-
- color = &composite->source_pattern.solid.color;
- if (composite->op == CAIRO_OPERATOR_CLEAR)
- color = CAIRO_COLOR_TRANSPARENT;
-
- if (fill_reduces_to_source (composite->op, color, dst, &r->u.fill.pixel)) {
- /* Use plain C for the fill operations as the span length is
- * typically small, too small to payback the startup overheads of
- * using SSE2 etc.
- */
- switch (PIXMAN_FORMAT_BPP(dst->pixman_format)) {
- case 8: r->base.render_rows = _fill8_spans; break;
- case 16: r->base.render_rows = _fill16_spans; break;
- case 32: r->base.render_rows = _fill32_spans; break;
- default: break;
- }
- r->u.fill.data = dst->data;
- r->u.fill.stride = dst->stride;
- }
- } else if ((composite->op == CAIRO_OPERATOR_SOURCE ||
- (composite->op == CAIRO_OPERATOR_OVER &&
- (dst->base.is_clear || (dst->base.content & CAIRO_CONTENT_ALPHA) == 0))) &&
- composite->source_pattern.base.type == CAIRO_PATTERN_TYPE_SURFACE &&
- composite->source_pattern.surface.surface->backend->type == CAIRO_SURFACE_TYPE_IMAGE &&
- to_image_surface(composite->source_pattern.surface.surface)->format == dst->format)
- {
- cairo_image_surface_t *src =
- to_image_surface(composite->source_pattern.surface.surface);
- int tx, ty;
-
- if (_cairo_matrix_is_integer_translation(&composite->source_pattern.base.matrix,
- &tx, &ty) &&
- composite->bounded.x + tx >= 0 &&
- composite->bounded.y + ty >= 0 &&
- composite->bounded.x + composite->bounded.width + tx <= src->width &&
- composite->bounded.y + composite->bounded.height + ty <= src->height) {
-
- r->u.blit.stride = dst->stride;
- r->u.blit.data = dst->data;
- r->u.blit.src_stride = src->stride;
- r->u.blit.src_data = src->data + src->stride * ty + tx * 4;
- r->base.render_rows = _blit_spans;
- }
- }
-
- if (r->base.render_rows == NULL) {
- r->src = _pixman_image_for_pattern (dst, &composite->source_pattern.base, FALSE,
- &composite->unbounded,
- &composite->source_sample_area,
- &r->u.composite.src_x, &r->u.composite.src_y);
- if (unlikely (r->src == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- r->u.composite.dst = to_pixman_image (composite->surface);
- r->op = _pixman_operator (composite->op);
- if (composite->is_bounded == 0) {
- r->base.render_rows = _mono_unbounded_spans;
- r->base.finish = _mono_finish_unbounded_spans;
- r->u.composite.mask_y = composite->unbounded.y;
- } else
- r->base.render_rows = _mono_spans;
- }
- r->bpp = PIXMAN_FORMAT_BPP(dst->pixman_format);
-
- return CAIRO_INT_STATUS_SUCCESS;
-}
-
-#define ONE_HALF 0x7f
-#define RB_MASK 0x00ff00ff
-#define RB_ONE_HALF 0x007f007f
-#define RB_MASK_PLUS_ONE 0x01000100
-#define G_SHIFT 8
-static inline uint32_t
-mul8x2_8 (uint32_t a, uint8_t b)
-{
- uint32_t t = (a & RB_MASK) * b + RB_ONE_HALF;
- return ((t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT) & RB_MASK;
-}
-
-static inline uint32_t
-add8x2_8x2 (uint32_t a, uint32_t b)
-{
- uint32_t t = a + b;
- t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK);
- return t & RB_MASK;
-}
-
-static inline uint8_t
-mul8_8 (uint8_t a, uint8_t b)
-{
- uint16_t t = a * (uint16_t)b + ONE_HALF;
- return ((t >> G_SHIFT) + t) >> G_SHIFT;
-}
-
-static inline uint32_t
-lerp8x4 (uint32_t src, uint8_t a, uint32_t dst)
-{
- return (add8x2_8x2 (mul8x2_8 (src, a),
- mul8x2_8 (dst, ~a)) |
- add8x2_8x2 (mul8x2_8 (src >> G_SHIFT, a),
- mul8x2_8 (dst >> G_SHIFT, ~a)) << G_SHIFT);
-}
-
-static cairo_status_t
-_fill_a8_lerp_opaque_spans (void *abstract_renderer, int y, int h,
- const cairo_half_open_span_t *spans, unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- if (likely(h == 1)) {
- uint8_t *d = r->u.fill.data + r->u.fill.stride*y;
- do {
- uint8_t a = spans[0].coverage;
- if (a) {
- int len = spans[1].x - spans[0].x;
- if (a == 0xff) {
- memset(d + spans[0].x, r->u.fill.pixel, len);
- } else {
- uint8_t s = mul8_8(a, r->u.fill.pixel);
- uint8_t *dst = d + spans[0].x;
- a = ~a;
- while (len-- > 0) {
- uint8_t t = mul8_8(*dst, a);
- *dst++ = t + s;
- }
- }
- }
- spans++;
- } while (--num_spans > 1);
- } else {
- do {
- uint8_t a = spans[0].coverage;
- if (a) {
- int yy = y, hh = h;
- if (a == 0xff) {
- do {
- int len = spans[1].x - spans[0].x;
- uint8_t *d = r->u.fill.data + r->u.fill.stride*yy + spans[0].x;
- memset(d, r->u.fill.pixel, len);
- yy++;
- } while (--hh);
- } else {
- uint8_t s = mul8_8(a, r->u.fill.pixel);
- a = ~a;
- do {
- int len = spans[1].x - spans[0].x;
- uint8_t *d = r->u.fill.data + r->u.fill.stride*yy + spans[0].x;
- while (len-- > 0) {
- uint8_t t = mul8_8(*d, a);
- *d++ = t + s;
- }
- yy++;
- } while (--hh);
- }
- }
- spans++;
- } while (--num_spans > 1);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_fill_xrgb32_lerp_opaque_spans (void *abstract_renderer, int y, int h,
- const cairo_half_open_span_t *spans, unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- if (likely(h == 1)) {
- do {
- uint8_t a = spans[0].coverage;
- if (a) {
- int len = spans[1].x - spans[0].x;
- uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*4);
- if (a == 0xff) {
- if (len > 31) {
- pixman_fill ((uint32_t *)r->u.fill.data, r->u.fill.stride / sizeof(uint32_t), 32,
- spans[0].x, y, len, 1, r->u.fill.pixel);
- } else {
- uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*4);
- while (len-- > 0)
- *d++ = r->u.fill.pixel;
- }
- } else while (len-- > 0) {
- *d = lerp8x4 (r->u.fill.pixel, a, *d);
- d++;
- }
- }
- spans++;
- } while (--num_spans > 1);
- } else {
- do {
- uint8_t a = spans[0].coverage;
- if (a) {
- if (a == 0xff) {
- if (spans[1].x - spans[0].x > 16) {
- pixman_fill ((uint32_t *)r->u.fill.data, r->u.fill.stride / sizeof(uint32_t), 32,
- spans[0].x, y, spans[1].x - spans[0].x, h,
- r->u.fill.pixel);
- } else {
- int yy = y, hh = h;
- do {
- int len = spans[1].x - spans[0].x;
- uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*4);
- while (len-- > 0)
- *d++ = r->u.fill.pixel;
- yy++;
- } while (--hh);
- }
- } else {
- int yy = y, hh = h;
- do {
- int len = spans[1].x - spans[0].x;
- uint32_t *d = (uint32_t *)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*4);
- while (len-- > 0) {
- *d = lerp8x4 (r->u.fill.pixel, a, *d);
- d++;
- }
- yy++;
- } while (--hh);
- }
- }
- spans++;
- } while (--num_spans > 1);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_fill_a8_lerp_spans (void *abstract_renderer, int y, int h,
- const cairo_half_open_span_t *spans, unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- if (likely(h == 1)) {
- do {
- uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
- if (a) {
- int len = spans[1].x - spans[0].x;
- uint8_t *d = r->u.fill.data + r->u.fill.stride*y + spans[0].x;
- uint16_t p = (uint16_t)a * r->u.fill.pixel + 0x7f;
- uint16_t ia = ~a;
- while (len-- > 0) {
- uint16_t t = *d*ia + p;
- *d++ = (t + (t>>8)) >> 8;
- }
- }
- spans++;
- } while (--num_spans > 1);
- } else {
- do {
- uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
- if (a) {
- int yy = y, hh = h;
- uint16_t p = (uint16_t)a * r->u.fill.pixel + 0x7f;
- uint16_t ia = ~a;
- do {
- int len = spans[1].x - spans[0].x;
- uint8_t *d = r->u.fill.data + r->u.fill.stride*yy + spans[0].x;
- while (len-- > 0) {
- uint16_t t = *d*ia + p;
- *d++ = (t + (t>>8)) >> 8;
- }
- yy++;
- } while (--hh);
- }
- spans++;
- } while (--num_spans > 1);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_fill_xrgb32_lerp_spans (void *abstract_renderer, int y, int h,
- const cairo_half_open_span_t *spans, unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- if (likely(h == 1)) {
- do {
- uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
- if (a) {
- int len = spans[1].x - spans[0].x;
- uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*4);
- while (len-- > 0) {
- *d = lerp8x4 (r->u.fill.pixel, a, *d);
- d++;
- }
- }
- spans++;
- } while (--num_spans > 1);
- } else {
- do {
- uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
- if (a) {
- int yy = y, hh = h;
- do {
- int len = spans[1].x - spans[0].x;
- uint32_t *d = (uint32_t *)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*4);
- while (len-- > 0) {
- *d = lerp8x4 (r->u.fill.pixel, a, *d);
- d++;
- }
- yy++;
- } while (--hh);
- }
- spans++;
- } while (--num_spans > 1);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_blit_xrgb32_lerp_spans (void *abstract_renderer, int y, int h,
- const cairo_half_open_span_t *spans, unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- if (likely(h == 1)) {
- uint8_t *src = r->u.blit.src_data + y*r->u.blit.src_stride;
- uint8_t *dst = r->u.blit.data + y*r->u.blit.stride;
- do {
- uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
- if (a) {
- uint32_t *s = (uint32_t*)src + spans[0].x;
- uint32_t *d = (uint32_t*)dst + spans[0].x;
- int len = spans[1].x - spans[0].x;
- if (a == 0xff) {
- if (len == 1)
- *d = *s;
- else
- memcpy(d, s, len*4);
- } else {
- while (len-- > 0) {
- *d = lerp8x4 (*s, a, *d);
- s++, d++;
- }
- }
- }
- spans++;
- } while (--num_spans > 1);
- } else {
- do {
- uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
- if (a) {
- int yy = y, hh = h;
- do {
- uint32_t *s = (uint32_t *)(r->u.blit.src_data + yy*r->u.blit.src_stride + spans[0].x * 4);
- uint32_t *d = (uint32_t *)(r->u.blit.data + yy*r->u.blit.stride + spans[0].x * 4);
- int len = spans[1].x - spans[0].x;
- if (a == 0xff) {
- if (len == 1)
- *d = *s;
- else
- memcpy(d, s, len * 4);
- } else {
- while (len-- > 0) {
- *d = lerp8x4 (*s, a, *d);
- s++, d++;
- }
- }
- yy++;
- } while (--hh);
- }
- spans++;
- } while (--num_spans > 1);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_inplace_spans (void *abstract_renderer,
- int y, int h,
- const cairo_half_open_span_t *spans,
- unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
- uint8_t *mask;
- int x0, x1;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- if (num_spans == 2 && spans[0].coverage == 0xff) {
- pixman_image_composite32 (r->op, r->src, NULL, r->u.composite.dst,
- spans[0].x + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- spans[0].x, y,
- spans[1].x - spans[0].x, h);
- return CAIRO_STATUS_SUCCESS;
- }
-
- mask = (uint8_t *)pixman_image_get_data (r->mask);
- x1 = x0 = spans[0].x;
- do {
- int len = spans[1].x - spans[0].x;
- *mask++ = spans[0].coverage;
- if (len > 1) {
- if (len >= r->u.composite.run_length && spans[0].coverage == 0xff) {
- if (x1 != x0) {
- pixman_image_composite32 (r->op, r->src, r->mask, r->u.composite.dst,
- x0 + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- x0, y,
- x1 - x0, h);
- }
- pixman_image_composite32 (r->op, r->src, NULL, r->u.composite.dst,
- spans[0].x + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- spans[0].x, y,
- len, h);
- mask = (uint8_t *)pixman_image_get_data (r->mask);
- x0 = spans[1].x;
- } else if (spans[0].coverage == 0x0 &&
- x1 - x0 > r->u.composite.run_length) {
- pixman_image_composite32 (r->op, r->src, r->mask, r->u.composite.dst,
- x0 + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- x0, y,
- x1 - x0, h);
- mask = (uint8_t *)pixman_image_get_data (r->mask);
- x0 = spans[1].x;
- }else {
- memset (mask, spans[0].coverage, --len);
- mask += len;
- }
- }
- x1 = spans[1].x;
- spans++;
- } while (--num_spans > 1);
-
- if (x1 != x0) {
- pixman_image_composite32 (r->op, r->src, r->mask, r->u.composite.dst,
- x0 + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- x0, y,
- x1 - x0, h);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_inplace_opacity_spans (void *abstract_renderer, int y, int h,
- const cairo_half_open_span_t *spans,
- unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
- uint8_t *mask;
- int x0, x1;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- mask = (uint8_t *)pixman_image_get_data (r->mask);
- x1 = x0 = spans[0].x;
- do {
- int len = spans[1].x - spans[0].x;
- uint8_t m = mul8_8(spans[0].coverage, r->bpp);
- *mask++ = m;
- if (len > 1) {
- if (m == 0 &&
- x1 - x0 > r->u.composite.run_length) {
- pixman_image_composite32 (r->op, r->src, r->mask, r->u.composite.dst,
- x0 + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- x0, y,
- x1 - x0, h);
- mask = (uint8_t *)pixman_image_get_data (r->mask);
- x0 = spans[1].x;
- }else {
- memset (mask, m, --len);
- mask += len;
- }
- }
- x1 = spans[1].x;
- spans++;
- } while (--num_spans > 1);
-
- if (x1 != x0) {
- pixman_image_composite32 (r->op, r->src, r->mask, r->u.composite.dst,
- x0 + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- x0, y,
- x1 - x0, h);
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_inplace_src_spans (void *abstract_renderer, int y, int h,
- const cairo_half_open_span_t *spans,
- unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
- uint8_t *m;
- int x0;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- x0 = spans[0].x;
- m = r->_buf;
- do {
- int len = spans[1].x - spans[0].x;
- if (len >= r->u.composite.run_length && spans[0].coverage == 0xff) {
- if (spans[0].x != x0) {
-#if PIXMAN_HAS_OP_LERP
- pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
- r->src, r->mask, r->u.composite.dst,
- x0 + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- x0, y,
- spans[0].x - x0, h);
-#else
- pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
- r->mask, NULL, r->u.composite.dst,
- 0, 0,
- 0, 0,
- x0, y,
- spans[0].x - x0, h);
- pixman_image_composite32 (PIXMAN_OP_ADD,
- r->src, r->mask, r->u.composite.dst,
- x0 + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- x0, y,
- spans[0].x - x0, h);
-#endif
- }
-
- pixman_image_composite32 (PIXMAN_OP_SRC,
- r->src, NULL, r->u.composite.dst,
- spans[0].x + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- spans[0].x, y,
- spans[1].x - spans[0].x, h);
-
- m = r->_buf;
- x0 = spans[1].x;
- } else if (spans[0].coverage == 0x0) {
- if (spans[0].x != x0) {
-#if PIXMAN_HAS_OP_LERP
- pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
- r->src, r->mask, r->u.composite.dst,
- x0 + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- x0, y,
- spans[0].x - x0, h);
-#else
- pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
- r->mask, NULL, r->u.composite.dst,
- 0, 0,
- 0, 0,
- x0, y,
- spans[0].x - x0, h);
- pixman_image_composite32 (PIXMAN_OP_ADD,
- r->src, r->mask, r->u.composite.dst,
- x0 + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- x0, y,
- spans[0].x - x0, h);
-#endif
- }
-
- m = r->_buf;
- x0 = spans[1].x;
- } else {
- *m++ = spans[0].coverage;
- if (len > 1) {
- memset (m, spans[0].coverage, --len);
- m += len;
- }
- }
- spans++;
- } while (--num_spans > 1);
-
- if (spans[0].x != x0) {
-#if PIXMAN_HAS_OP_LERP
- pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
- r->src, r->mask, r->u.composite.dst,
- x0 + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- x0, y,
- spans[0].x - x0, h);
-#else
- pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
- r->mask, NULL, r->u.composite.dst,
- 0, 0,
- 0, 0,
- x0, y,
- spans[0].x - x0, h);
- pixman_image_composite32 (PIXMAN_OP_ADD,
- r->src, r->mask, r->u.composite.dst,
- x0 + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- x0, y,
- spans[0].x - x0, h);
-#endif
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_inplace_src_opacity_spans (void *abstract_renderer, int y, int h,
- const cairo_half_open_span_t *spans,
- unsigned num_spans)
-{
- cairo_image_span_renderer_t *r = abstract_renderer;
- uint8_t *mask;
- int x0;
-
- if (num_spans == 0)
- return CAIRO_STATUS_SUCCESS;
-
- x0 = spans[0].x;
- mask = (uint8_t *)pixman_image_get_data (r->mask);
- do {
- int len = spans[1].x - spans[0].x;
- uint8_t m = mul8_8(spans[0].coverage, r->bpp);
- if (m == 0) {
- if (spans[0].x != x0) {
-#if PIXMAN_HAS_OP_LERP
- pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
- r->src, r->mask, r->u.composite.dst,
- x0 + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- x0, y,
- spans[0].x - x0, h);
-#else
- pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
- r->mask, NULL, r->u.composite.dst,
- 0, 0,
- 0, 0,
- x0, y,
- spans[0].x - x0, h);
- pixman_image_composite32 (PIXMAN_OP_ADD,
- r->src, r->mask, r->u.composite.dst,
- x0 + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- x0, y,
- spans[0].x - x0, h);
-#endif
- }
-
- mask = (uint8_t *)pixman_image_get_data (r->mask);
- x0 = spans[1].x;
- } else {
- *mask++ = m;
- if (len > 1) {
- memset (mask, m, --len);
- mask += len;
- }
- }
- spans++;
- } while (--num_spans > 1);
-
- if (spans[0].x != x0) {
-#if PIXMAN_HAS_OP_LERP
- pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
- r->src, r->mask, r->u.composite.dst,
- x0 + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- x0, y,
- spans[0].x - x0, h);
-#else
- pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
- r->mask, NULL, r->u.composite.dst,
- 0, 0,
- 0, 0,
- x0, y,
- spans[0].x - x0, h);
- pixman_image_composite32 (PIXMAN_OP_ADD,
- r->src, r->mask, r->u.composite.dst,
- x0 + r->u.composite.src_x,
- y + r->u.composite.src_y,
- 0, 0,
- x0, y,
- spans[0].x - x0, h);
-#endif
- }
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void free_pixels (pixman_image_t *image, void *data)
-{
- free (data);
-}
-
-static cairo_int_status_t
-inplace_renderer_init (cairo_image_span_renderer_t *r,
- const cairo_composite_rectangles_t *composite,
- cairo_antialias_t antialias,
- cairo_bool_t needs_clip)
-{
- cairo_image_surface_t *dst = (cairo_image_surface_t *)composite->surface;
- uint8_t *buf;
-
- if (composite->mask_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- r->base.render_rows = NULL;
- r->bpp = composite->mask_pattern.solid.color.alpha_short >> 8;
-
- if (composite->source_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID) {
- const cairo_color_t *color;
-
- color = &composite->source_pattern.solid.color;
- if (composite->op == CAIRO_OPERATOR_CLEAR)
- color = CAIRO_COLOR_TRANSPARENT;
-
- if (fill_reduces_to_source (composite->op, color, dst, &r->u.fill.pixel)) {
- /* Use plain C for the fill operations as the span length is
- * typically small, too small to payback the startup overheads of
- * using SSE2 etc.
- */
- if (r->bpp == 0xff) {
- switch (dst->format) {
- case CAIRO_FORMAT_A8:
- r->base.render_rows = _fill_a8_lerp_opaque_spans;
- break;
- case CAIRO_FORMAT_RGB24:
- case CAIRO_FORMAT_ARGB32:
- r->base.render_rows = _fill_xrgb32_lerp_opaque_spans;
- break;
- case CAIRO_FORMAT_A1:
- case CAIRO_FORMAT_RGB16_565:
- case CAIRO_FORMAT_RGB30:
- case CAIRO_FORMAT_INVALID:
- default: break;
- }
- } else {
- switch (dst->format) {
- case CAIRO_FORMAT_A8:
- r->base.render_rows = _fill_a8_lerp_spans;
- break;
- case CAIRO_FORMAT_RGB24:
- case CAIRO_FORMAT_ARGB32:
- r->base.render_rows = _fill_xrgb32_lerp_spans;
- break;
- case CAIRO_FORMAT_A1:
- case CAIRO_FORMAT_RGB16_565:
- case CAIRO_FORMAT_RGB30:
- case CAIRO_FORMAT_INVALID:
- default: break;
- }
- }
- r->u.fill.data = dst->data;
- r->u.fill.stride = dst->stride;
- }
- } else if ((dst->format == CAIRO_FORMAT_ARGB32 || dst->format == CAIRO_FORMAT_RGB24) &&
- (composite->op == CAIRO_OPERATOR_SOURCE ||
- (composite->op == CAIRO_OPERATOR_OVER &&
- (dst->base.is_clear || (dst->base.content & CAIRO_CONTENT_ALPHA) == 0))) &&
- composite->source_pattern.base.type == CAIRO_PATTERN_TYPE_SURFACE &&
- composite->source_pattern.surface.surface->backend->type == CAIRO_SURFACE_TYPE_IMAGE &&
- to_image_surface(composite->source_pattern.surface.surface)->format == dst->format)
- {
- cairo_image_surface_t *src =
- to_image_surface(composite->source_pattern.surface.surface);
- int tx, ty;
-
- if (_cairo_matrix_is_integer_translation(&composite->source_pattern.base.matrix,
- &tx, &ty) &&
- composite->bounded.x + tx >= 0 &&
- composite->bounded.y + ty >= 0 &&
- composite->bounded.x + composite->bounded.width + tx <= src->width &&
- composite->bounded.y + composite->bounded.height + ty <= src->height) {
-
- assert(PIXMAN_FORMAT_BPP(dst->pixman_format) == 32);
- r->u.blit.stride = dst->stride;
- r->u.blit.data = dst->data;
- r->u.blit.src_stride = src->stride;
- r->u.blit.src_data = src->data + src->stride * ty + tx * 4;
- r->base.render_rows = _blit_xrgb32_lerp_spans;
- }
- }
- if (r->base.render_rows == NULL) {
- const cairo_pattern_t *src = &composite->source_pattern.base;
- unsigned int width;
-
- if (composite->is_bounded == 0)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- r->base.render_rows = r->bpp == 0xff ? _inplace_spans : _inplace_opacity_spans;
- width = (composite->bounded.width + 3) & ~3;
-
- r->u.composite.run_length = 8;
- if (src->type == CAIRO_PATTERN_TYPE_LINEAR ||
- src->type == CAIRO_PATTERN_TYPE_RADIAL)
- r->u.composite.run_length = 256;
- if (dst->base.is_clear &&
- (composite->op == CAIRO_OPERATOR_SOURCE ||
- composite->op == CAIRO_OPERATOR_OVER ||
- composite->op == CAIRO_OPERATOR_ADD)) {
- r->op = PIXMAN_OP_SRC;
- } else if (composite->op == CAIRO_OPERATOR_SOURCE) {
- r->base.render_rows = r->bpp == 0xff ? _inplace_src_spans : _inplace_src_opacity_spans;
- r->u.composite.mask_y = r->composite->unbounded.y;
- width = (composite->unbounded.width + 3) & ~3;
- } else if (composite->op == CAIRO_OPERATOR_CLEAR) {
- r->op = PIXMAN_OP_OUT_REVERSE;
- src = NULL;
- } else {
- r->op = _pixman_operator (composite->op);
- }
-
- r->src = _pixman_image_for_pattern (dst, src, FALSE,
- &composite->bounded,
- &composite->source_sample_area,
- &r->u.composite.src_x, &r->u.composite.src_y);
- if (unlikely (r->src == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- /* Create an effectively unbounded mask by repeating the single line */
- buf = r->_buf;
- if (width > SZ_BUF) {
- buf = _cairo_malloc (width);
- if (unlikely (buf == NULL)) {
- pixman_image_unref (r->src);
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
- }
- }
- r->mask = pixman_image_create_bits (PIXMAN_a8,
- width, composite->unbounded.height,
- (uint32_t *)buf, 0);
- if (unlikely (r->mask == NULL)) {
- pixman_image_unref (r->src);
- if (buf != r->_buf)
- free (buf);
- return _cairo_error(CAIRO_STATUS_NO_MEMORY);
- }
-
- if (buf != r->_buf)
- pixman_image_set_destroy_function (r->mask, free_pixels, buf);
-
- r->u.composite.dst = dst->pixman_image;
- }
-
- return CAIRO_INT_STATUS_SUCCESS;
-}
-
-static cairo_int_status_t
-span_renderer_init (cairo_abstract_span_renderer_t *_r,
- const cairo_composite_rectangles_t *composite,
- cairo_antialias_t antialias,
- cairo_bool_t needs_clip)
-{
- cairo_image_span_renderer_t *r = (cairo_image_span_renderer_t *)_r;
- cairo_image_surface_t *dst = (cairo_image_surface_t *)composite->surface;
- const cairo_pattern_t *source = &composite->source_pattern.base;
- cairo_operator_t op = composite->op;
- cairo_int_status_t status;
-
- TRACE ((stderr, "%s: antialias=%d, needs_clip=%d\n", __FUNCTION__,
- antialias, needs_clip));
-
- if (needs_clip)
- return CAIRO_INT_STATUS_UNSUPPORTED;
-
- r->composite = composite;
- r->mask = NULL;
- r->src = NULL;
- r->base.finish = NULL;
-
- status = mono_renderer_init (r, composite, antialias, needs_clip);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
-
- status = inplace_renderer_init (r, composite, antialias, needs_clip);
- if (status != CAIRO_INT_STATUS_UNSUPPORTED)
- return status;
-
- r->bpp = 0;
-
- if (op == CAIRO_OPERATOR_CLEAR) {
-#if PIXMAN_HAS_OP_LERP
- op = PIXMAN_OP_LERP_CLEAR;
-#else
- source = &_cairo_pattern_white.base;
- op = PIXMAN_OP_OUT_REVERSE;
-#endif
- } else if (dst->base.is_clear &&
- (op == CAIRO_OPERATOR_SOURCE ||
- op == CAIRO_OPERATOR_OVER ||
- op == CAIRO_OPERATOR_ADD)) {
- op = PIXMAN_OP_SRC;
- } else if (op == CAIRO_OPERATOR_SOURCE) {
- if (_cairo_pattern_is_opaque (&composite->source_pattern.base,
- &composite->source_sample_area))
- {
- op = PIXMAN_OP_OVER;
- }
- else
- {
-#if PIXMAN_HAS_OP_LERP
- op = PIXMAN_OP_LERP_SRC;
-#else
- return CAIRO_INT_STATUS_UNSUPPORTED;
-#endif
- }
- } else {
- op = _pixman_operator (op);
- }
- r->op = op;
-
- r->src = _pixman_image_for_pattern (dst, source, FALSE,
- &composite->unbounded,
- &composite->source_sample_area,
- &r->u.mask.src_x, &r->u.mask.src_y);
- if (unlikely (r->src == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- r->opacity = 1.0;
- if (composite->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID) {
- r->opacity = composite->mask_pattern.solid.color.alpha;
- } else {
- pixman_image_t *mask;
- int mask_x, mask_y;
-
- mask = _pixman_image_for_pattern (dst,
- &composite->mask_pattern.base,
- TRUE,
- &composite->unbounded,
- &composite->mask_sample_area,
- &mask_x, &mask_y);
- if (unlikely (mask == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- /* XXX Component-alpha? */
- if ((dst->base.content & CAIRO_CONTENT_COLOR) == 0 &&
- _cairo_pattern_is_opaque (source, &composite->source_sample_area))
- {
- pixman_image_unref (r->src);
- r->src = mask;
- r->u.mask.src_x = mask_x;
- r->u.mask.src_y = mask_y;
- mask = NULL;
- }
-
- if (mask) {
- pixman_image_unref (mask);
- return CAIRO_INT_STATUS_UNSUPPORTED;
- }
- }
-
- r->u.mask.extents = composite->unbounded;
- r->u.mask.stride = (r->u.mask.extents.width + 3) & ~3;
- if (r->u.mask.extents.height * r->u.mask.stride > SZ_BUF) {
- r->mask = pixman_image_create_bits (PIXMAN_a8,
- r->u.mask.extents.width,
- r->u.mask.extents.height,
- NULL, 0);
-
- r->base.render_rows = _cairo_image_spans;
- r->base.finish = NULL;
- } else {
- r->mask = pixman_image_create_bits (PIXMAN_a8,
- r->u.mask.extents.width,
- r->u.mask.extents.height,
- (uint32_t *)r->_buf, r->u.mask.stride);
-
- r->base.render_rows = _cairo_image_spans_and_zero;
- r->base.finish = _cairo_image_finish_spans_and_zero;
- }
- if (unlikely (r->mask == NULL))
- return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
- r->u.mask.data = (uint8_t *) pixman_image_get_data (r->mask);
- r->u.mask.stride = pixman_image_get_stride (r->mask);
-
- r->u.mask.extents.height += r->u.mask.extents.y;
- return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-span_renderer_fini (cairo_abstract_span_renderer_t *_r,
- cairo_int_status_t status)
-{
- cairo_image_span_renderer_t *r = (cairo_image_span_renderer_t *) _r;
-
- TRACE ((stderr, "%s\n", __FUNCTION__));
-
- if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
- if (r->base.finish)
- r->base.finish (r);
- }
- if (likely (status == CAIRO_INT_STATUS_SUCCESS && r->bpp == 0)) {
- const cairo_composite_rectangles_t *composite = r->composite;
-
- pixman_image_composite32 (r->op, r->src, r->mask,
- to_pixman_image (composite->surface),
- composite->unbounded.x + r->u.mask.src_x,
- composite->unbounded.y + r->u.mask.src_y,
- 0, 0,
- composite->unbounded.x,
- composite->unbounded.y,
- composite->unbounded.width,
- composite->unbounded.height);
- }
-
- if (r->src)
- pixman_image_unref (r->src);
- if (r->mask)
- pixman_image_unref (r->mask);
-}
-#endif
-
-const cairo_compositor_t *
-_cairo_image_spans_compositor_get (void)
-{
- static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT;
- static cairo_spans_compositor_t spans;
- static cairo_compositor_t shape;
-
- if (_cairo_atomic_init_once_enter(&once)) {
- _cairo_shape_mask_compositor_init (&shape,
- _cairo_image_traps_compositor_get());
- shape.glyphs = NULL;
-
- _cairo_spans_compositor_init (&spans, &shape);
-
- spans.flags = 0;
-#if PIXMAN_HAS_OP_LERP
- spans.flags |= CAIRO_SPANS_COMPOSITOR_HAS_LERP;
-#endif
-
- //spans.acquire = acquire;
- //spans.release = release;
- spans.fill_boxes = fill_boxes;
- spans.draw_image_boxes = draw_image_boxes;
- //spans.copy_boxes = copy_boxes;
- spans.pattern_to_surface = _cairo_image_source_create_for_pattern;
- //spans.check_composite_boxes = check_composite_boxes;
- spans.composite_boxes = composite_boxes;
- //spans.check_span_renderer = check_span_renderer;
- spans.renderer_init = span_renderer_init;
- spans.renderer_fini = span_renderer_fini;
-
- _cairo_atomic_init_once_leave(&once);
- }
-
- return &spans.base;
-}