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