Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* cairo - a vector graphics library with display and print output
  2.  *
  3.  * Copyright © 2009 Intel Corporation
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it either under the terms of the GNU Lesser General Public
  7.  * License version 2.1 as published by the Free Software Foundation
  8.  * (the "LGPL") or, at your option, under the terms of the Mozilla
  9.  * Public License Version 1.1 (the "MPL"). If you do not alter this
  10.  * notice, a recipient may use your version of this file under either
  11.  * the MPL or the LGPL.
  12.  *
  13.  * You should have received a copy of the LGPL along with this library
  14.  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
  15.  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
  16.  * You should have received a copy of the MPL along with this library
  17.  * in the file COPYING-MPL-1.1
  18.  *
  19.  * The contents of this file are subject to the Mozilla Public License
  20.  * Version 1.1 (the "License"); you may not use this file except in
  21.  * compliance with the License. You may obtain a copy of the License at
  22.  * http://www.mozilla.org/MPL/
  23.  *
  24.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
  25.  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
  26.  * the specific language governing rights and limitations.
  27.  *
  28.  * Contributor(s):
  29.  *      Chris Wilson <chris@chris-wilson.co.uk>
  30.  */
  31.  
  32. #include "cairoint.h"
  33.  
  34. #include "cairo-xcb-private.h"
  35.  
  36. #include "cairo-boxes-private.h"
  37. #include "cairo-clip-inline.h"
  38. #include "cairo-clip-private.h"
  39. #include "cairo-composite-rectangles-private.h"
  40. #include "cairo-image-surface-private.h"
  41. #include "cairo-list-inline.h"
  42. #include "cairo-region-private.h"
  43. #include "cairo-surface-offset-private.h"
  44. #include "cairo-surface-snapshot-inline.h"
  45. #include "cairo-surface-subsurface-private.h"
  46. #include "cairo-traps-private.h"
  47. #include "cairo-recording-surface-inline.h"
  48. #include "cairo-paginated-private.h"
  49. #include "cairo-pattern-inline.h"
  50.  
  51. #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
  52.  
  53. static cairo_status_t
  54. _clip_and_composite_boxes (cairo_xcb_surface_t *dst,
  55.                            cairo_operator_t op,
  56.                            const cairo_pattern_t *src,
  57.                            cairo_boxes_t *boxes,
  58.                            cairo_composite_rectangles_t *extents);
  59.  
  60. static inline cairo_xcb_connection_t *
  61. _picture_to_connection (cairo_xcb_picture_t *picture)
  62. {
  63.     return (cairo_xcb_connection_t *) picture->base.device;
  64. }
  65.  
  66. static void
  67. _cairo_xcb_surface_ensure_picture (cairo_xcb_surface_t *surface);
  68.  
  69. static uint32_t
  70. hars_petruska_f54_1_random (void)
  71. {
  72. #define rol(x,k) ((x << k) | (x >> (32-k)))
  73.     static uint32_t x;
  74.     return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
  75. #undef rol
  76. }
  77.  
  78. static cairo_status_t
  79. _cairo_xcb_picture_finish (void *abstract_surface)
  80. {
  81.     cairo_xcb_picture_t *surface = abstract_surface;
  82.     cairo_xcb_connection_t *connection = _picture_to_connection (surface);
  83.     cairo_status_t status;
  84.  
  85.     status = _cairo_xcb_connection_acquire (connection);
  86.     cairo_list_del (&surface->link);
  87.     if (unlikely (status))
  88.         return status;
  89.  
  90.     _cairo_xcb_connection_render_free_picture (connection, surface->picture);
  91.  
  92.     _cairo_xcb_connection_release (connection);
  93.  
  94.     return CAIRO_STATUS_SUCCESS;
  95. }
  96.  
  97. static const cairo_surface_backend_t _cairo_xcb_picture_backend = {
  98.     CAIRO_SURFACE_TYPE_XCB,
  99.     _cairo_xcb_picture_finish,
  100. };
  101.  
  102. static const struct xcb_render_transform_t identity_transform = {
  103.     1 << 16, 0, 0,
  104.     0, 1 << 16, 0,
  105.     0, 0, 1 << 16,
  106. };
  107.  
  108. static cairo_xcb_picture_t *
  109. _cairo_xcb_picture_create (cairo_xcb_screen_t *screen,
  110.                            pixman_format_code_t pixman_format,
  111.                            xcb_render_pictformat_t xrender_format,
  112.                            int width, int height)
  113. {
  114.     cairo_xcb_picture_t *surface;
  115.  
  116.     surface = malloc (sizeof (cairo_xcb_picture_t));
  117.     if (unlikely (surface == NULL))
  118.         return (cairo_xcb_picture_t *)
  119.             _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
  120.  
  121.     _cairo_surface_init (&surface->base,
  122.                          &_cairo_xcb_picture_backend,
  123.                          &screen->connection->device,
  124.                          _cairo_content_from_pixman_format (pixman_format));
  125.  
  126.     cairo_list_add (&surface->link, &screen->pictures);
  127.  
  128.     surface->screen = screen;
  129.     surface->picture = _cairo_xcb_connection_get_xid (screen->connection);
  130.     surface->pixman_format = pixman_format;
  131.     surface->xrender_format = xrender_format;
  132.  
  133.     surface->x0 = surface->y0 = 0;
  134.     surface->x = surface->y = 0;
  135.     surface->width = width;
  136.     surface->height = height;
  137.  
  138.     surface->transform = identity_transform;
  139.     surface->extend = CAIRO_EXTEND_NONE;
  140.     surface->filter = CAIRO_FILTER_NEAREST;
  141.     surface->has_component_alpha = FALSE;
  142.  
  143.     return surface;
  144. }
  145.  
  146. static inline cairo_bool_t
  147. _operator_is_supported (uint32_t flags, cairo_operator_t op)
  148. {
  149.     if (op <= CAIRO_OPERATOR_SATURATE)
  150.         return TRUE;
  151.  
  152.     /* Can we use PDF operators? */
  153. #if CAIRO_XCB_RENDER_AT_LEAST(0, 11)
  154.     if (op <= CAIRO_OPERATOR_HSL_LUMINOSITY)
  155.         return flags & CAIRO_XCB_RENDER_HAS_PDF_OPERATORS;
  156. #endif
  157.  
  158.     return FALSE;
  159. }
  160.  
  161. static int
  162. _render_operator (cairo_operator_t op)
  163. {
  164. #define C(x,y) case CAIRO_OPERATOR_##x: return XCB_RENDER_PICT_OP_##y
  165.     switch (op) {
  166.     C(CLEAR, CLEAR);
  167.     C(SOURCE, SRC);
  168.  
  169.     C(OVER, OVER);
  170.     C(IN, IN);
  171.     C(OUT, OUT);
  172.     C(ATOP, ATOP);
  173.  
  174.     C(DEST, DST);
  175.     C(DEST_OVER, OVER_REVERSE);
  176.     C(DEST_IN, IN_REVERSE);
  177.     C(DEST_OUT, OUT_REVERSE);
  178.     C(DEST_ATOP, ATOP_REVERSE);
  179.  
  180.     C(XOR, XOR);
  181.     C(ADD, ADD);
  182.     C(SATURATE, SATURATE);
  183.  
  184.     /* PDF operators were added in RENDER 0.11, check if the xcb headers have
  185.      * the defines, else fall through to the default case. */
  186. #if CAIRO_XCB_RENDER_AT_LEAST(0, 11)
  187. #define BLEND(x,y) C(x,y)
  188. #else
  189. #define BLEND(x,y) case CAIRO_OPERATOR_##x:
  190. #endif
  191.     BLEND(MULTIPLY, MULTIPLY);
  192.     BLEND(SCREEN, SCREEN);
  193.     BLEND(OVERLAY, OVERLAY);
  194.     BLEND(DARKEN, DARKEN);
  195.     BLEND(LIGHTEN, LIGHTEN);
  196.     BLEND(COLOR_DODGE, COLOR_DODGE);
  197.     BLEND(COLOR_BURN, COLOR_BURN);
  198.     BLEND(HARD_LIGHT, HARD_LIGHT);
  199.     BLEND(SOFT_LIGHT, SOFT_LIGHT);
  200.     BLEND(DIFFERENCE, DIFFERENCE);
  201.     BLEND(EXCLUSION, EXCLUSION);
  202.     BLEND(HSL_HUE, HSL_HUE);
  203.     BLEND(HSL_SATURATION, HSL_SATURATION);
  204.     BLEND(HSL_COLOR, HSL_COLOR);
  205.     BLEND(HSL_LUMINOSITY, HSL_LUMINOSITY);
  206.  
  207.     default:
  208.         ASSERT_NOT_REACHED;
  209.         return XCB_RENDER_PICT_OP_OVER;
  210.     }
  211. }
  212.  
  213. static cairo_status_t
  214. _cairo_xcb_surface_set_clip_region (cairo_xcb_surface_t *surface,
  215.                                     cairo_region_t      *region)
  216. {
  217.     xcb_rectangle_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (xcb_rectangle_t)];
  218.     xcb_rectangle_t *rects = stack_rects;
  219.     int i, num_rects;
  220.  
  221.     num_rects = cairo_region_num_rectangles (region);
  222.  
  223.     if (num_rects > ARRAY_LENGTH (stack_rects)) {
  224.         rects = _cairo_malloc_ab (num_rects, sizeof (xcb_rectangle_t));
  225.         if (unlikely (rects == NULL)) {
  226.             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  227.         }
  228.     }
  229.  
  230.     for (i = 0; i < num_rects; i++) {
  231.         cairo_rectangle_int_t rect;
  232.  
  233.         cairo_region_get_rectangle (region, i, &rect);
  234.  
  235.         rects[i].x = rect.x;
  236.         rects[i].y = rect.y;
  237.         rects[i].width  = rect.width;
  238.         rects[i].height = rect.height;
  239.     }
  240.  
  241.     _cairo_xcb_connection_render_set_picture_clip_rectangles (surface->connection,
  242.                                                               surface->picture,
  243.                                                               0, 0,
  244.                                                               num_rects, rects);
  245.  
  246.     if (rects != stack_rects)
  247.         free (rects);
  248.  
  249.     return CAIRO_STATUS_SUCCESS;
  250. }
  251.  
  252. static void
  253. _cairo_xcb_surface_clear_clip_region (cairo_xcb_surface_t *surface)
  254. {
  255.     uint32_t values[] = { XCB_NONE };
  256.     _cairo_xcb_connection_render_change_picture (surface->connection,
  257.                                                  surface->picture,
  258.                                                  XCB_RENDER_CP_CLIP_MASK,
  259.                                                  values);
  260. }
  261.  
  262. static void
  263. _cairo_xcb_surface_set_precision (cairo_xcb_surface_t   *surface,
  264.                                   cairo_antialias_t      antialias)
  265. {
  266.     cairo_xcb_connection_t *connection = surface->connection;
  267.     uint32_t precision;
  268.  
  269.     if (connection->force_precision != -1)
  270.             precision = connection->force_precision;
  271.     else switch (antialias) {
  272.     default:
  273.     case CAIRO_ANTIALIAS_DEFAULT:
  274.     case CAIRO_ANTIALIAS_GRAY:
  275.     case CAIRO_ANTIALIAS_NONE:
  276.     case CAIRO_ANTIALIAS_FAST:
  277.     case CAIRO_ANTIALIAS_GOOD:
  278.         precision = XCB_RENDER_POLY_MODE_IMPRECISE;
  279.         break;
  280.     case CAIRO_ANTIALIAS_SUBPIXEL:
  281.     case CAIRO_ANTIALIAS_BEST:
  282.         precision = XCB_RENDER_POLY_MODE_PRECISE;
  283.         break;
  284.     }
  285.  
  286.     if (surface->precision != precision) {
  287.         _cairo_xcb_connection_render_change_picture (connection,
  288.                                                      surface->picture,
  289.                                                      XCB_RENDER_CP_POLY_MODE,
  290.                                                      &precision);
  291.         surface->precision = precision;
  292.     }
  293. }
  294.  
  295.  
  296. static void
  297. _cairo_xcb_surface_ensure_picture (cairo_xcb_surface_t *surface)
  298. {
  299.     assert (surface->fallback == NULL);
  300.     if (surface->picture == XCB_NONE) {
  301.         uint32_t values[1];
  302.         uint32_t flags = 0;
  303.  
  304.         if (surface->precision != XCB_RENDER_POLY_MODE_PRECISE) {
  305.             flags |= XCB_RENDER_CP_POLY_MODE;
  306.             values[0] = surface->precision;
  307.         }
  308.  
  309.         surface->picture = _cairo_xcb_connection_get_xid (surface->connection);
  310.         _cairo_xcb_connection_render_create_picture (surface->connection,
  311.                                                      surface->picture,
  312.                                                      surface->drawable,
  313.                                                      surface->xrender_format,
  314.                                                      flags, values);
  315.     }
  316. }
  317.  
  318. static cairo_xcb_picture_t *
  319. _picture_from_image (cairo_xcb_surface_t *target,
  320.                      xcb_render_pictformat_t format,
  321.                      cairo_image_surface_t *image,
  322.                      cairo_xcb_shm_info_t *shm_info)
  323. {
  324.     xcb_pixmap_t pixmap;
  325.     xcb_gcontext_t gc;
  326.     cairo_xcb_picture_t *picture;
  327.  
  328.     pixmap = _cairo_xcb_connection_create_pixmap (target->connection,
  329.                                                   image->depth,
  330.                                                   target->drawable,
  331.                                                   image->width, image->height);
  332.  
  333.     gc = _cairo_xcb_screen_get_gc (target->screen, pixmap, image->depth);
  334.  
  335.     if (shm_info != NULL) {
  336.         _cairo_xcb_connection_shm_put_image (target->connection,
  337.                                              pixmap, gc,
  338.                                              image->width, image->height,
  339.                                              0, 0,
  340.                                              image->width, image->height,
  341.                                              0, 0,
  342.                                              image->depth,
  343.                                              shm_info->shm,
  344.                                              shm_info->offset);
  345.     } else {
  346.         int len;
  347.  
  348.         /* Do we need to trim the image? */
  349.         len = CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format));
  350.         if (len == image->stride) {
  351.             _cairo_xcb_connection_put_image (target->connection,
  352.                                              pixmap, gc,
  353.                                              image->width, image->height,
  354.                                              0, 0,
  355.                                              image->depth,
  356.                                              image->stride,
  357.                                              image->data);
  358.         } else {
  359.             _cairo_xcb_connection_put_subimage (target->connection,
  360.                                                 pixmap, gc,
  361.                                                 0, 0,
  362.                                                 image->width, image->height,
  363.                                                 PIXMAN_FORMAT_BPP (image->pixman_format) / 8,
  364.                                                 image->stride,
  365.                                                 0, 0,
  366.                                                 image->depth,
  367.                                                 image->data);
  368.  
  369.         }
  370.     }
  371.  
  372.     _cairo_xcb_screen_put_gc (target->screen, image->depth, gc);
  373.  
  374.     picture = _cairo_xcb_picture_create (target->screen,
  375.                                          image->pixman_format, format,
  376.                                          image->width, image->height);
  377.     if (likely (picture->base.status == CAIRO_STATUS_SUCCESS)) {
  378.         _cairo_xcb_connection_render_create_picture (target->connection,
  379.                                                      picture->picture, pixmap, format,
  380.                                                      0, 0);
  381.     }
  382.  
  383.     _cairo_xcb_connection_free_pixmap (target->connection, pixmap);
  384.  
  385.     return picture;
  386. }
  387.  
  388. static cairo_bool_t
  389. _pattern_is_supported (uint32_t flags,
  390.                        const cairo_pattern_t *pattern)
  391.  
  392. {
  393.     if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
  394.         return TRUE;
  395.  
  396.     if (! _cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL)) {
  397.         if ((flags & CAIRO_XCB_RENDER_HAS_PICTURE_TRANSFORM) == 0)
  398.             return FALSE;
  399.     }
  400.  
  401.     switch (pattern->extend) {
  402.     default:
  403.         ASSERT_NOT_REACHED;
  404.     case CAIRO_EXTEND_NONE:
  405.     case CAIRO_EXTEND_REPEAT:
  406.         break;
  407.     case CAIRO_EXTEND_PAD:
  408.     case CAIRO_EXTEND_REFLECT:
  409.         if ((flags & CAIRO_XCB_RENDER_HAS_EXTENDED_REPEAT) == 0)
  410.             return FALSE;
  411.     }
  412.  
  413.     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
  414.         cairo_filter_t filter;
  415.  
  416.         filter = pattern->filter;
  417.         if (_cairo_matrix_has_unity_scale (&pattern->matrix) &&
  418.             _cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL))
  419.         {
  420.             filter = CAIRO_FILTER_NEAREST;
  421.         }
  422.  
  423.         if (! (filter == CAIRO_FILTER_NEAREST || filter == CAIRO_FILTER_FAST)) {
  424.             if ((flags & CAIRO_XCB_RENDER_HAS_FILTERS) == 0)
  425.                 return FALSE;
  426.         }
  427.     } else { /* gradient */
  428.         if ((flags & CAIRO_XCB_RENDER_HAS_GRADIENTS) == 0)
  429.             return FALSE;
  430.  
  431.         /* The RENDER specification says that the inner circle has to be
  432.          * completely contained inside the outer one. */
  433.         if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL &&
  434.             ! _cairo_radial_pattern_focus_is_inside ((cairo_radial_pattern_t *) pattern))
  435.         {
  436.             return FALSE;
  437.         }
  438.     }
  439.  
  440.     return pattern->type != CAIRO_PATTERN_TYPE_MESH;
  441. }
  442.  
  443. static void
  444. _cairo_xcb_picture_set_matrix (cairo_xcb_picture_t *picture,
  445.                                const cairo_matrix_t *matrix,
  446.                                cairo_filter_t filter,
  447.                                double xc, double yc)
  448. {
  449.     xcb_render_transform_t transform;
  450.     pixman_transform_t *pixman_transform;
  451.     cairo_int_status_t ignored;
  452.  
  453.     /* Casting between pixman_transform_t and xcb_render_transform_t is safe
  454.      * because they happen to be the exact same type.
  455.      */
  456.     pixman_transform = (pixman_transform_t *) &transform;
  457.  
  458.     picture->x = picture->x0;
  459.     picture->y = picture->y0;
  460.     ignored = _cairo_matrix_to_pixman_matrix_offset (matrix, filter, xc, yc,
  461.                                                      pixman_transform,
  462.                                                      &picture->x, &picture->y);
  463.     (void) ignored;
  464.  
  465.     if (memcmp (&picture->transform, &transform, sizeof (xcb_render_transform_t))) {
  466.         _cairo_xcb_connection_render_set_picture_transform (_picture_to_connection (picture),
  467.                                                             picture->picture,
  468.                                                             &transform);
  469.  
  470.         picture->transform = transform;
  471.     }
  472. }
  473.  
  474. static void
  475. _cairo_xcb_picture_set_filter (cairo_xcb_picture_t *picture,
  476.                                cairo_filter_t filter)
  477. {
  478.     const char *render_filter;
  479.     int len;
  480.  
  481.     if (picture->filter == filter)
  482.         return;
  483.  
  484.     switch (filter) {
  485.     case CAIRO_FILTER_FAST:
  486.         render_filter = "fast";
  487.         len = strlen ("fast");
  488.         break;
  489.  
  490.     case CAIRO_FILTER_GOOD:
  491.         render_filter = "good";
  492.         len = strlen ("good");
  493.         break;
  494.  
  495.     case CAIRO_FILTER_BEST:
  496.         render_filter = "best";
  497.         len = strlen ("best");
  498.         break;
  499.  
  500.     case CAIRO_FILTER_NEAREST:
  501.         render_filter = "nearest";
  502.         len = strlen ("nearest");
  503.         break;
  504.  
  505.     case CAIRO_FILTER_BILINEAR:
  506.         render_filter = "bilinear";
  507.         len = strlen ("bilinear");
  508.         break;
  509.  
  510.     default:
  511.         ASSERT_NOT_REACHED;
  512.     case CAIRO_FILTER_GAUSSIAN:
  513.         render_filter = "best";
  514.         len = strlen ("best");
  515.         break;
  516.     }
  517.  
  518.     _cairo_xcb_connection_render_set_picture_filter (_picture_to_connection (picture),
  519.                                                      picture->picture,
  520.                                                      len, (char *) render_filter);
  521.     picture->filter = filter;
  522. }
  523.  
  524. static void
  525. _cairo_xcb_picture_set_extend (cairo_xcb_picture_t *picture,
  526.                                cairo_extend_t extend)
  527. {
  528.     uint32_t pa[1];
  529.  
  530.     if (picture->extend == extend)
  531.         return;
  532.  
  533.     switch (extend) {
  534.     default:
  535.         ASSERT_NOT_REACHED;
  536.     case CAIRO_EXTEND_NONE:
  537.         pa[0] = XCB_RENDER_REPEAT_NONE;
  538.         break;
  539.  
  540.     case CAIRO_EXTEND_REPEAT:
  541.         pa[0] = XCB_RENDER_REPEAT_NORMAL;
  542.         break;
  543.  
  544.     case CAIRO_EXTEND_REFLECT:
  545.         pa[0] = XCB_RENDER_REPEAT_REFLECT;
  546.         break;
  547.  
  548.     case CAIRO_EXTEND_PAD:
  549.         pa[0] = XCB_RENDER_REPEAT_PAD;
  550.         break;
  551.     }
  552.  
  553.     _cairo_xcb_connection_render_change_picture (_picture_to_connection (picture),
  554.                                                  picture->picture,
  555.                                                  XCB_RENDER_CP_REPEAT, pa);
  556.     picture->extend = extend;
  557. }
  558.  
  559. static void
  560. _cairo_xcb_picture_set_component_alpha (cairo_xcb_picture_t *picture,
  561.                                         cairo_bool_t ca)
  562. {
  563.     uint32_t pa[1];
  564.  
  565.     if (picture->has_component_alpha == ca)
  566.         return;
  567.  
  568.     pa[0] = ca;
  569.  
  570.     _cairo_xcb_connection_render_change_picture (_picture_to_connection (picture),
  571.                                                  picture->picture,
  572.                                                  XCB_RENDER_CP_COMPONENT_ALPHA,
  573.                                                  pa);
  574.     picture->has_component_alpha = ca;
  575. }
  576.  
  577. static cairo_xcb_picture_t *
  578. _solid_picture (cairo_xcb_surface_t *target,
  579.                 const cairo_color_t *color)
  580. {
  581.     xcb_render_color_t xcb_color;
  582.     xcb_render_pictformat_t xrender_format;
  583.     cairo_xcb_picture_t *picture;
  584.  
  585.     xcb_color.red   = color->red_short;
  586.     xcb_color.green = color->green_short;
  587.     xcb_color.blue  = color->blue_short;
  588.     xcb_color.alpha = color->alpha_short;
  589.  
  590.     xrender_format = target->screen->connection->standard_formats[CAIRO_FORMAT_ARGB32];
  591.     picture = _cairo_xcb_picture_create (target->screen,
  592.                                          PIXMAN_a8r8g8b8,
  593.                                          xrender_format,
  594.                                          -1, -1);
  595.     if (unlikely (picture->base.status))
  596.         return picture;
  597.  
  598.     if (target->connection->flags & CAIRO_XCB_RENDER_HAS_GRADIENTS) {
  599.         _cairo_xcb_connection_render_create_solid_fill (target->connection,
  600.                                                         picture->picture,
  601.                                                         xcb_color);
  602.     } else {
  603.         xcb_pixmap_t pixmap;
  604.         uint32_t values[] = { XCB_RENDER_REPEAT_NORMAL };
  605.  
  606.         pixmap = _cairo_xcb_connection_create_pixmap (target->connection,
  607.                                                       32, target->drawable, 1, 1);
  608.         _cairo_xcb_connection_render_create_picture (target->connection,
  609.                                                      picture->picture,
  610.                                                      pixmap,
  611.                                                      xrender_format,
  612.                                                      XCB_RENDER_CP_REPEAT,
  613.                                                      values);
  614.         if (target->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES) {
  615.             xcb_rectangle_t rect;
  616.  
  617.             rect.x = rect.y = 0;
  618.             rect.width = rect.height = 1;
  619.  
  620.             _cairo_xcb_connection_render_fill_rectangles (_picture_to_connection (picture),
  621.                                                           XCB_RENDER_PICT_OP_SRC,
  622.                                                           picture->picture,
  623.                                                           xcb_color, 1, &rect);
  624.         } else {
  625.             xcb_gcontext_t gc;
  626.             uint32_t pixel;
  627.  
  628.             gc = _cairo_xcb_screen_get_gc (target->screen, pixmap, 32);
  629.  
  630.             /* XXX byte ordering? */
  631.             pixel = ((color->alpha_short >> 8) << 24) |
  632.                     ((color->red_short   >> 8) << 16) |
  633.                     ((color->green_short >> 8) << 8) |
  634.                     ((color->blue_short  >> 8) << 0);
  635.  
  636.             _cairo_xcb_connection_put_image (target->connection,
  637.                                              pixmap, gc,
  638.                                              1, 1, 0, 0,
  639.                                              32, 4, &pixel);
  640.  
  641.             _cairo_xcb_screen_put_gc (target->screen, 32, gc);
  642.         }
  643.  
  644.         _cairo_xcb_connection_free_pixmap (target->connection, pixmap);
  645.     }
  646.  
  647.     return picture;
  648. }
  649.  
  650. static cairo_xcb_picture_t *
  651. _cairo_xcb_transparent_picture (cairo_xcb_surface_t *target)
  652. {
  653.     cairo_xcb_picture_t *picture;
  654.  
  655.     picture = (cairo_xcb_picture_t *) target->screen->stock_colors[CAIRO_STOCK_TRANSPARENT];
  656.     if (picture == NULL) {
  657.         picture = _solid_picture (target, CAIRO_COLOR_TRANSPARENT);
  658.         target->screen->stock_colors[CAIRO_STOCK_TRANSPARENT] = &picture->base;
  659.     }
  660.  
  661.     return (cairo_xcb_picture_t *) cairo_surface_reference (&picture->base);
  662. }
  663.  
  664. static cairo_xcb_picture_t *
  665. _cairo_xcb_black_picture (cairo_xcb_surface_t *target)
  666. {
  667.     cairo_xcb_picture_t *picture;
  668.  
  669.     picture = (cairo_xcb_picture_t *) target->screen->stock_colors[CAIRO_STOCK_BLACK];
  670.     if (picture == NULL) {
  671.         picture = _solid_picture (target, CAIRO_COLOR_BLACK);
  672.         target->screen->stock_colors[CAIRO_STOCK_BLACK] = &picture->base;
  673.     }
  674.  
  675.     return (cairo_xcb_picture_t *) cairo_surface_reference (&picture->base);
  676. }
  677.  
  678. static cairo_xcb_picture_t *
  679. _cairo_xcb_white_picture (cairo_xcb_surface_t *target)
  680. {
  681.     cairo_xcb_picture_t *picture;
  682.  
  683.     picture = (cairo_xcb_picture_t *) target->screen->stock_colors[CAIRO_STOCK_WHITE];
  684.     if (picture == NULL) {
  685.         picture = _solid_picture (target, CAIRO_COLOR_WHITE);
  686.         target->screen->stock_colors[CAIRO_STOCK_WHITE] = &picture->base;
  687.     }
  688.  
  689.     return (cairo_xcb_picture_t *) cairo_surface_reference (&picture->base);
  690. }
  691.  
  692. static cairo_xcb_picture_t *
  693. _cairo_xcb_solid_picture (cairo_xcb_surface_t *target,
  694.                           const cairo_solid_pattern_t *pattern)
  695. {
  696.     cairo_xcb_picture_t *picture;
  697.     cairo_xcb_screen_t *screen;
  698.     int i, n_cached;
  699.  
  700.     if (pattern->color.alpha_short <= 0x00ff)
  701.         return _cairo_xcb_transparent_picture (target);
  702.  
  703.     if (pattern->color.alpha_short >= 0xff00) {
  704.         if (pattern->color.red_short <= 0x00ff &&
  705.             pattern->color.green_short <= 0x00ff &&
  706.             pattern->color.blue_short <= 0x00ff)
  707.         {
  708.             return _cairo_xcb_black_picture (target);
  709.         }
  710.  
  711.         if (pattern->color.red_short >= 0xff00 &&
  712.             pattern->color.green_short >= 0xff00 &&
  713.             pattern->color.blue_short >= 0xff00)
  714.         {
  715.             return _cairo_xcb_white_picture (target);
  716.         }
  717.     }
  718.  
  719.     screen = target->screen;
  720.     n_cached = screen->solid_cache_size;
  721.     for (i = 0; i < n_cached; i++) {
  722.         if (_cairo_color_equal (&screen->solid_cache[i].color, &pattern->color)) {
  723.             return (cairo_xcb_picture_t *) cairo_surface_reference (screen->solid_cache[i].picture);
  724.         }
  725.     }
  726.  
  727.     picture = _solid_picture (target, &pattern->color);
  728.     if (unlikely (picture->base.status))
  729.         return picture;
  730.  
  731.     if (screen->solid_cache_size < ARRAY_LENGTH (screen->solid_cache)) {
  732.         i = screen->solid_cache_size++;
  733.     } else {
  734.         i = hars_petruska_f54_1_random () % ARRAY_LENGTH (screen->solid_cache);
  735.         cairo_surface_destroy (screen->solid_cache[i].picture);
  736.     }
  737.     screen->solid_cache[i].picture = cairo_surface_reference (&picture->base);
  738.     screen->solid_cache[i].color = pattern->color;
  739.  
  740.     return picture;
  741. }
  742.  
  743. static cairo_xcb_picture_t *
  744. _render_to_picture (cairo_xcb_surface_t *target,
  745.                     const cairo_pattern_t *pattern,
  746.                     const cairo_rectangle_int_t *extents)
  747. {
  748.     cairo_image_surface_t *image;
  749.     cairo_xcb_shm_info_t *shm_info;
  750.     cairo_pattern_union_t copy;
  751.     cairo_status_t status;
  752.     cairo_xcb_picture_t *picture;
  753.     pixman_format_code_t pixman_format;
  754.     xcb_render_pictformat_t xrender_format;
  755.  
  756.     /* XXX handle extend modes via tiling? */
  757.     /* XXX alpha-only masks? */
  758.  
  759.     pixman_format = PIXMAN_a8r8g8b8;
  760.     xrender_format = target->screen->connection->standard_formats[CAIRO_FORMAT_ARGB32];
  761.  
  762.     status = _cairo_xcb_shm_image_create (target->screen->connection,
  763.                                           pixman_format,
  764.                                           extents->width, extents->height,
  765.                                           &image, &shm_info);
  766.     if (unlikely (status))
  767.         return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
  768.  
  769.     _cairo_pattern_init_static_copy (&copy.base, pattern);
  770.     cairo_matrix_translate (&copy.base.matrix, extents->x, extents->y);
  771.     status = _cairo_surface_paint (&image->base,
  772.                                    CAIRO_OPERATOR_SOURCE,
  773.                                    &copy.base,
  774.                                    NULL);
  775.     if (unlikely (status)) {
  776.         cairo_surface_destroy (&image->base);
  777.         return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
  778.     }
  779.  
  780.     picture = _picture_from_image (target, xrender_format, image, shm_info);
  781.     cairo_surface_destroy (&image->base);
  782.  
  783.     if (unlikely (picture->base.status))
  784.         return picture;
  785.  
  786.     _cairo_xcb_picture_set_component_alpha (picture, pattern->has_component_alpha);
  787.     picture->x = -extents->x;
  788.     picture->y = -extents->y;
  789.  
  790.     return picture;
  791. }
  792.  
  793. static xcb_render_fixed_t *
  794. _gradient_to_xcb (const cairo_gradient_pattern_t *gradient,
  795.                   unsigned int *n_stops,
  796.                   char *buf, unsigned int buflen)
  797. {
  798.     xcb_render_fixed_t *stops;
  799.     xcb_render_color_t *colors;
  800.     unsigned int i;
  801.  
  802.     assert (gradient->n_stops > 0);
  803.     *n_stops = MAX (gradient->n_stops, 2);
  804.  
  805.     if (*n_stops * (sizeof (xcb_render_fixed_t) + sizeof (xcb_render_color_t)) < buflen)
  806.     {
  807.         stops = (xcb_render_fixed_t *) buf;
  808.     }
  809.     else
  810.     {
  811.         stops =
  812.             _cairo_malloc_ab (*n_stops,
  813.                               sizeof (xcb_render_fixed_t) + sizeof (xcb_render_color_t));
  814.         if (unlikely (stops == NULL))
  815.             return NULL;
  816.     }
  817.  
  818.     colors = (xcb_render_color_t *) (stops + *n_stops);
  819.     for (i = 0; i < gradient->n_stops; i++) {
  820.         stops[i] =
  821.             _cairo_fixed_16_16_from_double (gradient->stops[i].offset);
  822.  
  823.         colors[i].red   = gradient->stops[i].color.red_short;
  824.         colors[i].green = gradient->stops[i].color.green_short;
  825.         colors[i].blue  = gradient->stops[i].color.blue_short;
  826.         colors[i].alpha = gradient->stops[i].color.alpha_short;
  827.     }
  828.  
  829.     /* RENDER does not support gradients with less than 2 stops. If a
  830.      * gradient has only a single stop, duplicate it to make RENDER
  831.      * happy. */
  832.     if (gradient->n_stops == 1) {
  833.         stops[1] = _cairo_fixed_16_16_from_double (gradient->stops[0].offset);
  834.  
  835.         colors[1].red   = gradient->stops[0].color.red_short;
  836.         colors[1].green = gradient->stops[0].color.green_short;
  837.         colors[1].blue  = gradient->stops[0].color.blue_short;
  838.         colors[1].alpha = gradient->stops[0].color.alpha_short;
  839.     }
  840.  
  841.     return stops;
  842. }
  843.  
  844. static cairo_xcb_picture_t *
  845. _cairo_xcb_linear_picture (cairo_xcb_surface_t *target,
  846.                            const cairo_linear_pattern_t *pattern,
  847.                            const cairo_rectangle_int_t *extents)
  848. {
  849.     char buf[CAIRO_STACK_BUFFER_SIZE];
  850.     xcb_render_fixed_t *stops;
  851.     xcb_render_color_t *colors;
  852.     xcb_render_pointfix_t p1, p2;
  853.     cairo_matrix_t matrix;
  854.     cairo_circle_double_t extremes[2];
  855.     cairo_xcb_picture_t *picture;
  856.     cairo_status_t status;
  857.     unsigned int n_stops;
  858.  
  859.     _cairo_gradient_pattern_fit_to_range (&pattern->base, PIXMAN_MAX_INT >> 1, &matrix, extremes);
  860.  
  861.     picture = (cairo_xcb_picture_t *)
  862.         _cairo_xcb_screen_lookup_linear_picture (target->screen, pattern);
  863.     if (picture != NULL)
  864.         goto setup_picture;
  865.  
  866.     stops = _gradient_to_xcb (&pattern->base, &n_stops, buf, sizeof (buf));
  867.     if (unlikely (stops == NULL))
  868.         return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
  869.  
  870.     picture = _cairo_xcb_picture_create (target->screen,
  871.                                          target->screen->connection->standard_formats[CAIRO_FORMAT_ARGB32],
  872.                                          PIXMAN_a8r8g8b8,
  873.                                          -1, -1);
  874.     if (unlikely (picture->base.status)) {
  875.         if (stops != (xcb_render_fixed_t *) buf)
  876.             free (stops);
  877.         return picture;
  878.     }
  879.     picture->filter = CAIRO_FILTER_DEFAULT;
  880.  
  881.     colors = (xcb_render_color_t *) (stops + n_stops);
  882.  
  883.     p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
  884.     p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
  885.     p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
  886.     p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
  887.  
  888.     _cairo_xcb_connection_render_create_linear_gradient (target->connection,
  889.                                                          picture->picture,
  890.                                                          p1, p2,
  891.                                                          n_stops,
  892.                                                          stops, colors);
  893.  
  894.     if (stops != (xcb_render_fixed_t *) buf)
  895.         free (stops);
  896.  
  897.     status = _cairo_xcb_screen_store_linear_picture (target->screen,
  898.                                                      pattern,
  899.                                                      &picture->base);
  900.     if (unlikely (status)) {
  901.         cairo_surface_destroy (&picture->base);
  902.         return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
  903.     }
  904.  
  905. setup_picture:
  906.     _cairo_xcb_picture_set_matrix (picture, &matrix,
  907.                                    pattern->base.base.filter,
  908.                                    extents->x + extents->width/2.,
  909.                                    extents->y + extents->height/2.);
  910.     _cairo_xcb_picture_set_filter (picture, pattern->base.base.filter);
  911.     _cairo_xcb_picture_set_extend (picture, pattern->base.base.extend);
  912.     _cairo_xcb_picture_set_component_alpha (picture,
  913.                                             pattern->base.base.has_component_alpha);
  914.  
  915.     return picture;
  916. }
  917.  
  918. static cairo_xcb_picture_t *
  919. _cairo_xcb_radial_picture (cairo_xcb_surface_t *target,
  920.                            const cairo_radial_pattern_t *pattern,
  921.                            const cairo_rectangle_int_t *extents)
  922. {
  923.     char buf[CAIRO_STACK_BUFFER_SIZE];
  924.     xcb_render_fixed_t *stops;
  925.     xcb_render_color_t *colors;
  926.     xcb_render_pointfix_t p1, p2;
  927.     xcb_render_fixed_t r1, r2;
  928.     cairo_matrix_t matrix;
  929.     cairo_circle_double_t extremes[2];
  930.     cairo_xcb_picture_t *picture;
  931.     cairo_status_t status;
  932.     unsigned int n_stops;
  933.  
  934.     _cairo_gradient_pattern_fit_to_range (&pattern->base, PIXMAN_MAX_INT >> 1, &matrix, extremes);
  935.  
  936.     picture = (cairo_xcb_picture_t *)
  937.         _cairo_xcb_screen_lookup_radial_picture (target->screen, pattern);
  938.     if (picture != NULL)
  939.         goto setup_picture;
  940.  
  941.     stops = _gradient_to_xcb (&pattern->base, &n_stops, buf, sizeof (buf));
  942.     if (unlikely (stops == NULL))
  943.         return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
  944.  
  945.     picture = _cairo_xcb_picture_create (target->screen,
  946.                                          target->screen->connection->standard_formats[CAIRO_FORMAT_ARGB32],
  947.                                          PIXMAN_a8r8g8b8,
  948.                                          -1, -1);
  949.     if (unlikely (picture->base.status)) {
  950.         if (stops != (xcb_render_fixed_t *) buf)
  951.             free (stops);
  952.         return picture;
  953.     }
  954.     picture->filter = CAIRO_FILTER_DEFAULT;
  955.  
  956.     colors = (xcb_render_color_t *) (stops + n_stops);
  957.  
  958.     p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
  959.     p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
  960.     p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
  961.     p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
  962.  
  963.     r1 = _cairo_fixed_16_16_from_double (extremes[0].radius);
  964.     r2 = _cairo_fixed_16_16_from_double (extremes[1].radius);
  965.  
  966.     _cairo_xcb_connection_render_create_radial_gradient (target->connection,
  967.                                                          picture->picture,
  968.                                                          p1, p2, r1, r2,
  969.                                                          n_stops,
  970.                                                          stops, colors);
  971.  
  972.     if (stops != (xcb_render_fixed_t *) buf)
  973.         free (stops);
  974.  
  975.     status = _cairo_xcb_screen_store_radial_picture (target->screen,
  976.                                                      pattern,
  977.                                                      &picture->base);
  978.     if (unlikely (status)) {
  979.         cairo_surface_destroy (&picture->base);
  980.         return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
  981.     }
  982.  
  983. setup_picture:
  984.     _cairo_xcb_picture_set_matrix (picture, &matrix,
  985.                                    pattern->base.base.filter,
  986.                                    extents->x + extents->width/2.,
  987.                                    extents->y + extents->height/2.);
  988.     _cairo_xcb_picture_set_filter (picture, pattern->base.base.filter);
  989.     _cairo_xcb_picture_set_extend (picture, pattern->base.base.extend);
  990.     _cairo_xcb_picture_set_component_alpha (picture,
  991.                                             pattern->base.base.has_component_alpha);
  992.  
  993.     return picture;
  994. }
  995.  
  996. static cairo_xcb_picture_t *
  997. _copy_to_picture (cairo_xcb_surface_t *source)
  998. {
  999.     cairo_xcb_picture_t *picture;
  1000.     uint32_t values[] = { 0, 1 };
  1001.  
  1002.     if (source->deferred_clear) {
  1003.         cairo_status_t status = _cairo_xcb_surface_clear (source);
  1004.         if (unlikely (status))
  1005.             return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
  1006.     }
  1007.  
  1008.     picture = _cairo_xcb_picture_create (source->screen,
  1009.                                          source->xrender_format,
  1010.                                          source->pixman_format,
  1011.                                          source->width,
  1012.                                          source->height);
  1013.     if (unlikely (picture->base.status))
  1014.         return picture;
  1015.  
  1016.     _cairo_xcb_connection_render_create_picture (source->connection,
  1017.                                                  picture->picture,
  1018.                                                  source->drawable,
  1019.                                                  source->xrender_format,
  1020.                                                  XCB_RENDER_CP_GRAPHICS_EXPOSURE |
  1021.                                                  XCB_RENDER_CP_SUBWINDOW_MODE,
  1022.                                                  values);
  1023.  
  1024.     return picture;
  1025. }
  1026.  
  1027. static void
  1028. _cairo_xcb_surface_setup_surface_picture(cairo_xcb_picture_t *picture,
  1029.                                          const cairo_surface_pattern_t *pattern,
  1030.                                          const cairo_rectangle_int_t *extents)
  1031. {
  1032.     cairo_filter_t filter;
  1033.  
  1034.     filter = pattern->base.filter;
  1035.     if (filter != CAIRO_FILTER_NEAREST &&
  1036.         _cairo_matrix_has_unity_scale (&pattern->base.matrix) &&
  1037.         _cairo_fixed_is_integer (_cairo_fixed_from_double (pattern->base.matrix.x0)) &&
  1038.         _cairo_fixed_is_integer (_cairo_fixed_from_double (pattern->base.matrix.y0)))
  1039.     {
  1040.         filter = CAIRO_FILTER_NEAREST;
  1041.     }
  1042.     _cairo_xcb_picture_set_filter (picture, filter);
  1043.  
  1044.     _cairo_xcb_picture_set_matrix (picture,
  1045.                                    &pattern->base.matrix, filter,
  1046.                                    extents->x + extents->width/2.,
  1047.                                    extents->y + extents->height/2.);
  1048.  
  1049.  
  1050.     _cairo_xcb_picture_set_extend (picture, pattern->base.extend);
  1051.     _cairo_xcb_picture_set_component_alpha (picture, pattern->base.has_component_alpha);
  1052. }
  1053.  
  1054. static cairo_xcb_picture_t *
  1055. record_to_picture (cairo_surface_t *target,
  1056.                    const cairo_surface_pattern_t *pattern,
  1057.                    const cairo_rectangle_int_t *extents)
  1058. {
  1059.     cairo_surface_pattern_t tmp_pattern;
  1060.     cairo_xcb_picture_t *picture;
  1061.     cairo_status_t status;
  1062.     cairo_matrix_t matrix;
  1063.     cairo_surface_t *tmp;
  1064.     cairo_surface_t *source;
  1065.     cairo_rectangle_int_t limit;
  1066.     cairo_extend_t extend;
  1067.  
  1068.     /* XXX: The following was once more or less copied from cairo-xlibs-ource.c,
  1069.      * record_source() and recording_pattern_get_surface(), can we share a
  1070.      * single version?
  1071.      */
  1072.  
  1073.     /* First get the 'real' recording surface and figure out the size for tmp */
  1074.     source = _cairo_pattern_get_source (pattern, &limit);
  1075.     assert (_cairo_surface_is_recording (source));
  1076.  
  1077.     if (! _cairo_matrix_is_identity (&pattern->base.matrix)) {
  1078.         double x1, y1, x2, y2;
  1079.  
  1080.         matrix = pattern->base.matrix;
  1081.         status = cairo_matrix_invert (&matrix);
  1082.         assert (status == CAIRO_STATUS_SUCCESS);
  1083.  
  1084.         x1 = limit.x;
  1085.         y1 = limit.y;
  1086.         x2 = limit.x + limit.width;
  1087.         y2 = limit.y + limit.height;
  1088.  
  1089.         _cairo_matrix_transform_bounding_box (&matrix,
  1090.                                               &x1, &y1, &x2, &y2, NULL);
  1091.  
  1092.         limit.x = floor (x1);
  1093.         limit.y = floor (y1);
  1094.         limit.width  = ceil (x2) - limit.x;
  1095.         limit.height = ceil (y2) - limit.y;
  1096.     }
  1097.     extend = pattern->base.extend;
  1098.     if (_cairo_rectangle_contains_rectangle (&limit, extents))
  1099.         extend = CAIRO_EXTEND_NONE;
  1100.     if (extend == CAIRO_EXTEND_NONE && ! _cairo_rectangle_intersect (&limit, extents))
  1101.         return _cairo_xcb_transparent_picture ((cairo_xcb_surface_t *) target);
  1102.  
  1103.     /* Now draw the recording surface to an xcb surface */
  1104.     tmp = _cairo_surface_create_similar_solid (target,
  1105.                                                source->content,
  1106.                                                limit.width,
  1107.                                                limit.height,
  1108.                                                CAIRO_COLOR_TRANSPARENT);
  1109.     if (tmp->status != CAIRO_STATUS_SUCCESS) {
  1110.         return (cairo_xcb_picture_t *) tmp;
  1111.     }
  1112.  
  1113.     cairo_matrix_init_translate (&matrix, limit.x, limit.y);
  1114.     cairo_matrix_multiply (&matrix, &matrix, &pattern->base.matrix);
  1115.  
  1116.     status = _cairo_recording_surface_replay_with_clip (source,
  1117.                                                         &matrix, tmp,
  1118.                                                         NULL);
  1119.     if (unlikely (status)) {
  1120.         cairo_surface_destroy (tmp);
  1121.         return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
  1122.     }
  1123.  
  1124.     /* Now that we have drawn this to an xcb surface, try again with that */
  1125.     _cairo_pattern_init_static_copy (&tmp_pattern.base, &pattern->base);
  1126.     tmp_pattern.surface = tmp;
  1127.     cairo_matrix_init_translate (&tmp_pattern.base.matrix, -limit.x, -limit.y);
  1128.  
  1129.     picture = _copy_to_picture ((cairo_xcb_surface_t *) tmp);
  1130.     if (picture->base.status == CAIRO_STATUS_SUCCESS)
  1131.         _cairo_xcb_surface_setup_surface_picture (picture, &tmp_pattern, extents);
  1132.     cairo_surface_destroy (tmp);
  1133.     return picture;
  1134. }
  1135.  
  1136. static cairo_xcb_picture_t *
  1137. _cairo_xcb_surface_picture (cairo_xcb_surface_t *target,
  1138.                             const cairo_surface_pattern_t *pattern,
  1139.                             const cairo_rectangle_int_t *extents)
  1140. {
  1141.     cairo_surface_t *source = pattern->surface;
  1142.     cairo_xcb_picture_t *picture;
  1143.  
  1144.     picture = (cairo_xcb_picture_t *)
  1145.         _cairo_surface_has_snapshot (source, &_cairo_xcb_picture_backend);
  1146.     if (picture != NULL) {
  1147.         if (picture->screen == target->screen) {
  1148.             picture = (cairo_xcb_picture_t *) cairo_surface_reference (&picture->base);
  1149.             _cairo_xcb_surface_setup_surface_picture (picture, pattern, extents);
  1150.             return picture;
  1151.         }
  1152.         picture = NULL;
  1153.     }
  1154.  
  1155.     if (source->type == CAIRO_SURFACE_TYPE_XCB)
  1156.     {
  1157.         if (source->backend->type == CAIRO_SURFACE_TYPE_XCB) {
  1158.             cairo_xcb_surface_t *xcb = (cairo_xcb_surface_t *) source;
  1159.             if (xcb->screen == target->screen && xcb->fallback == NULL) {
  1160.                 picture = _copy_to_picture ((cairo_xcb_surface_t *) source);
  1161.                 if (unlikely (picture->base.status))
  1162.                     return picture;
  1163.             }
  1164.         } else if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
  1165.             cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
  1166.             cairo_xcb_surface_t *xcb = (cairo_xcb_surface_t *) sub->target;
  1167.  
  1168.             /* XXX repeat interval with source clipping? */
  1169.             if (FALSE && xcb->screen == target->screen && xcb->fallback == NULL) {
  1170.                 xcb_rectangle_t rect;
  1171.  
  1172.                 picture = _copy_to_picture (xcb);
  1173.                 if (unlikely (picture->base.status))
  1174.                     return picture;
  1175.  
  1176.                 rect.x = sub->extents.x;
  1177.                 rect.y = sub->extents.y;
  1178.                 rect.width  = sub->extents.width;
  1179.                 rect.height = sub->extents.height;
  1180.  
  1181.                 _cairo_xcb_connection_render_set_picture_clip_rectangles (xcb->connection,
  1182.                                                                           picture->picture,
  1183.                                                                           0, 0,
  1184.                                                                           1, &rect);
  1185.                 picture->x0 = rect.x;
  1186.                 picture->y0 = rect.y;
  1187.                 picture->width  = rect.width;
  1188.                 picture->height = rect.height;
  1189.             }
  1190.         } else if (_cairo_surface_is_snapshot (source)) {
  1191.             cairo_surface_snapshot_t *snap = (cairo_surface_snapshot_t *) source;
  1192.             cairo_xcb_surface_t *xcb = (cairo_xcb_surface_t *) snap->target;
  1193.  
  1194.             if (xcb->screen == target->screen && xcb->fallback == NULL) {
  1195.                 picture = _copy_to_picture (xcb);
  1196.                 if (unlikely (picture->base.status))
  1197.                     return picture;
  1198.             }
  1199.         }
  1200.     }
  1201. #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
  1202.     else if (source->type == CAIRO_SURFACE_TYPE_XLIB)
  1203.     {
  1204.         if (source->backend->type == CAIRO_SURFACE_TYPE_XLIB) {
  1205.             cairo_xcb_surface_t *xcb = ((cairo_xlib_xcb_surface_t *) source)->xcb;
  1206.             if (xcb->screen == target->screen && xcb->fallback == NULL) {
  1207.                 picture = _copy_to_picture (xcb);
  1208.                 if (unlikely (picture->base.status))
  1209.                     return picture;
  1210.             }
  1211.         } else if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
  1212.             cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
  1213.             cairo_xcb_surface_t *xcb = ((cairo_xlib_xcb_surface_t *) sub->target)->xcb;
  1214.  
  1215.             if (FALSE && xcb->screen == target->screen && xcb->fallback == NULL) {
  1216.                 xcb_rectangle_t rect;
  1217.  
  1218.                 picture = _copy_to_picture (xcb);
  1219.                 if (unlikely (picture->base.status))
  1220.                     return picture;
  1221.  
  1222.                 rect.x = sub->extents.x;
  1223.                 rect.y = sub->extents.y;
  1224.                 rect.width  = sub->extents.width;
  1225.                 rect.height = sub->extents.height;
  1226.  
  1227.                 _cairo_xcb_connection_render_set_picture_clip_rectangles (xcb->connection,
  1228.                                                                           picture->picture,
  1229.                                                                           0, 0,
  1230.                                                                           1, &rect);
  1231.                 picture->x0 = rect.x;
  1232.                 picture->y0 = rect.y;
  1233.                 picture->width  = rect.width;
  1234.                 picture->height = rect.height;
  1235.             }
  1236.         } else if (_cairo_surface_is_snapshot (source)) {
  1237.             cairo_surface_snapshot_t *snap = (cairo_surface_snapshot_t *) source;
  1238.             cairo_xcb_surface_t *xcb = ((cairo_xlib_xcb_surface_t *) snap->target)->xcb;
  1239.  
  1240.             if (xcb->screen == target->screen && xcb->fallback == NULL) {
  1241.                 picture = _copy_to_picture (xcb);
  1242.                 if (unlikely (picture->base.status))
  1243.                     return picture;
  1244.             }
  1245.         }
  1246.     }
  1247. #endif
  1248. #if CAIRO_HAS_GL_FUNCTIONS
  1249.     else if (source->type == CAIRO_SURFACE_TYPE_GL)
  1250.     {
  1251.         /* pixmap from texture */
  1252.     }
  1253. #endif
  1254.     else if (source->type == CAIRO_SURFACE_TYPE_RECORDING)
  1255.     {
  1256.         /* We have to skip the call to attach_snapshot() because we possibly
  1257.          * only drew part of the recording surface.
  1258.          * TODO: When can we safely attach a snapshot?
  1259.          */
  1260.         return record_to_picture(&target->base, pattern, extents);
  1261.     }
  1262.  
  1263.     if (picture == NULL) {
  1264.         cairo_image_surface_t *image;
  1265.         void *image_extra;
  1266.         cairo_status_t status;
  1267.  
  1268.         status = _cairo_surface_acquire_source_image (source, &image, &image_extra);
  1269.         if (unlikely (status))
  1270.             return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
  1271.  
  1272.         if (image->format != CAIRO_FORMAT_INVALID) {
  1273.             xcb_render_pictformat_t format;
  1274.  
  1275.             format = target->screen->connection->standard_formats[image->format];
  1276.  
  1277.             picture = _picture_from_image (target, format, image, NULL);
  1278.             _cairo_surface_release_source_image (source, image, image_extra);
  1279.         } else {
  1280.             cairo_image_surface_t *conv;
  1281.             xcb_render_pictformat_t render_format;
  1282.  
  1283.             /* XXX XRenderPutImage! */
  1284.  
  1285.             conv = _cairo_image_surface_coerce (image);
  1286.             _cairo_surface_release_source_image (source, image, image_extra);
  1287.             if (unlikely (conv->base.status))
  1288.                 return (cairo_xcb_picture_t *) conv;
  1289.  
  1290.             render_format = target->screen->connection->standard_formats[conv->format];
  1291.             picture = _picture_from_image (target, render_format, conv, NULL);
  1292.             cairo_surface_destroy (&conv->base);
  1293.         }
  1294.  
  1295.         if (unlikely (picture->base.status))
  1296.             return picture;
  1297.     }
  1298.  
  1299.     _cairo_surface_attach_snapshot (source,
  1300.                                     &picture->base,
  1301.                                     NULL);
  1302.  
  1303.     _cairo_xcb_surface_setup_surface_picture (picture, pattern, extents);
  1304.     return picture;
  1305. }
  1306.  
  1307. static cairo_xcb_picture_t *
  1308. _cairo_xcb_picture_for_pattern (cairo_xcb_surface_t *target,
  1309.                                 const cairo_pattern_t *pattern,
  1310.                                 const cairo_rectangle_int_t *extents)
  1311. {
  1312.     if (pattern == NULL)
  1313.         return _cairo_xcb_white_picture (target);
  1314.  
  1315.     if (! _pattern_is_supported (target->connection->flags, pattern))
  1316.         return _render_to_picture (target, pattern, extents);
  1317.  
  1318.     switch (pattern->type) {
  1319.     case CAIRO_PATTERN_TYPE_SOLID:
  1320.         return _cairo_xcb_solid_picture (target, (cairo_solid_pattern_t *) pattern);
  1321.  
  1322.     case CAIRO_PATTERN_TYPE_LINEAR:
  1323.         return _cairo_xcb_linear_picture (target,
  1324.                                           (cairo_linear_pattern_t *) pattern,
  1325.                                           extents);
  1326.  
  1327.     case CAIRO_PATTERN_TYPE_RADIAL:
  1328.         return _cairo_xcb_radial_picture (target,
  1329.                                           (cairo_radial_pattern_t *) pattern,
  1330.                                           extents);
  1331.  
  1332.     case CAIRO_PATTERN_TYPE_SURFACE:
  1333.         return _cairo_xcb_surface_picture (target,
  1334.                                            (cairo_surface_pattern_t *) pattern,
  1335.                                            extents);
  1336.     default:
  1337.         ASSERT_NOT_REACHED;
  1338.     case CAIRO_PATTERN_TYPE_MESH:
  1339.     case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
  1340.         return _render_to_picture (target, pattern, extents);
  1341.     }
  1342. }
  1343.  
  1344. COMPILE_TIME_ASSERT (sizeof (xcb_rectangle_t) <= sizeof (cairo_box_t));
  1345.  
  1346. static cairo_status_t
  1347. _render_fill_boxes (void                        *abstract_dst,
  1348.                     cairo_operator_t             op,
  1349.                     const cairo_color_t         *color,
  1350.                     cairo_boxes_t               *boxes)
  1351. {
  1352.     cairo_xcb_surface_t *dst = abstract_dst;
  1353.     xcb_rectangle_t stack_xrects[CAIRO_STACK_ARRAY_LENGTH (sizeof (xcb_rectangle_t))];
  1354.     xcb_rectangle_t *xrects = stack_xrects;
  1355.     xcb_render_color_t render_color;
  1356.     int render_op = _render_operator (op);
  1357.     struct _cairo_boxes_chunk *chunk;
  1358.     int max_count;
  1359.  
  1360.     render_color.red   = color->red_short;
  1361.     render_color.green = color->green_short;
  1362.     render_color.blue  = color->blue_short;
  1363.     render_color.alpha = color->alpha_short;
  1364.  
  1365.     max_count = 0;
  1366.     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
  1367.         if (chunk->count > max_count)
  1368.             max_count = chunk->count;
  1369.     }
  1370.     if (max_count > ARRAY_LENGTH (stack_xrects)) {
  1371.         xrects = _cairo_malloc_ab (max_count, sizeof (xcb_rectangle_t));
  1372.         if (unlikely (xrects == NULL))
  1373.             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1374.     }
  1375.  
  1376.     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
  1377.         int i, j;
  1378.  
  1379.         for (i = j = 0; i < chunk->count; i++) {
  1380.             int x1 = _cairo_fixed_integer_round_down (chunk->base[i].p1.x);
  1381.             int y1 = _cairo_fixed_integer_round_down (chunk->base[i].p1.y);
  1382.             int x2 = _cairo_fixed_integer_round_down (chunk->base[i].p2.x);
  1383.             int y2 = _cairo_fixed_integer_round_down (chunk->base[i].p2.y);
  1384.  
  1385.             if (x2 > x1 && y2 > y1) {
  1386.                 xrects[j].x = x1;
  1387.                 xrects[j].y = y1;
  1388.                 xrects[j].width  = x2 - x1;
  1389.                 xrects[j].height = y2 - y1;
  1390.                 j++;
  1391.             }
  1392.         }
  1393.  
  1394.         if (j) {
  1395.             _cairo_xcb_connection_render_fill_rectangles
  1396.                 (dst->connection,
  1397.                  render_op, dst->picture,
  1398.                  render_color, j, xrects);
  1399.         }
  1400.     }
  1401.  
  1402.     if (xrects != stack_xrects)
  1403.         free (xrects);
  1404.  
  1405.     return CAIRO_STATUS_SUCCESS;
  1406. }
  1407.  
  1408. /* pixel aligned, non-overlapping boxes */
  1409. static cairo_int_status_t
  1410. _render_composite_boxes (cairo_xcb_surface_t    *dst,
  1411.                          cairo_operator_t        op,
  1412.                          const cairo_pattern_t  *src_pattern,
  1413.                          const cairo_pattern_t  *mask_pattern,
  1414.                          const cairo_rectangle_int_t *extents,
  1415.                          const cairo_boxes_t *boxes)
  1416. {
  1417.     cairo_xcb_picture_t *src, *mask;
  1418.     const struct _cairo_boxes_chunk *chunk;
  1419.     xcb_rectangle_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (xcb_rectangle_t)];
  1420.     xcb_rectangle_t *clip_boxes;
  1421.     cairo_rectangle_int_t stack_extents;
  1422.     cairo_status_t status;
  1423.     int num_boxes;
  1424.     int render_op;
  1425.  
  1426.     render_op = _render_operator (op);
  1427.  
  1428.     if (src_pattern == NULL) {
  1429.         src_pattern = mask_pattern;
  1430.         mask_pattern = NULL;
  1431.     }
  1432.  
  1433.     /* amalgamate into a single Composite call by setting a clip region */
  1434.     clip_boxes = stack_boxes;
  1435.     if (boxes->num_boxes > ARRAY_LENGTH (stack_boxes)) {
  1436.         clip_boxes = _cairo_malloc_ab (boxes->num_boxes, sizeof (xcb_rectangle_t));
  1437.         if (unlikely (clip_boxes == NULL))
  1438.             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  1439.     }
  1440.  
  1441.     src = _cairo_xcb_picture_for_pattern (dst, src_pattern, extents);
  1442.     status = src->base.status;
  1443.     if (unlikely (status))
  1444.         goto cleanup_boxes;
  1445.  
  1446.     num_boxes = 0;
  1447.     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
  1448.         const cairo_box_t *box = chunk->base;
  1449.         int i;
  1450.  
  1451.         for (i = 0; i < chunk->count; i++) {
  1452.             int x = _cairo_fixed_integer_round_down (box[i].p1.x);
  1453.             int y = _cairo_fixed_integer_round_down (box[i].p1.y);
  1454.             int width  = _cairo_fixed_integer_round_down (box[i].p2.x) - x;
  1455.             int height = _cairo_fixed_integer_round_down (box[i].p2.y) - y;
  1456.  
  1457.             if (width && height) {
  1458.                 clip_boxes[num_boxes].x = x;
  1459.                 clip_boxes[num_boxes].y = y;
  1460.                 clip_boxes[num_boxes].width = width;
  1461.                 clip_boxes[num_boxes].height = height;
  1462.                 num_boxes++;
  1463.             }
  1464.         }
  1465.     }
  1466.  
  1467.     if (num_boxes) {
  1468.         if (num_boxes > 1) {
  1469.             _cairo_xcb_connection_render_set_picture_clip_rectangles (dst->connection,
  1470.                                                                       dst->picture,
  1471.                                                                       0, 0,
  1472.                                                                       num_boxes,
  1473.                                                                       clip_boxes);
  1474.         } else {
  1475.             stack_extents.x = clip_boxes[0].x;
  1476.             stack_extents.y = clip_boxes[0].y;
  1477.             stack_extents.width  = clip_boxes[0].width;
  1478.             stack_extents.height = clip_boxes[0].height;
  1479.             extents = &stack_extents;
  1480.         }
  1481.  
  1482.         if (mask_pattern != NULL) {
  1483.             mask = _cairo_xcb_picture_for_pattern (dst, mask_pattern, extents);
  1484.             status = mask->base.status;
  1485.             if (unlikely (status))
  1486.                 goto cleanup_clip;
  1487.  
  1488.             _cairo_xcb_connection_render_composite (dst->connection,
  1489.                                                     render_op,
  1490.                                                     src->picture,
  1491.                                                     mask->picture,
  1492.                                                     dst->picture,
  1493.                                                     src->x + extents->x, src->y + extents->y,
  1494.                                                     mask->x + extents->x, mask->y + extents->y,
  1495.                                                     extents->x, extents->y,
  1496.                                                     extents->width, extents->height);
  1497.  
  1498.             cairo_surface_destroy (&mask->base);
  1499.         } else {
  1500.             _cairo_xcb_connection_render_composite (dst->connection,
  1501.                                                     render_op,
  1502.                                                     src->picture,
  1503.                                                     XCB_NONE,
  1504.                                                     dst->picture,
  1505.                                                     src->x + extents->x, src->y + extents->y,
  1506.                                                     0, 0,
  1507.                                                     extents->x, extents->y,
  1508.                                                     extents->width, extents->height);
  1509.         }
  1510.  
  1511. cleanup_clip:
  1512.  
  1513.         if (num_boxes > 1)
  1514.             _cairo_xcb_surface_clear_clip_region (dst);
  1515.     }
  1516.  
  1517.     cairo_surface_destroy (&src->base);
  1518.  
  1519. cleanup_boxes:
  1520.  
  1521.     if (clip_boxes != stack_boxes)
  1522.         free (clip_boxes);
  1523.  
  1524.     return status;
  1525. }
  1526.  
  1527.  
  1528. #define CAIRO_FIXED_16_16_MIN _cairo_fixed_from_int (-32768)
  1529. #define CAIRO_FIXED_16_16_MAX _cairo_fixed_from_int (32767)
  1530.  
  1531. static cairo_bool_t
  1532. _line_exceeds_16_16 (const cairo_line_t *line)
  1533. {
  1534.     return
  1535.         line->p1.x <= CAIRO_FIXED_16_16_MIN ||
  1536.         line->p1.x >= CAIRO_FIXED_16_16_MAX ||
  1537.  
  1538.         line->p2.x <= CAIRO_FIXED_16_16_MIN ||
  1539.         line->p2.x >= CAIRO_FIXED_16_16_MAX ||
  1540.  
  1541.         line->p1.y <= CAIRO_FIXED_16_16_MIN ||
  1542.         line->p1.y >= CAIRO_FIXED_16_16_MAX ||
  1543.  
  1544.         line->p2.y <= CAIRO_FIXED_16_16_MIN ||
  1545.         line->p2.y >= CAIRO_FIXED_16_16_MAX;
  1546. }
  1547.  
  1548. static void
  1549. _project_line_x_onto_16_16 (const cairo_line_t *line,
  1550.                             cairo_fixed_t top,
  1551.                             cairo_fixed_t bottom,
  1552.                             xcb_render_linefix_t *out)
  1553. {
  1554.     cairo_point_double_t p1, p2;
  1555.     double m;
  1556.  
  1557.     p1.x = _cairo_fixed_to_double (line->p1.x);
  1558.     p1.y = _cairo_fixed_to_double (line->p1.y);
  1559.  
  1560.     p2.x = _cairo_fixed_to_double (line->p2.x);
  1561.     p2.y = _cairo_fixed_to_double (line->p2.y);
  1562.  
  1563.     m = (p2.x - p1.x) / (p2.y - p1.y);
  1564.     out->p1.x = _cairo_fixed_16_16_from_double (p1.x + m * _cairo_fixed_to_double (top - line->p1.y));
  1565.     out->p2.x = _cairo_fixed_16_16_from_double (p1.x + m * _cairo_fixed_to_double (bottom - line->p1.y));
  1566. }
  1567.  
  1568. typedef struct {
  1569.     cairo_traps_t traps;
  1570.     cairo_antialias_t antialias;
  1571. } composite_traps_info_t;
  1572.  
  1573. COMPILE_TIME_ASSERT (sizeof (xcb_render_trapezoid_t) <= sizeof (cairo_trapezoid_t));
  1574.  
  1575. static cairo_int_status_t
  1576. _composite_traps (void *closure,
  1577.                   cairo_xcb_surface_t   *dst,
  1578.                   cairo_operator_t       op,
  1579.                   const cairo_pattern_t *pattern,
  1580.                   int dst_x, int dst_y,
  1581.                   const cairo_rectangle_int_t *extents,
  1582.                   cairo_clip_t          *clip)
  1583. {
  1584.     composite_traps_info_t *info = closure;
  1585.     const cairo_traps_t *traps = &info->traps;
  1586.     cairo_xcb_picture_t *src;
  1587.     cairo_format_t format;
  1588.     xcb_render_pictformat_t xrender_format;
  1589.     xcb_render_trapezoid_t *xtraps;
  1590.     int render_reference_x, render_reference_y;
  1591.     cairo_status_t status;
  1592.     int i;
  1593.  
  1594.     if (dst->deferred_clear) {
  1595.         status = _cairo_xcb_surface_clear (dst);
  1596.         if (unlikely (status))
  1597.                 return status;
  1598.     }
  1599.  
  1600.     src = _cairo_xcb_picture_for_pattern (dst, pattern, extents);
  1601.     if (unlikely (src->base.status))
  1602.         return src->base.status;
  1603.  
  1604.     if (info->antialias == CAIRO_ANTIALIAS_NONE)
  1605.         format = CAIRO_FORMAT_A1;
  1606.     else
  1607.         format = CAIRO_FORMAT_A8;
  1608.     xrender_format = dst->screen->connection->standard_formats[format];
  1609.  
  1610.     xtraps = (xcb_render_trapezoid_t *) traps->traps;
  1611.     for (i = 0; i < traps->num_traps; i++) {
  1612.         cairo_trapezoid_t t = traps->traps[i];
  1613.  
  1614.         /* top/bottom will be clamped to surface bounds */
  1615.         xtraps[i].top = _cairo_fixed_to_16_16 (t.top);
  1616.         xtraps[i].top -= dst_y << 16;
  1617.         xtraps[i].bottom = _cairo_fixed_to_16_16 (t.bottom);
  1618.         xtraps[i].bottom -= dst_y << 16;
  1619.  
  1620.         /* However, all the other coordinates will have been left untouched so
  1621.          * as not to introduce numerical error. Recompute them if they
  1622.          * exceed the 16.16 limits.
  1623.          */
  1624.         if (unlikely (_line_exceeds_16_16 (&t.left))) {
  1625.             _project_line_x_onto_16_16 (&t.left,
  1626.                                         t.top,
  1627.                                         t.bottom,
  1628.                                         &xtraps[i].left);
  1629.             xtraps[i].left.p1.y = xtraps[i].top;
  1630.             xtraps[i].left.p2.y = xtraps[i].bottom;
  1631.         } else {
  1632.             xtraps[i].left.p1.x = _cairo_fixed_to_16_16 (t.left.p1.x);
  1633.             xtraps[i].left.p1.y = _cairo_fixed_to_16_16 (t.left.p1.y);
  1634.             xtraps[i].left.p2.x = _cairo_fixed_to_16_16 (t.left.p2.x);
  1635.             xtraps[i].left.p2.y = _cairo_fixed_to_16_16 (t.left.p2.y);
  1636.         }
  1637.         xtraps[i].left.p1.x -= dst_x << 16;
  1638.         xtraps[i].left.p1.y -= dst_y << 16;
  1639.         xtraps[i].left.p2.x -= dst_x << 16;
  1640.         xtraps[i].left.p2.y -= dst_y << 16;
  1641.  
  1642.         if (unlikely (_line_exceeds_16_16 (&t.right))) {
  1643.             _project_line_x_onto_16_16 (&t.right,
  1644.                                         t.top,
  1645.                                         t.bottom,
  1646.                                         &xtraps[i].right);
  1647.             xtraps[i].right.p1.y = xtraps[i].top;
  1648.             xtraps[i].right.p2.y = xtraps[i].bottom;
  1649.         } else {
  1650.             xtraps[i].right.p1.x = _cairo_fixed_to_16_16 (t.right.p1.x);
  1651.             xtraps[i].right.p1.y = _cairo_fixed_to_16_16 (t.right.p1.y);
  1652.             xtraps[i].right.p2.x = _cairo_fixed_to_16_16 (t.right.p2.x);
  1653.             xtraps[i].right.p2.y = _cairo_fixed_to_16_16 (t.right.p2.y);
  1654.         }
  1655.         xtraps[i].right.p1.x -= dst_x << 16;
  1656.         xtraps[i].right.p1.y -= dst_y << 16;
  1657.         xtraps[i].right.p2.x -= dst_x << 16;
  1658.         xtraps[i].right.p2.y -= dst_y << 16;
  1659.     }
  1660.  
  1661.     if (xtraps[0].left.p1.y < xtraps[0].left.p2.y) {
  1662.         render_reference_x = xtraps[0].left.p1.x >> 16;
  1663.         render_reference_y = xtraps[0].left.p1.y >> 16;
  1664.     } else {
  1665.         render_reference_x = xtraps[0].left.p2.x >> 16;
  1666.         render_reference_y = xtraps[0].left.p2.y >> 16;
  1667.     }
  1668.     render_reference_x += src->x + dst_x;
  1669.     render_reference_y += src->y + dst_y;
  1670.  
  1671.     _cairo_xcb_surface_set_precision (dst, info->antialias);
  1672.     _cairo_xcb_connection_render_trapezoids (dst->connection,
  1673.                                              _render_operator (op),
  1674.                                              src->picture,
  1675.                                              dst->picture,
  1676.                                              xrender_format,
  1677.                                              render_reference_x,
  1678.                                              render_reference_y,
  1679.                                              traps->num_traps, xtraps);
  1680.  
  1681.     cairo_surface_destroy (&src->base);
  1682.  
  1683.     return CAIRO_STATUS_SUCCESS;
  1684. }
  1685.  
  1686. /* low-level composite driver */
  1687.  
  1688. static cairo_xcb_surface_t *
  1689. get_clip_surface (const cairo_clip_t *clip,
  1690.                   cairo_xcb_surface_t *target,
  1691.                   int *tx, int *ty)
  1692. {
  1693.     cairo_surface_t *surface;
  1694.     cairo_status_t status;
  1695.  
  1696.     surface = _cairo_surface_create_similar_solid (&target->base,
  1697.                                                    CAIRO_CONTENT_ALPHA,
  1698.                                                    clip->extents.width,
  1699.                                                    clip->extents.height,
  1700.                                                    CAIRO_COLOR_WHITE);
  1701.     if (unlikely (surface->status))
  1702.         return (cairo_xcb_surface_t *) surface;
  1703.  
  1704.     assert (surface->backend == &_cairo_xcb_surface_backend);
  1705.     status = _cairo_clip_combine_with_surface (clip, surface,
  1706.                                                clip->extents.x, clip->extents.y);
  1707.     if (unlikely (status)) {
  1708.         cairo_surface_destroy (surface);
  1709.         surface = _cairo_surface_create_in_error (status);
  1710.     }
  1711.  
  1712.     *tx = clip->extents.x;
  1713.     *ty = clip->extents.y;
  1714.  
  1715.     return (cairo_xcb_surface_t *) surface;
  1716. }
  1717.  
  1718. typedef cairo_int_status_t
  1719. (*xcb_draw_func_t) (void                                *closure,
  1720.                     cairo_xcb_surface_t                 *dst,
  1721.                     cairo_operator_t                     op,
  1722.                     const cairo_pattern_t               *src,
  1723.                     int                                  dst_x,
  1724.                     int                                  dst_y,
  1725.                     const cairo_rectangle_int_t         *extents,
  1726.                     cairo_clip_t                        *clip);
  1727.  
  1728. static void do_unaligned_row(void (*blt)(void *closure,
  1729.                                          int16_t x, int16_t y,
  1730.                                          int16_t w, int16_t h,
  1731.                                          uint16_t coverage),
  1732.                              void *closure,
  1733.                              const cairo_box_t *b,
  1734.                              int tx, int y, int h,
  1735.                              uint16_t coverage)
  1736. {
  1737.     int x1 = _cairo_fixed_integer_part (b->p1.x) - tx;
  1738.     int x2 = _cairo_fixed_integer_part (b->p2.x) - tx;
  1739.     if (x2 > x1) {
  1740.         if (! _cairo_fixed_is_integer (b->p1.x)) {
  1741.             blt(closure, x1, y, 1, h,
  1742.                 coverage * (256 - _cairo_fixed_fractional_part (b->p1.x)));
  1743.             x1++;
  1744.         }
  1745.  
  1746.         if (x2 > x1)
  1747.             blt(closure, x1, y, x2-x1, h, (coverage << 8) - (coverage >> 8));
  1748.  
  1749.         if (! _cairo_fixed_is_integer (b->p2.x))
  1750.             blt(closure, x2, y, 1, h,
  1751.                 coverage * _cairo_fixed_fractional_part (b->p2.x));
  1752.     } else
  1753.         blt(closure, x1, y, 1, h,
  1754.             coverage * (b->p2.x - b->p1.x));
  1755. }
  1756.  
  1757. static void do_unaligned_box(void (*blt)(void *closure,
  1758.                                          int16_t x, int16_t y,
  1759.                                          int16_t w, int16_t h,
  1760.                                          uint16_t coverage),
  1761.                              void *closure,
  1762.                              const cairo_box_t *b, int tx, int ty)
  1763. {
  1764.     int y1 = _cairo_fixed_integer_part (b->p1.y) - ty;
  1765.     int y2 = _cairo_fixed_integer_part (b->p2.y) - ty;
  1766.     if (y2 > y1) {
  1767.         if (! _cairo_fixed_is_integer (b->p1.y)) {
  1768.             do_unaligned_row(blt, closure, b, tx, y1, 1,
  1769.                              256 - _cairo_fixed_fractional_part (b->p1.y));
  1770.             y1++;
  1771.         }
  1772.  
  1773.         if (y2 > y1)
  1774.             do_unaligned_row(blt, closure, b, tx, y1, y2-y1, 256);
  1775.  
  1776.         if (! _cairo_fixed_is_integer (b->p2.y))
  1777.             do_unaligned_row(blt, closure, b, tx, y2, 1,
  1778.                              _cairo_fixed_fractional_part (b->p2.y));
  1779.     } else
  1780.         do_unaligned_row(blt, closure, b, tx, y1, 1,
  1781.                          b->p2.y - b->p1.y);
  1782. }
  1783.  
  1784.  
  1785. static void blt_in(void *closure,
  1786.                    int16_t x, int16_t y,
  1787.                    int16_t w, int16_t h,
  1788.                    uint16_t coverage)
  1789. {
  1790.     cairo_xcb_surface_t *mask = closure;
  1791.     xcb_render_color_t color;
  1792.     xcb_rectangle_t rect;
  1793.  
  1794.     if (coverage == 0xffff)
  1795.         return;
  1796.  
  1797.     color.red = color.green = color.blue = 0;
  1798.     color.alpha = coverage;
  1799.  
  1800.     rect.x = x;
  1801.     rect.y = y;
  1802.     rect.width  = w;
  1803.     rect.height = h;
  1804.  
  1805.     _cairo_xcb_connection_render_fill_rectangles (mask->connection,
  1806.                                                   XCB_RENDER_PICT_OP_IN,
  1807.                                                   mask->picture,
  1808.                                                   color, 1, &rect);
  1809. }
  1810.  
  1811. static cairo_xcb_surface_t *
  1812. _create_composite_mask (cairo_clip_t            *clip,
  1813.                         xcb_draw_func_t          draw_func,
  1814.                         xcb_draw_func_t          mask_func,
  1815.                         void                    *draw_closure,
  1816.                         cairo_xcb_surface_t     *dst,
  1817.                         const cairo_rectangle_int_t*extents)
  1818. {
  1819.     cairo_xcb_surface_t *surface;
  1820.     cairo_bool_t need_clip_combine;
  1821.     cairo_int_status_t status;
  1822.  
  1823.     surface = (cairo_xcb_surface_t *)
  1824.         _cairo_xcb_surface_create_similar (dst, CAIRO_CONTENT_ALPHA,
  1825.                                            extents->width, extents->height);
  1826.     if (unlikely (surface->base.status))
  1827.         return surface;
  1828.  
  1829.     _cairo_xcb_surface_ensure_picture (surface);
  1830.  
  1831.     surface->deferred_clear_color = *CAIRO_COLOR_TRANSPARENT;
  1832.     surface->deferred_clear = TRUE;
  1833.     surface->base.is_clear = TRUE;
  1834.  
  1835.     if (mask_func) {
  1836.         status = mask_func (draw_closure, surface,
  1837.                             CAIRO_OPERATOR_ADD, NULL,
  1838.                             extents->x, extents->y,
  1839.                             extents, clip);
  1840.         if (likely (status != CAIRO_INT_STATUS_UNSUPPORTED))
  1841.             return surface;
  1842.     }
  1843.  
  1844.     /* Is it worth setting the clip region here? */
  1845.     status = draw_func (draw_closure, surface,
  1846.                         CAIRO_OPERATOR_ADD, NULL,
  1847.                         extents->x, extents->y,
  1848.                         extents, NULL);
  1849.     if (unlikely (status)) {
  1850.         cairo_surface_destroy (&surface->base);
  1851.         return (cairo_xcb_surface_t *) _cairo_surface_create_in_error (status);
  1852.     }
  1853.  
  1854.     if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES) {
  1855.         int i;
  1856.  
  1857.         for (i = 0; i < clip->num_boxes; i++) {
  1858.             cairo_box_t *b = &clip->boxes[i];
  1859.  
  1860.             if (! _cairo_fixed_is_integer (b->p1.x) ||
  1861.                 ! _cairo_fixed_is_integer (b->p1.y) ||
  1862.                 ! _cairo_fixed_is_integer (b->p2.x) ||
  1863.                 ! _cairo_fixed_is_integer (b->p2.y))
  1864.             {
  1865.                 do_unaligned_box(blt_in, surface, b, extents->x, extents->y);
  1866.             }
  1867.         }
  1868.  
  1869.         need_clip_combine = clip->path != NULL;
  1870.     } else
  1871.         need_clip_combine = ! _cairo_clip_is_region (clip);
  1872.  
  1873.     if (need_clip_combine) {
  1874.         status = _cairo_clip_combine_with_surface (clip, &surface->base,
  1875.                                                    extents->x, extents->y);
  1876.         if (unlikely (status)) {
  1877.             cairo_surface_destroy (&surface->base);
  1878.             return (cairo_xcb_surface_t *) _cairo_surface_create_in_error (status);
  1879.         }
  1880.     }
  1881.  
  1882.     return surface;
  1883. }
  1884.  
  1885. /* Handles compositing with a clip surface when the operator allows
  1886.  * us to combine the clip with the mask
  1887.  */
  1888. static cairo_status_t
  1889. _clip_and_composite_with_mask (cairo_clip_t             *clip,
  1890.                                cairo_operator_t          op,
  1891.                                const cairo_pattern_t    *pattern,
  1892.                                xcb_draw_func_t           draw_func,
  1893.                                xcb_draw_func_t           mask_func,
  1894.                                void                     *draw_closure,
  1895.                                cairo_xcb_surface_t      *dst,
  1896.                                const cairo_rectangle_int_t*extents)
  1897. {
  1898.     cairo_xcb_surface_t *mask;
  1899.     cairo_xcb_picture_t *src;
  1900.  
  1901.     mask = _create_composite_mask (clip,
  1902.                                    draw_func, mask_func, draw_closure,
  1903.                                    dst, extents);
  1904.     if (unlikely (mask->base.status))
  1905.         return mask->base.status;
  1906.  
  1907.     if (pattern != NULL || dst->base.content != CAIRO_CONTENT_ALPHA) {
  1908.         src = _cairo_xcb_picture_for_pattern (dst, pattern, extents);
  1909.         if (unlikely (src->base.status)) {
  1910.             cairo_surface_destroy (&mask->base);
  1911.             return src->base.status;
  1912.         }
  1913.  
  1914.         _cairo_xcb_connection_render_composite (dst->connection,
  1915.                                                 _render_operator (op),
  1916.                                                 src->picture,
  1917.                                                 mask->picture,
  1918.                                                 dst->picture,
  1919.                                                 extents->x + src->x, extents->y + src->y,
  1920.                                                 0, 0,
  1921.                                                 extents->x,      extents->y,
  1922.                                                 extents->width,  extents->height);
  1923.  
  1924.         cairo_surface_destroy (&src->base);
  1925.     } else {
  1926.         _cairo_xcb_connection_render_composite (dst->connection,
  1927.                                                 _render_operator (op),
  1928.                                                 mask->picture,
  1929.                                                 XCB_NONE,
  1930.                                                 dst->picture,
  1931.                                                 0, 0,
  1932.                                                 0, 0,
  1933.                                                 extents->x,      extents->y,
  1934.                                                 extents->width,  extents->height);
  1935.     }
  1936.     cairo_surface_destroy (&mask->base);
  1937.  
  1938.     return CAIRO_STATUS_SUCCESS;
  1939. }
  1940.  
  1941. /* Handles compositing with a clip surface when we have to do the operation
  1942.  * in two pieces and combine them together.
  1943.  */
  1944. static cairo_status_t
  1945. _clip_and_composite_combine (cairo_clip_t               *clip,
  1946.                              cairo_operator_t            op,
  1947.                              const cairo_pattern_t      *pattern,
  1948.                              xcb_draw_func_t             draw_func,
  1949.                              void                       *draw_closure,
  1950.                              cairo_xcb_surface_t        *dst,
  1951.                              const cairo_rectangle_int_t*extents)
  1952. {
  1953.     cairo_xcb_surface_t *tmp;
  1954.     cairo_xcb_surface_t *clip_surface;
  1955.     int clip_x = 0, clip_y = 0;
  1956.     xcb_render_picture_t clip_picture;
  1957.     cairo_status_t status;
  1958.  
  1959.     tmp = (cairo_xcb_surface_t *)
  1960.         _cairo_xcb_surface_create_similar (dst, dst->base.content,
  1961.                                            extents->width, extents->height);
  1962.     if (unlikely (tmp->base.status))
  1963.         return tmp->base.status;
  1964.  
  1965.     /* create_similar() could have done a fallback to an image surface */
  1966.     assert (tmp->base.backend == &_cairo_xcb_surface_backend);
  1967.  
  1968.     _cairo_xcb_surface_ensure_picture (tmp);
  1969.  
  1970.     if (pattern == NULL) {
  1971.         status = (*draw_func) (draw_closure, tmp,
  1972.                                CAIRO_OPERATOR_ADD, NULL,
  1973.                                extents->x, extents->y,
  1974.                                extents, NULL);
  1975.     } else {
  1976.         /* Initialize the temporary surface from the destination surface */
  1977.         if (! dst->base.is_clear ||
  1978.             (dst->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES) == 0)
  1979.         {
  1980.             /* XCopyArea may actually be quicker here.
  1981.              * A good driver should translate if appropriate.
  1982.              */
  1983.             _cairo_xcb_connection_render_composite (dst->connection,
  1984.                                                     XCB_RENDER_PICT_OP_SRC,
  1985.                                                     dst->picture,
  1986.                                                     XCB_NONE,
  1987.                                                     tmp->picture,
  1988.                                                     extents->x,      extents->y,
  1989.                                                     0, 0,
  1990.                                                     0, 0,
  1991.                                                     extents->width,  extents->height);
  1992.         }
  1993.         else
  1994.         {
  1995.             xcb_render_color_t clear;
  1996.             xcb_rectangle_t xrect;
  1997.  
  1998.             clear.red = clear.green = clear.blue = clear.alpha = 0;
  1999.  
  2000.             xrect.x = xrect.y = 0;
  2001.             xrect.width  = extents->width;
  2002.             xrect.height = extents->height;
  2003.  
  2004.             _cairo_xcb_connection_render_fill_rectangles (dst->connection,
  2005.                                                           XCB_RENDER_PICT_OP_CLEAR,
  2006.                                                           dst->picture,
  2007.                                                           clear, 1, &xrect);
  2008.         }
  2009.  
  2010.         status = (*draw_func) (draw_closure, tmp, op, pattern,
  2011.                                extents->x, extents->y,
  2012.                                extents, NULL);
  2013.     }
  2014.     if (unlikely (status))
  2015.         goto CLEANUP_SURFACE;
  2016.  
  2017.     clip_surface = get_clip_surface (clip, dst, &clip_x, &clip_y);
  2018.     status = clip_surface->base.status;
  2019.     if (unlikely (status))
  2020.         goto CLEANUP_SURFACE;
  2021.  
  2022.     assert (clip_surface->base.backend == &_cairo_xcb_surface_backend);
  2023.     clip_picture = clip_surface->picture;
  2024.     assert (clip_picture != XCB_NONE);
  2025.  
  2026.     if (dst->base.is_clear) {
  2027.         _cairo_xcb_connection_render_composite (dst->connection,
  2028.                                                 XCB_RENDER_PICT_OP_SRC,
  2029.                                                 tmp->picture, clip_picture, dst->picture,
  2030.                                                 0, 0,
  2031.                                                 0, 0,
  2032.                                                 extents->x,      extents->y,
  2033.                                                 extents->width,  extents->height);
  2034.     } else {
  2035.         /* Punch the clip out of the destination */
  2036.         _cairo_xcb_connection_render_composite (dst->connection,
  2037.                                                 XCB_RENDER_PICT_OP_OUT_REVERSE,
  2038.                                                 clip_picture, XCB_NONE, dst->picture,
  2039.                                                 extents->x - clip_x,
  2040.                                                 extents->y - clip_y,
  2041.                                                 0, 0,
  2042.                                                 extents->x,     extents->y,
  2043.                                                 extents->width, extents->height);
  2044.  
  2045.         /* Now add the two results together */
  2046.         _cairo_xcb_connection_render_composite (dst->connection,
  2047.                                                 XCB_RENDER_PICT_OP_ADD,
  2048.                                                 tmp->picture, clip_picture, dst->picture,
  2049.                                                 0, 0,
  2050.                                                 extents->x - clip_x,
  2051.                                                 extents->y - clip_y,
  2052.                                                 extents->x,     extents->y,
  2053.                                                 extents->width, extents->height);
  2054.     }
  2055.     cairo_surface_destroy (&clip_surface->base);
  2056.  
  2057.  CLEANUP_SURFACE:
  2058.     cairo_surface_destroy (&tmp->base);
  2059.  
  2060.     return status;
  2061. }
  2062.  
  2063. /* Handles compositing for %CAIRO_OPERATOR_SOURCE, which is special; it's
  2064.  * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
  2065.  */
  2066. static cairo_status_t
  2067. _clip_and_composite_source (cairo_clip_t                *clip,
  2068.                             const cairo_pattern_t       *pattern,
  2069.                             xcb_draw_func_t              draw_func,
  2070.                             xcb_draw_func_t              mask_func,
  2071.                             void                        *draw_closure,
  2072.                             cairo_xcb_surface_t         *dst,
  2073.                             const cairo_rectangle_int_t *extents)
  2074. {
  2075.     cairo_xcb_surface_t *mask;
  2076.     cairo_xcb_picture_t *src;
  2077.  
  2078.     /* Create a surface that is mask IN clip */
  2079.     mask = _create_composite_mask (clip,
  2080.                                    draw_func, mask_func, draw_closure,
  2081.                                    dst, extents);
  2082.     if (unlikely (mask->base.status))
  2083.         return mask->base.status;
  2084.  
  2085.     src = _cairo_xcb_picture_for_pattern (dst, pattern, extents);
  2086.     if (unlikely (src->base.status)) {
  2087.         cairo_surface_destroy (&mask->base);
  2088.         return src->base.status;
  2089.     }
  2090.  
  2091.     if (dst->base.is_clear) {
  2092.         _cairo_xcb_connection_render_composite (dst->connection,
  2093.                                                 XCB_RENDER_PICT_OP_SRC,
  2094.                                                 src->picture,
  2095.                                                 mask->picture,
  2096.                                                 dst->picture,
  2097.                                                 extents->x + src->x, extents->y + src->y,
  2098.                                                 0, 0,
  2099.                                                 extents->x,      extents->y,
  2100.                                                 extents->width,  extents->height);
  2101.     } else {
  2102.         /* Compute dest' = dest OUT (mask IN clip) */
  2103.         _cairo_xcb_connection_render_composite (dst->connection,
  2104.                                                 XCB_RENDER_PICT_OP_OUT_REVERSE,
  2105.                                                 mask->picture,
  2106.                                                 XCB_NONE,
  2107.                                                 dst->picture,
  2108.                                                 0, 0, 0, 0,
  2109.                                                 extents->x,     extents->y,
  2110.                                                 extents->width, extents->height);
  2111.  
  2112.         /* Now compute (src IN (mask IN clip)) ADD dest' */
  2113.         _cairo_xcb_connection_render_composite (dst->connection,
  2114.                                                 XCB_RENDER_PICT_OP_ADD,
  2115.                                                 src->picture,
  2116.                                                 mask->picture,
  2117.                                                 dst->picture,
  2118.                                                 extents->x + src->x, extents->y + src->y,
  2119.                                                 0, 0,
  2120.                                                 extents->x,     extents->y,
  2121.                                                 extents->width, extents->height);
  2122.     }
  2123.  
  2124.     cairo_surface_destroy (&src->base);
  2125.     cairo_surface_destroy (&mask->base);
  2126.  
  2127.     return CAIRO_STATUS_SUCCESS;
  2128. }
  2129.  
  2130. static cairo_bool_t
  2131. can_reduce_alpha_op (cairo_operator_t op)
  2132. {
  2133.     int iop = op;
  2134.     switch (iop) {
  2135.     case CAIRO_OPERATOR_OVER:
  2136.     case CAIRO_OPERATOR_SOURCE:
  2137.     case CAIRO_OPERATOR_ADD:
  2138.         return TRUE;
  2139.     default:
  2140.         return FALSE;
  2141.     }
  2142. }
  2143.  
  2144. static cairo_bool_t
  2145. reduce_alpha_op (cairo_surface_t *dst,
  2146.                  cairo_operator_t op,
  2147.                  const cairo_pattern_t *pattern)
  2148. {
  2149.     return dst->is_clear &&
  2150.            dst->content == CAIRO_CONTENT_ALPHA &&
  2151.            _cairo_pattern_is_opaque_solid (pattern) &&
  2152.            can_reduce_alpha_op (op);
  2153. }
  2154.  
  2155. static cairo_status_t
  2156. _cairo_xcb_surface_fixup_unbounded (cairo_xcb_surface_t *dst,
  2157.                                     const cairo_composite_rectangles_t *rects)
  2158. {
  2159.     xcb_rectangle_t xrects[4];
  2160.     int n;
  2161.  
  2162.     if (rects->bounded.width  == rects->unbounded.width &&
  2163.         rects->bounded.height == rects->unbounded.height)
  2164.     {
  2165.         return CAIRO_STATUS_SUCCESS;
  2166.     }
  2167.  
  2168.     n = 0;
  2169.     if (rects->bounded.width == 0 || rects->bounded.height == 0) {
  2170.         xrects[n].x = rects->unbounded.x;
  2171.         xrects[n].width = rects->unbounded.width;
  2172.         xrects[n].y = rects->unbounded.y;
  2173.         xrects[n].height = rects->unbounded.height;
  2174.         n++;
  2175.     } else {
  2176.         /* top */
  2177.         if (rects->bounded.y != rects->unbounded.y) {
  2178.             xrects[n].x = rects->unbounded.x;
  2179.             xrects[n].width = rects->unbounded.width;
  2180.             xrects[n].y = rects->unbounded.y;
  2181.             xrects[n].height = rects->bounded.y - rects->unbounded.y;
  2182.             n++;
  2183.         }
  2184.         /* left */
  2185.         if (rects->bounded.x != rects->unbounded.x) {
  2186.             xrects[n].x = rects->unbounded.x;
  2187.             xrects[n].width = rects->bounded.x - rects->unbounded.x;
  2188.             xrects[n].y = rects->bounded.y;
  2189.             xrects[n].height = rects->bounded.height;
  2190.             n++;
  2191.         }
  2192.         /* right */
  2193.         if (rects->bounded.x + rects->bounded.width != rects->unbounded.x + rects->unbounded.width) {
  2194.             xrects[n].x = rects->bounded.x + rects->bounded.width;
  2195.             xrects[n].width = rects->unbounded.x + rects->unbounded.width - xrects[n].x;
  2196.             xrects[n].y = rects->bounded.y;
  2197.             xrects[n].height = rects->bounded.height;
  2198.             n++;
  2199.         }
  2200.         /* bottom */
  2201.         if (rects->bounded.y + rects->bounded.height != rects->unbounded.y + rects->unbounded.height) {
  2202.             xrects[n].x = rects->unbounded.x;
  2203.             xrects[n].width = rects->unbounded.width;
  2204.             xrects[n].y = rects->bounded.y + rects->bounded.height;
  2205.             xrects[n].height = rects->unbounded.y + rects->unbounded.height - xrects[n].y;
  2206.             n++;
  2207.         }
  2208.     }
  2209.  
  2210.     if (dst->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES) {
  2211.         xcb_render_color_t color;
  2212.  
  2213.         color.red   = 0;
  2214.         color.green = 0;
  2215.         color.blue  = 0;
  2216.         color.alpha = 0;
  2217.  
  2218.         _cairo_xcb_connection_render_fill_rectangles (dst->connection,
  2219.                                                       XCB_RENDER_PICT_OP_CLEAR,
  2220.                                                       dst->picture,
  2221.                                                       color, n, xrects);
  2222.     } else {
  2223.         int i;
  2224.         cairo_xcb_picture_t *src;
  2225.  
  2226.         src = _cairo_xcb_transparent_picture (dst);
  2227.         if (unlikely (src->base.status))
  2228.             return src->base.status;
  2229.  
  2230.         for (i = 0; i < n; i++) {
  2231.             _cairo_xcb_connection_render_composite (dst->connection,
  2232.                                                     XCB_RENDER_PICT_OP_CLEAR,
  2233.                                                     src->picture, XCB_NONE, dst->picture,
  2234.                                                     0, 0,
  2235.                                                     0, 0,
  2236.                                                     xrects[i].x, xrects[i].y,
  2237.                                                     xrects[i].width, xrects[i].height);
  2238.         }
  2239.         cairo_surface_destroy (&src->base);
  2240.     }
  2241.  
  2242.     return CAIRO_STATUS_SUCCESS;
  2243. }
  2244.  
  2245. static cairo_status_t
  2246. _cairo_xcb_surface_fixup_unbounded_with_mask (cairo_xcb_surface_t *dst,
  2247.                                               const cairo_composite_rectangles_t *rects,
  2248.                                               cairo_clip_t *clip)
  2249. {
  2250.     cairo_xcb_surface_t *mask;
  2251.     int mask_x = 0, mask_y = 0;
  2252.  
  2253.     mask = get_clip_surface (clip, dst, &mask_x, &mask_y);
  2254.     if (unlikely (mask->base.status))
  2255.         return mask->base.status;
  2256.  
  2257.     /* top */
  2258.     if (rects->bounded.y != rects->unbounded.y) {
  2259.         int x = rects->unbounded.x;
  2260.         int y = rects->unbounded.y;
  2261.         int width = rects->unbounded.width;
  2262.         int height = rects->bounded.y - y;
  2263.  
  2264.         _cairo_xcb_connection_render_composite (dst->connection,
  2265.                                                 XCB_RENDER_PICT_OP_OUT_REVERSE,
  2266.                                                 mask->picture, XCB_NONE, dst->picture,
  2267.                                                 x - mask_x, y - mask_y,
  2268.                                                 0, 0,
  2269.                                                 x, y,
  2270.                                                 width, height);
  2271.     }
  2272.  
  2273.     /* left */
  2274.     if (rects->bounded.x != rects->unbounded.x) {
  2275.         int x = rects->unbounded.x;
  2276.         int y = rects->bounded.y;
  2277.         int width = rects->bounded.x - x;
  2278.         int height = rects->bounded.height;
  2279.  
  2280.         _cairo_xcb_connection_render_composite (dst->connection,
  2281.                                                 XCB_RENDER_PICT_OP_OUT_REVERSE,
  2282.                                                 mask->picture, XCB_NONE, dst->picture,
  2283.                                                 x - mask_x, y - mask_y,
  2284.                                                 0, 0,
  2285.                                                 x, y,
  2286.                                                 width, height);
  2287.     }
  2288.  
  2289.     /* right */
  2290.     if (rects->bounded.x + rects->bounded.width != rects->unbounded.x + rects->unbounded.width) {
  2291.         int x = rects->bounded.x + rects->bounded.width;
  2292.         int y = rects->bounded.y;
  2293.         int width = rects->unbounded.x + rects->unbounded.width - x;
  2294.         int height = rects->bounded.height;
  2295.  
  2296.         _cairo_xcb_connection_render_composite (dst->connection,
  2297.                                                 XCB_RENDER_PICT_OP_OUT_REVERSE,
  2298.                                                 mask->picture, XCB_NONE, dst->picture,
  2299.                                                 x - mask_x, y - mask_y,
  2300.                                                 0, 0,
  2301.                                                 x, y,
  2302.                                                 width, height);
  2303.     }
  2304.  
  2305.     /* bottom */
  2306.     if (rects->bounded.y + rects->bounded.height != rects->unbounded.y + rects->unbounded.height) {
  2307.         int x = rects->unbounded.x;
  2308.         int y = rects->bounded.y + rects->bounded.height;
  2309.         int width = rects->unbounded.width;
  2310.         int height = rects->unbounded.y + rects->unbounded.height - y;
  2311.  
  2312.         _cairo_xcb_connection_render_composite (dst->connection,
  2313.                                                 XCB_RENDER_PICT_OP_OUT_REVERSE,
  2314.                                                 mask->picture, XCB_NONE, dst->picture,
  2315.                                                 x - mask_x, y - mask_y,
  2316.                                                 0, 0,
  2317.                                                 x, y,
  2318.                                                 width, height);
  2319.     }
  2320.  
  2321.     cairo_surface_destroy (&mask->base);
  2322.  
  2323.     return CAIRO_STATUS_SUCCESS;
  2324. }
  2325.  
  2326. static cairo_status_t
  2327. _cairo_xcb_surface_fixup_unbounded_boxes (cairo_xcb_surface_t *dst,
  2328.                                           const cairo_composite_rectangles_t *extents,
  2329.                                           cairo_clip_t *clip,
  2330.                                           cairo_boxes_t *boxes)
  2331. {
  2332.     cairo_boxes_t clear;
  2333.     cairo_box_t box;
  2334.     cairo_status_t status;
  2335.     struct _cairo_boxes_chunk *chunk;
  2336.     int i;
  2337.  
  2338.     if (boxes->num_boxes <= 1 && clip == NULL)
  2339.         return _cairo_xcb_surface_fixup_unbounded (dst, extents);
  2340.  
  2341.     _cairo_boxes_init (&clear);
  2342.  
  2343.     box.p1.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
  2344.     box.p1.y = _cairo_fixed_from_int (extents->unbounded.y);
  2345.     box.p2.x = _cairo_fixed_from_int (extents->unbounded.x);
  2346.     box.p2.y = _cairo_fixed_from_int (extents->unbounded.y + extents->unbounded.height);
  2347.  
  2348.     if (clip == NULL) {
  2349.         cairo_boxes_t tmp;
  2350.  
  2351.         _cairo_boxes_init (&tmp);
  2352.  
  2353.         status = _cairo_boxes_add (&tmp, CAIRO_ANTIALIAS_DEFAULT, &box);
  2354.         assert (status == CAIRO_STATUS_SUCCESS);
  2355.  
  2356.         tmp.chunks.next = &boxes->chunks;
  2357.         tmp.num_boxes += boxes->num_boxes;
  2358.  
  2359.         status = _cairo_bentley_ottmann_tessellate_boxes (&tmp,
  2360.                                                           CAIRO_FILL_RULE_WINDING,
  2361.                                                           &clear);
  2362.  
  2363.         tmp.chunks.next = NULL;
  2364.     } else {
  2365.         _cairo_boxes_init_with_clip (&clear, clip);
  2366.  
  2367.         status = _cairo_boxes_add (&clear, CAIRO_ANTIALIAS_DEFAULT, &box);
  2368.         assert (status == CAIRO_STATUS_SUCCESS);
  2369.  
  2370.         for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
  2371.             for (i = 0; i < chunk->count; i++) {
  2372.                 status = _cairo_boxes_add (&clear,
  2373.                                            CAIRO_ANTIALIAS_DEFAULT,
  2374.                                            &chunk->base[i]);
  2375.                 if (unlikely (status)) {
  2376.                     _cairo_boxes_fini (&clear);
  2377.                     return status;
  2378.                 }
  2379.             }
  2380.         }
  2381.  
  2382.         status = _cairo_bentley_ottmann_tessellate_boxes (&clear,
  2383.                                                           CAIRO_FILL_RULE_WINDING,
  2384.                                                           &clear);
  2385.     }
  2386.  
  2387.     if (likely (status == CAIRO_STATUS_SUCCESS)) {
  2388.         if (dst->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES)
  2389.             status = _render_fill_boxes (dst,
  2390.                                          CAIRO_OPERATOR_CLEAR,
  2391.                                          CAIRO_COLOR_TRANSPARENT,
  2392.                                          &clear);
  2393.         else
  2394.             status = _cairo_xcb_surface_core_fill_boxes (dst,
  2395.                                                          CAIRO_COLOR_TRANSPARENT,
  2396.                                                          &clear);
  2397.     }
  2398.  
  2399.     _cairo_boxes_fini (&clear);
  2400.  
  2401.     return status;
  2402. }
  2403.  
  2404. cairo_status_t
  2405. _cairo_xcb_surface_clear (cairo_xcb_surface_t *dst)
  2406. {
  2407.     xcb_gcontext_t gc;
  2408.     xcb_rectangle_t rect;
  2409.     cairo_status_t status;
  2410.  
  2411.     status = _cairo_xcb_connection_acquire (dst->connection);
  2412.     if (unlikely (status))
  2413.         return status;
  2414.  
  2415.     rect.x = rect.y = 0;
  2416.     rect.width  = dst->width;
  2417.     rect.height = dst->height;
  2418.  
  2419.     if (dst->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES) {
  2420.         xcb_render_color_t color;
  2421.         uint8_t op;
  2422.  
  2423.         color.red   = dst->deferred_clear_color.red_short;
  2424.         color.green = dst->deferred_clear_color.green_short;
  2425.         color.blue  = dst->deferred_clear_color.blue_short;
  2426.         color.alpha = dst->deferred_clear_color.alpha_short;
  2427.  
  2428.         if (color.alpha == 0)
  2429.             op = XCB_RENDER_PICT_OP_CLEAR;
  2430.         else
  2431.             op = XCB_RENDER_PICT_OP_SRC;
  2432.  
  2433.         _cairo_xcb_surface_ensure_picture (dst);
  2434.         _cairo_xcb_connection_render_fill_rectangles (dst->connection,
  2435.                                                       op, dst->picture, color,
  2436.                                                       1, &rect);
  2437.     } else {
  2438.         gc = _cairo_xcb_screen_get_gc (dst->screen, dst->drawable, dst->depth);
  2439.  
  2440.         /* XXX color */
  2441.         _cairo_xcb_connection_poly_fill_rectangle (dst->connection,
  2442.                                                    dst->drawable, gc,
  2443.                                                    1, &rect);
  2444.  
  2445.         _cairo_xcb_screen_put_gc (dst->screen, dst->depth, gc);
  2446.     }
  2447.  
  2448.     _cairo_xcb_connection_release (dst->connection);
  2449.  
  2450.     dst->deferred_clear = FALSE;
  2451.     return CAIRO_STATUS_SUCCESS;
  2452. }
  2453.  
  2454. enum {
  2455.     NEED_CLIP_REGION = 0x1,
  2456.     NEED_CLIP_SURFACE = 0x2,
  2457.     FORCE_CLIP_REGION = 0x4,
  2458. };
  2459.  
  2460. static cairo_bool_t
  2461. need_bounded_clip (cairo_composite_rectangles_t *extents)
  2462. {
  2463.     unsigned int flags = NEED_CLIP_REGION;
  2464.     if (! _cairo_clip_is_region (extents->clip))
  2465.         flags |= NEED_CLIP_SURFACE;
  2466.     return flags;
  2467. }
  2468.  
  2469. static cairo_bool_t
  2470. need_unbounded_clip (cairo_composite_rectangles_t *extents)
  2471. {
  2472.     unsigned int flags = 0;
  2473.     if (! extents->is_bounded) {
  2474.         flags |= NEED_CLIP_REGION;
  2475.         if (! _cairo_clip_is_region (extents->clip))
  2476.             flags |= NEED_CLIP_SURFACE;
  2477.     }
  2478.     if (extents->clip->path != NULL)
  2479.         flags |= NEED_CLIP_SURFACE;
  2480.     return flags;
  2481. }
  2482.  
  2483. static cairo_status_t
  2484. _clip_and_composite (cairo_xcb_surface_t        *dst,
  2485.                      cairo_operator_t            op,
  2486.                      const cairo_pattern_t      *src,
  2487.                      xcb_draw_func_t             draw_func,
  2488.                      xcb_draw_func_t             mask_func,
  2489.                      void                       *draw_closure,
  2490.                      cairo_composite_rectangles_t*extents,
  2491.                      unsigned int need_clip)
  2492. {
  2493.     cairo_region_t *clip_region = NULL;
  2494.     cairo_status_t status;
  2495.  
  2496.     status = _cairo_xcb_connection_acquire (dst->connection);
  2497.     if (unlikely (status))
  2498.         return status;
  2499.  
  2500.     if (dst->deferred_clear) {
  2501.         status = _cairo_xcb_surface_clear (dst);
  2502.         if (unlikely (status)) {
  2503.             _cairo_xcb_connection_release (dst->connection);
  2504.             return status;
  2505.         }
  2506.     }
  2507.  
  2508.     _cairo_xcb_surface_ensure_picture (dst);
  2509.  
  2510.     if (need_clip & NEED_CLIP_REGION) {
  2511.         clip_region = _cairo_clip_get_region (extents->clip);
  2512.         if ((need_clip & FORCE_CLIP_REGION) == 0 && clip_region != NULL &&
  2513.             cairo_region_contains_rectangle (clip_region,
  2514.                                              &extents->unbounded) == CAIRO_REGION_OVERLAP_IN)
  2515.             clip_region = NULL;
  2516.         if (clip_region != NULL) {
  2517.             status = _cairo_xcb_surface_set_clip_region (dst, clip_region);
  2518.             if (unlikely (status)) {
  2519.                 _cairo_xcb_connection_release (dst->connection);
  2520.                 return status;
  2521.             }
  2522.         }
  2523.     }
  2524.  
  2525.     if (reduce_alpha_op (&dst->base, op, src)) {
  2526.         op = CAIRO_OPERATOR_ADD;
  2527.         src = NULL;
  2528.     }
  2529.  
  2530.     if (extents->bounded.width != 0 && extents->bounded.height != 0) {
  2531.         if (op == CAIRO_OPERATOR_SOURCE) {
  2532.             status = _clip_and_composite_source (extents->clip, src,
  2533.                                                  draw_func, mask_func, draw_closure,
  2534.                                                  dst, &extents->bounded);
  2535.         } else {
  2536.             if (op == CAIRO_OPERATOR_CLEAR) {
  2537.                 op = CAIRO_OPERATOR_DEST_OUT;
  2538.                 src = NULL;
  2539.             }
  2540.  
  2541.             if (need_clip & NEED_CLIP_SURFACE) {
  2542.                 if (extents->is_bounded) {
  2543.                     status = _clip_and_composite_with_mask (extents->clip, op, src,
  2544.                                                             draw_func,
  2545.                                                             mask_func,
  2546.                                                             draw_closure,
  2547.                                                             dst, &extents->bounded);
  2548.                 } else {
  2549.                     status = _clip_and_composite_combine (extents->clip, op, src,
  2550.                                                           draw_func, draw_closure,
  2551.                                                           dst, &extents->bounded);
  2552.                 }
  2553.             } else {
  2554.                 status = draw_func (draw_closure,
  2555.                                     dst, op, src,
  2556.                                     0, 0,
  2557.                                     &extents->bounded,
  2558.                                     extents->clip);
  2559.             }
  2560.         }
  2561.     }
  2562.  
  2563.     if (status == CAIRO_STATUS_SUCCESS && ! extents->is_bounded) {
  2564.         if (need_clip & NEED_CLIP_SURFACE)
  2565.             status = _cairo_xcb_surface_fixup_unbounded_with_mask (dst, extents, extents->clip);
  2566.         else
  2567.             status = _cairo_xcb_surface_fixup_unbounded (dst, extents);
  2568.     }
  2569.  
  2570.     if (clip_region)
  2571.         _cairo_xcb_surface_clear_clip_region (dst);
  2572.  
  2573.     _cairo_xcb_connection_release (dst->connection);
  2574.  
  2575.     return status;
  2576. }
  2577.  
  2578. static cairo_status_t
  2579. _core_boxes (cairo_xcb_surface_t *dst,
  2580.              cairo_operator_t op,
  2581.              const cairo_pattern_t *src,
  2582.              cairo_boxes_t *boxes,
  2583.              const cairo_composite_rectangles_t *extents)
  2584. {
  2585.     if (! boxes->is_pixel_aligned)
  2586.         return CAIRO_INT_STATUS_UNSUPPORTED;
  2587.  
  2588.     if (! _cairo_clip_is_region (extents->clip))
  2589.         return CAIRO_INT_STATUS_UNSUPPORTED;
  2590.  
  2591.     if (op == CAIRO_OPERATOR_CLEAR)
  2592.         return _cairo_xcb_surface_core_fill_boxes (dst, CAIRO_COLOR_TRANSPARENT, boxes);
  2593.  
  2594.     if (op == CAIRO_OPERATOR_OVER) {
  2595.         if (dst->base.is_clear || _cairo_pattern_is_opaque (src, &extents->bounded))
  2596.             op = CAIRO_OPERATOR_SOURCE;
  2597.     }
  2598.     if (op != CAIRO_OPERATOR_SOURCE)
  2599.         return CAIRO_INT_STATUS_UNSUPPORTED;
  2600.  
  2601.     if (src->type == CAIRO_PATTERN_TYPE_SOLID) {
  2602.         return _cairo_xcb_surface_core_fill_boxes (dst,
  2603.                                                    &((cairo_solid_pattern_t *) src)->color,
  2604.                                                    boxes);
  2605.     }
  2606.  
  2607.     return _cairo_xcb_surface_core_copy_boxes (dst, src, &extents->bounded, boxes);
  2608. }
  2609.  
  2610. static cairo_status_t
  2611. _composite_boxes (cairo_xcb_surface_t *dst,
  2612.                   cairo_operator_t op,
  2613.                   const cairo_pattern_t *src,
  2614.                   cairo_boxes_t *boxes,
  2615.                   const cairo_composite_rectangles_t *extents)
  2616. {
  2617.     cairo_clip_t *clip = extents->clip;
  2618.     cairo_bool_t need_clip_mask = ! _cairo_clip_is_region (clip);
  2619.     cairo_status_t status;
  2620.  
  2621.     /* If the boxes are not pixel-aligned, we will need to compute a real mask */
  2622.     if (! boxes->is_pixel_aligned)
  2623.         return CAIRO_INT_STATUS_UNSUPPORTED;
  2624.  
  2625.     if (need_clip_mask &&
  2626.         (! extents->is_bounded || op == CAIRO_OPERATOR_SOURCE))
  2627.     {
  2628.         return CAIRO_INT_STATUS_UNSUPPORTED;
  2629.     }
  2630.  
  2631.     status = _cairo_xcb_connection_acquire (dst->connection);
  2632.     if (unlikely (status))
  2633.         return status;
  2634.  
  2635.     _cairo_xcb_surface_ensure_picture (dst);
  2636.     if (dst->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES && ! need_clip_mask &&
  2637.         (op == CAIRO_OPERATOR_CLEAR || src->type == CAIRO_PATTERN_TYPE_SOLID))
  2638.     {
  2639.         const cairo_color_t *color;
  2640.  
  2641.         if (op == CAIRO_OPERATOR_CLEAR)
  2642.             color = CAIRO_COLOR_TRANSPARENT;
  2643.         else
  2644.             color = &((cairo_solid_pattern_t *) src)->color;
  2645.  
  2646.         status = _render_fill_boxes (dst, op, color, boxes);
  2647.     }
  2648.     else
  2649.     {
  2650.         cairo_surface_pattern_t mask;
  2651.  
  2652.         if (need_clip_mask) {
  2653.             cairo_xcb_surface_t *clip_surface;
  2654.             int clip_x = 0, clip_y = 0;
  2655.  
  2656.             clip_surface = get_clip_surface (extents->clip, dst,
  2657.                                              &clip_x, &clip_y);
  2658.             if (unlikely (clip_surface->base.status))
  2659.                 return clip_surface->base.status;
  2660.  
  2661.             _cairo_pattern_init_for_surface (&mask, &clip_surface->base);
  2662.             mask.base.filter = CAIRO_FILTER_NEAREST;
  2663.             cairo_matrix_init_translate (&mask.base.matrix,
  2664.                                          -clip_x,
  2665.                                          -clip_y);
  2666.             cairo_surface_destroy (&clip_surface->base);
  2667.  
  2668.             if (op == CAIRO_OPERATOR_CLEAR) {
  2669.                 src = NULL;
  2670.                 op = CAIRO_OPERATOR_DEST_OUT;
  2671.             }
  2672.         }
  2673.  
  2674.         status = _render_composite_boxes (dst, op, src,
  2675.                                           need_clip_mask ? &mask.base : NULL,
  2676.                                           &extents->bounded, boxes);
  2677.  
  2678.         if (need_clip_mask)
  2679.             _cairo_pattern_fini (&mask.base);
  2680.     }
  2681.  
  2682.     if (status == CAIRO_STATUS_SUCCESS && ! extents->is_bounded) {
  2683.         status =
  2684.             _cairo_xcb_surface_fixup_unbounded_boxes (dst, extents,
  2685.                                                       clip, boxes);
  2686.     }
  2687.  
  2688.     _cairo_xcb_connection_release (dst->connection);
  2689.  
  2690.     return status;
  2691. }
  2692.  
  2693. static cairo_bool_t
  2694. cairo_boxes_for_each_box (cairo_boxes_t *boxes,
  2695.                           cairo_bool_t (*func) (cairo_box_t *box,
  2696.                                                 void *data),
  2697.                           void *data)
  2698. {
  2699.     struct _cairo_boxes_chunk *chunk;
  2700.     int i;
  2701.  
  2702.     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
  2703.         for (i = 0; i < chunk->count; i++)
  2704.             if (! func (&chunk->base[i], data))
  2705.                 return FALSE;
  2706.     }
  2707.  
  2708.     return TRUE;
  2709. }
  2710.  
  2711. struct _image_contains_box {
  2712.     int width, height;
  2713.     int tx, ty;
  2714. };
  2715.  
  2716. static cairo_bool_t image_contains_box (cairo_box_t *box, void *closure)
  2717. {
  2718.     struct _image_contains_box *data = closure;
  2719.  
  2720.     /* The box is pixel-aligned so the truncation is safe. */
  2721.     return
  2722.         _cairo_fixed_integer_part (box->p1.x) + data->tx >= 0 &&
  2723.         _cairo_fixed_integer_part (box->p1.y) + data->ty >= 0 &&
  2724.         _cairo_fixed_integer_part (box->p2.x) + data->tx <= data->width &&
  2725.         _cairo_fixed_integer_part (box->p2.y) + data->ty <= data->height;
  2726. }
  2727.  
  2728. struct _image_upload_box {
  2729.     cairo_xcb_surface_t *surface;
  2730.     cairo_image_surface_t *image;
  2731.     xcb_gcontext_t gc;
  2732.     int tx, ty;
  2733. };
  2734.  
  2735. static cairo_bool_t image_upload_box (cairo_box_t *box, void *closure)
  2736. {
  2737.     const struct _image_upload_box *iub = closure;
  2738.     /* The box is pixel-aligned so the truncation is safe. */
  2739.     int x = _cairo_fixed_integer_part (box->p1.x);
  2740.     int y = _cairo_fixed_integer_part (box->p1.y);
  2741.     int width  = _cairo_fixed_integer_part (box->p2.x - box->p1.x);
  2742.     int height = _cairo_fixed_integer_part (box->p2.y - box->p1.y);
  2743.     int bpp = PIXMAN_FORMAT_BPP (iub->image->pixman_format);
  2744.     int len = CAIRO_STRIDE_FOR_WIDTH_BPP (width, bpp);
  2745.     if (len == iub->image->stride) {
  2746.         _cairo_xcb_connection_put_image (iub->surface->connection,
  2747.                                          iub->surface->drawable,
  2748.                                          iub->gc,
  2749.                                          width, height,
  2750.                                          x, y,
  2751.                                          iub->image->depth,
  2752.                                          iub->image->stride,
  2753.                                          iub->image->data +
  2754.                                          (y + iub->ty) * iub->image->stride +
  2755.                                          (x + iub->tx) * bpp/8);
  2756.     } else {
  2757.         _cairo_xcb_connection_put_subimage (iub->surface->connection,
  2758.                                             iub->surface->drawable,
  2759.                                             iub->gc,
  2760.                                             x + iub->tx,
  2761.                                             y + iub->ty,
  2762.                                             width, height,
  2763.                                             bpp / 8,
  2764.                                             iub->image->stride,
  2765.                                             x, y,
  2766.                                             iub->image->depth,
  2767.                                             iub->image->data);
  2768.     }
  2769.  
  2770.     return TRUE;
  2771. }
  2772.  
  2773. static cairo_status_t
  2774. _upload_image_inplace (cairo_xcb_surface_t *surface,
  2775.                        const cairo_pattern_t *source,
  2776.                        cairo_boxes_t *boxes)
  2777. {
  2778.     const cairo_surface_pattern_t *pattern;
  2779.     struct _image_contains_box icb;
  2780.     struct _image_upload_box iub;
  2781.     cairo_image_surface_t *image;
  2782.     cairo_status_t status;
  2783.     int tx, ty;
  2784.  
  2785.     if (! boxes->is_pixel_aligned)
  2786.         return CAIRO_INT_STATUS_UNSUPPORTED;
  2787.  
  2788.     if (source->type != CAIRO_PATTERN_TYPE_SURFACE)
  2789.         return CAIRO_INT_STATUS_UNSUPPORTED;
  2790.  
  2791.     pattern = (const cairo_surface_pattern_t *) source;
  2792.     if (pattern->surface->type != CAIRO_SURFACE_TYPE_IMAGE)
  2793.         return CAIRO_INT_STATUS_UNSUPPORTED;
  2794.  
  2795.     /* Have we already upload this image to a pixmap? */
  2796.     {
  2797.         cairo_xcb_picture_t *snapshot;
  2798.  
  2799.         snapshot = (cairo_xcb_picture_t *)
  2800.             _cairo_surface_has_snapshot (pattern->surface, &_cairo_xcb_picture_backend);
  2801.         if (snapshot != NULL) {
  2802.             if (snapshot->screen == surface->screen)
  2803.                 return CAIRO_INT_STATUS_UNSUPPORTED;
  2804.         }
  2805.     }
  2806.  
  2807.     image = (cairo_image_surface_t *) pattern->surface;
  2808.     if (image->format == CAIRO_FORMAT_INVALID)
  2809.         return CAIRO_INT_STATUS_UNSUPPORTED;
  2810.  
  2811.     if (image->depth != surface->depth)
  2812.         return CAIRO_INT_STATUS_UNSUPPORTED;
  2813.  
  2814.     if (! _cairo_matrix_is_integer_translation (&source->matrix, &tx, &ty))
  2815.         return CAIRO_INT_STATUS_UNSUPPORTED;
  2816.  
  2817.     /* Check that the data is entirely within the image */
  2818.     icb.width = image->width;
  2819.     icb.height = image->height;
  2820.     icb.tx = tx;
  2821.     icb.ty = ty;
  2822.     if (! cairo_boxes_for_each_box (boxes, image_contains_box, &icb))
  2823.         return CAIRO_INT_STATUS_UNSUPPORTED;
  2824.  
  2825.     if (surface->deferred_clear) {
  2826.         status = _cairo_xcb_surface_clear (surface);
  2827.         if (unlikely (status))
  2828.             return status;
  2829.     }
  2830.  
  2831.     status = _cairo_xcb_connection_acquire (surface->connection);
  2832.     if (unlikely (status))
  2833.         return status;
  2834.  
  2835.     iub.surface = surface;
  2836.     iub.image = image;
  2837.     iub.gc = _cairo_xcb_screen_get_gc (surface->screen,
  2838.                                        surface->drawable,
  2839.                                        image->depth);
  2840.     iub.tx = tx;
  2841.     iub.ty = ty;
  2842.     cairo_boxes_for_each_box (boxes, image_upload_box, &iub);
  2843.  
  2844.     _cairo_xcb_screen_put_gc (surface->screen, image->depth, iub.gc);
  2845.     _cairo_xcb_connection_release (surface->connection);
  2846.  
  2847.     return CAIRO_STATUS_SUCCESS;
  2848. }
  2849.  
  2850. static cairo_int_status_t
  2851. trim_extents_to_traps (cairo_composite_rectangles_t *extents,
  2852.                        cairo_traps_t *traps)
  2853. {
  2854.     cairo_box_t box;
  2855.  
  2856.     /* X trims the affected area to the extents of the trapezoids, so
  2857.      * we need to compensate when fixing up the unbounded area.
  2858.     */
  2859.     _cairo_traps_extents (traps, &box);
  2860.     return _cairo_composite_rectangles_intersect_mask_extents (extents, &box);
  2861. }
  2862.  
  2863. static cairo_bool_t
  2864. _mono_edge_is_vertical (const cairo_line_t *line)
  2865. {
  2866.     return _cairo_fixed_integer_round_down (line->p1.x) == _cairo_fixed_integer_round_down (line->p2.x);
  2867. }
  2868.  
  2869. static cairo_bool_t
  2870. _traps_are_pixel_aligned (cairo_traps_t *traps,
  2871.                           cairo_antialias_t antialias)
  2872. {
  2873.     int i;
  2874.  
  2875.     if (antialias == CAIRO_ANTIALIAS_NONE) {
  2876.         for (i = 0; i < traps->num_traps; i++) {
  2877.             if (! _mono_edge_is_vertical (&traps->traps[i].left)   ||
  2878.                 ! _mono_edge_is_vertical (&traps->traps[i].right))
  2879.             {
  2880.                 traps->maybe_region = FALSE;
  2881.                 return FALSE;
  2882.             }
  2883.         }
  2884.     } else {
  2885.         for (i = 0; i < traps->num_traps; i++) {
  2886.             if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x   ||
  2887.                 traps->traps[i].right.p1.x != traps->traps[i].right.p2.x ||
  2888.                 ! _cairo_fixed_is_integer (traps->traps[i].top)          ||
  2889.                 ! _cairo_fixed_is_integer (traps->traps[i].bottom)       ||
  2890.                 ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x)    ||
  2891.                 ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
  2892.             {
  2893.                 traps->maybe_region = FALSE;
  2894.                 return FALSE;
  2895.             }
  2896.         }
  2897.     }
  2898.  
  2899.     return TRUE;
  2900. }
  2901.  
  2902. static void
  2903. _boxes_for_traps (cairo_boxes_t *boxes,
  2904.                   cairo_traps_t *traps,
  2905.                   cairo_antialias_t antialias)
  2906. {
  2907.     int i;
  2908.  
  2909.     _cairo_boxes_init (boxes);
  2910.  
  2911.     boxes->num_boxes    = traps->num_traps;
  2912.     boxes->chunks.base  = (cairo_box_t *) traps->traps;
  2913.     boxes->chunks.count = traps->num_traps;
  2914.     boxes->chunks.size  = traps->num_traps;
  2915.  
  2916.     if (antialias != CAIRO_ANTIALIAS_NONE) {
  2917.         for (i = 0; i < traps->num_traps; i++) {
  2918.             /* Note the traps and boxes alias so we need to take the local copies first. */
  2919.             cairo_fixed_t x1 = traps->traps[i].left.p1.x;
  2920.             cairo_fixed_t x2 = traps->traps[i].right.p1.x;
  2921.             cairo_fixed_t y1 = traps->traps[i].top;
  2922.             cairo_fixed_t y2 = traps->traps[i].bottom;
  2923.  
  2924.             boxes->chunks.base[i].p1.x = x1;
  2925.             boxes->chunks.base[i].p1.y = y1;
  2926.             boxes->chunks.base[i].p2.x = x2;
  2927.             boxes->chunks.base[i].p2.y = y2;
  2928.  
  2929.             if (boxes->is_pixel_aligned) {
  2930.                 boxes->is_pixel_aligned =
  2931.                     _cairo_fixed_is_integer (x1) && _cairo_fixed_is_integer (y1) &&
  2932.                     _cairo_fixed_is_integer (x2) && _cairo_fixed_is_integer (y2);
  2933.             }
  2934.         }
  2935.     } else {
  2936.         boxes->is_pixel_aligned = TRUE;
  2937.  
  2938.         for (i = 0; i < traps->num_traps; i++) {
  2939.             /* Note the traps and boxes alias so we need to take the local copies first. */
  2940.             cairo_fixed_t x1 = traps->traps[i].left.p1.x;
  2941.             cairo_fixed_t x2 = traps->traps[i].right.p1.x;
  2942.             cairo_fixed_t y1 = traps->traps[i].top;
  2943.             cairo_fixed_t y2 = traps->traps[i].bottom;
  2944.  
  2945.             /* round down here to match Pixman's behavior when using traps. */
  2946.             boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (x1);
  2947.             boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (y1);
  2948.             boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (x2);
  2949.             boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (y2);
  2950.         }
  2951.     }
  2952. }
  2953.  
  2954. static cairo_status_t
  2955. _composite_polygon (cairo_xcb_surface_t *dst,
  2956.                     cairo_operator_t op,
  2957.                     const cairo_pattern_t *source,
  2958.                     cairo_polygon_t *polygon,
  2959.                     cairo_antialias_t antialias,
  2960.                     cairo_fill_rule_t fill_rule,
  2961.                     cairo_composite_rectangles_t *extents)
  2962. {
  2963.     composite_traps_info_t traps;
  2964.     cairo_bool_t clip_surface = ! _cairo_clip_is_region (extents->clip);
  2965.     cairo_region_t *clip_region = _cairo_clip_get_region (extents->clip);
  2966.     cairo_status_t status;
  2967.  
  2968.     if (polygon->num_edges == 0) {
  2969.         status = CAIRO_STATUS_SUCCESS;
  2970.  
  2971.         if (! extents->is_bounded) {
  2972.             if (cairo_region_contains_rectangle (clip_region, &extents->unbounded) == CAIRO_REGION_OVERLAP_IN)
  2973.                 clip_region = NULL;
  2974.  
  2975.             if (clip_surface == FALSE) {
  2976.                 if (clip_region != NULL) {
  2977.                     status = _cairo_xcb_surface_set_clip_region (dst, clip_region);
  2978.                     if (unlikely (status))
  2979.                         return status;
  2980.                 }
  2981.  
  2982.                 status = _cairo_xcb_surface_fixup_unbounded (dst, extents);
  2983.  
  2984.                 if (clip_region != NULL)
  2985.                     _cairo_xcb_surface_clear_clip_region (dst);
  2986.             } else {
  2987.                 status = _cairo_xcb_surface_fixup_unbounded_with_mask (dst,
  2988.                                                                        extents,
  2989.                                                                        extents->clip);
  2990.             }
  2991.         }
  2992.  
  2993.         return status;
  2994.     }
  2995.  
  2996.     if (extents->clip->path != NULL && extents->is_bounded) {
  2997.         cairo_polygon_t clipper;
  2998.         cairo_fill_rule_t clipper_fill_rule;
  2999.         cairo_antialias_t clipper_antialias;
  3000.  
  3001.         status = _cairo_clip_get_polygon (extents->clip,
  3002.                                           &clipper,
  3003.                                           &clipper_fill_rule,
  3004.                                           &clipper_antialias);
  3005.         if (likely (status == CAIRO_STATUS_SUCCESS)) {
  3006.             if (clipper_antialias == antialias) {
  3007.                 status = _cairo_polygon_intersect (polygon, fill_rule,
  3008.                                                    &clipper, clipper_fill_rule);
  3009.                 if (likely (status == CAIRO_STATUS_SUCCESS)) {
  3010.                     cairo_clip_t * clip = _cairo_clip_copy_region (extents->clip);
  3011.                     _cairo_clip_destroy (extents->clip);
  3012.                     extents->clip = clip;
  3013.  
  3014.                     fill_rule = CAIRO_FILL_RULE_WINDING;
  3015.                 }
  3016.                 _cairo_polygon_fini (&clipper);
  3017.             }
  3018.         }
  3019.     }
  3020.  
  3021.     _cairo_traps_init (&traps.traps);
  3022.  
  3023.     status = _cairo_bentley_ottmann_tessellate_polygon (&traps.traps, polygon, fill_rule);
  3024.     if (unlikely (status))
  3025.         goto CLEANUP_TRAPS;
  3026.  
  3027.     if (traps.traps.has_intersections) {
  3028.         if (traps.traps.is_rectangular)
  3029.             status = _cairo_bentley_ottmann_tessellate_rectangular_traps (&traps.traps, CAIRO_FILL_RULE_WINDING);
  3030.         else if (traps.traps.is_rectilinear)
  3031.             status = _cairo_bentley_ottmann_tessellate_rectilinear_traps (&traps.traps, CAIRO_FILL_RULE_WINDING);
  3032.         else
  3033.             status = _cairo_bentley_ottmann_tessellate_traps (&traps.traps, CAIRO_FILL_RULE_WINDING);
  3034.         if (unlikely (status))
  3035.             goto CLEANUP_TRAPS;
  3036.     }
  3037.  
  3038.     /* Use a fast path if the trapezoids consist of a simple region,
  3039.      * but we can only do this if we do not have a clip surface, or can
  3040.      * substitute the mask with the clip.
  3041.      */
  3042.     if (traps.traps.maybe_region &&
  3043.         _traps_are_pixel_aligned (&traps.traps, antialias) &&
  3044.         (! clip_surface ||
  3045.          (extents->is_bounded && op != CAIRO_OPERATOR_SOURCE)))
  3046.     {
  3047.         cairo_boxes_t boxes;
  3048.  
  3049.         _boxes_for_traps (&boxes, &traps.traps, antialias);
  3050.         status = _clip_and_composite_boxes (dst, op, source, &boxes, extents);
  3051.     }
  3052.     else
  3053.     {
  3054.         /* Otherwise render the trapezoids to a mask and composite in the usual
  3055.          * fashion.
  3056.          */
  3057.         traps.antialias = antialias;
  3058.         status = trim_extents_to_traps (extents, &traps.traps);
  3059.         if (likely (status == CAIRO_STATUS_SUCCESS)) {
  3060.             unsigned int flags = 0;
  3061.  
  3062.             /* For unbounded operations, the X11 server will estimate the
  3063.              * affected rectangle and apply the operation to that. However,
  3064.              * there are cases where this is an overestimate (e.g. the
  3065.              * clip-fill-{eo,nz}-unbounded test).
  3066.              *
  3067.              * The clip will trim that overestimate to our expectations.
  3068.              */
  3069.             if (! extents->is_bounded)
  3070.                 flags |= FORCE_CLIP_REGION;
  3071.  
  3072.             status = _clip_and_composite (dst, op, source, _composite_traps,
  3073.                                           NULL, &traps, extents,
  3074.                                           need_unbounded_clip (extents) | flags);
  3075.         }
  3076.     }
  3077.  
  3078. CLEANUP_TRAPS:
  3079.     _cairo_traps_fini (&traps.traps);
  3080.  
  3081.     return status;
  3082. }
  3083.  
  3084. static cairo_status_t
  3085. _clip_and_composite_boxes (cairo_xcb_surface_t *dst,
  3086.                            cairo_operator_t op,
  3087.                            const cairo_pattern_t *src,
  3088.                            cairo_boxes_t *boxes,
  3089.                            cairo_composite_rectangles_t *extents)
  3090. {
  3091.     composite_traps_info_t info;
  3092.     cairo_int_status_t status;
  3093.  
  3094.     if (boxes->num_boxes == 0 && extents->is_bounded)
  3095.         return CAIRO_STATUS_SUCCESS;
  3096.  
  3097.     if (boxes->is_pixel_aligned && _cairo_clip_is_region (extents->clip) &&
  3098.         (op == CAIRO_OPERATOR_SOURCE ||
  3099.          (dst->base.is_clear && (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD))))
  3100.     {
  3101.         if (boxes->num_boxes == 1 &&
  3102.             extents->bounded.width  == dst->width &&
  3103.             extents->bounded.height == dst->height)
  3104.         {
  3105.             op = CAIRO_OPERATOR_SOURCE;
  3106.             dst->deferred_clear = FALSE;
  3107.         }
  3108.  
  3109.         status = _upload_image_inplace (dst, src, boxes);
  3110.         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
  3111.             return status;
  3112.     }
  3113.  
  3114.     /* Can we reduce drawing through a clip-mask to simply drawing the clip? */
  3115.     if (dst->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS &&
  3116.             extents->clip->path != NULL && extents->is_bounded) {
  3117.         cairo_polygon_t polygon;
  3118.         cairo_fill_rule_t fill_rule;
  3119.         cairo_antialias_t antialias;
  3120.         cairo_clip_t *clip;
  3121.  
  3122.         clip = _cairo_clip_copy (extents->clip);
  3123.         clip = _cairo_clip_intersect_boxes (clip, boxes);
  3124.         status = _cairo_clip_get_polygon (clip, &polygon,
  3125.                                           &fill_rule, &antialias);
  3126.         _cairo_clip_path_destroy (clip->path);
  3127.         clip->path = NULL;
  3128.         if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
  3129.             cairo_clip_t *saved_clip = extents->clip;
  3130.             extents->clip = clip;
  3131.             status = _composite_polygon (dst, op, src,
  3132.                                          &polygon,
  3133.                                          antialias,
  3134.                                          fill_rule,
  3135.                                          extents);
  3136.             if (extents->clip != clip)
  3137.                 clip = NULL;
  3138.             extents->clip = saved_clip;
  3139.             _cairo_polygon_fini (&polygon);
  3140.         }
  3141.         if (clip)
  3142.             _cairo_clip_destroy (clip);
  3143.  
  3144.         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
  3145.             return status;
  3146.     }
  3147.  
  3148.     if (dst->deferred_clear) {
  3149.         status = _cairo_xcb_surface_clear (dst);
  3150.         if (unlikely (status))
  3151.             return status;
  3152.     }
  3153.  
  3154.     if (boxes->is_pixel_aligned &&
  3155.         _cairo_clip_is_region (extents->clip) &&
  3156.         op == CAIRO_OPERATOR_SOURCE) {
  3157.         status = _upload_image_inplace (dst, src, boxes);
  3158.         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
  3159.             return status;
  3160.     }
  3161.  
  3162.     if ((dst->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) == 0)
  3163.         return _core_boxes (dst, op, src, boxes, extents);
  3164.  
  3165.     /* Use a fast path if the boxes are pixel aligned */
  3166.     status = _composite_boxes (dst, op, src, boxes, extents);
  3167.     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
  3168.         return status;
  3169.  
  3170.     if ((dst->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS) == 0)
  3171.         return CAIRO_INT_STATUS_UNSUPPORTED;
  3172.  
  3173.     /* Otherwise render via a mask and composite in the usual fashion.  */
  3174.     status = _cairo_traps_init_boxes (&info.traps, boxes);
  3175.     if (unlikely (status))
  3176.         return status;
  3177.  
  3178.     info.antialias = CAIRO_ANTIALIAS_DEFAULT;
  3179.     status = trim_extents_to_traps (extents, &info.traps);
  3180.     if (status == CAIRO_INT_STATUS_SUCCESS) {
  3181.         status = _clip_and_composite (dst, op, src,
  3182.                                       _composite_traps, NULL, &info,
  3183.                                       extents, need_unbounded_clip (extents));
  3184.     }
  3185.  
  3186.     _cairo_traps_fini (&info.traps);
  3187.     return status;
  3188. }
  3189.  
  3190. static cairo_int_status_t
  3191. _composite_mask (void                           *closure,
  3192.                  cairo_xcb_surface_t            *dst,
  3193.                  cairo_operator_t                op,
  3194.                  const cairo_pattern_t          *src_pattern,
  3195.                  int                             dst_x,
  3196.                  int                             dst_y,
  3197.                  const cairo_rectangle_int_t    *extents,
  3198.                  cairo_clip_t                   *clip)
  3199. {
  3200.     const cairo_pattern_t *mask_pattern = closure;
  3201.     cairo_xcb_picture_t *src, *mask = NULL;
  3202.     cairo_status_t status;
  3203.  
  3204.     if (dst->base.is_clear) {
  3205.         if (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD)
  3206.             op = CAIRO_OPERATOR_SOURCE;
  3207.     }
  3208.  
  3209.     if (op == CAIRO_OPERATOR_SOURCE && clip == NULL)
  3210.         dst->deferred_clear = FALSE;
  3211.  
  3212.     if (dst->deferred_clear) {
  3213.         status = _cairo_xcb_surface_clear (dst);
  3214.         if (unlikely (status))
  3215.                 return status;
  3216.     }
  3217.  
  3218.     if (src_pattern != NULL) {
  3219.         src = _cairo_xcb_picture_for_pattern (dst, src_pattern, extents);
  3220.         if (unlikely (src->base.status))
  3221.             return src->base.status;
  3222.  
  3223.         mask = _cairo_xcb_picture_for_pattern (dst, mask_pattern, extents);
  3224.         if (unlikely (mask->base.status)) {
  3225.             cairo_surface_destroy (&src->base);
  3226.             return mask->base.status;
  3227.         }
  3228.  
  3229.         _cairo_xcb_connection_render_composite (dst->connection,
  3230.                                                 _render_operator (op),
  3231.                                                 src->picture,
  3232.                                                 mask->picture,
  3233.                                                 dst->picture,
  3234.                                                 extents->x + src->x,  extents->y + src->y,
  3235.                                                 extents->x + mask->x, extents->y + mask->y,
  3236.                                                 extents->x - dst_x,   extents->y - dst_y,
  3237.                                                 extents->width,       extents->height);
  3238.         cairo_surface_destroy (&mask->base);
  3239.         cairo_surface_destroy (&src->base);
  3240.     } else {
  3241.         src = _cairo_xcb_picture_for_pattern (dst, mask_pattern, extents);
  3242.         if (unlikely (src->base.status))
  3243.             return src->base.status;
  3244.  
  3245.         _cairo_xcb_connection_render_composite (dst->connection,
  3246.                                                 _render_operator (op),
  3247.                                                 src->picture,
  3248.                                                 XCB_NONE,
  3249.                                                 dst->picture,
  3250.                                                 extents->x + src->x,  extents->y + src->y,
  3251.                                                 0, 0,
  3252.                                                 extents->x - dst_x,   extents->y - dst_y,
  3253.                                                 extents->width,       extents->height);
  3254.         cairo_surface_destroy (&src->base);
  3255.     }
  3256.  
  3257.     return CAIRO_STATUS_SUCCESS;
  3258. }
  3259.  
  3260. struct composite_box_info {
  3261.     cairo_xcb_surface_t *dst;
  3262.     cairo_xcb_picture_t *src;
  3263.     uint8_t op;
  3264. };
  3265.  
  3266. static void composite_box(void *closure,
  3267.                           int16_t x, int16_t y,
  3268.                           int16_t w, int16_t h,
  3269.                           uint16_t coverage)
  3270. {
  3271.     struct composite_box_info *info = closure;
  3272.  
  3273.     if (coverage < 0xff00) {
  3274.         cairo_xcb_picture_t *mask;
  3275.         cairo_color_t color;
  3276.  
  3277.         color.red_short = color.green_short = color.blue_short = 0;
  3278.         color.alpha_short = coverage;
  3279.  
  3280.         mask = _solid_picture (info->dst, &color);
  3281.         if (likely (mask->base.status == CAIRO_STATUS_SUCCESS)) {
  3282.             _cairo_xcb_connection_render_composite (info->dst->connection,
  3283.                                                     info->op,
  3284.                                                     info->src->picture,
  3285.                                                     mask->picture,
  3286.                                                     info->dst->picture,
  3287.                                                     x + info->src->x,  y + info->src->y,
  3288.                                                     0,                 0,
  3289.                                                     x,                 y,
  3290.                                                     w,                 h);
  3291.         }
  3292.         cairo_surface_destroy (&mask->base);
  3293.     } else {
  3294.         _cairo_xcb_connection_render_composite (info->dst->connection,
  3295.                                                 info->op,
  3296.                                                 info->src->picture,
  3297.                                                 XCB_NONE,
  3298.                                                 info->dst->picture,
  3299.                                                 x + info->src->x,  y + info->src->y,
  3300.                                                 0,                 0,
  3301.                                                 x,                 y,
  3302.                                                 w,                 h);
  3303.     }
  3304. }
  3305.  
  3306. static cairo_int_status_t
  3307. _composite_mask_clip_boxes (void                        *closure,
  3308.                             cairo_xcb_surface_t         *dst,
  3309.                             cairo_operator_t             op,
  3310.                             const cairo_pattern_t       *src_pattern,
  3311.                             int                          dst_x,
  3312.                             int                          dst_y,
  3313.                             const cairo_rectangle_int_t *extents,
  3314.                             cairo_clip_t                *clip)
  3315. {
  3316.     struct composite_box_info info;
  3317.     cairo_status_t status;
  3318.     int i;
  3319.  
  3320.     assert (src_pattern == NULL);
  3321.     assert (op == CAIRO_OPERATOR_ADD);
  3322.     assert (dst->base.is_clear);
  3323.  
  3324.     if (clip->num_boxes > 1) {
  3325.         status = _cairo_xcb_surface_clear (dst);
  3326.         if (unlikely (status))
  3327.             return status;
  3328.     }
  3329.  
  3330.     info.op = XCB_RENDER_PICT_OP_SRC;
  3331.     info.dst = dst;
  3332.     info.src = _cairo_xcb_picture_for_pattern (dst, closure, extents);
  3333.     if (unlikely (info.src->base.status))
  3334.         return info.src->base.status;
  3335.  
  3336.     info.src->x += dst_x;
  3337.     info.src->y += dst_y;
  3338.  
  3339.     for (i = 0; i < clip->num_boxes; i++)
  3340.         do_unaligned_box(composite_box, &info, &clip->boxes[i], dst_x, dst_y);
  3341.     cairo_surface_destroy (&info.src->base);
  3342.  
  3343.     return CAIRO_STATUS_SUCCESS;
  3344. }
  3345.  
  3346. static cairo_int_status_t
  3347. _composite_mask_clip (void                              *closure,
  3348.                       cairo_xcb_surface_t               *dst,
  3349.                       cairo_operator_t                   op,
  3350.                       const cairo_pattern_t             *src_pattern,
  3351.                       int                                dst_x,
  3352.                       int                                dst_y,
  3353.                       const cairo_rectangle_int_t       *extents,
  3354.                       cairo_clip_t                      *clip)
  3355. {
  3356.     const cairo_pattern_t *mask_pattern = closure;
  3357.     cairo_polygon_t polygon;
  3358.     cairo_fill_rule_t fill_rule;
  3359.     composite_traps_info_t info;
  3360.     cairo_status_t status;
  3361.  
  3362.     assert (src_pattern == NULL);
  3363.     assert (op == CAIRO_OPERATOR_ADD);
  3364.     assert (dst->base.is_clear);
  3365.  
  3366.     status = _cairo_clip_get_polygon (clip, &polygon,
  3367.                                       &fill_rule, &info.antialias);
  3368.     if (unlikely (status))
  3369.         return status;
  3370.  
  3371.     _cairo_traps_init (&info.traps);
  3372.     status = _cairo_bentley_ottmann_tessellate_polygon (&info.traps,
  3373.                                                         &polygon,
  3374.                                                         fill_rule);
  3375.     _cairo_polygon_fini (&polygon);
  3376.     if (unlikely (status))
  3377.         return status;
  3378.  
  3379.     if (info.traps.has_intersections) {
  3380.         if (info.traps.is_rectangular)
  3381.             status = _cairo_bentley_ottmann_tessellate_rectangular_traps (&info.traps, CAIRO_FILL_RULE_WINDING);
  3382.         else if (info.traps.is_rectilinear)
  3383.             status = _cairo_bentley_ottmann_tessellate_rectilinear_traps (&info.traps, CAIRO_FILL_RULE_WINDING);
  3384.         else
  3385.             status = _cairo_bentley_ottmann_tessellate_traps (&info.traps, CAIRO_FILL_RULE_WINDING);
  3386.         if (unlikely (status)) {
  3387.             _cairo_traps_fini (&info.traps);
  3388.             return status;
  3389.         }
  3390.     }
  3391.  
  3392.     dst->deferred_clear = FALSE; /* assert(trap extents == extents); */
  3393.  
  3394.     status = _composite_traps (&info,
  3395.                                dst, CAIRO_OPERATOR_SOURCE, mask_pattern,
  3396.                                dst_x, dst_y,
  3397.                                extents, NULL);
  3398.     _cairo_traps_fini (&info.traps);
  3399.  
  3400.     return status;
  3401. }
  3402.  
  3403. struct composite_opacity_info {
  3404.     uint8_t op;
  3405.     cairo_xcb_surface_t *dst;
  3406.     cairo_xcb_picture_t *src;
  3407.     double opacity;
  3408. };
  3409.  
  3410. static void composite_opacity(void *closure,
  3411.                               int16_t x, int16_t y,
  3412.                               int16_t w, int16_t h,
  3413.                               uint16_t coverage)
  3414. {
  3415.     struct composite_opacity_info *info = closure;
  3416.     cairo_xcb_picture_t *mask;
  3417.     cairo_color_t color;
  3418.  
  3419.     color.red_short = color.green_short = color.blue_short = 0;
  3420.     color.alpha_short = info->opacity * coverage;
  3421.  
  3422.     mask = _solid_picture (info->dst, &color);
  3423.     if (likely (mask->base.status == CAIRO_STATUS_SUCCESS)) {
  3424.         if (info->src) {
  3425.             _cairo_xcb_connection_render_composite (info->dst->connection,
  3426.                                                     info->op,
  3427.                                                     info->src->picture,
  3428.                                                     mask->picture,
  3429.                                                     info->dst->picture,
  3430.                                                     x + info->src->x,  y + info->src->y,
  3431.                                                     0,                 0,
  3432.                                                     x,                 y,
  3433.                                                     w,                 h);
  3434.         } else {
  3435.             _cairo_xcb_connection_render_composite (info->dst->connection,
  3436.                                                     info->op,
  3437.                                                     mask->picture,
  3438.                                                     XCB_NONE,
  3439.                                                     info->dst->picture,
  3440.                                                     0,                 0,
  3441.                                                     0,                 0,
  3442.                                                     x,                 y,
  3443.                                                     w,                 h);
  3444.         }
  3445.     }
  3446.  
  3447.     cairo_surface_destroy (&mask->base);
  3448. }
  3449.  
  3450. static cairo_int_status_t
  3451. _composite_opacity_boxes (void                          *closure,
  3452.                           cairo_xcb_surface_t           *dst,
  3453.                           cairo_operator_t               op,
  3454.                           const cairo_pattern_t         *src_pattern,
  3455.                           int                            dst_x,
  3456.                           int                            dst_y,
  3457.                           const cairo_rectangle_int_t   *extents,
  3458.                           cairo_clip_t                  *clip)
  3459. {
  3460.     const cairo_solid_pattern_t *mask_pattern = closure;
  3461.     struct composite_opacity_info info;
  3462.     cairo_status_t status;
  3463.     int i;
  3464.  
  3465.     if (dst->base.is_clear) {
  3466.         if (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD)
  3467.             op = CAIRO_OPERATOR_SOURCE;
  3468.     }
  3469.  
  3470.     if (op == CAIRO_OPERATOR_SOURCE &&
  3471.         (clip == NULL ||
  3472.          (clip->extents.width >= extents->width &&
  3473.           clip->extents.height >= extents->height)))
  3474.         dst->deferred_clear = FALSE;
  3475.  
  3476.     if (dst->deferred_clear) {
  3477.         status = _cairo_xcb_surface_clear (dst);
  3478.         if (unlikely (status))
  3479.             return status;
  3480.     }
  3481.  
  3482.     info.op = _render_operator (op);
  3483.     info.dst = dst;
  3484.  
  3485.     if (src_pattern != NULL) {
  3486.         info.src = _cairo_xcb_picture_for_pattern (dst, src_pattern, extents);
  3487.         if (unlikely (info.src->base.status))
  3488.             return info.src->base.status;
  3489.     } else
  3490.         info.src = NULL;
  3491.  
  3492.     info.opacity = mask_pattern->color.alpha;
  3493.  
  3494.     /* XXX for lots of boxes create a clip region for the fully opaque areas */
  3495.     if (clip) {
  3496.         for (i = 0; i < clip->num_boxes; i++)
  3497.             do_unaligned_box(composite_opacity, &info,
  3498.                              &clip->boxes[i], dst_x, dst_y);
  3499.     } else {
  3500.         composite_opacity(&info,
  3501.                           extents->x - dst_x,
  3502.                           extents->y - dst_y,
  3503.                           extents->width,
  3504.                           extents->height,
  3505.                           0xffff);
  3506.     }
  3507.     cairo_surface_destroy (&info.src->base);
  3508.  
  3509.     return CAIRO_STATUS_SUCCESS;
  3510. }
  3511.  
  3512. /* high level rasteriser -> compositor */
  3513.  
  3514. cairo_int_status_t
  3515. _cairo_xcb_render_compositor_paint (const cairo_compositor_t     *compositor,
  3516.                                     cairo_composite_rectangles_t *composite)
  3517. {
  3518.     cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) composite->surface;
  3519.     cairo_operator_t op = composite->op;
  3520.     cairo_pattern_t *source = &composite->source_pattern.base;
  3521.     cairo_boxes_t boxes;
  3522.     cairo_status_t status;
  3523.  
  3524.     if (unlikely (! _operator_is_supported (surface->connection->flags, op)))
  3525.         return CAIRO_INT_STATUS_UNSUPPORTED;
  3526.  
  3527.     if ((surface->connection->flags & (CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS |
  3528.                                        CAIRO_XCB_RENDER_HAS_COMPOSITE)) == 0)
  3529.     {
  3530.         return CAIRO_INT_STATUS_UNSUPPORTED;
  3531.     }
  3532.  
  3533.     if (composite->clip == NULL &&
  3534.         source->type == CAIRO_PATTERN_TYPE_SOLID &&
  3535.         (op == CAIRO_OPERATOR_SOURCE ||
  3536.          op == CAIRO_OPERATOR_CLEAR ||
  3537.          (surface->base.is_clear &&
  3538.           (op == CAIRO_OPERATOR_ADD || op == CAIRO_OPERATOR_OVER))))
  3539.     {
  3540.         surface->deferred_clear = TRUE;
  3541.         surface->deferred_clear_color = composite->source_pattern.solid.color;
  3542.         return CAIRO_STATUS_SUCCESS;
  3543.     }
  3544.  
  3545.      _cairo_clip_steal_boxes(composite->clip, &boxes);
  3546.      status = _clip_and_composite_boxes (surface, op, source, &boxes, composite);
  3547.      _cairo_clip_unsteal_boxes (composite->clip, &boxes);
  3548.  
  3549.     return status;
  3550. }
  3551.  
  3552. cairo_int_status_t
  3553. _cairo_xcb_render_compositor_mask (const cairo_compositor_t     *compositor,
  3554.                                    cairo_composite_rectangles_t *composite)
  3555. {
  3556.     cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) composite->surface;
  3557.     cairo_operator_t op = composite->op;
  3558.     cairo_pattern_t *source = &composite->source_pattern.base;
  3559.     cairo_pattern_t *mask = &composite->mask_pattern.base;
  3560.     cairo_status_t status;
  3561.  
  3562.     if (unlikely (! _operator_is_supported (surface->connection->flags, op)))
  3563.         return CAIRO_INT_STATUS_UNSUPPORTED;
  3564.  
  3565.     if ((surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) == 0)
  3566.         return CAIRO_INT_STATUS_UNSUPPORTED;
  3567.  
  3568.     if (mask->type == CAIRO_PATTERN_TYPE_SOLID &&
  3569.         composite->clip->path == NULL &&
  3570.         ! _cairo_clip_is_region (composite->clip)) {
  3571.         status = _clip_and_composite (surface, op, source,
  3572.                                       _composite_opacity_boxes,
  3573.                                       _composite_opacity_boxes,
  3574.                                       (void *) mask,
  3575.                                       composite, need_unbounded_clip (composite));
  3576.     } else {
  3577.         xcb_draw_func_t mask_func = NULL;
  3578.         if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS)
  3579.             mask_func = composite->clip->path ? _composite_mask_clip : _composite_mask_clip_boxes;
  3580.         status = _clip_and_composite (surface, op, source,
  3581.                                       _composite_mask, mask_func,
  3582.                                       (void *) mask,
  3583.                                       composite, need_bounded_clip (composite));
  3584.     }
  3585.  
  3586.     return status;
  3587. }
  3588.  
  3589. static cairo_int_status_t
  3590. _cairo_xcb_surface_render_stroke_as_polygon (cairo_xcb_surface_t        *dst,
  3591.                                              cairo_operator_t            op,
  3592.                                              const cairo_pattern_t      *source,
  3593.                                              const cairo_path_fixed_t           *path,
  3594.                                              const cairo_stroke_style_t *stroke_style,
  3595.                                              const cairo_matrix_t       *ctm,
  3596.                                              const cairo_matrix_t       *ctm_inverse,
  3597.                                              double                      tolerance,
  3598.                                              cairo_antialias_t           antialias,
  3599.                                              cairo_composite_rectangles_t *extents)
  3600. {
  3601.     cairo_polygon_t polygon;
  3602.     cairo_status_t status;
  3603.  
  3604.     _cairo_polygon_init_with_clip (&polygon, extents->clip);
  3605.     status = _cairo_path_fixed_stroke_to_polygon (path,
  3606.                                                   stroke_style,
  3607.                                                   ctm, ctm_inverse,
  3608.                                                   tolerance,
  3609.                                                   &polygon);
  3610.     if (likely (status == CAIRO_STATUS_SUCCESS)) {
  3611.         status = _composite_polygon (dst, op, source,
  3612.                                      &polygon, antialias,
  3613.                                      CAIRO_FILL_RULE_WINDING,
  3614.                                      extents);
  3615.     }
  3616.     _cairo_polygon_fini (&polygon);
  3617.  
  3618.     return status;
  3619. }
  3620.  
  3621. static cairo_status_t
  3622. _cairo_xcb_surface_render_stroke_via_mask (cairo_xcb_surface_t          *dst,
  3623.                                            cairo_operator_t              op,
  3624.                                            const cairo_pattern_t        *source,
  3625.                                            const cairo_path_fixed_t             *path,
  3626.                                            const cairo_stroke_style_t   *stroke_style,
  3627.                                            const cairo_matrix_t         *ctm,
  3628.                                            const cairo_matrix_t         *ctm_inverse,
  3629.                                            double                        tolerance,
  3630.                                            cairo_antialias_t             antialias,
  3631.                                            cairo_composite_rectangles_t *extents)
  3632. {
  3633.     cairo_surface_t *image;
  3634.     cairo_status_t status;
  3635.     cairo_clip_t *clip;
  3636.     int x, y;
  3637.  
  3638.     x = extents->bounded.x;
  3639.     y = extents->bounded.y;
  3640.     image = _cairo_xcb_surface_create_similar_image (dst, CAIRO_FORMAT_A8,
  3641.                                                      extents->bounded.width,
  3642.                                                      extents->bounded.height);
  3643.     if (unlikely (image->status))
  3644.         return image->status;
  3645.  
  3646.     clip = _cairo_clip_copy_region (extents->clip);
  3647.     status = _cairo_surface_offset_stroke (image, x, y,
  3648.                                            CAIRO_OPERATOR_ADD,
  3649.                                            &_cairo_pattern_white.base,
  3650.                                            path, stroke_style,
  3651.                                            ctm, ctm_inverse,
  3652.                                            tolerance, antialias,
  3653.                                            clip);
  3654.     _cairo_clip_destroy (clip);
  3655.     if (likely (status == CAIRO_STATUS_SUCCESS)) {
  3656.         cairo_surface_pattern_t mask;
  3657.  
  3658.         _cairo_pattern_init_for_surface (&mask, image);
  3659.         mask.base.filter = CAIRO_FILTER_NEAREST;
  3660.  
  3661.         cairo_matrix_init_translate (&mask.base.matrix, -x, -y);
  3662.         status = _clip_and_composite (dst, op, source,
  3663.                                       _composite_mask, NULL, &mask.base,
  3664.                                       extents, need_bounded_clip (extents));
  3665.         _cairo_pattern_fini (&mask.base);
  3666.     }
  3667.  
  3668.     cairo_surface_finish (image);
  3669.     cairo_surface_destroy (image);
  3670.  
  3671.     return status;
  3672. }
  3673.  
  3674. cairo_int_status_t
  3675. _cairo_xcb_render_compositor_stroke (const cairo_compositor_t     *compositor,
  3676.                                      cairo_composite_rectangles_t *composite,
  3677.                                      const cairo_path_fixed_t     *path,
  3678.                                      const cairo_stroke_style_t   *style,
  3679.                                      const cairo_matrix_t         *ctm,
  3680.                                      const cairo_matrix_t         *ctm_inverse,
  3681.                                      double                        tolerance,
  3682.                                      cairo_antialias_t             antialias)
  3683. {
  3684.     cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) composite->surface;
  3685.     cairo_operator_t op = composite->op;
  3686.     cairo_pattern_t *source = &composite->source_pattern.base;
  3687.     cairo_int_status_t status;
  3688.  
  3689.     if (unlikely (! _operator_is_supported (surface->connection->flags, op)))
  3690.         return CAIRO_INT_STATUS_UNSUPPORTED;
  3691.  
  3692.     if ((surface->connection->flags & (CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS |
  3693.                            CAIRO_XCB_RENDER_HAS_COMPOSITE)) == 0)
  3694.     {
  3695.         return CAIRO_INT_STATUS_UNSUPPORTED;
  3696.     }
  3697.  
  3698.     status = CAIRO_INT_STATUS_UNSUPPORTED;
  3699.     if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
  3700.         cairo_boxes_t boxes;
  3701.  
  3702.         _cairo_boxes_init_with_clip (&boxes, composite->clip);
  3703.         status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
  3704.                                                                 style,
  3705.                                                                 ctm,
  3706.                                                                 antialias,
  3707.                                                                 &boxes);
  3708.         if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
  3709.             status = _clip_and_composite_boxes (surface, op, source,
  3710.                                                 &boxes, composite);
  3711.         }
  3712.         _cairo_boxes_fini (&boxes);
  3713.     }
  3714.  
  3715.     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
  3716.         if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS) {
  3717.             status = _cairo_xcb_surface_render_stroke_as_polygon (surface, op, source,
  3718.                                                                   path, style,
  3719.                                                                   ctm, ctm_inverse,
  3720.                                                                   tolerance, antialias,
  3721.                                                                   composite);
  3722.         } else if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) {
  3723.             status = _cairo_xcb_surface_render_stroke_via_mask (surface, op, source,
  3724.                                                                 path, style,
  3725.                                                                 ctm, ctm_inverse,
  3726.                                                                 tolerance, antialias,
  3727.                                                                 composite);
  3728.         } else {
  3729.             ASSERT_NOT_REACHED;
  3730.         }
  3731.     }
  3732.  
  3733.     return status;
  3734. }
  3735.  
  3736. static cairo_status_t
  3737. _cairo_xcb_surface_render_fill_as_polygon (cairo_xcb_surface_t  *dst,
  3738.                                            cairo_operator_t      op,
  3739.                                            const cairo_pattern_t*source,
  3740.                                            const cairo_path_fixed_t     *path,
  3741.                                            cairo_fill_rule_t     fill_rule,
  3742.                                            double                tolerance,
  3743.                                            cairo_antialias_t     antialias,
  3744.                                            cairo_composite_rectangles_t *extents)
  3745. {
  3746.     cairo_polygon_t polygon;
  3747.     cairo_status_t status;
  3748.  
  3749.     _cairo_polygon_init_with_clip (&polygon, extents->clip);
  3750.     status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
  3751.     if (likely (status == CAIRO_STATUS_SUCCESS)) {
  3752.         status = _composite_polygon (dst, op, source,
  3753.                                      &polygon,
  3754.                                      antialias,
  3755.                                      fill_rule,
  3756.                                      extents);
  3757.     }
  3758.     _cairo_polygon_fini (&polygon);
  3759.  
  3760.     return status;
  3761. }
  3762.  
  3763. static cairo_status_t
  3764. _cairo_xcb_surface_render_fill_via_mask (cairo_xcb_surface_t    *dst,
  3765.                                          cairo_operator_t        op,
  3766.                                          const cairo_pattern_t  *source,
  3767.                                          const cairo_path_fixed_t       *path,
  3768.                                          cairo_fill_rule_t       fill_rule,
  3769.                                          double                  tolerance,
  3770.                                          cairo_antialias_t       antialias,
  3771.                                          cairo_composite_rectangles_t *extents)
  3772. {
  3773.     cairo_surface_t *image;
  3774.     cairo_status_t status;
  3775.     cairo_clip_t *clip;
  3776.     int x, y;
  3777.  
  3778.     x = extents->bounded.x;
  3779.     y = extents->bounded.y;
  3780.     image = _cairo_xcb_surface_create_similar_image (dst, CAIRO_FORMAT_A8,
  3781.                                                      extents->bounded.width,
  3782.                                                      extents->bounded.height);
  3783.     if (unlikely (image->status))
  3784.         return image->status;
  3785.  
  3786.     clip = _cairo_clip_copy_region (extents->clip);
  3787.     status = _cairo_surface_offset_fill (image, x, y,
  3788.                                          CAIRO_OPERATOR_ADD,
  3789.                                          &_cairo_pattern_white.base,
  3790.                                          path, fill_rule, tolerance, antialias,
  3791.                                          clip);
  3792.     _cairo_clip_destroy (clip);
  3793.     if (likely (status == CAIRO_STATUS_SUCCESS)) {
  3794.         cairo_surface_pattern_t mask;
  3795.  
  3796.         _cairo_pattern_init_for_surface (&mask, image);
  3797.         mask.base.filter = CAIRO_FILTER_NEAREST;
  3798.  
  3799.         cairo_matrix_init_translate (&mask.base.matrix, -x, -y);
  3800.         status = _clip_and_composite (dst, op, source,
  3801.                                       _composite_mask, NULL, &mask.base,
  3802.                                       extents, need_bounded_clip (extents));
  3803.  
  3804.         _cairo_pattern_fini (&mask.base);
  3805.     }
  3806.  
  3807.     cairo_surface_finish (image);
  3808.     cairo_surface_destroy (image);
  3809.  
  3810.     return status;
  3811. }
  3812.  
  3813. cairo_int_status_t
  3814. _cairo_xcb_render_compositor_fill (const cairo_compositor_t     *compositor,
  3815.                                    cairo_composite_rectangles_t *composite,
  3816.                                    const cairo_path_fixed_t     *path,
  3817.                                    cairo_fill_rule_t             fill_rule,
  3818.                                    double                        tolerance,
  3819.                                    cairo_antialias_t             antialias)
  3820. {
  3821.     cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) composite->surface;
  3822.     cairo_operator_t op = composite->op;
  3823.     cairo_pattern_t *source = &composite->source_pattern.base;
  3824.     cairo_int_status_t status;
  3825.  
  3826.     if (unlikely (! _operator_is_supported (surface->connection->flags, op)))
  3827.         return CAIRO_INT_STATUS_UNSUPPORTED;
  3828.  
  3829.     if ((surface->connection->flags & (CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS |
  3830.                                        CAIRO_XCB_RENDER_HAS_COMPOSITE)) == 0)
  3831.     {
  3832.         return CAIRO_INT_STATUS_UNSUPPORTED;
  3833.     }
  3834.  
  3835.     status = CAIRO_INT_STATUS_UNSUPPORTED;
  3836.     if (_cairo_path_fixed_fill_is_rectilinear (path)) {
  3837.         cairo_boxes_t boxes;
  3838.  
  3839.         _cairo_boxes_init_with_clip (&boxes, composite->clip);
  3840.         status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
  3841.                                                               fill_rule,
  3842.                                                               antialias,
  3843.                                                               &boxes);
  3844.         if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
  3845.             status = _clip_and_composite_boxes (surface, op, source,
  3846.                                                 &boxes, composite);
  3847.         }
  3848.         _cairo_boxes_fini (&boxes);
  3849.     }
  3850.  
  3851.     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
  3852.         if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS) {
  3853.             status = _cairo_xcb_surface_render_fill_as_polygon (surface, op, source, path,
  3854.                                                                 fill_rule, tolerance, antialias,
  3855.                                                                 composite);
  3856.         } else if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) {
  3857.             status = _cairo_xcb_surface_render_fill_via_mask (surface, op, source, path,
  3858.                                                               fill_rule, tolerance, antialias,
  3859.                                                               composite);
  3860.         } else {
  3861.             ASSERT_NOT_REACHED;
  3862.         }
  3863.     }
  3864.  
  3865.     return status;
  3866. }
  3867.  
  3868. static cairo_status_t
  3869. _cairo_xcb_surface_render_glyphs_via_mask (cairo_xcb_surface_t          *dst,
  3870.                                            cairo_operator_t              op,
  3871.                                            const cairo_pattern_t        *source,
  3872.                                            cairo_scaled_font_t          *scaled_font,
  3873.                                            cairo_glyph_t                *glyphs,
  3874.                                            int                           num_glyphs,
  3875.                                            cairo_composite_rectangles_t *extents)
  3876. {
  3877.     cairo_surface_t *image;
  3878.     cairo_content_t content;
  3879.     cairo_status_t status;
  3880.     cairo_clip_t *clip;
  3881.     int x, y;
  3882.  
  3883.     content = CAIRO_CONTENT_ALPHA;
  3884.     if (scaled_font->options.antialias == CAIRO_ANTIALIAS_SUBPIXEL)
  3885.         content = CAIRO_CONTENT_COLOR_ALPHA;
  3886.  
  3887.     x = extents->bounded.x;
  3888.     y = extents->bounded.y;
  3889.     image = _cairo_xcb_surface_create_similar_image (dst,
  3890.                                                      _cairo_format_from_content (content),
  3891.                                                      extents->bounded.width,
  3892.                                                      extents->bounded.height);
  3893.     if (unlikely (image->status))
  3894.         return image->status;
  3895.  
  3896.     clip = _cairo_clip_copy_region (extents->clip);
  3897.     status = _cairo_surface_offset_glyphs (image, x, y,
  3898.                                            CAIRO_OPERATOR_ADD,
  3899.                                            &_cairo_pattern_white.base,
  3900.                                            scaled_font, glyphs, num_glyphs,
  3901.                                            clip);
  3902.     _cairo_clip_destroy (clip);
  3903.     if (likely (status == CAIRO_STATUS_SUCCESS)) {
  3904.         cairo_surface_pattern_t mask;
  3905.  
  3906.         _cairo_pattern_init_for_surface (&mask, image);
  3907.         mask.base.filter = CAIRO_FILTER_NEAREST;
  3908.         if (content & CAIRO_CONTENT_COLOR)
  3909.             mask.base.has_component_alpha = TRUE;
  3910.  
  3911.         cairo_matrix_init_translate (&mask.base.matrix, -x, -y);
  3912.         status = _clip_and_composite (dst, op, source,
  3913.                                       _composite_mask, NULL, &mask.base,
  3914.                                       extents, need_bounded_clip (extents));
  3915.  
  3916.         _cairo_pattern_fini (&mask.base);
  3917.     }
  3918.  
  3919.     cairo_surface_finish (image);
  3920.     cairo_surface_destroy (image);
  3921.  
  3922.     return status;
  3923. }
  3924.  
  3925. /* Build a struct of the same size of #cairo_glyph_t that can be used both as
  3926.  * an input glyph with double coordinates, and as "working" glyph with
  3927.  * integer from-current-point offsets. */
  3928. typedef union {
  3929.     cairo_glyph_t d;
  3930.     unsigned long index;
  3931.     struct {
  3932.         unsigned long index;
  3933.         int x;
  3934.         int y;
  3935.     } i;
  3936. } cairo_xcb_glyph_t;
  3937.  
  3938. /* compile-time assert that #cairo_xcb_glyph_t is the same size as #cairo_glyph_t */
  3939. COMPILE_TIME_ASSERT (sizeof (cairo_xcb_glyph_t) == sizeof (cairo_glyph_t));
  3940.  
  3941. typedef struct {
  3942.     cairo_scaled_font_t *font;
  3943.     cairo_xcb_glyph_t *glyphs;
  3944.     int num_glyphs;
  3945.     cairo_bool_t use_mask;
  3946. } composite_glyphs_info_t;
  3947.  
  3948. static cairo_status_t
  3949. _can_composite_glyphs (cairo_xcb_surface_t *dst,
  3950.                        cairo_rectangle_int_t *extents,
  3951.                        cairo_scaled_font_t *scaled_font,
  3952.                        cairo_glyph_t *glyphs,
  3953.                        int *num_glyphs)
  3954. {
  3955. #define GLYPH_CACHE_SIZE 64
  3956.     cairo_box_t bbox_cache[GLYPH_CACHE_SIZE];
  3957.     unsigned long glyph_cache[GLYPH_CACHE_SIZE];
  3958. #undef GLYPH_CACHE_SIZE
  3959.     cairo_status_t status = CAIRO_STATUS_SUCCESS;
  3960.     cairo_glyph_t *glyphs_end, *valid_glyphs;
  3961.     const int max_glyph_size = dst->connection->maximum_request_length - 64;
  3962.  
  3963.     /* We must initialize the cache with values that cannot match the
  3964.      * "hash" to guarantee that when compared for the first time they
  3965.      * will result in a mismatch. The hash function is simply modulus,
  3966.      * so we cannot use 0 in glyph_cache[0], but we can use it in all
  3967.      * other array cells.
  3968.      */
  3969.     memset (glyph_cache, 0, sizeof (glyph_cache));
  3970.     glyph_cache[0] = 1;
  3971.  
  3972.     /* Scan for oversized glyphs or glyphs outside the representable
  3973.      * range and fallback in that case, discard glyphs outside of the
  3974.      * image.
  3975.      */
  3976.     valid_glyphs = glyphs;
  3977.     for (glyphs_end = glyphs + *num_glyphs; glyphs != glyphs_end; glyphs++) {
  3978.         double x1, y1, x2, y2;
  3979.         cairo_scaled_glyph_t *glyph;
  3980.         cairo_box_t *bbox;
  3981.         int width, height, len;
  3982.         int g;
  3983.  
  3984.         g = glyphs->index % ARRAY_LENGTH (glyph_cache);
  3985.         if (glyph_cache[g] != glyphs->index) {
  3986.             status = _cairo_scaled_glyph_lookup (scaled_font,
  3987.                                                  glyphs->index,
  3988.                                                  CAIRO_SCALED_GLYPH_INFO_METRICS,
  3989.                                                  &glyph);
  3990.             if (unlikely (status))
  3991.                 break;
  3992.  
  3993.             glyph_cache[g] = glyphs->index;
  3994.             bbox_cache[g] = glyph->bbox;
  3995.         }
  3996.         bbox = &bbox_cache[g];
  3997.  
  3998.         /* Drop glyphs outside the clipping */
  3999.         x1 = _cairo_fixed_to_double (bbox->p1.x);
  4000.         y1 = _cairo_fixed_to_double (bbox->p1.y);
  4001.         y2 = _cairo_fixed_to_double (bbox->p2.y);
  4002.         x2 = _cairo_fixed_to_double (bbox->p2.x);
  4003.         if (unlikely (glyphs->x + x2 <= extents->x ||
  4004.                       glyphs->y + y2 <= extents->y ||
  4005.                       glyphs->x + x1 >= extents->x + extents->width ||
  4006.                       glyphs->y + y1 >= extents->y + extents->height))
  4007.         {
  4008.             (*num_glyphs)--;
  4009.             continue;
  4010.         }
  4011.  
  4012.         /* XRenderAddGlyph does not handle a glyph surface larger than
  4013.          * the extended maximum XRequest size.
  4014.          */
  4015.         width  = _cairo_fixed_integer_ceil (bbox->p2.x - bbox->p1.x);
  4016.         height = _cairo_fixed_integer_ceil (bbox->p2.y - bbox->p1.y);
  4017.         len = CAIRO_STRIDE_FOR_WIDTH_BPP (width, 32) * height;
  4018.         if (unlikely (len >= max_glyph_size)) {
  4019.             status = CAIRO_INT_STATUS_UNSUPPORTED;
  4020.             break;
  4021.         }
  4022.  
  4023.         /* The glyph coordinates must be representable in an int16_t.
  4024.          * When possible, they will be expressed as an offset from the
  4025.          * previous glyph, otherwise they will be an offset from the
  4026.          * operation extents or from the surface origin. If the last
  4027.          * two options are not valid, fallback.
  4028.          */
  4029.         if (unlikely (glyphs->x > INT16_MAX ||
  4030.                       glyphs->y > INT16_MAX ||
  4031.                       glyphs->x - extents->x < INT16_MIN ||
  4032.                       glyphs->y - extents->y < INT16_MIN))
  4033.         {
  4034.             status = CAIRO_INT_STATUS_UNSUPPORTED;
  4035.             break;
  4036.         }
  4037.  
  4038.  
  4039.         if (unlikely (valid_glyphs != glyphs))
  4040.             *valid_glyphs = *glyphs;
  4041.         valid_glyphs++;
  4042.     }
  4043.  
  4044.     if (unlikely (valid_glyphs != glyphs)) {
  4045.         for (; glyphs != glyphs_end; glyphs++) {
  4046.             *valid_glyphs = *glyphs;
  4047.             valid_glyphs++;
  4048.         }
  4049.     }
  4050.  
  4051.     return status;
  4052. }
  4053.  
  4054. /* Start a new element for the first glyph,
  4055.  * or for any glyph that has unexpected position,
  4056.  * or if current element has too many glyphs
  4057.  * (Xrender limits each element to 252 glyphs, we limit them to 128)
  4058.  *
  4059.  * These same conditions need to be mirrored between
  4060.  * _cairo_xcb_surface_emit_glyphs and _emit_glyph_chunks
  4061.  */
  4062. #define _start_new_glyph_elt(count, glyph) \
  4063.     (((count) & 127) == 0 || (glyph)->i.x || (glyph)->i.y)
  4064.  
  4065. /* sz_xGlyphtElt required alignment to a 32-bit boundary, so ensure we have
  4066.  * enough room for padding */
  4067. typedef struct {
  4068.     uint8_t   len;
  4069.     uint8_t   pad1;
  4070.     uint16_t  pad2;
  4071.     int16_t   deltax;
  4072.     int16_t   deltay;
  4073. } x_glyph_elt_t;
  4074. #define _cairo_sz_x_glyph_elt_t (sizeof (x_glyph_elt_t) + 4)
  4075.  
  4076. static void
  4077. _cairo_xcb_font_destroy (cairo_xcb_font_t *font)
  4078. {
  4079.     int i;
  4080.  
  4081.     for (i = 0; i < NUM_GLYPHSETS; i++) {
  4082.         cairo_xcb_font_glyphset_info_t *info;
  4083.  
  4084.         info = &font->glyphset_info[i];
  4085.         free (info->pending_free_glyphs);
  4086.     }
  4087.  
  4088.     cairo_list_del (&font->base.link);
  4089.     cairo_list_del (&font->link);
  4090.  
  4091.     _cairo_xcb_connection_destroy (font->connection);
  4092.  
  4093.     free (font);
  4094. }
  4095.  
  4096. static void
  4097. _cairo_xcb_font_fini (cairo_scaled_font_private_t *abstract_private,
  4098.                       cairo_scaled_font_t *scaled_font)
  4099. {
  4100.     cairo_xcb_font_t *font_private = (cairo_xcb_font_t *)abstract_private;
  4101.     cairo_xcb_connection_t *connection;
  4102.     cairo_bool_t have_connection;
  4103.     cairo_status_t status;
  4104.     int i;
  4105.  
  4106.     connection = font_private->connection;
  4107.  
  4108.     status = _cairo_xcb_connection_acquire (connection);
  4109.     have_connection = status == CAIRO_STATUS_SUCCESS;
  4110.  
  4111.     for (i = 0; i < NUM_GLYPHSETS; i++) {
  4112.         cairo_xcb_font_glyphset_info_t *info;
  4113.  
  4114.         info = &font_private->glyphset_info[i];
  4115.         if (info->glyphset && status == CAIRO_STATUS_SUCCESS) {
  4116.             _cairo_xcb_connection_render_free_glyph_set (connection,
  4117.                                                          info->glyphset);
  4118.         }
  4119.     }
  4120.  
  4121.     if (have_connection)
  4122.         _cairo_xcb_connection_release (connection);
  4123.  
  4124.     _cairo_xcb_font_destroy (font_private);
  4125. }
  4126.  
  4127.  
  4128. static cairo_xcb_font_t *
  4129. _cairo_xcb_font_create (cairo_xcb_connection_t *connection,
  4130.                         cairo_scaled_font_t  *font)
  4131. {
  4132.     cairo_xcb_font_t    *priv;
  4133.     int i;
  4134.  
  4135.     priv = malloc (sizeof (cairo_xcb_font_t));
  4136.     if (unlikely (priv == NULL))
  4137.         return NULL;
  4138.  
  4139.     _cairo_scaled_font_attach_private (font, &priv->base, connection,
  4140.                                        _cairo_xcb_font_fini);
  4141.  
  4142.     priv->scaled_font = font;
  4143.     priv->connection = _cairo_xcb_connection_reference (connection);
  4144.     cairo_list_add (&priv->link, &connection->fonts);
  4145.  
  4146.     for (i = 0; i < NUM_GLYPHSETS; i++) {
  4147.         cairo_xcb_font_glyphset_info_t *info = &priv->glyphset_info[i];
  4148.         switch (i) {
  4149.         case GLYPHSET_INDEX_ARGB32: info->format = CAIRO_FORMAT_ARGB32; break;
  4150.         case GLYPHSET_INDEX_A8:     info->format = CAIRO_FORMAT_A8;     break;
  4151.         case GLYPHSET_INDEX_A1:     info->format = CAIRO_FORMAT_A1;     break;
  4152.         default:                    ASSERT_NOT_REACHED;                          break;
  4153.         }
  4154.         info->xrender_format = 0;
  4155.         info->glyphset = XCB_NONE;
  4156.         info->pending_free_glyphs = NULL;
  4157.     }
  4158.  
  4159.     return priv;
  4160. }
  4161.  
  4162. void
  4163. _cairo_xcb_font_close (cairo_xcb_font_t *font)
  4164. {
  4165.     cairo_scaled_font_t *scaled_font;
  4166.  
  4167.     scaled_font = font->scaled_font;
  4168.  
  4169.     //scaled_font->surface_private = NULL;
  4170.     _cairo_scaled_font_reset_cache (scaled_font);
  4171.  
  4172.     _cairo_xcb_font_destroy (font);
  4173. }
  4174.  
  4175. static void
  4176. _cairo_xcb_render_free_glyphs (cairo_xcb_connection_t *connection,
  4177.                                cairo_xcb_font_glyphset_free_glyphs_t *to_free)
  4178. {
  4179.     _cairo_xcb_connection_render_free_glyphs (connection,
  4180.                                               to_free->glyphset,
  4181.                                               to_free->glyph_count,
  4182.                                               to_free->glyph_indices);
  4183. }
  4184.  
  4185. static int
  4186. _cairo_xcb_get_glyphset_index_for_format (cairo_format_t format)
  4187. {
  4188.     if (format == CAIRO_FORMAT_A8)
  4189.         return GLYPHSET_INDEX_A8;
  4190.     if (format == CAIRO_FORMAT_A1)
  4191.         return GLYPHSET_INDEX_A1;
  4192.  
  4193.     assert (format == CAIRO_FORMAT_ARGB32);
  4194.     return GLYPHSET_INDEX_ARGB32;
  4195. }
  4196.  
  4197.  
  4198.  
  4199. static inline cairo_xcb_font_t *
  4200. _cairo_xcb_font_get (const cairo_xcb_connection_t *c,
  4201.                      cairo_scaled_font_t *font)
  4202. {
  4203.     return (cairo_xcb_font_t *)_cairo_scaled_font_find_private (font, c);
  4204. }
  4205.  
  4206.  
  4207. static cairo_xcb_font_glyphset_info_t *
  4208. _cairo_xcb_scaled_font_get_glyphset_info_for_format (cairo_xcb_connection_t *c,
  4209.                                                      cairo_scaled_font_t *font,
  4210.                                                      cairo_format_t       format)
  4211. {
  4212.     cairo_xcb_font_t *priv;
  4213.     cairo_xcb_font_glyphset_info_t *info;
  4214.     int glyphset_index;
  4215.  
  4216.     glyphset_index = _cairo_xcb_get_glyphset_index_for_format (format);
  4217.  
  4218.     priv = _cairo_xcb_font_get (c, font);
  4219.     if (priv == NULL) {
  4220.         priv = _cairo_xcb_font_create (c, font);
  4221.         if (priv == NULL)
  4222.             return NULL;
  4223.     }
  4224.  
  4225.     info = &priv->glyphset_info[glyphset_index];
  4226.     if (info->glyphset == XCB_NONE) {
  4227.         info->glyphset = _cairo_xcb_connection_get_xid (c);
  4228.         info->xrender_format = c->standard_formats[info->format];
  4229.  
  4230.         _cairo_xcb_connection_render_create_glyph_set (c,
  4231.                                                        info->glyphset,
  4232.                                                        info->xrender_format);
  4233.     }
  4234.  
  4235.     return info;
  4236. }
  4237.  
  4238. static cairo_bool_t
  4239. _cairo_xcb_glyphset_info_has_pending_free_glyph (
  4240.                                 cairo_xcb_font_glyphset_info_t *info,
  4241.                                 unsigned long glyph_index)
  4242. {
  4243.     if (info->pending_free_glyphs != NULL) {
  4244.         cairo_xcb_font_glyphset_free_glyphs_t *to_free;
  4245.         int i;
  4246.  
  4247.         to_free = info->pending_free_glyphs;
  4248.         for (i = 0; i < to_free->glyph_count; i++) {
  4249.             if (to_free->glyph_indices[i] == glyph_index) {
  4250.                 to_free->glyph_count--;
  4251.                 memmove (&to_free->glyph_indices[i],
  4252.                          &to_free->glyph_indices[i+1],
  4253.                          (to_free->glyph_count - i) * sizeof (to_free->glyph_indices[0]));
  4254.                 return TRUE;
  4255.             }
  4256.         }
  4257.     }
  4258.  
  4259.     return FALSE;
  4260. }
  4261.  
  4262. typedef struct {
  4263.     cairo_scaled_glyph_private_t base;
  4264.  
  4265.     cairo_xcb_font_glyphset_info_t *glyphset;
  4266. } cairo_xcb_glyph_private_t;
  4267.  
  4268. static cairo_xcb_font_glyphset_info_t *
  4269. _cairo_xcb_scaled_font_get_glyphset_info_for_pending_free_glyph (cairo_xcb_connection_t *c,
  4270.                                                cairo_scaled_font_t *font,
  4271.                                                unsigned long glyph_index,
  4272.                                                cairo_image_surface_t *surface)
  4273. {
  4274.     cairo_xcb_font_t *priv;
  4275.     int i;
  4276.  
  4277.     priv = _cairo_xcb_font_get (c, font);
  4278.     if (priv == NULL)
  4279.         return NULL;
  4280.  
  4281.     if (surface != NULL) {
  4282.         i = _cairo_xcb_get_glyphset_index_for_format (surface->format);
  4283.  
  4284.         if (_cairo_xcb_glyphset_info_has_pending_free_glyph (
  4285.                                                 &priv->glyphset_info[i],
  4286.                                                 glyph_index))
  4287.         {
  4288.             return &priv->glyphset_info[i];
  4289.         }
  4290.     } else {
  4291.         for (i = 0; i < NUM_GLYPHSETS; i++) {
  4292.             if (_cairo_xcb_glyphset_info_has_pending_free_glyph (
  4293.                                                 &priv->glyphset_info[i],
  4294.                                                 glyph_index))
  4295.             {
  4296.                 return &priv->glyphset_info[i];
  4297.             }
  4298.         }
  4299.     }
  4300.  
  4301.     return NULL;
  4302. }
  4303.  
  4304. static void
  4305. _cairo_xcb_glyph_fini (cairo_scaled_glyph_private_t *glyph_private,
  4306.                        cairo_scaled_glyph_t *glyph,
  4307.                        cairo_scaled_font_t  *font)
  4308. {
  4309.     cairo_xcb_glyph_private_t *priv = (cairo_xcb_glyph_private_t *)glyph_private;
  4310.  
  4311.     if (! font->finished) {
  4312.         cairo_xcb_font_glyphset_info_t *info = priv->glyphset;
  4313.         cairo_xcb_font_glyphset_free_glyphs_t *to_free;
  4314.         cairo_xcb_font_t *font_private;
  4315.  
  4316.         font_private = _cairo_xcb_font_get (glyph_private->key, font);
  4317.         assert (font_private);
  4318.  
  4319.         to_free = info->pending_free_glyphs;
  4320.         if (to_free != NULL &&
  4321.             to_free->glyph_count == ARRAY_LENGTH (to_free->glyph_indices))
  4322.         {
  4323.             _cairo_xcb_render_free_glyphs (font_private->connection, to_free);
  4324.             to_free = info->pending_free_glyphs = NULL;
  4325.         }
  4326.  
  4327.         if (to_free == NULL) {
  4328.             to_free = malloc (sizeof (cairo_xcb_font_glyphset_free_glyphs_t));
  4329.             if (unlikely (to_free == NULL)) {
  4330.                 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
  4331.                 return; /* XXX cannot propagate failure */
  4332.             }
  4333.  
  4334.             to_free->glyphset = info->glyphset;
  4335.             to_free->glyph_count = 0;
  4336.             info->pending_free_glyphs = to_free;
  4337.         }
  4338.  
  4339.         to_free->glyph_indices[to_free->glyph_count++] =
  4340.             _cairo_scaled_glyph_index (glyph);
  4341.     }
  4342.  
  4343.     cairo_list_del (&glyph_private->link);
  4344.     free (glyph_private);
  4345. }
  4346.  
  4347.  
  4348. static cairo_status_t
  4349. _cairo_xcb_glyph_attach (cairo_xcb_connection_t  *c,
  4350.                          cairo_scaled_glyph_t  *glyph,
  4351.                          cairo_xcb_font_glyphset_info_t *info)
  4352. {
  4353.     cairo_xcb_glyph_private_t *priv;
  4354.  
  4355.     priv = malloc (sizeof (*priv));
  4356.     if (unlikely (priv == NULL))
  4357.         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  4358.  
  4359.     _cairo_scaled_glyph_attach_private (glyph, &priv->base, c,
  4360.                                         _cairo_xcb_glyph_fini);
  4361.     priv->glyphset = info;
  4362.  
  4363.     glyph->dev_private = info;
  4364.     glyph->dev_private_key = c;
  4365.     return CAIRO_STATUS_SUCCESS;
  4366. }
  4367.  
  4368. static cairo_status_t
  4369. _cairo_xcb_surface_add_glyph (cairo_xcb_connection_t *connection,
  4370.                                cairo_scaled_font_t   *font,
  4371.                                cairo_scaled_glyph_t **scaled_glyph_out)
  4372. {
  4373.     xcb_render_glyphinfo_t glyph_info;
  4374.     uint32_t glyph_index;
  4375.     uint8_t *data;
  4376.     cairo_status_t status = CAIRO_STATUS_SUCCESS;
  4377.     cairo_scaled_glyph_t *scaled_glyph = *scaled_glyph_out;
  4378.     cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
  4379.     cairo_bool_t already_had_glyph_surface;
  4380.     cairo_xcb_font_glyphset_info_t *info;
  4381.  
  4382.     glyph_index = _cairo_scaled_glyph_index (scaled_glyph);
  4383.  
  4384.     /* check to see if we have a pending XRenderFreeGlyph for this glyph */
  4385.     info = _cairo_xcb_scaled_font_get_glyphset_info_for_pending_free_glyph (connection, font, glyph_index, glyph_surface);
  4386.     if (info != NULL)
  4387.         return _cairo_xcb_glyph_attach (connection, scaled_glyph, info);
  4388.  
  4389.     if (glyph_surface == NULL) {
  4390.         status = _cairo_scaled_glyph_lookup (font,
  4391.                                              glyph_index,
  4392.                                              CAIRO_SCALED_GLYPH_INFO_METRICS |
  4393.                                              CAIRO_SCALED_GLYPH_INFO_SURFACE,
  4394.                                              scaled_glyph_out);
  4395.         if (unlikely (status))
  4396.             return status;
  4397.  
  4398.         scaled_glyph = *scaled_glyph_out;
  4399.         glyph_surface = scaled_glyph->surface;
  4400.         already_had_glyph_surface = FALSE;
  4401.     } else {
  4402.         already_had_glyph_surface = TRUE;
  4403.     }
  4404.  
  4405.     info = _cairo_xcb_scaled_font_get_glyphset_info_for_format (connection,
  4406.                                                                 font,
  4407.                                                                 glyph_surface->format);
  4408.     if (unlikely (info == NULL)) {
  4409.         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  4410.         goto BAIL;
  4411.     }
  4412.  
  4413. #if 0
  4414.     /* If the glyph surface has zero height or width, we create
  4415.      * a clear 1x1 surface, to avoid various X server bugs.
  4416.      */
  4417.     if (glyph_surface->width == 0 || glyph_surface->height == 0) {
  4418.         cairo_surface_t *tmp_surface;
  4419.  
  4420.         tmp_surface = cairo_image_surface_create (info->format, 1, 1);
  4421.         status = tmp_surface->status;
  4422.         if (unlikely (status))
  4423.             goto BAIL;
  4424.  
  4425.         tmp_surface->device_transform = glyph_surface->base.device_transform;
  4426.         tmp_surface->device_transform_inverse = glyph_surface->base.device_transform_inverse;
  4427.  
  4428.         glyph_surface = (cairo_image_surface_t *) tmp_surface;
  4429.     }
  4430. #endif
  4431.  
  4432.     /* If the glyph format does not match the font format, then we
  4433.      * create a temporary surface for the glyph image with the font's
  4434.      * format.
  4435.      */
  4436.     if (glyph_surface->format != info->format) {
  4437.         glyph_surface = _cairo_image_surface_coerce_to_format (glyph_surface,
  4438.                                                                info->format);
  4439.         status = glyph_surface->base.status;
  4440.         if (unlikely (status))
  4441.             goto BAIL;
  4442.     }
  4443.  
  4444.     /* XXX: FRAGILE: We're ignore device_transform scaling here. A bug? */
  4445.     glyph_info.x = _cairo_lround (glyph_surface->base.device_transform.x0);
  4446.     glyph_info.y = _cairo_lround (glyph_surface->base.device_transform.y0);
  4447.     glyph_info.width  = glyph_surface->width;
  4448.     glyph_info.height = glyph_surface->height;
  4449.     glyph_info.x_off = scaled_glyph->x_advance;
  4450.     glyph_info.y_off = scaled_glyph->y_advance;
  4451.  
  4452.     data = glyph_surface->data;
  4453.  
  4454.     /* flip formats around */
  4455.     switch (_cairo_xcb_get_glyphset_index_for_format (scaled_glyph->surface->format)) {
  4456.     case GLYPHSET_INDEX_A1:
  4457.         /* local bitmaps are always stored with bit == byte */
  4458.         if (_cairo_is_little_endian() != (connection->root->bitmap_format_bit_order == XCB_IMAGE_ORDER_LSB_FIRST)) {
  4459.             int             c = glyph_surface->stride * glyph_surface->height;
  4460.             const uint8_t *d;
  4461.             uint8_t *new, *n;
  4462.  
  4463.             new = malloc (c);
  4464.             if (unlikely (new == NULL)) {
  4465.                 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  4466.                 goto BAIL;
  4467.             }
  4468.  
  4469.             n = new;
  4470.             d = data;
  4471.             do {
  4472.                 uint8_t b = *d++;
  4473.                 b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55);
  4474.                 b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33);
  4475.                 b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f);
  4476.                 *n++ = b;
  4477.             } while (--c);
  4478.             data = new;
  4479.         }
  4480.         break;
  4481.  
  4482.     case GLYPHSET_INDEX_A8:
  4483.         break;
  4484.  
  4485.     case GLYPHSET_INDEX_ARGB32:
  4486.         if (_cairo_is_little_endian() != (connection->root->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST)) {
  4487.             unsigned int c = glyph_surface->stride * glyph_surface->height / 4;
  4488.             const uint32_t *d;
  4489.             uint32_t *new, *n;
  4490.  
  4491.             new = malloc (4 * c);
  4492.             if (unlikely (new == NULL)) {
  4493.                 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
  4494.                 goto BAIL;
  4495.             }
  4496.  
  4497.             n = new;
  4498.             d = (uint32_t *) data;
  4499.             do {
  4500.                 *n++ = bswap_32 (*d);
  4501.                 d++;
  4502.             } while (--c);
  4503.             data = (uint8_t *) new;
  4504.         }
  4505.         break;
  4506.  
  4507.     default:
  4508.         ASSERT_NOT_REACHED;
  4509.         break;
  4510.     }
  4511.     /* XXX assume X server wants pixman padding. Xft assumes this as well */
  4512.  
  4513.     _cairo_xcb_connection_render_add_glyphs (connection,
  4514.                                              info->glyphset,
  4515.                                              1, &glyph_index, &glyph_info,
  4516.                                              glyph_surface->stride * glyph_surface->height,
  4517.                                              data);
  4518.  
  4519.     if (data != glyph_surface->data)
  4520.         free (data);
  4521.  
  4522.     status = _cairo_xcb_glyph_attach (connection, scaled_glyph, info);
  4523.  
  4524.  BAIL:
  4525.     if (glyph_surface != scaled_glyph->surface)
  4526.         cairo_surface_destroy (&glyph_surface->base);
  4527.  
  4528.     /* If the scaled glyph didn't already have a surface attached
  4529.      * to it, release the created surface now that we have it
  4530.      * uploaded to the X server.  If the surface has already been
  4531.      * there (e.g. because image backend requested it), leave it in
  4532.      * the cache
  4533.      */
  4534.     if (! already_had_glyph_surface)
  4535.         _cairo_scaled_glyph_set_surface (scaled_glyph, font, NULL);
  4536.  
  4537.     return status;
  4538. }
  4539.  
  4540. typedef void (*cairo_xcb_render_composite_text_func_t)
  4541.               (cairo_xcb_connection_t       *connection,
  4542.                uint8_t                          op,
  4543.                xcb_render_picture_t src,
  4544.                xcb_render_picture_t dst,
  4545.                xcb_render_pictformat_t mask_format,
  4546.                xcb_render_glyphset_t glyphset,
  4547.                int16_t                          src_x,
  4548.                int16_t                          src_y,
  4549.                uint32_t                          len,
  4550.                uint8_t                        *cmd);
  4551.  
  4552.  
  4553. static cairo_status_t
  4554. _emit_glyphs_chunk (cairo_xcb_surface_t *dst,
  4555.                     cairo_operator_t op,
  4556.                     cairo_xcb_picture_t *src,
  4557.                     /* info for this chunk */
  4558.                     cairo_xcb_glyph_t *glyphs,
  4559.                     int num_glyphs,
  4560.                     int width,
  4561.                     int estimated_req_size,
  4562.                     cairo_xcb_font_glyphset_info_t *info,
  4563.                     xcb_render_pictformat_t mask_format)
  4564. {
  4565.     cairo_xcb_render_composite_text_func_t composite_text_func;
  4566.     uint8_t stack_buf[CAIRO_STACK_BUFFER_SIZE];
  4567.     uint8_t *buf = stack_buf;
  4568.     x_glyph_elt_t *elt = NULL; /* silence compiler */
  4569.     uint32_t len;
  4570.     int i;
  4571.  
  4572.     if (estimated_req_size > ARRAY_LENGTH (stack_buf)) {
  4573.         buf = malloc (estimated_req_size);
  4574.         if (unlikely (buf == NULL))
  4575.             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
  4576.     }
  4577.  
  4578.     len = 0;
  4579.     for (i = 0; i < num_glyphs; i++) {
  4580.       if (_start_new_glyph_elt (i, &glyphs[i])) {
  4581.           if (len & 3)
  4582.               len += 4 - (len & 3);
  4583.  
  4584.           elt = (x_glyph_elt_t *) (buf + len);
  4585.           elt->len = 0;
  4586.           elt->deltax = glyphs[i].i.x;
  4587.           elt->deltay = glyphs[i].i.y;
  4588.           len += sizeof (x_glyph_elt_t);
  4589.       }
  4590.  
  4591.       switch (width) {
  4592.       case 1: *(uint8_t *) (buf + len) = glyphs[i].index; break;
  4593.       case 2: *(uint16_t *) (buf + len) = glyphs[i].index; break;
  4594.       default:
  4595.       case 4: *(uint32_t *) (buf + len) = glyphs[i].index; break;
  4596.       }
  4597.       len += width;
  4598.       elt->len++;
  4599.     }
  4600.     if (len & 3)
  4601.         len += 4 - (len & 3);
  4602.  
  4603.     switch (width) {
  4604.     case 1:
  4605.         composite_text_func = _cairo_xcb_connection_render_composite_glyphs_8;
  4606.         break;
  4607.     case 2:
  4608.         composite_text_func = _cairo_xcb_connection_render_composite_glyphs_16;
  4609.         break;
  4610.     default:
  4611.     case 4:
  4612.         composite_text_func = _cairo_xcb_connection_render_composite_glyphs_32;
  4613.         break;
  4614.     }
  4615.     composite_text_func (dst->connection,
  4616.                          _render_operator (op),
  4617.                          src->picture,
  4618.                          dst->picture,
  4619.                          mask_format,
  4620.                          info->glyphset,
  4621.                          src->x + glyphs[0].i.x,
  4622.                          src->y + glyphs[0].i.y,
  4623.                          len, buf);
  4624.  
  4625.     if (buf != stack_buf)
  4626.       free (buf);
  4627.  
  4628.     return CAIRO_STATUS_SUCCESS;
  4629. }
  4630.  
  4631. static cairo_int_status_t
  4632. _composite_glyphs (void                         *closure,
  4633.                   cairo_xcb_surface_t           *dst,
  4634.                   cairo_operator_t               op,
  4635.                   const cairo_pattern_t         *pattern,
  4636.                   int                            dst_x,
  4637.                   int                            dst_y,
  4638.                   const cairo_rectangle_int_t   *extents,
  4639.                   cairo_clip_t                  *clip)
  4640. {
  4641.     composite_glyphs_info_t *info = closure;
  4642.     cairo_scaled_glyph_t *glyph_cache[64];
  4643.     cairo_status_t status = CAIRO_STATUS_SUCCESS;
  4644.     cairo_fixed_t x = 0, y = 0;
  4645.     cairo_xcb_font_glyphset_info_t *glyphset_info = NULL, *this_glyphset_info;
  4646.     const unsigned int max_request_size = dst->connection->maximum_request_length - 64;
  4647.     cairo_xcb_picture_t *src;
  4648.  
  4649.     unsigned long max_index = 0;
  4650.     int width = 1;
  4651.  
  4652.     unsigned int request_size = 0;
  4653.     int i;
  4654.  
  4655.     if (dst->deferred_clear) {
  4656.         status = _cairo_xcb_surface_clear (dst);
  4657.         if (unlikely (status))
  4658.                 return status;
  4659.     }
  4660.  
  4661.     src = _cairo_xcb_picture_for_pattern (dst, pattern, extents);
  4662.     if (unlikely (src->base.status))
  4663.         return src->base.status;
  4664.  
  4665.     memset (glyph_cache, 0, sizeof (glyph_cache));
  4666.  
  4667.     for (i = 0; i < info->num_glyphs; i++) {
  4668.         cairo_scaled_glyph_t *glyph;
  4669.         unsigned long glyph_index = info->glyphs[i].index;
  4670.         int cache_index = glyph_index % ARRAY_LENGTH (glyph_cache);
  4671.         int old_width = width;
  4672.         int this_x, this_y;
  4673.  
  4674.         glyph = glyph_cache[cache_index];
  4675.         if (glyph == NULL ||
  4676.             _cairo_scaled_glyph_index (glyph) != glyph_index)
  4677.         {
  4678.             status = _cairo_scaled_glyph_lookup (info->font,
  4679.                                                  glyph_index,
  4680.                                                  CAIRO_SCALED_GLYPH_INFO_METRICS,
  4681.                                                  &glyph);
  4682.             if (unlikely (status)) {
  4683.                 cairo_surface_destroy (&src->base);
  4684.                 return status;
  4685.             }
  4686.  
  4687.             /* Send unseen glyphs to the server */
  4688.             if (glyph->dev_private_key != dst->connection) {
  4689.                 status = _cairo_xcb_surface_add_glyph (dst->connection,
  4690.                                                        info->font,
  4691.                                                        &glyph);
  4692.                 if (unlikely (status)) {
  4693.                     cairo_surface_destroy (&src->base);
  4694.                     return status;
  4695.                 }
  4696.             }
  4697.  
  4698.             glyph_cache[cache_index] = glyph;
  4699.         }
  4700.  
  4701.         this_x = _cairo_lround (info->glyphs[i].d.x) - dst_x;
  4702.         this_y = _cairo_lround (info->glyphs[i].d.y) - dst_y;
  4703.  
  4704.         this_glyphset_info = glyph->dev_private;
  4705.         if (glyphset_info == NULL)
  4706.             glyphset_info = this_glyphset_info;
  4707.  
  4708.         /* Update max glyph index */
  4709.         if (glyph_index > max_index) {
  4710.             max_index = glyph_index;
  4711.             if (max_index >= 65536)
  4712.                 width = 4;
  4713.             else if (max_index >= 256)
  4714.                 width = 2;
  4715.             if (width != old_width)
  4716.                 request_size += (width - old_width) * i;
  4717.         }
  4718.  
  4719.         /* If we will pass the max request size by adding this glyph,
  4720.          * flush current glyphs.  Note that we account for a
  4721.          * possible element being added below.
  4722.          *
  4723.          * Also flush if changing glyphsets, as Xrender limits one mask
  4724.          * format per request, so we can either break up, or use a
  4725.          * wide-enough mask format.  We do the former.  One reason to
  4726.          * prefer the latter is the fact that Xserver ADDs all glyphs
  4727.          * to the mask first, and then composes that to final surface,
  4728.          * though it's not a big deal.
  4729.          *
  4730.          * If the glyph has a coordinate which cannot be represented
  4731.          * as a 16-bit offset from the previous glyph, flush the
  4732.          * current chunk. The current glyph will be the first one in
  4733.          * the next chunk, thus its coordinates will be an offset from
  4734.          * the destination origin. This offset is guaranteed to be
  4735.          * representable as 16-bit offset in _can_composite_glyphs().
  4736.          */
  4737.         if (request_size + width > max_request_size - _cairo_sz_x_glyph_elt_t ||
  4738.             this_x - x > INT16_MAX || this_x - x < INT16_MIN ||
  4739.             this_y - y > INT16_MAX || this_y - y < INT16_MIN ||
  4740.             this_glyphset_info != glyphset_info)
  4741.         {
  4742.             status = _emit_glyphs_chunk (dst, op, src,
  4743.                                          info->glyphs, i,
  4744.                                          old_width, request_size,
  4745.                                          glyphset_info,
  4746.                                          info->use_mask ? glyphset_info->xrender_format : 0);
  4747.             if (unlikely (status)) {
  4748.                 cairo_surface_destroy (&src->base);
  4749.                 return status;
  4750.             }
  4751.  
  4752.             info->glyphs += i;
  4753.             info->num_glyphs -= i;
  4754.             i = 0;
  4755.  
  4756.             max_index = info->glyphs[0].index;
  4757.             width = max_index < 256 ? 1 : max_index < 65536 ? 2 : 4;
  4758.  
  4759.             request_size = 0;
  4760.  
  4761.             x = y = 0;
  4762.             glyphset_info = this_glyphset_info;
  4763.         }
  4764.  
  4765.         /* Convert absolute glyph position to relative-to-current-point
  4766.          * position */
  4767.         info->glyphs[i].i.x = this_x - x;
  4768.         info->glyphs[i].i.y = this_y - y;
  4769.  
  4770.         /* Start a new element for the first glyph,
  4771.          * or for any glyph that has unexpected position,
  4772.          * or if current element has too many glyphs.
  4773.          *
  4774.          * These same conditions are mirrored in _emit_glyphs_chunk().
  4775.          */
  4776.       if (_start_new_glyph_elt (i, &info->glyphs[i]))
  4777.             request_size += _cairo_sz_x_glyph_elt_t;
  4778.  
  4779.         /* adjust current-position */
  4780.         x = this_x + glyph->x_advance;
  4781.         y = this_y + glyph->y_advance;
  4782.  
  4783.         request_size += width;
  4784.     }
  4785.  
  4786.     if (i) {
  4787.         status = _emit_glyphs_chunk (dst, op, src,
  4788.                                      info->glyphs, i,
  4789.                                      width, request_size,
  4790.                                      glyphset_info,
  4791.                                      info->use_mask ? glyphset_info->xrender_format : 0);
  4792.     }
  4793.  
  4794.     cairo_surface_destroy (&src->base);
  4795.  
  4796.     return status;
  4797. }
  4798.  
  4799. cairo_int_status_t
  4800. _cairo_xcb_render_compositor_glyphs (const cairo_compositor_t     *compositor,
  4801.                                      cairo_composite_rectangles_t *composite,
  4802.                                      cairo_scaled_font_t          *scaled_font,
  4803.                                      cairo_glyph_t                *glyphs,
  4804.                                      int                           num_glyphs,
  4805.                                      cairo_bool_t                  overlap)
  4806. {
  4807.     cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) composite->surface;
  4808.     cairo_operator_t op = composite->op;
  4809.     cairo_pattern_t *source = &composite->source_pattern.base;
  4810.     cairo_int_status_t status;
  4811.  
  4812.     if (unlikely (! _operator_is_supported (surface->connection->flags, op)))
  4813.         return CAIRO_INT_STATUS_UNSUPPORTED;
  4814.  
  4815.     if ((surface->connection->flags & (CAIRO_XCB_RENDER_HAS_COMPOSITE_GLYPHS | CAIRO_XCB_RENDER_HAS_COMPOSITE)) == 0)
  4816.         return CAIRO_INT_STATUS_UNSUPPORTED;
  4817.  
  4818.     status = CAIRO_INT_STATUS_UNSUPPORTED;
  4819.     if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_GLYPHS) {
  4820.         _cairo_scaled_font_freeze_cache (scaled_font);
  4821.  
  4822.         status = _can_composite_glyphs (surface, &composite->bounded,
  4823.                                         scaled_font, glyphs, &num_glyphs);
  4824.         if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
  4825.             composite_glyphs_info_t info;
  4826.             unsigned flags = 0;
  4827.  
  4828.             info.font = scaled_font;
  4829.             info.glyphs = (cairo_xcb_glyph_t *) glyphs;
  4830.             info.num_glyphs = num_glyphs;
  4831.             info.use_mask =
  4832.                 overlap ||
  4833.                 ! composite->is_bounded ||
  4834.                 ! _cairo_clip_is_region(composite->clip);
  4835.  
  4836.             if (composite->mask.width  > composite->unbounded.width ||
  4837.                 composite->mask.height > composite->unbounded.height)
  4838.             {
  4839.                 /* Glyphs are tricky since we do not directly control the
  4840.                  * geometry and their inked extents depend on the
  4841.                  * individual glyph-surface size. We must set a clip region
  4842.                  * so that the X server can trim the glyphs appropriately.
  4843.                  */
  4844.                 flags |= FORCE_CLIP_REGION;
  4845.             }
  4846.             status = _clip_and_composite (surface, op, source,
  4847.                                           _composite_glyphs, NULL,
  4848.                                           &info, composite,
  4849.                                           need_bounded_clip (composite) |
  4850.                                           flags);
  4851.         }
  4852.  
  4853.         _cairo_scaled_font_thaw_cache (scaled_font);
  4854.     }
  4855.  
  4856.     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
  4857.         assert (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE);
  4858.         status =
  4859.             _cairo_xcb_surface_render_glyphs_via_mask (surface, op, source,
  4860.                                                        scaled_font, glyphs, num_glyphs,
  4861.                                                        composite);
  4862.     }
  4863.  
  4864.     return status;
  4865. }
  4866.