Bug Summary

File:root/firefox-clang/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c
Warning:line 1513, column 11
The right operand of '+' is a garbage value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cairo-xlib-render-compositor.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/cairo/cairo/src -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/cairo/cairo/src -resource-dir /usr/lib/llvm-21/lib/clang/21 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D HAVE_FT_LOAD_SFNT_TABLE -D PACKAGE_VERSION="moz" -D PACKAGE_BUGREPORT="http://bugzilla.mozilla.org/" -D CAIRO_HAS_PTHREAD -D _GNU_SOURCE -D MOZ_TREE_PIXMAN -D SIZEOF_VOID_P=__SIZEOF_POINTER__ -D SIZEOF_INT=__SIZEOF_INT__ -D SIZEOF_LONG=__SIZEOF_LONG__ -D SIZEOF_LONG_LONG=__SIZEOF_LONG_LONG__ -D HAVE_UINT64_T -D HAVE_CXX11_ATOMIC_PRIMITIVES -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/gfx/cairo/cairo/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/cairo/cairo/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/freetype2 -I /usr/include/libpng16 -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-enum-compare -Wno-int-to-pointer-cast -Wno-int-conversion -Wno-incompatible-pointer-types -Wno-sign-compare -Wno-type-limits -Wno-missing-field-initializers -Wno-conversion -Wno-narrowing -Wno-switch -Wno-unused -Wno-unused-variable -Wno-error=uninitialized -Wno-absolute-value -Wno-deprecated-register -Wno-incompatible-pointer-types -Wno-macro-redefined -Wno-shift-negative-value -Wno-tautological-compare -Wno-tautological-constant-out-of-range-compare -Wno-unreachable-code -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-26-231904-1820671-1 -x c /root/firefox-clang/gfx/cairo/cairo/src/cairo-xlib-render-compositor.c
1/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2/* cairo - a vector graphics library with display and print output
3 *
4 * Copyright © 2002 University of Southern California
5 * Copyright © 2005 Red Hat, Inc.
6 * 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
58static cairo_int_status_t
59check_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
69static cairo_int_status_t
70acquire (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
83static cairo_int_status_t
84release (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
94static cairo_int_status_t
95set_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
140static cairo_int_status_t
141copy_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
220static cairo_bool_t
221boxes_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
242static cairo_int_status_t
243draw_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
360draw_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
379out:
380 cairo_surface_destroy_moz_cairo_surface_destroy (&shm->base);
381 return status;
382}
383
384static cairo_int_status_t
385copy_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
517static 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
590static cairo_bool_t
591fill_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
605static cairo_int_status_t
606fill_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
675static cairo_int_status_t
676fill_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
758check_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
774static cairo_int_status_t
775composite (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
815static cairo_int_status_t
816lerp (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
849static cairo_int_status_t
850composite_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
932void
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
955static 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);
980BAIL:
981 cairo_device_destroy_moz_cairo_device_destroy (priv->device);
982 free (priv);
983}
984
985static 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
1019static 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
1031static 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
1038typedef struct {
1039 cairo_scaled_glyph_private_t base;
1040
1041
1042 cairo_xlib_font_glyphset_t *glyphset;
1043} cairo_xlib_glyph_private_t;
1044
1045static 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
1084static 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
1104static 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
1133static cairo_bool_t
1134has_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
1154static cairo_xlib_font_glyphset_t *
1155find_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
1181static 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
1367typedef 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. */
1383typedef 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 */
1394COMPILE_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
1407static 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) {
14
Control jumps to 'case 1:' at line 1442
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])))) {
16
Taking true branch
1459 elts = stack_elts;
15
Execution continues on line 1458
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++) {
17
Loop condition is false. Execution continues on line 1500
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
17.1
'n' is 0
) {
18
Taking false branch
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__); }))
;
19
Taking true branch
1508
1509 composite_text_func (display->display, op,
1510 src->picture,
1511 dst->picture,
1512 use_mask ? info->xrender_format : NULL((void*)0),
20
Assuming 'use_mask' is 0
21
'?' condition is false
1513 src_x + elts[0].xOff + dst_x,
22
The right operand of '+' is a garbage value
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
1524static cairo_int_status_t
1525check_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
1576static cairo_int_status_t
1577composite_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))))
1
'?' condition is false
2
'?' condition is false
3
'?' condition is false
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++) {
4
Assuming 'i' is < 'num_glyphs'
5
Loop condition is true. Entering loop body
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)))
6
Assuming 'status' is 0
7
Taking false branch
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) {
8
Assuming 'display' is equal to field 'dev_private_key'
9
Taking false branch
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
9.1
'glyphset' is null
)
10
Taking true branch
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) {
11
Assuming 'max_index' is >= field '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) ||
12
Assuming the condition is true
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,
13
Calling '_emit_glyphs_chunk'
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
1735const 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
1769static cairo_bool_t
1770line_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
1783static void
1784project_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
1803static cairo_int_status_T
1804check_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
1820static cairo_int_status_t
1821composite_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
1929static cairo_int_status_t
1930composite_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
1989const 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 */