Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/gfx/cairo/cairo/src/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 140 kB image not shown  

Quelle  cairo-xcb-surface-render.c   Sprache: C

 
/* cairo - a vector graphics library with display and print output
 *
 * Copyright © 2009 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.
 *
 * Contributor(s):
 * Chris Wilson <chris@chris-wilson.co.uk>
 */


#include "cairoint.h"

#include "cairo-xcb-private.h"

#include "cairo-boxes-private.h"
#include "cairo-clip-inline.h"
#include "cairo-clip-private.h"
#include "cairo-composite-rectangles-private.h"
#include "cairo-image-surface-inline.h"
#include "cairo-image-surface-private.h"
#include "cairo-list-inline.h"
#include "cairo-region-private.h"
#include "cairo-surface-offset-private.h"
#include "cairo-surface-snapshot-inline.h"
#include "cairo-surface-subsurface-private.h"
#include "cairo-traps-private.h"
#include "cairo-recording-surface-inline.h"
#include "cairo-paginated-private.h"
#include "cairo-pattern-inline.h"

#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */

static cairo_status_t
_clip_and_composite_boxes (cairo_xcb_surface_t *dst,
      cairo_operator_t op,
      const cairo_pattern_t *src,
      cairo_boxes_t *boxes,
      cairo_composite_rectangles_t *extents);

static inline cairo_xcb_connection_t *
_picture_to_connection (cairo_xcb_picture_t *picture)
{
    return (cairo_xcb_connection_t *) picture->base.device;
}

static void
_cairo_xcb_surface_ensure_picture (cairo_xcb_surface_t *surface);

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 cairo_status_t
_cairo_xcb_picture_finish (void *abstract_surface)
{
    cairo_xcb_picture_t *surface = abstract_surface;
    cairo_xcb_connection_t *connection = _picture_to_connection (surface);
    cairo_status_t status;

    status = _cairo_xcb_connection_acquire (connection);
    cairo_list_del (&surface->link);
    if (unlikely (status))
 return status;

    _cairo_xcb_connection_render_free_picture (connection, surface->picture);

    _cairo_xcb_connection_release (connection);

    return CAIRO_STATUS_SUCCESS;
}

static const cairo_surface_backend_t _cairo_xcb_picture_backend = {
    CAIRO_SURFACE_TYPE_XCB,
    _cairo_xcb_picture_finish,
};

static const struct xcb_render_transform_t identity_transform = {
    1 << 16, 0, 0,
    0, 1 << 16, 0,
    0, 0, 1 << 16,
};

static cairo_xcb_picture_t *
_cairo_xcb_picture_create (cairo_xcb_screen_t *screen,
      pixman_format_code_t pixman_format,
      xcb_render_pictformat_t xrender_format,
      int width, int height)
{
    cairo_xcb_picture_t *surface;

    surface = _cairo_malloc (sizeof (cairo_xcb_picture_t));
    if (unlikely (surface == NULL))
 return (cairo_xcb_picture_t *)
     _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));

    _cairo_surface_init (&surface->base,
    &_cairo_xcb_picture_backend,
    &screen->connection->device,
    _cairo_content_from_pixman_format (pixman_format),
    FALSE); /* is_vector */

    cairo_list_add (&surface->link, &screen->pictures);

    surface->screen = screen;
    surface->picture = xcb_generate_id (screen->connection->xcb_connection);
    surface->pixman_format = pixman_format;
    surface->xrender_format = xrender_format;

    surface->x0 = surface->y0 = 0;
    surface->x = surface->y = 0;
    surface->width = width;
    surface->height = height;

    surface->transform = identity_transform;
    surface->extend = CAIRO_EXTEND_NONE;
    surface->filter = CAIRO_FILTER_NEAREST;
    surface->has_component_alpha = FALSE;

    return surface;
}

static inline cairo_bool_t
_operator_is_supported (uint32_t flags, cairo_operator_t op)
{
    if (op <= CAIRO_OPERATOR_SATURATE)
 return TRUE;

    /* Can we use PDF operators? */
#if CAIRO_XCB_RENDER_AT_LEAST(0, 11)
    if (op <= CAIRO_OPERATOR_HSL_LUMINOSITY)
 return flags & CAIRO_XCB_RENDER_HAS_PDF_OPERATORS;
#endif

    return FALSE;
}

static int
_render_operator (cairo_operator_t op)
{
#define C(x,y) case CAIRO_OPERATOR_##x: return XCB_RENDER_PICT_OP_##y
    switch (op) {
    C(CLEAR, CLEAR);
    C(SOURCE, SRC);

    C(OVER, OVER);
    C(IN, IN);
    C(OUT, OUT);
    C(ATOP, ATOP);

    C(DEST, DST);
    C(DEST_OVER, OVER_REVERSE);
    C(DEST_IN, IN_REVERSE);
    C(DEST_OUT, OUT_REVERSE);
    C(DEST_ATOP, ATOP_REVERSE);

    C(XORXOR);
    C(ADD, ADD);
    C(SATURATE, SATURATE);

    /* PDF operators were added in RENDER 0.11, check if the xcb headers have
     * the defines, else fall through to the default case. */

#if CAIRO_XCB_RENDER_AT_LEAST(0, 11)
#define BLEND(x,y) C(x,y)
#else
#define BLEND(x,y) case CAIRO_OPERATOR_##x:
#endif
    BLEND(MULTIPLY, MULTIPLY);
    BLEND(SCREEN, SCREEN);
    BLEND(OVERLAY, OVERLAY);
    BLEND(DARKEN, DARKEN);
    BLEND(LIGHTEN, LIGHTEN);
    BLEND(COLOR_DODGE, COLOR_DODGE);
    BLEND(COLOR_BURN, COLOR_BURN);
    BLEND(HARD_LIGHT, HARD_LIGHT);
    BLEND(SOFT_LIGHT, SOFT_LIGHT);
    BLEND(DIFFERENCE, DIFFERENCE);
    BLEND(EXCLUSION, EXCLUSION);
    BLEND(HSL_HUE, HSL_HUE);
    BLEND(HSL_SATURATION, HSL_SATURATION);
    BLEND(HSL_COLOR, HSL_COLOR);
    BLEND(HSL_LUMINOSITY, HSL_LUMINOSITY);

    default:
 ASSERT_NOT_REACHED;
 return XCB_RENDER_PICT_OP_OVER;
    }
}

static cairo_status_t
_cairo_xcb_surface_set_clip_region (cairo_xcb_surface_t *surface,
        cairo_region_t *region)
{
    xcb_rectangle_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (xcb_rectangle_t)];
    xcb_rectangle_t *rects = stack_rects;
    int i, num_rects;

    num_rects = cairo_region_num_rectangles (region);

    if (num_rects > ARRAY_LENGTH (stack_rects)) {
 rects = _cairo_malloc_ab (num_rects, sizeof (xcb_rectangle_t));
 if (unlikely (rects == NULL)) {
     return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 }
    }

    for (i = 0; i < num_rects; i++) {
 cairo_rectangle_int_t rect;

 cairo_region_get_rectangle (region, i, &rect);

 rects[i].x = rect.x;
 rects[i].y = rect.y;
 rects[i].width  = rect.width;
 rects[i].height = rect.height;
    }

    _cairo_xcb_connection_render_set_picture_clip_rectangles (surface->connection,
             surface->picture,
             0, 0,
             num_rects, rects);

    if (rects != stack_rects)
 free (rects);

    return CAIRO_STATUS_SUCCESS;
}

static void
_cairo_xcb_surface_clear_clip_region (cairo_xcb_surface_t *surface)
{
    uint32_t values[] = { XCB_NONE };
    _cairo_xcb_connection_render_change_picture (surface->connection,
       surface->picture,
       XCB_RENDER_CP_CLIP_MASK,
       values);
}

static void
_cairo_xcb_surface_set_precision (cairo_xcb_surface_t *surface,
      cairo_antialias_t  antialias)
{
    cairo_xcb_connection_t *connection = surface->connection;
    uint32_t precision;

    if (connection->force_precision != -1)
     precision = connection->force_precision;
    else switch (antialias) {
    default:
    case CAIRO_ANTIALIAS_DEFAULT:
    case CAIRO_ANTIALIAS_GRAY:
    case CAIRO_ANTIALIAS_NONE:
    case CAIRO_ANTIALIAS_FAST:
    case CAIRO_ANTIALIAS_GOOD:
 precision = XCB_RENDER_POLY_MODE_IMPRECISE;
 break;
    case CAIRO_ANTIALIAS_SUBPIXEL:
    case CAIRO_ANTIALIAS_BEST:
 precision = XCB_RENDER_POLY_MODE_PRECISE;
 break;
    }

    if (surface->precision != precision) {
 _cairo_xcb_connection_render_change_picture (connection,
           surface->picture,
           XCB_RENDER_CP_POLY_MODE,
           &precision);
 surface->precision = precision;
    }
}


static void
_cairo_xcb_surface_ensure_picture (cairo_xcb_surface_t *surface)
{
    assert (surface->fallback == NULL);
    if (surface->picture == XCB_NONE) {
 uint32_t values[1];
 uint32_t flags = 0;

 if (surface->precision != XCB_RENDER_POLY_MODE_PRECISE) {
     flags |= XCB_RENDER_CP_POLY_MODE;
     values[0] = surface->precision;
 }

 surface->picture = xcb_generate_id (surface->connection->xcb_connection);
 _cairo_xcb_connection_render_create_picture (surface->connection,
           surface->picture,
           surface->drawable,
           surface->xrender_format,
           flags, values);
    }
}

static cairo_xcb_picture_t *
_picture_from_image (cairo_xcb_surface_t *target,
       xcb_render_pictformat_t format,
       cairo_image_surface_t *image,
       cairo_xcb_shm_info_t *shm_info)
{
    xcb_pixmap_t pixmap;
    xcb_gcontext_t gc;
    cairo_xcb_picture_t *picture;

    pixmap = _cairo_xcb_connection_create_pixmap (target->connection,
        image->depth,
        target->drawable,
        image->width, image->height);

    gc = _cairo_xcb_screen_get_gc (target->screen, pixmap, image->depth);

    if (shm_info != NULL) {
 _cairo_xcb_connection_shm_put_image (target->connection,
          pixmap, gc,
          image->width, image->height,
          0, 0,
          image->width, image->height,
          0, 0,
          image->depth,
          shm_info->shm,
          shm_info->offset);
    } else {
 int len;

 /* Do we need to trim the image? */
 len = CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format));
 if (len == image->stride) {
     _cairo_xcb_connection_put_image (target->connection,
          pixmap, gc,
          image->width, image->height,
          0, 0,
          image->depth,
          image->stride,
          image->data);
 } else {
     _cairo_xcb_connection_put_subimage (target->connection,
      pixmap, gc,
      0, 0,
      image->width, image->height,
      PIXMAN_FORMAT_BPP (image->pixman_format) / 8,
      image->stride,
      0, 0,
      image->depth,
      image->data);

 }
    }

    _cairo_xcb_screen_put_gc (target->screen, image->depth, gc);

    picture = _cairo_xcb_picture_create (target->screen,
      image->pixman_format, format,
      image->width, image->height);
    if (likely (picture->base.status == CAIRO_STATUS_SUCCESS)) {
 _cairo_xcb_connection_render_create_picture (target->connection,
           picture->picture, pixmap, format,
           0, 0);
    }

    xcb_free_pixmap (target->connection->xcb_connection, pixmap);

    return picture;
}

static cairo_bool_t
_pattern_is_supported (uint32_t flags,
         const cairo_pattern_t *pattern)

{
    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
 return TRUE;

    switch (pattern->extend) {
    default:
 ASSERT_NOT_REACHED;
    case CAIRO_EXTEND_NONE:
    case CAIRO_EXTEND_REPEAT:
 break;
    case CAIRO_EXTEND_PAD:
    case CAIRO_EXTEND_REFLECT:
 if ((flags & CAIRO_XCB_RENDER_HAS_EXTENDED_REPEAT) == 0)
     return FALSE;
    }

    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
 switch (pattern->filter) {
 case CAIRO_FILTER_FAST:
 case CAIRO_FILTER_NEAREST:
     return (flags & CAIRO_XCB_RENDER_HAS_PICTURE_TRANSFORM) ||
  _cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL);
 case CAIRO_FILTER_GOOD:
     return flags & CAIRO_XCB_RENDER_HAS_FILTER_GOOD;
 case CAIRO_FILTER_BEST:
     return flags & CAIRO_XCB_RENDER_HAS_FILTER_BEST;
 case CAIRO_FILTER_BILINEAR:
 case CAIRO_FILTER_GAUSSIAN:
 default:
     return flags & CAIRO_XCB_RENDER_HAS_FILTERS;
 }
    } else if (pattern->type == CAIRO_PATTERN_TYPE_MESH) {
 return FALSE;
    } else { /* gradient */
 if ((flags & CAIRO_XCB_RENDER_HAS_GRADIENTS) == 0)
     return FALSE;

 /* The RENDER specification says that the inner circle has to be
 * completely contained inside the outer one. */

 if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL &&
     ! _cairo_radial_pattern_focus_is_inside ((cairo_radial_pattern_t *) pattern))
 {
     return FALSE;
 }
 return TRUE;
    }
}

static void
_cairo_xcb_picture_set_matrix (cairo_xcb_picture_t *picture,
          const cairo_matrix_t *matrix,
          cairo_filter_t filter,
          double xc, double yc)
{
    xcb_render_transform_t transform;
    pixman_transform_t *pixman_transform;
    cairo_int_status_t ignored;

    /* Casting between pixman_transform_t and xcb_render_transform_t is safe
     * because they happen to be the exact same type.
     */

    pixman_transform = (pixman_transform_t *) &transform;

    picture->x = picture->x0;
    picture->y = picture->y0;
    ignored = _cairo_matrix_to_pixman_matrix_offset (matrix, filter, xc, yc,
           pixman_transform,
           &picture->x, &picture->y);
    (void) ignored;

    if (memcmp (&picture->transform, &transform, sizeof (xcb_render_transform_t))) {
 _cairo_xcb_connection_render_set_picture_transform (_picture_to_connection (picture),
           picture->picture,
           &transform);

 picture->transform = transform;
    }
}

static void
_cairo_xcb_picture_set_filter (cairo_xcb_picture_t *picture,
          cairo_filter_t filter)
{
    const char *render_filter;
    int len;

    if (picture->filter == filter)
 return;

    switch (filter) {
    case CAIRO_FILTER_FAST:
 render_filter = "fast";
 len = strlen ("fast");
 break;

    case CAIRO_FILTER_GOOD:
 render_filter = "good";
 len = strlen ("good");
 break;

    case CAIRO_FILTER_BEST:
 render_filter = "best";
 len = strlen ("best");
 break;

    case CAIRO_FILTER_NEAREST:
 render_filter = "nearest";
 len = strlen ("nearest");
 break;

    case CAIRO_FILTER_BILINEAR:
 render_filter = "bilinear";
 len = strlen ("bilinear");
 break;

    default:
 ASSERT_NOT_REACHED;
    case CAIRO_FILTER_GAUSSIAN:
 render_filter = "best";
 len = strlen ("best");
 break;
    }

    _cairo_xcb_connection_render_set_picture_filter (_picture_to_connection (picture),
           picture->picture,
           len, (char *) render_filter);
    picture->filter = filter;
}

static void
_cairo_xcb_picture_set_extend (cairo_xcb_picture_t *picture,
          cairo_extend_t extend)
{
    uint32_t pa[1];

    if (picture->extend == extend)
 return;

    switch (extend) {
    default:
 ASSERT_NOT_REACHED;
    case CAIRO_EXTEND_NONE:
 pa[0] = XCB_RENDER_REPEAT_NONE;
 break;

    case CAIRO_EXTEND_REPEAT:
 pa[0] = XCB_RENDER_REPEAT_NORMAL;
 break;

    case CAIRO_EXTEND_REFLECT:
 pa[0] = XCB_RENDER_REPEAT_REFLECT;
 break;

    case CAIRO_EXTEND_PAD:
 pa[0] = XCB_RENDER_REPEAT_PAD;
 break;
    }

    _cairo_xcb_connection_render_change_picture (_picture_to_connection (picture),
       picture->picture,
       XCB_RENDER_CP_REPEAT, pa);
    picture->extend = extend;
}

static void
_cairo_xcb_picture_set_component_alpha (cairo_xcb_picture_t *picture,
     cairo_bool_t ca)
{
    uint32_t pa[1];

    if (picture->has_component_alpha == ca)
 return;

    pa[0] = ca;

    _cairo_xcb_connection_render_change_picture (_picture_to_connection (picture),
       picture->picture,
       XCB_RENDER_CP_COMPONENT_ALPHA,
       pa);
    picture->has_component_alpha = ca;
}

static cairo_xcb_picture_t *
_solid_picture (cairo_xcb_surface_t *target,
  const cairo_color_t *color)
{
    xcb_render_color_t xcb_color;
    xcb_render_pictformat_t xrender_format;
    cairo_xcb_picture_t *picture;

    xcb_color.red   = color->red_short;
    xcb_color.green = color->green_short;
    xcb_color.blue  = color->blue_short;
    xcb_color.alpha = color->alpha_short;

    xrender_format = target->screen->connection->standard_formats[CAIRO_FORMAT_ARGB32];
    picture = _cairo_xcb_picture_create (target->screen,
      PIXMAN_a8r8g8b8,
      xrender_format,
      -1, -1);
    if (unlikely (picture->base.status))
 return picture;

    if (target->connection->flags & CAIRO_XCB_RENDER_HAS_GRADIENTS) {
 _cairo_xcb_connection_render_create_solid_fill (target->connection,
       picture->picture,
       xcb_color);
    } else {
 xcb_pixmap_t pixmap;
 uint32_t values[] = { XCB_RENDER_REPEAT_NORMAL };

 pixmap = _cairo_xcb_connection_create_pixmap (target->connection,
            32, target->drawable, 1, 1);
 _cairo_xcb_connection_render_create_picture (target->connection,
           picture->picture,
           pixmap,
           xrender_format,
           XCB_RENDER_CP_REPEAT,
           values);
 if (target->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES) {
     xcb_rectangle_t rect;

     rect.x = rect.y = 0;
     rect.width = rect.height = 1;

     _cairo_xcb_connection_render_fill_rectangles (_picture_to_connection (picture),
         XCB_RENDER_PICT_OP_SRC,
         picture->picture,
         xcb_color, 1, &rect);
 } else {
     xcb_gcontext_t gc;
     uint32_t pixel;

     gc = _cairo_xcb_screen_get_gc (target->screen, pixmap, 32);

     /* XXX byte ordering? */
     pixel = (((uint32_t)color->alpha_short >> 8) << 24) |
      ((color->red_short   >> 8) << 16) |
      ((color->green_short >> 8) << 8) |
      ((color->blue_short  >> 8) << 0);

     _cairo_xcb_connection_put_image (target->connection,
          pixmap, gc,
          1, 1, 0, 0,
          32, 4, &pixel);

     _cairo_xcb_screen_put_gc (target->screen, 32, gc);
 }

 xcb_free_pixmap (target->connection->xcb_connection, pixmap);
    }

    return picture;
}

static cairo_xcb_picture_t *
_cairo_xcb_transparent_picture (cairo_xcb_surface_t *target)
{
    cairo_xcb_picture_t *picture;

    picture = (cairo_xcb_picture_t *) target->screen->stock_colors[CAIRO_STOCK_TRANSPARENT];
    if (picture == NULL) {
 picture = _solid_picture (target, CAIRO_COLOR_TRANSPARENT);
 target->screen->stock_colors[CAIRO_STOCK_TRANSPARENT] = &picture->base;
    }

    return (cairo_xcb_picture_t *) cairo_surface_reference (&picture->base);
}

static cairo_xcb_picture_t *
_cairo_xcb_black_picture (cairo_xcb_surface_t *target)
{
    cairo_xcb_picture_t *picture;

    picture = (cairo_xcb_picture_t *) target->screen->stock_colors[CAIRO_STOCK_BLACK];
    if (picture == NULL) {
 picture = _solid_picture (target, CAIRO_COLOR_BLACK);
 target->screen->stock_colors[CAIRO_STOCK_BLACK] = &picture->base;
    }

    return (cairo_xcb_picture_t *) cairo_surface_reference (&picture->base);
}

static cairo_xcb_picture_t *
_cairo_xcb_white_picture (cairo_xcb_surface_t *target)
{
    cairo_xcb_picture_t *picture;

    picture = (cairo_xcb_picture_t *) target->screen->stock_colors[CAIRO_STOCK_WHITE];
    if (picture == NULL) {
 picture = _solid_picture (target, CAIRO_COLOR_WHITE);
 target->screen->stock_colors[CAIRO_STOCK_WHITE] = &picture->base;
    }

    return (cairo_xcb_picture_t *) cairo_surface_reference (&picture->base);
}

static cairo_xcb_picture_t *
_cairo_xcb_solid_picture (cairo_xcb_surface_t *target,
     const cairo_solid_pattern_t *pattern)
{
    cairo_xcb_picture_t *picture;
    cairo_xcb_screen_t *screen;
    int i, n_cached;

    if (pattern->color.alpha_short <= 0x00ff)
 return _cairo_xcb_transparent_picture (target);

    if (pattern->color.alpha_short >= 0xff00) {
 if (pattern->color.red_short <= 0x00ff &&
     pattern->color.green_short <= 0x00ff &&
     pattern->color.blue_short <= 0x00ff)
 {
     return _cairo_xcb_black_picture (target);
 }

 if (pattern->color.red_short >= 0xff00 &&
     pattern->color.green_short >= 0xff00 &&
     pattern->color.blue_short >= 0xff00)
 {
     return _cairo_xcb_white_picture (target);
 }
    }

    screen = target->screen;
    n_cached = screen->solid_cache_size;
    for (i = 0; i < n_cached; i++) {
 if (_cairo_color_equal (&screen->solid_cache[i].color, &pattern->color)) {
     return (cairo_xcb_picture_t *) cairo_surface_reference (screen->solid_cache[i].picture);
 }
    }

    picture = _solid_picture (target, &pattern->color);
    if (unlikely (picture->base.status))
 return picture;

    if (screen->solid_cache_size < ARRAY_LENGTH (screen->solid_cache)) {
 i = screen->solid_cache_size++;
    } else {
 i = hars_petruska_f54_1_random () % ARRAY_LENGTH (screen->solid_cache);
 cairo_surface_destroy (screen->solid_cache[i].picture);
    }
    screen->solid_cache[i].picture = cairo_surface_reference (&picture->base);
    screen->solid_cache[i].color = pattern->color;

    return picture;
}

static cairo_xcb_picture_t *
_render_to_picture (cairo_xcb_surface_t *target,
      const cairo_pattern_t *pattern,
      const cairo_rectangle_int_t *extents)
{
    cairo_image_surface_t *image;
    cairo_xcb_shm_info_t *shm_info;
    cairo_pattern_union_t copy;
    cairo_status_t status;
    cairo_xcb_picture_t *picture;
    pixman_format_code_t pixman_format;
    xcb_render_pictformat_t xrender_format;

    /* XXX handle extend modes via tiling? */
    /* XXX alpha-only masks? */

    pixman_format = PIXMAN_a8r8g8b8;
    xrender_format = target->screen->connection->standard_formats[CAIRO_FORMAT_ARGB32];

    status = _cairo_xcb_shm_image_create (target->screen->connection,
       pixman_format,
       extents->width, extents->height,
       &image, &shm_info);
    if (unlikely (status))
 return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);

    _cairo_pattern_init_static_copy (©.base, pattern);
    cairo_matrix_translate (©.base.matrix, extents->x, extents->y);
    status = _cairo_surface_paint (&image->base,
       CAIRO_OPERATOR_SOURCE,
       ©.base,
       NULL);
    if (unlikely (status)) {
 cairo_surface_destroy (&image->base);
 return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
    }

    picture = _picture_from_image (target, xrender_format, image, shm_info);
    cairo_surface_destroy (&image->base);

    if (unlikely (picture->base.status))
 return picture;

    _cairo_xcb_picture_set_component_alpha (picture, pattern->has_component_alpha);
    picture->x = -extents->x;
    picture->y = -extents->y;

    return picture;
}

static xcb_render_fixed_t *
_gradient_to_xcb (const cairo_gradient_pattern_t *gradient,
    unsigned int *n_stops,
    char *buf, unsigned int buflen)
{
    xcb_render_fixed_t *stops;
    xcb_render_color_t *colors;
    unsigned int i;

    assert (gradient->n_stops > 0);
    *n_stops = MAX (gradient->n_stops, 2);

    if (*n_stops * (sizeof (xcb_render_fixed_t) + sizeof (xcb_render_color_t)) < buflen)
    {
 stops = (xcb_render_fixed_t *) buf;
    }
    else
    {
 stops =
     _cairo_malloc_ab (*n_stops,
         sizeof (xcb_render_fixed_t) + sizeof (xcb_render_color_t));
 if (unlikely (stops == NULL))
     return NULL;
    }

    colors = (xcb_render_color_t *) (stops + *n_stops);
    for (i = 0; i < gradient->n_stops; i++) {
 stops[i] =
     _cairo_fixed_16_16_from_double (gradient->stops[i].offset);

 colors[i].red   = gradient->stops[i].color.red_short;
 colors[i].green = gradient->stops[i].color.green_short;
 colors[i].blue  = gradient->stops[i].color.blue_short;
 colors[i].alpha = gradient->stops[i].color.alpha_short;
    }

    /* RENDER does not support gradients with less than 2 stops. If a
     * gradient has only a single stop, duplicate it to make RENDER
     * happy. */

    if (gradient->n_stops == 1) {
 stops[1] = _cairo_fixed_16_16_from_double (gradient->stops[0].offset);

 colors[1].red   = gradient->stops[0].color.red_short;
 colors[1].green = gradient->stops[0].color.green_short;
 colors[1].blue  = gradient->stops[0].color.blue_short;
 colors[1].alpha = gradient->stops[0].color.alpha_short;
    }

    return stops;
}

static cairo_xcb_picture_t *
_cairo_xcb_linear_picture (cairo_xcb_surface_t *target,
      const cairo_linear_pattern_t *pattern,
      const cairo_rectangle_int_t *extents)
{
    char buf[CAIRO_STACK_BUFFER_SIZE];
    xcb_render_fixed_t *stops;
    xcb_render_color_t *colors;
    xcb_render_pointfix_t p1, p2;
    cairo_matrix_t matrix;
    cairo_circle_double_t extremes[2];
    cairo_xcb_picture_t *picture;
    cairo_status_t status;
    unsigned int n_stops;

    _cairo_gradient_pattern_fit_to_range (&pattern->base, PIXMAN_MAX_INT >> 1, &matrix, extremes);

    picture = (cairo_xcb_picture_t *)
 _cairo_xcb_screen_lookup_linear_picture (target->screen, pattern);
    if (picture != NULL)
 goto setup_picture;

    stops = _gradient_to_xcb (&pattern->base, &n_stops, buf, sizeof (buf));
    if (unlikely (stops == NULL))
 return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);

    picture = _cairo_xcb_picture_create (target->screen,
      target->screen->connection->standard_formats[CAIRO_FORMAT_ARGB32],
      PIXMAN_a8r8g8b8,
      -1, -1);
    if (unlikely (picture->base.status)) {
 if (stops != (xcb_render_fixed_t *) buf)
     free (stops);
 return picture;
    }
    picture->filter = CAIRO_FILTER_DEFAULT;

    colors = (xcb_render_color_t *) (stops + n_stops);

    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);

    _cairo_xcb_connection_render_create_linear_gradient (target->connection,
        picture->picture,
        p1, p2,
        n_stops,
        stops, colors);

    if (stops != (xcb_render_fixed_t *) buf)
 free (stops);

    status = _cairo_xcb_screen_store_linear_picture (target->screen,
           pattern,
           &picture->base);
    if (unlikely (status)) {
 cairo_surface_destroy (&picture->base);
 return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
    }

setup_picture:
    _cairo_xcb_picture_set_matrix (picture, &matrix,
       pattern->base.base.filter,
       extents->x + extents->width/2.,
       extents->y + extents->height/2.);
    _cairo_xcb_picture_set_filter (picture, pattern->base.base.filter);
    _cairo_xcb_picture_set_extend (picture, pattern->base.base.extend);
    _cairo_xcb_picture_set_component_alpha (picture,
         pattern->base.base.has_component_alpha);

    return picture;
}

static cairo_xcb_picture_t *
_cairo_xcb_radial_picture (cairo_xcb_surface_t *target,
      const cairo_radial_pattern_t *pattern,
      const cairo_rectangle_int_t *extents)
{
    char buf[CAIRO_STACK_BUFFER_SIZE];
    xcb_render_fixed_t *stops;
    xcb_render_color_t *colors;
    xcb_render_pointfix_t p1, p2;
    xcb_render_fixed_t r1, r2;
    cairo_matrix_t matrix;
    cairo_circle_double_t extremes[2];
    cairo_xcb_picture_t *picture;
    cairo_status_t status;
    unsigned int n_stops;

    _cairo_gradient_pattern_fit_to_range (&pattern->base, PIXMAN_MAX_INT >> 1, &matrix, extremes);

    picture = (cairo_xcb_picture_t *)
 _cairo_xcb_screen_lookup_radial_picture (target->screen, pattern);
    if (picture != NULL)
 goto setup_picture;

    stops = _gradient_to_xcb (&pattern->base, &n_stops, buf, sizeof (buf));
    if (unlikely (stops == NULL))
 return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);

    picture = _cairo_xcb_picture_create (target->screen,
      target->screen->connection->standard_formats[CAIRO_FORMAT_ARGB32],
      PIXMAN_a8r8g8b8,
      -1, -1);
    if (unlikely (picture->base.status)) {
 if (stops != (xcb_render_fixed_t *) buf)
     free (stops);
 return picture;
    }
    picture->filter = CAIRO_FILTER_DEFAULT;

    colors = (xcb_render_color_t *) (stops + n_stops);

    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);

    r1 = _cairo_fixed_16_16_from_double (extremes[0].radius);
    r2 = _cairo_fixed_16_16_from_double (extremes[1].radius);

    _cairo_xcb_connection_render_create_radial_gradient (target->connection,
        picture->picture,
        p1, p2, r1, r2,
        n_stops,
        stops, colors);

    if (stops != (xcb_render_fixed_t *) buf)
 free (stops);

    status = _cairo_xcb_screen_store_radial_picture (target->screen,
           pattern,
           &picture->base);
    if (unlikely (status)) {
 cairo_surface_destroy (&picture->base);
 return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
    }

setup_picture:
    _cairo_xcb_picture_set_matrix (picture, &matrix,
       pattern->base.base.filter,
       extents->x + extents->width/2.,
       extents->y + extents->height/2.);
    _cairo_xcb_picture_set_filter (picture, pattern->base.base.filter);
    _cairo_xcb_picture_set_extend (picture, pattern->base.base.extend);
    _cairo_xcb_picture_set_component_alpha (picture,
         pattern->base.base.has_component_alpha);

    return picture;
}

static cairo_xcb_picture_t *
_copy_to_picture (cairo_xcb_surface_t *source)
{
    cairo_xcb_picture_t *picture;
    uint32_t values[] = { 0, 1 };

    if (source->deferred_clear) {
 cairo_status_t status = _cairo_xcb_surface_clear (source);
 if (unlikely (status))
     return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
    }

    picture = _cairo_xcb_picture_create (source->screen,
      source->xrender_format,
      source->pixman_format,
      source->width,
      source->height);
    if (unlikely (picture->base.status))
 return picture;

    _cairo_xcb_connection_render_create_picture (source->connection,
       picture->picture,
       source->drawable,
       source->xrender_format,
       XCB_RENDER_CP_GRAPHICS_EXPOSURE |
       XCB_RENDER_CP_SUBWINDOW_MODE,
       values);

    return picture;
}

static void
_cairo_xcb_surface_setup_surface_picture(cairo_xcb_picture_t *picture,
      const cairo_surface_pattern_t *pattern,
      const cairo_rectangle_int_t *extents)
{
    cairo_filter_t filter;

    filter = pattern->base.filter;
    if (filter != CAIRO_FILTER_NEAREST &&
        _cairo_matrix_is_pixel_exact (&pattern->base.matrix))
    {
 filter = CAIRO_FILTER_NEAREST;
    }
    _cairo_xcb_picture_set_filter (picture, filter);

    _cairo_xcb_picture_set_matrix (picture,
       &pattern->base.matrix, filter,
       extents->x + extents->width/2.,
       extents->y + extents->height/2.);


    _cairo_xcb_picture_set_extend (picture, pattern->base.extend);
    _cairo_xcb_picture_set_component_alpha (picture, pattern->base.has_component_alpha);
}

static cairo_xcb_picture_t *
record_to_picture (cairo_surface_t *target,
     const cairo_surface_pattern_t *pattern,
     const cairo_rectangle_int_t *extents)
{
    cairo_surface_pattern_t tmp_pattern;
    cairo_xcb_picture_t *picture;
    cairo_status_t status;
    cairo_matrix_t matrix;
    cairo_surface_t *tmp;
    cairo_surface_t *source;
    cairo_rectangle_int_t limit;
    cairo_extend_t extend;

    /* XXX: The following was once more or less copied from cairo-xlibs-ource.c,
     * record_source() and recording_pattern_get_surface(), can we share a
     * single version?
     */


    /* First get the 'real' recording surface and figure out the size for tmp */
    source = _cairo_pattern_get_source (pattern, &limit);
    assert (_cairo_surface_is_recording (source));

    if (! _cairo_matrix_is_identity (&pattern->base.matrix)) {
 double x1, y1, x2, y2;

 matrix = pattern->base.matrix;
 status = cairo_matrix_invert (&matrix);
 assert (status == CAIRO_STATUS_SUCCESS);

 x1 = limit.x;
 y1 = limit.y;
 x2 = limit.x + limit.width;
 y2 = limit.y + limit.height;

 _cairo_matrix_transform_bounding_box (&matrix,
           &x1, &y1, &x2, &y2, NULL);

 limit.x = floor (x1);
 limit.y = floor (y1);
 limit.width  = ceil (x2) - limit.x;
 limit.height = ceil (y2) - limit.y;
    }
    extend = pattern->base.extend;
    if (_cairo_rectangle_contains_rectangle (&limit, extents))
 extend = CAIRO_EXTEND_NONE;
    if (extend == CAIRO_EXTEND_NONE && ! _cairo_rectangle_intersect (&limit, extents))
 return _cairo_xcb_transparent_picture ((cairo_xcb_surface_t *) target);

    /* Now draw the recording surface to an xcb surface */
    tmp = _cairo_surface_create_scratch (target,
                                         source->content,
                                         limit.width,
                                         limit.height,
                                         CAIRO_COLOR_TRANSPARENT);
    if (tmp->status != CAIRO_STATUS_SUCCESS) {
 return (cairo_xcb_picture_t *) tmp;
    }

    cairo_matrix_init_translate (&matrix, limit.x, limit.y);
    cairo_matrix_multiply (&matrix, &matrix, &pattern->base.matrix);

    status = _cairo_recording_surface_replay_with_clip (source,
       &matrix, tmp,
       NULL);
    if (unlikely (status)) {
 cairo_surface_destroy (tmp);
 return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
    }

    /* Now that we have drawn this to an xcb surface, try again with that */
    _cairo_pattern_init_static_copy (&tmp_pattern.base, &pattern->base);
    tmp_pattern.surface = tmp;
    cairo_matrix_init_translate (&tmp_pattern.base.matrix, -limit.x, -limit.y);

    picture = _copy_to_picture ((cairo_xcb_surface_t *) tmp);
    if (picture->base.status == CAIRO_STATUS_SUCCESS)
 _cairo_xcb_surface_setup_surface_picture (picture, &tmp_pattern, extents);
    cairo_surface_destroy (tmp);
    return picture;
}

static cairo_xcb_picture_t *
_cairo_xcb_surface_picture (cairo_xcb_surface_t *target,
       const cairo_surface_pattern_t *pattern,
       const cairo_rectangle_int_t *extents)
{
    cairo_surface_t *source = pattern->surface;
    cairo_xcb_picture_t *picture;

    picture = (cairo_xcb_picture_t *)
 _cairo_surface_has_snapshot (source, &_cairo_xcb_picture_backend);
    if (picture != NULL) {
 if (picture->screen == target->screen) {
     picture = (cairo_xcb_picture_t *) cairo_surface_reference (&picture->base);
     _cairo_xcb_surface_setup_surface_picture (picture, pattern, extents);
     return picture;
 }
 picture = NULL;
    }

    if (source->type == CAIRO_SURFACE_TYPE_XCB)
    {
 if (_cairo_surface_is_xcb(source)) {
     cairo_xcb_surface_t *xcb = (cairo_xcb_surface_t *) source;
     if (xcb->screen == target->screen && xcb->fallback == NULL) {
  picture = _copy_to_picture ((cairo_xcb_surface_t *) source);
  if (unlikely (picture->base.status))
      return picture;
     }
 } else if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
     cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
     cairo_xcb_surface_t *xcb = (cairo_xcb_surface_t *) sub->target;

     /* XXX repeat interval with source clipping? */
     if (FALSE && xcb->screen == target->screen && xcb->fallback == NULL) {
  xcb_rectangle_t rect;

  picture = _copy_to_picture (xcb);
  if (unlikely (picture->base.status))
      return picture;

  rect.x = sub->extents.x;
  rect.y = sub->extents.y;
  rect.width  = sub->extents.width;
  rect.height = sub->extents.height;

  _cairo_xcb_connection_render_set_picture_clip_rectangles (xcb->connection,
           picture->picture,
           0, 0,
           1, &rect);
  picture->x0 = rect.x;
  picture->y0 = rect.y;
  picture->width  = rect.width;
  picture->height = rect.height;
     }
 } else if (_cairo_surface_is_snapshot (source)) {
     cairo_surface_snapshot_t *snap = (cairo_surface_snapshot_t *) source;
     cairo_xcb_surface_t *xcb = (cairo_xcb_surface_t *) snap->target;

     if (xcb->screen == target->screen && xcb->fallback == NULL) {
  picture = _copy_to_picture (xcb);
  if (unlikely (picture->base.status))
      return picture;
     }
 }
    }
#if CAIRO_HAS_XLIB_XCB_FUNCTIONS
    else if (source->type == CAIRO_SURFACE_TYPE_XLIB)
    {
 if (source->backend->type == CAIRO_SURFACE_TYPE_XLIB) {
     cairo_xcb_surface_t *xcb = ((cairo_xlib_xcb_surface_t *) source)->xcb;
     if (xcb->screen == target->screen && xcb->fallback == NULL) {
  picture = _copy_to_picture (xcb);
  if (unlikely (picture->base.status))
      return picture;
     }
 } else if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
     cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
     cairo_xcb_surface_t *xcb = ((cairo_xlib_xcb_surface_t *) sub->target)->xcb;

     if (FALSE && xcb->screen == target->screen && xcb->fallback == NULL) {
  xcb_rectangle_t rect;

  picture = _copy_to_picture (xcb);
  if (unlikely (picture->base.status))
      return picture;

  rect.x = sub->extents.x;
  rect.y = sub->extents.y;
  rect.width  = sub->extents.width;
  rect.height = sub->extents.height;

  _cairo_xcb_connection_render_set_picture_clip_rectangles (xcb->connection,
           picture->picture,
           0, 0,
           1, &rect);
  picture->x0 = rect.x;
  picture->y0 = rect.y;
  picture->width  = rect.width;
  picture->height = rect.height;
     }
 } else if (_cairo_surface_is_snapshot (source)) {
     cairo_surface_snapshot_t *snap = (cairo_surface_snapshot_t *) source;
     cairo_xcb_surface_t *xcb = ((cairo_xlib_xcb_surface_t *) snap->target)->xcb;

     if (xcb->screen == target->screen && xcb->fallback == NULL) {
  picture = _copy_to_picture (xcb);
  if (unlikely (picture->base.status))
      return picture;
     }
 }
    }
#endif
    else if (source->type == CAIRO_SURFACE_TYPE_RECORDING)
    {
 /* We have to skip the call to attach_snapshot() because we possibly
 * only drew part of the recording surface.
 * TODO: When can we safely attach a snapshot?
 */

 return record_to_picture(&target->base, pattern, extents);
    }

    if (picture == NULL) {
 cairo_image_surface_t *image;
 void *image_extra;
 cairo_status_t status;

 status = _cairo_surface_acquire_source_image (source, &image, &image_extra);
 if (unlikely (status))
     return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);

 if (image->format != CAIRO_FORMAT_INVALID &&
     image->format < ARRAY_LENGTH (target->screen->connection->standard_formats)) {
     xcb_render_pictformat_t format;

     format = target->screen->connection->standard_formats[image->format];

     picture = _picture_from_image (target, format, image, NULL);
     _cairo_surface_release_source_image (source, image, image_extra);
 } else {
     cairo_image_surface_t *conv;
     xcb_render_pictformat_t render_format;

     /* XXX XRenderPutImage! */

     conv = _cairo_image_surface_coerce (image);
     _cairo_surface_release_source_image (source, image, image_extra);
     if (unlikely (conv->base.status))
  return (cairo_xcb_picture_t *) conv;

     render_format = target->screen->connection->standard_formats[conv->format];
     picture = _picture_from_image (target, render_format, conv, NULL);
     cairo_surface_destroy (&conv->base);
 }

 if (unlikely (picture->base.status))
     return picture;
    }

    /* XXX: This causes too many problems and bugs, let's skip it for now. */
#if 0
    _cairo_surface_attach_snapshot (source,
        &picture->base,
        NULL);
#endif

    _cairo_xcb_surface_setup_surface_picture (picture, pattern, extents);
    return picture;
}

static cairo_xcb_picture_t *
_cairo_xcb_picture_for_pattern (cairo_xcb_surface_t *target,
    const cairo_pattern_t *pattern,
    const cairo_rectangle_int_t *extents)
{
    if (pattern == NULL)
 return _cairo_xcb_white_picture (target);

    if (! _pattern_is_supported (target->connection->flags, pattern))
 return _render_to_picture (target, pattern, extents);

    switch (pattern->type) {
    case CAIRO_PATTERN_TYPE_SOLID:
 return _cairo_xcb_solid_picture (target, (cairo_solid_pattern_t *) pattern);

    case CAIRO_PATTERN_TYPE_LINEAR:
 return _cairo_xcb_linear_picture (target,
       (cairo_linear_pattern_t *) pattern,
       extents);

    case CAIRO_PATTERN_TYPE_RADIAL:
 return _cairo_xcb_radial_picture (target,
       (cairo_radial_pattern_t *) pattern,
       extents);

    case CAIRO_PATTERN_TYPE_SURFACE:
 return _cairo_xcb_surface_picture (target,
        (cairo_surface_pattern_t *) pattern,
        extents);
    default:
 ASSERT_NOT_REACHED;
    case CAIRO_PATTERN_TYPE_MESH:
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
 return _render_to_picture (target, pattern, extents);
    }
}

COMPILE_TIME_ASSERT (sizeof (xcb_rectangle_t) <= sizeof (cairo_box_t));

static cairo_status_t
_render_fill_boxes (void   *abstract_dst,
      cairo_operator_t   op,
      const cairo_color_t  *color,
      cairo_boxes_t  *boxes)
{
    cairo_xcb_surface_t *dst = abstract_dst;
    xcb_rectangle_t stack_xrects[CAIRO_STACK_ARRAY_LENGTH (xcb_rectangle_t)];
    xcb_rectangle_t *xrects = stack_xrects;
    xcb_render_color_t render_color;
    int render_op = _render_operator (op);
    struct _cairo_boxes_chunk *chunk;
    int max_count;

    render_color.red   = color->red_short;
    render_color.green = color->green_short;
    render_color.blue  = color->blue_short;
    render_color.alpha = color->alpha_short;

    max_count = 0;
    for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
 if (chunk->count > max_count)
     max_count = chunk->count;
    }
    if (max_count > ARRAY_LENGTH (stack_xrects)) {
 xrects = _cairo_malloc_ab (max_count, sizeof (xcb_rectangle_t));
 if (unlikely (xrects == NULL))
     return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    }

    for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
 int i, j;

 for (i = j = 0; i < chunk->count; i++) {
     int x1 = _cairo_fixed_integer_round_down (chunk->base[i].p1.x);
     int y1 = _cairo_fixed_integer_round_down (chunk->base[i].p1.y);
     int x2 = _cairo_fixed_integer_round_down (chunk->base[i].p2.x);
     int y2 = _cairo_fixed_integer_round_down (chunk->base[i].p2.y);

     if (x2 > x1 && y2 > y1) {
  xrects[j].x = x1;
  xrects[j].y = y1;
  xrects[j].width  = x2 - x1;
  xrects[j].height = y2 - y1;
  j++;
     }
 }

 if (j) {
     _cairo_xcb_connection_render_fill_rectangles
  (dst->connection,
   render_op, dst->picture,
   render_color, j, xrects);
 }
    }

    if (xrects != stack_xrects)
 free (xrects);

    return CAIRO_STATUS_SUCCESS;
}

/* pixel aligned, non-overlapping boxes */
static cairo_int_status_t
_render_composite_boxes (cairo_xcb_surface_t *dst,
    cairo_operator_t  op,
    const cairo_pattern_t *src_pattern,
    const cairo_pattern_t *mask_pattern,
    const cairo_rectangle_int_t *extents,
    const cairo_boxes_t *boxes)
{
    cairo_xcb_picture_t *src, *mask;
    const struct _cairo_boxes_chunk *chunk;
    xcb_rectangle_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (xcb_rectangle_t)];
    xcb_rectangle_t *clip_boxes;
    cairo_rectangle_int_t stack_extents;
    cairo_status_t status;
    int num_boxes;
    int render_op;

    render_op = _render_operator (op);

    if (src_pattern == NULL) {
 src_pattern = mask_pattern;
 mask_pattern = NULL;
    }

    /* amalgamate into a single Composite call by setting a clip region */
    clip_boxes = stack_boxes;
    if (boxes->num_boxes > ARRAY_LENGTH (stack_boxes)) {
 clip_boxes = _cairo_malloc_ab (boxes->num_boxes, sizeof (xcb_rectangle_t));
 if (unlikely (clip_boxes == NULL))
     return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    }

    src = _cairo_xcb_picture_for_pattern (dst, src_pattern, extents);
    status = src->base.status;
    if (unlikely (status))
 goto cleanup_boxes;

    num_boxes = 0;
    for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
 const cairo_box_t *box = chunk->base;
 int i;

 for (i = 0; i < chunk->count; i++) {
     int x = _cairo_fixed_integer_round_down (box[i].p1.x);
     int y = _cairo_fixed_integer_round_down (box[i].p1.y);
     int width  = _cairo_fixed_integer_round_down (box[i].p2.x) - x;
     int height = _cairo_fixed_integer_round_down (box[i].p2.y) - y;

     if (width && height) {
  clip_boxes[num_boxes].x = x;
  clip_boxes[num_boxes].y = y;
  clip_boxes[num_boxes].width = width;
  clip_boxes[num_boxes].height = height;
  num_boxes++;
     }
 }
    }

    if (num_boxes) {
 if (num_boxes > 1) {
     _cairo_xcb_connection_render_set_picture_clip_rectangles (dst->connection,
              dst->picture,
              0, 0,
              num_boxes,
              clip_boxes);
 } else {
     stack_extents.x = clip_boxes[0].x;
     stack_extents.y = clip_boxes[0].y;
     stack_extents.width  = clip_boxes[0].width;
     stack_extents.height = clip_boxes[0].height;
     extents = &stack_extents;
 }

 if (mask_pattern != NULL) {
     mask = _cairo_xcb_picture_for_pattern (dst, mask_pattern, extents);
     status = mask->base.status;
     if (unlikely (status))
  goto cleanup_clip;

     _cairo_xcb_connection_render_composite (dst->connection,
          render_op,
          src->picture,
          mask->picture,
          dst->picture,
          src->x + extents->x, src->y + extents->y,
          mask->x + extents->x, mask->y + extents->y,
          extents->x, extents->y,
          extents->width, extents->height);

     cairo_surface_destroy (&mask->base);
 } else {
     _cairo_xcb_connection_render_composite (dst->connection,
          render_op,
          src->picture,
          XCB_NONE,
          dst->picture,
          src->x + extents->x, src->y + extents->y,
          0, 0,
          extents->x, extents->y,
          extents->width, extents->height);
 }

cleanup_clip:

 if (num_boxes > 1)
     _cairo_xcb_surface_clear_clip_region (dst);
    }

    cairo_surface_destroy (&src->base);

cleanup_boxes:

    if (clip_boxes != stack_boxes)
 free (clip_boxes);

    return status;
}


#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,
       xcb_render_linefix_t *out)
{
    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));
}

typedef struct {
    cairo_traps_t traps;
    cairo_antialias_t antialias;
} composite_traps_info_t;

COMPILE_TIME_ASSERT (sizeof (xcb_render_trapezoid_t) <= sizeof (cairo_trapezoid_t));

static cairo_int_status_t
_composite_traps (void *closure,
    cairo_xcb_surface_t *dst,
    cairo_operator_t  op,
    const cairo_pattern_t *pattern,
    int dst_x, int dst_y,
    const cairo_rectangle_int_t *extents,
    cairo_clip_t  *clip)
{
    composite_traps_info_t *info = closure;
    const cairo_traps_t *traps = &info->traps;
    cairo_xcb_picture_t *src;
    cairo_format_t format;
    xcb_render_pictformat_t xrender_format;
    xcb_render_trapezoid_t *xtraps;
    int render_reference_x, render_reference_y;
    cairo_status_t status;
    int i;

    if (dst->deferred_clear) {
 status = _cairo_xcb_surface_clear (dst);
 if (unlikely (status))
  return status;
    }

    src = _cairo_xcb_picture_for_pattern (dst, pattern, extents);
    if (unlikely (src->base.status))
 return src->base.status;

    if (info->antialias == CAIRO_ANTIALIAS_NONE)
 format = CAIRO_FORMAT_A1;
    else
 format = CAIRO_FORMAT_A8;
    xrender_format = dst->screen->connection->standard_formats[format];

    xtraps = (xcb_render_trapezoid_t *) traps->traps;
    for (i = 0; i < traps->num_traps; i++) {
 cairo_trapezoid_t t = traps->traps[i];

 /* top/bottom will be clamped to surface bounds */
 xtraps[i].top = _cairo_fixed_to_16_16 (t.top);
 xtraps[i].top -= dst_y << 16;
 xtraps[i].bottom = _cairo_fixed_to_16_16 (t.bottom);
 xtraps[i].bottom -= dst_y << 16;

 /* 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,
     &xtraps[i].left);
     xtraps[i].left.p1.y = xtraps[i].top;
     xtraps[i].left.p2.y = xtraps[i].bottom;
 } else {
     xtraps[i].left.p1.x = _cairo_fixed_to_16_16 (t.left.p1.x);
     xtraps[i].left.p1.y = _cairo_fixed_to_16_16 (t.left.p1.y);
     xtraps[i].left.p2.x = _cairo_fixed_to_16_16 (t.left.p2.x);
     xtraps[i].left.p2.y = _cairo_fixed_to_16_16 (t.left.p2.y);
 }
 xtraps[i].left.p1.x -= dst_x << 16;
 xtraps[i].left.p1.y -= dst_y << 16;
 xtraps[i].left.p2.x -= dst_x << 16;
 xtraps[i].left.p2.y -= dst_y << 16;

 if (unlikely (_line_exceeds_16_16 (&t.right))) {
     _project_line_x_onto_16_16 (&t.right,
     t.top,
     t.bottom,
     &xtraps[i].right);
     xtraps[i].right.p1.y = xtraps[i].top;
     xtraps[i].right.p2.y = xtraps[i].bottom;
 } else {
     xtraps[i].right.p1.x = _cairo_fixed_to_16_16 (t.right.p1.x);
     xtraps[i].right.p1.y = _cairo_fixed_to_16_16 (t.right.p1.y);
     xtraps[i].right.p2.x = _cairo_fixed_to_16_16 (t.right.p2.x);
     xtraps[i].right.p2.y = _cairo_fixed_to_16_16 (t.right.p2.y);
 }
 xtraps[i].right.p1.x -= dst_x << 16;
 xtraps[i].right.p1.y -= dst_y << 16;
 xtraps[i].right.p2.x -= dst_x << 16;
 xtraps[i].right.p2.y -= dst_y << 16;
    }

    if (xtraps[0].left.p1.y < xtraps[0].left.p2.y) {
 render_reference_x = xtraps[0].left.p1.x >> 16;
 render_reference_y = xtraps[0].left.p1.y >> 16;
    } else {
 render_reference_x = xtraps[0].left.p2.x >> 16;
 render_reference_y = xtraps[0].left.p2.y >> 16;
    }
    render_reference_x += src->x + dst_x;
    render_reference_y += src->y + dst_y;

    _cairo_xcb_surface_set_precision (dst, info->antialias);
    _cairo_xcb_connection_render_trapezoids (dst->connection,
          _render_operator (op),
          src->picture,
          dst->picture,
          xrender_format,
          render_reference_x,
          render_reference_y,
          traps->num_traps, xtraps);

    cairo_surface_destroy (&src->base);

    return CAIRO_STATUS_SUCCESS;
}

/* low-level composite driver */

static cairo_xcb_surface_t *
get_clip_surface (const cairo_clip_t *clip,
    cairo_xcb_surface_t *target,
    int *tx, int *ty)
{
    cairo_surface_t *surface;
    cairo_status_t status;

    surface = _cairo_surface_create_scratch (&target->base,
         CAIRO_CONTENT_ALPHA,
         clip->extents.width,
         clip->extents.height,
         CAIRO_COLOR_WHITE);
    if (unlikely (surface->status))
 return (cairo_xcb_surface_t *) surface;

    assert (surface->backend == &_cairo_xcb_surface_backend);
    status = _cairo_clip_combine_with_surface (clip, surface,
            clip->extents.x, clip->extents.y);
    if (unlikely (status)) {
 cairo_surface_destroy (surface);
 surface = _cairo_surface_create_in_error (status);
    }

    *tx = clip->extents.x;
    *ty = clip->extents.y;

    return (cairo_xcb_surface_t *) surface;
}

typedef cairo_int_status_t
(*xcb_draw_func_t) (void    *closure,
      cairo_xcb_surface_t   *dst,
      cairo_operator_t    op,
      const cairo_pattern_t  *src,
      int      dst_x,
      int      dst_y,
      const cairo_rectangle_int_t  *extents,
      cairo_clip_t   *clip);

static void do_unaligned_row(void (*blt)(void *closure,
      int16_t x, int16_t y,
      int16_t w, int16_t h,
      uint16_t coverage),
        void *closure,
        const cairo_box_t *b,
        int tx, int y, int h,
        uint16_t coverage)
{
    int x1 = _cairo_fixed_integer_part (b->p1.x) - tx;
    int x2 = _cairo_fixed_integer_part (b->p2.x) - tx;
    if (x2 > x1) {
 if (! _cairo_fixed_is_integer (b->p1.x)) {
     blt(closure, x1, y, 1, h,
  coverage * (256 - _cairo_fixed_fractional_part (b->p1.x)));
     x1++;
 }

 if (x2 > x1)
     blt(closure, x1, y, x2-x1, h, (coverage << 8) - (coverage >> 8));

 if (! _cairo_fixed_is_integer (b->p2.x))
     blt(closure, x2, y, 1, h,
  coverage * _cairo_fixed_fractional_part (b->p2.x));
    } else
 blt(closure, x1, y, 1, h,
     coverage * (b->p2.x - b->p1.x));
}

static void do_unaligned_box(void (*blt)(void *closure,
      int16_t x, int16_t y,
      int16_t w, int16_t h,
      uint16_t coverage),
        void *closure,
        const cairo_box_t *b, int tx, int ty)
{
    int y1 = _cairo_fixed_integer_part (b->p1.y) - ty;
    int y2 = _cairo_fixed_integer_part (b->p2.y) - ty;
    if (y2 > y1) {
 if (! _cairo_fixed_is_integer (b->p1.y)) {
     do_unaligned_row(blt, closure, b, tx, y1, 1,
        256 - _cairo_fixed_fractional_part (b->p1.y));
     y1++;
 }

 if (y2 > y1)
     do_unaligned_row(blt, closure, b, tx, y1, y2-y1, 256);

 if (! _cairo_fixed_is_integer (b->p2.y))
     do_unaligned_row(blt, closure, b, tx, y2, 1,
        _cairo_fixed_fractional_part (b->p2.y));
    } else
 do_unaligned_row(blt, closure, b, tx, y1, 1,
    b->p2.y - b->p1.y);
}


static void blt_in(void *closure,
     int16_t x, int16_t y,
     int16_t w, int16_t h,
     uint16_t coverage)
{
    cairo_xcb_surface_t *mask = closure;
    xcb_render_color_t color;
    xcb_rectangle_t rect;

    if (coverage == 0xffff)
 return;

    color.red = color.green = color.blue = 0;
    color.alpha = coverage;

    rect.x = x;
    rect.y = y;
    rect.width  = w;
    rect.height = h;

    _cairo_xcb_connection_render_fill_rectangles (mask->connection,
        XCB_RENDER_PICT_OP_IN,
        mask->picture,
        color, 1, &rect);
}

static cairo_xcb_surface_t *
_create_composite_mask (cairo_clip_t  *clip,
   xcb_draw_func_t   draw_func,
   xcb_draw_func_t   mask_func,
   void   *draw_closure,
   cairo_xcb_surface_t *dst,
   const cairo_rectangle_int_t*extents)
{
    cairo_xcb_surface_t *surface;
    cairo_bool_t need_clip_combine;
    cairo_int_status_t status;

    surface = (cairo_xcb_surface_t *)
 _cairo_xcb_surface_create_similar (dst, CAIRO_CONTENT_ALPHA,
        extents->width, extents->height);
    if (unlikely (surface->base.status))
 return surface;

    _cairo_xcb_surface_ensure_picture (surface);

    surface->deferred_clear_color = *CAIRO_COLOR_TRANSPARENT;
    surface->deferred_clear = TRUE;
    surface->base.is_clear = TRUE;

    if (mask_func) {
 status = mask_func (draw_closure, surface,
       CAIRO_OPERATOR_ADD, NULL,
       extents->x, extents->y,
       extents, clip);
 if (likely (status != CAIRO_INT_STATUS_UNSUPPORTED))
     return surface;
    }

    /* Is it worth setting the clip region here? */
    status = draw_func (draw_closure, surface,
   CAIRO_OPERATOR_ADD, NULL,
   extents->x, extents->y,
   extents, NULL);
    if (unlikely (status)) {
 cairo_surface_destroy (&surface->base);
 return (cairo_xcb_surface_t *) _cairo_surface_create_in_error (status);
    }

    if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES) {
 int i;

 for (i = 0; i < clip->num_boxes; i++) {
     cairo_box_t *b = &clip->boxes[i];

     if (! _cairo_fixed_is_integer (b->p1.x) ||
  ! _cairo_fixed_is_integer (b->p1.y) ||
  ! _cairo_fixed_is_integer (b->p2.x) ||
  ! _cairo_fixed_is_integer (b->p2.y))
     {
  do_unaligned_box(blt_in, surface, b, extents->x, extents->y);
     }
 }

 need_clip_combine = clip->path != NULL;
    } else
 need_clip_combine = ! _cairo_clip_is_region (clip);

    if (need_clip_combine) {
 status = _cairo_clip_combine_with_surface (clip, &surface->base,
         extents->x, extents->y);
 if (unlikely (status)) {
     cairo_surface_destroy (&surface->base);
     return (cairo_xcb_surface_t *) _cairo_surface_create_in_error (status);
 }
    }

    return surface;
}

/* Handles compositing with a clip surface when the operator allows
 * us to combine the clip with the mask
 */

static cairo_status_t
_clip_and_composite_with_mask (cairo_clip_t  *clip,
          cairo_operator_t   op,
          const cairo_pattern_t *pattern,
          xcb_draw_func_t   draw_func,
          xcb_draw_func_t   mask_func,
          void   *draw_closure,
          cairo_xcb_surface_t *dst,
          const cairo_rectangle_int_t*extents)
{
    cairo_xcb_surface_t *mask;
    cairo_xcb_picture_t *src;

    mask = _create_composite_mask (clip,
       draw_func, mask_func, draw_closure,
       dst, extents);
    if (unlikely (mask->base.status))
 return mask->base.status;

    if (pattern != NULL || dst->base.content != CAIRO_CONTENT_ALPHA) {
 src = _cairo_xcb_picture_for_pattern (dst, pattern, extents);
 if (unlikely (src->base.status)) {
     cairo_surface_destroy (&mask->base);
     return src->base.status;
 }

 _cairo_xcb_connection_render_composite (dst->connection,
      _render_operator (op),
      src->picture,
      mask->picture,
      dst->picture,
      extents->x + src->x, extents->y + src->y,
      0, 0,
      extents->x,      extents->y,
      extents->width,  extents->height);

 cairo_surface_destroy (&src->base);
    } else {
 _cairo_xcb_connection_render_composite (dst->connection,
      _render_operator (op),
      mask->picture,
      XCB_NONE,
      dst->picture,
      0, 0,
      0, 0,
      extents->x,      extents->y,
      extents->width,  extents->height);
    }
    cairo_surface_destroy (&mask->base);

    return CAIRO_STATUS_SUCCESS;
}

/* Handles compositing with a clip surface when we have to do the operation
 * in two pieces and combine them together.
 */

static cairo_status_t
_clip_and_composite_combine (cairo_clip_t  *clip,
        cairo_operator_t   op,
        const cairo_pattern_t *pattern,
        xcb_draw_func_t   draw_func,
        void   *draw_closure,
        cairo_xcb_surface_t *dst,
        const cairo_rectangle_int_t*extents)
{
    cairo_xcb_surface_t *tmp;
    cairo_xcb_surface_t *clip_surface;
    int clip_x = 0, clip_y = 0;
    xcb_render_picture_t clip_picture;
    cairo_status_t status;

    tmp = (cairo_xcb_surface_t *)
 _cairo_xcb_surface_create_similar (dst, dst->base.content,
        extents->width, extents->height);
    if (unlikely (tmp->base.status))
 return tmp->base.status;

    /* create_similar() could have done a fallback to an image surface */
    assert (tmp->base.backend == &_cairo_xcb_surface_backend);

    _cairo_xcb_surface_ensure_picture (tmp);

    if (pattern == NULL) {
 status = (*draw_func) (draw_closure, tmp,
          CAIRO_OPERATOR_ADD, NULL,
          extents->x, extents->y,
          extents, NULL);
    } else {
 /* Initialize the temporary surface from the destination surface */
 if (! dst->base.is_clear ||
     (dst->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES) == 0)
 {
     /* XCopyArea may actually be quicker here.
     * A good driver should translate if appropriate.
     */

     _cairo_xcb_connection_render_composite (dst->connection,
          XCB_RENDER_PICT_OP_SRC,
          dst->picture,
          XCB_NONE,
          tmp->picture,
          extents->x,      extents->y,
          0, 0,
          0, 0,
          extents->width,  extents->height);
 }
 else
 {
     xcb_render_color_t clear;
     xcb_rectangle_t xrect;

     clear.red = clear.green = clear.blue = clear.alpha = 0;

     xrect.x = xrect.y = 0;
     xrect.width  = extents->width;
     xrect.height = extents->height;

     _cairo_xcb_connection_render_fill_rectangles (dst->connection,
         XCB_RENDER_PICT_OP_CLEAR,
         dst->picture,
         clear, 1, &xrect);
 }

 status = (*draw_func) (draw_closure, tmp, op, pattern,
          extents->x, extents->y,
          extents, NULL);
    }
    if (unlikely (status))
 goto CLEANUP_SURFACE;

    clip_surface = get_clip_surface (clip, dst, &clip_x, &clip_y);
    status = clip_surface->base.status;
    if (unlikely (status))
 goto CLEANUP_SURFACE;

    assert (clip_surface->base.backend == &_cairo_xcb_surface_backend);
    clip_picture = clip_surface->picture;
    assert (clip_picture != XCB_NONE);

    if (dst->base.is_clear) {
 _cairo_xcb_connection_render_composite (dst->connection,
      XCB_RENDER_PICT_OP_SRC,
      tmp->picture, clip_picture, dst->picture,
      0, 0,
      0, 0,
      extents->x,      extents->y,
      extents->width,  extents->height);
    } else {
 /* Punch the clip out of the destination */
 _cairo_xcb_connection_render_composite (dst->connection,
      XCB_RENDER_PICT_OP_OUT_REVERSE,
      clip_picture, XCB_NONE, dst->picture,
      extents->x - clip_x,
      extents->y - clip_y,
      0, 0,
      extents->x,     extents->y,
      extents->width, extents->height);

 /* Now add the two results together */
 _cairo_xcb_connection_render_composite (dst->connection,
      XCB_RENDER_PICT_OP_ADD,
      tmp->picture, clip_picture, dst->picture,
      0, 0,
      extents->x - clip_x,
      extents->y - clip_y,
      extents->x,     extents->y,
      extents->width, extents->height);
    }
    cairo_surface_destroy (&clip_surface->base);

 CLEANUP_SURFACE:
    cairo_surface_destroy (&tmp->base);

    return status;
}

/* Handles compositing for %CAIRO_OPERATOR_SOURCE, which is special; it's
 * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
 */

static cairo_status_t
_clip_and_composite_source (cairo_clip_t  *clip,
       const cairo_pattern_t *pattern,
       xcb_draw_func_t   draw_func,
       xcb_draw_func_t   mask_func,
       void   *draw_closure,
       cairo_xcb_surface_t  *dst,
       const cairo_rectangle_int_t *extents)
{
    cairo_xcb_surface_t *mask;
    cairo_xcb_picture_t *src;

    /* Create a surface that is mask IN clip */
    mask = _create_composite_mask (clip,
       draw_func, mask_func, draw_closure,
       dst, extents);
    if (unlikely (mask->base.status))
 return mask->base.status;

    src = _cairo_xcb_picture_for_pattern (dst, pattern, extents);
    if (unlikely (src->base.status)) {
 cairo_surface_destroy (&mask->base);
 return src->base.status;
    }

    if (dst->base.is_clear) {
 _cairo_xcb_connection_render_composite (dst->connection,
      XCB_RENDER_PICT_OP_SRC,
      src->picture,
      mask->picture,
      dst->picture,
      extents->x + src->x, extents->y + src->y,
      0, 0,
      extents->x,      extents->y,
      extents->width,  extents->height);
    } else {
 /* Compute dest' = dest OUT (mask IN clip) */
 _cairo_xcb_connection_render_composite (dst->connection,
      XCB_RENDER_PICT_OP_OUT_REVERSE,
      mask->picture,
      XCB_NONE,
      dst->picture,
      0, 0, 0, 0,
      extents->x,     extents->y,
      extents->width, extents->height);

 /* Now compute (src IN (mask IN clip)) ADD dest' */
 _cairo_xcb_connection_render_composite (dst->connection,
      XCB_RENDER_PICT_OP_ADD,
      src->picture,
      mask->picture,
      dst->picture,
      extents->x + src->x, extents->y + src->y,
      0, 0,
      extents->x,     extents->y,
      extents->width, extents->height);
    }

    cairo_surface_destroy (&src->base);
    cairo_surface_destroy (&mask->base);

    return CAIRO_STATUS_SUCCESS;
}

static cairo_bool_t
can_reduce_alpha_op (cairo_operator_t op)
{
    int iop = op;
    switch (iop) {
    case CAIRO_OPERATOR_OVER:
    case CAIRO_OPERATOR_SOURCE:
    case CAIRO_OPERATOR_ADD:
 return TRUE;
    default:
 return FALSE;
    }
}

static cairo_bool_t
reduce_alpha_op (cairo_surface_t *dst,
   cairo_operator_t op,
   const cairo_pattern_t *pattern)
{
    return dst->is_clear &&
    dst->content == CAIRO_CONTENT_ALPHA &&
    _cairo_pattern_is_opaque_solid (pattern) &&
    can_reduce_alpha_op (op);
}

static cairo_status_t
_cairo_xcb_surface_fixup_unbounded (cairo_xcb_surface_t *dst,
        const cairo_composite_rectangles_t *rects)
{
    xcb_rectangle_t xrects[4];
    int n;

    if (rects->bounded.width  == rects->unbounded.width &&
 rects->bounded.height == rects->unbounded.height)
    {
 return CAIRO_STATUS_SUCCESS;
    }

    n = 0;
    if (rects->bounded.width == 0 || rects->bounded.height == 0) {
 xrects[n].x = rects->unbounded.x;
 xrects[n].width = rects->unbounded.width;
 xrects[n].y = rects->unbounded.y;
 xrects[n].height = rects->unbounded.height;
 n++;
    } else {
 /* top */
 if (rects->bounded.y != rects->unbounded.y) {
     xrects[n].x = rects->unbounded.x;
     xrects[n].width = rects->unbounded.width;
     xrects[n].y = rects->unbounded.y;
     xrects[n].height = rects->bounded.y - rects->unbounded.y;
     n++;
 }
 /* left */
 if (rects->bounded.x != rects->unbounded.x) {
     xrects[n].x = rects->unbounded.x;
     xrects[n].width = rects->bounded.x - rects->unbounded.x;
     xrects[n].y = rects->bounded.y;
     xrects[n].height = rects->bounded.height;
     n++;
 }
 /* right */
 if (rects->bounded.x + rects->bounded.width != rects->unbounded.x + rects->unbounded.width) {
     xrects[n].x = rects->bounded.x + rects->bounded.width;
     xrects[n].width = rects->unbounded.x + rects->unbounded.width - xrects[n].x;
     xrects[n].y = rects->bounded.y;
     xrects[n].height = rects->bounded.height;
     n++;
 }
 /* bottom */
 if (rects->bounded.y + rects->bounded.height != rects->unbounded.y + rects->unbounded.height) {
     xrects[n].x = rects->unbounded.x;
     xrects[n].width = rects->unbounded.width;
     xrects[n].y = rects->bounded.y + rects->bounded.height;
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=99 H=95 G=96

¤ Dauer der Verarbeitung: 0.20 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.