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
4 * Copyright © 2002 University of Southern California
5 * Copyright © 2005 Red Hat, Inc.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * You should have received a copy of the MPL along with this library
19 * in the file COPYING-MPL-1.1
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/
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.
30 * The Original Code is the cairo graphics library.
32 * The Initial Developer of the Original Code is University of Southern
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
44 #include "cairo-xlib-private.h"
45 #include "cairo-xlib-surface-private.h"
46 #include "cairo-clip-private.h"
47 #include "cairo-scaled-font-private.h"
49 #include <X11/Xutil.h> /* for XDestroyImage */
51 #define XLIB_COORD_MAX 32767
53 /* Xlib doesn't define a typedef, so define one ourselves */
54 typedef int (*cairo_xlib_error_func_t
) (Display
*display
,
57 static cairo_surface_t
*
58 _cairo_xlib_surface_create_internal (Display
*dpy
,
62 XRenderPictFormat
*xrender_format
,
68 _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t
*surface
);
71 _cairo_xlib_surface_maybe_put_gc (cairo_xlib_surface_t
*surface
);
74 _cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t
*surface
);
77 _cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t
*surface
);
80 _cairo_surface_is_xlib (cairo_surface_t
*surface
);
83 _native_byte_order_lsb (void);
85 static cairo_int_status_t
86 _cairo_xlib_surface_show_glyphs (void *abstract_dst
,
88 const cairo_pattern_t
*src_pattern
,
89 cairo_glyph_t
*glyphs
,
91 cairo_scaled_font_t
*scaled_font
,
92 int *remaining_glyphs
,
93 cairo_rectangle_int_t
*extents
);
95 /* XXX temporarily used by cairo-qt-surface.c */
96 slim_hidden_proto (cairo_xlib_surface_create
);
97 slim_hidden_proto (cairo_xlib_surface_create_with_xrender_format
);
100 * Instead of taking two round trips for each blending request,
101 * assume that if a particular drawable fails GetImage that it will
102 * fail for a "while"; use temporary pixmaps to avoid the errors
105 #define CAIRO_ASSUME_PIXMAP 20
107 static const XTransform identity
= { {
108 { 1 << 16, 0x00000, 0x00000 },
109 { 0x00000, 1 << 16, 0x00000 },
110 { 0x00000, 0x00000, 1 << 16 },
113 #define CAIRO_SURFACE_RENDER_AT_LEAST(surface, major, minor) \
114 (((surface)->render_major > major) || \
115 (((surface)->render_major == major) && ((surface)->render_minor >= minor)))
117 #define CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)
118 #define CAIRO_SURFACE_RENDER_HAS_COMPOSITE(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)
119 #define CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 0)
121 #define CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 1)
123 #define CAIRO_SURFACE_RENDER_HAS_DISJOINT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 2)
124 #define CAIRO_SURFACE_RENDER_HAS_CONJOINT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 2)
126 #define CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
127 #define CAIRO_SURFACE_RENDER_HAS_TRIANGLES(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
128 #define CAIRO_SURFACE_RENDER_HAS_TRISTRIP(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
129 #define CAIRO_SURFACE_RENDER_HAS_TRIFAN(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 4)
131 #define CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)
132 #define CAIRO_SURFACE_RENDER_HAS_FILTERS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)
134 static cairo_surface_t
*
135 _cairo_xlib_surface_create_similar_with_format (void *abstract_src
,
136 cairo_format_t format
,
140 cairo_xlib_surface_t
*src
= abstract_src
;
141 Display
*dpy
= src
->dpy
;
143 cairo_xlib_surface_t
*surface
;
144 XRenderPictFormat
*xrender_format
;
146 assert (width
<= XLIB_COORD_MAX
&& height
<= XLIB_COORD_MAX
);
148 /* As a good first approximation, if the display doesn't have even
149 * the most elementary RENDER operation, then we're better off
150 * using image surfaces for all temporary operations, so return NULL
151 * and let the fallback code happen.
153 if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src
))
156 xrender_format
= _cairo_xlib_display_get_xrender_format (src
->display
,
158 if (xrender_format
== NULL
)
161 pix
= XCreatePixmap (dpy
, src
->drawable
,
162 width
<= 0 ? 1 : width
, height
<= 0 ? 1 : height
,
163 xrender_format
->depth
);
165 surface
= (cairo_xlib_surface_t
*)
166 _cairo_xlib_surface_create_internal (dpy
, pix
,
170 xrender_format
->depth
);
171 if (surface
->base
.status
) {
172 XFreePixmap (dpy
, pix
);
173 return &surface
->base
;
176 surface
->owns_pixmap
= TRUE
;
178 return &surface
->base
;
181 static cairo_content_t
182 _xrender_format_to_content (XRenderPictFormat
*xrender_format
)
184 cairo_bool_t xrender_format_has_alpha
;
185 cairo_bool_t xrender_format_has_color
;
187 /* This only happens when using a non-Render server. Let's punt
188 * and say there's no alpha here. */
189 if (xrender_format
== NULL
)
190 return CAIRO_CONTENT_COLOR
;
192 xrender_format_has_alpha
= (xrender_format
->direct
.alphaMask
!= 0);
193 xrender_format_has_color
= (xrender_format
->direct
.redMask
!= 0 ||
194 xrender_format
->direct
.greenMask
!= 0 ||
195 xrender_format
->direct
.blueMask
!= 0);
197 if (xrender_format_has_alpha
)
198 if (xrender_format_has_color
)
199 return CAIRO_CONTENT_COLOR_ALPHA
;
201 return CAIRO_CONTENT_ALPHA
;
203 return CAIRO_CONTENT_COLOR
;
206 static cairo_surface_t
*
207 _cairo_xlib_surface_create_similar (void *abstract_src
,
208 cairo_content_t content
,
212 cairo_xlib_surface_t
*src
= abstract_src
;
213 XRenderPictFormat
*xrender_format
;
214 cairo_xlib_surface_t
*surface
;
217 if (width
> XLIB_COORD_MAX
|| height
> XLIB_COORD_MAX
)
220 _cairo_xlib_display_notify (src
->display
);
222 /* If we never found an XRenderFormat or if it isn't compatible
223 * with the content being requested, then we fallback to just
224 * constructing a cairo_format_t instead, (which will fairly
225 * arbitrarily pick a visual/depth for the similar surface.
227 xrender_format
= src
->xrender_format
;
228 if (xrender_format
== NULL
||
229 _xrender_format_to_content (xrender_format
) != content
)
231 return _cairo_xlib_surface_create_similar_with_format (abstract_src
,
232 _cairo_format_from_content (content
),
236 /* We've got a compatible XRenderFormat now, which means the
237 * similar surface will match the existing surface as closely in
238 * visual/depth etc. as possible. */
239 pix
= XCreatePixmap (src
->dpy
, src
->drawable
,
240 width
<= 0 ? 1 : width
, height
<= 0 ? 1 : height
,
241 xrender_format
->depth
);
243 surface
= (cairo_xlib_surface_t
*)
244 _cairo_xlib_surface_create_internal (src
->dpy
, pix
,
245 src
->screen
, src
->visual
,
248 xrender_format
->depth
);
249 if (surface
->base
.status
!= CAIRO_STATUS_SUCCESS
) {
250 XFreePixmap (src
->dpy
, pix
);
251 return &surface
->base
;
254 surface
->owns_pixmap
= TRUE
;
256 return &surface
->base
;
259 static cairo_status_t
260 _cairo_xlib_surface_finish (void *abstract_surface
)
262 cairo_xlib_surface_t
*surface
= abstract_surface
;
263 cairo_xlib_display_t
*display
= surface
->display
;
264 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
266 if (surface
->owns_pixmap
) {
267 cairo_status_t status2
;
269 if (surface
->dst_picture
!= None
) {
270 status2
= _cairo_xlib_display_queue_resource (display
,
272 surface
->dst_picture
);
273 if (status2
== CAIRO_STATUS_SUCCESS
)
274 surface
->dst_picture
= None
;
275 else if (status
== CAIRO_STATUS_SUCCESS
)
279 if (surface
->src_picture
!= None
) {
280 status2
= _cairo_xlib_display_queue_resource (display
,
282 surface
->src_picture
);
283 if (status2
== CAIRO_STATUS_SUCCESS
)
284 surface
->src_picture
= None
;
285 else if (status
== CAIRO_STATUS_SUCCESS
)
289 status2
= _cairo_xlib_display_queue_resource (display
,
290 (cairo_xlib_notify_resource_func
) XFreePixmap
,
292 if (status2
== CAIRO_STATUS_SUCCESS
) {
293 surface
->owns_pixmap
= FALSE
;
294 surface
->drawable
= None
;
295 } else if (status
== CAIRO_STATUS_SUCCESS
)
298 if (surface
->dst_picture
!= None
)
299 XRenderFreePicture (surface
->dpy
, surface
->dst_picture
);
301 if (surface
->src_picture
!= None
)
302 XRenderFreePicture (surface
->dpy
, surface
->src_picture
);
305 if (surface
->gc
!= NULL
) {
306 _cairo_xlib_screen_put_gc (surface
->screen_info
,
309 surface
->gc_has_clip_rects
);
313 if (surface
->clip_rects
!= surface
->embedded_clip_rects
)
314 free (surface
->clip_rects
);
316 if (surface
->screen_info
!= NULL
)
317 _cairo_xlib_screen_info_destroy (surface
->screen_info
);
319 if (surface
->display
!= NULL
) {
320 _cairo_xlib_remove_close_display_hook (surface
->display
,
321 &surface
->close_display_hook
);
322 _cairo_xlib_display_destroy (surface
->display
);
331 _noop_error_handler (Display
*display
,
334 return False
; /* return value is ignored */
338 _swap_ximage_2bytes (XImage
*ximage
)
341 char *line
= ximage
->data
;
343 for (j
= ximage
->height
; j
; j
--) {
344 uint16_t *p
= (uint16_t *) line
;
345 for (i
= ximage
->width
; i
; i
--) {
350 line
+= ximage
->bytes_per_line
;
355 _swap_ximage_3bytes (XImage
*ximage
)
358 char *line
= ximage
->data
;
360 for (j
= ximage
->height
; j
; j
--) {
361 uint8_t *p
= (uint8_t *) line
;
362 for (i
= ximage
->width
; i
; i
--) {
370 line
+= ximage
->bytes_per_line
;
375 _swap_ximage_4bytes (XImage
*ximage
)
378 char *line
= ximage
->data
;
380 for (j
= ximage
->height
; j
; j
--) {
381 uint32_t *p
= (uint32_t *) line
;
382 for (i
= ximage
->width
; i
; i
--) {
387 line
+= ximage
->bytes_per_line
;
392 _swap_ximage_nibbles (XImage
*ximage
)
395 char *line
= ximage
->data
;
397 for (j
= ximage
->height
; j
; j
--) {
398 uint8_t *p
= (uint8_t *) line
;
399 for (i
= (ximage
->width
+ 1) / 2; i
; i
--) {
400 *p
= ((*p
>> 4) & 0xf) | ((*p
<< 4) & ~0xf);
404 line
+= ximage
->bytes_per_line
;
409 _swap_ximage_bits (XImage
*ximage
)
412 char *line
= ximage
->data
;
413 int unit
= ximage
->bitmap_unit
;
414 int line_bytes
= ((ximage
->width
+ unit
- 1) & ~(unit
- 1)) / 8;
416 for (j
= ximage
->height
; j
; j
--) {
419 for (i
= line_bytes
; i
; i
--) {
421 b
= ((b
<< 1) & 0xaa) | ((b
>> 1) & 0x55);
422 b
= ((b
<< 2) & 0xcc) | ((b
>> 2) & 0x33);
423 b
= ((b
<< 4) & 0xf0) | ((b
>> 4) & 0x0f);
429 line
+= ximage
->bytes_per_line
;
434 _swap_ximage_to_native (XImage
*ximage
)
437 int native_byte_order
= _native_byte_order_lsb () ? LSBFirst
: MSBFirst
;
439 if (ximage
->bits_per_pixel
== 1 &&
440 ximage
->bitmap_bit_order
!= native_byte_order
)
442 _swap_ximage_bits (ximage
);
443 if (ximage
->bitmap_bit_order
== ximage
->byte_order
)
447 if (ximage
->byte_order
== native_byte_order
)
450 switch (ximage
->bits_per_pixel
) {
452 unit_bytes
= ximage
->bitmap_unit
/ 8;
455 _swap_ximage_nibbles (ximage
);
464 unit_bytes
= (ximage
->bits_per_pixel
+ 7) / 8;
467 /* This could be hit on some rare but possible cases. */
471 switch (unit_bytes
) {
475 _swap_ximage_2bytes (ximage
);
478 _swap_ximage_3bytes (ximage
);
481 _swap_ximage_4bytes (ximage
);
489 /* Given a mask, (with a single sequence of contiguous 1 bits), return
490 * the number of 1 bits in 'width' and the number of 0 bits to its
491 * right in 'shift'. */
493 _characterize_field (uint32_t mask
, int *width
, int *shift
)
495 *width
= _cairo_popcount (mask
);
496 /* The final '& 31' is to force a 0 mask to result in 0 shift. */
497 *shift
= _cairo_popcount ((mask
- 1) & ~mask
) & 31;
501 /* Convert a field of 'width' bits to 'new_width' bits with correct
503 static inline uint32_t
504 _resize_field (uint32_t field
, int width
, int new_width
)
509 if (width
>= new_width
) {
510 return field
>> (width
- new_width
);
512 uint32_t result
= field
<< (new_width
- width
);
514 while (width
< new_width
) {
515 result
|= result
>> width
;
522 static inline uint32_t
523 _adjust_field (uint32_t field
, int adjustment
)
525 return MIN (255, MAX(0, (int)field
+ adjustment
));
528 /* Given a shifted field value, (described by 'width' and 'shift),
529 * resize it 8-bits and return that value.
531 * Note that the original field value must not have any non-field bits
534 static inline uint32_t
535 _field_to_8 (uint32_t field
, int width
, int shift
)
537 return _resize_field (field
>> shift
, width
, 8);
540 static inline uint32_t
541 _field_to_8_undither (uint32_t field
, int width
, int shift
,
542 int dither_adjustment
)
544 return _adjust_field (_field_to_8 (field
, width
, shift
), - dither_adjustment
>>width
);
547 /* Given an 8-bit value, convert it to a field of 'width', shift it up
548 * to 'shift, and return it. */
549 static inline uint32_t
550 _field_from_8 (uint32_t field
, int width
, int shift
)
552 return _resize_field (field
, 8, width
) << shift
;
555 static inline uint32_t
556 _field_from_8_dither (uint32_t field
, int width
, int shift
,
557 int8_t dither_adjustment
)
559 return _field_from_8 (_adjust_field (field
, dither_adjustment
>>width
), width
, shift
);
562 static inline uint32_t
563 _pseudocolor_from_rgb888_dither (cairo_xlib_visual_info_t
*visual_info
,
564 uint32_t r
, uint32_t g
, uint32_t b
,
565 int8_t dither_adjustment
)
567 if (r
== g
&& g
== b
) {
568 dither_adjustment
/= RAMP_SIZE
;
569 return visual_info
->gray8_to_pseudocolor
[_adjust_field (r
, dither_adjustment
)];
571 dither_adjustment
= visual_info
->dither8_to_cube
[dither_adjustment
+128];
572 return visual_info
->cube_to_pseudocolor
[visual_info
->field8_to_cube
[_adjust_field (r
, dither_adjustment
)]]
573 [visual_info
->field8_to_cube
[_adjust_field (g
, dither_adjustment
)]]
574 [visual_info
->field8_to_cube
[_adjust_field (b
, dither_adjustment
)]];
578 static inline uint32_t
579 _pseudocolor_to_rgb888 (cairo_xlib_visual_info_t
*visual_info
,
584 r
= visual_info
->colors
[pixel
].r
;
585 g
= visual_info
->colors
[pixel
].g
;
586 b
= visual_info
->colors
[pixel
].b
;
593 /* should range from -128 to 127 */
595 static const int8_t dither_pattern
[4][4] = {
596 {-8*X
, +0*X
, -6*X
, +2*X
},
597 {+4*X
, -4*X
, +6*X
, -2*X
},
598 {-5*X
, +4*X
, -7*X
, +1*X
},
599 {+7*X
, -1*X
, +5*X
, -3*X
}
604 static cairo_status_t
605 _get_image_surface (cairo_xlib_surface_t
*surface
,
606 cairo_rectangle_int_t
*interest_rect
,
607 cairo_image_surface_t
**image_out
,
608 cairo_rectangle_int_t
*image_rect
)
610 cairo_int_status_t status
;
611 cairo_image_surface_t
*image
= NULL
;
613 cairo_rectangle_int_t extents
;
614 pixman_format_code_t pixman_format
;
615 cairo_format_masks_t xlib_masks
;
619 extents
.width
= surface
->width
;
620 extents
.height
= surface
->height
;
623 if (! _cairo_rectangle_intersect (&extents
, interest_rect
)) {
625 return CAIRO_STATUS_SUCCESS
;
630 *image_rect
= extents
;
632 /* XXX: This should try to use the XShm extension if available */
634 if (surface
->use_pixmap
== 0)
636 cairo_xlib_error_func_t old_handler
;
638 old_handler
= XSetErrorHandler (_noop_error_handler
);
640 ximage
= XGetImage (surface
->dpy
,
642 extents
.x
, extents
.y
,
643 extents
.width
, extents
.height
,
646 XSetErrorHandler (old_handler
);
648 /* If we get an error, the surface must have been a window,
649 * so retry with the safe code path.
652 surface
->use_pixmap
= CAIRO_ASSUME_PIXMAP
;
656 surface
->use_pixmap
--;
662 /* XGetImage from a window is dangerous because it can
663 * produce errors if the window is unmapped or partially
664 * outside the screen. We could check for errors and
665 * retry, but to keep things simple, we just create a
670 status
= _cairo_xlib_surface_ensure_gc (surface
);
671 if (unlikely (status
))
674 pixmap
= XCreatePixmap (surface
->dpy
,
676 extents
.width
, extents
.height
,
679 XCopyArea (surface
->dpy
, surface
->drawable
, pixmap
, surface
->gc
,
680 extents
.x
, extents
.y
,
681 extents
.width
, extents
.height
,
684 ximage
= XGetImage (surface
->dpy
,
687 extents
.width
, extents
.height
,
690 XFreePixmap (surface
->dpy
, pixmap
);
694 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
696 _cairo_xlib_surface_maybe_put_gc (surface
);
699 _swap_ximage_to_native (ximage
);
701 xlib_masks
.bpp
= ximage
->bits_per_pixel
;
702 xlib_masks
.alpha_mask
= surface
->a_mask
;
703 xlib_masks
.red_mask
= surface
->r_mask
;
704 xlib_masks
.green_mask
= surface
->g_mask
;
705 xlib_masks
.blue_mask
= surface
->b_mask
;
707 if (_pixman_format_from_masks (&xlib_masks
, &pixman_format
) &&
708 xlib_masks
.bpp
>= 24 &&
709 ximage
->bitmap_unit
== 32 &&
710 ximage
->bitmap_pad
== 32)
712 image
= (cairo_image_surface_t
*)
713 _cairo_image_surface_create_with_pixman_format ((unsigned char *) ximage
->data
,
717 ximage
->bytes_per_line
);
718 status
= image
->base
.status
;
719 if (unlikely (status
))
722 /* Let the surface take ownership of the data */
723 _cairo_image_surface_assume_ownership_of_data (image
);
726 /* The visual we are dealing with is not supported by the
727 * standard pixman formats. So we must first convert the data
728 * to a supported format. */
730 cairo_format_t format
;
733 uint32_t in_pixel
, out_pixel
;
734 unsigned int rowstride
;
735 uint32_t a_mask
=0, r_mask
=0, g_mask
=0, b_mask
=0;
736 int a_width
=0, r_width
=0, g_width
=0, b_width
=0;
737 int a_shift
=0, r_shift
=0, g_shift
=0, b_shift
=0;
738 int x
, y
, x0
, y0
, x_off
, y_off
;
739 cairo_xlib_visual_info_t
*visual_info
;
741 if (surface
->visual
== NULL
|| surface
->visual
->class == TrueColor
) {
742 cairo_bool_t has_alpha
;
743 cairo_bool_t has_color
;
745 has_alpha
= surface
->a_mask
;
746 has_color
= (surface
->r_mask
||
752 format
= CAIRO_FORMAT_ARGB32
;
754 format
= CAIRO_FORMAT_RGB24
;
757 /* XXX: Using CAIRO_FORMAT_A8 here would be more
758 * efficient, but would require slightly different code in
759 * the image conversion to put the alpha channel values
760 * into the right place. */
761 format
= CAIRO_FORMAT_ARGB32
;
764 a_mask
= surface
->a_mask
;
765 r_mask
= surface
->r_mask
;
766 g_mask
= surface
->g_mask
;
767 b_mask
= surface
->b_mask
;
769 _characterize_field (a_mask
, &a_width
, &a_shift
);
770 _characterize_field (r_mask
, &r_width
, &r_shift
);
771 _characterize_field (g_mask
, &g_width
, &g_shift
);
772 _characterize_field (b_mask
, &b_width
, &b_shift
);
775 format
= CAIRO_FORMAT_RGB24
;
777 status
= _cairo_xlib_screen_get_visual_info (surface
->screen_info
,
780 if (unlikely (status
))
784 image
= (cairo_image_surface_t
*) cairo_image_surface_create
785 (format
, ximage
->width
, ximage
->height
);
786 status
= image
->base
.status
;
787 if (unlikely (status
))
790 data
= cairo_image_surface_get_data (&image
->base
);
791 rowstride
= cairo_image_surface_get_stride (&image
->base
) >> 2;
792 row
= (uint32_t *) data
;
793 x0
= extents
.x
+ surface
->base
.device_transform
.x0
;
794 y0
= extents
.y
+ surface
->base
.device_transform
.y0
;
795 for (y
= 0, y_off
= y0
% ARRAY_LENGTH (dither_pattern
);
797 y
++, y_off
= (y_off
+1) % ARRAY_LENGTH (dither_pattern
)) {
798 const int8_t *dither_row
= dither_pattern
[y_off
];
799 for (x
= 0, x_off
= x0
% ARRAY_LENGTH (dither_pattern
[0]);
801 x
++, x_off
= (x_off
+1) % ARRAY_LENGTH (dither_pattern
[0])) {
802 int dither_adjustment
= dither_row
[x_off
];
804 in_pixel
= XGetPixel (ximage
, x
, y
);
805 if (surface
->visual
== NULL
|| surface
->visual
->class == TrueColor
) {
807 _field_to_8 (in_pixel
& a_mask
, a_width
, a_shift
) << 24 |
808 _field_to_8_undither (in_pixel
& r_mask
, r_width
, r_shift
, dither_adjustment
) << 16 |
809 _field_to_8_undither (in_pixel
& g_mask
, g_width
, g_shift
, dither_adjustment
) << 8 |
810 _field_to_8_undither (in_pixel
& b_mask
, b_width
, b_shift
, dither_adjustment
));
812 /* Undithering pseudocolor does not look better */
813 out_pixel
= _pseudocolor_to_rgb888 (visual_info
, in_pixel
);
822 XDestroyImage (ximage
);
824 if (unlikely (status
)) {
826 cairo_surface_destroy (&image
->base
);
835 _cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t
*surface
)
837 if (!surface
->src_picture
) {
838 XRenderPictureAttributes pa
;
841 pa
.subwindow_mode
= IncludeInferiors
;
842 mask
|= CPSubwindowMode
;
844 surface
->src_picture
= XRenderCreatePicture (surface
->dpy
,
846 surface
->xrender_format
,
852 _cairo_xlib_surface_set_picture_clip_rects (cairo_xlib_surface_t
*surface
)
854 if (surface
->have_clip_rects
) {
855 XRenderSetPictureClipRectangles (surface
->dpy
, surface
->dst_picture
,
858 surface
->num_clip_rects
);
860 XRenderPictureAttributes pa
;
862 XRenderChangePicture (surface
->dpy
, surface
->dst_picture
,
866 surface
->clip_dirty
&= ~CAIRO_XLIB_SURFACE_CLIP_DIRTY_PICTURE
;
870 _cairo_xlib_surface_set_gc_clip_rects (cairo_xlib_surface_t
*surface
)
872 surface
->gc_has_clip_rects
= surface
->have_clip_rects
;
873 if (surface
->have_clip_rects
) {
874 XSetClipRectangles(surface
->dpy
, surface
->gc
,
877 surface
->num_clip_rects
, YXSorted
);
879 XSetClipMask (surface
->dpy
, surface
->gc
, None
);
881 surface
->clip_dirty
&= ~CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC
;
885 _cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t
*surface
)
887 if (!surface
->dst_picture
) {
888 surface
->dst_picture
= XRenderCreatePicture (surface
->dpy
,
890 surface
->xrender_format
,
894 if (surface
->clip_dirty
& CAIRO_XLIB_SURFACE_CLIP_DIRTY_PICTURE
)
895 _cairo_xlib_surface_set_picture_clip_rects (surface
);
898 static cairo_status_t
899 _cairo_xlib_surface_ensure_gc (cairo_xlib_surface_t
*surface
)
902 if (surface
->gc
== NULL
) {
903 surface
->gc
= _cairo_xlib_screen_get_gc (surface
->screen_info
,
906 &surface
->clip_dirty
);
907 if (unlikely (surface
->gc
== NULL
))
908 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
911 if (surface
->clip_dirty
& CAIRO_XLIB_SURFACE_CLIP_DIRTY_GC
)
912 _cairo_xlib_surface_set_gc_clip_rects (surface
);
914 return CAIRO_STATUS_SUCCESS
;
918 _cairo_xlib_surface_maybe_put_gc (cairo_xlib_surface_t
*surface
)
920 /* return the GC back to the common pool if clean */
922 if (surface
->gc_has_clip_rects
)
925 _cairo_xlib_screen_put_gc (surface
->screen_info
,
932 static cairo_status_t
933 _draw_image_surface (cairo_xlib_surface_t
*surface
,
934 cairo_image_surface_t
*image
,
943 cairo_format_masks_t image_masks
;
944 int native_byte_order
= _native_byte_order_lsb () ? LSBFirst
: MSBFirst
;
945 cairo_status_t status
;
946 cairo_bool_t own_data
;
948 _pixman_format_to_masks (image
->pixman_format
, &image_masks
);
950 ximage
.width
= image
->width
;
951 ximage
.height
= image
->height
;
952 ximage
.format
= ZPixmap
;
953 ximage
.byte_order
= native_byte_order
;
954 ximage
.bitmap_unit
= 32; /* always for libpixman */
955 ximage
.bitmap_bit_order
= native_byte_order
;
956 ximage
.bitmap_pad
= 32; /* always for libpixman */
957 ximage
.depth
= surface
->depth
;
958 ximage
.red_mask
= surface
->r_mask
;
959 ximage
.green_mask
= surface
->g_mask
;
960 ximage
.blue_mask
= surface
->b_mask
;
963 if ((image_masks
.alpha_mask
== surface
->a_mask
|| surface
->a_mask
== 0) &&
964 (image_masks
.red_mask
== surface
->r_mask
|| surface
->r_mask
== 0) &&
965 (image_masks
.green_mask
== surface
->g_mask
|| surface
->g_mask
== 0) &&
966 (image_masks
.blue_mask
== surface
->b_mask
|| surface
->b_mask
== 0))
970 ximage
.bits_per_pixel
= image_masks
.bpp
;
971 ximage
.bytes_per_line
= image
->stride
;
972 ximage
.data
= (char *)image
->data
;
975 ret
= XInitImage (&ximage
);
978 unsigned int stride
, rowstride
;
979 int x
, y
, x0
, y0
, x_off
, y_off
;
980 uint32_t in_pixel
, out_pixel
, *row
;
981 int i_a_width
=0, i_r_width
=0, i_g_width
=0, i_b_width
=0;
982 int i_a_shift
=0, i_r_shift
=0, i_g_shift
=0, i_b_shift
=0;
983 int o_a_width
=0, o_r_width
=0, o_g_width
=0, o_b_width
=0;
984 int o_a_shift
=0, o_r_shift
=0, o_g_shift
=0, o_b_shift
=0;
985 cairo_xlib_visual_info_t
*visual_info
= NULL
;
986 cairo_bool_t true_color
;
989 if (surface
->depth
> 16) {
990 ximage
.bits_per_pixel
= 32;
991 } else if (surface
->depth
> 8) {
992 ximage
.bits_per_pixel
= 16;
993 } else if (surface
->depth
> 1) {
994 ximage
.bits_per_pixel
= 8;
996 ximage
.bits_per_pixel
= 1;
998 stride
= CAIRO_STRIDE_FOR_WIDTH_BPP (ximage
.width
,
999 ximage
.bits_per_pixel
);
1000 ximage
.bytes_per_line
= stride
;
1001 ximage
.data
= _cairo_malloc_ab (stride
, ximage
.height
);
1002 if (unlikely (ximage
.data
== NULL
))
1003 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1007 ret
= XInitImage (&ximage
);
1010 _characterize_field (image_masks
.alpha_mask
, &i_a_width
, &i_a_shift
);
1011 _characterize_field (image_masks
.red_mask
, &i_r_width
, &i_r_shift
);
1012 _characterize_field (image_masks
.green_mask
, &i_g_width
, &i_g_shift
);
1013 _characterize_field (image_masks
.blue_mask
, &i_b_width
, &i_b_shift
);
1015 true_color
= surface
->visual
== NULL
||
1016 surface
->visual
->class == TrueColor
;
1018 _characterize_field (surface
->a_mask
, &o_a_width
, &o_a_shift
);
1019 _characterize_field (surface
->r_mask
, &o_r_width
, &o_r_shift
);
1020 _characterize_field (surface
->g_mask
, &o_g_width
, &o_g_shift
);
1021 _characterize_field (surface
->b_mask
, &o_b_width
, &o_b_shift
);
1023 status
= _cairo_xlib_screen_get_visual_info (surface
->screen_info
,
1026 if (unlikely (status
))
1030 rowstride
= image
->stride
>> 2;
1031 row
= (uint32_t *) image
->data
;
1032 x0
= dst_x
+ surface
->base
.device_transform
.x0
;
1033 y0
= dst_y
+ surface
->base
.device_transform
.y0
;
1034 for (y
= 0, y_off
= y0
% ARRAY_LENGTH (dither_pattern
);
1036 y
++, y_off
= (y_off
+1) % ARRAY_LENGTH (dither_pattern
))
1038 const int8_t *dither_row
= dither_pattern
[y_off
];
1040 for (x
= 0, x_off
= x0
% ARRAY_LENGTH (dither_pattern
[0]);
1042 x
++, x_off
= (x_off
+1) % ARRAY_LENGTH (dither_pattern
[0]))
1044 int dither_adjustment
= dither_row
[x_off
];
1047 if (image_masks
.bpp
<= 8)
1048 in_pixel
= ((uint8_t*)row
)[x
];
1049 else if (image_masks
.bpp
<= 16)
1050 in_pixel
= ((uint16_t*)row
)[x
];
1054 /* If the incoming image has no alpha channel, then the input
1055 * is opaque and the output should have the maximum alpha value.
1056 * For all other channels, their absence implies 0.
1058 if (image_masks
.alpha_mask
== 0x0)
1061 a
= _field_to_8 (in_pixel
& image_masks
.alpha_mask
, i_a_width
, i_a_shift
);
1062 r
= _field_to_8 (in_pixel
& image_masks
.red_mask
, i_r_width
, i_r_shift
);
1063 g
= _field_to_8 (in_pixel
& image_masks
.green_mask
, i_g_width
, i_g_shift
);
1064 b
= _field_to_8 (in_pixel
& image_masks
.blue_mask
, i_b_width
, i_b_shift
);
1067 out_pixel
= _field_from_8 (a
, o_a_width
, o_a_shift
) |
1068 _field_from_8_dither (r
, o_r_width
, o_r_shift
, dither_adjustment
) |
1069 _field_from_8_dither (g
, o_g_width
, o_g_shift
, dither_adjustment
) |
1070 _field_from_8_dither (b
, o_b_width
, o_b_shift
, dither_adjustment
);
1072 out_pixel
= _pseudocolor_from_rgb888_dither (visual_info
, r
, g
, b
, dither_adjustment
);
1075 XPutPixel (&ximage
, x
, y
, out_pixel
);
1082 status
= _cairo_xlib_surface_ensure_gc (surface
);
1083 if (unlikely (status
))
1086 XPutImage(surface
->dpy
, surface
->drawable
, surface
->gc
,
1087 &ximage
, src_x
, src_y
, dst_x
, dst_y
,
1090 _cairo_xlib_surface_maybe_put_gc (surface
);
1099 static cairo_status_t
1100 _cairo_xlib_surface_acquire_source_image (void *abstract_surface
,
1101 cairo_image_surface_t
**image_out
,
1104 cairo_xlib_surface_t
*surface
= abstract_surface
;
1105 cairo_image_surface_t
*image
;
1106 cairo_status_t status
;
1108 _cairo_xlib_display_notify (surface
->display
);
1110 status
= _get_image_surface (surface
, NULL
, &image
, NULL
);
1111 if (unlikely (status
))
1115 *image_extra
= NULL
;
1117 return CAIRO_STATUS_SUCCESS
;
1120 static cairo_surface_t
*
1121 _cairo_xlib_surface_snapshot (void *abstract_surface
)
1123 cairo_xlib_surface_t
*surface
= abstract_surface
;
1124 cairo_image_surface_t
*image
;
1125 cairo_status_t status
;
1127 _cairo_xlib_display_notify (surface
->display
);
1129 status
= _get_image_surface (surface
, NULL
, &image
, NULL
);
1130 if (unlikely (status
))
1131 return _cairo_surface_create_in_error (status
);
1133 return &image
->base
;
1137 _cairo_xlib_surface_release_source_image (void *abstract_surface
,
1138 cairo_image_surface_t
*image
,
1141 cairo_surface_destroy (&image
->base
);
1144 static cairo_status_t
1145 _cairo_xlib_surface_acquire_dest_image (void *abstract_surface
,
1146 cairo_rectangle_int_t
*interest_rect
,
1147 cairo_image_surface_t
**image_out
,
1148 cairo_rectangle_int_t
*image_rect_out
,
1151 cairo_xlib_surface_t
*surface
= abstract_surface
;
1152 cairo_image_surface_t
*image
;
1153 cairo_status_t status
;
1155 _cairo_xlib_display_notify (surface
->display
);
1157 status
= _get_image_surface (surface
, interest_rect
, &image
, image_rect_out
);
1158 if (unlikely (status
))
1162 *image_extra
= NULL
;
1164 return CAIRO_STATUS_SUCCESS
;
1168 _cairo_xlib_surface_release_dest_image (void *abstract_surface
,
1169 cairo_rectangle_int_t
*interest_rect
,
1170 cairo_image_surface_t
*image
,
1171 cairo_rectangle_int_t
*image_rect
,
1174 cairo_xlib_surface_t
*surface
= abstract_surface
;
1175 cairo_status_t status
;
1177 status
= _draw_image_surface (surface
, image
,
1178 0, 0, image
->width
, image
->height
,
1179 image_rect
->x
, image_rect
->y
);
1180 status
= _cairo_surface_set_error (&surface
->base
, status
);
1182 cairo_surface_destroy (&image
->base
);
1186 * Return whether two xlib surfaces share the same
1187 * screen. Both core and Render drawing require this
1188 * when using multiple drawables in an operation.
1191 _cairo_xlib_surface_same_screen (cairo_xlib_surface_t
*dst
,
1192 cairo_xlib_surface_t
*src
)
1194 return dst
->dpy
== src
->dpy
&& dst
->screen
== src
->screen
;
1197 static cairo_status_t
1198 _cairo_xlib_surface_clone_similar (void *abstract_surface
,
1199 cairo_surface_t
*src
,
1200 cairo_content_t content
,
1205 int *clone_offset_x
,
1206 int *clone_offset_y
,
1207 cairo_surface_t
**clone_out
)
1209 cairo_xlib_surface_t
*surface
= abstract_surface
;
1210 cairo_xlib_surface_t
*clone
;
1211 cairo_status_t status
;
1213 _cairo_xlib_display_notify (surface
->display
);
1215 if (src
->backend
== surface
->base
.backend
) {
1216 cairo_xlib_surface_t
*xlib_src
= (cairo_xlib_surface_t
*)src
;
1218 if (_cairo_xlib_surface_same_screen (surface
, xlib_src
)) {
1219 *clone_offset_x
= 0;
1220 *clone_offset_y
= 0;
1221 *clone_out
= cairo_surface_reference (src
);
1223 return CAIRO_STATUS_SUCCESS
;
1225 } else if (_cairo_surface_is_image (src
)) {
1226 cairo_image_surface_t
*image_src
= (cairo_image_surface_t
*)src
;
1227 cairo_format_t format
;
1229 if (width
> XLIB_COORD_MAX
|| height
> XLIB_COORD_MAX
)
1230 return CAIRO_INT_STATUS_UNSUPPORTED
;
1232 format
= image_src
->format
;
1233 if (format
== CAIRO_FORMAT_INVALID
||
1234 (_cairo_content_from_format (format
) & ~content
))
1236 format
= _cairo_format_from_content (image_src
->base
.content
& content
);
1238 clone
= (cairo_xlib_surface_t
*)
1239 _cairo_xlib_surface_create_similar_with_format (surface
,
1243 return CAIRO_INT_STATUS_UNSUPPORTED
;
1245 if (clone
->base
.status
)
1246 return clone
->base
.status
;
1248 status
= _draw_image_surface (clone
, image_src
,
1252 if (unlikely (status
)) {
1253 cairo_surface_destroy (&clone
->base
);
1257 *clone_offset_x
= src_x
;
1258 *clone_offset_y
= src_y
;
1259 *clone_out
= &clone
->base
;
1261 return CAIRO_STATUS_SUCCESS
;
1264 return CAIRO_INT_STATUS_UNSUPPORTED
;
1267 static cairo_surface_t
*
1268 _cairo_xlib_surface_create_solid_pattern_surface (void *abstract_surface
,
1269 const cairo_solid_pattern_t
*solid_pattern
)
1271 /* This function's only responsibility is to create a proper surface
1272 * for when XRender is not available. The proper surface is a xlib
1273 * surface (as opposed to image surface which is what create_similar
1274 * returns in those cases) and the size of the dithering pattern, not
1275 * 1x1. This surface can then be used in
1276 * _cairo_xlib_surface_solid_fill_rectangles() to do dithered "solid"
1277 * fills using core protocol */
1279 cairo_xlib_surface_t
*other
= abstract_surface
;
1280 cairo_image_surface_t
*image
;
1281 cairo_xlib_surface_t
*surface
= NULL
;
1282 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
1284 int width
= ARRAY_LENGTH (dither_pattern
[0]);
1285 int height
= ARRAY_LENGTH (dither_pattern
);
1287 Pixmap pixmap
= None
;
1289 if (CAIRO_SURFACE_RENDER_HAS_COMPOSITE (other
))
1292 if (width
> XLIB_COORD_MAX
|| height
> XLIB_COORD_MAX
)
1295 image
= (cairo_image_surface_t
*)
1296 _cairo_image_surface_create_with_content (solid_pattern
->content
,
1298 status
= image
->base
.status
;
1299 if (unlikely (status
))
1302 pixmap
= XCreatePixmap (other
->dpy
,
1307 surface
= (cairo_xlib_surface_t
*)
1308 _cairo_xlib_surface_create_internal (other
->dpy
,
1310 other
->screen
, other
->visual
,
1311 other
->xrender_format
,
1314 status
= surface
->base
.status
;
1315 if (unlikely (status
))
1318 status
= _cairo_surface_paint (&image
->base
,
1319 CAIRO_OPERATOR_SOURCE
,
1320 &solid_pattern
->base
, NULL
);
1321 if (unlikely (status
))
1324 status
= _draw_image_surface (surface
, image
,
1328 if (unlikely (status
))
1332 cairo_surface_destroy (&image
->base
);
1334 if (unlikely (status
)) {
1336 XFreePixmap (other
->dpy
, pixmap
);
1337 cairo_surface_destroy (&surface
->base
);
1339 return _cairo_surface_create_in_error (status
);
1342 surface
->owns_pixmap
= TRUE
;
1343 return &surface
->base
;
1347 _cairo_xlib_surface_can_repaint_solid_pattern_surface (void *abstract_surface
,
1348 const cairo_solid_pattern_t
*solid_pattern
)
1350 cairo_xlib_surface_t
*other
= abstract_surface
;
1351 return CAIRO_SURFACE_RENDER_HAS_COMPOSITE (other
);
1355 static cairo_status_t
1356 _cairo_xlib_surface_set_matrix (cairo_xlib_surface_t
*surface
,
1357 cairo_matrix_t
*matrix
,
1361 XTransform xtransform
;
1363 /* Casting between pixman_transform_t and XTransform is safe because
1364 * they happen to be the exact same type.
1366 _cairo_matrix_to_pixman_matrix (matrix
,
1367 (pixman_transform_t
*) &xtransform
,
1370 if (memcmp (&xtransform
, &surface
->xtransform
, sizeof (XTransform
)) == 0)
1371 return CAIRO_STATUS_SUCCESS
;
1373 if (!CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface
))
1374 return CAIRO_INT_STATUS_UNSUPPORTED
;
1376 XRenderSetPictureTransform (surface
->dpy
, surface
->src_picture
, &xtransform
);
1377 surface
->xtransform
= xtransform
;
1379 return CAIRO_STATUS_SUCCESS
;
1382 static cairo_status_t
1383 _cairo_xlib_surface_set_filter (cairo_xlib_surface_t
*surface
,
1384 cairo_filter_t filter
)
1386 const char *render_filter
;
1388 if (surface
->filter
== filter
)
1389 return CAIRO_STATUS_SUCCESS
;
1391 if (!CAIRO_SURFACE_RENDER_HAS_FILTERS (surface
))
1393 if (filter
== CAIRO_FILTER_FAST
|| filter
== CAIRO_FILTER_NEAREST
)
1394 return CAIRO_STATUS_SUCCESS
;
1396 return CAIRO_INT_STATUS_UNSUPPORTED
;
1400 case CAIRO_FILTER_FAST
:
1401 render_filter
= FilterFast
;
1403 case CAIRO_FILTER_GOOD
:
1404 render_filter
= FilterGood
;
1406 case CAIRO_FILTER_BEST
:
1407 render_filter
= FilterBest
;
1409 case CAIRO_FILTER_NEAREST
:
1410 render_filter
= FilterNearest
;
1412 case CAIRO_FILTER_BILINEAR
:
1413 render_filter
= FilterBilinear
;
1415 case CAIRO_FILTER_GAUSSIAN
:
1416 /* XXX: The GAUSSIAN value has no implementation in cairo
1417 * whatsoever, so it was really a mistake to have it in the
1418 * API. We could fix this by officially deprecating it, or
1419 * else inventing semantics and providing an actual
1420 * implementation for it. */
1422 render_filter
= FilterBest
;
1426 XRenderSetPictureFilter (surface
->dpy
, surface
->src_picture
,
1427 (char *) render_filter
, NULL
, 0);
1428 surface
->filter
= filter
;
1430 return CAIRO_STATUS_SUCCESS
;
1434 _cairo_xlib_surface_set_repeat (cairo_xlib_surface_t
*surface
, int repeat
)
1436 XRenderPictureAttributes pa
;
1439 if (surface
->repeat
== repeat
)
1445 XRenderChangePicture (surface
->dpy
, surface
->src_picture
, mask
, &pa
);
1446 surface
->repeat
= repeat
;
1449 static cairo_int_status_t
1450 _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t
*surface
,
1451 cairo_surface_attributes_t
*attributes
,
1455 cairo_int_status_t status
;
1457 _cairo_xlib_surface_ensure_src_picture (surface
);
1459 status
= _cairo_xlib_surface_set_matrix (surface
, &attributes
->matrix
,
1461 if (unlikely (status
))
1464 switch (attributes
->extend
) {
1465 case CAIRO_EXTEND_NONE
:
1466 _cairo_xlib_surface_set_repeat (surface
, RepeatNone
);
1468 case CAIRO_EXTEND_REPEAT
:
1469 _cairo_xlib_surface_set_repeat (surface
, RepeatNormal
);
1471 case CAIRO_EXTEND_REFLECT
:
1472 if (surface
->buggy_pad_reflect
)
1473 return CAIRO_INT_STATUS_UNSUPPORTED
;
1474 _cairo_xlib_surface_set_repeat (surface
, RepeatReflect
);
1476 case CAIRO_EXTEND_PAD
:
1477 if (surface
->buggy_pad_reflect
)
1478 return CAIRO_INT_STATUS_UNSUPPORTED
;
1479 _cairo_xlib_surface_set_repeat (surface
, RepeatPad
);
1482 return CAIRO_INT_STATUS_UNSUPPORTED
;
1485 status
= _cairo_xlib_surface_set_filter (surface
, attributes
->filter
);
1486 if (unlikely (status
))
1489 return CAIRO_STATUS_SUCCESS
;
1492 /* Checks whether we can can directly draw from src to dst with
1493 * the core protocol: either with CopyArea or using src as a
1497 _surfaces_compatible (cairo_xlib_surface_t
*dst
,
1498 cairo_xlib_surface_t
*src
)
1501 if (!_cairo_xlib_surface_same_screen (dst
, src
))
1504 /* same depth (for core) */
1505 if (src
->depth
!= dst
->depth
)
1508 /* if Render is supported, match picture formats */
1509 if (src
->xrender_format
!= dst
->xrender_format
)
1511 else if (src
->xrender_format
!= NULL
)
1514 /* Without Render, match visuals instead */
1515 if (src
->visual
== dst
->visual
)
1522 _surface_has_alpha (cairo_xlib_surface_t
*surface
)
1524 if (surface
->xrender_format
) {
1525 if (surface
->xrender_format
->type
== PictTypeDirect
&&
1526 surface
->xrender_format
->direct
.alphaMask
!= 0)
1532 /* In the no-render case, we never have alpha */
1537 /* Returns true if the given operator and source-alpha combination
1538 * requires alpha compositing to complete.
1541 _operator_needs_alpha_composite (cairo_operator_t op
,
1542 cairo_bool_t destination_has_alpha
,
1543 cairo_bool_t source_has_alpha
)
1545 if (op
== CAIRO_OPERATOR_SOURCE
||
1546 (! source_has_alpha
&&
1547 (op
== CAIRO_OPERATOR_OVER
||
1548 op
== CAIRO_OPERATOR_ATOP
||
1549 op
== CAIRO_OPERATOR_IN
)))
1550 return destination_has_alpha
;
1555 /* There is a bug in most older X servers with compositing using a
1556 * untransformed repeating source pattern when the source is in off-screen
1557 * video memory, and another with repeated transformed images using a
1558 * general transform matrix. When these bugs could be triggered, we need a
1559 * fallback: in the common case where we have no transformation and the
1560 * source and destination have the same format/visual, we can do the
1561 * operation using the core protocol for the first bug, otherwise, we need
1562 * a software fallback.
1564 * We can also often optimize a compositing operation by calling XCopyArea
1565 * for some common cases where there is no alpha compositing to be done.
1566 * We figure that out here as well.
1569 DO_RENDER
, /* use render */
1570 DO_XCOPYAREA
, /* core protocol XCopyArea optimization/fallback */
1571 DO_XTILE
, /* core protocol XSetTile optimization/fallback */
1572 DO_UNSUPPORTED
/* software fallback */
1573 } composite_operation_t
;
1575 /* Initial check for the render bugs; we need to recheck for the
1576 * offscreen-memory bug after we turn patterns into surfaces, since that
1577 * may introduce a repeating pattern for gradient patterns. We don't need
1578 * to check for the repeat+transform bug because gradient surfaces aren't
1581 * All we do here is reject cases where we *know* are going to
1582 * hit the bug and won't be able to use a core protocol fallback.
1584 static composite_operation_t
1585 _categorize_composite_operation (cairo_xlib_surface_t
*dst
,
1586 cairo_operator_t op
,
1587 const cairo_pattern_t
*src_pattern
,
1588 cairo_bool_t have_mask
)
1591 if (!dst
->buggy_repeat
)
1594 if (src_pattern
->type
== CAIRO_PATTERN_TYPE_SURFACE
)
1596 cairo_surface_pattern_t
*surface_pattern
= (cairo_surface_pattern_t
*)src_pattern
;
1598 if (_cairo_matrix_is_integer_translation (&src_pattern
->matrix
, NULL
, NULL
) &&
1599 src_pattern
->extend
== CAIRO_EXTEND_REPEAT
)
1601 /* This is the case where we have the bug involving
1602 * untransformed repeating source patterns with off-screen
1603 * video memory; reject some cases where a core protocol
1604 * fallback is impossible.
1607 !(op
== CAIRO_OPERATOR_SOURCE
|| op
== CAIRO_OPERATOR_OVER
))
1608 return DO_UNSUPPORTED
;
1610 if (_cairo_surface_is_xlib (surface_pattern
->surface
)) {
1611 cairo_xlib_surface_t
*src
= (cairo_xlib_surface_t
*)surface_pattern
->surface
;
1613 if (op
== CAIRO_OPERATOR_OVER
&& _surface_has_alpha (src
))
1614 return DO_UNSUPPORTED
;
1616 /* If these are on the same screen but otherwise incompatible,
1617 * make a copy as core drawing can't cross depths and doesn't
1618 * work right across visuals of the same depth
1620 if (_cairo_xlib_surface_same_screen (dst
, src
) &&
1621 !_surfaces_compatible (dst
, src
))
1622 return DO_UNSUPPORTED
;
1626 /* Check for the other bug involving repeat patterns with general
1628 if (!_cairo_matrix_is_integer_translation (&src_pattern
->matrix
, NULL
, NULL
) &&
1629 src_pattern
->extend
== CAIRO_EXTEND_REPEAT
)
1630 return DO_UNSUPPORTED
;
1636 /* Recheck for composite-repeat once we've turned patterns into Xlib surfaces
1637 * If we end up returning DO_UNSUPPORTED here, we're throwing away work we
1638 * did to turn gradients into a pattern, but most of the time we can handle
1639 * that case with core protocol fallback.
1641 * Also check here if we can just use XCopyArea, instead of going through
1644 static composite_operation_t
1645 _recategorize_composite_operation (cairo_xlib_surface_t
*dst
,
1646 cairo_operator_t op
,
1647 cairo_xlib_surface_t
*src
,
1648 cairo_surface_attributes_t
*src_attr
,
1649 cairo_bool_t have_mask
)
1651 cairo_bool_t is_integer_translation
=
1652 _cairo_matrix_is_integer_translation (&src_attr
->matrix
, NULL
, NULL
);
1653 cairo_bool_t needs_alpha_composite
;
1655 if (! _cairo_surface_is_xlib (&src
->base
))
1656 return DO_UNSUPPORTED
;
1658 needs_alpha_composite
=
1659 _operator_needs_alpha_composite (op
,
1660 _surface_has_alpha (dst
),
1661 _surface_has_alpha (src
));
1664 is_integer_translation
&&
1665 src_attr
->extend
== CAIRO_EXTEND_NONE
&&
1666 ! needs_alpha_composite
&&
1667 _surfaces_compatible (src
, dst
))
1669 return DO_XCOPYAREA
;
1672 if (dst
->buggy_repeat
&&
1673 is_integer_translation
&&
1674 src_attr
->extend
== CAIRO_EXTEND_REPEAT
&&
1675 (src
->width
!= 1 || src
->height
!= 1))
1678 ! needs_alpha_composite
&&
1679 _surfaces_compatible (dst
, src
))
1684 return DO_UNSUPPORTED
;
1687 if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src
))
1688 return DO_UNSUPPORTED
;
1690 if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst
))
1691 return DO_UNSUPPORTED
;
1697 _render_operator (cairo_operator_t op
)
1700 case CAIRO_OPERATOR_CLEAR
:
1703 case CAIRO_OPERATOR_SOURCE
:
1705 case CAIRO_OPERATOR_OVER
:
1707 case CAIRO_OPERATOR_IN
:
1709 case CAIRO_OPERATOR_OUT
:
1711 case CAIRO_OPERATOR_ATOP
:
1714 case CAIRO_OPERATOR_DEST
:
1716 case CAIRO_OPERATOR_DEST_OVER
:
1717 return PictOpOverReverse
;
1718 case CAIRO_OPERATOR_DEST_IN
:
1719 return PictOpInReverse
;
1720 case CAIRO_OPERATOR_DEST_OUT
:
1721 return PictOpOutReverse
;
1722 case CAIRO_OPERATOR_DEST_ATOP
:
1723 return PictOpAtopReverse
;
1725 case CAIRO_OPERATOR_XOR
:
1727 case CAIRO_OPERATOR_ADD
:
1729 case CAIRO_OPERATOR_SATURATE
:
1730 return PictOpSaturate
;
1736 static cairo_int_status_t
1737 _cairo_xlib_surface_composite (cairo_operator_t op
,
1738 const cairo_pattern_t
*src_pattern
,
1739 const cairo_pattern_t
*mask_pattern
,
1748 unsigned int height
)
1750 cairo_surface_attributes_t src_attr
, mask_attr
;
1751 cairo_xlib_surface_t
*dst
= abstract_dst
;
1752 cairo_xlib_surface_t
*src
;
1753 cairo_xlib_surface_t
*mask
;
1754 cairo_int_status_t status
;
1755 composite_operation_t operation
;
1757 cairo_bool_t is_integer_translation
;
1758 cairo_bool_t needs_alpha_composite
;
1759 cairo_content_t src_content
;
1761 _cairo_xlib_display_notify (dst
->display
);
1763 operation
= _categorize_composite_operation (dst
, op
, src_pattern
,
1764 mask_pattern
!= NULL
);
1765 if (operation
== DO_UNSUPPORTED
)
1766 return CAIRO_INT_STATUS_UNSUPPORTED
;
1768 needs_alpha_composite
=
1769 _operator_needs_alpha_composite (op
,
1770 _surface_has_alpha (dst
),
1771 ! _cairo_pattern_is_opaque (src_pattern
));
1772 src_content
= CAIRO_CONTENT_COLOR_ALPHA
;
1773 if (! needs_alpha_composite
)
1774 src_content
&= ~CAIRO_CONTENT_ALPHA
;
1776 status
= _cairo_pattern_acquire_surfaces (src_pattern
, mask_pattern
,
1782 dst
->buggy_pad_reflect
?
1783 CAIRO_PATTERN_ACQUIRE_NO_REFLECT
:
1784 CAIRO_PATTERN_ACQUIRE_NONE
,
1785 (cairo_surface_t
**) &src
,
1786 (cairo_surface_t
**) &mask
,
1787 &src_attr
, &mask_attr
);
1788 if (unlikely (status
))
1791 /* check for fallback surfaces that we cannot handle ... */
1792 if (!_cairo_surface_is_xlib (&src
->base
)) {
1793 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
1797 (! _cairo_surface_is_xlib (&mask
->base
) ||
1798 ! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (dst
)))
1800 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
1804 operation
= _recategorize_composite_operation (dst
, op
, src
, &src_attr
,
1805 mask_pattern
!= NULL
);
1806 if (operation
== DO_UNSUPPORTED
) {
1807 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
1814 status
= _cairo_xlib_surface_set_attributes (src
, &src_attr
,
1816 dst_y
+ height
/ 2.);
1817 if (unlikely (status
))
1820 _cairo_xlib_surface_ensure_dst_picture (dst
);
1822 status
= _cairo_xlib_surface_set_attributes (mask
, &mask_attr
,
1824 dst_y
+ height
/ 2.);
1825 if (unlikely (status
))
1828 XRenderComposite (dst
->dpy
,
1829 _render_operator (op
),
1833 src_x
+ src_attr
.x_offset
,
1834 src_y
+ src_attr
.y_offset
,
1835 mask_x
+ mask_attr
.x_offset
,
1836 mask_y
+ mask_attr
.y_offset
,
1840 XRenderComposite (dst
->dpy
,
1841 _render_operator (op
),
1845 src_x
+ src_attr
.x_offset
,
1846 src_y
+ src_attr
.y_offset
,
1855 status
= _cairo_xlib_surface_ensure_gc (dst
);
1856 if (unlikely (status
))
1859 is_integer_translation
= _cairo_matrix_is_integer_translation (&src_attr
.matrix
,
1861 /* This is a pre-condition for DO_XCOPYAREA. */
1862 assert (is_integer_translation
);
1864 XCopyArea (dst
->dpy
,
1868 src_x
+ src_attr
.x_offset
+ itx
,
1869 src_y
+ src_attr
.y_offset
+ ity
,
1873 _cairo_xlib_surface_maybe_put_gc (dst
);
1877 /* This case is only used for bug fallbacks, though we also use it for
1878 * the case where we don't have the RENDER extension, by forcing
1879 * buggy_repeat to TRUE.
1881 * We've checked that we have a repeating unscaled source in
1882 * _recategorize_composite_operation.
1885 status
= _cairo_xlib_surface_ensure_gc (dst
);
1886 if (unlikely (status
))
1888 is_integer_translation
= _cairo_matrix_is_integer_translation (&src_attr
.matrix
,
1890 /* This is a pre-condition for DO_XTILE. */
1891 assert (is_integer_translation
);
1893 XSetTSOrigin (dst
->dpy
, dst
->gc
,
1894 - (itx
+ src_attr
.x_offset
), - (ity
+ src_attr
.y_offset
));
1895 XSetTile (dst
->dpy
, dst
->gc
, src
->drawable
);
1896 XSetFillStyle (dst
->dpy
, dst
->gc
, FillTiled
);
1898 XFillRectangle (dst
->dpy
, dst
->drawable
, dst
->gc
,
1899 dst_x
, dst_y
, width
, height
);
1901 _cairo_xlib_surface_maybe_put_gc (dst
);
1904 case DO_UNSUPPORTED
:
1909 if (!_cairo_operator_bounded_by_source (op
))
1910 status
= _cairo_surface_composite_fixup_unbounded (&dst
->base
,
1911 &src_attr
, src
->width
, src
->height
,
1912 mask
? &mask_attr
: NULL
,
1913 mask
? mask
->width
: 0,
1914 mask
? mask
->height
: 0,
1917 dst_x
, dst_y
, width
, height
);
1921 _cairo_pattern_release_surface (mask_pattern
, &mask
->base
, &mask_attr
);
1923 _cairo_pattern_release_surface (src_pattern
, &src
->base
, &src_attr
);
1928 static cairo_int_status_t
1929 _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t
*surface
,
1930 const cairo_color_t
*color
,
1931 cairo_rectangle_int_t
*rects
,
1934 cairo_status_t status
;
1935 cairo_solid_pattern_t solid
;
1936 cairo_surface_t
*solid_surface
= NULL
;
1937 cairo_surface_attributes_t attrs
;
1940 _cairo_pattern_init_solid (&solid
, color
, CAIRO_CONTENT_COLOR
);
1942 status
= _cairo_xlib_surface_ensure_gc (surface
);
1943 if (unlikely (status
))
1946 status
= _cairo_pattern_acquire_surface (&solid
.base
, &surface
->base
,
1947 CAIRO_CONTENT_COLOR_ALPHA
,
1949 ARRAY_LENGTH (dither_pattern
[0]),
1950 ARRAY_LENGTH (dither_pattern
),
1951 CAIRO_PATTERN_ACQUIRE_NONE
,
1954 if (unlikely (status
))
1957 if (! _cairo_surface_is_xlib (solid_surface
)) {
1958 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
1962 XSetTSOrigin (surface
->dpy
, surface
->gc
,
1963 - (surface
->base
.device_transform
.x0
+ attrs
.x_offset
),
1964 - (surface
->base
.device_transform
.y0
+ attrs
.y_offset
));
1965 XSetTile (surface
->dpy
, surface
->gc
,
1966 ((cairo_xlib_surface_t
*) solid_surface
)->drawable
);
1967 XSetFillStyle (surface
->dpy
, surface
->gc
, FillTiled
);
1969 for (i
= 0; i
< num_rects
; i
++) {
1970 XFillRectangle (surface
->dpy
, surface
->drawable
, surface
->gc
,
1971 rects
[i
].x
, rects
[i
].y
,
1972 rects
[i
].width
, rects
[i
].height
);
1975 _cairo_xlib_surface_maybe_put_gc (surface
);
1978 _cairo_pattern_release_surface (&solid
.base
, solid_surface
, &attrs
);
1983 static cairo_int_status_t
1984 _cairo_xlib_surface_fill_rectangles (void *abstract_surface
,
1985 cairo_operator_t op
,
1986 const cairo_color_t
*color
,
1987 cairo_rectangle_int_t
*rects
,
1990 cairo_xlib_surface_t
*surface
= abstract_surface
;
1991 XRenderColor render_color
;
1994 _cairo_xlib_display_notify (surface
->display
);
1996 if (! CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES (surface
)) {
1997 if (op
== CAIRO_OPERATOR_CLEAR
||
1998 ((op
== CAIRO_OPERATOR_SOURCE
|| op
== CAIRO_OPERATOR_OVER
) &&
1999 CAIRO_COLOR_IS_OPAQUE (color
)))
2001 return _cairo_xlib_surface_solid_fill_rectangles (surface
, color
,
2005 return CAIRO_INT_STATUS_UNSUPPORTED
;
2008 render_color
.red
= color
->red_short
;
2009 render_color
.green
= color
->green_short
;
2010 render_color
.blue
= color
->blue_short
;
2011 render_color
.alpha
= color
->alpha_short
;
2013 _cairo_xlib_surface_ensure_dst_picture (surface
);
2014 if (num_rects
== 1) {
2015 /* Take advantage of the protocol compaction that libXrender performs
2016 * to amalgamate sequences of XRenderFillRectangle().
2018 XRenderFillRectangle (surface
->dpy
,
2019 _render_operator (op
),
2020 surface
->dst_picture
,
2027 XRectangle static_xrects
[CAIRO_STACK_ARRAY_LENGTH (XRectangle
)];
2028 XRectangle
*xrects
= static_xrects
;
2030 if (num_rects
> ARRAY_LENGTH (static_xrects
)) {
2031 xrects
= _cairo_malloc_ab (num_rects
, sizeof (XRectangle
));
2032 if (unlikely (xrects
== NULL
))
2033 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2036 for (i
= 0; i
< num_rects
; i
++) {
2037 xrects
[i
].x
= rects
[i
].x
;
2038 xrects
[i
].y
= rects
[i
].y
;
2039 xrects
[i
].width
= rects
[i
].width
;
2040 xrects
[i
].height
= rects
[i
].height
;
2043 XRenderFillRectangles (surface
->dpy
,
2044 _render_operator (op
),
2045 surface
->dst_picture
,
2046 &render_color
, xrects
, num_rects
);
2048 if (xrects
!= static_xrects
)
2052 return CAIRO_STATUS_SUCCESS
;
2055 /* Creates an A8 picture of size @width x @height, initialized with @color
2058 _create_a8_picture (cairo_xlib_surface_t
*surface
,
2059 XRenderColor
*color
,
2062 cairo_bool_t repeat
)
2064 XRenderPictureAttributes pa
;
2065 unsigned long mask
= 0;
2069 XRenderPictFormat
*xrender_format
;
2071 if (width
> XLIB_COORD_MAX
|| height
> XLIB_COORD_MAX
)
2075 _cairo_xlib_display_get_xrender_format (surface
->display
,
2077 if (xrender_format
== NULL
)
2080 pixmap
= XCreatePixmap (surface
->dpy
, surface
->drawable
,
2081 width
<= 0 ? 1 : width
,
2082 height
<= 0 ? 1 : height
,
2090 picture
= XRenderCreatePicture (surface
->dpy
, pixmap
,
2091 xrender_format
, mask
, &pa
);
2092 XRenderFillRectangle (surface
->dpy
, PictOpSrc
, picture
, color
,
2093 0, 0, width
, height
);
2094 XFreePixmap (surface
->dpy
, pixmap
);
2099 /* Creates a temporary mask for the trapezoids covering the area
2100 * [@dst_x, @dst_y, @width, @height] of the destination surface.
2103 _create_trapezoid_mask (cairo_xlib_surface_t
*dst
,
2104 cairo_trapezoid_t
*traps
,
2110 XRenderPictFormat
*pict_format
)
2112 XRenderColor transparent
= { 0, 0, 0, 0 };
2113 XRenderColor solid
= { 0xffff, 0xffff, 0xffff, 0xffff };
2114 Picture mask_picture
, solid_picture
;
2115 XTrapezoid
*offset_traps
;
2118 /* This would be considerably simpler using XRenderAddTraps(), but since
2119 * we are only using this in the unbounded-operator case, we stick with
2120 * XRenderCompositeTrapezoids, which is available on older versions
2121 * of RENDER rather than conditionalizing. We should still hit an
2122 * optimization that avoids creating another intermediate surface on
2123 * the servers that have XRenderAddTraps().
2125 mask_picture
= _create_a8_picture (dst
, &transparent
, width
, height
, FALSE
);
2126 if (mask_picture
== None
|| num_traps
== 0)
2127 return mask_picture
;
2129 offset_traps
= _cairo_malloc_ab (num_traps
, sizeof (XTrapezoid
));
2130 if (!offset_traps
) {
2131 XRenderFreePicture (dst
->dpy
, mask_picture
);
2132 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
2136 for (i
= 0; i
< num_traps
; i
++) {
2137 offset_traps
[i
].top
= _cairo_fixed_to_16_16(traps
[i
].top
) - 0x10000 * dst_y
;
2138 offset_traps
[i
].bottom
= _cairo_fixed_to_16_16(traps
[i
].bottom
) - 0x10000 * dst_y
;
2139 offset_traps
[i
].left
.p1
.x
= _cairo_fixed_to_16_16(traps
[i
].left
.p1
.x
) - 0x10000 * dst_x
;
2140 offset_traps
[i
].left
.p1
.y
= _cairo_fixed_to_16_16(traps
[i
].left
.p1
.y
) - 0x10000 * dst_y
;
2141 offset_traps
[i
].left
.p2
.x
= _cairo_fixed_to_16_16(traps
[i
].left
.p2
.x
) - 0x10000 * dst_x
;
2142 offset_traps
[i
].left
.p2
.y
= _cairo_fixed_to_16_16(traps
[i
].left
.p2
.y
) - 0x10000 * dst_y
;
2143 offset_traps
[i
].right
.p1
.x
= _cairo_fixed_to_16_16(traps
[i
].right
.p1
.x
) - 0x10000 * dst_x
;
2144 offset_traps
[i
].right
.p1
.y
= _cairo_fixed_to_16_16(traps
[i
].right
.p1
.y
) - 0x10000 * dst_y
;
2145 offset_traps
[i
].right
.p2
.x
= _cairo_fixed_to_16_16(traps
[i
].right
.p2
.x
) - 0x10000 * dst_x
;
2146 offset_traps
[i
].right
.p2
.y
= _cairo_fixed_to_16_16(traps
[i
].right
.p2
.y
) - 0x10000 * dst_y
;
2149 solid_picture
= _create_a8_picture (dst
, &solid
, width
, height
, TRUE
);
2150 if (solid_picture
== None
) {
2151 XRenderFreePicture (dst
->dpy
, mask_picture
);
2152 free (offset_traps
);
2156 XRenderCompositeTrapezoids (dst
->dpy
, PictOpAdd
,
2157 solid_picture
, mask_picture
,
2160 offset_traps
, num_traps
);
2162 XRenderFreePicture (dst
->dpy
, solid_picture
);
2163 free (offset_traps
);
2165 return mask_picture
;
2168 static cairo_int_status_t
2169 _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op
,
2170 const cairo_pattern_t
*pattern
,
2172 cairo_antialias_t antialias
,
2178 unsigned int height
,
2179 cairo_trapezoid_t
*traps
,
2182 cairo_surface_attributes_t attributes
;
2183 cairo_xlib_surface_t
*dst
= abstract_dst
;
2184 cairo_xlib_surface_t
*src
;
2185 cairo_int_status_t status
;
2186 composite_operation_t operation
;
2187 int render_reference_x
, render_reference_y
;
2188 int render_src_x
, render_src_y
;
2189 XRenderPictFormat
*pict_format
;
2191 _cairo_xlib_display_notify (dst
->display
);
2193 if (!CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst
))
2194 return CAIRO_INT_STATUS_UNSUPPORTED
;
2196 operation
= _categorize_composite_operation (dst
, op
, pattern
, TRUE
);
2197 if (operation
== DO_UNSUPPORTED
)
2198 return CAIRO_INT_STATUS_UNSUPPORTED
;
2200 status
= _cairo_pattern_acquire_surface (pattern
, &dst
->base
,
2201 CAIRO_CONTENT_COLOR_ALPHA
,
2202 src_x
, src_y
, width
, height
,
2203 dst
->buggy_pad_reflect
?
2204 CAIRO_PATTERN_ACQUIRE_NO_REFLECT
:
2205 CAIRO_PATTERN_ACQUIRE_NONE
,
2206 (cairo_surface_t
**) &src
,
2208 if (unlikely (status
))
2211 operation
= _recategorize_composite_operation (dst
, op
, src
,
2213 if (operation
== DO_UNSUPPORTED
) {
2214 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
2219 _cairo_xlib_display_get_xrender_format (dst
->display
,
2220 (antialias
== CAIRO_ANTIALIAS_NONE
) ? CAIRO_FORMAT_A1
: CAIRO_FORMAT_A8
);
2222 if (traps
[0].left
.p1
.y
< traps
[0].left
.p2
.y
) {
2223 render_reference_x
= _cairo_fixed_integer_floor (traps
[0].left
.p1
.x
);
2224 render_reference_y
= _cairo_fixed_integer_floor (traps
[0].left
.p1
.y
);
2226 render_reference_x
= _cairo_fixed_integer_floor (traps
[0].left
.p2
.x
);
2227 render_reference_y
= _cairo_fixed_integer_floor (traps
[0].left
.p2
.y
);
2230 render_src_x
= src_x
+ render_reference_x
- dst_x
;
2231 render_src_y
= src_y
+ render_reference_y
- dst_y
;
2233 _cairo_xlib_surface_ensure_dst_picture (dst
);
2234 status
= _cairo_xlib_surface_set_attributes (src
, &attributes
,
2236 dst_y
+ height
/ 2.);
2237 if (unlikely (status
))
2240 if (!_cairo_operator_bounded_by_mask (op
)) {
2241 /* XRenderCompositeTrapezoids() creates a mask only large enough for the
2242 * trapezoids themselves, but if the operator is unbounded, then we need
2243 * to actually composite all the way out to the bounds, so we create
2244 * the mask and composite ourselves. There actually would
2245 * be benefit to doing this in all cases, since RENDER implementations
2246 * will frequently create a too temporary big mask, ignoring destination
2247 * bounds and clip. (XRenderAddTraps() could be used to make creating
2248 * the mask somewhat cheaper.)
2250 Picture mask_picture
= _create_trapezoid_mask (dst
, traps
, num_traps
,
2251 dst_x
, dst_y
, width
, height
,
2253 if (!mask_picture
) {
2254 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2258 XRenderComposite (dst
->dpy
,
2259 _render_operator (op
),
2263 src_x
+ attributes
.x_offset
,
2264 src_y
+ attributes
.y_offset
,
2269 XRenderFreePicture (dst
->dpy
, mask_picture
);
2271 status
= _cairo_surface_composite_shape_fixup_unbounded (&dst
->base
,
2272 &attributes
, src
->width
, src
->height
,
2276 dst_x
, dst_y
, width
, height
);
2279 XTrapezoid xtraps_stack
[CAIRO_STACK_ARRAY_LENGTH (XTrapezoid
)];
2280 XTrapezoid
*xtraps
= xtraps_stack
;
2283 if (num_traps
> ARRAY_LENGTH (xtraps_stack
)) {
2284 xtraps
= _cairo_malloc_ab (num_traps
, sizeof (XTrapezoid
));
2285 if (unlikely (xtraps
== NULL
)) {
2286 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2291 for (i
= 0; i
< num_traps
; i
++) {
2292 xtraps
[i
].top
= _cairo_fixed_to_16_16(traps
[i
].top
);
2293 xtraps
[i
].bottom
= _cairo_fixed_to_16_16(traps
[i
].bottom
);
2294 xtraps
[i
].left
.p1
.x
= _cairo_fixed_to_16_16(traps
[i
].left
.p1
.x
);
2295 xtraps
[i
].left
.p1
.y
= _cairo_fixed_to_16_16(traps
[i
].left
.p1
.y
);
2296 xtraps
[i
].left
.p2
.x
= _cairo_fixed_to_16_16(traps
[i
].left
.p2
.x
);
2297 xtraps
[i
].left
.p2
.y
= _cairo_fixed_to_16_16(traps
[i
].left
.p2
.y
);
2298 xtraps
[i
].right
.p1
.x
= _cairo_fixed_to_16_16(traps
[i
].right
.p1
.x
);
2299 xtraps
[i
].right
.p1
.y
= _cairo_fixed_to_16_16(traps
[i
].right
.p1
.y
);
2300 xtraps
[i
].right
.p2
.x
= _cairo_fixed_to_16_16(traps
[i
].right
.p2
.x
);
2301 xtraps
[i
].right
.p2
.y
= _cairo_fixed_to_16_16(traps
[i
].right
.p2
.y
);
2304 XRenderCompositeTrapezoids (dst
->dpy
,
2305 _render_operator (op
),
2306 src
->src_picture
, dst
->dst_picture
,
2308 render_src_x
+ attributes
.x_offset
,
2309 render_src_y
+ attributes
.y_offset
,
2312 if (xtraps
!= xtraps_stack
)
2317 _cairo_pattern_release_surface (pattern
, &src
->base
, &attributes
);
2322 static cairo_region_t
*
2323 _surface_maybe_clip_region (cairo_xlib_surface_t
*surface
,
2324 cairo_region_t
*clip
,
2325 cairo_region_t
*bounded
)
2327 cairo_rectangle_int_t rect
;
2329 cairo_region_get_extents (clip
, &rect
);
2332 rect
.x
+ rect
.width
<= surface
->width
&&
2333 rect
.y
+ rect
.height
<= surface
->height
)
2338 rect
.x
= rect
.y
= 0;
2339 rect
.width
= surface
->width
;
2340 rect
.height
= surface
->height
;
2341 _cairo_region_init_rectangle (bounded
, &rect
);
2343 bounded
->status
= cairo_region_intersect (bounded
, clip
);
2348 static cairo_int_status_t
2349 _cairo_xlib_surface_set_clip_region (void *abstract_surface
,
2350 cairo_region_t
*region
)
2352 cairo_xlib_surface_t
*surface
= abstract_surface
;
2353 cairo_bool_t had_clip_rects
= surface
->have_clip_rects
;
2355 if (had_clip_rects
== FALSE
&& region
== NULL
)
2356 return CAIRO_STATUS_SUCCESS
;
2358 if (surface
->clip_rects
!= surface
->embedded_clip_rects
) {
2359 free (surface
->clip_rects
);
2360 surface
->clip_rects
= surface
->embedded_clip_rects
;
2363 surface
->have_clip_rects
= FALSE
;
2364 surface
->num_clip_rects
= 0;
2366 if (region
!= NULL
) {
2367 XRectangle
*rects
= NULL
;
2369 cairo_region_t bounded
;
2371 /* Intersect the region with the bounds of the surface. This
2372 * is necessary so we don't wrap around when we convert cairo's
2373 * 32 bit region into 16 bit rectangles.
2375 region
= _surface_maybe_clip_region (surface
, region
, &bounded
);
2376 if (unlikely (region
->status
))
2377 return region
->status
;
2379 n_rects
= cairo_region_num_rectangles (region
);
2380 if (n_rects
> ARRAY_LENGTH (surface
->embedded_clip_rects
)) {
2381 rects
= _cairo_malloc_ab (n_rects
, sizeof (XRectangle
));
2382 if (unlikely (rects
== NULL
)) {
2383 if (unlikely (region
== &bounded
))
2384 _cairo_region_fini (&bounded
);
2385 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2388 rects
= surface
->embedded_clip_rects
;
2391 for (i
= 0; i
< n_rects
; i
++) {
2392 cairo_rectangle_int_t rect
;
2394 cairo_region_get_rectangle (region
, i
, &rect
);
2396 rects
[i
].x
= rect
.x
;
2397 rects
[i
].y
= rect
.y
;
2398 rects
[i
].width
= rect
.width
;
2399 rects
[i
].height
= rect
.height
;
2402 if (unlikely (region
== &bounded
))
2403 _cairo_region_fini (&bounded
);
2405 surface
->have_clip_rects
= TRUE
;
2406 surface
->clip_rects
= rects
;
2407 surface
->num_clip_rects
= n_rects
;
2409 /* Discard the trivial clip rectangle that covers the entire surface */
2413 rects
[0].width
== surface
->width
&&
2414 rects
[0].height
== surface
->height
)
2416 surface
->have_clip_rects
= FALSE
;
2417 surface
->num_clip_rects
= 0;
2419 if (! had_clip_rects
)
2424 surface
->clip_dirty
= CAIRO_XLIB_SURFACE_CLIP_DIRTY_ALL
;
2427 return CAIRO_STATUS_SUCCESS
;
2430 static cairo_int_status_t
2431 _cairo_xlib_surface_get_extents (void *abstract_surface
,
2432 cairo_rectangle_int_t
*rectangle
)
2434 cairo_xlib_surface_t
*surface
= abstract_surface
;
2439 rectangle
->width
= surface
->width
;
2440 rectangle
->height
= surface
->height
;
2442 return CAIRO_STATUS_SUCCESS
;
2446 _cairo_xlib_surface_get_font_options (void *abstract_surface
,
2447 cairo_font_options_t
*options
)
2449 cairo_xlib_surface_t
*surface
= abstract_surface
;
2451 *options
= *_cairo_xlib_screen_get_font_options (surface
->screen_info
);
2455 _cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t
*scaled_font
);
2458 _cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t
*scaled_glyph
,
2459 cairo_scaled_font_t
*scaled_font
);
2462 _cairo_xlib_surface_is_similar (void *surface_a
,
2464 cairo_content_t content
)
2466 cairo_xlib_surface_t
*a
= surface_a
;
2467 cairo_xlib_surface_t
*b
= surface_b
;
2468 XRenderPictFormat
*xrender_format
= b
->xrender_format
;
2470 if (!_cairo_xlib_surface_same_screen (a
, b
))
2473 /* now inspect the content to check that a is similar to b */
2474 if (xrender_format
== NULL
&& b
->visual
!= NULL
)
2475 xrender_format
= XRenderFindVisualFormat (b
->dpy
, b
->visual
);
2477 if (xrender_format
== NULL
||
2478 _xrender_format_to_content (xrender_format
) != content
)
2480 xrender_format
= _cairo_xlib_display_get_xrender_format (
2482 _cairo_format_from_content (content
));
2486 return a
->xrender_format
== xrender_format
;
2489 static cairo_status_t
2490 _cairo_xlib_surface_reset (void *abstract_surface
)
2492 cairo_xlib_surface_t
*surface
= abstract_surface
;
2493 cairo_status_t status
;
2495 status
= _cairo_xlib_surface_set_clip_region (surface
, NULL
);
2496 if (unlikely (status
))
2499 return CAIRO_STATUS_SUCCESS
;
2503 _cairo_xlib_surface_set_drawable(void* abstract_surface
, unsigned long drawable
, unsigned long visualid
, cairo_bool_t double_buffered
, int width
, int height
)
2505 cairo_xlib_surface_t
* surface
= abstract_surface
;
2506 cairo_status_t status
;
2508 /* XXX: and what about this case? */
2509 if (surface
->owns_pixmap
)
2513 drawable
= surface
->drawable
;
2515 if (surface
->drawable
!= drawable
) {
2516 if (surface
->dst_picture
!= None
) {
2517 status
= _cairo_xlib_display_queue_resource (
2520 surface
->dst_picture
);
2521 if (unlikely (status
)) {
2522 status
= _cairo_surface_set_error (&surface
->base
, status
);
2526 surface
->dst_picture
= None
;
2529 if (surface
->src_picture
!= None
) {
2530 status
= _cairo_xlib_display_queue_resource (
2533 surface
->src_picture
);
2534 if (unlikely (status
)) {
2535 status
= _cairo_surface_set_error (&surface
->base
, status
);
2539 surface
->src_picture
= None
;
2542 surface
->drawable
= drawable
;
2544 surface
->width
= width
;
2545 surface
->height
= height
;
2548 static const cairo_surface_backend_t cairo_xlib_surface_backend
= {
2549 CAIRO_SURFACE_TYPE_XLIB
,
2550 _cairo_xlib_surface_create_similar
,
2551 _cairo_xlib_surface_finish
,
2552 _cairo_xlib_surface_acquire_source_image
,
2553 _cairo_xlib_surface_release_source_image
,
2554 _cairo_xlib_surface_acquire_dest_image
,
2555 _cairo_xlib_surface_release_dest_image
,
2556 _cairo_xlib_surface_clone_similar
,
2557 _cairo_xlib_surface_composite
,
2558 _cairo_xlib_surface_fill_rectangles
,
2559 _cairo_xlib_surface_composite_trapezoids
,
2560 NULL
, /* create_span_renderer */
2561 NULL
, /* check_span_renderer */
2562 NULL
, /* copy_page */
2563 NULL
, /* show_page */
2564 _cairo_xlib_surface_set_clip_region
,
2565 NULL
, /* intersect_clip_path */
2566 _cairo_xlib_surface_get_extents
,
2567 NULL
, /* old_show_glyphs */
2568 _cairo_xlib_surface_get_font_options
,
2570 NULL
, /* mark_dirty_rectangle */
2571 _cairo_xlib_surface_scaled_font_fini
,
2572 _cairo_xlib_surface_scaled_glyph_fini
,
2578 _cairo_xlib_surface_show_glyphs
,
2580 _cairo_xlib_surface_snapshot
,
2582 _cairo_xlib_surface_is_similar
,
2583 _cairo_xlib_surface_reset
,
2584 NULL
, /* fill_stroke */
2585 _cairo_xlib_surface_create_solid_pattern_surface
,
2586 _cairo_xlib_surface_can_repaint_solid_pattern_surface
,
2587 NULL
, /* has_show_text_glyphs */
2588 NULL
, /* show_text_glyphs */
2592 * _cairo_surface_is_xlib:
2593 * @surface: a #cairo_surface_t
2595 * Checks if a surface is a #cairo_xlib_surface_t
2597 * Return value: True if the surface is an xlib surface
2600 _cairo_surface_is_xlib (cairo_surface_t
*surface
)
2602 return surface
->backend
== &cairo_xlib_surface_backend
;
2605 /* callback from CloseDisplay */
2607 _cairo_xlib_surface_detach_display (cairo_xlib_display_t
*display
, void *data
)
2609 cairo_xlib_surface_t
*surface
= cairo_container_of (data
,
2610 cairo_xlib_surface_t
,
2611 close_display_hook
);
2615 surface
->dpy
= NULL
;
2617 if (surface
->dst_picture
!= None
) {
2618 XRenderFreePicture (dpy
, surface
->dst_picture
);
2619 surface
->dst_picture
= None
;
2622 if (surface
->src_picture
!= None
) {
2623 XRenderFreePicture (dpy
, surface
->src_picture
);
2624 surface
->src_picture
= None
;
2627 if (surface
->owns_pixmap
) {
2628 XFreePixmap (dpy
, surface
->drawable
);
2629 surface
->drawable
= None
;
2630 surface
->owns_pixmap
= FALSE
;
2633 if (surface
->gc
!= NULL
) {
2634 XFreeGC (dpy
, surface
->gc
);
2639 static cairo_surface_t
*
2640 _cairo_xlib_surface_init_internal (cairo_xlib_surface_t
* surface
,
2645 XRenderPictFormat
*xrender_format
,
2650 cairo_xlib_display_t
*display
;
2651 cairo_xlib_screen_info_t
*screen_info
;
2652 cairo_status_t status
;
2654 CAIRO_MUTEX_INITIALIZE ();
2656 if (xrender_format
) {
2657 depth
= xrender_format
->depth
;
2659 /* XXX find matching visual for core/dithering fallbacks? */
2660 } else if (visual
) {
2663 /* This is ugly, but we have to walk over all visuals
2664 * for the display to find the correct depth.
2667 for (j
= 0; j
< screen
->ndepths
; j
++) {
2668 Depth
*d
= &screen
->depths
[j
];
2669 for (k
= 0; k
< d
->nvisuals
; k
++) {
2670 if (&d
->visuals
[k
] == visual
) {
2681 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL
));
2683 status
= _cairo_xlib_display_get (dpy
, &display
);
2684 if (unlikely (status
))
2685 return _cairo_surface_create_in_error (status
);
2687 status
= _cairo_xlib_screen_info_get (display
, screen
, &screen_info
);
2688 if (unlikely (status
)) {
2689 _cairo_xlib_display_destroy (display
);
2690 return _cairo_surface_create_in_error (status
);
2694 _cairo_xlib_surface_finish(surface
);
2696 /* initialize and hook into the CloseDisplay callback */
2697 surface
->close_display_hook
.func
= _cairo_xlib_surface_detach_display
;
2698 _cairo_xlib_add_close_display_hook (display
, &surface
->close_display_hook
);
2700 surface
->render_major
= display
->render_major
;
2701 surface
->render_minor
= display
->render_minor
;
2702 if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface
)) {
2703 if (!xrender_format
) {
2705 xrender_format
= XRenderFindVisualFormat (dpy
, visual
);
2706 } else if (depth
== 1) {
2708 _cairo_xlib_display_get_xrender_format (display
,
2713 xrender_format
= NULL
;
2716 /* we cannot use XRender for this surface, so ensure we don't try */
2717 if (xrender_format
== NULL
) {
2718 surface
->render_major
= -1;
2719 surface
->render_minor
= -1;
2722 surface
->base
.content
= _xrender_format_to_content (xrender_format
);
2724 surface
->display
= display
;
2725 surface
->screen_info
= screen_info
;
2728 surface
->drawable
= drawable
;
2729 surface
->screen
= screen
;
2730 surface
->owns_pixmap
= FALSE
;
2731 surface
->use_pixmap
= 0;
2732 surface
->width
= width
;
2733 surface
->height
= height
;
2735 surface
->buggy_repeat
= screen_info
->display
->buggy_repeat
;
2736 if (!CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES (surface
)) {
2737 /* so we can use the XTile fallback */
2738 surface
->buggy_repeat
= TRUE
;
2740 surface
->buggy_pad_reflect
= screen_info
->display
->buggy_pad_reflect
;
2742 surface
->dst_picture
= None
;
2743 surface
->src_picture
= None
;
2745 surface
->visual
= visual
;
2746 surface
->xrender_format
= xrender_format
;
2747 surface
->depth
= depth
;
2748 surface
->filter
= CAIRO_FILTER_NEAREST
;
2749 surface
->repeat
= FALSE
;
2750 surface
->xtransform
= identity
;
2752 surface
->have_clip_rects
= FALSE
;
2753 surface
->gc_has_clip_rects
= FALSE
;
2754 surface
->clip_rects
= surface
->embedded_clip_rects
;
2755 surface
->num_clip_rects
= 0;
2756 surface
->clip_dirty
= 0;
2759 * Compute the pixel format masks from either a XrenderFormat or
2760 * else from a visual; failing that we assume the drawable is an
2761 * alpha-only pixmap as it could only have been created that way
2762 * through the cairo_xlib_surface_create_for_bitmap function.
2764 if (xrender_format
) {
2765 surface
->a_mask
= (unsigned long)
2766 surface
->xrender_format
->direct
.alphaMask
2767 << surface
->xrender_format
->direct
.alpha
;
2768 surface
->r_mask
= (unsigned long)
2769 surface
->xrender_format
->direct
.redMask
2770 << surface
->xrender_format
->direct
.red
;
2771 surface
->g_mask
= (unsigned long)
2772 surface
->xrender_format
->direct
.greenMask
2773 << surface
->xrender_format
->direct
.green
;
2774 surface
->b_mask
= (unsigned long)
2775 surface
->xrender_format
->direct
.blueMask
2776 << surface
->xrender_format
->direct
.blue
;
2777 } else if (visual
) {
2778 surface
->a_mask
= 0;
2779 surface
->r_mask
= visual
->red_mask
;
2780 surface
->g_mask
= visual
->green_mask
;
2781 surface
->b_mask
= visual
->blue_mask
;
2784 surface
->a_mask
= (1 << depth
) - 1;
2786 surface
->a_mask
= 0xffffffff;
2787 surface
->r_mask
= 0;
2788 surface
->g_mask
= 0;
2789 surface
->b_mask
= 0;
2792 return (cairo_surface_t
*) surface
;
2795 static cairo_surface_t
*
2796 _cairo_xlib_surface_create_internal (Display
*dpy
,
2800 XRenderPictFormat
*xrender_format
,
2805 cairo_xlib_surface_t
* surface
= malloc (sizeof (cairo_xlib_surface_t
));
2806 cairo_surface_t
* ret
;
2807 if (unlikely (surface
== NULL
))
2808 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
2810 _cairo_surface_init (&surface
->base
, &cairo_xlib_surface_backend
, 0);
2813 ret
= _cairo_xlib_surface_init_internal(surface
, dpy
, drawable
, screen
, visual
, xrender_format
, width
, height
, depth
);
2814 if(ret
!= &surface
->base
)
2821 _cairo_xlib_screen_from_visual (Display
*dpy
, Visual
*visual
)
2829 for (s
= 0; s
< ScreenCount (dpy
); s
++) {
2830 screen
= ScreenOfDisplay (dpy
, s
);
2831 if (visual
== DefaultVisualOfScreen (screen
))
2833 for (d
= 0; d
< screen
->ndepths
; d
++) {
2834 depth
= &screen
->depths
[d
];
2835 for (v
= 0; v
< depth
->nvisuals
; v
++)
2836 if (visual
== &depth
->visuals
[v
])
2844 * cairo_xlib_surface_create:
2845 * @dpy: an X Display
2846 * @drawable: an X Drawable, (a Pixmap or a Window)
2847 * @visual: the visual to use for drawing to @drawable. The depth
2848 * of the visual must match the depth of the drawable.
2849 * Currently, only TrueColor visuals are fully supported.
2850 * @width: the current width of @drawable.
2851 * @height: the current height of @drawable.
2853 * Creates an Xlib surface that draws to the given drawable.
2854 * The way that colors are represented in the drawable is specified
2855 * by the provided visual.
2857 * Note: If @drawable is a Window, then the function
2858 * cairo_xlib_surface_set_size() must be called whenever the size of the
2861 * When @drawable is a Window containing child windows then drawing to
2862 * the created surface will be clipped by those child windows. When
2863 * the created surface is used as a source, the contents of the
2864 * children will be included.
2866 * Return value: the newly created surface
2869 cairo_xlib_surface_create (Display
*dpy
,
2877 screen
= _cairo_xlib_screen_from_visual (dpy
, visual
);
2880 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL
));
2882 return _cairo_xlib_surface_create_internal (dpy
, drawable
, screen
,
2883 visual
, NULL
, width
, height
, 0);
2885 slim_hidden_def (cairo_xlib_surface_create
);
2888 * cairo_xlib_surface_create_for_bitmap:
2889 * @dpy: an X Display
2890 * @bitmap: an X Drawable, (a depth-1 Pixmap)
2891 * @screen: the X Screen associated with @bitmap
2892 * @width: the current width of @bitmap.
2893 * @height: the current height of @bitmap.
2895 * Creates an Xlib surface that draws to the given bitmap.
2896 * This will be drawn to as a %CAIRO_FORMAT_A1 object.
2898 * Return value: the newly created surface
2901 cairo_xlib_surface_create_for_bitmap (Display
*dpy
,
2907 return _cairo_xlib_surface_create_internal (dpy
, bitmap
, screen
,
2908 NULL
, NULL
, width
, height
, 1);
2911 #if CAIRO_HAS_XLIB_XRENDER_SURFACE
2913 * cairo_xlib_surface_create_with_xrender_format:
2914 * @dpy: an X Display
2915 * @drawable: an X Drawable, (a Pixmap or a Window)
2916 * @screen: the X Screen associated with @drawable
2917 * @format: the picture format to use for drawing to @drawable. The depth
2918 * of @format must match the depth of the drawable.
2919 * @width: the current width of @drawable.
2920 * @height: the current height of @drawable.
2922 * Creates an Xlib surface that draws to the given drawable.
2923 * The way that colors are represented in the drawable is specified
2924 * by the provided picture format.
2926 * Note: If @drawable is a Window, then the function
2927 * cairo_xlib_surface_set_size() must be called whenever the size of the
2930 * Return value: the newly created surface
2933 cairo_xlib_surface_create_with_xrender_format (Display
*dpy
,
2936 XRenderPictFormat
*format
,
2940 return _cairo_xlib_surface_create_internal (dpy
, drawable
, screen
,
2941 NULL
, format
, width
, height
, 0);
2943 slim_hidden_def (cairo_xlib_surface_create_with_xrender_format
);
2946 * cairo_xlib_surface_get_xrender_format:
2947 * @surface: an xlib surface
2949 * Gets the X Render picture format that @surface uses for rendering with the
2950 * X Render extension. If the surface was created by
2951 * cairo_xlib_surface_create_with_xrender_format() originally, the return
2952 * value is the format passed to that constructor.
2954 * Return value: the XRenderPictFormat* associated with @surface,
2955 * or %NULL if the surface is not an xlib surface
2956 * or if the X Render extension is not available.
2961 cairo_xlib_surface_get_xrender_format (cairo_surface_t
*surface
)
2963 cairo_xlib_surface_t
*xlib_surface
= (cairo_xlib_surface_t
*) surface
;
2965 /* Throw an error for a non-xlib surface */
2966 if (! _cairo_surface_is_xlib (surface
)) {
2967 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH
);
2971 return xlib_surface
->xrender_format
;
2976 * cairo_xlib_surface_set_size:
2977 * @surface: a #cairo_surface_t for the XLib backend
2978 * @width: the new width of the surface
2979 * @height: the new height of the surface
2981 * Informs cairo of the new size of the X Drawable underlying the
2982 * surface. For a surface created for a Window (rather than a Pixmap),
2983 * this function must be called each time the size of the window
2984 * changes. (For a subwindow, you are normally resizing the window
2985 * yourself, but for a toplevel window, it is necessary to listen for
2986 * ConfigureNotify events.)
2988 * A Pixmap can never change size, so it is never necessary to call
2989 * this function on a surface created for a Pixmap.
2992 cairo_xlib_surface_set_size (cairo_surface_t
*abstract_surface
,
2996 cairo_xlib_surface_t
*surface
= (cairo_xlib_surface_t
*) abstract_surface
;
2998 if (! _cairo_surface_is_xlib (abstract_surface
)) {
2999 (void)cairo_surface_create_for_drawable(0, abstract_surface
, 0, ~0L, 0, 0, width
, height
);
3003 surface
->width
= width
;
3004 surface
->height
= height
;
3008 * cairo_xlib_surface_set_drawable:
3009 * @surface: a #cairo_surface_t for the XLib backend
3010 * @drawable: the new drawable for the surface
3011 * @width: the width of the new drawable
3012 * @height: the height of the new drawable
3014 * Informs cairo of a new X Drawable underlying the
3015 * surface. The drawable must match the display, screen
3016 * and format of the existing drawable or the application
3017 * will get X protocol errors and will probably terminate.
3018 * No checks are done by this function to ensure this
3022 cairo_xlib_surface_set_drawable (cairo_surface_t
*abstract_surface
,
3027 if (! _cairo_surface_is_xlib (abstract_surface
))
3028 cairo_surface_create_for_drawable(0, abstract_surface
, 0, drawable
, 0, 0, width
, height
);
3030 _cairo_xlib_surface_set_drawable(abstract_surface
, drawable
, 0, 0, width
, height
);
3034 * cairo_xlib_surface_get_display:
3035 * @surface: a #cairo_xlib_surface_t
3037 * Get the X Display for the underlying X Drawable.
3039 * Return value: the display.
3044 cairo_xlib_surface_get_display (cairo_surface_t
*abstract_surface
)
3046 cairo_xlib_surface_t
*surface
= (cairo_xlib_surface_t
*) abstract_surface
;
3048 if (! _cairo_surface_is_xlib (abstract_surface
)) {
3049 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH
);
3053 return surface
->dpy
;
3057 * cairo_xlib_surface_get_drawable:
3058 * @surface: a #cairo_xlib_surface_t
3060 * Get the underlying X Drawable used for the surface.
3062 * Return value: the drawable.
3067 cairo_xlib_surface_get_drawable (cairo_surface_t
*abstract_surface
)
3069 cairo_xlib_surface_t
*surface
= (cairo_xlib_surface_t
*) abstract_surface
;
3071 if (! _cairo_surface_is_xlib (abstract_surface
)) {
3072 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH
);
3076 return surface
->drawable
;
3080 * cairo_xlib_surface_get_screen:
3081 * @surface: a #cairo_xlib_surface_t
3083 * Get the X Screen for the underlying X Drawable.
3085 * Return value: the screen.
3090 cairo_xlib_surface_get_screen (cairo_surface_t
*abstract_surface
)
3092 cairo_xlib_surface_t
*surface
= (cairo_xlib_surface_t
*) abstract_surface
;
3094 if (! _cairo_surface_is_xlib (abstract_surface
)) {
3095 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH
);
3099 return surface
->screen
;
3103 * cairo_xlib_surface_get_visual:
3104 * @surface: a #cairo_xlib_surface_t
3106 * Get the X Visual used for underlying X Drawable.
3108 * Return value: the visual.
3113 cairo_xlib_surface_get_visual (cairo_surface_t
*abstract_surface
)
3115 cairo_xlib_surface_t
*surface
= (cairo_xlib_surface_t
*) abstract_surface
;
3117 if (! _cairo_surface_is_xlib (abstract_surface
)) {
3118 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH
);
3122 return surface
->visual
;
3126 * cairo_xlib_surface_get_depth:
3127 * @surface: a #cairo_xlib_surface_t
3129 * Get the number of bits used to represent each pixel value.
3131 * Return value: the depth of the surface in bits.
3136 cairo_xlib_surface_get_depth (cairo_surface_t
*abstract_surface
)
3138 cairo_xlib_surface_t
*surface
= (cairo_xlib_surface_t
*) abstract_surface
;
3140 if (! _cairo_surface_is_xlib (abstract_surface
)) {
3141 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH
);
3145 return surface
->depth
;
3149 * cairo_xlib_surface_get_width:
3150 * @surface: a #cairo_xlib_surface_t
3152 * Get the width of the X Drawable underlying the surface in pixels.
3154 * Return value: the width of the surface in pixels.
3159 cairo_xlib_surface_get_width (cairo_surface_t
*abstract_surface
)
3161 cairo_xlib_surface_t
*surface
= (cairo_xlib_surface_t
*) abstract_surface
;
3163 if (! _cairo_surface_is_xlib (abstract_surface
)) {
3164 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH
);
3168 return surface
->width
;
3172 * cairo_xlib_surface_get_height:
3173 * @surface: a #cairo_xlib_surface_t
3175 * Get the height of the X Drawable underlying the surface in pixels.
3177 * Return value: the height of the surface in pixels.
3182 cairo_xlib_surface_get_height (cairo_surface_t
*abstract_surface
)
3184 cairo_xlib_surface_t
*surface
= (cairo_xlib_surface_t
*) abstract_surface
;
3186 if (! _cairo_surface_is_xlib (abstract_surface
)) {
3187 _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH
);
3191 return surface
->height
;
3195 GLYPHSET_INDEX_ARGB32
,
3201 typedef struct _cairo_xlib_font_glyphset_free_glyphs
{
3204 unsigned long glyph_indices
[128];
3205 } cairo_xlib_font_glyphset_free_glyphs_t
;
3207 typedef struct _cairo_xlib_font_glyphset_info
{
3209 cairo_format_t format
;
3210 XRenderPictFormat
*xrender_format
;
3211 cairo_xlib_font_glyphset_free_glyphs_t
*pending_free_glyphs
;
3212 } cairo_xlib_font_glyphset_info_t
;
3214 typedef struct _cairo_xlib_surface_font_private
{
3215 cairo_scaled_font_t
*scaled_font
;
3216 cairo_xlib_hook_t close_display_hook
;
3217 cairo_xlib_display_t
*display
;
3218 cairo_xlib_font_glyphset_info_t glyphset_info
[NUM_GLYPHSETS
];
3219 } cairo_xlib_surface_font_private_t
;
3221 /* callback from CloseDisplay */
3223 _cairo_xlib_surface_remove_scaled_font (cairo_xlib_display_t
*display
,
3226 cairo_xlib_surface_font_private_t
*font_private
;
3227 cairo_scaled_font_t
*scaled_font
;
3229 font_private
= cairo_container_of (data
,
3230 cairo_xlib_surface_font_private_t
,
3231 close_display_hook
);
3232 scaled_font
= font_private
->scaled_font
;
3234 CAIRO_MUTEX_LOCK (scaled_font
->mutex
);
3235 font_private
= scaled_font
->surface_private
;
3236 scaled_font
->surface_private
= NULL
;
3238 _cairo_scaled_font_reset_cache (scaled_font
);
3239 CAIRO_MUTEX_UNLOCK (scaled_font
->mutex
);
3241 if (font_private
!= NULL
) {
3245 dpy
= display
->display
;
3246 for (i
= 0; i
< NUM_GLYPHSETS
; i
++) {
3247 cairo_xlib_font_glyphset_info_t
*glyphset_info
;
3249 glyphset_info
= &font_private
->glyphset_info
[i
];
3250 if (glyphset_info
->glyphset
)
3251 XRenderFreeGlyphSet (dpy
, glyphset_info
->glyphset
);
3253 if (glyphset_info
->pending_free_glyphs
!= NULL
)
3254 free (glyphset_info
->pending_free_glyphs
);
3257 _cairo_xlib_display_destroy (font_private
->display
);
3258 free (font_private
);
3262 static cairo_status_t
3263 _cairo_xlib_surface_font_init (Display
*dpy
,
3264 cairo_scaled_font_t
*scaled_font
)
3266 cairo_xlib_surface_font_private_t
*font_private
;
3267 cairo_status_t status
;
3270 font_private
= malloc (sizeof (cairo_xlib_surface_font_private_t
));
3271 if (unlikely (font_private
== NULL
))
3272 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
3274 font_private
->scaled_font
= scaled_font
;
3275 status
= _cairo_xlib_display_get (dpy
, &font_private
->display
);
3276 if (unlikely (status
)) {
3277 free (font_private
);
3281 /* initialize and hook into the CloseDisplay callback */
3282 font_private
->close_display_hook
.func
=
3283 _cairo_xlib_surface_remove_scaled_font
;
3284 _cairo_xlib_add_close_display_hook (font_private
->display
,
3285 &font_private
->close_display_hook
);
3288 for (i
= 0; i
< NUM_GLYPHSETS
; i
++) {
3289 cairo_xlib_font_glyphset_info_t
*glyphset_info
= &font_private
->glyphset_info
[i
];
3291 case GLYPHSET_INDEX_ARGB32
: glyphset_info
->format
= CAIRO_FORMAT_ARGB32
; break;
3292 case GLYPHSET_INDEX_A8
: glyphset_info
->format
= CAIRO_FORMAT_A8
; break;
3293 case GLYPHSET_INDEX_A1
: glyphset_info
->format
= CAIRO_FORMAT_A1
; break;
3294 default: ASSERT_NOT_REACHED
; break;
3296 glyphset_info
->xrender_format
= NULL
;
3297 glyphset_info
->glyphset
= None
;
3298 glyphset_info
->pending_free_glyphs
= NULL
;
3301 scaled_font
->surface_private
= font_private
;
3302 scaled_font
->surface_backend
= &cairo_xlib_surface_backend
;
3304 return CAIRO_STATUS_SUCCESS
;
3308 _cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t
*scaled_font
)
3310 cairo_xlib_surface_font_private_t
*font_private
;
3312 font_private
= scaled_font
->surface_private
;
3313 if (font_private
!= NULL
) {
3314 cairo_xlib_display_t
*display
;
3317 display
= font_private
->display
;
3318 _cairo_xlib_remove_close_display_hook (display
,
3319 &font_private
->close_display_hook
);
3321 for (i
= 0; i
< NUM_GLYPHSETS
; i
++) {
3322 cairo_xlib_font_glyphset_info_t
*glyphset_info
;
3324 glyphset_info
= &font_private
->glyphset_info
[i
];
3326 if (glyphset_info
->pending_free_glyphs
!= NULL
)
3327 free (glyphset_info
->pending_free_glyphs
);
3329 if (glyphset_info
->glyphset
) {
3330 cairo_status_t status
;
3332 status
= _cairo_xlib_display_queue_resource (display
,
3333 XRenderFreeGlyphSet
,
3334 glyphset_info
->glyphset
);
3335 (void) status
; /* XXX cannot propagate failure */
3339 _cairo_xlib_display_destroy (display
);
3340 free (font_private
);
3345 _cairo_xlib_render_free_glyphs (Display
*dpy
,
3346 cairo_xlib_font_glyphset_free_glyphs_t
*to_free
)
3348 XRenderFreeGlyphs (dpy
,
3350 to_free
->glyph_indices
,
3351 to_free
->glyph_count
);
3354 static cairo_xlib_font_glyphset_info_t
*
3355 _cairo_xlib_scaled_glyph_get_glyphset_info (cairo_scaled_glyph_t
*scaled_glyph
)
3357 return scaled_glyph
->surface_private
;
3361 _cairo_xlib_scaled_glyph_set_glyphset_info (cairo_scaled_glyph_t
*scaled_glyph
,
3362 cairo_xlib_font_glyphset_info_t
*glyphset_info
)
3364 scaled_glyph
->surface_private
= glyphset_info
;
3368 _cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t
*scaled_glyph
,
3369 cairo_scaled_font_t
*scaled_font
)
3371 cairo_xlib_surface_font_private_t
*font_private
;
3372 cairo_xlib_font_glyphset_info_t
*glyphset_info
;
3374 if (scaled_font
->finished
)
3377 font_private
= scaled_font
->surface_private
;
3378 glyphset_info
= _cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph
);
3379 if (font_private
!= NULL
&& glyphset_info
!= NULL
) {
3380 cairo_xlib_font_glyphset_free_glyphs_t
*to_free
;
3381 cairo_status_t status
;
3383 to_free
= glyphset_info
->pending_free_glyphs
;
3384 if (to_free
!= NULL
&&
3385 to_free
->glyph_count
== ARRAY_LENGTH (to_free
->glyph_indices
))
3387 status
= _cairo_xlib_display_queue_work (font_private
->display
,
3388 (cairo_xlib_notify_func
) _cairo_xlib_render_free_glyphs
,
3391 /* XXX cannot propagate failure */
3392 if (unlikely (status
))
3395 to_free
= glyphset_info
->pending_free_glyphs
= NULL
;
3398 if (to_free
== NULL
) {
3399 to_free
= malloc (sizeof (cairo_xlib_font_glyphset_free_glyphs_t
));
3400 if (unlikely (to_free
== NULL
)) {
3401 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
3402 return; /* XXX cannot propagate failure */
3405 to_free
->glyphset
= glyphset_info
->glyphset
;
3406 to_free
->glyph_count
= 0;
3407 glyphset_info
->pending_free_glyphs
= to_free
;
3410 to_free
->glyph_indices
[to_free
->glyph_count
++] =
3411 _cairo_scaled_glyph_index (scaled_glyph
);
3416 _native_byte_order_lsb (void)
3420 return *((char *) &x
) == 1;
3423 static cairo_xlib_font_glyphset_info_t
*
3424 _cairo_xlib_scaled_font_get_glyphset_info_for_format (cairo_scaled_font_t
*scaled_font
,
3425 cairo_format_t format
)
3427 cairo_xlib_surface_font_private_t
*font_private
;
3428 cairo_xlib_font_glyphset_info_t
*glyphset_info
;
3433 case CAIRO_FORMAT_RGB24
:
3434 case CAIRO_FORMAT_ARGB32
: glyphset_index
= GLYPHSET_INDEX_ARGB32
; break;
3435 case CAIRO_FORMAT_A8
: glyphset_index
= GLYPHSET_INDEX_A8
; break;
3436 case CAIRO_FORMAT_A1
: glyphset_index
= GLYPHSET_INDEX_A1
; break;
3439 font_private
= scaled_font
->surface_private
;
3440 glyphset_info
= &font_private
->glyphset_info
[glyphset_index
];
3441 if (glyphset_info
->glyphset
== None
) {
3442 cairo_xlib_display_t
*display
= font_private
->display
;
3444 glyphset_info
->xrender_format
=
3445 _cairo_xlib_display_get_xrender_format (display
,
3446 glyphset_info
->format
);
3447 glyphset_info
->glyphset
= XRenderCreateGlyphSet (display
->display
,
3448 glyphset_info
->xrender_format
);
3451 return glyphset_info
;
3455 _cairo_xlib_glyphset_info_has_pending_free_glyph (
3456 cairo_xlib_font_glyphset_info_t
*glyphset_info
,
3457 unsigned long glyph_index
)
3459 if (glyphset_info
->pending_free_glyphs
!= NULL
) {
3460 cairo_xlib_font_glyphset_free_glyphs_t
*to_free
;
3463 to_free
= glyphset_info
->pending_free_glyphs
;
3464 for (i
= 0; i
< to_free
->glyph_count
; i
++) {
3465 if (to_free
->glyph_indices
[i
] == glyph_index
) {
3466 to_free
->glyph_count
--;
3467 memmove (&to_free
->glyph_indices
[i
],
3468 &to_free
->glyph_indices
[i
+1],
3469 (to_free
->glyph_count
- i
) * sizeof (to_free
->glyph_indices
[0]));
3478 static cairo_xlib_font_glyphset_info_t
*
3479 _cairo_xlib_scaled_font_get_glyphset_info_for_pending_free_glyph (
3480 cairo_scaled_font_t
*scaled_font
,
3481 unsigned long glyph_index
,
3482 cairo_image_surface_t
*surface
)
3484 cairo_xlib_surface_font_private_t
*font_private
;
3487 font_private
= scaled_font
->surface_private
;
3488 if (font_private
== NULL
)
3491 if (surface
!= NULL
) {
3492 switch (surface
->format
) {
3494 case CAIRO_FORMAT_RGB24
:
3495 case CAIRO_FORMAT_ARGB32
: i
= GLYPHSET_INDEX_ARGB32
; break;
3496 case CAIRO_FORMAT_A8
: i
= GLYPHSET_INDEX_A8
; break;
3497 case CAIRO_FORMAT_A1
: i
= GLYPHSET_INDEX_A1
; break;
3499 if (_cairo_xlib_glyphset_info_has_pending_free_glyph (
3500 &font_private
->glyphset_info
[i
],
3503 return &font_private
->glyphset_info
[i
];
3506 for (i
= 0; i
< NUM_GLYPHSETS
; i
++) {
3507 if (_cairo_xlib_glyphset_info_has_pending_free_glyph (
3508 &font_private
->glyphset_info
[i
],
3511 return &font_private
->glyphset_info
[i
];
3519 static cairo_status_t
3520 _cairo_xlib_surface_add_glyph (Display
*dpy
,
3521 cairo_scaled_font_t
*scaled_font
,
3522 cairo_scaled_glyph_t
**pscaled_glyph
)
3524 XGlyphInfo glyph_info
;
3525 unsigned long glyph_index
;
3526 unsigned char *data
;
3527 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
3528 cairo_scaled_glyph_t
*scaled_glyph
= *pscaled_glyph
;
3529 cairo_image_surface_t
*glyph_surface
= scaled_glyph
->surface
;
3530 cairo_bool_t already_had_glyph_surface
;
3531 cairo_xlib_font_glyphset_info_t
*glyphset_info
;
3533 glyph_index
= _cairo_scaled_glyph_index (scaled_glyph
);
3535 /* check to see if we have a pending XRenderFreeGlyph for this glyph */
3536 glyphset_info
= _cairo_xlib_scaled_font_get_glyphset_info_for_pending_free_glyph (scaled_font
, glyph_index
, glyph_surface
);
3537 if (glyphset_info
!= NULL
) {
3538 _cairo_xlib_scaled_glyph_set_glyphset_info (scaled_glyph
, glyphset_info
);
3539 return CAIRO_STATUS_SUCCESS
;
3542 if (!glyph_surface
) {
3543 status
= _cairo_scaled_glyph_lookup (scaled_font
,
3545 CAIRO_SCALED_GLYPH_INFO_METRICS
|
3546 CAIRO_SCALED_GLYPH_INFO_SURFACE
,
3548 if (unlikely (status
))
3551 scaled_glyph
= *pscaled_glyph
;
3552 glyph_surface
= scaled_glyph
->surface
;
3553 already_had_glyph_surface
= FALSE
;
3555 already_had_glyph_surface
= TRUE
;
3558 if (scaled_font
->surface_private
== NULL
) {
3559 status
= _cairo_xlib_surface_font_init (dpy
, scaled_font
);
3560 if (unlikely (status
))
3564 glyphset_info
= _cairo_xlib_scaled_font_get_glyphset_info_for_format (scaled_font
,
3565 glyph_surface
->format
);
3567 /* XRenderAddGlyph does not handle a glyph surface larger than the extended maximum XRequest size. */
3569 int len
= cairo_format_stride_for_width (glyphset_info
->format
, glyph_surface
->width
) * glyph_surface
->height
;
3570 int max_request_size
= (XExtendedMaxRequestSize (dpy
) ? XExtendedMaxRequestSize (dpy
) : XMaxRequestSize (dpy
)) * 4 -
3571 sz_xRenderAddGlyphsReq
-
3574 if (len
>= max_request_size
)
3575 return CAIRO_INT_STATUS_UNSUPPORTED
;
3578 /* If the glyph surface has zero height or width, we create
3579 * a clear 1x1 surface, to avoid various X server bugs.
3581 if (glyph_surface
->width
== 0 || glyph_surface
->height
== 0) {
3583 cairo_surface_t
*tmp_surface
;
3585 tmp_surface
= cairo_image_surface_create (glyphset_info
->format
, 1, 1);
3586 status
= tmp_surface
->status
;
3587 if (unlikely (status
))
3590 cr
= cairo_create (tmp_surface
);
3591 cairo_set_operator (cr
, CAIRO_OPERATOR_CLEAR
);
3593 status
= cairo_status (cr
);
3596 tmp_surface
->device_transform
= glyph_surface
->base
.device_transform
;
3597 tmp_surface
->device_transform_inverse
= glyph_surface
->base
.device_transform_inverse
;
3599 glyph_surface
= (cairo_image_surface_t
*) tmp_surface
;
3601 if (unlikely (status
))
3605 /* If the glyph format does not match the font format, then we
3606 * create a temporary surface for the glyph image with the font's
3609 if (glyph_surface
->format
!= glyphset_info
->format
) {
3611 cairo_surface_t
*tmp_surface
;
3613 tmp_surface
= cairo_image_surface_create (glyphset_info
->format
,
3614 glyph_surface
->width
,
3615 glyph_surface
->height
);
3616 status
= tmp_surface
->status
;
3617 if (unlikely (status
))
3620 tmp_surface
->device_transform
= glyph_surface
->base
.device_transform
;
3621 tmp_surface
->device_transform_inverse
= glyph_surface
->base
.device_transform_inverse
;
3623 cr
= cairo_create (tmp_surface
);
3624 cairo_set_source_surface (cr
, &glyph_surface
->base
, 0, 0);
3625 cairo_set_operator (cr
, CAIRO_OPERATOR_SOURCE
);
3627 status
= cairo_status (cr
);
3630 glyph_surface
= (cairo_image_surface_t
*) tmp_surface
;
3632 if (unlikely (status
))
3636 /* XXX: FRAGILE: We're ignore device_transform scaling here. A bug? */
3637 glyph_info
.x
= _cairo_lround (glyph_surface
->base
.device_transform
.x0
);
3638 glyph_info
.y
= _cairo_lround (glyph_surface
->base
.device_transform
.y0
);
3639 glyph_info
.width
= glyph_surface
->width
;
3640 glyph_info
.height
= glyph_surface
->height
;
3641 glyph_info
.xOff
= scaled_glyph
->x_advance
;
3642 glyph_info
.yOff
= scaled_glyph
->y_advance
;
3644 data
= glyph_surface
->data
;
3646 /* flip formats around */
3647 switch (scaled_glyph
->surface
->format
) {
3648 case CAIRO_FORMAT_A1
:
3649 /* local bitmaps are always stored with bit == byte */
3650 if (_native_byte_order_lsb() != (BitmapBitOrder (dpy
) == LSBFirst
)) {
3651 int c
= glyph_surface
->stride
* glyph_surface
->height
;
3653 unsigned char *new, *n
;
3657 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
3664 b
= ((b
<< 1) & 0xaa) | ((b
>> 1) & 0x55);
3665 b
= ((b
<< 2) & 0xcc) | ((b
>> 2) & 0x33);
3666 b
= ((b
<< 4) & 0xf0) | ((b
>> 4) & 0x0f);
3672 case CAIRO_FORMAT_A8
:
3674 case CAIRO_FORMAT_ARGB32
:
3675 if (_native_byte_order_lsb() != (ImageByteOrder (dpy
) == LSBFirst
)) {
3676 unsigned int c
= glyph_surface
->stride
* glyph_surface
->height
/ 4;
3680 new = malloc (4 * c
);
3681 if (unlikely (new == NULL
)) {
3682 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
3686 d
= (uint32_t *) data
;
3688 *n
++ = bswap_32 (*d
++);
3690 data
= (uint8_t *) new;
3693 case CAIRO_FORMAT_RGB24
:
3698 /* XXX assume X server wants pixman padding. Xft assumes this as well */
3700 XRenderAddGlyphs (dpy
, glyphset_info
->glyphset
,
3701 &glyph_index
, &glyph_info
, 1,
3703 glyph_surface
->stride
* glyph_surface
->height
);
3705 if (data
!= glyph_surface
->data
)
3708 _cairo_xlib_scaled_glyph_set_glyphset_info (scaled_glyph
, glyphset_info
);
3711 if (glyph_surface
!= scaled_glyph
->surface
)
3712 cairo_surface_destroy (&glyph_surface
->base
);
3714 /* if the scaled glyph didn't already have a surface attached
3715 * to it, release the created surface now that we have it
3716 * uploaded to the X server. If the surface has already been
3717 * there (eg. because image backend requested it), leave it in
3720 if (!already_had_glyph_surface
)
3721 _cairo_scaled_glyph_set_surface (scaled_glyph
, scaled_font
, NULL
);
3726 typedef void (*cairo_xrender_composite_text_func_t
)
3731 _Xconst XRenderPictFormat
*maskFormat
,
3736 _Xconst XGlyphElt8
*elts
,
3739 /* Build a struct of the same size of #cairo_glyph_t that can be used both as
3740 * an input glyph with double coordinates, and as "working" glyph with
3741 * integer from-current-point offsets. */
3744 unsigned long index
;
3746 unsigned long index
;
3750 } cairo_xlib_glyph_t
;
3752 /* compile-time assert that #cairo_xlib_glyph_t is the same size as #cairo_glyph_t */
3753 COMPILE_TIME_ASSERT (sizeof (cairo_xlib_glyph_t
) == sizeof (cairo_glyph_t
));
3755 /* Start a new element for the first glyph,
3756 * or for any glyph that has unexpected position,
3757 * or if current element has too many glyphs
3758 * (Xrender limits each element to 252 glyphs, we limit them to 128)
3760 * These same conditions need to be mirrored between
3761 * _cairo_xlib_surface_emit_glyphs and _emit_glyph_chunks
3763 #define _start_new_glyph_elt(count, glyph) \
3764 (((count) & 127) == 0 || (glyph)->i.x || (glyph)->i.y)
3766 static cairo_status_t
3767 _emit_glyphs_chunk (cairo_xlib_surface_t
*dst
,
3768 cairo_xlib_glyph_t
*glyphs
,
3770 cairo_scaled_font_t
*scaled_font
,
3771 cairo_operator_t op
,
3772 cairo_xlib_surface_t
*src
,
3773 cairo_surface_attributes_t
*attributes
,
3774 /* info for this chunk */
3777 cairo_xlib_font_glyphset_info_t
*glyphset_info
)
3779 /* Which XRenderCompositeText function to use */
3780 cairo_xrender_composite_text_func_t composite_text_func
;
3783 /* Element buffer stuff */
3785 XGlyphElt8 stack_elts
[CAIRO_STACK_ARRAY_LENGTH (XGlyphElt8
)];
3787 /* Reuse the input glyph array for output char generation */
3788 char *char8
= (char *) glyphs
;
3789 unsigned short *char16
= (unsigned short *) glyphs
;
3790 unsigned int *char32
= (unsigned int *) glyphs
;
3793 int nelt
; /* Element index */
3794 int n
; /* Num output glyphs in current element */
3795 int j
; /* Num output glyphs so far */
3799 /* don't cast the 8-variant, to catch possible mismatches */
3800 composite_text_func
= XRenderCompositeText8
;
3801 size
= sizeof (char);
3804 composite_text_func
= (cairo_xrender_composite_text_func_t
) XRenderCompositeText16
;
3805 size
= sizeof (unsigned short);
3809 composite_text_func
= (cairo_xrender_composite_text_func_t
) XRenderCompositeText32
;
3810 size
= sizeof (unsigned int);
3813 /* Allocate element array */
3814 if (num_elts
<= ARRAY_LENGTH (stack_elts
)) {
3817 elts
= _cairo_malloc_ab (num_elts
, sizeof (XGlyphElt8
));
3818 if (unlikely (elts
== NULL
))
3819 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
3826 for (i
= 0; i
< num_glyphs
; i
++) {
3828 /* Start a new element for first output glyph,
3829 * or for any glyph that has unexpected position,
3830 * or if current element has too many glyphs.
3832 * These same conditions are mirrored in _cairo_xlib_surface_emit_glyphs()
3834 if (_start_new_glyph_elt (j
, &glyphs
[i
])) {
3836 elts
[nelt
].nchars
= n
;
3840 elts
[nelt
].chars
= char8
+ size
* j
;
3841 elts
[nelt
].glyphset
= glyphset_info
->glyphset
;
3842 elts
[nelt
].xOff
= glyphs
[i
].i
.x
;
3843 elts
[nelt
].yOff
= glyphs
[i
].i
.y
;
3847 case 1: char8
[j
] = (char) glyphs
[i
].index
; break;
3848 case 2: char16
[j
] = (unsigned short) glyphs
[i
].index
; break;
3850 case 4: char32
[j
] = (unsigned int) glyphs
[i
].index
; break;
3858 elts
[nelt
].nchars
= n
;
3863 /* Check that we agree with _cairo_xlib_surface_emit_glyphs() on the
3864 * expected number of xGlyphElts. */
3865 assert (nelt
== num_elts
);
3867 composite_text_func (dst
->dpy
,
3868 _render_operator (op
),
3871 glyphset_info
->xrender_format
,
3872 attributes
->x_offset
+ elts
[0].xOff
,
3873 attributes
->y_offset
+ elts
[0].yOff
,
3874 elts
[0].xOff
, elts
[0].yOff
,
3875 (XGlyphElt8
*) elts
, nelt
);
3877 if (elts
!= stack_elts
)
3880 return CAIRO_STATUS_SUCCESS
;
3884 /* sz_xGlyphtElt required alignment to a 32-bit boundary, so ensure we have
3885 * enough room for padding */
3886 #define _cairo_sz_xGlyphElt (sz_xGlyphElt + 4)
3888 static cairo_status_t
3889 _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t
*dst
,
3890 cairo_xlib_glyph_t
*glyphs
,
3892 cairo_scaled_font_t
*scaled_font
,
3893 cairo_operator_t op
,
3894 cairo_xlib_surface_t
*src
,
3895 cairo_surface_attributes_t
*attributes
,
3896 int *remaining_glyphs
)
3899 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
3900 cairo_scaled_glyph_t
*scaled_glyph
;
3901 cairo_fixed_t x
= 0, y
= 0;
3902 cairo_xlib_font_glyphset_info_t
*glyphset_info
= NULL
, *this_glyphset_info
;
3904 unsigned long max_index
= 0;
3907 int num_out_glyphs
= 0;
3909 int max_request_size
= XMaxRequestSize (dst
->dpy
) * 4
3910 - MAX (sz_xRenderCompositeGlyphs8Req
,
3911 MAX(sz_xRenderCompositeGlyphs16Req
,
3912 sz_xRenderCompositeGlyphs32Req
));
3913 int request_size
= 0;
3915 _cairo_xlib_surface_ensure_dst_picture (dst
);
3916 _cairo_xlib_display_notify (dst
->display
);
3918 for (i
= 0; i
< num_glyphs
; i
++) {
3922 status
= _cairo_scaled_glyph_lookup (scaled_font
,
3924 CAIRO_SCALED_GLYPH_INFO_METRICS
,
3926 if (status
!= CAIRO_STATUS_SUCCESS
)
3929 this_x
= _cairo_lround (glyphs
[i
].d
.x
);
3930 this_y
= _cairo_lround (glyphs
[i
].d
.y
);
3934 * We skip any glyphs that have troublesome coordinates. We want
3935 * to make sure that (glyph2.x - (glyph1.x + glyph1.width)) fits in
3936 * a signed 16bit integer, otherwise it will overflow in the render
3938 * To ensure this, we'll make sure that (glyph2.x - glyph1.x) fits in
3939 * a signed 15bit integer. The trivial option would be to allow
3940 * coordinates -8192..8192, but that's kinda dull. It probably will
3941 * take a decade or so to get monitors 8192x4096 or something. A
3942 * negative value of -8192 on the other hand, is absolutely useless.
3943 * Note that we do want to allow some negative positions. The glyph
3944 * may start off the screen but part of it make it to the screen.
3945 * Anyway, we will allow positions in the range -4096..122887. That
3946 * will buy us a few more years before this stops working.
3948 * Update: upon seeing weird glyphs, we just return and let fallback
3951 if (((this_x
+4096)|(this_y
+4096))&~0x3fffu
)
3954 /* Send unsent glyphs to the server */
3955 if (_cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph
) == NULL
) {
3956 status
= _cairo_xlib_surface_add_glyph (dst
->dpy
,
3959 if (unlikely (status
)) {
3960 if (status
== CAIRO_INT_STATUS_UNSUPPORTED
)
3961 /* Break so we flush glyphs so far and let fallback code
3962 * handle the rest */
3969 this_glyphset_info
= _cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph
);
3971 glyphset_info
= this_glyphset_info
;
3973 /* The invariant here is that we can always flush the glyphs
3974 * accumulated before this one, using old_width, and they
3975 * would fit in the request.
3979 /* Update max glyph index */
3980 if (glyphs
[i
].index
> max_index
) {
3981 max_index
= glyphs
[i
].index
;
3982 if (max_index
>= 65536)
3984 else if (max_index
>= 256)
3986 if (width
!= old_width
)
3987 request_size
+= (width
- old_width
) * num_out_glyphs
;
3990 /* If we will pass the max request size by adding this glyph,
3991 * flush current glyphs. Note that we account for a
3992 * possible element being added below.
3994 * Also flush if changing glyphsets, as Xrender limits one mask
3995 * format per request, so we can either break up, or use a
3996 * wide-enough mask format. We do the former. One reason to
3997 * prefer the latter is the fact that Xserver ADDs all glyphs
3998 * to the mask first, and then composes that to final surface,
3999 * though it's not a big deal.
4001 if (request_size
+ width
> max_request_size
- _cairo_sz_xGlyphElt
||
4002 (this_glyphset_info
!= glyphset_info
)) {
4003 status
= _emit_glyphs_chunk (dst
, glyphs
, i
,
4004 scaled_font
, op
, src
, attributes
,
4005 num_elts
, old_width
, glyphset_info
);
4006 if (status
!= CAIRO_STATUS_SUCCESS
)
4012 max_index
= glyphs
[i
].index
;
4013 width
= max_index
< 256 ? 1 : max_index
< 65536 ? 2 : 4;
4018 glyphset_info
= this_glyphset_info
;
4021 /* Convert absolute glyph position to relative-to-current-point
4023 glyphs
[i
].i
.x
= this_x
- x
;
4024 glyphs
[i
].i
.y
= this_y
- y
;
4026 /* Start a new element for the first glyph,
4027 * or for any glyph that has unexpected position,
4028 * or if current element has too many glyphs.
4030 * These same conditions are mirrored in _emit_glyphs_chunk().
4032 if (_start_new_glyph_elt (num_out_glyphs
, &glyphs
[i
])) {
4034 request_size
+= _cairo_sz_xGlyphElt
;
4037 /* adjust current-position */
4038 x
= this_x
+ scaled_glyph
->x_advance
;
4039 y
= this_y
+ scaled_glyph
->y_advance
;
4042 request_size
+= width
;
4046 status
= _emit_glyphs_chunk (dst
, glyphs
, i
,
4047 scaled_font
, op
, src
, attributes
,
4048 num_elts
, width
, glyphset_info
);
4050 *remaining_glyphs
= num_glyphs
- i
;
4051 if (*remaining_glyphs
&& status
== CAIRO_STATUS_SUCCESS
)
4052 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
4058 _cairo_xlib_surface_owns_font (cairo_xlib_surface_t
*dst
,
4059 cairo_scaled_font_t
*scaled_font
)
4061 cairo_xlib_surface_font_private_t
*font_private
;
4063 font_private
= scaled_font
->surface_private
;
4064 if ((scaled_font
->surface_backend
!= NULL
&&
4065 scaled_font
->surface_backend
!= &cairo_xlib_surface_backend
) ||
4066 (font_private
!= NULL
&& font_private
->display
!= dst
->display
))
4074 static cairo_int_status_t
4075 _cairo_xlib_surface_show_glyphs (void *abstract_dst
,
4076 cairo_operator_t op
,
4077 const cairo_pattern_t
*src_pattern
,
4078 cairo_glyph_t
*glyphs
,
4080 cairo_scaled_font_t
*scaled_font
,
4081 int *remaining_glyphs
,
4082 cairo_rectangle_int_t
*extents
)
4084 cairo_int_status_t status
= CAIRO_STATUS_SUCCESS
;
4085 cairo_xlib_surface_t
*dst
= (cairo_xlib_surface_t
*) abstract_dst
;
4087 composite_operation_t operation
;
4088 cairo_surface_attributes_t attributes
;
4089 cairo_xlib_surface_t
*src
= NULL
;
4091 cairo_solid_pattern_t solid_pattern
;
4093 if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst
))
4094 return CAIRO_INT_STATUS_UNSUPPORTED
;
4096 /* Just let unbounded operators go through the fallback code
4097 * instead of trying to do the fixups here */
4098 if (!_cairo_operator_bounded_by_mask (op
))
4099 return CAIRO_INT_STATUS_UNSUPPORTED
;
4101 /* Render <= 0.10 seems to have a bug with PictOpSrc and glyphs --
4102 * the solid source seems to be multiplied by the glyph mask, and
4103 * then the entire thing is copied to the destination surface,
4104 * including the fully transparent "background" of the rectangular
4106 if (op
== CAIRO_OPERATOR_SOURCE
&&
4107 !CAIRO_SURFACE_RENDER_AT_LEAST(dst
, 0, 11))
4108 return CAIRO_INT_STATUS_UNSUPPORTED
;
4110 /* We can only use our code if we either have no clip or
4111 * have a real native clip region set. If we're using
4112 * fallback clip masking, we have to go through the full
4115 if (dst
->base
.clip
&&
4116 (dst
->base
.clip
->mode
!= CAIRO_CLIP_MODE_REGION
||
4117 dst
->base
.clip
->surface
!= NULL
))
4118 return CAIRO_INT_STATUS_UNSUPPORTED
;
4120 operation
= _categorize_composite_operation (dst
, op
, src_pattern
, TRUE
);
4121 if (operation
== DO_UNSUPPORTED
)
4122 return CAIRO_INT_STATUS_UNSUPPORTED
;
4124 if (! _cairo_xlib_surface_owns_font (dst
, scaled_font
))
4125 return CAIRO_INT_STATUS_UNSUPPORTED
;
4127 /* After passing all those tests, we're now committed to rendering
4128 * these glyphs or to fail trying. We first upload any glyphs to
4129 * the X server that it doesn't have already, then we draw
4133 /* PictOpClear doesn't seem to work with CompositeText; it seems to ignore
4134 * the mask (the glyphs). This code below was executed as a side effect
4135 * of going through the _clip_and_composite fallback code for old_show_glyphs,
4136 * so PictOpClear was never used with CompositeText before.
4138 if (op
== CAIRO_OPERATOR_CLEAR
) {
4139 _cairo_pattern_init_solid (&solid_pattern
, CAIRO_COLOR_WHITE
,
4140 CAIRO_CONTENT_COLOR
);
4141 src_pattern
= &solid_pattern
.base
;
4142 op
= CAIRO_OPERATOR_DEST_OUT
;
4145 if (src_pattern
->type
== CAIRO_PATTERN_TYPE_SOLID
) {
4146 status
= _cairo_pattern_acquire_surface (src_pattern
, &dst
->base
,
4147 CAIRO_CONTENT_COLOR_ALPHA
,
4149 CAIRO_PATTERN_ACQUIRE_NONE
,
4150 (cairo_surface_t
**) &src
,
4152 if (unlikely (status
))
4155 cairo_rectangle_int_t glyph_extents
;
4157 status
= _cairo_scaled_font_glyph_device_extents (scaled_font
,
4161 if (unlikely (status
))
4164 status
= _cairo_pattern_acquire_surface (src_pattern
, &dst
->base
,
4165 CAIRO_CONTENT_COLOR_ALPHA
,
4166 glyph_extents
.x
, glyph_extents
.y
,
4167 glyph_extents
.width
, glyph_extents
.height
,
4168 dst
->buggy_pad_reflect
?
4169 CAIRO_PATTERN_ACQUIRE_NO_REFLECT
:
4170 CAIRO_PATTERN_ACQUIRE_NONE
,
4171 (cairo_surface_t
**) &src
,
4173 if (unlikely (status
))
4177 operation
= _recategorize_composite_operation (dst
, op
, src
,
4179 if (operation
== DO_UNSUPPORTED
) {
4180 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
4184 status
= _cairo_xlib_surface_set_attributes (src
, &attributes
, 0, 0);
4185 if (unlikely (status
))
4188 _cairo_scaled_font_freeze_cache (scaled_font
);
4189 if (_cairo_xlib_surface_owns_font (dst
, scaled_font
)) {
4190 status
= _cairo_xlib_surface_emit_glyphs (dst
,
4191 (cairo_xlib_glyph_t
*) glyphs
,
4199 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
4200 _cairo_scaled_font_thaw_cache (scaled_font
);
4204 _cairo_pattern_release_surface (src_pattern
, &src
->base
, &attributes
);
4205 if (src_pattern
== &solid_pattern
.base
)
4206 _cairo_pattern_fini (&solid_pattern
.base
);
4208 _cairo_xlib_display_notify (dst
->display
);
4220 } cairo_xlib_space_t
;
4223 _cairo_xlib_space_destroy(void* abstract_space
)
4225 cairo_xlib_space_t
* space
= abstract_space
;
4227 XCloseDisplay(space
->dpy
);
4231 static cairo_surface_t
*
4232 _cairo_xlib_surface_create_offscreen(Display
* dpy
, cairo_xlib_surface_t
* surface
, cairo_content_t content
, double width
, double height
)
4234 cairo_xlib_display_t
* display
;
4237 XRenderPictFormat
*xrender_format
;
4239 screen
= DefaultScreenOfDisplay(dpy
);
4241 assert (width
<= XLIB_COORD_MAX
&& height
<= XLIB_COORD_MAX
);
4243 if(_cairo_xlib_display_get(dpy
, &display
))
4244 return _cairo_surface_create_in_error(CAIRO_STATUS_NO_MEMORY
);
4246 /* As a good first approximation, if the display doesn't have even
4247 * the most elementary RENDER operation, then we're better off
4248 * using image surfaces for all temporary operations, so return NULL
4249 * and let the fallback code happen.
4252 if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (display))
4253 return _cairo_surface_create_in_error(CAIRO_STATUS_NO_MEMORY);
4255 xrender_format
= _cairo_xlib_display_get_xrender_format (display
,
4256 _cairo_format_from_content(content
));
4257 if (xrender_format
== NULL
)
4258 return _cairo_surface_create_in_error(CAIRO_STATUS_NO_MEMORY
);
4260 pix
= XCreatePixmap (dpy
, RootWindowOfScreen(screen
),
4261 width
<= 0 ? 1 : width
, height
<= 0 ? 1 : height
,
4262 xrender_format
->depth
);
4264 surface
= (cairo_xlib_surface_t
*)
4265 _cairo_xlib_surface_init_internal (surface
, dpy
, pix
,
4269 xrender_format
->depth
);
4270 if (surface
->base
.status
) {
4271 XFreePixmap (dpy
, pix
);
4272 return &surface
->base
;
4275 surface
->owns_pixmap
= TRUE
;
4277 return &surface
->base
;
4281 _cairo_get_xvisualinfo(Display
* dpy
, unsigned long drawable
, unsigned long visualid
)
4289 XWindowAttributes attr
;
4290 XGetWindowAttributes(dpy
, drawable
, &attr
);
4291 visualid
= XVisualIDFromVisual(attr
.visual
);
4294 vit
.visualid
= visualid
;
4295 vi
= XGetVisualInfo(dpy
, VisualIDMask
, &vit
, &nvi
);
4303 static cairo_surface_t
*
4304 _cairo_xlib_surface_create_for_drawable(Display
* dpy
, cairo_xlib_surface_t
* surface
, cairo_content_t content
, unsigned long drawable
, unsigned long visualid
, double width
, double height
)
4310 vi
= _cairo_get_xvisualinfo(dpy
, drawable
, visualid
);
4312 return _cairo_surface_create_in_error(CAIRO_STATUS_INVALID_VISUAL
);
4314 visual
= vi
->visual
;
4316 screen
= _cairo_xlib_screen_from_visual (dpy
, vi
->visual
);
4320 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL
));
4322 return _cairo_xlib_surface_init_internal (surface
, dpy
, (Drawable
)drawable
, screen
,
4323 visual
, NULL
, width
, height
, 0);
4326 static cairo_surface_t
*
4327 _cairo_xlib_space_surface_create(void *abstract_space
, void* abstract_surface
, cairo_content_t content
,
4328 unsigned long drawable
, unsigned long visualid
, cairo_bool_t double_buffered
,
4329 double width
, double height
, int color_mantissa_bits
, int alpha_mantissa_bits
, int exponent_bits
, int shared_exponent_bits
)
4332 cairo_xlib_space_t
* space
= abstract_space
;
4333 cairo_xlib_surface_t
* surface
= abstract_surface
;
4334 if(surface
&& surface
->base
.backend
!= &cairo_xlib_surface_backend
)
4335 return _cairo_surface_create_in_error(CAIRO_STATUS_SURFACE_TYPE_MISMATCH
);
4337 if(!surface
&& !space
)
4338 return _cairo_surface_create_in_error(CAIRO_STATUS_SURFACE_FINISHED
);
4340 dpy
= space
? space
->dpy
: surface
->dpy
;
4342 if(drawable
== ~0UL)
4343 drawable
= surface
? (unsigned long)surface
->drawable
: 0;
4348 return _cairo_surface_create_in_error(CAIRO_STATUS_SURFACE_FINISHED
);
4349 width
= surface
->width
;
4355 return _cairo_surface_create_in_error(CAIRO_STATUS_SURFACE_FINISHED
);
4356 height
= surface
->height
;
4361 surface
= malloc (sizeof (cairo_xlib_surface_t
));
4363 if (unlikely (surface
== NULL
))
4364 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
4366 _cairo_surface_init (&surface
->base
, &cairo_xlib_surface_backend
, 0);
4371 return _cairo_xlib_surface_create_for_drawable(dpy
, surface
, content
, drawable
, visualid
, width
, height
);
4373 return _cairo_xlib_surface_create_offscreen(dpy
, surface
, content
, width
, height
);
4376 static cairo_status_t
4377 _cairo_xlib_space_sync(void* abstract_space
)
4379 cairo_xlib_space_t
* space
= abstract_space
;
4380 XSync(space
->dpy
, 0);
4381 return CAIRO_STATUS_SUCCESS
;
4384 static cairo_space_backend_t _cairo_xlib_space_backend
=
4386 _cairo_xlib_space_destroy
,
4387 _cairo_xlib_space_surface_create
,
4388 _cairo_xlib_space_sync
,
4391 cairo_public cairo_space_t
*
4392 cairo_xlib_space_create(const char* name
)
4395 dpy
= XOpenDisplay(name
);
4398 return cairo_xlib_space_wrap(dpy
, DefaultScreen(dpy
), 1);
4401 cairo_public cairo_space_t
*
4402 cairo_xlib_space_wrap(Display
*dpy
, int screen
, int owns_dpy
)
4404 cairo_xlib_space_t
* space
;
4406 return cairo_xlib_space_create(0);
4408 space
= calloc(sizeof(cairo_xlib_space_t
), 1);
4410 CAIRO_REFERENCE_COUNT_INIT(&space
->base
.ref_count
, 1);
4411 space
->base
.backend
= &_cairo_xlib_space_backend
;
4413 space
->screen
= ScreenOfDisplay(dpy
, screen
);
4414 space
->owns_dpy
= owns_dpy
;
4416 return &space
->base
;