ae2153b95c772d9b1cacda2fee111c79c5915c2b
[framework/graphics/cairo.git] / src / cairo-xlib-surface.c
1 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2 /* cairo - a vector graphics library with display and print output
3  *
4  * Copyright © 2002 University of Southern California
5  * Copyright © 2005 Red Hat, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it either under the terms of the GNU Lesser General Public
9  * License version 2.1 as published by the Free Software Foundation
10  * (the "LGPL") or, at your option, under the terms of the Mozilla
11  * Public License Version 1.1 (the "MPL"). If you do not alter this
12  * notice, a recipient may use your version of this file under either
13  * the MPL or the LGPL.
14  *
15  * You should have received a copy of the LGPL along with this library
16  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
18  * You should have received a copy of the MPL along with this library
19  * in the file COPYING-MPL-1.1
20  *
21  * The contents of this file are subject to the Mozilla Public License
22  * Version 1.1 (the "License"); you may not use this file except in
23  * compliance with the License. You may obtain a copy of the License at
24  * http://www.mozilla.org/MPL/
25  *
26  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28  * the specific language governing rights and limitations.
29  *
30  * The Original Code is the cairo graphics library.
31  *
32  * The Initial Developer of the Original Code is University of Southern
33  * California.
34  *
35  * Contributor(s):
36  *      Carl D. Worth <cworth@cworth.org>
37  *      Behdad Esfahbod <behdad@behdad.org>
38  *      Chris Wilson <chris@chris-wilson.co.uk>
39  *      Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
40  */
41
42 /* Heed well the words of Owen Taylor:
43  * "Any patch that works around a render bug, or claims to, without a
44  * specific reference to the bug filed in bugzilla.freedesktop.org will
45  * never pass approval."
46  */
47
48 #include "cairoint.h"
49
50 #if !CAIRO_HAS_XLIB_XCB_FUNCTIONS
51
52 #include "cairo-xlib-private.h"
53 #include "cairo-xlib-surface-private.h"
54
55 #include "cairo-compositor-private.h"
56 #include "cairo-clip-private.h"
57 #include "cairo-default-context-private.h"
58 #include "cairo-error-private.h"
59 #include "cairo-image-surface-private.h"
60 #include "cairo-list-inline.h"
61 #include "cairo-pattern-private.h"
62 #include "cairo-region-private.h"
63 #include "cairo-scaled-font-private.h"
64 #include "cairo-surface-snapshot-private.h"
65 #include "cairo-surface-subsurface-private.h"
66
67 #include <X11/Xutil.h> /* for XDestroyImage */
68
69 #define XLIB_COORD_MAX 32767
70
71 #define DEBUG 0
72
73 #if DEBUG
74 #define UNSUPPORTED(reason) \
75     fprintf (stderr, \
76              "cairo-xlib: hit unsupported operation %s(), line %d: %s\n", \
77              __FUNCTION__, __LINE__, reason), \
78     CAIRO_INT_STATUS_UNSUPPORTED
79 #else
80 #define UNSUPPORTED(reason) CAIRO_INT_STATUS_UNSUPPORTED
81 #endif
82
83 #if DEBUG
84 #include <X11/Xlibint.h>
85 static void CAIRO_PRINTF_FORMAT (2, 3)
86 _x_bread_crumb (Display *dpy,
87                 const char *fmt,
88                 ...)
89 {
90     xReq *req;
91     char buf[2048];
92     unsigned int len, len_dwords;
93     va_list ap;
94
95     va_start (ap, fmt);
96     len = vsnprintf (buf, sizeof (buf), fmt, ap);
97     va_end (ap);
98
99     buf[len++] = '\0';
100     while (len & 3)
101         buf[len++] = '\0';
102
103     LockDisplay (dpy);
104     GetEmptyReq (NoOperation, req);
105
106     len_dwords = len >> 2;
107     SetReqLen (req, len_dwords, len_dwords);
108     Data (dpy, buf, len);
109
110     UnlockDisplay (dpy);
111     SyncHandle ();
112 }
113 #define X_DEBUG(x) _x_bread_crumb x
114 #else
115 #define X_DEBUG(x)
116 #endif
117
118 /**
119  * SECTION:cairo-xlib
120  * @Title: XLib Surfaces
121  * @Short_Description: X Window System rendering using XLib
122  * @See_Also: #cairo_surface_t
123  *
124  * The XLib surface is used to render cairo graphics to X Window System
125  * windows and pixmaps using the XLib library.
126  *
127  * Note that the XLib surface automatically takes advantage of X render extension
128  * if it is available.
129  **/
130
131 /**
132  * CAIRO_HAS_XLIB_SURFACE:
133  *
134  * Defined if the Xlib surface backend is available.
135  * This macro can be used to conditionally compile backend-specific code.
136  *
137  * Since: 1.0
138  **/
139
140 /**
141  * SECTION:cairo-xlib-xrender
142  * @Title: XLib-XRender Backend
143  * @Short_Description: X Window System rendering using XLib and the X Render extension
144  * @See_Also: #cairo_surface_t
145  *
146  * The XLib surface is used to render cairo graphics to X Window System
147  * windows and pixmaps using the XLib and Xrender libraries.
148  *
149  * Note that the XLib surface automatically takes advantage of X Render extension
150  * if it is available.
151  **/
152
153 /**
154  * CAIRO_HAS_XLIB_XRENDER_SURFACE:
155  *
156  * Defined if the XLib/XRender surface functions are available.
157  * This macro can be used to conditionally compile backend-specific code.
158  *
159  * Since: 1.6
160  **/
161
162 /* Xlib doesn't define a typedef, so define one ourselves */
163 typedef int (*cairo_xlib_error_func_t) (Display     *display,
164                                         XErrorEvent *event);
165
166 static cairo_surface_t *
167 _cairo_xlib_surface_create_internal (cairo_xlib_screen_t        *screen,
168                                      Drawable                   drawable,
169                                      Visual                    *visual,
170                                      XRenderPictFormat         *xrender_format,
171                                      int                        width,
172                                      int                        height,
173                                      int                        depth);
174
175 static cairo_bool_t
176 _cairo_surface_is_xlib (cairo_surface_t *surface);
177
178 /*
179  * Instead of taking two round trips for each blending request,
180  * assume that if a particular drawable fails GetImage that it will
181  * fail for a "while"; use temporary pixmaps to avoid the errors
182  */
183
184 #define CAIRO_ASSUME_PIXMAP     20
185
186 static const XTransform identity = { {
187     { 1 << 16, 0x00000, 0x00000 },
188     { 0x00000, 1 << 16, 0x00000 },
189     { 0x00000, 0x00000, 1 << 16 },
190 } };
191
192 static Visual *
193 _visual_for_xrender_format(Screen *screen,
194                            XRenderPictFormat *xrender_format)
195 {
196     int d, v;
197
198     /* XXX Consider searching through the list of known cairo_visual_t for
199      * the reverse mapping.
200      */
201
202     for (d = 0; d < screen->ndepths; d++) {
203         Depth *d_info = &screen->depths[d];
204
205         if (d_info->depth != xrender_format->depth)
206             continue;
207
208         for (v = 0; v < d_info->nvisuals; v++) {
209             Visual *visual = &d_info->visuals[v];
210
211             switch (visual->class) {
212             case TrueColor:
213                 if (xrender_format->type != PictTypeDirect)
214                     continue;
215                 break;
216
217             case DirectColor:
218                 /* Prefer TrueColor to DirectColor.
219                  * (XRenderFindVisualFormat considers both TrueColor and DirectColor
220                  * Visuals to match the same PictFormat.)
221                  */
222                 continue;
223
224             case StaticGray:
225             case GrayScale:
226             case StaticColor:
227             case PseudoColor:
228                 if (xrender_format->type != PictTypeIndexed)
229                     continue;
230                 break;
231             }
232
233             if (xrender_format ==
234                 XRenderFindVisualFormat (DisplayOfScreen(screen), visual))
235                 return visual;
236         }
237     }
238
239     return NULL;
240 }
241
242 static cairo_content_t
243 _xrender_format_to_content (XRenderPictFormat *xrender_format)
244 {
245     cairo_content_t content;
246
247     /* This only happens when using a non-Render server. Let's punt
248      * and say there's no alpha here. */
249     if (xrender_format == NULL)
250         return CAIRO_CONTENT_COLOR;
251
252     content = 0;
253     if (xrender_format->direct.alphaMask)
254             content |= CAIRO_CONTENT_ALPHA;
255     if (xrender_format->direct.redMask |
256         xrender_format->direct.greenMask |
257         xrender_format->direct.blueMask)
258             content |= CAIRO_CONTENT_COLOR;
259
260     return content;
261 }
262
263 static cairo_surface_t *
264 _cairo_xlib_surface_create_similar (void               *abstract_src,
265                                     cairo_content_t     content,
266                                     int                 width,
267                                     int                 height)
268 {
269     cairo_xlib_surface_t *src = abstract_src;
270     XRenderPictFormat *xrender_format;
271     cairo_xlib_surface_t *surface;
272     cairo_xlib_display_t *display;
273     Pixmap pix;
274
275     if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
276         return NULL;
277
278     if (width == 0 || height == 0)
279         return NULL;
280
281     if (_cairo_xlib_display_acquire (src->base.device, &display))
282         return NULL;
283
284     /* If we never found an XRenderFormat or if it isn't compatible
285      * with the content being requested, then we fallback to just
286      * constructing a cairo_format_t instead, (which will fairly
287      * arbitrarily pick a visual/depth for the similar surface.
288      */
289     xrender_format = NULL;
290     if (src->xrender_format &&
291         _xrender_format_to_content (src->xrender_format) == content)
292     {
293         xrender_format = src->xrender_format;
294     }
295     if (xrender_format == NULL) {
296         xrender_format =
297             _cairo_xlib_display_get_xrender_format (display,
298                                                     _cairo_format_from_content (content));
299     }
300     if (xrender_format) {
301         Visual *visual;
302
303         /* We've got a compatible XRenderFormat now, which means the
304          * similar surface will match the existing surface as closely in
305          * visual/depth etc. as possible. */
306         pix = XCreatePixmap (display->display, src->drawable,
307                              width, height, xrender_format->depth);
308
309         if (xrender_format == src->xrender_format)
310             visual = src->visual;
311         else
312             visual = _visual_for_xrender_format(src->screen->screen,
313                                                 xrender_format);
314
315         surface = (cairo_xlib_surface_t *)
316                   _cairo_xlib_surface_create_internal (src->screen, pix, visual,
317                                                        xrender_format,
318                                                        width, height,
319                                                        xrender_format->depth);
320     }
321     else
322     {
323         Screen *screen = src->screen->screen;
324         int depth;
325
326         /* No compatible XRenderFormat, see if we can make an ordinary pixmap,
327          * so that we can still accelerate blits with XCopyArea(). */
328         if (content != CAIRO_CONTENT_COLOR) {
329             cairo_device_release (&display->base);
330             return NULL;
331         }
332
333         depth = DefaultDepthOfScreen (screen);
334
335         pix = XCreatePixmap (display->display, RootWindowOfScreen (screen),
336                              width <= 0 ? 1 : width, height <= 0 ? 1 : height,
337                              depth);
338
339         surface = (cairo_xlib_surface_t *)
340                   _cairo_xlib_surface_create_internal (src->screen, pix,
341                                                        DefaultVisualOfScreen (screen),
342                                                        NULL,
343                                                        width, height, depth);
344     }
345
346     if (likely (surface->base.status == CAIRO_STATUS_SUCCESS))
347         surface->owns_pixmap = TRUE;
348     else
349         XFreePixmap (display->display, pix);
350
351     cairo_device_release (&display->base);
352
353     return &surface->base;
354 }
355
356 static cairo_status_t
357 _cairo_xlib_surface_finish (void *abstract_surface)
358 {
359     cairo_xlib_surface_t *surface = abstract_surface;
360     cairo_status_t        status;
361     cairo_xlib_display_t *display;
362
363     X_DEBUG ((display->display, "finish (drawable=%x)", (unsigned int) surface->drawable));
364
365     cairo_list_del (&surface->link);
366
367     status = _cairo_xlib_display_acquire (surface->base.device, &display);
368     if (unlikely (status))
369         return status;
370
371     if (surface->embedded_source.picture)
372         XRenderFreePicture (display->display, surface->embedded_source.picture);
373     if (surface->picture)
374         XRenderFreePicture (display->display, surface->picture);
375     if (surface->owns_pixmap)
376         XFreePixmap (display->display, surface->drawable);
377
378     cairo_device_release (&display->base);
379
380     return status;
381 }
382
383 cairo_status_t
384 _cairo_xlib_surface_get_gc (cairo_xlib_display_t *display,
385                             cairo_xlib_surface_t *surface,
386                             GC                   *gc)
387 {
388     *gc = _cairo_xlib_screen_get_gc (display,
389                                      surface->screen,
390                                      surface->depth,
391                                      surface->drawable);
392     if (unlikely (*gc == NULL))
393         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
394
395     return CAIRO_STATUS_SUCCESS;
396 }
397
398 static int
399 _noop_error_handler (Display     *display,
400                      XErrorEvent *event)
401 {
402     return False;               /* return value is ignored */
403 }
404
405 static void
406 _swap_ximage_2bytes (XImage *ximage)
407 {
408     int i, j;
409     char *line = ximage->data;
410
411     for (j = ximage->height; j; j--) {
412         uint16_t *p = (uint16_t *) line;
413         for (i = ximage->width; i; i--) {
414             *p = bswap_16 (*p);
415             p++;
416         }
417
418         line += ximage->bytes_per_line;
419     }
420 }
421
422 static void
423 _swap_ximage_3bytes (XImage *ximage)
424 {
425     int i, j;
426     char *line = ximage->data;
427
428     for (j = ximage->height; j; j--) {
429         uint8_t *p = (uint8_t *) line;
430         for (i = ximage->width; i; i--) {
431             uint8_t tmp;
432             tmp = p[2];
433             p[2] = p[0];
434             p[0] = tmp;
435             p += 3;
436         }
437
438         line += ximage->bytes_per_line;
439     }
440 }
441
442 static void
443 _swap_ximage_4bytes (XImage *ximage)
444 {
445     int i, j;
446     char *line = ximage->data;
447
448     for (j = ximage->height; j; j--) {
449         uint32_t *p = (uint32_t *) line;
450         for (i = ximage->width; i; i--) {
451             *p = bswap_32 (*p);
452             p++;
453         }
454
455         line += ximage->bytes_per_line;
456     }
457 }
458
459 static void
460 _swap_ximage_nibbles (XImage *ximage)
461 {
462     int i, j;
463     char *line = ximage->data;
464
465     for (j = ximage->height; j; j--) {
466         uint8_t *p = (uint8_t *) line;
467         for (i = (ximage->width + 1) / 2; i; i--) {
468             *p = ((*p >> 4) & 0xf) | ((*p << 4) & ~0xf);
469             p++;
470         }
471
472         line += ximage->bytes_per_line;
473     }
474 }
475
476 static void
477 _swap_ximage_bits (XImage *ximage)
478 {
479     int i, j;
480     char *line = ximage->data;
481     int unit = ximage->bitmap_unit;
482     int line_bytes = ((ximage->width + unit - 1) & ~(unit - 1)) / 8;
483
484     for (j = ximage->height; j; j--) {
485         char *p = line;
486
487         for (i = line_bytes; i; i--) {
488             char b = *p;
489             b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55);
490             b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33);
491             b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f);
492             *p = b;
493
494             p++;
495         }
496
497         line += ximage->bytes_per_line;
498     }
499 }
500
501 static void
502 _swap_ximage_to_native (XImage *ximage)
503 {
504     int unit_bytes = 0;
505     int native_byte_order = _cairo_is_little_endian () ? LSBFirst : MSBFirst;
506
507     if (ximage->bits_per_pixel == 1 &&
508         ximage->bitmap_bit_order != native_byte_order)
509     {
510         _swap_ximage_bits (ximage);
511         if (ximage->bitmap_bit_order == ximage->byte_order)
512             return;
513     }
514
515     if (ximage->byte_order == native_byte_order)
516         return;
517
518     switch (ximage->bits_per_pixel) {
519     case 1:
520         unit_bytes = ximage->bitmap_unit / 8;
521         break;
522     case 4:
523         _swap_ximage_nibbles (ximage);
524         /* fall-through */
525     case 8:
526     case 16:
527     case 20:
528     case 24:
529     case 28:
530     case 30:
531     case 32:
532         unit_bytes = (ximage->bits_per_pixel + 7) / 8;
533         break;
534     default:
535         /* This could be hit on some rare but possible cases. */
536         ASSERT_NOT_REACHED;
537     }
538
539     switch (unit_bytes) {
540     case 1:
541         break;
542     case 2:
543         _swap_ximage_2bytes (ximage);
544         break;
545     case 3:
546         _swap_ximage_3bytes (ximage);
547         break;
548     case 4:
549         _swap_ximage_4bytes (ximage);
550         break;
551     default:
552         ASSERT_NOT_REACHED;
553     }
554 }
555
556
557 /* Given a mask, (with a single sequence of contiguous 1 bits), return
558  * the number of 1 bits in 'width' and the number of 0 bits to its
559  * right in 'shift'. */
560 static void
561 _characterize_field (uint32_t mask, int *width, int *shift)
562 {
563     *width = _cairo_popcount (mask);
564     /* The final '& 31' is to force a 0 mask to result in 0 shift. */
565     *shift = _cairo_popcount ((mask - 1) & ~mask) & 31;
566 }
567
568 /* Convert a field of 'width' bits to 'new_width' bits with correct
569  * rounding. */
570 static inline uint32_t
571 _resize_field (uint32_t field, int width, int new_width)
572 {
573     if (width == 0)
574         return 0;
575
576     if (width >= new_width) {
577         return field >> (width - new_width);
578     } else {
579         uint32_t result = field << (new_width - width);
580
581         while (width < new_width) {
582             result |= result >> width;
583             width <<= 1;
584         }
585         return result;
586     }
587 }
588
589 static inline uint32_t
590 _adjust_field (uint32_t field, int adjustment)
591 {
592     return MIN (255, MAX(0, (int)field + adjustment));
593 }
594
595 /* Given a shifted field value, (described by 'width' and 'shift),
596  * resize it 8-bits and return that value.
597  *
598  * Note that the original field value must not have any non-field bits
599  * set.
600  */
601 static inline uint32_t
602 _field_to_8 (uint32_t field, int width, int shift)
603 {
604     return _resize_field (field >> shift, width, 8);
605 }
606
607 static inline uint32_t
608 _field_to_8_undither (uint32_t field, int width, int shift,
609                       int dither_adjustment)
610 {
611     return _adjust_field (_field_to_8 (field, width, shift), - dither_adjustment>>width);
612 }
613
614 /* Given an 8-bit value, convert it to a field of 'width', shift it up
615  *  to 'shift, and return it. */
616 static inline uint32_t
617 _field_from_8 (uint32_t field, int width, int shift)
618 {
619     return _resize_field (field, 8, width) << shift;
620 }
621
622 static inline uint32_t
623 _field_from_8_dither (uint32_t field, int width, int shift,
624                       int8_t dither_adjustment)
625 {
626     return _field_from_8 (_adjust_field (field, dither_adjustment>>width), width, shift);
627 }
628
629 static inline uint32_t
630 _pseudocolor_from_rgb888_dither (cairo_xlib_visual_info_t *visual_info,
631                                  uint32_t r, uint32_t g, uint32_t b,
632                                  int8_t dither_adjustment)
633 {
634     if (r == g && g == b) {
635         dither_adjustment /= RAMP_SIZE;
636         return visual_info->gray8_to_pseudocolor[_adjust_field (r, dither_adjustment)];
637     } else {
638         dither_adjustment = visual_info->dither8_to_cube[dither_adjustment+128];
639         return visual_info->cube_to_pseudocolor[visual_info->field8_to_cube[_adjust_field (r, dither_adjustment)]]
640                                                [visual_info->field8_to_cube[_adjust_field (g, dither_adjustment)]]
641                                                [visual_info->field8_to_cube[_adjust_field (b, dither_adjustment)]];
642     }
643 }
644
645 static inline uint32_t
646 _pseudocolor_to_rgb888 (cairo_xlib_visual_info_t *visual_info,
647                         uint32_t pixel)
648 {
649     uint32_t r, g, b;
650     pixel &= 0xff;
651     r = visual_info->colors[pixel].r;
652     g = visual_info->colors[pixel].g;
653     b = visual_info->colors[pixel].b;
654     return (r << 16) |
655            (g <<  8) |
656            (b      );
657 }
658
659 /* should range from -128 to 127 */
660 #define X 16
661 static const int8_t dither_pattern[4][4] = {
662     {-8*X, +0*X, -6*X, +2*X},
663     {+4*X, -4*X, +6*X, -2*X},
664     {-5*X, +4*X, -7*X, +1*X},
665     {+7*X, -1*X, +5*X, -3*X}
666 };
667 #undef X
668
669 static int bits_per_pixel(cairo_xlib_surface_t *surface)
670 {
671     if (surface->depth > 16)
672         return 32;
673     else if (surface->depth > 8)
674         return 16;
675     else if (surface->depth > 1)
676         return 8;
677     else
678         return 1;
679 }
680
681 static cairo_surface_t *
682 _get_image_surface (cairo_xlib_surface_t    *surface,
683                     const cairo_rectangle_int_t *extents)
684 {
685     cairo_int_status_t status;
686     cairo_image_surface_t *image = NULL;
687     XImage *ximage;
688     pixman_format_code_t pixman_format;
689     cairo_format_masks_t xlib_masks;
690     cairo_xlib_display_t *display;
691
692     assert (extents->x >= 0);
693     assert (extents->y >= 0);
694     assert (extents->x + extents->width <= surface->width);
695     assert (extents->y + extents->height <= surface->height);
696
697     if (surface->base.is_clear ||
698         (surface->base.serial == 0 && surface->owns_pixmap))
699     {
700         xlib_masks.bpp = bits_per_pixel (surface);
701         xlib_masks.alpha_mask = surface->a_mask;
702         xlib_masks.red_mask = surface->r_mask;
703         xlib_masks.green_mask = surface->g_mask;
704         xlib_masks.blue_mask = surface->b_mask;
705         if (_pixman_format_from_masks (&xlib_masks, &pixman_format) &&
706             _cairo_format_from_pixman_format (pixman_format) != CAIRO_FORMAT_INVALID)
707         {
708             return _cairo_image_surface_create_with_pixman_format (NULL,
709                                                                    pixman_format,
710                                                                    extents->width,
711                                                                    extents->height,
712                                                                    0);
713         }
714     }
715
716     status = _cairo_xlib_display_acquire (surface->base.device, &display);
717     if (status)
718         return _cairo_surface_create_in_error (status);
719
720     /* XXX: This should try to use the XShm extension if available */
721
722     if (surface->use_pixmap == 0) {
723         cairo_xlib_error_func_t old_handler;
724
725         old_handler = XSetErrorHandler (_noop_error_handler);
726
727         ximage = XGetImage (display->display,
728                             surface->drawable,
729                             extents->x, extents->y,
730                             extents->width, extents->height,
731                             AllPlanes, ZPixmap);
732
733         XSetErrorHandler (old_handler);
734
735         /* If we get an error, the surface must have been a window,
736          * so retry with the safe code path.
737          */
738         if (!ximage)
739             surface->use_pixmap = CAIRO_ASSUME_PIXMAP;
740     } else {
741         surface->use_pixmap--;
742         ximage = NULL;
743     }
744
745     if (ximage == NULL) {
746         /* XGetImage from a window is dangerous because it can
747          * produce errors if the window is unmapped or partially
748          * outside the screen. We could check for errors and
749          * retry, but to keep things simple, we just create a
750          * temporary pixmap
751          */
752         Pixmap pixmap;
753         GC gc;
754
755         status = _cairo_xlib_surface_get_gc (display, surface, &gc);
756         if (unlikely (status))
757             goto BAIL;
758
759         pixmap = XCreatePixmap (display->display,
760                                 surface->drawable,
761                                 extents->width, extents->height,
762                                 surface->depth);
763         if (pixmap) {
764             XGCValues gcv;
765
766             gcv.subwindow_mode = IncludeInferiors;
767             XChangeGC (display->display, gc, GCSubwindowMode, &gcv);
768
769             XCopyArea (display->display, surface->drawable, pixmap, gc,
770                        extents->x, extents->y,
771                        extents->width, extents->height,
772                        0, 0);
773
774             gcv.subwindow_mode = ClipByChildren;
775             XChangeGC (display->display, gc, GCSubwindowMode, &gcv);
776
777             ximage = XGetImage (display->display,
778                                 pixmap,
779                                 0, 0,
780                                 extents->width, extents->height,
781                                 AllPlanes, ZPixmap);
782
783             XFreePixmap (display->display, pixmap);
784         }
785
786         _cairo_xlib_surface_put_gc (display, surface, gc);
787
788         if (ximage == NULL) {
789             status =  _cairo_error (CAIRO_STATUS_NO_MEMORY);
790             goto BAIL;
791         }
792     }
793
794     _swap_ximage_to_native (ximage);
795
796     xlib_masks.bpp = ximage->bits_per_pixel;
797     xlib_masks.alpha_mask = surface->a_mask;
798     xlib_masks.red_mask = surface->r_mask;
799     xlib_masks.green_mask = surface->g_mask;
800     xlib_masks.blue_mask = surface->b_mask;
801
802     /* We can't use pixman to simply write to image if:
803      *   (a) the pixels are not appropriately aligned,
804      *   (b) pixman does not the pixel format, or
805      *   (c) if the image is palettized and we need to convert.
806      */
807     if (ximage->bitmap_unit == 32 && ximage->bitmap_pad == 32 &&
808         _pixman_format_from_masks (&xlib_masks, &pixman_format) &&
809         (surface->visual == NULL || surface->visual->class == TrueColor))
810     {
811         image = (cairo_image_surface_t*)
812             _cairo_image_surface_create_with_pixman_format ((unsigned char *) ximage->data,
813                                                             pixman_format,
814                                                             ximage->width,
815                                                             ximage->height,
816                                                             ximage->bytes_per_line);
817         status = image->base.status;
818         if (unlikely (status))
819             goto BAIL;
820
821         /* Let the surface take ownership of the data */
822         _cairo_image_surface_assume_ownership_of_data (image);
823         ximage->data = NULL;
824     } else {
825         /* The visual we are dealing with is not supported by the
826          * standard pixman formats. So we must first convert the data
827          * to a supported format. */
828
829         cairo_format_t format;
830         unsigned char *data;
831         uint32_t *row;
832         uint32_t in_pixel, out_pixel;
833         unsigned int rowstride;
834         uint32_t a_mask=0, r_mask=0, g_mask=0, b_mask=0;
835         int a_width=0, r_width=0, g_width=0, b_width=0;
836         int a_shift=0, r_shift=0, g_shift=0, b_shift=0;
837         int x, y, x0, y0, x_off, y_off;
838         cairo_xlib_visual_info_t *visual_info = NULL;
839
840         if (surface->visual == NULL || surface->visual->class == TrueColor) {
841             cairo_bool_t has_alpha;
842             cairo_bool_t has_color;
843
844             has_alpha =  surface->a_mask;
845             has_color = (surface->r_mask ||
846                          surface->g_mask ||
847                          surface->b_mask);
848
849             if (has_color) {
850                 if (has_alpha) {
851                     format = CAIRO_FORMAT_ARGB32;
852                 } else {
853                     format = CAIRO_FORMAT_RGB24;
854                 }
855             } else {
856                 /* XXX: Using CAIRO_FORMAT_A8 here would be more
857                  * efficient, but would require slightly different code in
858                  * the image conversion to put the alpha channel values
859                  * into the right place. */
860                 format = CAIRO_FORMAT_ARGB32;
861             }
862
863             a_mask = surface->a_mask;
864             r_mask = surface->r_mask;
865             g_mask = surface->g_mask;
866             b_mask = surface->b_mask;
867
868             _characterize_field (a_mask, &a_width, &a_shift);
869             _characterize_field (r_mask, &r_width, &r_shift);
870             _characterize_field (g_mask, &g_width, &g_shift);
871             _characterize_field (b_mask, &b_width, &b_shift);
872
873         } else {
874             format = CAIRO_FORMAT_RGB24;
875
876             status = _cairo_xlib_screen_get_visual_info (display,
877                                                          surface->screen,
878                                                          surface->visual,
879                                                          &visual_info);
880             if (unlikely (status))
881                 goto BAIL;
882         }
883
884         image = (cairo_image_surface_t *) cairo_image_surface_create
885             (format, ximage->width, ximage->height);
886         status = image->base.status;
887         if (unlikely (status))
888             goto BAIL;
889
890         data = cairo_image_surface_get_data (&image->base);
891         rowstride = cairo_image_surface_get_stride (&image->base) >> 2;
892         row = (uint32_t *) data;
893         x0 = extents->x + surface->base.device_transform.x0;
894         y0 = extents->y + surface->base.device_transform.y0;
895         for (y = 0, y_off = y0 % ARRAY_LENGTH (dither_pattern);
896              y < ximage->height;
897              y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern)) {
898             const int8_t *dither_row = dither_pattern[y_off];
899             for (x = 0, x_off = x0 % ARRAY_LENGTH (dither_pattern[0]);
900                  x < ximage->width;
901                  x++, x_off = (x_off+1) % ARRAY_LENGTH (dither_pattern[0])) {
902                 int dither_adjustment = dither_row[x_off];
903
904                 in_pixel = XGetPixel (ximage, x, y);
905                 if (visual_info == NULL) {
906                     out_pixel = (
907                         _field_to_8 (in_pixel & a_mask, a_width, a_shift) << 24 |
908                         _field_to_8_undither (in_pixel & r_mask, r_width, r_shift, dither_adjustment) << 16 |
909                         _field_to_8_undither (in_pixel & g_mask, g_width, g_shift, dither_adjustment) << 8 |
910                         _field_to_8_undither (in_pixel & b_mask, b_width, b_shift, dither_adjustment));
911                 } else {
912                     /* Undithering pseudocolor does not look better */
913                     out_pixel = _pseudocolor_to_rgb888 (visual_info, in_pixel);
914                 }
915                 row[x] = out_pixel;
916             }
917             row += rowstride;
918         }
919         cairo_surface_mark_dirty (&image->base);
920     }
921
922  BAIL:
923     if (ximage)
924         XDestroyImage (ximage);
925
926     cairo_device_release (&display->base);
927
928     if (unlikely (status)) {
929         cairo_surface_destroy (&image->base);
930         return _cairo_surface_create_in_error (status);
931     }
932
933     return &image->base;
934 }
935
936 void
937 _cairo_xlib_surface_set_precision (cairo_xlib_surface_t *surface,
938                                    cairo_antialias_t     antialias)
939 {
940     cairo_xlib_display_t        *display = surface->display;
941     int precision;
942
943     if (display->force_precision != -1)
944             precision = display->force_precision;
945     else switch (antialias) {
946     default:
947     case CAIRO_ANTIALIAS_DEFAULT:
948     case CAIRO_ANTIALIAS_GRAY:
949     case CAIRO_ANTIALIAS_NONE:
950     case CAIRO_ANTIALIAS_FAST:
951     case CAIRO_ANTIALIAS_GOOD:
952         precision = PolyModeImprecise;
953         break;
954     case CAIRO_ANTIALIAS_BEST:
955     case CAIRO_ANTIALIAS_SUBPIXEL:
956         precision = PolyModePrecise;
957         break;
958     }
959
960     if (surface->precision != precision) {
961         XRenderPictureAttributes pa;
962
963         pa.poly_mode = precision;
964         XRenderChangePicture (display->display, surface->picture,
965                               CPPolyMode, &pa);
966
967         surface->precision = precision;
968     }
969 }
970
971 void
972 _cairo_xlib_surface_ensure_picture (cairo_xlib_surface_t    *surface)
973 {
974     cairo_xlib_display_t *display = surface->display;
975     XRenderPictureAttributes pa;
976     int mask = 0;
977
978     if (surface->picture)
979         return;
980
981     if (display->force_precision != -1)
982         pa.poly_mode = display->force_precision;
983     else
984         pa.poly_mode = PolyModeImprecise;
985     if (pa.poly_mode)
986             mask |= CPPolyMode;
987
988     surface->precision = pa.poly_mode;
989     surface->picture = XRenderCreatePicture (display->display,
990                                              surface->drawable,
991                                              surface->xrender_format,
992                                              mask, &pa);
993 }
994
995 cairo_status_t
996 _cairo_xlib_surface_draw_image (cairo_xlib_surface_t   *surface,
997                                 cairo_image_surface_t  *image,
998                                 int                    src_x,
999                                 int                    src_y,
1000                                 int                    width,
1001                                 int                    height,
1002                                 int                    dst_x,
1003                                 int                    dst_y)
1004 {
1005     cairo_xlib_display_t *display;
1006     XImage ximage;
1007     cairo_format_masks_t image_masks;
1008     int native_byte_order = _cairo_is_little_endian () ? LSBFirst : MSBFirst;
1009     pixman_image_t *pixman_image = NULL;
1010     cairo_status_t status;
1011     cairo_bool_t own_data;
1012     cairo_bool_t is_rgb_image;
1013     GC gc;
1014
1015     ximage.width = image->width;
1016     ximage.height = image->height;
1017     ximage.format = ZPixmap;
1018     ximage.byte_order = native_byte_order;
1019     ximage.bitmap_unit = 32;    /* always for libpixman */
1020     ximage.bitmap_bit_order = native_byte_order;
1021     ximage.bitmap_pad = 32;     /* always for libpixman */
1022     ximage.depth = surface->depth;
1023     ximage.red_mask = surface->r_mask;
1024     ximage.green_mask = surface->g_mask;
1025     ximage.blue_mask = surface->b_mask;
1026     ximage.xoffset = 0;
1027
1028     status = _cairo_xlib_display_acquire (surface->base.device, &display);
1029     if (unlikely (status))
1030         return status;
1031
1032     is_rgb_image = _pixman_format_to_masks (image->pixman_format, &image_masks);
1033
1034     if (is_rgb_image &&
1035         (image_masks.alpha_mask == surface->a_mask || surface->a_mask == 0) &&
1036         (image_masks.red_mask   == surface->r_mask || surface->r_mask == 0) &&
1037         (image_masks.green_mask == surface->g_mask || surface->g_mask == 0) &&
1038         (image_masks.blue_mask  == surface->b_mask || surface->b_mask == 0))
1039     {
1040         int ret;
1041
1042         ximage.bits_per_pixel = image_masks.bpp;
1043         ximage.bytes_per_line = image->stride;
1044         ximage.data = (char *)image->data;
1045         own_data = FALSE;
1046
1047         ret = XInitImage (&ximage);
1048         assert (ret != 0);
1049     }
1050     else if (surface->visual == NULL || surface->visual->class == TrueColor)
1051     {
1052         pixman_format_code_t intermediate_format;
1053         int ret;
1054
1055         image_masks.alpha_mask = surface->a_mask;
1056         image_masks.red_mask   = surface->r_mask;
1057         image_masks.green_mask = surface->g_mask;
1058         image_masks.blue_mask  = surface->b_mask;
1059         image_masks.bpp        = bits_per_pixel (surface);
1060         ret = _pixman_format_from_masks (&image_masks, &intermediate_format);
1061         assert (ret);
1062
1063         own_data = FALSE;
1064
1065         pixman_image = pixman_image_create_bits (intermediate_format,
1066                                                  width, height, NULL, 0);
1067         if (pixman_image == NULL) {
1068             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1069             goto BAIL;
1070         }
1071
1072         pixman_image_composite32 (PIXMAN_OP_SRC,
1073                                   image->pixman_image,
1074                                   NULL,
1075                                   pixman_image,
1076                                   src_x, src_y,
1077                                   0, 0,
1078                                   0, 0,
1079                                   width, height);
1080
1081         ximage.width = width;
1082         ximage.height = height;
1083         ximage.bits_per_pixel = image_masks.bpp;
1084         ximage.data = (char *) pixman_image_get_data (pixman_image);
1085         ximage.bytes_per_line = pixman_image_get_stride (pixman_image);
1086
1087         ret = XInitImage (&ximage);
1088         assert (ret != 0);
1089
1090         src_x = src_y = 0;
1091     }
1092     else
1093     {
1094         unsigned int stride, rowstride;
1095         int x, y, x0, y0, x_off, y_off;
1096         uint32_t in_pixel, out_pixel, *row;
1097         int i_a_width=0, i_r_width=0, i_g_width=0, i_b_width=0;
1098         int i_a_shift=0, i_r_shift=0, i_g_shift=0, i_b_shift=0;
1099         int o_a_width=0, o_r_width=0, o_g_width=0, o_b_width=0;
1100         int o_a_shift=0, o_r_shift=0, o_g_shift=0, o_b_shift=0;
1101         cairo_xlib_visual_info_t *visual_info = NULL;
1102         cairo_bool_t true_color;
1103         int ret;
1104
1105         ximage.bits_per_pixel = bits_per_pixel(surface);
1106         stride = CAIRO_STRIDE_FOR_WIDTH_BPP (ximage.width,
1107                                              ximage.bits_per_pixel);
1108         ximage.bytes_per_line = stride;
1109         ximage.data = _cairo_malloc_ab (stride, ximage.height);
1110         if (unlikely (ximage.data == NULL)) {
1111             own_data = FALSE;
1112             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1113             goto BAIL;
1114         }
1115
1116         own_data = TRUE;
1117
1118         ret = XInitImage (&ximage);
1119         assert (ret != 0);
1120
1121         _characterize_field (image_masks.alpha_mask, &i_a_width, &i_a_shift);
1122         _characterize_field (image_masks.red_mask  , &i_r_width, &i_r_shift);
1123         _characterize_field (image_masks.green_mask, &i_g_width, &i_g_shift);
1124         _characterize_field (image_masks.blue_mask , &i_b_width, &i_b_shift);
1125
1126         true_color = surface->visual == NULL ||
1127                      surface->visual->class == TrueColor;
1128         if (true_color) {
1129             _characterize_field (surface->a_mask, &o_a_width, &o_a_shift);
1130             _characterize_field (surface->r_mask, &o_r_width, &o_r_shift);
1131             _characterize_field (surface->g_mask, &o_g_width, &o_g_shift);
1132             _characterize_field (surface->b_mask, &o_b_width, &o_b_shift);
1133         } else {
1134             status = _cairo_xlib_screen_get_visual_info (display,
1135                                                          surface->screen,
1136                                                          surface->visual,
1137                                                          &visual_info);
1138             if (unlikely (status))
1139                 goto BAIL;
1140         }
1141
1142         rowstride = image->stride >> 2;
1143         row = (uint32_t *) image->data;
1144         x0 = dst_x + surface->base.device_transform.x0;
1145         y0 = dst_y + surface->base.device_transform.y0;
1146         for (y = 0, y_off = y0 % ARRAY_LENGTH (dither_pattern);
1147              y < ximage.height;
1148              y++, y_off = (y_off+1) % ARRAY_LENGTH (dither_pattern))
1149         {
1150             const int8_t *dither_row = dither_pattern[y_off];
1151
1152             for (x = 0, x_off = x0 % ARRAY_LENGTH (dither_pattern[0]);
1153                  x < ximage.width;
1154                  x++, x_off = (x_off+1) % ARRAY_LENGTH (dither_pattern[0]))
1155             {
1156                 int dither_adjustment = dither_row[x_off];
1157                 int a, r, g, b;
1158
1159                 if (image_masks.bpp == 1)
1160                     in_pixel = !! (((uint8_t*)row)[x/8] & (1 << (x & 7)));
1161                 else if (image_masks.bpp <= 8)
1162                     in_pixel = ((uint8_t*)row)[x];
1163                 else if (image_masks.bpp <= 16)
1164                     in_pixel = ((uint16_t*)row)[x];
1165                 else if (image_masks.bpp <= 24)
1166 #ifdef WORDS_BIGENDIAN
1167                     in_pixel = ((uint8_t*)row)[3 * x]     << 16 |
1168                                ((uint8_t*)row)[3 * x + 1] << 8  |
1169                                ((uint8_t*)row)[3 * x + 2];
1170 #else
1171                     in_pixel = ((uint8_t*)row)[3 * x]           |
1172                                ((uint8_t*)row)[3 * x + 1] << 8  |
1173                                ((uint8_t*)row)[3 * x + 2] << 16;
1174 #endif
1175                 else
1176                     in_pixel = row[x];
1177
1178                 /* If the incoming image has no alpha channel, then the input
1179                  * is opaque and the output should have the maximum alpha value.
1180                  * For all other channels, their absence implies 0.
1181                  */
1182                 if (image_masks.alpha_mask == 0x0)
1183                     a = 0xff;
1184                 else
1185                     a = _field_to_8 (in_pixel & image_masks.alpha_mask, i_a_width, i_a_shift);
1186                 r = _field_to_8 (in_pixel & image_masks.red_mask  , i_r_width, i_r_shift);
1187                 g = _field_to_8 (in_pixel & image_masks.green_mask, i_g_width, i_g_shift);
1188                 b = _field_to_8 (in_pixel & image_masks.blue_mask , i_b_width, i_b_shift);
1189
1190                 if (true_color) {
1191                     out_pixel = _field_from_8        (a, o_a_width, o_a_shift) |
1192                                 _field_from_8_dither (r, o_r_width, o_r_shift, dither_adjustment) |
1193                                 _field_from_8_dither (g, o_g_width, o_g_shift, dither_adjustment) |
1194                                 _field_from_8_dither (b, o_b_width, o_b_shift, dither_adjustment);
1195                 } else {
1196                     out_pixel = _pseudocolor_from_rgb888_dither (visual_info, r, g, b, dither_adjustment);
1197                 }
1198
1199                 XPutPixel (&ximage, x, y, out_pixel);
1200             }
1201
1202             row += rowstride;
1203         }
1204     }
1205
1206     status = _cairo_xlib_surface_get_gc (display, surface, &gc);
1207     if (unlikely (status))
1208         goto BAIL;
1209
1210     XPutImage (display->display, surface->drawable, gc, &ximage,
1211                src_x, src_y, dst_x, dst_y, width, height);
1212
1213     _cairo_xlib_surface_put_gc (display, surface, gc);
1214
1215   BAIL:
1216
1217     cairo_device_release (&display->base);
1218
1219     if (own_data)
1220         free (ximage.data);
1221     if (pixman_image)
1222         pixman_image_unref (pixman_image);
1223
1224     return CAIRO_STATUS_SUCCESS;
1225 }
1226
1227 static cairo_surface_t *
1228 _cairo_xlib_surface_source(void                    *abstract_surface,
1229                            cairo_rectangle_int_t *extents)
1230 {
1231     cairo_xlib_surface_t *surface = abstract_surface;
1232
1233     if (extents) {
1234         extents->x = extents->y = 0;
1235         extents->width  = surface->width;
1236         extents->height = surface->height;
1237     }
1238
1239     return &surface->base;
1240 }
1241
1242 static cairo_status_t
1243 _cairo_xlib_surface_acquire_source_image (void                    *abstract_surface,
1244                                           cairo_image_surface_t  **image_out,
1245                                           void                   **image_extra)
1246 {
1247     cairo_xlib_surface_t *surface = abstract_surface;
1248     cairo_rectangle_int_t extents;
1249
1250     extents.x = extents.y = 0;
1251     extents.width = surface->width;
1252     extents.height = surface->height;
1253
1254     *image_extra = NULL;
1255     *image_out = (cairo_image_surface_t*)_get_image_surface (surface, &extents);
1256     return (*image_out)->base.status;
1257 }
1258
1259 static cairo_surface_t *
1260 _cairo_xlib_surface_snapshot (void *abstract_surface)
1261 {
1262     cairo_xlib_surface_t *surface = abstract_surface;
1263     cairo_rectangle_int_t extents;
1264
1265     extents.x = extents.y = 0;
1266     extents.width = surface->width;
1267     extents.height = surface->height;
1268
1269     /* XXX notice the duplication with acquire source */
1270     return _get_image_surface (surface, &extents);
1271 }
1272
1273 static void
1274 _cairo_xlib_surface_release_source_image (void                   *abstract_surface,
1275                                           cairo_image_surface_t  *image,
1276                                           void                   *image_extra)
1277 {
1278     cairo_surface_destroy (&image->base);
1279 }
1280
1281 static cairo_surface_t *
1282 _cairo_xlib_surface_map_to_image (void                    *abstract_surface,
1283                                   const cairo_rectangle_int_t   *extents)
1284 {
1285     cairo_surface_t *image;
1286
1287     image = _get_image_surface (abstract_surface, extents);
1288     cairo_surface_set_device_offset (image, -extents->x, -extents->y);
1289
1290     return image;
1291 }
1292
1293 static cairo_int_status_t
1294 _cairo_xlib_surface_unmap_image (void *abstract_surface,
1295                                  cairo_image_surface_t *image)
1296 {
1297     return _cairo_xlib_surface_draw_image (abstract_surface, image,
1298                                            0, 0,
1299                                            image->width, image->height,
1300                                            image->base.device_transform_inverse.x0,
1301                                            image->base.device_transform_inverse.y0);
1302 }
1303
1304 static cairo_bool_t
1305 _cairo_xlib_surface_get_extents (void                    *abstract_surface,
1306                                  cairo_rectangle_int_t   *rectangle)
1307 {
1308     cairo_xlib_surface_t *surface = abstract_surface;
1309
1310     rectangle->x = 0;
1311     rectangle->y = 0;
1312
1313     rectangle->width  = surface->width;
1314     rectangle->height = surface->height;
1315
1316     return TRUE;
1317 }
1318
1319 static void
1320 _cairo_xlib_surface_get_font_options (void                  *abstract_surface,
1321                                       cairo_font_options_t  *options)
1322 {
1323     cairo_xlib_surface_t *surface = abstract_surface;
1324
1325     *options = *_cairo_xlib_screen_get_font_options (surface->screen);
1326 }
1327
1328
1329 static cairo_int_status_t
1330 _cairo_xlib_surface_paint (void                         *_surface,
1331                            cairo_operator_t              op,
1332                            const cairo_pattern_t        *source,
1333                            const cairo_clip_t           *clip)
1334 {
1335     cairo_xlib_surface_t *surface = _surface;
1336     return _cairo_compositor_paint (surface->compositor,
1337                                     &surface->base, op, source,
1338                                     clip);
1339 }
1340
1341 static cairo_int_status_t
1342 _cairo_xlib_surface_mask (void                  *_surface,
1343                           cairo_operator_t       op,
1344                           const cairo_pattern_t *source,
1345                           const cairo_pattern_t *mask,
1346                           const cairo_clip_t    *clip)
1347 {
1348     cairo_xlib_surface_t *surface = _surface;
1349     return _cairo_compositor_mask (surface->compositor,
1350                                    &surface->base, op, source, mask,
1351                                    clip);
1352 }
1353
1354 static cairo_int_status_t
1355 _cairo_xlib_surface_stroke (void                        *_surface,
1356                             cairo_operator_t             op,
1357                             const cairo_pattern_t       *source,
1358                             const cairo_path_fixed_t    *path,
1359                             const cairo_stroke_style_t  *style,
1360                             const cairo_matrix_t        *ctm,
1361                             const cairo_matrix_t        *ctm_inverse,
1362                             double                       tolerance,
1363                             cairo_antialias_t            antialias,
1364                             const cairo_clip_t          *clip)
1365 {
1366     cairo_xlib_surface_t *surface = _surface;
1367     return _cairo_compositor_stroke (surface->compositor,
1368                                      &surface->base, op, source,
1369                                      path, style, ctm, ctm_inverse,
1370                                      tolerance, antialias,
1371                                      clip);
1372 }
1373
1374 static cairo_int_status_t
1375 _cairo_xlib_surface_fill (void                          *_surface,
1376                           cairo_operator_t               op,
1377                           const cairo_pattern_t         *source,
1378                           const cairo_path_fixed_t      *path,
1379                           cairo_fill_rule_t              fill_rule,
1380                           double                         tolerance,
1381                           cairo_antialias_t              antialias,
1382                           const cairo_clip_t            *clip)
1383 {
1384     cairo_xlib_surface_t *surface = _surface;
1385     return _cairo_compositor_fill (surface->compositor,
1386                                    &surface->base, op, source,
1387                                    path, fill_rule, tolerance, antialias,
1388                                    clip);
1389 }
1390
1391 static cairo_int_status_t
1392 _cairo_xlib_surface_glyphs (void                        *_surface,
1393                             cairo_operator_t             op,
1394                             const cairo_pattern_t       *source,
1395                             cairo_glyph_t               *glyphs,
1396                             int                          num_glyphs,
1397                             cairo_scaled_font_t         *scaled_font,
1398                             const cairo_clip_t          *clip)
1399 {
1400     cairo_xlib_surface_t *surface = _surface;
1401     return _cairo_compositor_glyphs (surface->compositor,
1402                                      &surface->base, op, source,
1403                                      glyphs, num_glyphs, scaled_font,
1404                                      clip);
1405 }
1406
1407 static const cairo_surface_backend_t cairo_xlib_surface_backend = {
1408     CAIRO_SURFACE_TYPE_XLIB,
1409     _cairo_xlib_surface_finish,
1410
1411     _cairo_default_context_create,
1412
1413     _cairo_xlib_surface_create_similar,
1414     NULL, //_cairo_xlib_surface_create_similar_image, /* XXX shm */
1415     _cairo_xlib_surface_map_to_image,
1416     _cairo_xlib_surface_unmap_image,
1417
1418     _cairo_xlib_surface_source,
1419     _cairo_xlib_surface_acquire_source_image,
1420     _cairo_xlib_surface_release_source_image,
1421     _cairo_xlib_surface_snapshot,
1422
1423     NULL, /* copy_page */
1424     NULL, /* show_page */
1425
1426     _cairo_xlib_surface_get_extents,
1427     _cairo_xlib_surface_get_font_options,
1428
1429     NULL, /* flush */
1430     NULL, /* mark_dirty_rectangle */
1431
1432     _cairo_xlib_surface_paint,
1433     _cairo_xlib_surface_mask,
1434     _cairo_xlib_surface_stroke,
1435     _cairo_xlib_surface_fill,
1436     NULL, /* fill-stroke */
1437     _cairo_xlib_surface_glyphs,
1438 };
1439
1440 /**
1441  * _cairo_surface_is_xlib:
1442  * @surface: a #cairo_surface_t
1443  *
1444  * Checks if a surface is a #cairo_xlib_surface_t
1445  *
1446  * Return value: True if the surface is an xlib surface
1447  **/
1448 static cairo_bool_t
1449 _cairo_surface_is_xlib (cairo_surface_t *surface)
1450 {
1451     return surface->backend == &cairo_xlib_surface_backend;
1452 }
1453
1454 static cairo_surface_t *
1455 _cairo_xlib_surface_create_internal (cairo_xlib_screen_t        *screen,
1456                                      Drawable                    drawable,
1457                                      Visual                     *visual,
1458                                      XRenderPictFormat          *xrender_format,
1459                                      int                         width,
1460                                      int                         height,
1461                                      int                         depth)
1462 {
1463     cairo_xlib_surface_t *surface;
1464     cairo_xlib_display_t *display;
1465     cairo_status_t status;
1466
1467     if (depth == 0) {
1468         if (xrender_format) {
1469             depth = xrender_format->depth;
1470
1471             /* XXX find matching visual for core/dithering fallbacks? */
1472         } else if (visual) {
1473             Screen *scr = screen->screen;
1474
1475             if (visual == DefaultVisualOfScreen (scr)) {
1476                 depth = DefaultDepthOfScreen (scr);
1477             } else  {
1478                 int j, k;
1479
1480                 /* This is ugly, but we have to walk over all visuals
1481                  * for the display to find the correct depth.
1482                  */
1483                 depth = 0;
1484                 for (j = 0; j < scr->ndepths; j++) {
1485                     Depth *d = &scr->depths[j];
1486                     for (k = 0; k < d->nvisuals; k++) {
1487                         if (&d->visuals[k] == visual) {
1488                             depth = d->depth;
1489                             goto found;
1490                         }
1491                     }
1492                 }
1493             }
1494         }
1495
1496         if (depth == 0)
1497             return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
1498
1499 found:
1500         ;
1501     }
1502
1503     surface = malloc (sizeof (cairo_xlib_surface_t));
1504     if (unlikely (surface == NULL))
1505         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1506
1507     status = _cairo_xlib_display_acquire (screen->device, &display);
1508     if (unlikely (status)) {
1509         free (surface);
1510         return _cairo_surface_create_in_error (_cairo_error (status));
1511     }
1512
1513     surface->display = display;
1514     if (CAIRO_RENDER_HAS_CREATE_PICTURE (display)) {
1515         if (!xrender_format) {
1516             if (visual) {
1517                 xrender_format = XRenderFindVisualFormat (display->display, visual);
1518             } else if (depth == 1) {
1519                 xrender_format =
1520                     _cairo_xlib_display_get_xrender_format (display,
1521                                                             CAIRO_FORMAT_A1);
1522             }
1523         }
1524     }
1525
1526     cairo_device_release (&display->base);
1527
1528     _cairo_surface_init (&surface->base,
1529                          &cairo_xlib_surface_backend,
1530                          screen->device,
1531                          _xrender_format_to_content (xrender_format));
1532
1533     surface->screen = screen;
1534     surface->compositor = display->compositor;
1535
1536     surface->drawable = drawable;
1537     surface->owns_pixmap = FALSE;
1538     surface->use_pixmap = 0;
1539     surface->width = width;
1540     surface->height = height;
1541
1542     surface->picture = None;
1543     surface->precision = PolyModePrecise;
1544
1545     surface->embedded_source.picture = None;
1546
1547     surface->visual = visual;
1548     surface->xrender_format = xrender_format;
1549     surface->depth = depth;
1550
1551     /*
1552      * Compute the pixel format masks from either a XrenderFormat or
1553      * else from a visual; failing that we assume the drawable is an
1554      * alpha-only pixmap as it could only have been created that way
1555      * through the cairo_xlib_surface_create_for_bitmap function.
1556      */
1557     if (xrender_format) {
1558         surface->a_mask = (unsigned long)
1559             surface->xrender_format->direct.alphaMask
1560             << surface->xrender_format->direct.alpha;
1561         surface->r_mask = (unsigned long)
1562             surface->xrender_format->direct.redMask
1563             << surface->xrender_format->direct.red;
1564         surface->g_mask = (unsigned long)
1565             surface->xrender_format->direct.greenMask
1566             << surface->xrender_format->direct.green;
1567         surface->b_mask = (unsigned long)
1568             surface->xrender_format->direct.blueMask
1569             << surface->xrender_format->direct.blue;
1570     } else if (visual) {
1571         surface->a_mask = 0;
1572         surface->r_mask = visual->red_mask;
1573         surface->g_mask = visual->green_mask;
1574         surface->b_mask = visual->blue_mask;
1575     } else {
1576         if (depth < 32)
1577             surface->a_mask = (1 << depth) - 1;
1578         else
1579             surface->a_mask = 0xffffffff;
1580         surface->r_mask = 0;
1581         surface->g_mask = 0;
1582         surface->b_mask = 0;
1583     }
1584
1585     cairo_list_add (&surface->link, &screen->surfaces);
1586
1587     return &surface->base;
1588 }
1589
1590 static Screen *
1591 _cairo_xlib_screen_from_visual (Display *dpy, Visual *visual)
1592 {
1593     int s, d, v;
1594
1595     for (s = 0; s < ScreenCount (dpy); s++) {
1596         Screen *screen;
1597
1598         screen = ScreenOfDisplay (dpy, s);
1599         if (visual == DefaultVisualOfScreen (screen))
1600             return screen;
1601
1602         for (d = 0; d < screen->ndepths; d++) {
1603             Depth  *depth;
1604
1605             depth = &screen->depths[d];
1606             for (v = 0; v < depth->nvisuals; v++)
1607                 if (visual == &depth->visuals[v])
1608                     return screen;
1609         }
1610     }
1611
1612     return NULL;
1613 }
1614
1615 static cairo_bool_t valid_size (int width, int height)
1616 {
1617     /* Note: the minimum surface size allowed in the X protocol is 1x1.
1618      * However, as we historically did not check the minimum size we
1619      * allowed applications to lie and set the correct size later (one hopes).
1620      * To preserve compatability we must allow applications to use
1621      * 0x0 surfaces.
1622      */
1623     return (width  >= 0 && width  <= XLIB_COORD_MAX &&
1624             height >= 0 && height <= XLIB_COORD_MAX);
1625 }
1626
1627 /**
1628  * cairo_xlib_surface_create:
1629  * @dpy: an X Display
1630  * @drawable: an X Drawable, (a Pixmap or a Window)
1631  * @visual: the visual to use for drawing to @drawable. The depth
1632  *          of the visual must match the depth of the drawable.
1633  *          Currently, only TrueColor visuals are fully supported.
1634  * @width: the current width of @drawable.
1635  * @height: the current height of @drawable.
1636  *
1637  * Creates an Xlib surface that draws to the given drawable.
1638  * The way that colors are represented in the drawable is specified
1639  * by the provided visual.
1640  *
1641  * Note: If @drawable is a Window, then the function
1642  * cairo_xlib_surface_set_size() must be called whenever the size of the
1643  * window changes.
1644  *
1645  * When @drawable is a Window containing child windows then drawing to
1646  * the created surface will be clipped by those child windows.  When
1647  * the created surface is used as a source, the contents of the
1648  * children will be included.
1649  *
1650  * Return value: the newly created surface
1651  *
1652  * Since: 1.0
1653  **/
1654 cairo_surface_t *
1655 cairo_xlib_surface_create (Display     *dpy,
1656                            Drawable     drawable,
1657                            Visual      *visual,
1658                            int          width,
1659                            int          height)
1660 {
1661     Screen *scr;
1662     cairo_xlib_screen_t *screen;
1663     cairo_status_t status;
1664
1665     if (! valid_size (width, height)) {
1666         /* you're lying, and you know it! */
1667         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1668     }
1669
1670     scr = _cairo_xlib_screen_from_visual (dpy, visual);
1671     if (scr == NULL)
1672         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
1673
1674     status = _cairo_xlib_screen_get (dpy, scr, &screen);
1675     if (unlikely (status))
1676         return _cairo_surface_create_in_error (status);
1677
1678     X_DEBUG ((dpy, "create (drawable=%x)", (unsigned int) drawable));
1679
1680     return _cairo_xlib_surface_create_internal (screen, drawable,
1681                                                 visual, NULL,
1682                                                 width, height, 0);
1683 }
1684
1685 /**
1686  * cairo_xlib_surface_create_for_bitmap:
1687  * @dpy: an X Display
1688  * @bitmap: an X Drawable, (a depth-1 Pixmap)
1689  * @screen: the X Screen associated with @bitmap
1690  * @width: the current width of @bitmap.
1691  * @height: the current height of @bitmap.
1692  *
1693  * Creates an Xlib surface that draws to the given bitmap.
1694  * This will be drawn to as a %CAIRO_FORMAT_A1 object.
1695  *
1696  * Return value: the newly created surface
1697  *
1698  * Since: 1.0
1699  **/
1700 cairo_surface_t *
1701 cairo_xlib_surface_create_for_bitmap (Display  *dpy,
1702                                       Pixmap    bitmap,
1703                                       Screen   *scr,
1704                                       int       width,
1705                                       int       height)
1706 {
1707     cairo_xlib_screen_t *screen;
1708     cairo_status_t status;
1709
1710     if (! valid_size (width, height))
1711         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1712
1713     status = _cairo_xlib_screen_get (dpy, scr, &screen);
1714     if (unlikely (status))
1715         return _cairo_surface_create_in_error (status);
1716
1717     X_DEBUG ((dpy, "create_for_bitmap (drawable=%x)", (unsigned int) bitmap));
1718
1719     return _cairo_xlib_surface_create_internal (screen, bitmap,
1720                                                 NULL, NULL,
1721                                                 width, height, 1);
1722 }
1723
1724 #if CAIRO_HAS_XLIB_XRENDER_SURFACE
1725 /**
1726  * cairo_xlib_surface_create_with_xrender_format:
1727  * @dpy: an X Display
1728  * @drawable: an X Drawable, (a Pixmap or a Window)
1729  * @screen: the X Screen associated with @drawable
1730  * @format: the picture format to use for drawing to @drawable. The depth
1731  *          of @format must match the depth of the drawable.
1732  * @width: the current width of @drawable.
1733  * @height: the current height of @drawable.
1734  *
1735  * Creates an Xlib surface that draws to the given drawable.
1736  * The way that colors are represented in the drawable is specified
1737  * by the provided picture format.
1738  *
1739  * Note: If @drawable is a Window, then the function
1740  * cairo_xlib_surface_set_size() must be called whenever the size of the
1741  * window changes.
1742  *
1743  * Return value: the newly created surface
1744  *
1745  * Since: 1.0
1746  **/
1747 cairo_surface_t *
1748 cairo_xlib_surface_create_with_xrender_format (Display              *dpy,
1749                                                Drawable             drawable,
1750                                                Screen               *scr,
1751                                                XRenderPictFormat    *format,
1752                                                int                  width,
1753                                                int                  height)
1754 {
1755     cairo_xlib_screen_t *screen;
1756     cairo_status_t status;
1757
1758     if (! valid_size (width, height))
1759         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1760
1761     status = _cairo_xlib_screen_get (dpy, scr, &screen);
1762     if (unlikely (status))
1763         return _cairo_surface_create_in_error (status);
1764
1765     X_DEBUG ((dpy, "create_with_xrender_format (drawable=%x)", (unsigned int) drawable));
1766
1767     return _cairo_xlib_surface_create_internal (screen, drawable,
1768                                                 _visual_for_xrender_format (scr, format),
1769                                                 format, width, height, 0);
1770 }
1771
1772 /**
1773  * cairo_xlib_surface_get_xrender_format:
1774  * @surface: an xlib surface
1775  *
1776  * Gets the X Render picture format that @surface uses for rendering with the
1777  * X Render extension. If the surface was created by
1778  * cairo_xlib_surface_create_with_xrender_format() originally, the return
1779  * value is the format passed to that constructor.
1780  *
1781  * Return value: the XRenderPictFormat* associated with @surface,
1782  * or %NULL if the surface is not an xlib surface
1783  * or if the X Render extension is not available.
1784  *
1785  * Since: 1.6
1786  **/
1787 XRenderPictFormat *
1788 cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface)
1789 {
1790     cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface;
1791
1792     /* Throw an error for a non-xlib surface */
1793     if (! _cairo_surface_is_xlib (surface)) {
1794         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
1795         return NULL;
1796     }
1797
1798     return xlib_surface->xrender_format;
1799 }
1800 #endif
1801
1802 /**
1803  * cairo_xlib_surface_set_size:
1804  * @surface: a #cairo_surface_t for the XLib backend
1805  * @width: the new width of the surface
1806  * @height: the new height of the surface
1807  *
1808  * Informs cairo of the new size of the X Drawable underlying the
1809  * surface. For a surface created for a Window (rather than a Pixmap),
1810  * this function must be called each time the size of the window
1811  * changes. (For a subwindow, you are normally resizing the window
1812  * yourself, but for a toplevel window, it is necessary to listen for
1813  * ConfigureNotify events.)
1814  *
1815  * A Pixmap can never change size, so it is never necessary to call
1816  * this function on a surface created for a Pixmap.
1817  *
1818  * Since: 1.0
1819  **/
1820 void
1821 cairo_xlib_surface_set_size (cairo_surface_t *abstract_surface,
1822                              int              width,
1823                              int              height)
1824 {
1825     cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
1826
1827     if (unlikely (abstract_surface->status))
1828         return;
1829     if (unlikely (abstract_surface->finished)) {
1830         _cairo_surface_set_error (abstract_surface,
1831                                   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
1832         return;
1833     }
1834
1835     if (! _cairo_surface_is_xlib (abstract_surface)) {
1836         _cairo_surface_set_error (abstract_surface,
1837                                   _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
1838         return;
1839     }
1840
1841     if (! valid_size (width, height)) {
1842         _cairo_surface_set_error (abstract_surface,
1843                                   _cairo_error (CAIRO_STATUS_INVALID_SIZE));
1844         return;
1845     }
1846
1847     surface->width = width;
1848     surface->height = height;
1849 }
1850 /**
1851  * cairo_xlib_surface_set_drawable:
1852  * @surface: a #cairo_surface_t for the XLib backend
1853  * @drawable: the new drawable for the surface
1854  * @width: the width of the new drawable
1855  * @height: the height of the new drawable
1856  *
1857  * Informs cairo of a new X Drawable underlying the
1858  * surface. The drawable must match the display, screen
1859  * and format of the existing drawable or the application
1860  * will get X protocol errors and will probably terminate.
1861  * No checks are done by this function to ensure this
1862  * compatibility.
1863  *
1864  * Since: 1.0
1865  **/
1866 void
1867 cairo_xlib_surface_set_drawable (cairo_surface_t   *abstract_surface,
1868                                  Drawable           drawable,
1869                                  int                width,
1870                                  int                height)
1871 {
1872     cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *)abstract_surface;
1873     cairo_status_t status;
1874
1875     if (unlikely (abstract_surface->status))
1876         return;
1877     if (unlikely (abstract_surface->finished)) {
1878         status = _cairo_surface_set_error (abstract_surface,
1879                                            _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
1880         return;
1881     }
1882
1883     if (! _cairo_surface_is_xlib (abstract_surface)) {
1884         status = _cairo_surface_set_error (abstract_surface,
1885                                            _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
1886         return;
1887     }
1888
1889     if (! valid_size (width, height)) {
1890         status = _cairo_surface_set_error (abstract_surface,
1891                                            _cairo_error (CAIRO_STATUS_INVALID_SIZE));
1892         return;
1893     }
1894
1895     /* XXX: and what about this case? */
1896     if (surface->owns_pixmap)
1897         return;
1898
1899     if (surface->drawable != drawable) {
1900         cairo_xlib_display_t *display;
1901
1902         status = _cairo_xlib_display_acquire (surface->base.device, &display);
1903         if (unlikely (status))
1904             return;
1905
1906         X_DEBUG ((display->display, "set_drawable (drawable=%x)", (unsigned int) drawable));
1907
1908         if (surface->picture != None) {
1909             XRenderFreePicture (display->display, surface->picture);
1910             if (unlikely (status)) {
1911                 status = _cairo_surface_set_error (&surface->base, status);
1912                 return;
1913             }
1914
1915             surface->picture = None;
1916         }
1917
1918         cairo_device_release (&display->base);
1919
1920         surface->drawable = drawable;
1921     }
1922     surface->width = width;
1923     surface->height = height;
1924 }
1925
1926 /**
1927  * cairo_xlib_surface_get_display:
1928  * @surface: a #cairo_xlib_surface_t
1929  *
1930  * Get the X Display for the underlying X Drawable.
1931  *
1932  * Return value: the display.
1933  *
1934  * Since: 1.2
1935  **/
1936 Display *
1937 cairo_xlib_surface_get_display (cairo_surface_t *abstract_surface)
1938 {
1939     if (! _cairo_surface_is_xlib (abstract_surface)) {
1940         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
1941         return NULL;
1942     }
1943
1944     return ((cairo_xlib_display_t *) abstract_surface->device)->display;
1945 }
1946
1947 /**
1948  * cairo_xlib_surface_get_drawable:
1949  * @surface: a #cairo_xlib_surface_t
1950  *
1951  * Get the underlying X Drawable used for the surface.
1952  *
1953  * Return value: the drawable.
1954  *
1955  * Since: 1.2
1956  **/
1957 Drawable
1958 cairo_xlib_surface_get_drawable (cairo_surface_t *abstract_surface)
1959 {
1960     cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
1961
1962     if (! _cairo_surface_is_xlib (abstract_surface)) {
1963         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
1964         return 0;
1965     }
1966
1967     return surface->drawable;
1968 }
1969
1970 /**
1971  * cairo_xlib_surface_get_screen:
1972  * @surface: a #cairo_xlib_surface_t
1973  *
1974  * Get the X Screen for the underlying X Drawable.
1975  *
1976  * Return value: the screen.
1977  *
1978  * Since: 1.2
1979  **/
1980 Screen *
1981 cairo_xlib_surface_get_screen (cairo_surface_t *abstract_surface)
1982 {
1983     cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
1984
1985     if (! _cairo_surface_is_xlib (abstract_surface)) {
1986         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
1987         return NULL;
1988     }
1989
1990     return surface->screen->screen;
1991 }
1992
1993 /**
1994  * cairo_xlib_surface_get_visual:
1995  * @surface: a #cairo_xlib_surface_t
1996  *
1997  * Gets the X Visual associated with @surface, suitable for use with the
1998  * underlying X Drawable.  If @surface was created by
1999  * cairo_xlib_surface_create(), the return value is the Visual passed to that
2000  * constructor.
2001  *
2002  * Return value: the Visual or %NULL if there is no appropriate Visual for
2003  * @surface.
2004  *
2005  * Since: 1.2
2006  **/
2007 Visual *
2008 cairo_xlib_surface_get_visual (cairo_surface_t *surface)
2009 {
2010     cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface;
2011
2012     if (! _cairo_surface_is_xlib (surface)) {
2013         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
2014         return NULL;
2015     }
2016
2017     return xlib_surface->visual;
2018 }
2019
2020 /**
2021  * cairo_xlib_surface_get_depth:
2022  * @surface: a #cairo_xlib_surface_t
2023  *
2024  * Get the number of bits used to represent each pixel value.
2025  *
2026  * Return value: the depth of the surface in bits.
2027  *
2028  * Since: 1.2
2029  **/
2030 int
2031 cairo_xlib_surface_get_depth (cairo_surface_t *abstract_surface)
2032 {
2033     cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
2034
2035     if (! _cairo_surface_is_xlib (abstract_surface)) {
2036         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
2037         return 0;
2038     }
2039
2040     return surface->depth;
2041 }
2042
2043 /**
2044  * cairo_xlib_surface_get_width:
2045  * @surface: a #cairo_xlib_surface_t
2046  *
2047  * Get the width of the X Drawable underlying the surface in pixels.
2048  *
2049  * Return value: the width of the surface in pixels.
2050  *
2051  * Since: 1.2
2052  **/
2053 int
2054 cairo_xlib_surface_get_width (cairo_surface_t *abstract_surface)
2055 {
2056     cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
2057
2058     if (! _cairo_surface_is_xlib (abstract_surface)) {
2059         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
2060         return 0;
2061     }
2062
2063     return surface->width;
2064 }
2065
2066 /**
2067  * cairo_xlib_surface_get_height:
2068  * @surface: a #cairo_xlib_surface_t
2069  *
2070  * Get the height of the X Drawable underlying the surface in pixels.
2071  *
2072  * Return value: the height of the surface in pixels.
2073  *
2074  * Since: 1.2
2075  **/
2076 int
2077 cairo_xlib_surface_get_height (cairo_surface_t *abstract_surface)
2078 {
2079     cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface;
2080
2081     if (! _cairo_surface_is_xlib (abstract_surface)) {
2082         _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
2083         return 0;
2084     }
2085
2086     return surface->height;
2087 }
2088
2089 #endif /* !CAIRO_HAS_XLIB_XCB_FUNCTIONS */