Bug Summary

File:root/firefox-clang/gfx/cairo/cairo/src/cairo-traps-compositor.c
Warning:line 1574, column 5
Value stored to 'status' is never read

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-traps-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-traps-compositor.c
1/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
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 * Joonas Pihlaja <jpihlaja@cc.helsinki.fi>
39 * Chris Wilson <chris@chris-wilson.co.uk>
40 */
41
42#include "cairoint.h"
43
44#include "cairo-box-inline.h"
45#include "cairo-boxes-private.h"
46#include "cairo-clip-inline.h"
47#include "cairo-clip-private.h"
48#include "cairo-composite-rectangles-private.h"
49#include "cairo-compositor-private.h"
50#include "cairo-error-private.h"
51#include "cairo-image-surface-private.h"
52#include "cairo-pattern-inline.h"
53#include "cairo-paginated-private.h"
54#include "cairo-recording-surface-inline.h"
55#include "cairo-surface-subsurface-private.h"
56#include "cairo-surface-snapshot-inline.h"
57#include "cairo-surface-observer-private.h"
58#include "cairo-region-private.h"
59#include "cairo-spans-private.h"
60#include "cairo-traps-private.h"
61#include "cairo-tristrip-private.h"
62
63typedef cairo_int_status_t
64(*draw_func_t) (const cairo_traps_compositor_t *compositor,
65 cairo_surface_t *dst,
66 void *closure,
67 cairo_operator_t op,
68 cairo_surface_t *src,
69 int src_x,
70 int src_y,
71 int dst_x,
72 int dst_y,
73 const cairo_rectangle_int_t *extents,
74 cairo_clip_t *clip);
75
76static void do_unaligned_row(void (*blt)(void *closure,
77 int16_t x, int16_t y,
78 int16_t w, int16_t h,
79 uint16_t coverage),
80 void *closure,
81 const cairo_box_t *b,
82 int tx, int y, int h,
83 uint16_t coverage)
84{
85 int x1 = _cairo_fixed_integer_part (b->p1.x) - tx;
86 int x2 = _cairo_fixed_integer_part (b->p2.x) - tx;
87 if (x2 > x1) {
88 if (! _cairo_fixed_is_integer (b->p1.x)) {
89 blt(closure, x1, y, 1, h,
90 coverage * (256 - _cairo_fixed_fractional_part (b->p1.x)));
91 x1++;
92 }
93
94 if (x2 > x1)
95 blt(closure, x1, y, x2-x1, h, (coverage << 8) - (coverage >> 8));
96
97 if (! _cairo_fixed_is_integer (b->p2.x))
98 blt(closure, x2, y, 1, h,
99 coverage * _cairo_fixed_fractional_part (b->p2.x));
100 } else
101 blt(closure, x1, y, 1, h,
102 coverage * (b->p2.x - b->p1.x));
103}
104
105static void do_unaligned_box(void (*blt)(void *closure,
106 int16_t x, int16_t y,
107 int16_t w, int16_t h,
108 uint16_t coverage),
109 void *closure,
110 const cairo_box_t *b, int tx, int ty)
111{
112 int y1 = _cairo_fixed_integer_part (b->p1.y) - ty;
113 int y2 = _cairo_fixed_integer_part (b->p2.y) - ty;
114 if (y2 > y1) {
115 if (! _cairo_fixed_is_integer (b->p1.y)) {
116 do_unaligned_row(blt, closure, b, tx, y1, 1,
117 256 - _cairo_fixed_fractional_part (b->p1.y));
118 y1++;
119 }
120
121 if (y2 > y1)
122 do_unaligned_row(blt, closure, b, tx, y1, y2-y1, 256);
123
124 if (! _cairo_fixed_is_integer (b->p2.y))
125 do_unaligned_row(blt, closure, b, tx, y2, 1,
126 _cairo_fixed_fractional_part (b->p2.y));
127 } else
128 do_unaligned_row(blt, closure, b, tx, y1, 1,
129 b->p2.y - b->p1.y);
130}
131
132struct blt_in {
133 const cairo_traps_compositor_t *compositor;
134 cairo_surface_t *dst;
135 cairo_boxes_t boxes;
136};
137
138static void blt_in(void *closure,
139 int16_t x, int16_t y,
140 int16_t w, int16_t h,
141 uint16_t coverage)
142{
143 struct blt_in *info = closure;
144 cairo_color_t color;
145
146 if (CAIRO_ALPHA_SHORT_IS_OPAQUE (coverage)((coverage) >= 0xff00))
147 return;
148
149 _cairo_box_from_integers (&info->boxes.chunks.base[0], x, y, w, h);
150
151 _cairo_color_init_rgba (&color, 0, 0, 0, coverage / (double) 0xffff);
152 info->compositor->fill_boxes (info->dst,
153 CAIRO_OPERATOR_IN, &color,
154 &info->boxes);
155}
156
157static void
158add_rect_with_offset (cairo_boxes_t *boxes, int x1, int y1, int x2, int y2, int dx, int dy)
159{
160 cairo_box_t box;
161 cairo_int_status_t status;
162
163 box.p1.x = _cairo_fixed_from_int (x1 - dx);
164 box.p1.y = _cairo_fixed_from_int (y1 - dy);
165 box.p2.x = _cairo_fixed_from_int (x2 - dx);
166 box.p2.y = _cairo_fixed_from_int (y2 - dy);
167
168 status = _cairo_boxes_add (boxes, CAIRO_ANTIALIAS_DEFAULT, &box);
169 assert (status == CAIRO_INT_STATUS_SUCCESS)((void) sizeof ((status == CAIRO_INT_STATUS_SUCCESS) ? 1 : 0)
, __extension__ ({ if (status == CAIRO_INT_STATUS_SUCCESS) ; else
__assert_fail ("status == CAIRO_INT_STATUS_SUCCESS", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-traps-compositor.c"
, 169, __extension__ __PRETTY_FUNCTION__); }))
;
170}
171
172static cairo_int_status_t
173combine_clip_as_traps (const cairo_traps_compositor_t *compositor,
174 cairo_surface_t *mask,
175 const cairo_clip_t *clip,
176 const cairo_rectangle_int_t *extents)
177{
178 cairo_polygon_t polygon;
179 cairo_fill_rule_t fill_rule;
180 cairo_antialias_t antialias;
181 cairo_traps_t traps;
182 cairo_surface_t *src;
183 cairo_box_t box;
184 cairo_rectangle_int_t fixup;
185 int src_x, src_y;
186 cairo_int_status_t status;
187
188 TRACE ((stderr, "%s\n", __FUNCTION__));
189
190 status = _cairo_clip_get_polygon (clip, &polygon,
191 &fill_rule, &antialias);
192 if (status)
193 return status;
194
195 _cairo_traps_init (&traps);
196 status = _cairo_bentley_ottmann_tessellate_polygon (&traps,
197 &polygon,
198 fill_rule);
199 _cairo_polygon_fini (&polygon);
200 if (unlikely (status)(__builtin_expect (!!(status), 0)))
201 return status;
202
203 src = compositor->pattern_to_surface (mask, NULL((void*)0), FALSE0,
204 extents, NULL((void*)0),
205 &src_x, &src_y);
206 if (unlikely (src->status)(__builtin_expect (!!(src->status), 0))) {
207 _cairo_traps_fini (&traps);
208 return src->status;
209 }
210
211 status = compositor->composite_traps (mask, CAIRO_OPERATOR_IN, src,
212 src_x, src_y,
213 extents->x, extents->y,
214 extents,
215 antialias, &traps);
216
217 _cairo_traps_extents (&traps, &box);
218 _cairo_box_round_to_rectangle (&box, &fixup);
219 _cairo_traps_fini (&traps);
220 cairo_surface_destroy_moz_cairo_surface_destroy (src);
221
222 if (unlikely (status)(__builtin_expect (!!(status), 0)))
223 return status;
224
225 if (! _cairo_rectangle_intersect (&fixup, extents))
226 return CAIRO_STATUS_SUCCESS;
227
228 if (fixup.width < extents->width || fixup.height < extents->height) {
229 cairo_boxes_t clear;
230
231 _cairo_boxes_init (&clear);
232
233 /* top */
234 if (fixup.y != extents->y) {
235 add_rect_with_offset (&clear,
236 extents->x, extents->y,
237 extents->x + extents->width,
238 fixup.y,
239 extents->x, extents->y);
240 }
241 /* left */
242 if (fixup.x != extents->x) {
243 add_rect_with_offset (&clear,
244 extents->x, fixup.y,
245 fixup.x,
246 fixup.y + fixup.height,
247 extents->x, extents->y);
248 }
249 /* right */
250 if (fixup.x + fixup.width != extents->x + extents->width) {
251 add_rect_with_offset (&clear,
252 fixup.x + fixup.width,
253 fixup.y,
254 extents->x + extents->width,
255 fixup.y + fixup.height,
256 extents->x, extents->y);
257 }
258 /* bottom */
259 if (fixup.y + fixup.height != extents->y + extents->height) {
260 add_rect_with_offset (&clear,
261 extents->x,
262 fixup.y + fixup.height,
263 extents->x + extents->width,
264 extents->y + extents->height,
265 extents->x, extents->y);
266 }
267
268 status = compositor->fill_boxes (mask,
269 CAIRO_OPERATOR_CLEAR,
270 CAIRO_COLOR_TRANSPARENT_cairo_stock_color (CAIRO_STOCK_TRANSPARENT),
271 &clear);
272
273 _cairo_boxes_fini (&clear);
274 }
275
276 return status;
277}
278
279static cairo_status_t
280__clip_to_surface (const cairo_traps_compositor_t *compositor,
281 const cairo_composite_rectangles_t *composite,
282 const cairo_rectangle_int_t *extents,
283 cairo_surface_t **surface)
284{
285 cairo_surface_t *mask;
286 cairo_polygon_t polygon;
287 cairo_fill_rule_t fill_rule;
288 cairo_antialias_t antialias;
289 cairo_traps_t traps;
290 cairo_boxes_t clear;
291 cairo_surface_t *src;
292 int src_x, src_y;
293 cairo_int_status_t status;
294
295 TRACE ((stderr, "%s\n", __FUNCTION__));
296
297 status = _cairo_clip_get_polygon (composite->clip, &polygon,
298 &fill_rule, &antialias);
299 if (status)
300 return status;
301
302 _cairo_traps_init (&traps);
303 status = _cairo_bentley_ottmann_tessellate_polygon (&traps,
304 &polygon,
305 fill_rule);
306 _cairo_polygon_fini (&polygon);
307 if (unlikely (status)(__builtin_expect (!!(status), 0)))
308 return status;
309
310 mask = _cairo_surface_create_scratch (composite->surface,
311 CAIRO_CONTENT_ALPHA,
312 extents->width,
313 extents->height,
314 NULL((void*)0));
315 if (unlikely (mask->status)(__builtin_expect (!!(mask->status), 0))) {
316 _cairo_traps_fini (&traps);
317 return status;
318 }
319
320 src = compositor->pattern_to_surface (mask, NULL((void*)0), FALSE0,
321 extents, NULL((void*)0),
322 &src_x, &src_y);
323 if (unlikely (status = src->status)(__builtin_expect (!!(status = src->status), 0)))
324 goto error;
325
326 status = compositor->acquire (mask);
327 if (unlikely (status)(__builtin_expect (!!(status), 0)))
328 goto error;
329
330 _cairo_boxes_init_from_rectangle (&clear,
331 0, 0,
332 extents->width,
333 extents->height);
334 status = compositor->fill_boxes (mask,
335 CAIRO_OPERATOR_CLEAR,
336 CAIRO_COLOR_TRANSPARENT_cairo_stock_color (CAIRO_STOCK_TRANSPARENT),
337 &clear);
338 if (unlikely (status)(__builtin_expect (!!(status), 0)))
339 goto error_release;
340
341 status = compositor->composite_traps (mask, CAIRO_OPERATOR_ADD, src,
342 src_x, src_y,
343 extents->x, extents->y,
344 extents,
345 antialias, &traps);
346 if (unlikely (status)(__builtin_expect (!!(status), 0)))
347 goto error_release;
348
349 compositor->release (mask);
350 *surface = mask;
351out:
352 cairo_surface_destroy_moz_cairo_surface_destroy (src);
353 _cairo_traps_fini (&traps);
354 return status;
355
356error_release:
357 compositor->release (mask);
358error:
359 cairo_surface_destroy_moz_cairo_surface_destroy (mask);
360 goto out;
361}
362
363static cairo_surface_t *
364traps_get_clip_surface (const cairo_traps_compositor_t *compositor,
365 const cairo_composite_rectangles_t *composite,
366 const cairo_rectangle_int_t *extents)
367{
368 cairo_surface_t *surface = NULL((void*)0);
369 cairo_int_status_t status;
370
371 TRACE ((stderr, "%s\n", __FUNCTION__));
372
373 status = __clip_to_surface (compositor, composite, extents, &surface);
374 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
375 surface = _cairo_surface_create_scratch (composite->surface,
376 CAIRO_CONTENT_ALPHA,
377 extents->width,
378 extents->height,
379 CAIRO_COLOR_WHITE_cairo_stock_color (CAIRO_STOCK_WHITE));
380 if (unlikely (surface->status)(__builtin_expect (!!(surface->status), 0)))
381 return surface;
382
383 status = _cairo_clip_combine_with_surface (composite->clip, surface,
384 extents->x, extents->y);
385 }
386 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
387 cairo_surface_destroy_moz_cairo_surface_destroy (surface);
388 surface = _cairo_surface_create_in_error (status);
389 }
390
391 return surface;
392}
393
394static void blt_unaligned_boxes(const cairo_traps_compositor_t *compositor,
395 cairo_surface_t *surface,
396 int dx, int dy,
397 cairo_box_t *boxes,
398 int num_boxes)
399{
400 struct blt_in info;
401 int i;
402
403 info.compositor = compositor;
404 info.dst = surface;
405 _cairo_boxes_init (&info.boxes);
406 info.boxes.num_boxes = 1;
407 for (i = 0; i < num_boxes; i++) {
408 cairo_box_t *b = &boxes[i];
409
410 if (! _cairo_fixed_is_integer (b->p1.x) ||
411 ! _cairo_fixed_is_integer (b->p1.y) ||
412 ! _cairo_fixed_is_integer (b->p2.x) ||
413 ! _cairo_fixed_is_integer (b->p2.y))
414 {
415 do_unaligned_box(blt_in, &info, b, dx, dy);
416 }
417 }
418}
419
420static cairo_surface_t *
421create_composite_mask (const cairo_traps_compositor_t *compositor,
422 cairo_surface_t *dst,
423 void *draw_closure,
424 draw_func_t draw_func,
425 draw_func_t mask_func,
426 const cairo_composite_rectangles_t *extents)
427{
428 cairo_surface_t *surface, *src;
429 cairo_int_status_t status;
430 int src_x, src_y;
431
432 TRACE ((stderr, "%s\n", __FUNCTION__));
433
434 surface = _cairo_surface_create_scratch (dst, CAIRO_CONTENT_ALPHA,
435 extents->bounded.width,
436 extents->bounded.height,
437 NULL((void*)0));
438 if (unlikely (surface->status)(__builtin_expect (!!(surface->status), 0)))
439 return surface;
440
441 src = compositor->pattern_to_surface (surface,
442 &_cairo_pattern_white.base,
443 FALSE0,
444 &extents->bounded,
445 &extents->bounded,
446 &src_x, &src_y);
447 if (unlikely (src->status)(__builtin_expect (!!(src->status), 0))) {
448 cairo_surface_destroy_moz_cairo_surface_destroy (surface);
449 return src;
450 }
451
452 status = compositor->acquire (surface);
453 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
454 cairo_surface_destroy_moz_cairo_surface_destroy (src);
455 cairo_surface_destroy_moz_cairo_surface_destroy (surface);
456 return _cairo_surface_create_in_error (status);
457 }
458
459 if (!surface->is_clear) {
460 cairo_boxes_t clear;
461
462 _cairo_boxes_init_from_rectangle (&clear,
463 0, 0,
464 extents->bounded.width,
465 extents->bounded.height);
466 status = compositor->fill_boxes (surface,
467 CAIRO_OPERATOR_CLEAR,
468 CAIRO_COLOR_TRANSPARENT_cairo_stock_color (CAIRO_STOCK_TRANSPARENT),
469 &clear);
470 if (unlikely (status)(__builtin_expect (!!(status), 0)))
471 goto error;
472
473 surface->is_clear = TRUE1;
474 }
475
476 if (mask_func) {
477 status = mask_func (compositor, surface, draw_closure,
478 CAIRO_OPERATOR_SOURCE, src, src_x, src_y,
479 extents->bounded.x, extents->bounded.y,
480 &extents->bounded, extents->clip);
481 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
) {
482 surface->is_clear = FALSE0;
483 goto out;
484 }
485 if (unlikely (status != CAIRO_INT_STATUS_UNSUPPORTED)(__builtin_expect (!!(status != CAIRO_INT_STATUS_UNSUPPORTED)
, 0))
)
486 goto error;
487 }
488
489 /* Is it worth setting the clip region here? */
490 status = draw_func (compositor, surface, draw_closure,
491 CAIRO_OPERATOR_ADD, src, src_x, src_y,
492 extents->bounded.x, extents->bounded.y,
493 &extents->bounded, NULL((void*)0));
494 if (unlikely (status)(__builtin_expect (!!(status), 0)))
495 goto error;
496
497 surface->is_clear = FALSE0;
498 if (extents->clip->path != NULL((void*)0)) {
499 status = combine_clip_as_traps (compositor, surface,
500 extents->clip, &extents->bounded);
501 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
502 status = _cairo_clip_combine_with_surface (extents->clip, surface,
503 extents->bounded.x,
504 extents->bounded.y);
505 }
506 if (unlikely (status)(__builtin_expect (!!(status), 0)))
507 goto error;
508 } else if (extents->clip->boxes) {
509 blt_unaligned_boxes(compositor, surface,
510 extents->bounded.x, extents->bounded.y,
511 extents->clip->boxes, extents->clip->num_boxes);
512
513 }
514
515out:
516 compositor->release (surface);
517 cairo_surface_destroy_moz_cairo_surface_destroy (src);
518 return surface;
519
520error:
521 compositor->release (surface);
522 if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
523 cairo_surface_destroy_moz_cairo_surface_destroy (surface);
524 surface = _cairo_surface_create_in_error (status);
525 }
526 cairo_surface_destroy_moz_cairo_surface_destroy (src);
527 return surface;
528}
529
530/* Handles compositing with a clip surface when the operator allows
531 * us to combine the clip with the mask
532 */
533static cairo_status_t
534clip_and_composite_with_mask (const cairo_traps_compositor_t *compositor,
535 const cairo_composite_rectangles_t*extents,
536 draw_func_t draw_func,
537 draw_func_t mask_func,
538 void *draw_closure,
539 cairo_operator_t op,
540 cairo_surface_t *src,
541 int src_x, int src_y)
542{
543 cairo_surface_t *dst = extents->surface;
544 cairo_surface_t *mask;
545
546 TRACE ((stderr, "%s\n", __FUNCTION__));
547
548 mask = create_composite_mask (compositor, dst, draw_closure,
549 draw_func, mask_func,
550 extents);
551 if (unlikely (mask->status)(__builtin_expect (!!(mask->status), 0)))
552 return mask->status;
553
554 if (mask->is_clear)
555 goto skip;
556
557 if (src != NULL((void*)0) || dst->content != CAIRO_CONTENT_ALPHA) {
558 compositor->composite (dst, op, src, mask,
559 extents->bounded.x + src_x,
560 extents->bounded.y + src_y,
561 0, 0,
562 extents->bounded.x, extents->bounded.y,
563 extents->bounded.width, extents->bounded.height);
564 } else {
565 compositor->composite (dst, op, mask, NULL((void*)0),
566 0, 0,
567 0, 0,
568 extents->bounded.x, extents->bounded.y,
569 extents->bounded.width, extents->bounded.height);
570 }
571
572skip:
573 cairo_surface_destroy_moz_cairo_surface_destroy (mask);
574 return CAIRO_STATUS_SUCCESS;
575}
576
577/* Handles compositing with a clip surface when we have to do the operation
578 * in two pieces and combine them together.
579 */
580static cairo_status_t
581clip_and_composite_combine (const cairo_traps_compositor_t *compositor,
582 const cairo_composite_rectangles_t*extents,
583 draw_func_t draw_func,
584 void *draw_closure,
585 cairo_operator_t op,
586 cairo_surface_t *src,
587 int src_x, int src_y)
588{
589 cairo_surface_t *dst = extents->surface;
590 cairo_surface_t *tmp, *clip;
591 cairo_status_t status;
592
593 TRACE ((stderr, "%s\n", __FUNCTION__));
594
595 tmp = _cairo_surface_create_scratch (dst, dst->content,
596 extents->bounded.width,
597 extents->bounded.height,
598 NULL((void*)0));
599 if (unlikely (tmp->status)(__builtin_expect (!!(tmp->status), 0)))
600 return tmp->status;
601
602 status = compositor->acquire (tmp);
603 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
604 cairo_surface_destroy_moz_cairo_surface_destroy (tmp);
605 return status;
606 }
607
608 compositor->composite (tmp,
609 dst->is_clear ? CAIRO_OPERATOR_CLEAR : CAIRO_OPERATOR_SOURCE,
610 dst, NULL((void*)0),
611 extents->bounded.x, extents->bounded.y,
612 0, 0,
613 0, 0,
614 extents->bounded.width, extents->bounded.height);
615
616 status = draw_func (compositor, tmp, draw_closure, op,
617 src, src_x, src_y,
618 extents->bounded.x, extents->bounded.y,
619 &extents->bounded, NULL((void*)0));
620
621 if (unlikely (status)(__builtin_expect (!!(status), 0)))
622 goto cleanup;
623
624 clip = traps_get_clip_surface (compositor, extents, &extents->bounded);
625 if (unlikely ((status = clip->status))(__builtin_expect (!!((status = clip->status)), 0)))
626 goto cleanup;
627
628 if (dst->is_clear) {
629 compositor->composite (dst, CAIRO_OPERATOR_SOURCE, tmp, clip,
630 0, 0,
631 0, 0,
632 extents->bounded.x, extents->bounded.y,
633 extents->bounded.width, extents->bounded.height);
634 } else {
635 compositor->lerp (dst, tmp, clip,
636 0, 0,
637 0,0,
638 extents->bounded.x, extents->bounded.y,
639 extents->bounded.width, extents->bounded.height);
640 }
641 cairo_surface_destroy_moz_cairo_surface_destroy (clip);
642
643cleanup:
644 compositor->release (tmp);
645 cairo_surface_destroy_moz_cairo_surface_destroy (tmp);
646
647 return status;
648}
649
650/* Handles compositing for %CAIRO_OPERATOR_SOURCE, which is special; it's
651 * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
652 */
653static cairo_status_t
654clip_and_composite_source (const cairo_traps_compositor_t *compositor,
655 cairo_surface_t *dst,
656 draw_func_t draw_func,
657 draw_func_t mask_func,
658 void *draw_closure,
659 cairo_surface_t *src,
660 int src_x,
661 int src_y,
662 const cairo_composite_rectangles_t *extents)
663{
664 cairo_surface_t *mask;
665
666 TRACE ((stderr, "%s\n", __FUNCTION__));
667
668 /* Create a surface that is mask IN clip */
669 mask = create_composite_mask (compositor, dst, draw_closure,
670 draw_func, mask_func,
671 extents);
672 if (unlikely (mask->status)(__builtin_expect (!!(mask->status), 0)))
673 return mask->status;
674
675 if (mask->is_clear)
676 goto skip;
677
678 if (dst->is_clear) {
679 compositor->composite (dst, CAIRO_OPERATOR_SOURCE, src, mask,
680 extents->bounded.x + src_x, extents->bounded.y + src_y,
681 0, 0,
682 extents->bounded.x, extents->bounded.y,
683 extents->bounded.width, extents->bounded.height);
684 } else {
685 compositor->lerp (dst, src, mask,
686 extents->bounded.x + src_x, extents->bounded.y + src_y,
687 0, 0,
688 extents->bounded.x, extents->bounded.y,
689 extents->bounded.width, extents->bounded.height);
690 }
691
692skip:
693 cairo_surface_destroy_moz_cairo_surface_destroy (mask);
694
695 return CAIRO_STATUS_SUCCESS;
696}
697
698static cairo_bool_t
699can_reduce_alpha_op (cairo_operator_t op)
700{
701 int iop = op;
702 switch (iop) {
703 case CAIRO_OPERATOR_OVER:
704 case CAIRO_OPERATOR_SOURCE:
705 case CAIRO_OPERATOR_ADD:
706 return TRUE1;
707 default:
708 return FALSE0;
709 }
710}
711
712static cairo_bool_t
713reduce_alpha_op (cairo_composite_rectangles_t *extents)
714{
715 cairo_surface_t *dst = extents->surface;
716 cairo_operator_t op = extents->op;
717 const cairo_pattern_t *pattern = &extents->source_pattern.base;
718 return dst->is_clear &&
719 dst->content == CAIRO_CONTENT_ALPHA &&
720 _cairo_pattern_is_opaque_solid (pattern) &&
721 can_reduce_alpha_op (op);
722}
723
724static cairo_status_t
725fixup_unbounded_with_mask (const cairo_traps_compositor_t *compositor,
726 const cairo_composite_rectangles_t *extents)
727{
728 cairo_surface_t *dst = extents->surface;
729 cairo_surface_t *mask;
730
731 TRACE ((stderr, "%s\n", __FUNCTION__));
732
733 /* XXX can we avoid querying the clip surface again? */
734 mask = traps_get_clip_surface (compositor, extents, &extents->unbounded);
735 if (unlikely (mask->status)(__builtin_expect (!!(mask->status), 0)))
736 return mask->status;
737
738 /* top */
739 if (extents->bounded.y != extents->unbounded.y) {
740 int x = extents->unbounded.x;
741 int y = extents->unbounded.y;
742 int width = extents->unbounded.width;
743 int height = extents->bounded.y - y;
744
745 compositor->composite (dst, CAIRO_OPERATOR_DEST_OUT, mask, NULL((void*)0),
746 0, 0,
747 0, 0,
748 x, y,
749 width, height);
750 }
751
752 /* left */
753 if (extents->bounded.x != extents->unbounded.x) {
754 int x = extents->unbounded.x;
755 int y = extents->bounded.y;
756 int width = extents->bounded.x - x;
757 int height = extents->bounded.height;
758
759 compositor->composite (dst, CAIRO_OPERATOR_DEST_OUT, mask, NULL((void*)0),
760 0, y - extents->unbounded.y,
761 0, 0,
762 x, y,
763 width, height);
764 }
765
766 /* right */
767 if (extents->bounded.x + extents->bounded.width != extents->unbounded.x + extents->unbounded.width) {
768 int x = extents->bounded.x + extents->bounded.width;
769 int y = extents->bounded.y;
770 int width = extents->unbounded.x + extents->unbounded.width - x;
771 int height = extents->bounded.height;
772
773 compositor->composite (dst, CAIRO_OPERATOR_DEST_OUT, mask, NULL((void*)0),
774 x - extents->unbounded.x, y - extents->unbounded.y,
775 0, 0,
776 x, y,
777 width, height);
778 }
779
780 /* bottom */
781 if (extents->bounded.y + extents->bounded.height != extents->unbounded.y + extents->unbounded.height) {
782 int x = extents->unbounded.x;
783 int y = extents->bounded.y + extents->bounded.height;
784 int width = extents->unbounded.width;
785 int height = extents->unbounded.y + extents->unbounded.height - y;
786
787 compositor->composite (dst, CAIRO_OPERATOR_DEST_OUT, mask, NULL((void*)0),
788 0, y - extents->unbounded.y,
789 0, 0,
790 x, y,
791 width, height);
792 }
793
794 cairo_surface_destroy_moz_cairo_surface_destroy (mask);
795
796 return CAIRO_STATUS_SUCCESS;
797}
798
799static void
800add_rect (cairo_boxes_t *boxes, int x1, int y1, int x2, int y2)
801{
802 cairo_box_t box;
803 cairo_int_status_t status;
804
805 box.p1.x = _cairo_fixed_from_int (x1);
806 box.p1.y = _cairo_fixed_from_int (y1);
807 box.p2.x = _cairo_fixed_from_int (x2);
808 box.p2.y = _cairo_fixed_from_int (y2);
809
810 status = _cairo_boxes_add (boxes, CAIRO_ANTIALIAS_DEFAULT, &box);
811 assert (status == CAIRO_INT_STATUS_SUCCESS)((void) sizeof ((status == CAIRO_INT_STATUS_SUCCESS) ? 1 : 0)
, __extension__ ({ if (status == CAIRO_INT_STATUS_SUCCESS) ; else
__assert_fail ("status == CAIRO_INT_STATUS_SUCCESS", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-traps-compositor.c"
, 811, __extension__ __PRETTY_FUNCTION__); }))
;
812}
813
814static cairo_status_t
815fixup_unbounded (const cairo_traps_compositor_t *compositor,
816 cairo_composite_rectangles_t *extents,
817 cairo_boxes_t *boxes)
818{
819 cairo_surface_t *dst = extents->surface;
820 cairo_boxes_t clear, tmp;
821 cairo_box_t box;
822 cairo_int_status_t status;
823
824 TRACE ((stderr, "%s\n", __FUNCTION__));
825
826 if (extents->bounded.width == extents->unbounded.width &&
827 extents->bounded.height == extents->unbounded.height)
828 {
829 return CAIRO_STATUS_SUCCESS;
830 }
831
832 assert (extents->clip->path == NULL)((void) sizeof ((extents->clip->path == ((void*)0)) ? 1
: 0), __extension__ ({ if (extents->clip->path == ((void
*)0)) ; else __assert_fail ("extents->clip->path == NULL"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-traps-compositor.c"
, 832, __extension__ __PRETTY_FUNCTION__); }))
;
833
834 /* subtract the drawn boxes from the unbounded area */
835 _cairo_boxes_init (&clear);
836
837 box.p1.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
838 box.p1.y = _cairo_fixed_from_int (extents->unbounded.y);
839 box.p2.x = _cairo_fixed_from_int (extents->unbounded.x);
840 box.p2.y = _cairo_fixed_from_int (extents->unbounded.y + extents->unbounded.height);
841
842 if (boxes == NULL((void*)0)) {
843 if (extents->bounded.width == 0 || extents->bounded.height == 0) {
844 goto empty;
845 } else {
846 /* top */
847 if (extents->bounded.y != extents->unbounded.y) {
848 add_rect (&clear,
849 extents->unbounded.x, extents->unbounded.y,
850 extents->unbounded.x + extents->unbounded.width,
851 extents->bounded.y);
852 }
853 /* left */
854 if (extents->bounded.x != extents->unbounded.x) {
855 add_rect (&clear,
856 extents->unbounded.x, extents->bounded.y,
857 extents->bounded.x,
858 extents->bounded.y + extents->bounded.height);
859 }
860 /* right */
861 if (extents->bounded.x + extents->bounded.width != extents->unbounded.x + extents->unbounded.width) {
862 add_rect (&clear,
863 extents->bounded.x + extents->bounded.width,
864 extents->bounded.y,
865 extents->unbounded.x + extents->unbounded.width,
866 extents->bounded.y + extents->bounded.height);
867 }
868 /* bottom */
869 if (extents->bounded.y + extents->bounded.height != extents->unbounded.y + extents->unbounded.height) {
870 add_rect (&clear,
871 extents->unbounded.x,
872 extents->bounded.y + extents->bounded.height,
873 extents->unbounded.x + extents->unbounded.width,
874 extents->unbounded.y + extents->unbounded.height);
875 }
876 }
877 } else if (boxes->num_boxes) {
878 _cairo_boxes_init (&tmp);
879
880 assert (boxes->is_pixel_aligned)((void) sizeof ((boxes->is_pixel_aligned) ? 1 : 0), __extension__
({ if (boxes->is_pixel_aligned) ; else __assert_fail ("boxes->is_pixel_aligned"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-traps-compositor.c"
, 880, __extension__ __PRETTY_FUNCTION__); }))
;
881
882 status = _cairo_boxes_add (&tmp, CAIRO_ANTIALIAS_DEFAULT, &box);
883 assert (status == CAIRO_INT_STATUS_SUCCESS)((void) sizeof ((status == CAIRO_INT_STATUS_SUCCESS) ? 1 : 0)
, __extension__ ({ if (status == CAIRO_INT_STATUS_SUCCESS) ; else
__assert_fail ("status == CAIRO_INT_STATUS_SUCCESS", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-traps-compositor.c"
, 883, __extension__ __PRETTY_FUNCTION__); }))
;
884
885 tmp.chunks.next = &boxes->chunks;
886 tmp.num_boxes += boxes->num_boxes;
887
888 status = _cairo_bentley_ottmann_tessellate_boxes (&tmp,
889 CAIRO_FILL_RULE_WINDING,
890 &clear);
891 tmp.chunks.next = NULL((void*)0);
892 if (unlikely (status)(__builtin_expect (!!(status), 0)))
893 goto error;
894 } else {
895empty:
896 box.p1.x = _cairo_fixed_from_int (extents->unbounded.x);
897 box.p2.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
898
899 status = _cairo_boxes_add (&clear, CAIRO_ANTIALIAS_DEFAULT, &box);
900 assert (status == CAIRO_INT_STATUS_SUCCESS)((void) sizeof ((status == CAIRO_INT_STATUS_SUCCESS) ? 1 : 0)
, __extension__ ({ if (status == CAIRO_INT_STATUS_SUCCESS) ; else
__assert_fail ("status == CAIRO_INT_STATUS_SUCCESS", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-traps-compositor.c"
, 900, __extension__ __PRETTY_FUNCTION__); }))
;
901 }
902
903 /* Now intersect with the clip boxes */
904 if (extents->clip->num_boxes) {
905 _cairo_boxes_init_for_array (&tmp,
906 extents->clip->boxes,
907 extents->clip->num_boxes);
908 status = _cairo_boxes_intersect (&clear, &tmp, &clear);
909 if (unlikely (status)(__builtin_expect (!!(status), 0)))
910 goto error;
911 }
912
913 status = compositor->fill_boxes (dst,
914 CAIRO_OPERATOR_CLEAR,
915 CAIRO_COLOR_TRANSPARENT_cairo_stock_color (CAIRO_STOCK_TRANSPARENT),
916 &clear);
917
918error:
919 _cairo_boxes_fini (&clear);
920 return status;
921}
922
923enum {
924 NEED_CLIP_REGION = 0x1,
925 NEED_CLIP_SURFACE = 0x2,
926 FORCE_CLIP_REGION = 0x4,
927};
928
929static cairo_bool_t
930need_bounded_clip (cairo_composite_rectangles_t *extents)
931{
932 unsigned int flags = 0;
933
934 if (extents->clip->num_boxes > 1 ||
935 extents->mask.width > extents->unbounded.width ||
936 extents->mask.height > extents->unbounded.height)
937 {
938 flags |= NEED_CLIP_REGION;
939 }
940
941 if (extents->clip->num_boxes > 1 ||
942 extents->mask.width > extents->bounded.width ||
943 extents->mask.height > extents->bounded.height)
944 {
945 flags |= FORCE_CLIP_REGION;
946 }
947
948 if (! _cairo_clip_is_region (extents->clip))
949 flags |= NEED_CLIP_SURFACE;
950
951 return flags;
952}
953
954static cairo_bool_t
955need_unbounded_clip (cairo_composite_rectangles_t *extents)
956{
957 unsigned int flags = 0;
958 if (! extents->is_bounded) {
959 flags |= NEED_CLIP_REGION;
960 if (! _cairo_clip_is_region (extents->clip))
961 flags |= NEED_CLIP_SURFACE;
962 }
963 if (extents->clip->path != NULL((void*)0))
964 flags |= NEED_CLIP_SURFACE;
965 return flags;
966}
967
968static cairo_status_t
969clip_and_composite (const cairo_traps_compositor_t *compositor,
970 cairo_composite_rectangles_t *extents,
971 draw_func_t draw_func,
972 draw_func_t mask_func,
973 void *draw_closure,
974 unsigned int need_clip)
975{
976 cairo_surface_t *dst = extents->surface;
977 cairo_operator_t op = extents->op;
978 cairo_pattern_t *source = &extents->source_pattern.base;
979 cairo_surface_t *src;
980 int src_x, src_y;
981 cairo_region_t *clip_region = NULL((void*)0);
982 cairo_status_t status = CAIRO_STATUS_SUCCESS;
983
984 TRACE ((stderr, "%s\n", __FUNCTION__));
985
986 if (reduce_alpha_op (extents)) {
987 op = CAIRO_OPERATOR_ADD;
988 source = NULL((void*)0);
989 }
990
991 if (op == CAIRO_OPERATOR_CLEAR) {
992 op = CAIRO_OPERATOR_DEST_OUT;
993 source = NULL((void*)0);
994 }
995
996 compositor->acquire (dst);
997
998 if (need_clip & NEED_CLIP_REGION) {
999 const cairo_rectangle_int_t *limit;
1000
1001 if ((need_clip & FORCE_CLIP_REGION) == 0)
1002 limit = &extents->unbounded;
1003 else
1004 limit = &extents->destination;
1005
1006 clip_region = _cairo_clip_get_region (extents->clip);
1007 if (clip_region != NULL((void*)0) &&
1008 cairo_region_contains_rectangle_moz_cairo_region_contains_rectangle (clip_region,
1009 limit) == CAIRO_REGION_OVERLAP_IN)
1010 clip_region = NULL((void*)0);
1011
1012 if (clip_region != NULL((void*)0)) {
1013 status = compositor->set_clip_region (dst, clip_region);
1014 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
1015 compositor->release (dst);
1016 return status;
1017 }
1018 }
1019 }
1020
1021 if (extents->bounded.width == 0 || extents->bounded.height == 0)
1022 goto skip;
1023
1024 src = compositor->pattern_to_surface (dst, source, FALSE0,
1025 &extents->bounded,
1026 &extents->source_sample_area,
1027 &src_x, &src_y);
1028 if (unlikely (status = src->status)(__builtin_expect (!!(status = src->status), 0)))
1029 goto error;
1030
1031 if (op == CAIRO_OPERATOR_SOURCE) {
1032 status = clip_and_composite_source (compositor, dst,
1033 draw_func, mask_func, draw_closure,
1034 src, src_x, src_y,
1035 extents);
1036 } else {
1037 if (need_clip & NEED_CLIP_SURFACE) {
1038 if (extents->is_bounded) {
1039 status = clip_and_composite_with_mask (compositor, extents,
1040 draw_func, mask_func,
1041 draw_closure,
1042 op, src, src_x, src_y);
1043 } else {
1044 status = clip_and_composite_combine (compositor, extents,
1045 draw_func, draw_closure,
1046 op, src, src_x, src_y);
1047 }
1048 } else {
1049 status = draw_func (compositor,
1050 dst, draw_closure,
1051 op, src, src_x, src_y,
1052 0, 0,
1053 &extents->bounded,
1054 extents->clip);
1055 }
1056 }
1057 cairo_surface_destroy_moz_cairo_surface_destroy (src);
1058
1059skip:
1060 if (status == CAIRO_STATUS_SUCCESS && ! extents->is_bounded) {
1061 if (need_clip & NEED_CLIP_SURFACE)
1062 status = fixup_unbounded_with_mask (compositor, extents);
1063 else
1064 status = fixup_unbounded (compositor, extents, NULL((void*)0));
1065 }
1066
1067error:
1068 if (clip_region)
1069 compositor->set_clip_region (dst, NULL((void*)0));
1070
1071 compositor->release (dst);
1072
1073 return status;
1074}
1075
1076/* meta-ops */
1077
1078typedef struct {
1079 cairo_traps_t traps;
1080 cairo_antialias_t antialias;
1081} composite_traps_info_t;
1082
1083static cairo_int_status_t
1084composite_traps (const cairo_traps_compositor_t *compositor,
1085 cairo_surface_t *dst,
1086 void *closure,
1087 cairo_operator_t op,
1088 cairo_surface_t *src,
1089 int src_x, int src_y,
1090 int dst_x, int dst_y,
1091 const cairo_rectangle_int_t *extents,
1092 cairo_clip_t *clip)
1093{
1094 composite_traps_info_t *info = closure;
1095
1096 TRACE ((stderr, "%s\n", __FUNCTION__));
1097
1098 return compositor->composite_traps (dst, op, src,
1099 src_x - dst_x, src_y - dst_y,
1100 dst_x, dst_y,
1101 extents,
1102 info->antialias, &info->traps);
1103}
1104
1105typedef struct {
1106 cairo_tristrip_t strip;
1107 cairo_antialias_t antialias;
1108} composite_tristrip_info_t;
1109
1110static cairo_int_status_t
1111composite_tristrip (const cairo_traps_compositor_t *compositor,
1112 cairo_surface_t *dst,
1113 void *closure,
1114 cairo_operator_t op,
1115 cairo_surface_t *src,
1116 int src_x, int src_y,
1117 int dst_x, int dst_y,
1118 const cairo_rectangle_int_t *extents,
1119 cairo_clip_t *clip)
1120{
1121 composite_tristrip_info_t *info = closure;
1122
1123 TRACE ((stderr, "%s\n", __FUNCTION__));
1124
1125 return compositor->composite_tristrip (dst, op, src,
1126 src_x - dst_x, src_y - dst_y,
1127 dst_x, dst_y,
1128 extents,
1129 info->antialias, &info->strip);
1130}
1131
1132static cairo_bool_t
1133is_recording_pattern (const cairo_pattern_t *pattern)
1134{
1135 cairo_surface_t *surface;
1136
1137 if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
1138 return FALSE0;
1139
1140 surface = ((const cairo_surface_pattern_t *) pattern)->surface;
1141 surface = _cairo_surface_get_source (surface, NULL((void*)0));
1142 return _cairo_surface_is_recording (surface);
1143}
1144
1145static cairo_surface_t *
1146recording_pattern_get_surface (const cairo_pattern_t *pattern)
1147{
1148 cairo_surface_t *surface;
1149
1150 surface = ((const cairo_surface_pattern_t *) pattern)->surface;
1151 return _cairo_surface_get_source (surface, NULL((void*)0));
1152}
1153
1154static cairo_bool_t
1155recording_pattern_contains_sample (const cairo_pattern_t *pattern,
1156 const cairo_rectangle_int_t *sample)
1157{
1158 cairo_recording_surface_t *surface;
1159
1160 if (! is_recording_pattern (pattern))
1161 return FALSE0;
1162
1163 if (pattern->extend == CAIRO_EXTEND_NONE)
1164 return TRUE1;
1165
1166 surface = (cairo_recording_surface_t *) recording_pattern_get_surface (pattern);
1167 if (surface->unbounded)
1168 return TRUE1;
1169
1170 return _cairo_rectangle_contains_rectangle (&surface->extents, sample);
1171}
1172
1173static cairo_bool_t
1174op_reduces_to_source (cairo_composite_rectangles_t *extents)
1175{
1176 if (extents->op == CAIRO_OPERATOR_SOURCE)
1177 return TRUE1;
1178
1179 if (extents->surface->is_clear)
1180 return extents->op == CAIRO_OPERATOR_OVER || extents->op == CAIRO_OPERATOR_ADD;
1181
1182 return FALSE0;
1183}
1184
1185static cairo_status_t
1186composite_aligned_boxes (const cairo_traps_compositor_t *compositor,
1187 cairo_composite_rectangles_t *extents,
1188 cairo_boxes_t *boxes)
1189{
1190 cairo_surface_t *dst = extents->surface;
1191 cairo_operator_t op = extents->op;
1192 cairo_bool_t need_clip_mask = ! _cairo_clip_is_region (extents->clip);
1193 cairo_bool_t op_is_source;
1194 cairo_status_t status;
1195
1196 TRACE ((stderr, "%s\n", __FUNCTION__));
1197
1198 if (need_clip_mask &&
1199 (! extents->is_bounded || extents->op == CAIRO_OPERATOR_SOURCE))
1200 {
1201 return CAIRO_INT_STATUS_UNSUPPORTED;
1202 }
1203
1204 op_is_source = op_reduces_to_source (extents);
1205
1206 /* Are we just copying a recording surface? */
1207 if (! need_clip_mask && op_is_source &&
1208 recording_pattern_contains_sample (&extents->source_pattern.base,
1209 &extents->source_sample_area))
1210 {
1211 cairo_clip_t *recording_clip;
1212 const cairo_pattern_t *source = &extents->source_pattern.base;
1213 const cairo_matrix_t *m;
1214 cairo_matrix_t matrix;
1215
1216 /* XXX could also do tiling repeat modes... */
1217
1218 /* first clear the area about to be overwritten */
1219 if (! dst->is_clear) {
1220 status = compositor->acquire (dst);
1221 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1222 return status;
1223
1224 status = compositor->fill_boxes (dst,
1225 CAIRO_OPERATOR_CLEAR,
1226 CAIRO_COLOR_TRANSPARENT_cairo_stock_color (CAIRO_STOCK_TRANSPARENT),
1227 boxes);
1228 compositor->release (dst);
1229 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1230 return status;
1231 }
1232
1233 m = &source->matrix;
1234 if (_cairo_surface_has_device_transform (dst)) {
1235 cairo_matrix_multiply_moz_cairo_matrix_multiply (&matrix,
1236 &source->matrix,
1237 &dst->device_transform);
1238 m = &matrix;
1239 }
1240
1241 recording_clip = _cairo_clip_from_boxes (boxes);
1242 status = _cairo_recording_surface_replay_with_clip (recording_pattern_get_surface (source),
1243 m, dst, recording_clip);
1244 _cairo_clip_destroy (recording_clip);
1245
1246 return status;
1247 }
1248
1249 status = compositor->acquire (dst);
1250 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1251 return status;
1252
1253 if (! need_clip_mask &&
1254 (op == CAIRO_OPERATOR_CLEAR ||
1255 extents->source_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID))
1256 {
1257 const cairo_color_t *color;
1258
1259 if (op == CAIRO_OPERATOR_CLEAR) {
1260 color = CAIRO_COLOR_TRANSPARENT_cairo_stock_color (CAIRO_STOCK_TRANSPARENT);
1261 } else {
1262 color = &((cairo_solid_pattern_t *) &extents->source_pattern)->color;
1263 if (op_is_source)
1264 op = CAIRO_OPERATOR_SOURCE;
1265 }
1266
1267 status = compositor->fill_boxes (dst, op, color, boxes);
1268 }
1269 else
1270 {
1271 cairo_surface_t *src, *mask = NULL((void*)0);
1272 cairo_pattern_t *source = &extents->source_pattern.base;
1273 int src_x, src_y;
1274 int mask_x = 0, mask_y = 0;
1275
1276 if (need_clip_mask) {
1277 mask = traps_get_clip_surface (compositor,
1278 extents, &extents->bounded);
1279 if (unlikely (mask->status)(__builtin_expect (!!(mask->status), 0)))
1280 return mask->status;
1281
1282 mask_x = -extents->bounded.x;
1283 mask_y = -extents->bounded.y;
1284
1285 if (op == CAIRO_OPERATOR_CLEAR) {
1286 source = NULL((void*)0);
1287 op = CAIRO_OPERATOR_DEST_OUT;
1288 }
1289 } else if (op_is_source)
1290 op = CAIRO_OPERATOR_SOURCE;
1291
1292 src = compositor->pattern_to_surface (dst, source, FALSE0,
1293 &extents->bounded,
1294 &extents->source_sample_area,
1295 &src_x, &src_y);
1296 if (likely (src->status == CAIRO_STATUS_SUCCESS)(__builtin_expect (!!(src->status == CAIRO_STATUS_SUCCESS)
, 1))
) {
1297 status = compositor->composite_boxes (dst, op, src, mask,
1298 src_x, src_y,
1299 mask_x, mask_y,
1300 0, 0,
1301 boxes, &extents->bounded);
1302 cairo_surface_destroy_moz_cairo_surface_destroy (src);
1303 } else
1304 status = src->status;
1305
1306 cairo_surface_destroy_moz_cairo_surface_destroy (mask);
1307 }
1308
1309 if (status == CAIRO_STATUS_SUCCESS && ! extents->is_bounded)
1310 status = fixup_unbounded (compositor, extents, boxes);
1311
1312 compositor->release (dst);
1313
1314 return status;
1315}
1316
1317static cairo_status_t
1318upload_boxes (const cairo_traps_compositor_t *compositor,
1319 cairo_composite_rectangles_t *extents,
1320 cairo_boxes_t *boxes)
1321{
1322 cairo_surface_t *dst = extents->surface;
1323 const cairo_pattern_t *source = &extents->source_pattern.base;
1324 cairo_surface_t *src;
1325 cairo_rectangle_int_t limit;
1326 cairo_int_status_t status;
1327 int tx, ty;
1328
1329 TRACE ((stderr, "%s\n", __FUNCTION__));
1330
1331 src = _cairo_pattern_get_source((cairo_surface_pattern_t *)source,
1332 &limit);
1333 if (!(src->type == CAIRO_SURFACE_TYPE_IMAGE || src->type == dst->type))
1334 return CAIRO_INT_STATUS_UNSUPPORTED;
1335
1336 if (! _cairo_matrix_is_integer_translation (&source->matrix, &tx, &ty))
1337 return CAIRO_INT_STATUS_UNSUPPORTED;
1338
1339 /* Check that the data is entirely within the image */
1340 if (extents->bounded.x + tx < limit.x || extents->bounded.y + ty < limit.y)
1341 return CAIRO_INT_STATUS_UNSUPPORTED;
1342
1343 if (extents->bounded.x + extents->bounded.width + tx > limit.x + limit.width ||
1344 extents->bounded.y + extents->bounded.height + ty > limit.y + limit.height)
1345 return CAIRO_INT_STATUS_UNSUPPORTED;
1346
1347 tx += limit.x;
1348 ty += limit.y;
1349
1350 if (src->type == CAIRO_SURFACE_TYPE_IMAGE)
1351 status = compositor->draw_image_boxes (dst,
1352 (cairo_image_surface_t *)src,
1353 boxes, tx, ty);
1354 else
1355 status = compositor->copy_boxes (dst, src, boxes, &extents->bounded,
1356 tx, ty);
1357
1358 return status;
1359}
1360
1361static cairo_int_status_t
1362trim_extents_to_traps (cairo_composite_rectangles_t *extents,
1363 cairo_traps_t *traps)
1364{
1365 cairo_box_t box;
1366
1367 _cairo_traps_extents (traps, &box);
1368 return _cairo_composite_rectangles_intersect_mask_extents (extents, &box);
1369}
1370
1371static cairo_int_status_t
1372trim_extents_to_tristrip (cairo_composite_rectangles_t *extents,
1373 cairo_tristrip_t *strip)
1374{
1375 cairo_box_t box;
1376
1377 _cairo_tristrip_extents (strip, &box);
1378 return _cairo_composite_rectangles_intersect_mask_extents (extents, &box);
1379}
1380
1381static cairo_int_status_t
1382trim_extents_to_boxes (cairo_composite_rectangles_t *extents,
1383 cairo_boxes_t *boxes)
1384{
1385 cairo_box_t box;
1386
1387 _cairo_boxes_extents (boxes, &box);
1388 return _cairo_composite_rectangles_intersect_mask_extents (extents, &box);
1389}
1390
1391static cairo_int_status_t
1392boxes_for_traps (cairo_boxes_t *boxes,
1393 cairo_traps_t *traps,
1394 cairo_antialias_t antialias)
1395{
1396 int i, j;
1397
1398 /* first check that the traps are rectilinear */
1399 if (antialias == CAIRO_ANTIALIAS_NONE) {
1400 for (i = 0; i < traps->num_traps; i++) {
1401 const cairo_trapezoid_t *t = &traps->traps[i];
1402 if (_cairo_fixed_integer_round_down (t->left.p1.x) !=
1403 _cairo_fixed_integer_round_down (t->left.p2.x) ||
1404 _cairo_fixed_integer_round_down (t->right.p1.x) !=
1405 _cairo_fixed_integer_round_down (t->right.p2.x))
1406 {
1407 return CAIRO_INT_STATUS_UNSUPPORTED;
1408 }
1409 }
1410 } else {
1411 for (i = 0; i < traps->num_traps; i++) {
1412 const cairo_trapezoid_t *t = &traps->traps[i];
1413 if (t->left.p1.x != t->left.p2.x || t->right.p1.x != t->right.p2.x)
1414 return CAIRO_INT_STATUS_UNSUPPORTED;
1415 }
1416 }
1417
1418 _cairo_boxes_init (boxes);
1419
1420 boxes->chunks.base = (cairo_box_t *) traps->traps;
1421 boxes->chunks.size = traps->num_traps;
1422
1423 if (antialias != CAIRO_ANTIALIAS_NONE) {
1424 for (i = j = 0; i < traps->num_traps; i++) {
1425 /* Note the traps and boxes alias so we need to take the local copies first. */
1426 cairo_fixed_t x1 = traps->traps[i].left.p1.x;
1427 cairo_fixed_t x2 = traps->traps[i].right.p1.x;
1428 cairo_fixed_t y1 = traps->traps[i].top;
1429 cairo_fixed_t y2 = traps->traps[i].bottom;
1430
1431 if (x1 == x2 || y1 == y2)
1432 continue;
1433
1434 boxes->chunks.base[j].p1.x = x1;
1435 boxes->chunks.base[j].p1.y = y1;
1436 boxes->chunks.base[j].p2.x = x2;
1437 boxes->chunks.base[j].p2.y = y2;
1438 j++;
1439
1440 if (boxes->is_pixel_aligned) {
1441 boxes->is_pixel_aligned =
1442 _cairo_fixed_is_integer (x1) && _cairo_fixed_is_integer (y1) &&
1443 _cairo_fixed_is_integer (x2) && _cairo_fixed_is_integer (y2);
1444 }
1445 }
1446 } else {
1447 boxes->is_pixel_aligned = TRUE1;
1448
1449 for (i = j = 0; i < traps->num_traps; i++) {
1450 /* Note the traps and boxes alias so we need to take the local copies first. */
1451 cairo_fixed_t x1 = traps->traps[i].left.p1.x;
1452 cairo_fixed_t x2 = traps->traps[i].right.p1.x;
1453 cairo_fixed_t y1 = traps->traps[i].top;
1454 cairo_fixed_t y2 = traps->traps[i].bottom;
1455
1456 /* round down here to match Pixman's behavior when using traps. */
1457 boxes->chunks.base[j].p1.x = _cairo_fixed_round_down (x1);
1458 boxes->chunks.base[j].p1.y = _cairo_fixed_round_down (y1);
1459 boxes->chunks.base[j].p2.x = _cairo_fixed_round_down (x2);
1460 boxes->chunks.base[j].p2.y = _cairo_fixed_round_down (y2);
1461 j += (boxes->chunks.base[j].p1.x != boxes->chunks.base[j].p2.x &&
1462 boxes->chunks.base[j].p1.y != boxes->chunks.base[j].p2.y);
1463 }
1464 }
1465 boxes->chunks.count = j;
1466 boxes->num_boxes = j;
1467
1468 return CAIRO_INT_STATUS_SUCCESS;
1469}
1470
1471static cairo_status_t
1472clip_and_composite_boxes (const cairo_traps_compositor_t *compositor,
1473 cairo_composite_rectangles_t *extents,
1474 cairo_boxes_t *boxes);
1475
1476static cairo_status_t
1477clip_and_composite_polygon (const cairo_traps_compositor_t *compositor,
1478 cairo_composite_rectangles_t *extents,
1479 cairo_polygon_t *polygon,
1480 cairo_antialias_t antialias,
1481 cairo_fill_rule_t fill_rule,
1482 cairo_bool_t curvy)
1483{
1484 composite_traps_info_t traps;
1485 cairo_surface_t *dst = extents->surface;
1486 cairo_bool_t clip_surface = ! _cairo_clip_is_region (extents->clip);
1487 cairo_int_status_t status;
1488
1489 TRACE ((stderr, "%s\n", __FUNCTION__));
1490
1491 if (polygon->num_edges == 0) {
1492 status = CAIRO_INT_STATUS_SUCCESS;
1493
1494 if (! extents->is_bounded) {
1495 cairo_region_t *clip_region = _cairo_clip_get_region (extents->clip);
1496
1497 if (clip_region &&
1498 cairo_region_contains_rectangle_moz_cairo_region_contains_rectangle (clip_region,
1499 &extents->unbounded) == CAIRO_REGION_OVERLAP_IN)
1500 clip_region = NULL((void*)0);
1501
1502 if (clip_region != NULL((void*)0)) {
1503 status = compositor->set_clip_region (dst, clip_region);
1504 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1505 return status;
1506 }
1507
1508 if (clip_surface)
1509 status = fixup_unbounded_with_mask (compositor, extents);
1510 else
1511 status = fixup_unbounded (compositor, extents, NULL((void*)0));
1512
1513 if (clip_region != NULL((void*)0))
1514 compositor->set_clip_region (dst, NULL((void*)0));
1515 }
1516
1517 return status;
1518 }
1519
1520 if (extents->clip->path != NULL((void*)0) && extents->is_bounded) {
1521 cairo_polygon_t clipper;
1522 cairo_fill_rule_t clipper_fill_rule;
1523 cairo_antialias_t clipper_antialias;
1524
1525 status = _cairo_clip_get_polygon (extents->clip,
1526 &clipper,
1527 &clipper_fill_rule,
1528 &clipper_antialias);
1529 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
) {
1530 if (clipper_antialias == antialias) {
1531 status = _cairo_polygon_intersect (polygon, fill_rule,
1532 &clipper, clipper_fill_rule);
1533 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
) {
1534 cairo_clip_t * clip = _cairo_clip_copy_region (extents->clip);
1535 _cairo_clip_destroy (extents->clip);
1536 extents->clip = clip;
1537
1538 fill_rule = CAIRO_FILL_RULE_WINDING;
1539 }
1540 _cairo_polygon_fini (&clipper);
1541 }
1542 }
1543 }
1544
1545 if (antialias == CAIRO_ANTIALIAS_NONE && curvy) {
1546 cairo_boxes_t boxes;
1547
1548 _cairo_boxes_init (&boxes);
1549 status = _cairo_rasterise_polygon_to_boxes (polygon, fill_rule, &boxes);
1550 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
) {
1551 assert (boxes.is_pixel_aligned)((void) sizeof ((boxes.is_pixel_aligned) ? 1 : 0), __extension__
({ if (boxes.is_pixel_aligned) ; else __assert_fail ("boxes.is_pixel_aligned"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-traps-compositor.c"
, 1551, __extension__ __PRETTY_FUNCTION__); }))
;
1552 status = clip_and_composite_boxes (compositor, extents, &boxes);
1553 }
1554 _cairo_boxes_fini (&boxes);
1555 if ((status != CAIRO_INT_STATUS_UNSUPPORTED))
1556 return status;
1557 }
1558
1559 _cairo_traps_init (&traps.traps);
1560
1561 if (antialias == CAIRO_ANTIALIAS_NONE && curvy) {
1562 status = _cairo_rasterise_polygon_to_traps (polygon, fill_rule, antialias, &traps.traps);
1563 } else {
1564 status = _cairo_bentley_ottmann_tessellate_polygon (&traps.traps, polygon, fill_rule);
1565 }
1566 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1567 goto CLEANUP_TRAPS;
1568
1569 status = trim_extents_to_traps (extents, &traps.traps);
1570 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1571 goto CLEANUP_TRAPS;
1572
1573 /* Use a fast path if the trapezoids consist of a set of boxes. */
1574 status = CAIRO_INT_STATUS_UNSUPPORTED;
Value stored to 'status' is never read
1575 if (1) {
1576 cairo_boxes_t boxes;
1577
1578 status = boxes_for_traps (&boxes, &traps.traps, antialias);
1579 if (status == CAIRO_INT_STATUS_SUCCESS) {
1580 status = clip_and_composite_boxes (compositor, extents, &boxes);
1581 /* XXX need to reconstruct the traps! */
1582 assert (status != CAIRO_INT_STATUS_UNSUPPORTED)((void) sizeof ((status != CAIRO_INT_STATUS_UNSUPPORTED) ? 1 :
0), __extension__ ({ if (status != CAIRO_INT_STATUS_UNSUPPORTED
) ; else __assert_fail ("status != CAIRO_INT_STATUS_UNSUPPORTED"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-traps-compositor.c"
, 1582, __extension__ __PRETTY_FUNCTION__); }))
;
1583 }
1584 }
1585 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1586 /* Otherwise render the trapezoids to a mask and composite in the usual
1587 * fashion.
1588 */
1589 unsigned int flags = 0;
1590
1591 /* For unbounded operations, the X11 server will estimate the
1592 * affected rectangle and apply the operation to that. However,
1593 * there are cases where this is an overestimate (e.g. the
1594 * clip-fill-{eo,nz}-unbounded test).
1595 *
1596 * The clip will trim that overestimate to our expectations.
1597 */
1598 if (! extents->is_bounded)
1599 flags |= FORCE_CLIP_REGION;
1600
1601 traps.antialias = antialias;
1602 status = clip_and_composite (compositor, extents,
1603 composite_traps, NULL((void*)0), &traps,
1604 need_unbounded_clip (extents) | flags);
1605 }
1606
1607CLEANUP_TRAPS:
1608 _cairo_traps_fini (&traps.traps);
1609
1610 return status;
1611}
1612
1613struct composite_opacity_info {
1614 const cairo_traps_compositor_t *compositor;
1615 uint8_t op;
1616 cairo_surface_t *dst;
1617 cairo_surface_t *src;
1618 int src_x, src_y;
1619 double opacity;
1620};
1621
1622static void composite_opacity(void *closure,
1623 int16_t x, int16_t y,
1624 int16_t w, int16_t h,
1625 uint16_t coverage)
1626{
1627 struct composite_opacity_info *info = closure;
1628 const cairo_traps_compositor_t *compositor = info->compositor;
1629 cairo_surface_t *mask;
1630 int mask_x, mask_y;
1631 cairo_color_t color;
1632 cairo_solid_pattern_t solid;
1633
1634 _cairo_color_init_rgba (&color, 0, 0, 0, info->opacity * coverage);
1635 _cairo_pattern_init_solid (&solid, &color);
1636 mask = compositor->pattern_to_surface (info->dst, &solid.base, TRUE1,
1637 &_cairo_unbounded_rectangle,
1638 &_cairo_unbounded_rectangle,
1639 &mask_x, &mask_y);
1640 if (likely (mask->status == CAIRO_STATUS_SUCCESS)(__builtin_expect (!!(mask->status == CAIRO_STATUS_SUCCESS
), 1))
) {
1641 if (info->src) {
1642 compositor->composite (info->dst, info->op, info->src, mask,
1643 x + info->src_x, y + info->src_y,
1644 mask_x, mask_y,
1645 x, y,
1646 w, h);
1647 } else {
1648 compositor->composite (info->dst, info->op, mask, NULL((void*)0),
1649 mask_x, mask_y,
1650 0, 0,
1651 x, y,
1652 w, h);
1653 }
1654 }
1655
1656 cairo_surface_destroy_moz_cairo_surface_destroy (mask);
1657}
1658
1659
1660static cairo_int_status_t
1661composite_opacity_boxes (const cairo_traps_compositor_t *compositor,
1662 cairo_surface_t *dst,
1663 void *closure,
1664 cairo_operator_t op,
1665 cairo_surface_t *src,
1666 int src_x,
1667 int src_y,
1668 int dst_x,
1669 int dst_y,
1670 const cairo_rectangle_int_t *extents,
1671 cairo_clip_t *clip)
1672{
1673 const cairo_solid_pattern_t *mask = closure;
1674 struct composite_opacity_info info;
1675 int i;
1676
1677 TRACE ((stderr, "%s\n", __FUNCTION__));
1678
1679 info.compositor = compositor;
1680 info.op = op;
1681 info.dst = dst;
1682
1683 info.src = src;
1684 info.src_x = src_x;
1685 info.src_y = src_y;
1686
1687 info.opacity = mask->color.alpha / (double) 0xffff;
1688
1689 /* XXX for lots of boxes create a clip region for the fully opaque areas */
1690 for (i = 0; i < clip->num_boxes; i++)
1691 do_unaligned_box(composite_opacity, &info,
1692 &clip->boxes[i], dst_x, dst_y);
1693
1694 return CAIRO_STATUS_SUCCESS;
1695}
1696
1697static cairo_int_status_t
1698composite_boxes (const cairo_traps_compositor_t *compositor,
1699 cairo_surface_t *dst,
1700 void *closure,
1701 cairo_operator_t op,
1702 cairo_surface_t *src,
1703 int src_x,
1704 int src_y,
1705 int dst_x,
1706 int dst_y,
1707 const cairo_rectangle_int_t *extents,
1708 cairo_clip_t *clip)
1709{
1710 cairo_traps_t traps;
1711 cairo_status_t status;
1712
1713 TRACE ((stderr, "%s\n", __FUNCTION__));
1714
1715 status = _cairo_traps_init_boxes (&traps, closure);
1716 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1717 return status;
1718
1719 status = compositor->composite_traps (dst, op, src,
1720 src_x - dst_x, src_y - dst_y,
1721 dst_x, dst_y,
1722 extents,
1723 CAIRO_ANTIALIAS_DEFAULT, &traps);
1724 _cairo_traps_fini (&traps);
1725
1726 return status;
1727}
1728
1729static cairo_status_t
1730clip_and_composite_boxes (const cairo_traps_compositor_t *compositor,
1731 cairo_composite_rectangles_t *extents,
1732 cairo_boxes_t *boxes)
1733{
1734 cairo_int_status_t status;
1735
1736 TRACE ((stderr, "%s\n", __FUNCTION__));
1737
1738 if (boxes->num_boxes == 0 && extents->is_bounded)
1739 return CAIRO_STATUS_SUCCESS;
1740
1741 status = trim_extents_to_boxes (extents, boxes);
1742 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1743 return status;
1744
1745 if (boxes->is_pixel_aligned && extents->clip->path == NULL((void*)0) &&
1746 extents->source_pattern.base.type == CAIRO_PATTERN_TYPE_SURFACE &&
1747 (op_reduces_to_source (extents) ||
1748 (extents->op == CAIRO_OPERATOR_OVER &&
1749 (extents->source_pattern.surface.surface->content & CAIRO_CONTENT_ALPHA) == 0)))
1750 {
1751 status = upload_boxes (compositor, extents, boxes);
1752 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1753 return status;
1754 }
1755
1756 /* Can we reduce drawing through a clip-mask to simply drawing the clip? */
1757 if (extents->clip->path != NULL((void*)0) && extents->is_bounded) {
1758 cairo_polygon_t polygon;
1759 cairo_fill_rule_t fill_rule;
1760 cairo_antialias_t antialias;
1761 cairo_clip_t *clip;
1762
1763 clip = _cairo_clip_copy (extents->clip);
1764 clip = _cairo_clip_intersect_boxes (clip, boxes);
1765 if (_cairo_clip_is_all_clipped (clip))
1766 return CAIRO_INT_STATUS_NOTHING_TO_DO;
1767
1768 status = _cairo_clip_get_polygon (clip, &polygon,
1769 &fill_rule, &antialias);
1770 _cairo_clip_path_destroy (clip->path);
1771 clip->path = NULL((void*)0);
1772 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
) {
1773 cairo_clip_t *saved_clip = extents->clip;
1774 extents->clip = clip;
1775
1776 status = clip_and_composite_polygon (compositor, extents, &polygon,
1777 antialias, fill_rule, FALSE0);
1778
1779 clip = extents->clip;
1780 extents->clip = saved_clip;
1781
1782 _cairo_polygon_fini (&polygon);
1783 }
1784 _cairo_clip_destroy (clip);
1785
1786 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1787 return status;
1788 }
1789
1790 /* Use a fast path if the boxes are pixel aligned (or nearly aligned!) */
1791 if (boxes->is_pixel_aligned) {
1792 status = composite_aligned_boxes (compositor, extents, boxes);
1793 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1794 return status;
1795 }
1796
1797 return clip_and_composite (compositor, extents,
1798 composite_boxes, NULL((void*)0), boxes,
1799 need_unbounded_clip (extents));
1800}
1801
1802static cairo_int_status_t
1803composite_traps_as_boxes (const cairo_traps_compositor_t *compositor,
1804 cairo_composite_rectangles_t *extents,
1805 composite_traps_info_t *info)
1806{
1807 cairo_boxes_t boxes;
1808
1809 TRACE ((stderr, "%s\n", __FUNCTION__));
1810
1811 if (! _cairo_traps_to_boxes (&info->traps, info->antialias, &boxes))
1812 return CAIRO_INT_STATUS_UNSUPPORTED;
1813
1814 return clip_and_composite_boxes (compositor, extents, &boxes);
1815}
1816
1817static cairo_int_status_t
1818clip_and_composite_traps (const cairo_traps_compositor_t *compositor,
1819 cairo_composite_rectangles_t *extents,
1820 composite_traps_info_t *info,
1821 unsigned flags)
1822{
1823 cairo_int_status_t status;
1824
1825 TRACE ((stderr, "%s\n", __FUNCTION__));
1826
1827 status = trim_extents_to_traps (extents, &info->traps);
1828 if (unlikely (status != CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status != CAIRO_INT_STATUS_SUCCESS), 0)
)
)
1829 return status;
1830
1831 status = CAIRO_INT_STATUS_UNSUPPORTED;
1832 if ((flags & FORCE_CLIP_REGION) == 0)
1833 status = composite_traps_as_boxes (compositor, extents, info);
1834 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1835 /* For unbounded operations, the X11 server will estimate the
1836 * affected rectangle and apply the operation to that. However,
1837 * there are cases where this is an overestimate (e.g. the
1838 * clip-fill-{eo,nz}-unbounded test).
1839 *
1840 * The clip will trim that overestimate to our expectations.
1841 */
1842 if (! extents->is_bounded)
1843 flags |= FORCE_CLIP_REGION;
1844
1845 status = clip_and_composite (compositor, extents,
1846 composite_traps, NULL((void*)0), info,
1847 need_unbounded_clip (extents) | flags);
1848 }
1849
1850 return status;
1851}
1852
1853static cairo_int_status_t
1854clip_and_composite_tristrip (const cairo_traps_compositor_t *compositor,
1855 cairo_composite_rectangles_t *extents,
1856 composite_tristrip_info_t *info)
1857{
1858 cairo_int_status_t status;
1859 unsigned int flags = 0;
1860
1861 TRACE ((stderr, "%s\n", __FUNCTION__));
1862
1863 status = trim_extents_to_tristrip (extents, &info->strip);
1864 if (unlikely (status != CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status != CAIRO_INT_STATUS_SUCCESS), 0)
)
)
1865 return status;
1866
1867 if (! extents->is_bounded)
1868 flags |= FORCE_CLIP_REGION;
1869
1870 status = clip_and_composite (compositor, extents,
1871 composite_tristrip, NULL((void*)0), info,
1872 need_unbounded_clip (extents) | flags);
1873
1874 return status;
1875}
1876
1877struct composite_mask {
1878 cairo_surface_t *mask;
1879 int mask_x, mask_y;
1880};
1881
1882static cairo_int_status_t
1883composite_mask (const cairo_traps_compositor_t *compositor,
1884 cairo_surface_t *dst,
1885 void *closure,
1886 cairo_operator_t op,
1887 cairo_surface_t *src,
1888 int src_x,
1889 int src_y,
1890 int dst_x,
1891 int dst_y,
1892 const cairo_rectangle_int_t *extents,
1893 cairo_clip_t *clip)
1894{
1895 struct composite_mask *data = closure;
1896
1897 TRACE ((stderr, "%s\n", __FUNCTION__));
1898
1899 if (src != NULL((void*)0)) {
1900 compositor->composite (dst, op, src, data->mask,
1901 extents->x + src_x, extents->y + src_y,
1902 extents->x + data->mask_x, extents->y + data->mask_y,
1903 extents->x - dst_x, extents->y - dst_y,
1904 extents->width, extents->height);
1905 } else {
1906 compositor->composite (dst, op, data->mask, NULL((void*)0),
1907 extents->x + data->mask_x, extents->y + data->mask_y,
1908 0, 0,
1909 extents->x - dst_x, extents->y - dst_y,
1910 extents->width, extents->height);
1911 }
1912
1913 return CAIRO_STATUS_SUCCESS;
1914}
1915
1916struct composite_box_info {
1917 const cairo_traps_compositor_t *compositor;
1918 cairo_surface_t *dst;
1919 cairo_surface_t *src;
1920 int src_x, src_y;
1921 uint8_t op;
1922};
1923
1924static void composite_box(void *closure,
1925 int16_t x, int16_t y,
1926 int16_t w, int16_t h,
1927 uint16_t coverage)
1928{
1929 struct composite_box_info *info = closure;
1930 const cairo_traps_compositor_t *compositor = info->compositor;
1931
1932 TRACE ((stderr, "%s\n", __FUNCTION__));
1933
1934 if (! CAIRO_ALPHA_SHORT_IS_OPAQUE (coverage)((coverage) >= 0xff00)) {
1935 cairo_surface_t *mask;
1936 cairo_color_t color;
1937 cairo_solid_pattern_t solid;
1938 int mask_x, mask_y;
1939
1940 _cairo_color_init_rgba (&color, 0, 0, 0, coverage / (double)0xffff);
1941 _cairo_pattern_init_solid (&solid, &color);
1942
1943 mask = compositor->pattern_to_surface (info->dst, &solid.base, FALSE0,
1944 &_cairo_unbounded_rectangle,
1945 &_cairo_unbounded_rectangle,
1946 &mask_x, &mask_y);
1947
1948 if (likely (mask->status == CAIRO_STATUS_SUCCESS)(__builtin_expect (!!(mask->status == CAIRO_STATUS_SUCCESS
), 1))
) {
1949 compositor->composite (info->dst, info->op, info->src, mask,
1950 x + info->src_x, y + info->src_y,
1951 mask_x, mask_y,
1952 x, y,
1953 w, h);
1954 }
1955
1956 cairo_surface_destroy_moz_cairo_surface_destroy (mask);
1957 } else {
1958 compositor->composite (info->dst, info->op, info->src, NULL((void*)0),
1959 x + info->src_x, y + info->src_y,
1960 0, 0,
1961 x, y,
1962 w, h);
1963 }
1964}
1965
1966static cairo_int_status_t
1967composite_mask_clip_boxes (const cairo_traps_compositor_t *compositor,
1968 cairo_surface_t *dst,
1969 void *closure,
1970 cairo_operator_t op,
1971 cairo_surface_t *src,
1972 int src_x,
1973 int src_y,
1974 int dst_x,
1975 int dst_y,
1976 const cairo_rectangle_int_t *extents,
1977 cairo_clip_t *clip)
1978{
1979 struct composite_mask *data = closure;
1980 struct composite_box_info info;
1981 int i;
1982
1983 TRACE ((stderr, "%s\n", __FUNCTION__));
1984
1985 info.compositor = compositor;
1986 info.op = CAIRO_OPERATOR_SOURCE;
1987 info.dst = dst;
1988 info.src = data->mask;
1989 info.src_x = data->mask_x;
1990 info.src_y = data->mask_y;
1991
1992 info.src_x += dst_x;
1993 info.src_y += dst_y;
1994
1995 for (i = 0; i < clip->num_boxes; i++)
1996 do_unaligned_box(composite_box, &info, &clip->boxes[i], dst_x, dst_y);
1997
1998 return CAIRO_STATUS_SUCCESS;
1999}
2000
2001static cairo_int_status_t
2002composite_mask_clip (const cairo_traps_compositor_t *compositor,
2003 cairo_surface_t *dst,
2004 void *closure,
2005 cairo_operator_t op,
2006 cairo_surface_t *src,
2007 int src_x,
2008 int src_y,
2009 int dst_x,
2010 int dst_y,
2011 const cairo_rectangle_int_t *extents,
2012 cairo_clip_t *clip)
2013{
2014 struct composite_mask *data = closure;
2015 cairo_polygon_t polygon;
2016 cairo_fill_rule_t fill_rule;
2017 composite_traps_info_t info;
2018 cairo_status_t status;
2019
2020 TRACE ((stderr, "%s\n", __FUNCTION__));
2021
2022 status = _cairo_clip_get_polygon (clip, &polygon,
2023 &fill_rule, &info.antialias);
2024 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2025 return status;
2026
2027 _cairo_traps_init (&info.traps);
2028 status = _cairo_bentley_ottmann_tessellate_polygon (&info.traps,
2029 &polygon,
2030 fill_rule);
2031 _cairo_polygon_fini (&polygon);
2032 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2033 return status;
2034
2035 status = composite_traps (compositor, dst, &info,
2036 CAIRO_OPERATOR_SOURCE,
2037 data->mask,
2038 data->mask_x + dst_x, data->mask_y + dst_y,
2039 dst_x, dst_y,
2040 extents, NULL((void*)0));
2041 _cairo_traps_fini (&info.traps);
2042
2043 return status;
2044}
2045
2046/* high-level compositor interface */
2047
2048static cairo_int_status_t
2049_cairo_traps_compositor_paint (const cairo_compositor_t *_compositor,
2050 cairo_composite_rectangles_t *extents)
2051{
2052 cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t*)_compositor;
2053 cairo_boxes_t boxes;
2054 cairo_int_status_t status;
2055
2056 TRACE ((stderr, "%s\n", __FUNCTION__));
2057
2058 status = compositor->check_composite (extents);
2059 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2060 return status;
2061
2062 _cairo_clip_steal_boxes (extents->clip, &boxes);
2063 status = clip_and_composite_boxes (compositor, extents, &boxes);
2064 _cairo_clip_unsteal_boxes (extents->clip, &boxes);
2065
2066 return status;
2067}
2068
2069static cairo_int_status_t
2070_cairo_traps_compositor_mask (const cairo_compositor_t *_compositor,
2071 cairo_composite_rectangles_t *extents)
2072{
2073 const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t*)_compositor;
2074 cairo_int_status_t status;
2075
2076 TRACE ((stderr, "%s\n", __FUNCTION__));
2077
2078 status = compositor->check_composite (extents);
2079 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2080 return status;
2081
2082 if (extents->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID &&
2083 extents->clip->path == NULL((void*)0)) {
2084 status = clip_and_composite (compositor, extents,
2085 composite_opacity_boxes,
2086 composite_opacity_boxes,
2087 &extents->mask_pattern,
2088 need_unbounded_clip (extents));
2089 } else {
2090 struct composite_mask data;
2091
2092 data.mask = compositor->pattern_to_surface (extents->surface,
2093 &extents->mask_pattern.base,
2094 TRUE1,
2095 &extents->bounded,
2096 &extents->mask_sample_area,
2097 &data.mask_x,
2098 &data.mask_y);
2099 if (unlikely (data.mask->status)(__builtin_expect (!!(data.mask->status), 0)))
2100 return data.mask->status;
2101
2102 status = clip_and_composite (compositor, extents,
2103 composite_mask,
2104 extents->clip->path ? composite_mask_clip : composite_mask_clip_boxes,
2105 &data, need_bounded_clip (extents));
2106
2107 cairo_surface_destroy_moz_cairo_surface_destroy (data.mask);
2108 }
2109
2110 return status;
2111}
2112
2113static cairo_int_status_t
2114_cairo_traps_compositor_stroke (const cairo_compositor_t *_compositor,
2115 cairo_composite_rectangles_t *extents,
2116 const cairo_path_fixed_t *path,
2117 const cairo_stroke_style_t *style,
2118 const cairo_matrix_t *ctm,
2119 const cairo_matrix_t *ctm_inverse,
2120 double tolerance,
2121 cairo_antialias_t antialias)
2122{
2123 const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
2124 cairo_int_status_t status;
2125
2126 TRACE ((stderr, "%s\n", __FUNCTION__));
2127
2128 status = compositor->check_composite (extents);
2129 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2130 return status;
2131
2132 status = CAIRO_INT_STATUS_UNSUPPORTED;
2133 if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
2134 cairo_boxes_t boxes;
2135
2136 _cairo_boxes_init_with_clip (&boxes, extents->clip);
2137 status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
2138 style,
2139 ctm,
2140 antialias,
2141 &boxes);
2142 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
)
2143 status = clip_and_composite_boxes (compositor, extents, &boxes);
2144 _cairo_boxes_fini (&boxes);
2145 }
2146
2147 if (status == CAIRO_INT_STATUS_UNSUPPORTED && 0 &&
2148 _cairo_clip_is_region (extents->clip)) /* XXX */
2149 {
2150 composite_tristrip_info_t info;
2151
2152 info.antialias = antialias;
2153 _cairo_tristrip_init_with_clip (&info.strip, extents->clip);
2154 status = _cairo_path_fixed_stroke_to_tristrip (path, style,
2155 ctm, ctm_inverse,
2156 tolerance,
2157 &info.strip);
2158 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
)
2159 status = clip_and_composite_tristrip (compositor, extents, &info);
2160 _cairo_tristrip_fini (&info.strip);
2161 }
2162
2163 if (status == CAIRO_INT_STATUS_UNSUPPORTED &&
2164 path->has_curve_to && antialias == CAIRO_ANTIALIAS_NONE) {
2165 cairo_polygon_t polygon;
2166
2167 _cairo_polygon_init_with_clip (&polygon, extents->clip);
2168 status = _cairo_path_fixed_stroke_to_polygon (path, style,
2169 ctm, ctm_inverse,
2170 tolerance,
2171 &polygon);
2172 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
)
2173 status = clip_and_composite_polygon (compositor,
2174 extents, &polygon,
2175 CAIRO_ANTIALIAS_NONE,
2176 CAIRO_FILL_RULE_WINDING,
2177 TRUE1);
2178 _cairo_polygon_fini (&polygon);
2179 }
2180
2181 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
2182 cairo_int_status_t (*func) (const cairo_path_fixed_t *path,
2183 const cairo_stroke_style_t *stroke_style,
2184 const cairo_matrix_t *ctm,
2185 const cairo_matrix_t *ctm_inverse,
2186 double tolerance,
2187 cairo_traps_t *traps);
2188 composite_traps_info_t info;
2189 unsigned flags;
2190
2191 if (antialias == CAIRO_ANTIALIAS_BEST || antialias == CAIRO_ANTIALIAS_GOOD) {
2192 func = _cairo_path_fixed_stroke_polygon_to_traps;
2193 flags = 0;
2194 } else {
2195 func = _cairo_path_fixed_stroke_to_traps;
2196 flags = need_bounded_clip (extents) & ~NEED_CLIP_SURFACE;
2197 }
2198
2199 info.antialias = antialias;
2200 _cairo_traps_init_with_clip (&info.traps, extents->clip);
2201 status = func (path, style, ctm, ctm_inverse, tolerance, &info.traps);
2202 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
)
2203 status = clip_and_composite_traps (compositor, extents, &info, flags);
2204 _cairo_traps_fini (&info.traps);
2205 }
2206
2207 return status;
2208}
2209
2210static cairo_int_status_t
2211_cairo_traps_compositor_fill (const cairo_compositor_t *_compositor,
2212 cairo_composite_rectangles_t *extents,
2213 const cairo_path_fixed_t *path,
2214 cairo_fill_rule_t fill_rule,
2215 double tolerance,
2216 cairo_antialias_t antialias)
2217{
2218 const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
2219 cairo_int_status_t status;
2220
2221 TRACE ((stderr, "%s\n", __FUNCTION__));
2222
2223 status = compositor->check_composite (extents);
2224 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2225 return status;
2226
2227 status = CAIRO_INT_STATUS_UNSUPPORTED;
2228 if (_cairo_path_fixed_fill_is_rectilinear (path)) {
2229 cairo_boxes_t boxes;
2230
2231 _cairo_boxes_init_with_clip (&boxes, extents->clip);
2232 status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
2233 fill_rule,
2234 antialias,
2235 &boxes);
2236 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
)
2237 status = clip_and_composite_boxes (compositor, extents, &boxes);
2238 _cairo_boxes_fini (&boxes);
2239 }
2240
2241 if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
2242 cairo_polygon_t polygon;
2243
2244#if 0
2245 if (extents->mask.width > extents->unbounded.width ||
2246 extents->mask.height > extents->unbounded.height)
2247 {
2248 cairo_box_t limits;
2249 _cairo_box_from_rectangle (&limits, &extents->unbounded);
2250 _cairo_polygon_init (&polygon, &limits, 1);
2251 }
2252 else
2253 {
2254 _cairo_polygon_init (&polygon, NULL((void*)0), 0);
2255 }
2256
2257 status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
2258 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
) {
2259 status = _cairo_polygon_intersect_with_boxes (&polygon, &fill_rule,
2260 extents->clip->boxes,
2261 extents->clip->num_boxes);
2262 }
2263#else
2264 _cairo_polygon_init_with_clip (&polygon, extents->clip);
2265 status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
2266#endif
2267 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
) {
2268 status = clip_and_composite_polygon (compositor, extents, &polygon,
2269 antialias, fill_rule, path->has_curve_to);
2270 }
2271 _cairo_polygon_fini (&polygon);
2272 }
2273
2274 return status;
2275}
2276
2277static cairo_int_status_t
2278composite_glyphs (const cairo_traps_compositor_t *compositor,
2279 cairo_surface_t *dst,
2280 void *closure,
2281 cairo_operator_t op,
2282 cairo_surface_t *src,
2283 int src_x, int src_y,
2284 int dst_x, int dst_y,
2285 const cairo_rectangle_int_t *extents,
2286 cairo_clip_t *clip)
2287{
2288 cairo_composite_glyphs_info_t *info = closure;
2289
2290 TRACE ((stderr, "%s\n", __FUNCTION__));
2291
2292 if (op == CAIRO_OPERATOR_ADD && (dst->content & CAIRO_CONTENT_COLOR) == 0)
2293 info->use_mask = 0;
2294
2295 return compositor->composite_glyphs (dst, op, src,
2296 src_x, src_y,
2297 dst_x, dst_y,
2298 info);
2299}
2300
2301static cairo_int_status_t
2302_cairo_traps_compositor_glyphs (const cairo_compositor_t *_compositor,
2303 cairo_composite_rectangles_t *extents,
2304 cairo_scaled_font_t *scaled_font,
2305 cairo_glyph_t *glyphs,
2306 int num_glyphs,
2307 cairo_bool_t overlap)
2308{
2309 const cairo_traps_compositor_t *compositor = (cairo_traps_compositor_t *)_compositor;
2310 cairo_int_status_t status;
2311
2312 TRACE ((stderr, "%s\n", __FUNCTION__));
2313
2314 status = compositor->check_composite (extents);
2315 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2316 return status;
2317
2318 _cairo_scaled_font_freeze_cache (scaled_font);
2319 status = compositor->check_composite_glyphs (extents,
2320 scaled_font, glyphs,
2321 &num_glyphs);
2322 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
) {
2323 cairo_composite_glyphs_info_t info;
2324
2325 info.font = scaled_font;
2326 info.glyphs = glyphs;
2327 info.num_glyphs = num_glyphs;
2328 info.use_mask = overlap || ! extents->is_bounded;
2329 info.extents = extents->bounded;
2330
2331 status = clip_and_composite (compositor, extents,
2332 composite_glyphs, NULL((void*)0), &info,
2333 need_bounded_clip (extents) | FORCE_CLIP_REGION);
2334 }
2335 _cairo_scaled_font_thaw_cache (scaled_font);
2336
2337 return status;
2338}
2339
2340void
2341_cairo_traps_compositor_init (cairo_traps_compositor_t *compositor,
2342 const cairo_compositor_t *delegate)
2343{
2344 compositor->base.delegate = delegate;
2345
2346 compositor->base.paint = _cairo_traps_compositor_paint;
2347 compositor->base.mask = _cairo_traps_compositor_mask;
2348 compositor->base.fill = _cairo_traps_compositor_fill;
2349 compositor->base.stroke = _cairo_traps_compositor_stroke;
2350 compositor->base.glyphs = _cairo_traps_compositor_glyphs;
2351}