File: | root/firefox-clang/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c |
Warning: | line 1971, column 14 1st function call argument is an uninitialized value |
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 | * Copyright © 2011 Intel Corporation | |||
7 | * | |||
8 | * This library is free software; you can redistribute it and/or | |||
9 | * modify it either under the terms of the GNU Lesser General Public | |||
10 | * License version 2.1 as published by the Free Software Foundation | |||
11 | * (the "LGPL") or, at your option, under the terms of the Mozilla | |||
12 | * Public License Version 1.1 (the "MPL"). If you do not alter this | |||
13 | * notice, a recipient may use your version of this file under either | |||
14 | * the MPL or the LGPL. | |||
15 | * | |||
16 | * You should have received a copy of the LGPL along with this library | |||
17 | * in the file COPYING-LGPL-2.1; if not, write to the Free Software | |||
18 | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA | |||
19 | * You should have received a copy of the MPL along with this library | |||
20 | * in the file COPYING-MPL-1.1 | |||
21 | * | |||
22 | * The contents of this file are subject to the Mozilla Public License | |||
23 | * Version 1.1 (the "License"); you may not use this file except in | |||
24 | * compliance with the License. You may obtain a copy of the License at | |||
25 | * http://www.mozilla.org/MPL/ | |||
26 | * | |||
27 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY | |||
28 | * OF ANY KIND, either express or implied. See the LGPL or the MPL for | |||
29 | * the specific language governing rights and limitations. | |||
30 | * | |||
31 | * The Original Code is the cairo graphics library. | |||
32 | * | |||
33 | * The Initial Developer of the Original Code is University of Southern | |||
34 | * California. | |||
35 | * | |||
36 | * Contributor(s): | |||
37 | * Carl D. Worth <cworth@cworth.org> | |||
38 | * Behdad Esfahbod <behdad@behdad.org> | |||
39 | * Chris Wilson <chris@chris-wilson.co.uk> | |||
40 | * Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation | |||
41 | */ | |||
42 | ||||
43 | #include "cairoint.h" | |||
44 | ||||
45 | #if !CAIRO_HAS_XLIB_XCB_FUNCTIONS | |||
46 | ||||
47 | #include "cairo-xlib-private.h" | |||
48 | ||||
49 | #include "cairo-compositor-private.h" | |||
50 | #include "cairo-damage-private.h" | |||
51 | #include "cairo-image-surface-private.h" | |||
52 | #include "cairo-list-inline.h" | |||
53 | #include "cairo-pattern-private.h" | |||
54 | #include "cairo-pixman-private.h" | |||
55 | #include "cairo-traps-private.h" | |||
56 | #include "cairo-tristrip-private.h" | |||
57 | ||||
58 | static cairo_int_status_t | |||
59 | check_composite (const cairo_composite_rectangles_t *extents) | |||
60 | { | |||
61 | cairo_xlib_display_t *display = ((cairo_xlib_surface_t *)extents->surface)->display; | |||
62 | ||||
63 | if (! CAIRO_RENDER_SUPPORTS_OPERATOR (display, extents->op)((extents->op) <= CAIRO_OPERATOR_SATURATE || (((((display ))->render_major > 0) || ((((display))->render_major == 0) && (((display))->render_minor >= 11))) && (extents->op) <= CAIRO_OPERATOR_HSL_LUMINOSITY))) | |||
64 | return CAIRO_INT_STATUS_UNSUPPORTED; | |||
65 | ||||
66 | return CAIRO_STATUS_SUCCESS; | |||
67 | } | |||
68 | ||||
69 | static cairo_int_status_t | |||
70 | acquire (void *abstract_dst) | |||
71 | { | |||
72 | cairo_xlib_surface_t *dst = abstract_dst; | |||
73 | cairo_int_status_t status; | |||
74 | ||||
75 | status = _cairo_xlib_display_acquire (dst->base.device, &dst->display); | |||
76 | if (unlikely (status)(__builtin_expect (!!(status), 0))) | |||
77 | return status; | |||
78 | ||||
79 | dst->dpy = dst->display->display; | |||
80 | return CAIRO_STATUS_SUCCESS; | |||
81 | } | |||
82 | ||||
83 | static cairo_int_status_t | |||
84 | release (void *abstract_dst) | |||
85 | { | |||
86 | cairo_xlib_surface_t *dst = abstract_dst; | |||
87 | ||||
88 | cairo_device_release_moz_cairo_device_release (&dst->display->base); | |||
89 | dst->dpy = NULL((void*)0); | |||
90 | ||||
91 | return CAIRO_STATUS_SUCCESS; | |||
92 | } | |||
93 | ||||
94 | static cairo_int_status_t | |||
95 | set_clip_region (void *_surface, | |||
96 | cairo_region_t *region) | |||
97 | { | |||
98 | cairo_xlib_surface_t *surface = _surface; | |||
99 | ||||
100 | _cairo_xlib_surface_ensure_picture (surface); | |||
101 | ||||
102 | if (region != NULL((void*)0)) { | |||
103 | XRectangle stack_rects[CAIRO_STACK_ARRAY_LENGTH (XRectangle)((512 * sizeof (int)) / sizeof(XRectangle))]; | |||
104 | XRectangle *rects = stack_rects; | |||
105 | int n_rects, i; | |||
106 | ||||
107 | n_rects = cairo_region_num_rectangles_moz_cairo_region_num_rectangles (region); | |||
108 | if (n_rects > ARRAY_LENGTH (stack_rects)((int) (sizeof (stack_rects) / sizeof (stack_rects[0])))) { | |||
109 | rects = _cairo_malloc_ab (n_rects, sizeof (XRectangle)); | |||
110 | if (unlikely (rects == NULL)(__builtin_expect (!!(rects == ((void*)0)), 0))) | |||
111 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); | |||
112 | } | |||
113 | for (i = 0; i < n_rects; i++) { | |||
114 | cairo_rectangle_int_t rect; | |||
115 | ||||
116 | cairo_region_get_rectangle_moz_cairo_region_get_rectangle (region, i, &rect); | |||
117 | ||||
118 | rects[i].x = rect.x; | |||
119 | rects[i].y = rect.y; | |||
120 | rects[i].width = rect.width; | |||
121 | rects[i].height = rect.height; | |||
122 | } | |||
123 | XRenderSetPictureClipRectangles_void_consume (surface->dpy, | |||
124 | surface->picture, | |||
125 | 0, 0, | |||
126 | rects, n_rects); | |||
127 | if (rects != stack_rects) | |||
128 | free (rects); | |||
129 | } else { | |||
130 | XRenderPictureAttributes pa; | |||
131 | pa.clip_mask = None0L; | |||
132 | XRenderChangePicture_void_consume (surface->dpy, | |||
133 | surface->picture, | |||
134 | CPClipMask(1 << 6), &pa); | |||
135 | } | |||
136 | ||||
137 | return CAIRO_STATUS_SUCCESS; | |||
138 | } | |||
139 | ||||
140 | static cairo_int_status_t | |||
141 | copy_image_boxes (void *_dst, | |||
142 | cairo_image_surface_t *image, | |||
143 | cairo_boxes_t *boxes, | |||
144 | int dx, int dy) | |||
145 | { | |||
146 | cairo_xlib_surface_t *dst = _dst; | |||
147 | struct _cairo_boxes_chunk *chunk; | |||
148 | cairo_int_status_t status; | |||
149 | Pixmap src; | |||
150 | GC gc; | |||
151 | int i, j; | |||
152 | ||||
153 | assert (image->depth == dst->depth)((void) sizeof ((image->depth == dst->depth) ? 1 : 0), __extension__ ({ if (image->depth == dst->depth) ; else __assert_fail ("image->depth == dst->depth", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c" , 153, __extension__ __PRETTY_FUNCTION__); })); | |||
154 | ||||
155 | status = acquire (dst); | |||
156 | if (unlikely (status)(__builtin_expect (!!(status), 0))) | |||
157 | return status; | |||
158 | ||||
159 | status = _cairo_xlib_surface_get_gc (dst->display, dst, &gc); | |||
160 | if (unlikely (status)(__builtin_expect (!!(status), 0))) { | |||
161 | release (dst); | |||
162 | return status; | |||
163 | } | |||
164 | ||||
165 | src = _cairo_xlib_shm_surface_get_pixmap (&image->base); | |||
166 | if (boxes->num_boxes == 1) { | |||
167 | int x1 = _cairo_fixed_integer_part (boxes->chunks.base[0].p1.x); | |||
168 | int y1 = _cairo_fixed_integer_part (boxes->chunks.base[0].p1.y); | |||
169 | int x2 = _cairo_fixed_integer_part (boxes->chunks.base[0].p2.x); | |||
170 | int y2 = _cairo_fixed_integer_part (boxes->chunks.base[0].p2.y); | |||
171 | ||||
172 | _cairo_xlib_shm_surface_mark_active (&image->base); | |||
173 | XCopyArea (dst->dpy, src, dst->drawable, gc, | |||
174 | x1 + dx, y1 + dy, | |||
175 | x2 - x1, y2 - y1, | |||
176 | x1, y1); | |||
177 | } else { | |||
178 | XRectangle stack_rects[CAIRO_STACK_ARRAY_LENGTH (XRectangle)((512 * sizeof (int)) / sizeof(XRectangle))]; | |||
179 | XRectangle *rects = stack_rects; | |||
180 | ||||
181 | if (boxes->num_boxes > ARRAY_LENGTH (stack_rects)((int) (sizeof (stack_rects) / sizeof (stack_rects[0])))) { | |||
182 | rects = _cairo_malloc_ab (boxes->num_boxes, sizeof (XRectangle)); | |||
183 | if (unlikely (rects == NULL)(__builtin_expect (!!(rects == ((void*)0)), 0))) | |||
184 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); | |||
185 | } | |||
186 | ||||
187 | j = 0; | |||
188 | for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { | |||
189 | for (i = 0; i < chunk->count; i++) { | |||
190 | int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x); | |||
191 | int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y); | |||
192 | int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x); | |||
193 | int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y); | |||
194 | ||||
195 | if (x2 > x1 && y2 > y1) { | |||
196 | rects[j].x = x1; | |||
197 | rects[j].y = y1; | |||
198 | rects[j].width = x2 - x1; | |||
199 | rects[j].height = y2 - y1; | |||
200 | j++; | |||
201 | } | |||
202 | } | |||
203 | } | |||
204 | ||||
205 | XSetClipRectangles (dst->dpy, gc, 0, 0, rects, j, Unsorted0); | |||
206 | _cairo_xlib_shm_surface_mark_active (&image->base); | |||
207 | XCopyArea (dst->dpy, src, dst->drawable, gc, | |||
208 | 0, 0, image->width, image->height, -dx, -dy); | |||
209 | XSetClipMask (dst->dpy, gc, None0L); | |||
210 | ||||
211 | if (rects != stack_rects) | |||
212 | free (rects); | |||
213 | } | |||
214 | ||||
215 | _cairo_xlib_surface_put_gc (dst->display, dst, gc); | |||
216 | release (dst); | |||
217 | return CAIRO_STATUS_SUCCESS; | |||
218 | } | |||
219 | ||||
220 | static cairo_bool_t | |||
221 | boxes_cover_surface (cairo_boxes_t *boxes, | |||
222 | cairo_xlib_surface_t *surface) | |||
223 | { | |||
224 | cairo_box_t *b; | |||
225 | ||||
226 | if (boxes->num_boxes != 1) | |||
227 | return FALSE0; | |||
228 | ||||
229 | b = &boxes->chunks.base[0]; | |||
230 | ||||
231 | if (_cairo_fixed_integer_part (b->p1.x) > 0 || | |||
232 | _cairo_fixed_integer_part (b->p1.y) > 0) | |||
233 | return FALSE0; | |||
234 | ||||
235 | if (_cairo_fixed_integer_part (b->p2.x) < surface->width || | |||
236 | _cairo_fixed_integer_part (b->p2.y) < surface->height) | |||
237 | return FALSE0; | |||
238 | ||||
239 | return TRUE1; | |||
240 | } | |||
241 | ||||
242 | static cairo_int_status_t | |||
243 | draw_image_boxes (void *_dst, | |||
244 | cairo_image_surface_t *image, | |||
245 | cairo_boxes_t *boxes, | |||
246 | int dx, int dy) | |||
247 | { | |||
248 | cairo_xlib_surface_t *dst = _dst; | |||
249 | struct _cairo_boxes_chunk *chunk; | |||
250 | cairo_image_surface_t *shm = NULL((void*)0); | |||
251 | cairo_int_status_t status; | |||
252 | int i; | |||
253 | ||||
254 | if (image->base.device == dst->base.device) { | |||
255 | if (image->depth != dst->depth) | |||
256 | return CAIRO_INT_STATUS_UNSUPPORTED; | |||
257 | ||||
258 | if (_cairo_xlib_shm_surface_get_pixmap (&image->base)) | |||
259 | return copy_image_boxes (dst, image, boxes, dx, dy); | |||
260 | ||||
261 | goto draw_image_boxes; | |||
262 | } | |||
263 | ||||
264 | if (boxes_cover_surface (boxes, dst)) | |||
265 | shm = (cairo_image_surface_t *) _cairo_xlib_surface_get_shm (dst, TRUE1); | |||
266 | if (shm) { | |||
267 | for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { | |||
268 | for (i = 0; i < chunk->count; i++) { | |||
269 | cairo_box_t *b = &chunk->base[i]; | |||
270 | cairo_rectangle_int_t r; | |||
271 | ||||
272 | r.x = _cairo_fixed_integer_part (b->p1.x); | |||
273 | r.y = _cairo_fixed_integer_part (b->p1.y); | |||
274 | r.width = _cairo_fixed_integer_part (b->p2.x) - r.x; | |||
275 | r.height = _cairo_fixed_integer_part (b->p2.y) - r.y; | |||
276 | ||||
277 | if (shm->pixman_format != image->pixman_format || | |||
278 | ! pixman_blt_moz_pixman_blt ((uint32_t *)image->data, (uint32_t *)shm->data, | |||
279 | image->stride / sizeof (uint32_t), | |||
280 | shm->stride / sizeof (uint32_t), | |||
281 | PIXMAN_FORMAT_BPP (image->pixman_format)(((image->pixman_format >> (24)) & ((1 << ( 8)) - 1)) << ((image->pixman_format >> 22) & 3)), | |||
282 | PIXMAN_FORMAT_BPP (shm->pixman_format)(((shm->pixman_format >> (24)) & ((1 << (8 )) - 1)) << ((shm->pixman_format >> 22) & 3 )), | |||
283 | r.x + dx, r.y + dy, | |||
284 | r.x, r.y, | |||
285 | r.width, r.height)) | |||
286 | { | |||
287 | pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_SRC, | |||
288 | image->pixman_image, NULL((void*)0), shm->pixman_image, | |||
289 | r.x + dx, r.y + dy, | |||
290 | 0, 0, | |||
291 | r.x, r.y, | |||
292 | r.width, r.height); | |||
293 | } | |||
294 | ||||
295 | shm->base.damage = | |||
296 | _cairo_damage_add_rectangle (shm->base.damage, &r); | |||
297 | } | |||
298 | } | |||
299 | dst->base.is_clear = FALSE0; | |||
300 | dst->fallback++; | |||
301 | dst->base.serial++; | |||
302 | return CAIRO_INT_STATUS_NOTHING_TO_DO; | |||
303 | } | |||
304 | ||||
305 | if (image->depth == dst->depth && | |||
306 | ((cairo_xlib_display_t *)dst->display)->shm) { | |||
307 | cairo_box_t extents; | |||
308 | cairo_rectangle_int_t r; | |||
309 | ||||
310 | _cairo_boxes_extents (boxes, &extents); | |||
311 | _cairo_box_round_to_rectangle (&extents, &r); | |||
312 | ||||
313 | shm = (cairo_image_surface_t *) | |||
314 | _cairo_xlib_surface_create_shm (dst, image->pixman_format, | |||
315 | r.width, r.height); | |||
316 | if (shm) { | |||
317 | int tx = -r.x, ty = -r.y; | |||
318 | ||||
319 | assert (shm->pixman_format == image->pixman_format)((void) sizeof ((shm->pixman_format == image->pixman_format ) ? 1 : 0), __extension__ ({ if (shm->pixman_format == image ->pixman_format) ; else __assert_fail ("shm->pixman_format == image->pixman_format" , "/root/firefox-clang/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c" , 319, __extension__ __PRETTY_FUNCTION__); })); | |||
320 | for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { | |||
321 | for (i = 0; i < chunk->count; i++) { | |||
322 | cairo_box_t *b = &chunk->base[i]; | |||
323 | ||||
324 | r.x = _cairo_fixed_integer_part (b->p1.x); | |||
325 | r.y = _cairo_fixed_integer_part (b->p1.y); | |||
326 | r.width = _cairo_fixed_integer_part (b->p2.x) - r.x; | |||
327 | r.height = _cairo_fixed_integer_part (b->p2.y) - r.y; | |||
328 | ||||
329 | if (! pixman_blt_moz_pixman_blt ((uint32_t *)image->data, (uint32_t *)shm->data, | |||
330 | image->stride / sizeof (uint32_t), | |||
331 | shm->stride / sizeof (uint32_t), | |||
332 | PIXMAN_FORMAT_BPP (image->pixman_format)(((image->pixman_format >> (24)) & ((1 << ( 8)) - 1)) << ((image->pixman_format >> 22) & 3)), | |||
333 | PIXMAN_FORMAT_BPP (shm->pixman_format)(((shm->pixman_format >> (24)) & ((1 << (8 )) - 1)) << ((shm->pixman_format >> 22) & 3 )), | |||
334 | r.x + dx, r.y + dy, | |||
335 | r.x + tx, r.y + ty, | |||
336 | r.width, r.height)) | |||
337 | { | |||
338 | pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_SRC, | |||
339 | image->pixman_image, NULL((void*)0), shm->pixman_image, | |||
340 | r.x + dx, r.y + dy, | |||
341 | 0, 0, | |||
342 | r.x + tx, r.y + ty, | |||
343 | r.width, r.height); | |||
344 | } | |||
345 | } | |||
346 | } | |||
347 | ||||
348 | dx = tx; | |||
349 | dy = ty; | |||
350 | image = shm; | |||
351 | ||||
352 | if (_cairo_xlib_shm_surface_get_pixmap (&image->base)) { | |||
353 | status = copy_image_boxes (dst, image, boxes, dx, dy); | |||
354 | if (status != CAIRO_INT_STATUS_UNSUPPORTED) | |||
355 | goto out; | |||
356 | } | |||
357 | } | |||
358 | } | |||
359 | ||||
360 | draw_image_boxes: | |||
361 | status = CAIRO_STATUS_SUCCESS; | |||
362 | for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { | |||
363 | for (i = 0; i < chunk->count; i++) { | |||
364 | cairo_box_t *b = &chunk->base[i]; | |||
365 | int x1 = _cairo_fixed_integer_part (b->p1.x); | |||
366 | int y1 = _cairo_fixed_integer_part (b->p1.y); | |||
367 | int x2 = _cairo_fixed_integer_part (b->p2.x); | |||
368 | int y2 = _cairo_fixed_integer_part (b->p2.y); | |||
369 | if (_cairo_xlib_surface_draw_image (dst, image, | |||
370 | x1 + dx, y1 + dy, | |||
371 | x2 - x1, y2 - y1, | |||
372 | x1, y1)) { | |||
373 | status = CAIRO_INT_STATUS_UNSUPPORTED; | |||
374 | goto out; | |||
375 | } | |||
376 | } | |||
377 | } | |||
378 | ||||
379 | out: | |||
380 | cairo_surface_destroy_moz_cairo_surface_destroy (&shm->base); | |||
381 | return status; | |||
382 | } | |||
383 | ||||
384 | static cairo_int_status_t | |||
385 | copy_boxes (void *_dst, | |||
386 | cairo_surface_t *_src, | |||
387 | cairo_boxes_t *boxes, | |||
388 | const cairo_rectangle_int_t *extents, | |||
389 | int dx, int dy) | |||
390 | { | |||
391 | cairo_xlib_surface_t *dst = _dst; | |||
392 | cairo_xlib_surface_t *src = (cairo_xlib_surface_t *)_src; | |||
393 | struct _cairo_boxes_chunk *chunk; | |||
394 | cairo_int_status_t status; | |||
395 | GC gc; | |||
396 | Drawable d; | |||
397 | int i, j; | |||
398 | ||||
399 | if (! _cairo_xlib_surface_same_screen (dst, src)) | |||
400 | return CAIRO_INT_STATUS_UNSUPPORTED; | |||
401 | ||||
402 | if (dst->depth != src->depth) | |||
403 | return CAIRO_INT_STATUS_UNSUPPORTED; | |||
404 | ||||
405 | status = acquire (dst); | |||
406 | if (unlikely (status)(__builtin_expect (!!(status), 0))) | |||
407 | return status; | |||
408 | ||||
409 | status = _cairo_xlib_surface_get_gc (dst->display, dst, &gc); | |||
410 | if (unlikely (status)(__builtin_expect (!!(status), 0))) { | |||
411 | release (dst); | |||
412 | return status; | |||
413 | } | |||
414 | ||||
415 | if (src->fallback && src->shm->damage->dirty) { | |||
416 | assert (src != dst)((void) sizeof ((src != dst) ? 1 : 0), __extension__ ({ if (src != dst) ; else __assert_fail ("src != dst", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c" , 416, __extension__ __PRETTY_FUNCTION__); })); | |||
417 | d = _cairo_xlib_shm_surface_get_pixmap (src->shm); | |||
418 | assert (d != 0)((void) sizeof ((d != 0) ? 1 : 0), __extension__ ({ if (d != 0 ) ; else __assert_fail ("d != 0", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c" , 418, __extension__ __PRETTY_FUNCTION__); })); | |||
419 | } else { | |||
420 | if (! src->owns_pixmap) { | |||
421 | XGCValues gcv; | |||
422 | ||||
423 | gcv.subwindow_mode = IncludeInferiors1; | |||
424 | XChangeGC (dst->display->display, gc, GCSubwindowMode(1L<<15), &gcv); | |||
425 | } | |||
426 | d = src->drawable; | |||
427 | } | |||
428 | ||||
429 | if (boxes->num_boxes == 1) { | |||
430 | int x1 = _cairo_fixed_integer_part (boxes->chunks.base[0].p1.x); | |||
431 | int y1 = _cairo_fixed_integer_part (boxes->chunks.base[0].p1.y); | |||
432 | int x2 = _cairo_fixed_integer_part (boxes->chunks.base[0].p2.x); | |||
433 | int y2 = _cairo_fixed_integer_part (boxes->chunks.base[0].p2.y); | |||
434 | ||||
435 | XCopyArea (dst->dpy, d, dst->drawable, gc, | |||
436 | x1 + dx, y1 + dy, | |||
437 | x2 - x1, y2 - y1, | |||
438 | x1, y1); | |||
439 | } else { | |||
440 | /* We can only have a single control for subwindow_mode on the | |||
441 | * GC. If we have a Window destination, we need to set ClipByChildren, | |||
442 | * but if we have a Window source, we need IncludeInferiors. If we have | |||
443 | * both a Window destination and source, we must fallback. There is | |||
444 | * no convenient way to detect if a drawable is a Pixmap or Window, | |||
445 | * therefore we can only rely on those surfaces that we created | |||
446 | * ourselves to be Pixmaps, and treat everything else as a potential | |||
447 | * Window. | |||
448 | */ | |||
449 | if (src == dst || (!src->owns_pixmap && !dst->owns_pixmap)) { | |||
450 | for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { | |||
451 | for (i = 0; i < chunk->count; i++) { | |||
452 | int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x); | |||
453 | int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y); | |||
454 | int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x); | |||
455 | int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y); | |||
456 | XCopyArea (dst->dpy, d, dst->drawable, gc, | |||
457 | x1 + dx, y1 + dy, | |||
458 | x2 - x1, y2 - y1, | |||
459 | x1, y1); | |||
460 | } | |||
461 | } | |||
462 | } else { | |||
463 | XRectangle stack_rects[CAIRO_STACK_ARRAY_LENGTH (XRectangle)((512 * sizeof (int)) / sizeof(XRectangle))]; | |||
464 | XRectangle *rects = stack_rects; | |||
465 | ||||
466 | if (boxes->num_boxes > ARRAY_LENGTH (stack_rects)((int) (sizeof (stack_rects) / sizeof (stack_rects[0])))) { | |||
467 | rects = _cairo_malloc_ab (boxes->num_boxes, sizeof (XRectangle)); | |||
468 | if (unlikely (rects == NULL)(__builtin_expect (!!(rects == ((void*)0)), 0))) | |||
469 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); | |||
470 | } | |||
471 | ||||
472 | j = 0; | |||
473 | for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { | |||
474 | for (i = 0; i < chunk->count; i++) { | |||
475 | int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x); | |||
476 | int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y); | |||
477 | int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x); | |||
478 | int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y); | |||
479 | ||||
480 | rects[j].x = x1; | |||
481 | rects[j].y = y1; | |||
482 | rects[j].width = x2 - x1; | |||
483 | rects[j].height = y2 - y1; | |||
484 | j++; | |||
485 | } | |||
486 | } | |||
487 | assert (j == boxes->num_boxes)((void) sizeof ((j == boxes->num_boxes) ? 1 : 0), __extension__ ({ if (j == boxes->num_boxes) ; else __assert_fail ("j == boxes->num_boxes" , "/root/firefox-clang/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c" , 487, __extension__ __PRETTY_FUNCTION__); })); | |||
488 | ||||
489 | XSetClipRectangles (dst->dpy, gc, 0, 0, rects, j, Unsorted0); | |||
490 | ||||
491 | XCopyArea (dst->dpy, d, dst->drawable, gc, | |||
492 | extents->x + dx, extents->y + dy, | |||
493 | extents->width, extents->height, | |||
494 | extents->x, extents->y); | |||
495 | ||||
496 | XSetClipMask (dst->dpy, gc, None0L); | |||
497 | ||||
498 | if (rects != stack_rects) | |||
499 | free (rects); | |||
500 | } | |||
501 | } | |||
502 | ||||
503 | if (src->fallback && src->shm->damage->dirty) { | |||
504 | _cairo_xlib_shm_surface_mark_active (src->shm); | |||
505 | } else if (! src->owns_pixmap) { | |||
506 | XGCValues gcv; | |||
507 | ||||
508 | gcv.subwindow_mode = ClipByChildren0; | |||
509 | XChangeGC (dst->display->display, gc, GCSubwindowMode(1L<<15), &gcv); | |||
510 | } | |||
511 | ||||
512 | _cairo_xlib_surface_put_gc (dst->display, dst, gc); | |||
513 | release (dst); | |||
514 | return CAIRO_STATUS_SUCCESS; | |||
515 | } | |||
516 | ||||
517 | static int | |||
518 | _render_operator (cairo_operator_t op) | |||
519 | { | |||
520 | switch (op) { | |||
521 | case CAIRO_OPERATOR_CLEAR: | |||
522 | return PictOpClear0; | |||
523 | ||||
524 | case CAIRO_OPERATOR_SOURCE: | |||
525 | return PictOpSrc1; | |||
526 | case CAIRO_OPERATOR_OVER: | |||
527 | return PictOpOver3; | |||
528 | case CAIRO_OPERATOR_IN: | |||
529 | return PictOpIn5; | |||
530 | case CAIRO_OPERATOR_OUT: | |||
531 | return PictOpOut7; | |||
532 | case CAIRO_OPERATOR_ATOP: | |||
533 | return PictOpAtop9; | |||
534 | ||||
535 | case CAIRO_OPERATOR_DEST: | |||
536 | return PictOpDst2; | |||
537 | case CAIRO_OPERATOR_DEST_OVER: | |||
538 | return PictOpOverReverse4; | |||
539 | case CAIRO_OPERATOR_DEST_IN: | |||
540 | return PictOpInReverse6; | |||
541 | case CAIRO_OPERATOR_DEST_OUT: | |||
542 | return PictOpOutReverse8; | |||
543 | case CAIRO_OPERATOR_DEST_ATOP: | |||
544 | return PictOpAtopReverse10; | |||
545 | ||||
546 | case CAIRO_OPERATOR_XOR: | |||
547 | return PictOpXor11; | |||
548 | case CAIRO_OPERATOR_ADD: | |||
549 | return PictOpAdd12; | |||
550 | case CAIRO_OPERATOR_SATURATE: | |||
551 | return PictOpSaturate13; | |||
552 | ||||
553 | case CAIRO_OPERATOR_MULTIPLY: | |||
554 | return PictOpMultiply0x30; | |||
555 | case CAIRO_OPERATOR_SCREEN: | |||
556 | return PictOpScreen0x31; | |||
557 | case CAIRO_OPERATOR_OVERLAY: | |||
558 | return PictOpOverlay0x32; | |||
559 | case CAIRO_OPERATOR_DARKEN: | |||
560 | return PictOpDarken0x33; | |||
561 | case CAIRO_OPERATOR_LIGHTEN: | |||
562 | return PictOpLighten0x34; | |||
563 | case CAIRO_OPERATOR_COLOR_DODGE: | |||
564 | return PictOpColorDodge0x35; | |||
565 | case CAIRO_OPERATOR_COLOR_BURN: | |||
566 | return PictOpColorBurn0x36; | |||
567 | case CAIRO_OPERATOR_HARD_LIGHT: | |||
568 | return PictOpHardLight0x37; | |||
569 | case CAIRO_OPERATOR_SOFT_LIGHT: | |||
570 | return PictOpSoftLight0x38; | |||
571 | case CAIRO_OPERATOR_DIFFERENCE: | |||
572 | return PictOpDifference0x39; | |||
573 | case CAIRO_OPERATOR_EXCLUSION: | |||
574 | return PictOpExclusion0x3a; | |||
575 | case CAIRO_OPERATOR_HSL_HUE: | |||
576 | return PictOpHSLHue0x3b; | |||
577 | case CAIRO_OPERATOR_HSL_SATURATION: | |||
578 | return PictOpHSLSaturation0x3c; | |||
579 | case CAIRO_OPERATOR_HSL_COLOR: | |||
580 | return PictOpHSLColor0x3d; | |||
581 | case CAIRO_OPERATOR_HSL_LUMINOSITY: | |||
582 | return PictOpHSLLuminosity0x3e; | |||
583 | ||||
584 | default: | |||
585 | ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if (!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c" , 585, __extension__ __PRETTY_FUNCTION__); })); } while (0); | |||
586 | return PictOpOver3; | |||
587 | } | |||
588 | } | |||
589 | ||||
590 | static cairo_bool_t | |||
591 | fill_reduces_to_source (cairo_operator_t op, | |||
592 | const cairo_color_t *color, | |||
593 | cairo_xlib_surface_t *dst) | |||
594 | { | |||
595 | if (dst->base.is_clear || CAIRO_COLOR_IS_OPAQUE (color)(((color)->alpha_short) >= 0xff00)) { | |||
596 | if (op == CAIRO_OPERATOR_OVER) | |||
597 | return TRUE1; | |||
598 | if (op == CAIRO_OPERATOR_ADD) | |||
599 | return (dst->base.content & CAIRO_CONTENT_COLOR) == 0; | |||
600 | } | |||
601 | ||||
602 | return FALSE0; | |||
603 | } | |||
604 | ||||
605 | static cairo_int_status_t | |||
606 | fill_rectangles (void *abstract_surface, | |||
607 | cairo_operator_t op, | |||
608 | const cairo_color_t *color, | |||
609 | cairo_rectangle_int_t *rects, | |||
610 | int num_rects) | |||
611 | { | |||
612 | cairo_xlib_surface_t *dst = abstract_surface; | |||
613 | XRenderColor render_color; | |||
614 | int i; | |||
615 | ||||
616 | //X_DEBUG ((display->display, "fill_rectangles (dst=%x)", (unsigned int) surface->drawable)); | |||
617 | ||||
618 | if (fill_reduces_to_source (op, color, dst)) | |||
619 | op = CAIRO_OPERATOR_SOURCE; | |||
620 | ||||
621 | if (!CAIRO_RENDER_HAS_FILL_RECTANGLES(dst->display)((((dst->display))->render_major > 0) || ((((dst-> display))->render_major == 0) && (((dst->display ))->render_minor >= 1)))) { | |||
622 | cairo_int_status_t status; | |||
623 | ||||
624 | status = CAIRO_INT_STATUS_UNSUPPORTED; | |||
625 | if (op == CAIRO_OPERATOR_SOURCE) | |||
626 | status = _cairo_xlib_core_fill_rectangles (dst, color, num_rects, rects); | |||
627 | return status; | |||
628 | } | |||
629 | ||||
630 | render_color.red = color->red_short; | |||
631 | render_color.green = color->green_short; | |||
632 | render_color.blue = color->blue_short; | |||
633 | render_color.alpha = color->alpha_short; | |||
634 | ||||
635 | _cairo_xlib_surface_ensure_picture (dst); | |||
636 | if (num_rects == 1) { | |||
637 | /* Take advantage of the protocol compaction that libXrender performs | |||
638 | * to amalgamate sequences of XRenderFillRectangle(). | |||
639 | */ | |||
640 | XRenderFillRectangle_void_consume (dst->dpy, | |||
641 | _render_operator (op), | |||
642 | dst->picture, | |||
643 | &render_color, | |||
644 | rects->x, rects->y, | |||
645 | rects->width, rects->height); | |||
646 | } else { | |||
647 | XRectangle stack_xrects[CAIRO_STACK_ARRAY_LENGTH (XRectangle)((512 * sizeof (int)) / sizeof(XRectangle))]; | |||
648 | XRectangle *xrects = stack_xrects; | |||
649 | ||||
650 | if (num_rects > ARRAY_LENGTH (stack_xrects)((int) (sizeof (stack_xrects) / sizeof (stack_xrects[0])))) { | |||
651 | xrects = _cairo_malloc_ab (num_rects, sizeof (XRectangle)); | |||
652 | if (unlikely (xrects == NULL)(__builtin_expect (!!(xrects == ((void*)0)), 0))) | |||
653 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); | |||
654 | } | |||
655 | ||||
656 | for (i = 0; i < num_rects; i++) { | |||
657 | xrects[i].x = rects[i].x; | |||
658 | xrects[i].y = rects[i].y; | |||
659 | xrects[i].width = rects[i].width; | |||
660 | xrects[i].height = rects[i].height; | |||
661 | } | |||
662 | ||||
663 | XRenderFillRectangles_void_consume (dst->dpy, | |||
664 | _render_operator (op), | |||
665 | dst->picture, | |||
666 | &render_color, xrects, num_rects); | |||
667 | ||||
668 | if (xrects != stack_xrects) | |||
669 | free (xrects); | |||
670 | } | |||
671 | ||||
672 | return CAIRO_STATUS_SUCCESS; | |||
673 | } | |||
674 | ||||
675 | static cairo_int_status_t | |||
676 | fill_boxes (void *abstract_surface, | |||
677 | cairo_operator_t op, | |||
678 | const cairo_color_t *color, | |||
679 | cairo_boxes_t *boxes) | |||
680 | { | |||
681 | cairo_xlib_surface_t *dst = abstract_surface; | |||
682 | XRenderColor render_color; | |||
683 | ||||
684 | if (fill_reduces_to_source (op, color, dst)) | |||
685 | op = CAIRO_OPERATOR_SOURCE; | |||
686 | ||||
687 | if (!CAIRO_RENDER_HAS_FILL_RECTANGLES(dst->display)((((dst->display))->render_major > 0) || ((((dst-> display))->render_major == 0) && (((dst->display ))->render_minor >= 1)))) { | |||
688 | cairo_int_status_t status; | |||
689 | ||||
690 | status = CAIRO_INT_STATUS_UNSUPPORTED; | |||
691 | if (op == CAIRO_OPERATOR_SOURCE) | |||
692 | status = _cairo_xlib_core_fill_boxes (dst, color, boxes); | |||
693 | return status; | |||
694 | } | |||
695 | ||||
696 | render_color.red = color->red_short; | |||
697 | render_color.green = color->green_short; | |||
698 | render_color.blue = color->blue_short; | |||
699 | render_color.alpha = color->alpha_short; | |||
700 | ||||
701 | _cairo_xlib_surface_ensure_picture (dst); | |||
702 | if (boxes->num_boxes == 1) { | |||
703 | int x1 = _cairo_fixed_integer_part (boxes->chunks.base[0].p1.x); | |||
704 | int y1 = _cairo_fixed_integer_part (boxes->chunks.base[0].p1.y); | |||
705 | int x2 = _cairo_fixed_integer_part (boxes->chunks.base[0].p2.x); | |||
706 | int y2 = _cairo_fixed_integer_part (boxes->chunks.base[0].p2.y); | |||
707 | ||||
708 | /* Take advantage of the protocol compaction that libXrender performs | |||
709 | * to amalgamate sequences of XRenderFillRectangle(). | |||
710 | */ | |||
711 | XRenderFillRectangle_void_consume (dst->dpy, | |||
712 | _render_operator (op), | |||
713 | dst->picture, | |||
714 | &render_color, | |||
715 | x1, y1, | |||
716 | x2 - x1, y2 - y1); | |||
717 | } else { | |||
718 | XRectangle stack_xrects[CAIRO_STACK_ARRAY_LENGTH (XRectangle)((512 * sizeof (int)) / sizeof(XRectangle))]; | |||
719 | XRectangle *xrects = stack_xrects; | |||
720 | struct _cairo_boxes_chunk *chunk; | |||
721 | int i, j; | |||
722 | ||||
723 | if (boxes->num_boxes > ARRAY_LENGTH (stack_xrects)((int) (sizeof (stack_xrects) / sizeof (stack_xrects[0])))) { | |||
724 | xrects = _cairo_malloc_ab (boxes->num_boxes, sizeof (XRectangle)); | |||
725 | if (unlikely (xrects == NULL)(__builtin_expect (!!(xrects == ((void*)0)), 0))) | |||
726 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); | |||
727 | } | |||
728 | ||||
729 | j = 0; | |||
730 | for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { | |||
731 | for (i = 0; i < chunk->count; i++) { | |||
732 | int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x); | |||
733 | int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y); | |||
734 | int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x); | |||
735 | int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y); | |||
736 | ||||
737 | xrects[j].x = x1; | |||
738 | xrects[j].y = y1; | |||
739 | xrects[j].width = x2 - x1; | |||
740 | xrects[j].height = y2 - y1; | |||
741 | j++; | |||
742 | } | |||
743 | } | |||
744 | ||||
745 | XRenderFillRectangles_void_consume (dst->dpy, | |||
746 | _render_operator (op), | |||
747 | dst->picture, | |||
748 | &render_color, xrects, j); | |||
749 | ||||
750 | if (xrects != stack_xrects) | |||
751 | free (xrects); | |||
752 | } | |||
753 | ||||
754 | return CAIRO_STATUS_SUCCESS; | |||
755 | } | |||
756 | ||||
757 | #if 0 | |||
758 | check_composite () | |||
759 | operation = _categorize_composite_operation (dst, op, src_pattern, | |||
760 | mask_pattern != NULL((void*)0)); | |||
761 | if (operation == DO_UNSUPPORTED) | |||
762 | return UNSUPPORTED ("unsupported operation"); | |||
763 | ||||
764 | //X_DEBUG ((display->display, "composite (dst=%x)", (unsigned int) dst->drawable)); | |||
765 | ||||
766 | operation = _recategorize_composite_operation (dst, op, src, &src_attr, | |||
767 | mask_pattern != NULL((void*)0)); | |||
768 | if (operation == DO_UNSUPPORTED) { | |||
769 | status = UNSUPPORTED ("unsupported operation"); | |||
770 | goto BAIL; | |||
771 | } | |||
772 | #endif | |||
773 | ||||
774 | static cairo_int_status_t | |||
775 | composite (void *abstract_dst, | |||
776 | cairo_operator_t op, | |||
777 | cairo_surface_t *abstract_src, | |||
778 | cairo_surface_t *abstract_mask, | |||
779 | int src_x, | |||
780 | int src_y, | |||
781 | int mask_x, | |||
782 | int mask_y, | |||
783 | int dst_x, | |||
784 | int dst_y, | |||
785 | unsigned int width, | |||
786 | unsigned int height) | |||
787 | { | |||
788 | cairo_xlib_surface_t *dst = abstract_dst; | |||
789 | cairo_xlib_source_t *src = (cairo_xlib_source_t *)abstract_src; | |||
790 | ||||
791 | op = _render_operator (op); | |||
792 | ||||
793 | _cairo_xlib_surface_ensure_picture (dst); | |||
794 | if (abstract_mask) { | |||
795 | cairo_xlib_source_t *mask = (cairo_xlib_source_t *)abstract_mask; | |||
796 | ||||
797 | XRenderComposite_void_consume (dst->dpy, op, | |||
798 | src->picture, mask->picture, dst->picture, | |||
799 | src_x, src_y, | |||
800 | mask_x, mask_y, | |||
801 | dst_x, dst_y, | |||
802 | width, height); | |||
803 | } else { | |||
804 | XRenderComposite_void_consume (dst->dpy, op, | |||
805 | src->picture, 0, dst->picture, | |||
806 | src_x, src_y, | |||
807 | 0, 0, | |||
808 | dst_x, dst_y, | |||
809 | width, height); | |||
810 | } | |||
811 | ||||
812 | return CAIRO_STATUS_SUCCESS; | |||
813 | } | |||
814 | ||||
815 | static cairo_int_status_t | |||
816 | lerp (void *abstract_dst, | |||
817 | cairo_surface_t *abstract_src, | |||
818 | cairo_surface_t *abstract_mask, | |||
819 | int src_x, | |||
820 | int src_y, | |||
821 | int mask_x, | |||
822 | int mask_y, | |||
823 | int dst_x, | |||
824 | int dst_y, | |||
825 | unsigned int width, | |||
826 | unsigned int height) | |||
827 | { | |||
828 | cairo_xlib_surface_t *dst = abstract_dst; | |||
829 | cairo_xlib_source_t *src = (cairo_xlib_source_t *)abstract_src; | |||
830 | cairo_xlib_source_t *mask = (cairo_xlib_source_t *)abstract_mask; | |||
831 | ||||
832 | _cairo_xlib_surface_ensure_picture (dst); | |||
833 | XRenderComposite_void_consume (dst->dpy, PictOpOutReverse8, | |||
834 | mask->picture, None0L, dst->picture, | |||
835 | mask_x, mask_y, | |||
836 | 0, 0, | |||
837 | dst_x, dst_y, | |||
838 | width, height); | |||
839 | XRenderComposite_void_consume (dst->dpy, PictOpAdd12, | |||
840 | src->picture, mask->picture, dst->picture, | |||
841 | src_x, src_y, | |||
842 | mask_x, mask_y, | |||
843 | dst_x, dst_y, | |||
844 | width, height); | |||
845 | ||||
846 | return CAIRO_STATUS_SUCCESS; | |||
847 | } | |||
848 | ||||
849 | static cairo_int_status_t | |||
850 | composite_boxes (void *abstract_dst, | |||
851 | cairo_operator_t op, | |||
852 | cairo_surface_t *abstract_src, | |||
853 | cairo_surface_t *abstract_mask, | |||
854 | int src_x, | |||
855 | int src_y, | |||
856 | int mask_x, | |||
857 | int mask_y, | |||
858 | int dst_x, | |||
859 | int dst_y, | |||
860 | cairo_boxes_t *boxes, | |||
861 | const cairo_rectangle_int_t *extents) | |||
862 | { | |||
863 | cairo_xlib_surface_t *dst = abstract_dst; | |||
864 | Picture src = ((cairo_xlib_source_t *)abstract_src)->picture; | |||
865 | Picture mask = abstract_mask ? ((cairo_xlib_source_t *)abstract_mask)->picture : 0; | |||
866 | XRectangle stack_rects[CAIRO_STACK_ARRAY_LENGTH (XRectangle)((512 * sizeof (int)) / sizeof(XRectangle))]; | |||
867 | XRectangle *rects = stack_rects; | |||
868 | struct _cairo_boxes_chunk *chunk; | |||
869 | int i, j; | |||
870 | ||||
871 | op = _render_operator (op); | |||
872 | _cairo_xlib_surface_ensure_picture (dst); | |||
873 | if (boxes->num_boxes == 1) { | |||
874 | int x1 = _cairo_fixed_integer_part (boxes->chunks.base[0].p1.x); | |||
875 | int y1 = _cairo_fixed_integer_part (boxes->chunks.base[0].p1.y); | |||
876 | int x2 = _cairo_fixed_integer_part (boxes->chunks.base[0].p2.x); | |||
877 | int y2 = _cairo_fixed_integer_part (boxes->chunks.base[0].p2.y); | |||
878 | ||||
879 | XRenderComposite_void_consume (dst->dpy, op, | |||
880 | src, mask, dst->picture, | |||
881 | x1 + src_x, y1 + src_y, | |||
882 | x1 + mask_x, y1 + mask_y, | |||
883 | x1 - dst_x, y1 - dst_y, | |||
884 | x2 - x1, y2 - y1); | |||
885 | return CAIRO_STATUS_SUCCESS; | |||
886 | } | |||
887 | ||||
888 | if (boxes->num_boxes > ARRAY_LENGTH (stack_rects)((int) (sizeof (stack_rects) / sizeof (stack_rects[0])))) { | |||
889 | rects = _cairo_malloc_ab (boxes->num_boxes, sizeof (XRectangle)); | |||
890 | if (unlikely (rects == NULL)(__builtin_expect (!!(rects == ((void*)0)), 0))) | |||
891 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); | |||
892 | } | |||
893 | ||||
894 | j = 0; | |||
895 | for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { | |||
896 | for (i = 0; i < chunk->count; i++) { | |||
897 | int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x); | |||
898 | int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y); | |||
899 | int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x); | |||
900 | int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y); | |||
901 | ||||
902 | rects[j].x = x1 - dst_x; | |||
903 | rects[j].y = y1 - dst_y; | |||
904 | rects[j].width = x2 - x1; | |||
905 | rects[j].height = y2 - y1; | |||
906 | j++; | |||
907 | } | |||
908 | } | |||
909 | assert (j == boxes->num_boxes)((void) sizeof ((j == boxes->num_boxes) ? 1 : 0), __extension__ ({ if (j == boxes->num_boxes) ; else __assert_fail ("j == boxes->num_boxes" , "/root/firefox-clang/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c" , 909, __extension__ __PRETTY_FUNCTION__); })); | |||
910 | ||||
911 | XRenderSetPictureClipRectangles_void_consume (dst->dpy, | |||
912 | dst->picture, | |||
913 | 0, 0, | |||
914 | rects, j); | |||
915 | if (rects != stack_rects) | |||
916 | free (rects); | |||
917 | ||||
918 | XRenderComposite_void_consume (dst->dpy, op, | |||
919 | src, mask, dst->picture, | |||
920 | extents->x + src_x, extents->y + src_y, | |||
921 | extents->x + mask_x, extents->y + mask_y, | |||
922 | extents->x - dst_x, extents->y - dst_y, | |||
923 | extents->width, extents->height); | |||
924 | ||||
925 | set_clip_region (dst, NULL((void*)0)); | |||
926 | ||||
927 | return CAIRO_STATUS_SUCCESS; | |||
928 | } | |||
929 | ||||
930 | /* font rendering */ | |||
931 | ||||
932 | void | |||
933 | _cairo_xlib_font_close (cairo_xlib_font_t *priv) | |||
934 | { | |||
935 | cairo_xlib_display_t *display = (cairo_xlib_display_t *)priv->base.key; | |||
936 | int i; | |||
937 | ||||
938 | /* XXX All I really want is to do is zap my glyphs... */ | |||
939 | _cairo_scaled_font_reset_cache (priv->font); | |||
940 | ||||
941 | for (i = 0; i < NUM_GLYPHSETS; i++) { | |||
942 | cairo_xlib_font_glyphset_t *info; | |||
943 | ||||
944 | info = &priv->glyphset[i]; | |||
945 | if (info->glyphset) | |||
946 | XRenderFreeGlyphSet_void_consume_free (display->display, info->glyphset); | |||
947 | } | |||
948 | ||||
949 | /* XXX locking */ | |||
950 | cairo_list_del (&priv->link); | |||
951 | cairo_list_del (&priv->base.link); | |||
952 | free (priv); | |||
953 | } | |||
954 | ||||
955 | static void | |||
956 | _cairo_xlib_font_fini (cairo_scaled_font_private_t *abstract_private, | |||
957 | cairo_scaled_font_t *font) | |||
958 | { | |||
959 | cairo_xlib_font_t *priv = (cairo_xlib_font_t *) abstract_private; | |||
960 | cairo_status_t status; | |||
961 | cairo_xlib_display_t *display; | |||
962 | int i; | |||
963 | ||||
964 | cairo_list_del (&priv->base.link); | |||
965 | cairo_list_del (&priv->link); | |||
966 | ||||
967 | status = _cairo_xlib_display_acquire (priv->device, &display); | |||
968 | if (unlikely (status)(__builtin_expect (!!(status), 0))) /* this should be impossible but leak just in case */ | |||
969 | goto BAIL; | |||
970 | ||||
971 | for (i = 0; i < NUM_GLYPHSETS; i++) { | |||
972 | cairo_xlib_font_glyphset_t *info; | |||
973 | ||||
974 | info = &priv->glyphset[i]; | |||
975 | if (info->glyphset) | |||
976 | XRenderFreeGlyphSet_void_consume_free (display->display, info->glyphset); | |||
977 | } | |||
978 | ||||
979 | cairo_device_release_moz_cairo_device_release (&display->base); | |||
980 | BAIL: | |||
981 | cairo_device_destroy_moz_cairo_device_destroy (priv->device); | |||
982 | free (priv); | |||
983 | } | |||
984 | ||||
985 | static cairo_xlib_font_t * | |||
986 | _cairo_xlib_font_create (cairo_xlib_display_t *display, | |||
987 | cairo_scaled_font_t *font) | |||
988 | { | |||
989 | cairo_xlib_font_t *priv; | |||
990 | int i; | |||
991 | ||||
992 | priv = _cairo_malloc (sizeof (cairo_xlib_font_t))((sizeof (cairo_xlib_font_t)) != 0 ? malloc(sizeof (cairo_xlib_font_t )) : ((void*)0)); | |||
993 | if (unlikely (priv == NULL)(__builtin_expect (!!(priv == ((void*)0)), 0))) | |||
994 | return NULL((void*)0); | |||
995 | ||||
996 | _cairo_scaled_font_attach_private (font, &priv->base, display, | |||
997 | _cairo_xlib_font_fini); | |||
998 | ||||
999 | priv->device = cairo_device_reference_moz_cairo_device_reference (&display->base); | |||
1000 | priv->font = font; | |||
1001 | cairo_list_add (&priv->link, &display->fonts); | |||
1002 | ||||
1003 | for (i = 0; i < NUM_GLYPHSETS; i++) { | |||
1004 | cairo_xlib_font_glyphset_t *info = &priv->glyphset[i]; | |||
1005 | switch (i) { | |||
1006 | case GLYPHSET_INDEX_ARGB32: info->format = CAIRO_FORMAT_ARGB32; break; | |||
1007 | case GLYPHSET_INDEX_A8: info->format = CAIRO_FORMAT_A8; break; | |||
1008 | case GLYPHSET_INDEX_A1: info->format = CAIRO_FORMAT_A1; break; | |||
1009 | default: ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if (!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c" , 1009, __extension__ __PRETTY_FUNCTION__); })); } while (0); break; | |||
1010 | } | |||
1011 | info->xrender_format = NULL((void*)0); | |||
1012 | info->glyphset = None0L; | |||
1013 | info->to_free.count = 0; | |||
1014 | } | |||
1015 | ||||
1016 | return priv; | |||
1017 | } | |||
1018 | ||||
1019 | static int | |||
1020 | _cairo_xlib_get_glyphset_index_for_format (cairo_format_t format) | |||
1021 | { | |||
1022 | if (format == CAIRO_FORMAT_A8) | |||
1023 | return GLYPHSET_INDEX_A8; | |||
1024 | if (format == CAIRO_FORMAT_A1) | |||
1025 | return GLYPHSET_INDEX_A1; | |||
1026 | ||||
1027 | assert (format == CAIRO_FORMAT_ARGB32)((void) sizeof ((format == CAIRO_FORMAT_ARGB32) ? 1 : 0), __extension__ ({ if (format == CAIRO_FORMAT_ARGB32) ; else __assert_fail ( "format == CAIRO_FORMAT_ARGB32", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c" , 1027, __extension__ __PRETTY_FUNCTION__); })); | |||
1028 | return GLYPHSET_INDEX_ARGB32; | |||
1029 | } | |||
1030 | ||||
1031 | static inline cairo_xlib_font_t * | |||
1032 | _cairo_xlib_font_get (const cairo_xlib_display_t *display, | |||
1033 | cairo_scaled_font_t *font) | |||
1034 | { | |||
1035 | return (cairo_xlib_font_t *)_cairo_scaled_font_find_private (font, display); | |||
1036 | } | |||
1037 | ||||
1038 | typedef struct { | |||
1039 | cairo_scaled_glyph_private_t base; | |||
1040 | ||||
1041 | ||||
1042 | cairo_xlib_font_glyphset_t *glyphset; | |||
1043 | } cairo_xlib_glyph_private_t; | |||
1044 | ||||
1045 | static void | |||
1046 | _cairo_xlib_glyph_fini (cairo_scaled_glyph_private_t *glyph_private, | |||
1047 | cairo_scaled_glyph_t *glyph, | |||
1048 | cairo_scaled_font_t *font) | |||
1049 | { | |||
1050 | cairo_xlib_glyph_private_t *priv = (cairo_xlib_glyph_private_t *)glyph_private; | |||
1051 | ||||
1052 | if (! font->finished) { | |||
1053 | cairo_xlib_font_t *font_private; | |||
1054 | struct _cairo_xlib_font_glyphset_free_glyphs *to_free; | |||
1055 | cairo_xlib_font_glyphset_t *info; | |||
1056 | ||||
1057 | font_private = _cairo_xlib_font_get (glyph_private->key, font); | |||
1058 | assert (font_private)((void) sizeof ((font_private) ? 1 : 0), __extension__ ({ if ( font_private) ; else __assert_fail ("font_private", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c" , 1058, __extension__ __PRETTY_FUNCTION__); })); | |||
1059 | ||||
1060 | info = priv->glyphset; | |||
1061 | to_free = &info->to_free; | |||
1062 | if (to_free->count == ARRAY_LENGTH (to_free->indices)((int) (sizeof (to_free->indices) / sizeof (to_free->indices [0])))) { | |||
1063 | cairo_xlib_display_t *display; | |||
1064 | ||||
1065 | if (_cairo_xlib_display_acquire (font_private->device, | |||
1066 | &display) == CAIRO_STATUS_SUCCESS) { | |||
1067 | XRenderFreeGlyphs_void_consume (display->display, | |||
1068 | info->glyphset, | |||
1069 | to_free->indices, | |||
1070 | to_free->count); | |||
1071 | cairo_device_release_moz_cairo_device_release (&display->base); | |||
1072 | } | |||
1073 | ||||
1074 | to_free->count = 0; | |||
1075 | } | |||
1076 | ||||
1077 | to_free->indices[to_free->count++] = glyph->hash_entry.hash; | |||
1078 | } | |||
1079 | ||||
1080 | cairo_list_del (&glyph_private->link); | |||
1081 | free (glyph_private); | |||
1082 | } | |||
1083 | ||||
1084 | static cairo_status_t | |||
1085 | _cairo_xlib_glyph_attach (cairo_xlib_display_t *display, | |||
1086 | cairo_scaled_glyph_t *glyph, | |||
1087 | cairo_xlib_font_glyphset_t *info) | |||
1088 | { | |||
1089 | cairo_xlib_glyph_private_t *priv; | |||
1090 | ||||
1091 | priv = _cairo_malloc (sizeof (*priv))((sizeof (*priv)) != 0 ? malloc(sizeof (*priv)) : ((void*)0)); | |||
1092 | if (unlikely (priv == NULL)(__builtin_expect (!!(priv == ((void*)0)), 0))) | |||
1093 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); | |||
1094 | ||||
1095 | _cairo_scaled_glyph_attach_private (glyph, &priv->base, display, | |||
1096 | _cairo_xlib_glyph_fini); | |||
1097 | priv->glyphset = info; | |||
1098 | ||||
1099 | glyph->dev_private = info; | |||
1100 | glyph->dev_private_key = display; | |||
1101 | return CAIRO_STATUS_SUCCESS; | |||
1102 | } | |||
1103 | ||||
1104 | static cairo_xlib_font_glyphset_t * | |||
1105 | _cairo_xlib_font_get_glyphset_info_for_format (cairo_xlib_display_t *display, | |||
1106 | cairo_scaled_font_t *font, | |||
1107 | cairo_format_t format) | |||
1108 | { | |||
1109 | cairo_xlib_font_t *priv; | |||
1110 | cairo_xlib_font_glyphset_t *info; | |||
1111 | int glyphset_index; | |||
1112 | ||||
1113 | glyphset_index = _cairo_xlib_get_glyphset_index_for_format (format); | |||
1114 | ||||
1115 | priv = _cairo_xlib_font_get (display, font); | |||
1116 | if (priv == NULL((void*)0)) { | |||
1117 | priv = _cairo_xlib_font_create (display, font); | |||
1118 | if (priv == NULL((void*)0)) | |||
1119 | return NULL((void*)0); | |||
1120 | } | |||
1121 | ||||
1122 | info = &priv->glyphset[glyphset_index]; | |||
1123 | if (info->glyphset == None0L) { | |||
1124 | info->xrender_format = | |||
1125 | _cairo_xlib_display_get_xrender_format (display, info->format); | |||
1126 | info->glyphset = XRenderCreateGlyphSet_int_consume (display->display, | |||
1127 | info->xrender_format); | |||
1128 | } | |||
1129 | ||||
1130 | return info; | |||
1131 | } | |||
1132 | ||||
1133 | static cairo_bool_t | |||
1134 | has_pending_free_glyph (cairo_xlib_font_glyphset_t *info, | |||
1135 | unsigned long glyph_index) | |||
1136 | { | |||
1137 | struct _cairo_xlib_font_glyphset_free_glyphs *to_free; | |||
1138 | int i; | |||
1139 | ||||
1140 | to_free = &info->to_free; | |||
1141 | for (i = 0; i < to_free->count; i++) { | |||
1142 | if (to_free->indices[i] == glyph_index) { | |||
1143 | to_free->count--; | |||
1144 | memmove (&to_free->indices[i], | |||
1145 | &to_free->indices[i+1], | |||
1146 | (to_free->count - i) * sizeof (to_free->indices[0])); | |||
1147 | return TRUE1; | |||
1148 | } | |||
1149 | } | |||
1150 | ||||
1151 | return FALSE0; | |||
1152 | } | |||
1153 | ||||
1154 | static cairo_xlib_font_glyphset_t * | |||
1155 | find_pending_free_glyph (cairo_xlib_display_t *display, | |||
1156 | cairo_scaled_font_t *font, | |||
1157 | unsigned long glyph_index, | |||
1158 | cairo_image_surface_t *surface) | |||
1159 | { | |||
1160 | cairo_xlib_font_t *priv; | |||
1161 | int i; | |||
1162 | ||||
1163 | priv = _cairo_xlib_font_get (display, font); | |||
1164 | if (priv == NULL((void*)0)) | |||
1165 | return NULL((void*)0); | |||
1166 | ||||
1167 | if (surface != NULL((void*)0)) { | |||
1168 | i = _cairo_xlib_get_glyphset_index_for_format (surface->format); | |||
1169 | if (has_pending_free_glyph (&priv->glyphset[i], glyph_index)) | |||
1170 | return &priv->glyphset[i]; | |||
1171 | } else { | |||
1172 | for (i = 0; i < NUM_GLYPHSETS; i++) { | |||
1173 | if (has_pending_free_glyph (&priv->glyphset[i], glyph_index)) | |||
1174 | return &priv->glyphset[i]; | |||
1175 | } | |||
1176 | } | |||
1177 | ||||
1178 | return NULL((void*)0); | |||
1179 | } | |||
1180 | ||||
1181 | static cairo_status_t | |||
1182 | _cairo_xlib_surface_add_glyph (cairo_xlib_display_t *display, | |||
1183 | cairo_scaled_font_t *font, | |||
1184 | cairo_scaled_glyph_t **pscaled_glyph) | |||
1185 | { | |||
1186 | XGlyphInfo glyph_info; | |||
1187 | unsigned long glyph_index; | |||
1188 | unsigned char *data; | |||
1189 | cairo_status_t status = CAIRO_STATUS_SUCCESS; | |||
1190 | cairo_scaled_glyph_t *glyph = *pscaled_glyph; | |||
1191 | cairo_image_surface_t *glyph_surface = glyph->surface; | |||
1192 | cairo_bool_t already_had_glyph_surface; | |||
1193 | cairo_xlib_font_glyphset_t *info; | |||
1194 | ||||
1195 | glyph_index = glyph->hash_entry.hash; | |||
1196 | ||||
1197 | /* check to see if we have a pending XRenderFreeGlyph for this glyph */ | |||
1198 | info = find_pending_free_glyph (display, font, glyph_index, glyph_surface); | |||
1199 | if (info != NULL((void*)0)) | |||
1200 | return _cairo_xlib_glyph_attach (display, glyph, info); | |||
1201 | ||||
1202 | if (glyph_surface == NULL((void*)0)) { | |||
1203 | status = _cairo_scaled_glyph_lookup (font, | |||
1204 | glyph_index, | |||
1205 | CAIRO_SCALED_GLYPH_INFO_METRICS | | |||
1206 | CAIRO_SCALED_GLYPH_INFO_SURFACE, | |||
1207 | NULL((void*)0), /* foreground color */ | |||
1208 | pscaled_glyph); | |||
1209 | if (unlikely (status)(__builtin_expect (!!(status), 0))) | |||
1210 | return status; | |||
1211 | ||||
1212 | glyph = *pscaled_glyph; | |||
1213 | glyph_surface = glyph->surface; | |||
1214 | already_had_glyph_surface = FALSE0; | |||
1215 | } else { | |||
1216 | already_had_glyph_surface = TRUE1; | |||
1217 | } | |||
1218 | ||||
1219 | info = _cairo_xlib_font_get_glyphset_info_for_format (display, font, | |||
1220 | glyph_surface->format); | |||
1221 | ||||
1222 | #if 0 | |||
1223 | /* If the glyph surface has zero height or width, we create | |||
1224 | * a clear 1x1 surface, to avoid various X server bugs. | |||
1225 | */ | |||
1226 | if (glyph_surface->width == 0 || glyph_surface->height == 0) { | |||
1227 | cairo_surface_t *tmp_surface; | |||
1228 | ||||
1229 | tmp_surface = cairo_image_surface_create_moz_cairo_image_surface_create (info->format, 1, 1); | |||
1230 | status = tmp_surface->status; | |||
1231 | if (unlikely (status)(__builtin_expect (!!(status), 0))) | |||
1232 | goto BAIL; | |||
1233 | ||||
1234 | tmp_surface->device_transform = glyph_surface->base.device_transform; | |||
1235 | tmp_surface->device_transform_inverse = glyph_surface->base.device_transform_inverse; | |||
1236 | ||||
1237 | glyph_surface = (cairo_image_surface_t *) tmp_surface; | |||
1238 | } | |||
1239 | #endif | |||
1240 | ||||
1241 | /* If the glyph format does not match the font format, then we | |||
1242 | * create a temporary surface for the glyph image with the font's | |||
1243 | * format. | |||
1244 | */ | |||
1245 | if (glyph_surface->format != info->format) { | |||
1246 | cairo_surface_pattern_t pattern; | |||
1247 | cairo_surface_t *tmp_surface; | |||
1248 | ||||
1249 | tmp_surface = cairo_image_surface_create_moz_cairo_image_surface_create (info->format, | |||
1250 | glyph_surface->width, | |||
1251 | glyph_surface->height); | |||
1252 | status = tmp_surface->status; | |||
1253 | if (unlikely (status)(__builtin_expect (!!(status), 0))) | |||
1254 | goto BAIL; | |||
1255 | ||||
1256 | tmp_surface->device_transform = glyph_surface->base.device_transform; | |||
1257 | tmp_surface->device_transform_inverse = glyph_surface->base.device_transform_inverse; | |||
1258 | ||||
1259 | _cairo_pattern_init_for_surface (&pattern, &glyph_surface->base); | |||
1260 | status = _cairo_surface_paint (tmp_surface, | |||
1261 | CAIRO_OPERATOR_SOURCE, &pattern.base, | |||
1262 | NULL((void*)0)); | |||
1263 | _cairo_pattern_fini (&pattern.base); | |||
1264 | ||||
1265 | glyph_surface = (cairo_image_surface_t *) tmp_surface; | |||
1266 | ||||
1267 | if (unlikely (status)(__builtin_expect (!!(status), 0))) | |||
1268 | goto BAIL; | |||
1269 | } | |||
1270 | ||||
1271 | /* XXX: FRAGILE: We're ignore device_transform scaling here. A bug? */ | |||
1272 | glyph_info.x = _cairo_lround (glyph_surface->base.device_transform.x0); | |||
1273 | glyph_info.y = _cairo_lround (glyph_surface->base.device_transform.y0); | |||
1274 | glyph_info.width = glyph_surface->width; | |||
1275 | glyph_info.height = glyph_surface->height; | |||
1276 | glyph_info.xOff = glyph->x_advance; | |||
1277 | glyph_info.yOff = glyph->y_advance; | |||
1278 | ||||
1279 | data = glyph_surface->data; | |||
1280 | ||||
1281 | /* flip formats around */ | |||
1282 | switch (_cairo_xlib_get_glyphset_index_for_format (glyph->surface->format)) { | |||
1283 | case GLYPHSET_INDEX_A1: | |||
1284 | /* local bitmaps are always stored with bit == byte */ | |||
1285 | if (_cairo_is_little_endian() != (BitmapBitOrder (display->display)(((_XPrivDisplay)(display->display))->bitmap_bit_order) == LSBFirst0)) { | |||
1286 | int c = glyph_surface->stride * glyph_surface->height; | |||
1287 | unsigned char *d; | |||
1288 | unsigned char *new, *n; | |||
1289 | ||||
1290 | if (c == 0) | |||
1291 | break; | |||
1292 | ||||
1293 | new = _cairo_malloc (c)((c) != 0 ? malloc(c) : ((void*)0)); | |||
1294 | if (!new) { | |||
1295 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); | |||
1296 | goto BAIL; | |||
1297 | } | |||
1298 | n = new; | |||
1299 | d = data; | |||
1300 | do { | |||
1301 | char b = *d++; | |||
1302 | b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55); | |||
1303 | b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33); | |||
1304 | b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f); | |||
1305 | *n++ = b; | |||
1306 | } while (--c); | |||
1307 | data = new; | |||
1308 | } | |||
1309 | break; | |||
1310 | case GLYPHSET_INDEX_A8: | |||
1311 | break; | |||
1312 | case GLYPHSET_INDEX_ARGB32: | |||
1313 | if (_cairo_is_little_endian() != (ImageByteOrder (display->display)(((_XPrivDisplay)(display->display))->byte_order) == LSBFirst0)) { | |||
1314 | unsigned int c = glyph_surface->stride * glyph_surface->height / 4; | |||
1315 | const uint32_t *d; | |||
1316 | uint32_t *new, *n; | |||
1317 | ||||
1318 | if (c == 0) | |||
1319 | break; | |||
1320 | ||||
1321 | new = _cairo_malloc (4 * c)((4 * c) != 0 ? malloc(4 * c) : ((void*)0)); | |||
1322 | if (unlikely (new == NULL)(__builtin_expect (!!(new == ((void*)0)), 0))) { | |||
1323 | status = _cairo_error (CAIRO_STATUS_NO_MEMORY); | |||
1324 | goto BAIL; | |||
1325 | } | |||
1326 | n = new; | |||
1327 | d = (uint32_t *) data; | |||
1328 | do { | |||
1329 | *n++ = bswap_32 (*d)__bswap_32 (*d); | |||
1330 | d++; | |||
1331 | } while (--c); | |||
1332 | data = (uint8_t *) new; | |||
1333 | } | |||
1334 | break; | |||
1335 | default: | |||
1336 | ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if (!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c" , 1336, __extension__ __PRETTY_FUNCTION__); })); } while (0); | |||
1337 | break; | |||
1338 | } | |||
1339 | /* XXX assume X server wants pixman padding. Xft assumes this as well */ | |||
1340 | ||||
1341 | XRenderAddGlyphs_void_consume (display->display, info->glyphset, | |||
1342 | &glyph_index, &glyph_info, 1, | |||
1343 | (char *) data, | |||
1344 | glyph_surface->stride * glyph_surface->height); | |||
1345 | ||||
1346 | if (data != glyph_surface->data) | |||
1347 | free (data); | |||
1348 | ||||
1349 | status = _cairo_xlib_glyph_attach (display, glyph, info); | |||
1350 | ||||
1351 | BAIL: | |||
1352 | if (glyph_surface != glyph->surface) | |||
1353 | cairo_surface_destroy_moz_cairo_surface_destroy (&glyph_surface->base); | |||
1354 | ||||
1355 | /* if the scaled glyph didn't already have a surface attached | |||
1356 | * to it, release the created surface now that we have it | |||
1357 | * uploaded to the X server. If the surface has already been | |||
1358 | * there (eg. because image backend requested it), leave it in | |||
1359 | * the cache | |||
1360 | */ | |||
1361 | if (!already_had_glyph_surface) | |||
1362 | _cairo_scaled_glyph_set_surface (glyph, font, NULL((void*)0)); | |||
1363 | ||||
1364 | return status; | |||
1365 | } | |||
1366 | ||||
1367 | typedef void (*cairo_xrender_composite_text_func_t) | |||
1368 | (Display *dpy, | |||
1369 | int op, | |||
1370 | Picture src, | |||
1371 | Picture dst, | |||
1372 | _Xconstconst XRenderPictFormat *maskFormat, | |||
1373 | int xSrc, | |||
1374 | int ySrc, | |||
1375 | int xDst, | |||
1376 | int yDst, | |||
1377 | _Xconstconst XGlyphElt8 *elts, | |||
1378 | int nelt); | |||
1379 | ||||
1380 | /* Build a struct of the same size of #cairo_glyph_t that can be used both as | |||
1381 | * an input glyph with double coordinates, and as "working" glyph with | |||
1382 | * integer from-current-point offsets. */ | |||
1383 | typedef union { | |||
1384 | cairo_glyph_t d; | |||
1385 | unsigned long index; | |||
1386 | struct { | |||
1387 | unsigned long index; | |||
1388 | int x; | |||
1389 | int y; | |||
1390 | } i; | |||
1391 | } cairo_xlib_glyph_t; | |||
1392 | ||||
1393 | /* compile-time assert that #cairo_xlib_glyph_t is the same size as #cairo_glyph_t */ | |||
1394 | COMPILE_TIME_ASSERT (sizeof (cairo_xlib_glyph_t) == sizeof (cairo_glyph_t))typedef int compile_time_assertion_at_line_1394_failed [(sizeof (cairo_xlib_glyph_t) == sizeof (cairo_glyph_t))?1:-1]; | |||
1395 | ||||
1396 | /* Start a new element for the first glyph, | |||
1397 | * or for any glyph that has unexpected position, | |||
1398 | * or if current element has too many glyphs | |||
1399 | * (Xrender limits each element to 252 glyphs, we limit them to 128) | |||
1400 | * | |||
1401 | * These same conditions need to be mirrored between | |||
1402 | * _cairo_xlib_surface_emit_glyphs and _emit_glyph_chunks | |||
1403 | */ | |||
1404 | #define _start_new_glyph_elt(count, glyph)(((count) & 127) == 0 || (glyph)->i.x || (glyph)->i .y) \ | |||
1405 | (((count) & 127) == 0 || (glyph)->i.x || (glyph)->i.y) | |||
1406 | ||||
1407 | static cairo_status_t | |||
1408 | _emit_glyphs_chunk (cairo_xlib_display_t *display, | |||
1409 | cairo_xlib_surface_t *dst, | |||
1410 | int dst_x, int dst_y, | |||
1411 | cairo_xlib_glyph_t *glyphs, | |||
1412 | int num_glyphs, | |||
1413 | cairo_scaled_font_t *font, | |||
1414 | cairo_bool_t use_mask, | |||
1415 | cairo_operator_t op, | |||
1416 | cairo_xlib_source_t *src, | |||
1417 | int src_x, int src_y, | |||
1418 | /* info for this chunk */ | |||
1419 | int num_elts, | |||
1420 | int width, | |||
1421 | cairo_xlib_font_glyphset_t *info) | |||
1422 | { | |||
1423 | /* Which XRenderCompositeText function to use */ | |||
1424 | cairo_xrender_composite_text_func_t composite_text_func; | |||
1425 | int size; | |||
1426 | ||||
1427 | /* Element buffer stuff */ | |||
1428 | XGlyphElt8 *elts; | |||
1429 | XGlyphElt8 stack_elts[CAIRO_STACK_ARRAY_LENGTH (XGlyphElt8)((512 * sizeof (int)) / sizeof(XGlyphElt8))]; | |||
1430 | ||||
1431 | /* Reuse the input glyph array for output char generation */ | |||
1432 | char *char8 = (char *) glyphs; | |||
1433 | unsigned short *char16 = (unsigned short *) glyphs; | |||
1434 | unsigned int *char32 = (unsigned int *) glyphs; | |||
1435 | ||||
1436 | int i; | |||
1437 | int nelt; /* Element index */ | |||
1438 | int n; /* Num output glyphs in current element */ | |||
1439 | int j; /* Num output glyphs so far */ | |||
1440 | ||||
1441 | switch (width) { | |||
1442 | case 1: | |||
1443 | /* don't cast the 8-variant, to catch possible mismatches */ | |||
1444 | composite_text_func = XRenderCompositeText8(cairo_xrender_composite_text_func_t) _void_consume; | |||
1445 | size = sizeof (char); | |||
1446 | break; | |||
1447 | case 2: | |||
1448 | composite_text_func = (cairo_xrender_composite_text_func_t) XRenderCompositeText16_void_consume; | |||
1449 | size = sizeof (unsigned short); | |||
1450 | break; | |||
1451 | default: | |||
1452 | case 4: | |||
1453 | composite_text_func = (cairo_xrender_composite_text_func_t) XRenderCompositeText32_void_consume; | |||
1454 | size = sizeof (unsigned int); | |||
1455 | } | |||
1456 | ||||
1457 | /* Allocate element array */ | |||
1458 | if (num_elts <= ARRAY_LENGTH (stack_elts)((int) (sizeof (stack_elts) / sizeof (stack_elts[0])))) { | |||
1459 | elts = stack_elts; | |||
1460 | } else { | |||
1461 | elts = _cairo_malloc_ab (num_elts, sizeof (XGlyphElt8)); | |||
1462 | if (unlikely (elts == NULL)(__builtin_expect (!!(elts == ((void*)0)), 0))) | |||
1463 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); | |||
1464 | } | |||
1465 | ||||
1466 | /* Fill them in */ | |||
1467 | nelt = 0; | |||
1468 | n = 0; | |||
1469 | j = 0; | |||
1470 | for (i = 0; i < num_glyphs; i++) { | |||
1471 | /* Start a new element for first output glyph, | |||
1472 | * or for any glyph that has unexpected position, | |||
1473 | * or if current element has too many glyphs. | |||
1474 | * | |||
1475 | * These same conditions are mirrored in _cairo_xlib_surface_emit_glyphs() | |||
1476 | */ | |||
1477 | if (_start_new_glyph_elt (j, &glyphs[i])(((j) & 127) == 0 || (&glyphs[i])->i.x || (&glyphs [i])->i.y)) { | |||
1478 | if (j) { | |||
1479 | elts[nelt].nchars = n; | |||
1480 | nelt++; | |||
1481 | n = 0; | |||
1482 | } | |||
1483 | elts[nelt].chars = char8 + size * j; | |||
1484 | elts[nelt].glyphset = info->glyphset; | |||
1485 | elts[nelt].xOff = glyphs[i].i.x; | |||
1486 | elts[nelt].yOff = glyphs[i].i.y; | |||
1487 | } | |||
1488 | ||||
1489 | switch (width) { | |||
1490 | case 1: char8 [j] = (char) glyphs[i].index; break; | |||
1491 | case 2: char16[j] = (unsigned short) glyphs[i].index; break; | |||
1492 | default: | |||
1493 | case 4: char32[j] = (unsigned int) glyphs[i].index; break; | |||
1494 | } | |||
1495 | ||||
1496 | n++; | |||
1497 | j++; | |||
1498 | } | |||
1499 | ||||
1500 | if (n) { | |||
1501 | elts[nelt].nchars = n; | |||
1502 | nelt++; | |||
1503 | } | |||
1504 | ||||
1505 | /* Check that we agree with _cairo_xlib_surface_emit_glyphs() on the | |||
1506 | * expected number of xGlyphElts. */ | |||
1507 | assert (nelt == num_elts)((void) sizeof ((nelt == num_elts) ? 1 : 0), __extension__ ({ if (nelt == num_elts) ; else __assert_fail ("nelt == num_elts" , "/root/firefox-clang/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c" , 1507, __extension__ __PRETTY_FUNCTION__); })); | |||
1508 | ||||
1509 | composite_text_func (display->display, op, | |||
1510 | src->picture, | |||
1511 | dst->picture, | |||
1512 | use_mask ? info->xrender_format : NULL((void*)0), | |||
1513 | src_x + elts[0].xOff + dst_x, | |||
1514 | src_y + elts[0].yOff + dst_y, | |||
1515 | elts[0].xOff, elts[0].yOff, | |||
1516 | (XGlyphElt8 *) elts, nelt); | |||
1517 | ||||
1518 | if (elts != stack_elts) | |||
1519 | free (elts); | |||
1520 | ||||
1521 | return CAIRO_STATUS_SUCCESS; | |||
1522 | } | |||
1523 | ||||
1524 | static cairo_int_status_t | |||
1525 | check_composite_glyphs (const cairo_composite_rectangles_t *extents, | |||
1526 | cairo_scaled_font_t *font, | |||
1527 | cairo_glyph_t *glyphs, | |||
1528 | int *num_glyphs) | |||
1529 | { | |||
1530 | cairo_xlib_surface_t *dst = (cairo_xlib_surface_t *)extents->surface; | |||
1531 | cairo_xlib_display_t *display = dst->display; | |||
1532 | int max_request_size, size; | |||
1533 | ||||
1534 | TRACE ((stderr, "%s\n", __FUNCTION__)); | |||
1535 | ||||
1536 | if (! CAIRO_RENDER_SUPPORTS_OPERATOR (display, extents->op)((extents->op) <= CAIRO_OPERATOR_SATURATE || (((((display ))->render_major > 0) || ((((display))->render_major == 0) && (((display))->render_minor >= 11))) && (extents->op) <= CAIRO_OPERATOR_HSL_LUMINOSITY))) | |||
1537 | return CAIRO_INT_STATUS_UNSUPPORTED; | |||
1538 | ||||
1539 | /* The glyph coordinates must be representable in an int16_t. | |||
1540 | * When possible, they will be expressed as an offset from the | |||
1541 | * previous glyph, otherwise they will be an offset from the | |||
1542 | * surface origin. If we can't guarantee this to be possible, | |||
1543 | * fallback. | |||
1544 | */ | |||
1545 | if (extents->bounded.x + extents->bounded.width > INT16_MAX(32767) || | |||
1546 | extents->bounded.y + extents->bounded.height> INT16_MAX(32767) || | |||
1547 | extents->bounded.x < INT16_MIN(-32767-1) || | |||
1548 | extents->bounded.y < INT16_MIN(-32767-1)) | |||
1549 | { | |||
1550 | return CAIRO_INT_STATUS_UNSUPPORTED; | |||
1551 | } | |||
1552 | ||||
1553 | /* Approximate the size of the largest glyph and fallback if we can not | |||
1554 | * upload it to the xserver. | |||
1555 | */ | |||
1556 | size = ceil (font->max_scale); | |||
1557 | size = 4 * size * size; | |||
1558 | max_request_size = (XExtendedMaxRequestSize (display->display) ? XExtendedMaxRequestSize (display->display) | |||
1559 | : XMaxRequestSize (display->display)) * 4 - | |||
1560 | sz_xRenderAddGlyphsReq12 - | |||
1561 | sz_xGlyphInfo12 - | |||
1562 | 8; | |||
1563 | if (size >= max_request_size) | |||
1564 | return CAIRO_INT_STATUS_UNSUPPORTED; | |||
1565 | ||||
1566 | return CAIRO_STATUS_SUCCESS; | |||
1567 | } | |||
1568 | ||||
1569 | /* sz_xGlyphtElt required alignment to a 32-bit boundary, so ensure we have | |||
1570 | * enough room for padding */ | |||
1571 | #define _cairo_sz_xGlyphElt(8 + 4) (sz_xGlyphElt8 + 4) | |||
1572 | ||||
1573 | #define PHASE(x)((int)(floor (4 * (x + 0.125)) - 4 * floor (x + 0.125))) ((int)(floor (4 * (x + 0.125)) - 4 * floor (x + 0.125))) | |||
1574 | #define POSITION(x)((int) floor (x + 0.125)) ((int) floor (x + 0.125)) | |||
1575 | ||||
1576 | static cairo_int_status_t | |||
1577 | composite_glyphs (void *surface, | |||
1578 | cairo_operator_t op, | |||
1579 | cairo_surface_t *_src, | |||
1580 | int src_x, | |||
1581 | int src_y, | |||
1582 | int dst_x, | |||
1583 | int dst_y, | |||
1584 | cairo_composite_glyphs_info_t *info) | |||
1585 | { | |||
1586 | cairo_xlib_surface_t *dst = surface; | |||
1587 | cairo_xlib_glyph_t *glyphs = (cairo_xlib_glyph_t *)info->glyphs; | |||
1588 | cairo_xlib_source_t *src = (cairo_xlib_source_t *)_src; | |||
1589 | cairo_xlib_display_t *display = dst->display; | |||
1590 | cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS; | |||
1591 | cairo_scaled_glyph_t *glyph; | |||
1592 | cairo_fixed_t x = dst_x, y = dst_y; | |||
1593 | cairo_xlib_font_glyphset_t *glyphset = NULL((void*)0), *this_glyphset_info; | |||
1594 | ||||
1595 | unsigned long max_index = 0; | |||
1596 | int width = 1; | |||
1597 | int num_elts = 0; | |||
1598 | int num_out_glyphs = 0; | |||
1599 | int num_glyphs = info->num_glyphs; | |||
1600 | ||||
1601 | int max_request_size = XMaxRequestSize (display->display) * 4 | |||
1602 | - MAX (sz_xRenderCompositeGlyphs8Req,((28) > (((28) > (28) ? (28) : (28))) ? (28) : (((28) > (28) ? (28) : (28)))) | |||
1603 | MAX(sz_xRenderCompositeGlyphs16Req,((28) > (((28) > (28) ? (28) : (28))) ? (28) : (((28) > (28) ? (28) : (28)))) | |||
1604 | sz_xRenderCompositeGlyphs32Req))((28) > (((28) > (28) ? (28) : (28))) ? (28) : (((28) > (28) ? (28) : (28)))); | |||
1605 | int request_size = 0; | |||
1606 | int i; | |||
1607 | ||||
1608 | op = _render_operator (op), | |||
1609 | _cairo_xlib_surface_ensure_picture (dst); | |||
1610 | for (i = 0; i < num_glyphs; i++) { | |||
1611 | unsigned long xphase, yphase; | |||
1612 | int this_x, this_y; | |||
1613 | int old_width; | |||
1614 | ||||
1615 | xphase = PHASE(glyphs[i].d.x)((int)(floor (4 * (glyphs[i].d.x + 0.125)) - 4 * floor (glyphs [i].d.x + 0.125))); | |||
1616 | yphase = PHASE(glyphs[i].d.y)((int)(floor (4 * (glyphs[i].d.y + 0.125)) - 4 * floor (glyphs [i].d.y + 0.125))); | |||
1617 | ||||
1618 | glyphs[i].index |= (xphase << 24) | (yphase << 26); | |||
1619 | ||||
1620 | status = _cairo_scaled_glyph_lookup (info->font, | |||
1621 | glyphs[i].index, | |||
1622 | CAIRO_SCALED_GLYPH_INFO_METRICS, | |||
1623 | NULL((void*)0), /* foreground color */ | |||
1624 | &glyph); | |||
1625 | if (unlikely (status)(__builtin_expect (!!(status), 0))) | |||
1626 | return status; | |||
1627 | ||||
1628 | this_x = POSITION (glyphs[i].d.x)((int) floor (glyphs[i].d.x + 0.125)); | |||
1629 | this_y = POSITION (glyphs[i].d.y)((int) floor (glyphs[i].d.y + 0.125)); | |||
1630 | ||||
1631 | /* Send unsent glyphs to the server */ | |||
1632 | if (glyph->dev_private_key != display) { | |||
1633 | status = _cairo_xlib_surface_add_glyph (display, info->font, &glyph); | |||
1634 | if (unlikely (status)(__builtin_expect (!!(status), 0))) | |||
1635 | return status; | |||
1636 | } | |||
1637 | ||||
1638 | this_glyphset_info = glyph->dev_private; | |||
1639 | if (!glyphset) | |||
1640 | glyphset = this_glyphset_info; | |||
1641 | ||||
1642 | /* The invariant here is that we can always flush the glyphs | |||
1643 | * accumulated before this one, using old_width, and they | |||
1644 | * would fit in the request. | |||
1645 | */ | |||
1646 | old_width = width; | |||
1647 | ||||
1648 | /* Update max glyph index */ | |||
1649 | if (glyphs[i].index > max_index) { | |||
1650 | max_index = glyphs[i].index; | |||
1651 | if (max_index >= 65536) | |||
1652 | width = 4; | |||
1653 | else if (max_index >= 256) | |||
1654 | width = 2; | |||
1655 | if (width != old_width) | |||
1656 | request_size += (width - old_width) * num_out_glyphs; | |||
1657 | } | |||
1658 | ||||
1659 | /* If we will pass the max request size by adding this glyph, | |||
1660 | * flush current glyphs. Note that we account for a | |||
1661 | * possible element being added below. | |||
1662 | * | |||
1663 | * Also flush if changing glyphsets, as Xrender limits one mask | |||
1664 | * format per request, so we can either break up, or use a | |||
1665 | * wide-enough mask format. We do the former. One reason to | |||
1666 | * prefer the latter is the fact that Xserver ADDs all glyphs | |||
1667 | * to the mask first, and then composes that to final surface, | |||
1668 | * though it's not a big deal. | |||
1669 | * | |||
1670 | * If the glyph has a coordinate which cannot be represented | |||
1671 | * as a 16-bit offset from the previous glyph, flush the | |||
1672 | * current chunk. The current glyph will be the first one in | |||
1673 | * the next chunk, thus its coordinates will be an offset from | |||
1674 | * the destination origin. This offset is guaranteed to be | |||
1675 | * representable as 16-bit offset (otherwise we would have | |||
1676 | * fallen back). | |||
1677 | */ | |||
1678 | if (request_size + width > max_request_size - _cairo_sz_xGlyphElt(8 + 4) || | |||
1679 | this_x - x > INT16_MAX(32767) || this_x - x < INT16_MIN(-32767-1) || | |||
1680 | this_y - y > INT16_MAX(32767) || this_y - y < INT16_MIN(-32767-1) || | |||
1681 | (this_glyphset_info != glyphset)) { | |||
1682 | status = _emit_glyphs_chunk (display, dst, dst_x, dst_y, | |||
1683 | glyphs, i, info->font, info->use_mask, | |||
1684 | op, src, src_x, src_y, | |||
1685 | num_elts, old_width, glyphset); | |||
1686 | if (unlikely (status)(__builtin_expect (!!(status), 0))) | |||
1687 | return status; | |||
1688 | ||||
1689 | glyphs += i; | |||
1690 | num_glyphs -= i; | |||
1691 | i = 0; | |||
1692 | max_index = glyphs[i].index; | |||
1693 | width = max_index < 256 ? 1 : max_index < 65536 ? 2 : 4; | |||
1694 | request_size = 0; | |||
1695 | num_elts = 0; | |||
1696 | num_out_glyphs = 0; | |||
1697 | x = y = 0; | |||
1698 | glyphset = this_glyphset_info; | |||
1699 | } | |||
1700 | ||||
1701 | /* Convert absolute glyph position to relative-to-current-point | |||
1702 | * position */ | |||
1703 | glyphs[i].i.x = this_x - x; | |||
1704 | glyphs[i].i.y = this_y - y; | |||
1705 | ||||
1706 | /* Start a new element for the first glyph, | |||
1707 | * or for any glyph that has unexpected position, | |||
1708 | * or if current element has too many glyphs. | |||
1709 | * | |||
1710 | * These same conditions are mirrored in _emit_glyphs_chunk(). | |||
1711 | */ | |||
1712 | if (_start_new_glyph_elt (num_out_glyphs, &glyphs[i])(((num_out_glyphs) & 127) == 0 || (&glyphs[i])->i. x || (&glyphs[i])->i.y)) { | |||
1713 | num_elts++; | |||
1714 | request_size += _cairo_sz_xGlyphElt(8 + 4); | |||
1715 | } | |||
1716 | ||||
1717 | /* adjust current-position */ | |||
1718 | x = this_x + glyph->x_advance; | |||
1719 | y = this_y + glyph->y_advance; | |||
1720 | ||||
1721 | num_out_glyphs++; | |||
1722 | request_size += width; | |||
1723 | } | |||
1724 | ||||
1725 | if (num_elts) { | |||
1726 | status = _emit_glyphs_chunk (display, dst, dst_x, dst_y, | |||
1727 | glyphs, i, info->font, info->use_mask, | |||
1728 | op, src, src_x, src_y, | |||
1729 | num_elts, width, glyphset); | |||
1730 | } | |||
1731 | ||||
1732 | return status; | |||
1733 | } | |||
1734 | ||||
1735 | const cairo_compositor_t * | |||
1736 | _cairo_xlib_mask_compositor_get (void) | |||
1737 | { | |||
1738 | static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT(0); | |||
1739 | static cairo_mask_compositor_t compositor; | |||
1740 | ||||
1741 | if (_cairo_atomic_init_once_enter(&once)) { | |||
1742 | _cairo_mask_compositor_init (&compositor, | |||
1743 | _cairo_xlib_fallback_compositor_get ()); | |||
1744 | ||||
1745 | compositor.acquire = acquire; | |||
1746 | compositor.release = release; | |||
1747 | compositor.set_clip_region = set_clip_region; | |||
1748 | compositor.pattern_to_surface = _cairo_xlib_source_create_for_pattern; | |||
1749 | compositor.draw_image_boxes = draw_image_boxes; | |||
1750 | compositor.fill_rectangles = fill_rectangles; | |||
1751 | compositor.fill_boxes = fill_boxes; | |||
1752 | compositor.copy_boxes = copy_boxes; | |||
1753 | compositor.check_composite = check_composite; | |||
1754 | compositor.composite = composite; | |||
1755 | //compositor.check_composite_boxes = check_composite_boxes; | |||
1756 | compositor.composite_boxes = composite_boxes; | |||
1757 | compositor.check_composite_glyphs = check_composite_glyphs; | |||
1758 | compositor.composite_glyphs = composite_glyphs; | |||
1759 | ||||
1760 | _cairo_atomic_init_once_leave(&once); | |||
1761 | } | |||
1762 | ||||
1763 | return &compositor.base; | |||
1764 | } | |||
1765 | ||||
1766 | #define CAIRO_FIXED_16_16_MIN-32768 -32768 | |||
1767 | #define CAIRO_FIXED_16_16_MAX32767 32767 | |||
1768 | ||||
1769 | static cairo_bool_t | |||
1770 | line_exceeds_16_16 (const cairo_line_t *line) | |||
1771 | { | |||
1772 | return | |||
1773 | line->p1.x < _cairo_fixed_from_int (CAIRO_FIXED_16_16_MIN-32768) || | |||
1774 | line->p1.x > _cairo_fixed_from_int (CAIRO_FIXED_16_16_MAX32767) || | |||
1775 | line->p2.x < _cairo_fixed_from_int (CAIRO_FIXED_16_16_MIN-32768) || | |||
1776 | line->p2.x > _cairo_fixed_from_int (CAIRO_FIXED_16_16_MAX32767) || | |||
1777 | line->p1.y < _cairo_fixed_from_int (CAIRO_FIXED_16_16_MIN-32768) || | |||
1778 | line->p1.y > _cairo_fixed_from_int (CAIRO_FIXED_16_16_MAX32767) || | |||
1779 | line->p2.y < _cairo_fixed_from_int (CAIRO_FIXED_16_16_MIN-32768) || | |||
1780 | line->p2.y > _cairo_fixed_from_int (CAIRO_FIXED_16_16_MAX32767); | |||
1781 | } | |||
1782 | ||||
1783 | static void | |||
1784 | project_line_x_onto_16_16 (const cairo_line_t *line, | |||
1785 | cairo_fixed_t top, | |||
1786 | cairo_fixed_t bottom, | |||
1787 | XLineFixed *out) | |||
1788 | { | |||
1789 | cairo_point_double_t p1, p2; | |||
1790 | double m; | |||
1791 | ||||
1792 | p1.x = _cairo_fixed_to_double (line->p1.x); | |||
1793 | p1.y = _cairo_fixed_to_double (line->p1.y); | |||
1794 | ||||
1795 | p2.x = _cairo_fixed_to_double (line->p2.x); | |||
1796 | p2.y = _cairo_fixed_to_double (line->p2.y); | |||
1797 | ||||
1798 | m = (p2.x - p1.x) / (p2.y - p1.y); | |||
1799 | out->p1.x = _cairo_fixed_16_16_from_double (p1.x + m * _cairo_fixed_to_double (top - line->p1.y)); | |||
1800 | out->p2.x = _cairo_fixed_16_16_from_double (p1.x + m * _cairo_fixed_to_double (bottom - line->p1.y)); | |||
1801 | } | |||
1802 | #if 0 | |||
1803 | static cairo_int_status_T | |||
1804 | check_composite_trapezoids () | |||
1805 | { | |||
1806 | operation = _categorize_composite_operation (dst, op, pattern, TRUE1); | |||
1807 | if (operation == DO_UNSUPPORTED) | |||
1808 | return UNSUPPORTED ("unsupported operation"); | |||
1809 | ||||
1810 | operation = _recategorize_composite_operation (dst, op, src, | |||
1811 | &attributes, TRUE1); | |||
1812 | if (operation == DO_UNSUPPORTED) { | |||
1813 | status = UNSUPPORTED ("unsupported operation"); | |||
1814 | goto BAIL; | |||
1815 | } | |||
1816 | ||||
1817 | } | |||
1818 | #endif | |||
1819 | ||||
1820 | static cairo_int_status_t | |||
1821 | composite_traps (void *abstract_dst, | |||
1822 | cairo_operator_t op, | |||
1823 | cairo_surface_t *abstract_src, | |||
1824 | int src_x, | |||
1825 | int src_y, | |||
1826 | int dst_x, | |||
1827 | int dst_y, | |||
1828 | const cairo_rectangle_int_t *extents, | |||
1829 | cairo_antialias_t antialias, | |||
1830 | cairo_traps_t *traps) | |||
1831 | { | |||
1832 | cairo_xlib_surface_t *dst = abstract_dst; | |||
1833 | cairo_xlib_display_t *display = dst->display; | |||
1834 | cairo_xlib_source_t *src = (cairo_xlib_source_t *)abstract_src; | |||
1835 | XRenderPictFormat *pict_format; | |||
1836 | XTrapezoid xtraps_stack[CAIRO_STACK_ARRAY_LENGTH (XTrapezoid)((512 * sizeof (int)) / sizeof(XTrapezoid))]; | |||
1837 | XTrapezoid *xtraps = xtraps_stack; | |||
1838 | int dx, dy; | |||
1839 | int i; | |||
1840 | ||||
1841 | //X_DEBUG ((display->display, "composite_trapezoids (dst=%x)", (unsigned int) dst->drawable)); | |||
1842 | ||||
1843 | if (traps->num_traps == 0) | |||
1844 | return CAIRO_STATUS_SUCCESS; | |||
1845 | ||||
1846 | if (dst->base.is_clear && | |||
1847 | (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD)) | |||
1848 | { | |||
1849 | op = CAIRO_OPERATOR_SOURCE; | |||
1850 | } | |||
1851 | ||||
1852 | pict_format = | |||
1853 | _cairo_xlib_display_get_xrender_format (display, | |||
1854 | antialias == CAIRO_ANTIALIAS_NONE ? CAIRO_FORMAT_A1 : CAIRO_FORMAT_A8); | |||
1855 | ||||
1856 | if (traps->num_traps > ARRAY_LENGTH (xtraps_stack)((int) (sizeof (xtraps_stack) / sizeof (xtraps_stack[0])))) { | |||
1857 | xtraps = _cairo_malloc_ab (traps->num_traps, sizeof (XTrapezoid)); | |||
1858 | if (unlikely (xtraps == NULL)(__builtin_expect (!!(xtraps == ((void*)0)), 0))) | |||
1859 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); | |||
1860 | } | |||
1861 | ||||
1862 | dx = -dst_x << 16; | |||
1863 | dy = -dst_y << 16; | |||
1864 | for (i = 0; i < traps->num_traps; i++) { | |||
1865 | cairo_trapezoid_t *t = &traps->traps[i]; | |||
1866 | ||||
1867 | /* top/bottom will be clamped to surface bounds */ | |||
1868 | xtraps[i].top = _cairo_fixed_to_16_16(t->top) + dy; | |||
1869 | xtraps[i].bottom = _cairo_fixed_to_16_16(t->bottom) + dy; | |||
1870 | ||||
1871 | /* However, all the other coordinates will have been left untouched so | |||
1872 | * as not to introduce numerical error. Recompute them if they | |||
1873 | * exceed the 16.16 limits. | |||
1874 | */ | |||
1875 | if (unlikely (line_exceeds_16_16 (&t->left))(__builtin_expect (!!(line_exceeds_16_16 (&t->left)), 0 ))) { | |||
1876 | project_line_x_onto_16_16 (&t->left, t->top, t->bottom, | |||
1877 | &xtraps[i].left); | |||
1878 | xtraps[i].left.p1.x += dx; | |||
1879 | xtraps[i].left.p2.x += dx; | |||
1880 | xtraps[i].left.p1.y = xtraps[i].top; | |||
1881 | xtraps[i].left.p2.y = xtraps[i].bottom; | |||
1882 | } else { | |||
1883 | xtraps[i].left.p1.x = _cairo_fixed_to_16_16(t->left.p1.x) + dx; | |||
1884 | xtraps[i].left.p1.y = _cairo_fixed_to_16_16(t->left.p1.y) + dy; | |||
1885 | xtraps[i].left.p2.x = _cairo_fixed_to_16_16(t->left.p2.x) + dx; | |||
1886 | xtraps[i].left.p2.y = _cairo_fixed_to_16_16(t->left.p2.y) + dy; | |||
1887 | } | |||
1888 | ||||
1889 | if (unlikely (line_exceeds_16_16 (&t->right))(__builtin_expect (!!(line_exceeds_16_16 (&t->right)), 0))) { | |||
1890 | project_line_x_onto_16_16 (&t->right, t->top, t->bottom, | |||
1891 | &xtraps[i].right); | |||
1892 | xtraps[i].right.p1.x += dx; | |||
1893 | xtraps[i].right.p2.x += dx; | |||
1894 | xtraps[i].right.p1.y = xtraps[i].top; | |||
1895 | xtraps[i].right.p2.y = xtraps[i].bottom; | |||
1896 | } else { | |||
1897 | xtraps[i].right.p1.x = _cairo_fixed_to_16_16(t->right.p1.x) + dx; | |||
1898 | xtraps[i].right.p1.y = _cairo_fixed_to_16_16(t->right.p1.y) + dy; | |||
1899 | xtraps[i].right.p2.x = _cairo_fixed_to_16_16(t->right.p2.x) + dx; | |||
1900 | xtraps[i].right.p2.y = _cairo_fixed_to_16_16(t->right.p2.y) + dy; | |||
1901 | } | |||
1902 | } | |||
1903 | ||||
1904 | if (xtraps[0].left.p1.y < xtraps[0].left.p2.y) { | |||
1905 | src_x += _cairo_fixed_16_16_floor (xtraps[0].left.p1.x); | |||
1906 | src_y += _cairo_fixed_16_16_floor (xtraps[0].left.p1.y); | |||
1907 | } else { | |||
1908 | src_x += _cairo_fixed_16_16_floor (xtraps[0].left.p2.x); | |||
1909 | src_y += _cairo_fixed_16_16_floor (xtraps[0].left.p2.y); | |||
1910 | } | |||
1911 | src_x += dst_x; | |||
1912 | src_y += dst_y; | |||
1913 | ||||
1914 | _cairo_xlib_surface_ensure_picture (dst); | |||
1915 | _cairo_xlib_surface_set_precision (dst, antialias); | |||
1916 | XRenderCompositeTrapezoids_void_consume (dst->dpy, | |||
1917 | _render_operator (op), | |||
1918 | src->picture, dst->picture, | |||
1919 | pict_format, | |||
1920 | src_x, src_y, | |||
1921 | xtraps, traps->num_traps); | |||
1922 | ||||
1923 | if (xtraps != xtraps_stack) | |||
1924 | free (xtraps); | |||
1925 | ||||
1926 | return CAIRO_STATUS_SUCCESS; | |||
1927 | } | |||
1928 | ||||
1929 | static cairo_int_status_t | |||
1930 | composite_tristrip (void *abstract_dst, | |||
1931 | cairo_operator_t op, | |||
1932 | cairo_surface_t *abstract_src, | |||
1933 | int src_x, | |||
1934 | int src_y, | |||
1935 | int dst_x, | |||
1936 | int dst_y, | |||
1937 | const cairo_rectangle_int_t *extents, | |||
1938 | cairo_antialias_t antialias, | |||
1939 | cairo_tristrip_t *strip) | |||
1940 | { | |||
1941 | cairo_xlib_surface_t *dst = abstract_dst; | |||
1942 | cairo_xlib_display_t *display = dst->display; | |||
1943 | cairo_xlib_source_t *src = (cairo_xlib_source_t *)abstract_src; | |||
1944 | XRenderPictFormat *pict_format; | |||
1945 | XPointFixed points_stack[CAIRO_STACK_ARRAY_LENGTH (XPointFixed)((512 * sizeof (int)) / sizeof(XPointFixed))]; | |||
1946 | XPointFixed *points = points_stack; | |||
1947 | int dx, dy; | |||
1948 | int i; | |||
1949 | ||||
1950 | //X_DEBUG ((display->display, "composite_trapezoids (dst=%x)", (unsigned int) dst->drawable)); | |||
1951 | ||||
1952 | pict_format = | |||
1953 | _cairo_xlib_display_get_xrender_format (display, | |||
1954 | antialias == CAIRO_ANTIALIAS_NONE ? CAIRO_FORMAT_A1 : CAIRO_FORMAT_A8); | |||
| ||||
1955 | ||||
1956 | if (strip->num_points > ARRAY_LENGTH (points_stack)((int) (sizeof (points_stack) / sizeof (points_stack[0])))) { | |||
1957 | points = _cairo_malloc_ab (strip->num_points, sizeof (XPointFixed)); | |||
1958 | if (unlikely (points == NULL)(__builtin_expect (!!(points == ((void*)0)), 0))) | |||
1959 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); | |||
1960 | } | |||
1961 | ||||
1962 | dx = -dst_x << 16; | |||
1963 | dy = -dst_y << 16; | |||
1964 | for (i = 0; i < strip->num_points; i++) { | |||
1965 | cairo_point_t *p = &strip->points[i]; | |||
1966 | ||||
1967 | points[i].x = _cairo_fixed_to_16_16(p->x) + dx; | |||
1968 | points[i].y = _cairo_fixed_to_16_16(p->y) + dy; | |||
1969 | } | |||
1970 | ||||
1971 | src_x += _cairo_fixed_16_16_floor (points[0].x) + dst_x; | |||
| ||||
1972 | src_y += _cairo_fixed_16_16_floor (points[0].y) + dst_y; | |||
1973 | ||||
1974 | _cairo_xlib_surface_ensure_picture (dst); | |||
1975 | _cairo_xlib_surface_set_precision (dst, antialias); | |||
1976 | XRenderCompositeTriStrip_void_consume (dst->dpy, | |||
1977 | _render_operator (op), | |||
1978 | src->picture, dst->picture, | |||
1979 | pict_format, | |||
1980 | src_x, src_y, | |||
1981 | points, strip->num_points); | |||
1982 | ||||
1983 | if (points != points_stack) | |||
1984 | free (points); | |||
1985 | ||||
1986 | return CAIRO_STATUS_SUCCESS; | |||
1987 | } | |||
1988 | ||||
1989 | const cairo_compositor_t * | |||
1990 | _cairo_xlib_traps_compositor_get (void) | |||
1991 | { | |||
1992 | static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT(0); | |||
1993 | static cairo_traps_compositor_t compositor; | |||
1994 | ||||
1995 | if (_cairo_atomic_init_once_enter(&once)) { | |||
1996 | _cairo_traps_compositor_init (&compositor, | |||
1997 | _cairo_xlib_mask_compositor_get ()); | |||
1998 | ||||
1999 | compositor.acquire = acquire; | |||
2000 | compositor.release = release; | |||
2001 | compositor.set_clip_region = set_clip_region; | |||
2002 | compositor.pattern_to_surface = _cairo_xlib_source_create_for_pattern; | |||
2003 | compositor.draw_image_boxes = draw_image_boxes; | |||
2004 | compositor.copy_boxes = copy_boxes; | |||
2005 | compositor.fill_boxes = fill_boxes; | |||
2006 | compositor.check_composite = check_composite; | |||
2007 | compositor.composite = composite; | |||
2008 | compositor.lerp = lerp; | |||
2009 | //compositor.check_composite_boxes = check_composite_boxes; | |||
2010 | compositor.composite_boxes = composite_boxes; | |||
2011 | //compositor.check_composite_traps = check_composite_traps; | |||
2012 | compositor.composite_traps = composite_traps; | |||
2013 | //compositor.check_composite_tristrip = check_composite_tristrip; | |||
2014 | compositor.composite_tristrip = composite_tristrip; | |||
2015 | compositor.check_composite_glyphs = check_composite_glyphs; | |||
2016 | compositor.composite_glyphs = composite_glyphs; | |||
2017 | ||||
2018 | _cairo_atomic_init_once_leave(&once); | |||
2019 | } | |||
2020 | ||||
2021 | return &compositor.base; | |||
2022 | } | |||
2023 | ||||
2024 | #endif /* !CAIRO_HAS_XLIB_XCB_FUNCTIONS */ |