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