Bug Summary

File:root/firefox-clang/gfx/cairo/cairo/src/cairo-image-compositor.c
Warning:line 1098, 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 Unified_c_gfx_cairo_cairo_src2.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 Unified_c_gfx_cairo_cairo_src2.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 © 2003 University of Southern California
5 * Copyright © 2009,2010,2011 Intel Corporation
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it either under the terms of the GNU Lesser General Public
9 * License version 2.1 as published by the Free Software Foundation
10 * (the "LGPL") or, at your option, under the terms of the Mozilla
11 * Public License Version 1.1 (the "MPL"). If you do not alter this
12 * notice, a recipient may use your version of this file under either
13 * the MPL or the LGPL.
14 *
15 * You should have received a copy of the LGPL along with this library
16 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
18 * You should have received a copy of the MPL along with this library
19 * in the file COPYING-MPL-1.1
20 *
21 * The contents of this file are subject to the Mozilla Public License
22 * Version 1.1 (the "License"); you may not use this file except in
23 * compliance with the License. You may obtain a copy of the License at
24 * http://www.mozilla.org/MPL/
25 *
26 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28 * the specific language governing rights and limitations.
29 *
30 * The Original Code is the cairo graphics library.
31 *
32 * The Initial Developer of the Original Code is University of Southern
33 * California.
34 *
35 * Contributor(s):
36 * Carl D. Worth <cworth@cworth.org>
37 * Chris Wilson <chris@chris-wilson.co.uk>
38 */
39
40/* The primarily reason for keeping a traps-compositor around is
41 * for validating cairo-xlib (which currently also uses traps).
42 */
43
44#include "cairoint.h"
45
46#include "cairo-image-surface-private.h"
47
48#include "cairo-compositor-private.h"
49#include "cairo-spans-compositor-private.h"
50
51#include "cairo-region-private.h"
52#include "cairo-traps-private.h"
53#include "cairo-tristrip-private.h"
54
55#include "cairo-pixman-private.h"
56
57static pixman_image_t *
58to_pixman_image (cairo_surface_t *s)
59{
60 return ((cairo_image_surface_t *)s)->pixman_image;
61}
62
63static cairo_int_status_t
64acquire (void *abstract_dst)
65{
66 return CAIRO_STATUS_SUCCESS;
67}
68
69static cairo_int_status_t
70release (void *abstract_dst)
71{
72 return CAIRO_STATUS_SUCCESS;
73}
74
75static cairo_int_status_t
76set_clip_region (void *_surface,
77 cairo_region_t *region)
78{
79 cairo_image_surface_t *surface = _surface;
80 pixman_region32_t *rgn = region ? &region->rgn : NULL((void*)0);
81
82 if (! pixman_image_set_clip_region32_moz_pixman_image_set_clip_region32 (surface->pixman_image, rgn))
83 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
84
85 return CAIRO_STATUS_SUCCESS;
86}
87
88static cairo_int_status_t
89draw_image_boxes (void *_dst,
90 cairo_image_surface_t *image,
91 cairo_boxes_t *boxes,
92 int dx, int dy)
93{
94 cairo_image_surface_t *dst = _dst;
95 struct _cairo_boxes_chunk *chunk;
96 int i;
97
98 TRACE ((stderr, "%s x %d\n", __FUNCTION__, boxes->num_boxes));
99
100 for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
101 for (i = 0; i < chunk->count; i++) {
102 cairo_box_t *b = &chunk->base[i];
103 int x = _cairo_fixed_integer_part (b->p1.x);
104 int y = _cairo_fixed_integer_part (b->p1.y);
105 int w = _cairo_fixed_integer_part (b->p2.x) - x;
106 int h = _cairo_fixed_integer_part (b->p2.y) - y;
107 if (dst->pixman_format != image->pixman_format ||
108 ! pixman_blt_moz_pixman_blt ((uint32_t *)image->data, (uint32_t *)dst->data,
109 image->stride / sizeof (uint32_t),
110 dst->stride / sizeof (uint32_t),
111 PIXMAN_FORMAT_BPP (image->pixman_format)(((image->pixman_format >> (24)) & ((1 << (
8)) - 1)) << ((image->pixman_format >> 22) &
3))
,
112 PIXMAN_FORMAT_BPP (dst->pixman_format)(((dst->pixman_format >> (24)) & ((1 << (8
)) - 1)) << ((dst->pixman_format >> 22) & 3
))
,
113 x + dx, y + dy,
114 x, y,
115 w, h))
116 {
117 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_SRC,
118 image->pixman_image, NULL((void*)0), dst->pixman_image,
119 x + dx, y + dy,
120 0, 0,
121 x, y,
122 w, h);
123 }
124 }
125 }
126 return CAIRO_STATUS_SUCCESS;
127}
128
129static inline uint32_t
130color_to_uint32 (const cairo_color_t *color)
131{
132 return
133 ((uint32_t)color->alpha_short >> 8 << 24) |
134 (color->red_short >> 8 << 16) |
135 (color->green_short & 0xff00) |
136 (color->blue_short >> 8);
137}
138
139static inline cairo_bool_t
140color_to_pixel (const cairo_color_t *color,
141 pixman_format_code_t format,
142 uint32_t *pixel)
143{
144 uint32_t c;
145
146 if (!(format == PIXMAN_a8r8g8b8 ||
147 format == PIXMAN_x8r8g8b8 ||
148 format == PIXMAN_a8b8g8r8 ||
149 format == PIXMAN_x8b8g8r8 ||
150 format == PIXMAN_b8g8r8a8 ||
151 format == PIXMAN_b8g8r8x8 ||
152 format == PIXMAN_r5g6b5 ||
153 format == PIXMAN_b5g6r5 ||
154 format == PIXMAN_a8))
155 {
156 return FALSE0;
157 }
158
159 c = color_to_uint32 (color);
160
161 if (PIXMAN_FORMAT_TYPE (format)(((format) >> 16) & 0x3f) == PIXMAN_TYPE_ABGR3) {
162 c = ((c & 0xff000000) >> 0) |
163 ((c & 0x00ff0000) >> 16) |
164 ((c & 0x0000ff00) >> 0) |
165 ((c & 0x000000ff) << 16);
166 }
167
168 if (PIXMAN_FORMAT_TYPE (format)(((format) >> 16) & 0x3f) == PIXMAN_TYPE_BGRA8) {
169 c = ((c & 0xff000000) >> 24) |
170 ((c & 0x00ff0000) >> 8) |
171 ((c & 0x0000ff00) << 8) |
172 ((c & 0x000000ff) << 24);
173 }
174
175 if (format == PIXMAN_a8) {
176 c = c >> 24;
177 } else if (format == PIXMAN_r5g6b5 || format == PIXMAN_b5g6r5) {
178 c = ((((c) >> 3) & 0x001f) |
179 (((c) >> 5) & 0x07e0) |
180 (((c) >> 8) & 0xf800));
181 }
182
183 *pixel = c;
184 return TRUE1;
185}
186
187static pixman_op_t
188_pixman_operator (cairo_operator_t op)
189{
190 switch ((int) op) {
191 case CAIRO_OPERATOR_CLEAR:
192 return PIXMAN_OP_CLEAR;
193
194 case CAIRO_OPERATOR_SOURCE:
195 return PIXMAN_OP_SRC;
196 case CAIRO_OPERATOR_OVER:
197 return PIXMAN_OP_OVER;
198 case CAIRO_OPERATOR_IN:
199 return PIXMAN_OP_IN;
200 case CAIRO_OPERATOR_OUT:
201 return PIXMAN_OP_OUT;
202 case CAIRO_OPERATOR_ATOP:
203 return PIXMAN_OP_ATOP;
204
205 case CAIRO_OPERATOR_DEST:
206 return PIXMAN_OP_DST;
207 case CAIRO_OPERATOR_DEST_OVER:
208 return PIXMAN_OP_OVER_REVERSE;
209 case CAIRO_OPERATOR_DEST_IN:
210 return PIXMAN_OP_IN_REVERSE;
211 case CAIRO_OPERATOR_DEST_OUT:
212 return PIXMAN_OP_OUT_REVERSE;
213 case CAIRO_OPERATOR_DEST_ATOP:
214 return PIXMAN_OP_ATOP_REVERSE;
215
216 case CAIRO_OPERATOR_XOR:
217 return PIXMAN_OP_XOR;
218 case CAIRO_OPERATOR_ADD:
219 return PIXMAN_OP_ADD;
220 case CAIRO_OPERATOR_SATURATE:
221 return PIXMAN_OP_SATURATE;
222
223 case CAIRO_OPERATOR_MULTIPLY:
224 return PIXMAN_OP_MULTIPLY;
225 case CAIRO_OPERATOR_SCREEN:
226 return PIXMAN_OP_SCREEN;
227 case CAIRO_OPERATOR_OVERLAY:
228 return PIXMAN_OP_OVERLAY;
229 case CAIRO_OPERATOR_DARKEN:
230 return PIXMAN_OP_DARKEN;
231 case CAIRO_OPERATOR_LIGHTEN:
232 return PIXMAN_OP_LIGHTEN;
233 case CAIRO_OPERATOR_COLOR_DODGE:
234 return PIXMAN_OP_COLOR_DODGE;
235 case CAIRO_OPERATOR_COLOR_BURN:
236 return PIXMAN_OP_COLOR_BURN;
237 case CAIRO_OPERATOR_HARD_LIGHT:
238 return PIXMAN_OP_HARD_LIGHT;
239 case CAIRO_OPERATOR_SOFT_LIGHT:
240 return PIXMAN_OP_SOFT_LIGHT;
241 case CAIRO_OPERATOR_DIFFERENCE:
242 return PIXMAN_OP_DIFFERENCE;
243 case CAIRO_OPERATOR_EXCLUSION:
244 return PIXMAN_OP_EXCLUSION;
245 case CAIRO_OPERATOR_HSL_HUE:
246 return PIXMAN_OP_HSL_HUE;
247 case CAIRO_OPERATOR_HSL_SATURATION:
248 return PIXMAN_OP_HSL_SATURATION;
249 case CAIRO_OPERATOR_HSL_COLOR:
250 return PIXMAN_OP_HSL_COLOR;
251 case CAIRO_OPERATOR_HSL_LUMINOSITY:
252 return PIXMAN_OP_HSL_LUMINOSITY;
253
254 default:
255 ASSERT_NOT_REACHEDdo { ((void) sizeof ((!"reached") ? 1 : 0), __extension__ ({ if
(!"reached") ; else __assert_fail ("!\"reached\"", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-image-compositor.c"
, 255, __extension__ __PRETTY_FUNCTION__); })); } while (0)
;
256 return PIXMAN_OP_OVER;
257 }
258}
259
260static cairo_bool_t
261__fill_reduces_to_source (cairo_operator_t op,
262 const cairo_color_t *color,
263 const cairo_image_surface_t *dst)
264{
265 if (op == CAIRO_OPERATOR_SOURCE || op == CAIRO_OPERATOR_CLEAR)
266 return TRUE1;
267 if (op == CAIRO_OPERATOR_OVER && CAIRO_COLOR_IS_OPAQUE (color)(((color)->alpha_short) >= 0xff00))
268 return TRUE1;
269 if (dst->base.is_clear)
270 return op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD;
271
272 return FALSE0;
273}
274
275static cairo_bool_t
276fill_reduces_to_source (cairo_operator_t op,
277 const cairo_color_t *color,
278 const cairo_image_surface_t *dst,
279 uint32_t *pixel)
280{
281 if (__fill_reduces_to_source (op, color, dst)) {
282 return color_to_pixel (color, dst->pixman_format, pixel);
283 }
284
285 return FALSE0;
286}
287
288static cairo_int_status_t
289fill_rectangles (void *_dst,
290 cairo_operator_t op,
291 const cairo_color_t *color,
292 cairo_rectangle_int_t *rects,
293 int num_rects)
294{
295 cairo_image_surface_t *dst = _dst;
296 uint32_t pixel;
297 int i;
298
299 TRACE ((stderr, "%s\n", __FUNCTION__));
300
301 if (fill_reduces_to_source (op, color, dst, &pixel)) {
302 for (i = 0; i < num_rects; i++) {
303 pixman_fill_moz_pixman_fill ((uint32_t *) dst->data, dst->stride / sizeof (uint32_t),
304 PIXMAN_FORMAT_BPP (dst->pixman_format)(((dst->pixman_format >> (24)) & ((1 << (8
)) - 1)) << ((dst->pixman_format >> 22) & 3
))
,
305 rects[i].x, rects[i].y,
306 rects[i].width, rects[i].height,
307 pixel);
308 }
309 } else {
310 pixman_image_t *src = _pixman_image_for_color (color);
311 if (unlikely (src == NULL)(__builtin_expect (!!(src == ((void*)0)), 0)))
312 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
313
314 op = _pixman_operator (op);
315 for (i = 0; i < num_rects; i++) {
316 pixman_image_composite32_moz_pixman_image_composite32 (op,
317 src, NULL((void*)0), dst->pixman_image,
318 0, 0,
319 0, 0,
320 rects[i].x, rects[i].y,
321 rects[i].width, rects[i].height);
322 }
323
324 pixman_image_unref_moz_pixman_image_unref (src);
325 }
326
327 return CAIRO_STATUS_SUCCESS;
328}
329
330static cairo_int_status_t
331fill_boxes (void *_dst,
332 cairo_operator_t op,
333 const cairo_color_t *color,
334 cairo_boxes_t *boxes)
335{
336 cairo_image_surface_t *dst = _dst;
337 struct _cairo_boxes_chunk *chunk;
338 uint32_t pixel;
339 int i;
340
341 TRACE ((stderr, "%s x %d\n", __FUNCTION__, boxes->num_boxes));
342
343 if (fill_reduces_to_source (op, color, dst, &pixel)) {
344 for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
345 for (i = 0; i < chunk->count; i++) {
346 int x = _cairo_fixed_integer_part (chunk->base[i].p1.x);
347 int y = _cairo_fixed_integer_part (chunk->base[i].p1.y);
348 int w = _cairo_fixed_integer_part (chunk->base[i].p2.x) - x;
349 int h = _cairo_fixed_integer_part (chunk->base[i].p2.y) - y;
350 pixman_fill_moz_pixman_fill ((uint32_t *) dst->data,
351 dst->stride / sizeof (uint32_t),
352 PIXMAN_FORMAT_BPP (dst->pixman_format)(((dst->pixman_format >> (24)) & ((1 << (8
)) - 1)) << ((dst->pixman_format >> 22) & 3
))
,
353 x, y, w, h, pixel);
354 }
355 }
356 }
357 else
358 {
359 pixman_image_t *src = _pixman_image_for_color (color);
360 if (unlikely (src == NULL)(__builtin_expect (!!(src == ((void*)0)), 0)))
361 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
362
363 op = _pixman_operator (op);
364 for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
365 for (i = 0; i < chunk->count; i++) {
366 int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x);
367 int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
368 int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
369 int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
370 pixman_image_composite32_moz_pixman_image_composite32 (op,
371 src, NULL((void*)0), dst->pixman_image,
372 0, 0,
373 0, 0,
374 x1, y1,
375 x2-x1, y2-y1);
376 }
377 }
378
379 pixman_image_unref_moz_pixman_image_unref (src);
380 }
381
382 return CAIRO_STATUS_SUCCESS;
383}
384
385static cairo_int_status_t
386composite (void *_dst,
387 cairo_operator_t op,
388 cairo_surface_t *abstract_src,
389 cairo_surface_t *abstract_mask,
390 int src_x,
391 int src_y,
392 int mask_x,
393 int mask_y,
394 int dst_x,
395 int dst_y,
396 unsigned int width,
397 unsigned int height)
398{
399 cairo_image_source_t *src = (cairo_image_source_t *)abstract_src;
400 cairo_image_source_t *mask = (cairo_image_source_t *)abstract_mask;
401
402 TRACE ((stderr, "%s\n", __FUNCTION__));
403
404 if (mask) {
405 pixman_image_composite32_moz_pixman_image_composite32 (_pixman_operator (op),
406 src->pixman_image, mask->pixman_image, to_pixman_image (_dst),
407 src_x, src_y,
408 mask_x, mask_y,
409 dst_x, dst_y,
410 width, height);
411 } else {
412 pixman_image_composite32_moz_pixman_image_composite32 (_pixman_operator (op),
413 src->pixman_image, NULL((void*)0), to_pixman_image (_dst),
414 src_x, src_y,
415 0, 0,
416 dst_x, dst_y,
417 width, height);
418 }
419
420 return CAIRO_STATUS_SUCCESS;
421}
422
423static cairo_int_status_t
424lerp (void *_dst,
425 cairo_surface_t *abstract_src,
426 cairo_surface_t *abstract_mask,
427 int src_x,
428 int src_y,
429 int mask_x,
430 int mask_y,
431 int dst_x,
432 int dst_y,
433 unsigned int width,
434 unsigned int height)
435{
436 cairo_image_surface_t *dst = _dst;
437 cairo_image_source_t *src = (cairo_image_source_t *)abstract_src;
438 cairo_image_source_t *mask = (cairo_image_source_t *)abstract_mask;
439
440 TRACE ((stderr, "%s\n", __FUNCTION__));
441
442#if PIXMAN_HAS_OP_LERP
443 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
444 src->pixman_image, mask->pixman_image, dst->pixman_image,
445 src_x, src_y,
446 mask_x, mask_y,
447 dst_x, dst_y,
448 width, height);
449#else
450 /* Punch the clip out of the destination */
451 TRACE ((stderr, "%s - OUT_REVERSE (mask=%d/%p, dst=%d/%p)\n",
452 __FUNCTION__,
453 mask->base.unique_id, mask->pixman_image,
454 dst->base.unique_id, dst->pixman_image));
455 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
456 mask->pixman_image, NULL((void*)0), dst->pixman_image,
457 mask_x, mask_y,
458 0, 0,
459 dst_x, dst_y,
460 width, height);
461
462 /* Now add the two results together */
463 TRACE ((stderr, "%s - ADD (src=%d/%p, mask=%d/%p, dst=%d/%p)\n",
464 __FUNCTION__,
465 src->base.unique_id, src->pixman_image,
466 mask->base.unique_id, mask->pixman_image,
467 dst->base.unique_id, dst->pixman_image));
468 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_ADD,
469 src->pixman_image, mask->pixman_image, dst->pixman_image,
470 src_x, src_y,
471 mask_x, mask_y,
472 dst_x, dst_y,
473 width, height);
474#endif
475
476 return CAIRO_STATUS_SUCCESS;
477}
478
479static cairo_int_status_t
480composite_boxes (void *_dst,
481 cairo_operator_t op,
482 cairo_surface_t *abstract_src,
483 cairo_surface_t *abstract_mask,
484 int src_x,
485 int src_y,
486 int mask_x,
487 int mask_y,
488 int dst_x,
489 int dst_y,
490 cairo_boxes_t *boxes,
491 const cairo_rectangle_int_t *extents)
492{
493 pixman_image_t *dst = to_pixman_image (_dst);
494 pixman_image_t *src = ((cairo_image_source_t *)abstract_src)->pixman_image;
495 pixman_image_t *mask = abstract_mask ? ((cairo_image_source_t *)abstract_mask)->pixman_image : NULL((void*)0);
496 pixman_image_t *free_src = NULL((void*)0);
497 struct _cairo_boxes_chunk *chunk;
498 int i;
499
500 /* XXX consider using a region? saves multiple prepare-composite */
501 TRACE ((stderr, "%s x %d\n", __FUNCTION__, boxes->num_boxes));
502
503 if (((cairo_surface_t *)_dst)->is_clear &&
504 (op == CAIRO_OPERATOR_SOURCE ||
505 op == CAIRO_OPERATOR_OVER ||
506 op == CAIRO_OPERATOR_ADD)) {
507 op = PIXMAN_OP_SRC;
508 } else if (mask) {
509 if (op == CAIRO_OPERATOR_CLEAR) {
510#if PIXMAN_HAS_OP_LERP
511 op = PIXMAN_OP_LERP_CLEAR;
512#else
513 free_src = src = _pixman_image_for_color (CAIRO_COLOR_WHITE_cairo_stock_color (CAIRO_STOCK_WHITE));
514 if (unlikely (src == NULL)(__builtin_expect (!!(src == ((void*)0)), 0)))
515 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
516 op = PIXMAN_OP_OUT_REVERSE;
517#endif
518 } else if (op == CAIRO_OPERATOR_SOURCE) {
519#if PIXMAN_HAS_OP_LERP
520 op = PIXMAN_OP_LERP_SRC;
521#else
522 return CAIRO_INT_STATUS_UNSUPPORTED;
523#endif
524 } else {
525 op = _pixman_operator (op);
526 }
527 } else {
528 op = _pixman_operator (op);
529 }
530
531 for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
532 for (i = 0; i < chunk->count; i++) {
533 int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x);
534 int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y);
535 int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x);
536 int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y);
537
538 pixman_image_composite32_moz_pixman_image_composite32 (op, src, mask, dst,
539 x1 + src_x, y1 + src_y,
540 x1 + mask_x, y1 + mask_y,
541 x1 + dst_x, y1 + dst_y,
542 x2 - x1, y2 - y1);
543 }
544 }
545
546 if (free_src)
547 pixman_image_unref_moz_pixman_image_unref (free_src);
548
549 return CAIRO_STATUS_SUCCESS;
550}
551
552#define CAIRO_FIXED_16_16_MIN_cairo_fixed_from_int (-32768) _cairo_fixed_from_int (-32768)
553#define CAIRO_FIXED_16_16_MAX_cairo_fixed_from_int (32767) _cairo_fixed_from_int (32767)
554
555static cairo_bool_t
556line_exceeds_16_16 (const cairo_line_t *line)
557{
558 return
559 line->p1.x <= CAIRO_FIXED_16_16_MIN_cairo_fixed_from_int (-32768) ||
560 line->p1.x >= CAIRO_FIXED_16_16_MAX_cairo_fixed_from_int (32767) ||
561
562 line->p2.x <= CAIRO_FIXED_16_16_MIN_cairo_fixed_from_int (-32768) ||
563 line->p2.x >= CAIRO_FIXED_16_16_MAX_cairo_fixed_from_int (32767) ||
564
565 line->p1.y <= CAIRO_FIXED_16_16_MIN_cairo_fixed_from_int (-32768) ||
566 line->p1.y >= CAIRO_FIXED_16_16_MAX_cairo_fixed_from_int (32767) ||
567
568 line->p2.y <= CAIRO_FIXED_16_16_MIN_cairo_fixed_from_int (-32768) ||
569 line->p2.y >= CAIRO_FIXED_16_16_MAX_cairo_fixed_from_int (32767);
570}
571
572static void
573project_line_x_onto_16_16 (const cairo_line_t *line,
574 cairo_fixed_t top,
575 cairo_fixed_t bottom,
576 pixman_line_fixed_t *out)
577{
578 /* XXX use fixed-point arithmetic? */
579 cairo_point_double_t p1, p2;
580 double m;
581
582 p1.x = _cairo_fixed_to_double (line->p1.x);
583 p1.y = _cairo_fixed_to_double (line->p1.y);
584
585 p2.x = _cairo_fixed_to_double (line->p2.x);
586 p2.y = _cairo_fixed_to_double (line->p2.y);
587
588 m = (p2.x - p1.x) / (p2.y - p1.y);
589 out->p1.x = _cairo_fixed_16_16_from_double (p1.x + m * _cairo_fixed_to_double (top - line->p1.y));
590 out->p2.x = _cairo_fixed_16_16_from_double (p1.x + m * _cairo_fixed_to_double (bottom - line->p1.y));
591}
592
593void
594_pixman_image_add_traps (pixman_image_t *image,
595 int dst_x, int dst_y,
596 cairo_traps_t *traps)
597{
598 cairo_trapezoid_t *t = traps->traps;
599 int num_traps = traps->num_traps;
600 while (num_traps--) {
601 pixman_trapezoid_t trap;
602
603 /* top/bottom will be clamped to surface bounds */
604 trap.top = _cairo_fixed_to_16_16 (t->top);
605 trap.bottom = _cairo_fixed_to_16_16 (t->bottom);
606
607 /* However, all the other coordinates will have been left untouched so
608 * as not to introduce numerical error. Recompute them if they
609 * exceed the 16.16 limits.
610 */
611 if (unlikely (line_exceeds_16_16 (&t->left))(__builtin_expect (!!(line_exceeds_16_16 (&t->left)), 0
))
) {
612 project_line_x_onto_16_16 (&t->left, t->top, t->bottom, &trap.left);
613 trap.left.p1.y = trap.top;
614 trap.left.p2.y = trap.bottom;
615 } else {
616 trap.left.p1.x = _cairo_fixed_to_16_16 (t->left.p1.x);
617 trap.left.p1.y = _cairo_fixed_to_16_16 (t->left.p1.y);
618 trap.left.p2.x = _cairo_fixed_to_16_16 (t->left.p2.x);
619 trap.left.p2.y = _cairo_fixed_to_16_16 (t->left.p2.y);
620 }
621
622 if (unlikely (line_exceeds_16_16 (&t->right))(__builtin_expect (!!(line_exceeds_16_16 (&t->right)),
0))
) {
623 project_line_x_onto_16_16 (&t->right, t->top, t->bottom, &trap.right);
624 trap.right.p1.y = trap.top;
625 trap.right.p2.y = trap.bottom;
626 } else {
627 trap.right.p1.x = _cairo_fixed_to_16_16 (t->right.p1.x);
628 trap.right.p1.y = _cairo_fixed_to_16_16 (t->right.p1.y);
629 trap.right.p2.x = _cairo_fixed_to_16_16 (t->right.p2.x);
630 trap.right.p2.y = _cairo_fixed_to_16_16 (t->right.p2.y);
631 }
632
633 pixman_rasterize_trapezoid_moz_pixman_rasterize_trapezoid (image, &trap, -dst_x, -dst_y);
634 t++;
635 }
636}
637
638static cairo_int_status_t
639composite_traps (void *_dst,
640 cairo_operator_t op,
641 cairo_surface_t *abstract_src,
642 int src_x,
643 int src_y,
644 int dst_x,
645 int dst_y,
646 const cairo_rectangle_int_t *extents,
647 cairo_antialias_t antialias,
648 cairo_traps_t *traps)
649{
650 cairo_image_surface_t *dst = (cairo_image_surface_t *) _dst;
651 cairo_image_source_t *src = (cairo_image_source_t *) abstract_src;
652 cairo_int_status_t status;
653 pixman_image_t *mask;
654 pixman_format_code_t format;
655
656 TRACE ((stderr, "%s\n", __FUNCTION__));
657
658 /* pixman doesn't eliminate self-intersecting trapezoids/edges */
659 status = _cairo_bentley_ottmann_tessellate_traps (traps,
660 CAIRO_FILL_RULE_WINDING);
661 if (status != CAIRO_INT_STATUS_SUCCESS)
662 return status;
663
664 /* Special case adding trapezoids onto a mask surface; we want to avoid
665 * creating an intermediate temporary mask unnecessarily.
666 *
667 * We make the assumption here that the portion of the trapezoids
668 * contained within the surface is bounded by [dst_x,dst_y,width,height];
669 * the Cairo core code passes bounds based on the trapezoid extents.
670 */
671 format = antialias == CAIRO_ANTIALIAS_NONE ? PIXMAN_a1 : PIXMAN_a8;
672 if (dst->pixman_format == format &&
673 (abstract_src == NULL((void*)0) ||
674 (op == CAIRO_OPERATOR_ADD && src->is_opaque_solid)))
675 {
676 _pixman_image_add_traps (dst->pixman_image, dst_x, dst_y, traps);
677 return CAIRO_STATUS_SUCCESS;
678 }
679
680 mask = pixman_image_create_bits_moz_pixman_image_create_bits (format,
681 extents->width, extents->height,
682 NULL((void*)0), 0);
683 if (unlikely (mask == NULL)(__builtin_expect (!!(mask == ((void*)0)), 0)))
684 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
685
686 _pixman_image_add_traps (mask, extents->x, extents->y, traps);
687 pixman_image_composite32_moz_pixman_image_composite32 (_pixman_operator (op),
688 src->pixman_image, mask, dst->pixman_image,
689 extents->x + src_x, extents->y + src_y,
690 0, 0,
691 extents->x - dst_x, extents->y - dst_y,
692 extents->width, extents->height);
693
694 pixman_image_unref_moz_pixman_image_unref (mask);
695
696 return CAIRO_STATUS_SUCCESS;
697}
698
699#if PIXMAN_VERSION( ((0) * 10000) + ((46) * 100) + ((0) * 1)) >= PIXMAN_VERSION_ENCODE(0,22,0)( ((0) * 10000) + ((22) * 100) + ((0) * 1))
700static void
701set_point (pixman_point_fixed_t *p, cairo_point_t *c)
702{
703 p->x = _cairo_fixed_to_16_16 (c->x);
704 p->y = _cairo_fixed_to_16_16 (c->y);
705}
706
707void
708_pixman_image_add_tristrip (pixman_image_t *image,
709 int dst_x, int dst_y,
710 cairo_tristrip_t *strip)
711{
712 pixman_triangle_t tri;
713 pixman_point_fixed_t *p[3] = {&tri.p1, &tri.p2, &tri.p3 };
714 int n;
715
716 set_point (p[0], &strip->points[0]);
717 set_point (p[1], &strip->points[1]);
718 set_point (p[2], &strip->points[2]);
719 pixman_add_triangles_moz_pixman_add_triangles (image, -dst_x, -dst_y, 1, &tri);
720 for (n = 3; n < strip->num_points; n++) {
721 set_point (p[n%3], &strip->points[n]);
722 pixman_add_triangles_moz_pixman_add_triangles (image, -dst_x, -dst_y, 1, &tri);
723 }
724}
725
726static cairo_int_status_t
727composite_tristrip (void *_dst,
728 cairo_operator_t op,
729 cairo_surface_t *abstract_src,
730 int src_x,
731 int src_y,
732 int dst_x,
733 int dst_y,
734 const cairo_rectangle_int_t *extents,
735 cairo_antialias_t antialias,
736 cairo_tristrip_t *strip)
737{
738 cairo_image_surface_t *dst = (cairo_image_surface_t *) _dst;
739 cairo_image_source_t *src = (cairo_image_source_t *) abstract_src;
740 pixman_image_t *mask;
741 pixman_format_code_t format;
742
743 TRACE ((stderr, "%s\n", __FUNCTION__));
744
745 if (strip->num_points < 3)
746 return CAIRO_STATUS_SUCCESS;
747
748 if (1) { /* pixman doesn't eliminate self-intersecting triangles/edges */
749 cairo_int_status_t status;
750 cairo_traps_t traps;
751 int n;
752
753 _cairo_traps_init (&traps);
754 for (n = 0; n < strip->num_points; n++) {
755 cairo_point_t p[4];
756
757 p[0] = strip->points[0];
758 p[1] = strip->points[1];
759 p[2] = strip->points[2];
760 p[3] = strip->points[0];
761
762 _cairo_traps_tessellate_convex_quad (&traps, p);
763 }
764 status = composite_traps (_dst, op, abstract_src,
765 src_x, src_y,
766 dst_x, dst_y,
767 extents, antialias, &traps);
768 _cairo_traps_fini (&traps);
769
770 return status;
771 }
772
773 format = antialias == CAIRO_ANTIALIAS_NONE ? PIXMAN_a1 : PIXMAN_a8;
774 if (dst->pixman_format == format &&
775 (abstract_src == NULL((void*)0) ||
776 (op == CAIRO_OPERATOR_ADD && src->is_opaque_solid)))
777 {
778 _pixman_image_add_tristrip (dst->pixman_image, dst_x, dst_y, strip);
779 return CAIRO_STATUS_SUCCESS;
780 }
781
782 mask = pixman_image_create_bits_moz_pixman_image_create_bits (format,
783 extents->width, extents->height,
784 NULL((void*)0), 0);
785 if (unlikely (mask == NULL)(__builtin_expect (!!(mask == ((void*)0)), 0)))
786 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
787
788 _pixman_image_add_tristrip (mask, extents->x, extents->y, strip);
789 pixman_image_composite32_moz_pixman_image_composite32 (_pixman_operator (op),
790 src->pixman_image, mask, dst->pixman_image,
791 extents->x + src_x, extents->y + src_y,
792 0, 0,
793 extents->x - dst_x, extents->y - dst_y,
794 extents->width, extents->height);
795
796 pixman_image_unref_moz_pixman_image_unref (mask);
797
798 return CAIRO_STATUS_SUCCESS;
799}
800#endif
801
802static cairo_int_status_t
803check_composite_glyphs (const cairo_composite_rectangles_t *extents,
804 cairo_scaled_font_t *scaled_font,
805 cairo_glyph_t *glyphs,
806 int *num_glyphs)
807{
808 return CAIRO_STATUS_SUCCESS;
809}
810
811#if HAS_PIXMAN_GLYPHS
812static pixman_glyph_cache_t *global_glyph_cache;
813
814static inline pixman_glyph_cache_t *
815get_glyph_cache (void)
816{
817 if (!global_glyph_cache)
818 global_glyph_cache = pixman_glyph_cache_create_moz_pixman_glyph_cache_create ();
819
820 return global_glyph_cache;
821}
822
823void
824_cairo_image_compositor_reset_static_data (void)
825{
826 CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex)pthread_mutex_lock (&(_cairo_glyph_cache_mutex));
827
828 if (global_glyph_cache)
829 pixman_glyph_cache_destroy_moz_pixman_glyph_cache_destroy (global_glyph_cache);
830 global_glyph_cache = NULL((void*)0);
831
832 CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex)pthread_mutex_unlock (&(_cairo_glyph_cache_mutex));
833}
834
835void
836_cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
837 cairo_scaled_glyph_t *scaled_glyph)
838{
839 CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex)pthread_mutex_lock (&(_cairo_glyph_cache_mutex));
840
841 if (global_glyph_cache) {
842 pixman_glyph_cache_remove_moz_pixman_glyph_cache_remove (
843 global_glyph_cache, scaled_font,
844 (void *)scaled_glyph->hash_entry.hash);
845 }
846
847 CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex)pthread_mutex_unlock (&(_cairo_glyph_cache_mutex));
848}
849
850#define PHASE(x) ((int)(floor (4 * (x + 0.125)) - 4 * floor (x + 0.125)))
851#define POSITION(x) ((int) floor (x + 0.125))
852
853static cairo_int_status_t
854composite_glyphs (void *_dst,
855 cairo_operator_t op,
856 cairo_surface_t *_src,
857 int src_x,
858 int src_y,
859 int dst_x,
860 int dst_y,
861 cairo_composite_glyphs_info_t *info)
862{
863 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
864 pixman_glyph_cache_t *glyph_cache;
865 pixman_glyph_t pglyphs_stack[CAIRO_STACK_ARRAY_LENGTH (pixman_glyph_t)((512 * sizeof (int)) / sizeof(pixman_glyph_t))];
866 pixman_glyph_t *pglyphs = pglyphs_stack;
867 pixman_glyph_t *pg;
868 int i;
869
870 TRACE ((stderr, "%s\n", __FUNCTION__));
871
872 CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex)pthread_mutex_lock (&(_cairo_glyph_cache_mutex));
873
874 glyph_cache = get_glyph_cache();
875 if (unlikely (glyph_cache == NULL)(__builtin_expect (!!(glyph_cache == ((void*)0)), 0))) {
876 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
877 goto out_unlock;
878 }
879
880 pixman_glyph_cache_freeze_moz_pixman_glyph_cache_freeze (glyph_cache);
881
882 if (info->num_glyphs > ARRAY_LENGTH (pglyphs_stack)((int) (sizeof (pglyphs_stack) / sizeof (pglyphs_stack[0])))) {
883 pglyphs = _cairo_malloc_ab (info->num_glyphs, sizeof (pixman_glyph_t));
884 if (unlikely (pglyphs == NULL)(__builtin_expect (!!(pglyphs == ((void*)0)), 0))) {
885 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
886 goto out_thaw;
887 }
888 }
889
890 pg = pglyphs;
891 for (i = 0; i < info->num_glyphs; i++) {
892 unsigned long index = info->glyphs[i].index;
893 const void *glyph;
894 unsigned long xphase, yphase;
895
896 xphase = PHASE(info->glyphs[i].x);
897 yphase = PHASE(info->glyphs[i].y);
898
899 index = index | (xphase << 24) | (yphase << 26);
900
901 glyph = pixman_glyph_cache_lookup_moz_pixman_glyph_cache_lookup (glyph_cache, info->font, (void *)(uintptr_t)index);
902 if (!glyph) {
903 cairo_scaled_glyph_t *scaled_glyph;
904 cairo_image_surface_t *glyph_surface;
905
906 /* This call can actually end up recursing, so we have to
907 * drop the mutex around it.
908 */
909 CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex)pthread_mutex_unlock (&(_cairo_glyph_cache_mutex));
910 status = _cairo_scaled_glyph_lookup (info->font, index,
911 CAIRO_SCALED_GLYPH_INFO_SURFACE,
912 NULL((void*)0), /* foreground color */
913 &scaled_glyph);
914 CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex)pthread_mutex_lock (&(_cairo_glyph_cache_mutex));
915
916 if (unlikely (status)(__builtin_expect (!!(status), 0)))
917 goto out_thaw;
918
919 glyph_surface = scaled_glyph->surface;
920 glyph = pixman_glyph_cache_insert_moz_pixman_glyph_cache_insert (glyph_cache, info->font, (void *)(uintptr_t)index,
921 glyph_surface->base.device_transform.x0,
922 glyph_surface->base.device_transform.y0,
923 glyph_surface->pixman_image);
924 if (unlikely (!glyph)(__builtin_expect (!!(!glyph), 0))) {
925 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
926 goto out_thaw;
927 }
928 }
929
930 pg->x = POSITION (info->glyphs[i].x);
931 pg->y = POSITION (info->glyphs[i].y);
932 pg->glyph = glyph;
933 pg++;
934 }
935
936 if (info->use_mask) {
937 pixman_format_code_t mask_format;
938
939 mask_format = pixman_glyph_get_mask_format_moz_pixman_glyph_get_mask_format (glyph_cache, pg - pglyphs, pglyphs);
940
941 pixman_composite_glyphs_moz_pixman_composite_glyphs (_pixman_operator (op),
942 ((cairo_image_source_t *)_src)->pixman_image,
943 to_pixman_image (_dst),
944 mask_format,
945 info->extents.x + src_x, info->extents.y + src_y,
946 info->extents.x, info->extents.y,
947 info->extents.x - dst_x, info->extents.y - dst_y,
948 info->extents.width, info->extents.height,
949 glyph_cache, pg - pglyphs, pglyphs);
950 } else {
951 pixman_composite_glyphs_no_mask_moz_pixman_composite_glyphs_no_mask (_pixman_operator (op),
952 ((cairo_image_source_t *)_src)->pixman_image,
953 to_pixman_image (_dst),
954 src_x, src_y,
955 - dst_x, - dst_y,
956 glyph_cache, pg - pglyphs, pglyphs);
957 }
958
959out_thaw:
960 pixman_glyph_cache_thaw_moz_pixman_glyph_cache_thaw (glyph_cache);
961
962 if (pglyphs != pglyphs_stack)
963 free(pglyphs);
964
965out_unlock:
966 CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex)pthread_mutex_unlock (&(_cairo_glyph_cache_mutex));
967 return status;
968}
969#else
970void
971_cairo_image_compositor_reset_static_data (void)
972{
973}
974
975void
976_cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
977 cairo_scaled_glyph_t *scaled_glyph)
978{
979}
980
981static cairo_int_status_t
982composite_one_glyph (void *_dst,
983 cairo_operator_t op,
984 cairo_surface_t *_src,
985 int src_x,
986 int src_y,
987 int dst_x,
988 int dst_y,
989 cairo_composite_glyphs_info_t *info)
990{
991 cairo_image_surface_t *glyph_surface;
992 cairo_scaled_glyph_t *scaled_glyph;
993 cairo_status_t status;
994 int x, y;
995
996 TRACE ((stderr, "%s\n", __FUNCTION__));
997
998 status = _cairo_scaled_glyph_lookup (info->font,
999 info->glyphs[0].index,
1000 CAIRO_SCALED_GLYPH_INFO_SURFACE,
1001 NULL((void*)0), /* foreground color */
1002 &scaled_glyph);
1003
1004 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1005 return status;
1006
1007 glyph_surface = scaled_glyph->surface;
1008 if (glyph_surface->width == 0 || glyph_surface->height == 0)
1009 return CAIRO_INT_STATUS_NOTHING_TO_DO;
1010
1011 /* round glyph locations to the nearest pixel */
1012 /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
1013 x = _cairo_lround (info->glyphs[0].x -
1014 glyph_surface->base.device_transform.x0);
1015 y = _cairo_lround (info->glyphs[0].y -
1016 glyph_surface->base.device_transform.y0);
1017
1018 pixman_image_composite32_moz_pixman_image_composite32 (_pixman_operator (op),
1019 ((cairo_image_source_t *)_src)->pixman_image,
1020 glyph_surface->pixman_image,
1021 to_pixman_image (_dst),
1022 x + src_x, y + src_y,
1023 0, 0,
1024 x - dst_x, y - dst_y,
1025 glyph_surface->width,
1026 glyph_surface->height);
1027
1028 return CAIRO_INT_STATUS_SUCCESS;
1029}
1030
1031static cairo_int_status_t
1032composite_glyphs_via_mask (void *_dst,
1033 cairo_operator_t op,
1034 cairo_surface_t *_src,
1035 int src_x,
1036 int src_y,
1037 int dst_x,
1038 int dst_y,
1039 cairo_composite_glyphs_info_t *info)
1040{
1041 cairo_scaled_glyph_t *glyph_cache[64];
1042 pixman_image_t *white = _pixman_image_for_color (CAIRO_COLOR_WHITE_cairo_stock_color (CAIRO_STOCK_WHITE));
1043 cairo_scaled_glyph_t *scaled_glyph;
1044 uint8_t buf[2048];
1045 pixman_image_t *mask;
1046 pixman_format_code_t format;
1047 cairo_status_t status;
1048 int i;
1049
1050 TRACE ((stderr, "%s\n", __FUNCTION__));
1051
1052 if (unlikely (white == NULL)(__builtin_expect (!!(white == ((void*)0)), 0)))
1053 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1054
1055 /* XXX convert the glyphs to common formats a8/a8r8g8b8 to hit
1056 * optimised paths through pixman. Should we increase the bit
1057 * depth of the target surface, we should reconsider the appropriate
1058 * mask formats.
1059 */
1060
1061 status = _cairo_scaled_glyph_lookup (info->font,
1062 info->glyphs[0].index,
1063 CAIRO_SCALED_GLYPH_INFO_SURFACE,
1064 NULL((void*)0), /* foreground color */
1065 &scaled_glyph);
1066 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
1067 pixman_image_unref_moz_pixman_image_unref (white);
1068 return status;
1069 }
1070
1071 memset (glyph_cache, 0, sizeof (glyph_cache));
1072 glyph_cache[info->glyphs[0].index % ARRAY_LENGTH (glyph_cache)((int) (sizeof (glyph_cache) / sizeof (glyph_cache[0])))] = scaled_glyph;
1073
1074 format = PIXMAN_a8;
1075 i = (info->extents.width + 3) & ~3;
1076 if (scaled_glyph->surface->base.content & CAIRO_CONTENT_COLOR) {
1077 format = PIXMAN_a8r8g8b8;
1078 i = info->extents.width * 4;
1079 }
1080
1081 if (i * info->extents.height > (int) sizeof (buf)) {
1082 mask = pixman_image_create_bits_moz_pixman_image_create_bits (format,
1083 info->extents.width,
1084 info->extents.height,
1085 NULL((void*)0), 0);
1086 } else {
1087 memset (buf, 0, i * info->extents.height);
1088 mask = pixman_image_create_bits_moz_pixman_image_create_bits (format,
1089 info->extents.width,
1090 info->extents.height,
1091 (uint32_t *)buf, i);
1092 }
1093 if (unlikely (mask == NULL)(__builtin_expect (!!(mask == ((void*)0)), 0))) {
1094 pixman_image_unref_moz_pixman_image_unref (white);
1095 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1096 }
1097
1098 status = CAIRO_STATUS_SUCCESS;
Value stored to 'status' is never read
1099 for (i = 0; i < info->num_glyphs; i++) {
1100 unsigned long glyph_index = info->glyphs[i].index;
1101 int cache_index = glyph_index % ARRAY_LENGTH (glyph_cache)((int) (sizeof (glyph_cache) / sizeof (glyph_cache[0])));
1102 cairo_image_surface_t *glyph_surface;
1103 int x, y;
1104
1105 scaled_glyph = glyph_cache[cache_index];
1106 if (scaled_glyph == NULL((void*)0) ||
1107 _cairo_scaled_glyph_index (scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
!= glyph_index)
1108 {
1109 status = _cairo_scaled_glyph_lookup (info->font, glyph_index,
1110 CAIRO_SCALED_GLYPH_INFO_SURFACE,
1111 NULL((void*)0), /* foreground color */
1112 &scaled_glyph);
1113
1114 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
1115 pixman_image_unref_moz_pixman_image_unref (mask);
1116 pixman_image_unref_moz_pixman_image_unref (white);
1117 return status;
1118 }
1119
1120 glyph_cache[cache_index] = scaled_glyph;
1121 }
1122
1123 glyph_surface = scaled_glyph->surface;
1124 if (glyph_surface->width && glyph_surface->height) {
1125 if (glyph_surface->base.content & CAIRO_CONTENT_COLOR &&
1126 format == PIXMAN_a8) {
1127 pixman_image_t *ca_mask;
1128
1129 format = PIXMAN_a8r8g8b8;
1130 ca_mask = pixman_image_create_bits_moz_pixman_image_create_bits (format,
1131 info->extents.width,
1132 info->extents.height,
1133 NULL((void*)0), 0);
1134 if (unlikely (ca_mask == NULL)(__builtin_expect (!!(ca_mask == ((void*)0)), 0))) {
1135 pixman_image_unref_moz_pixman_image_unref (mask);
1136 pixman_image_unref_moz_pixman_image_unref (white);
1137 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1138 }
1139
1140 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_SRC,
1141 white, mask, ca_mask,
1142 0, 0,
1143 0, 0,
1144 0, 0,
1145 info->extents.width,
1146 info->extents.height);
1147 pixman_image_unref_moz_pixman_image_unref (mask);
1148 mask = ca_mask;
1149 }
1150
1151 /* round glyph locations to the nearest pixel */
1152 /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
1153 x = _cairo_lround (info->glyphs[i].x -
1154 glyph_surface->base.device_transform.x0);
1155 y = _cairo_lround (info->glyphs[i].y -
1156 glyph_surface->base.device_transform.y0);
1157
1158 if (glyph_surface->pixman_format == format) {
1159 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_ADD,
1160 glyph_surface->pixman_image, NULL((void*)0), mask,
1161 0, 0,
1162 0, 0,
1163 x - info->extents.x, y - info->extents.y,
1164 glyph_surface->width,
1165 glyph_surface->height);
1166 } else {
1167 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_ADD,
1168 white, glyph_surface->pixman_image, mask,
1169 0, 0,
1170 0, 0,
1171 x - info->extents.x, y - info->extents.y,
1172 glyph_surface->width,
1173 glyph_surface->height);
1174 }
1175 }
1176 }
1177
1178 if (format == PIXMAN_a8r8g8b8)
1179 pixman_image_set_component_alpha_moz_pixman_image_set_component_alpha (mask, TRUE1);
1180
1181 pixman_image_composite32_moz_pixman_image_composite32 (_pixman_operator (op),
1182 ((cairo_image_source_t *)_src)->pixman_image,
1183 mask,
1184 to_pixman_image (_dst),
1185 info->extents.x + src_x, info->extents.y + src_y,
1186 0, 0,
1187 info->extents.x - dst_x, info->extents.y - dst_y,
1188 info->extents.width, info->extents.height);
1189 pixman_image_unref_moz_pixman_image_unref (mask);
1190 pixman_image_unref_moz_pixman_image_unref (white);
1191
1192 return CAIRO_STATUS_SUCCESS;
1193}
1194
1195static cairo_int_status_t
1196composite_glyphs (void *_dst,
1197 cairo_operator_t op,
1198 cairo_surface_t *_src,
1199 int src_x,
1200 int src_y,
1201 int dst_x,
1202 int dst_y,
1203 cairo_composite_glyphs_info_t *info)
1204{
1205 cairo_scaled_glyph_t *glyph_cache[64];
1206 pixman_image_t *dst, *src;
1207 cairo_status_t status;
1208 int i;
1209
1210 TRACE ((stderr, "%s\n", __FUNCTION__));
1211
1212 if (info->num_glyphs == 1)
1213 return composite_one_glyph(_dst, op, _src, src_x, src_y, dst_x, dst_y, info);
1214
1215 if (info->use_mask)
1216 return composite_glyphs_via_mask(_dst, op, _src, src_x, src_y, dst_x, dst_y, info);
1217
1218 op = _pixman_operator (op);
1219 dst = to_pixman_image (_dst);
1220 src = ((cairo_image_source_t *)_src)->pixman_image;
1221
1222 memset (glyph_cache, 0, sizeof (glyph_cache));
1223 status = CAIRO_STATUS_SUCCESS;
1224
1225 for (i = 0; i < info->num_glyphs; i++) {
1226 int x, y;
1227 cairo_image_surface_t *glyph_surface;
1228 cairo_scaled_glyph_t *scaled_glyph;
1229 unsigned long glyph_index = info->glyphs[i].index;
1230 int cache_index = glyph_index % ARRAY_LENGTH (glyph_cache)((int) (sizeof (glyph_cache) / sizeof (glyph_cache[0])));
1231
1232 scaled_glyph = glyph_cache[cache_index];
1233 if (scaled_glyph == NULL((void*)0) ||
1234 _cairo_scaled_glyph_index (scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
!= glyph_index)
1235 {
1236 status = _cairo_scaled_glyph_lookup (info->font, glyph_index,
1237 CAIRO_SCALED_GLYPH_INFO_SURFACE,
1238 NULL((void*)0), /* foreground color */
1239 &scaled_glyph);
1240
1241 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1242 break;
1243
1244 glyph_cache[cache_index] = scaled_glyph;
1245 }
1246
1247 glyph_surface = scaled_glyph->surface;
1248 if (glyph_surface->width && glyph_surface->height) {
1249 /* round glyph locations to the nearest pixel */
1250 /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
1251 x = _cairo_lround (info->glyphs[i].x -
1252 glyph_surface->base.device_transform.x0);
1253 y = _cairo_lround (info->glyphs[i].y -
1254 glyph_surface->base.device_transform.y0);
1255
1256 pixman_image_composite32_moz_pixman_image_composite32 (op, src, glyph_surface->pixman_image, dst,
1257 x + src_x, y + src_y,
1258 0, 0,
1259 x - dst_x, y - dst_y,
1260 glyph_surface->width,
1261 glyph_surface->height);
1262 }
1263 }
1264
1265 return status;
1266}
1267#endif
1268
1269static cairo_int_status_t
1270check_composite (const cairo_composite_rectangles_t *extents)
1271{
1272 return CAIRO_STATUS_SUCCESS;
1273}
1274
1275const cairo_compositor_t *
1276_cairo_image_traps_compositor_get (void)
1277{
1278 static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT(0);
1279 static cairo_traps_compositor_t compositor;
1280
1281 if (_cairo_atomic_init_once_enter(&once)) {
1282 _cairo_traps_compositor_init(&compositor,
1283 &__cairo_no_compositor);
1284 compositor.acquire = acquire;
1285 compositor.release = release;
1286 compositor.set_clip_region = set_clip_region;
1287 compositor.pattern_to_surface = _cairo_image_source_create_for_pattern;
1288 compositor.draw_image_boxes = draw_image_boxes;
1289 //compositor.copy_boxes = copy_boxes;
1290 compositor.fill_boxes = fill_boxes;
1291 compositor.check_composite = check_composite;
1292 compositor.composite = composite;
1293 compositor.lerp = lerp;
1294 //compositor.check_composite_boxes = check_composite_boxes;
1295 compositor.composite_boxes = composite_boxes;
1296 //compositor.check_composite_traps = check_composite_traps;
1297 compositor.composite_traps = composite_traps;
1298 //compositor.check_composite_tristrip = check_composite_traps;
1299#if PIXMAN_VERSION( ((0) * 10000) + ((46) * 100) + ((0) * 1)) >= PIXMAN_VERSION_ENCODE(0,22,0)( ((0) * 10000) + ((22) * 100) + ((0) * 1))
1300 compositor.composite_tristrip = composite_tristrip;
1301#endif
1302 compositor.check_composite_glyphs = check_composite_glyphs;
1303 compositor.composite_glyphs = composite_glyphs;
1304
1305 _cairo_atomic_init_once_leave(&once);
1306 }
1307
1308 return &compositor.base;
1309}
1310
1311const cairo_compositor_t *
1312_cairo_image_mask_compositor_get (void)
1313{
1314 static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT(0);
1315 static cairo_mask_compositor_t compositor;
1316
1317 if (_cairo_atomic_init_once_enter(&once)) {
1318 _cairo_mask_compositor_init (&compositor,
1319 _cairo_image_traps_compositor_get ());
1320 compositor.acquire = acquire;
1321 compositor.release = release;
1322 compositor.set_clip_region = set_clip_region;
1323 compositor.pattern_to_surface = _cairo_image_source_create_for_pattern;
1324 compositor.draw_image_boxes = draw_image_boxes;
1325 compositor.fill_rectangles = fill_rectangles;
1326 compositor.fill_boxes = fill_boxes;
1327 compositor.check_composite = check_composite;
1328 compositor.composite = composite;
1329 //compositor.lerp = lerp;
1330 //compositor.check_composite_boxes = check_composite_boxes;
1331 compositor.composite_boxes = composite_boxes;
1332 compositor.check_composite_glyphs = check_composite_glyphs;
1333 compositor.composite_glyphs = composite_glyphs;
1334
1335 _cairo_atomic_init_once_leave(&once);
1336 }
1337
1338 return &compositor.base;
1339}
1340
1341#if PIXMAN_HAS_COMPOSITOR
1342typedef struct _cairo_image_span_renderer {
1343 cairo_span_renderer_t base;
1344
1345 pixman_image_compositor_t *compositor;
1346 pixman_image_t *src, *mask;
1347 float opacity;
1348 cairo_rectangle_int_t extents;
1349} cairo_image_span_renderer_t;
1350COMPILE_TIME_ASSERT (sizeof (cairo_image_span_renderer_t) <= sizeof (cairo_abstract_span_renderer_t))typedef int compile_time_assertion_at_line_1350_failed [(sizeof
(cairo_image_span_renderer_t) <= sizeof (cairo_abstract_span_renderer_t
))?1:-1]
;
1351
1352static cairo_status_t
1353_cairo_image_bounded_opaque_spans (void *abstract_renderer,
1354 int y, int height,
1355 const cairo_half_open_span_t *spans,
1356 unsigned num_spans)
1357{
1358 cairo_image_span_renderer_t *r = abstract_renderer;
1359
1360 if (num_spans == 0)
1361 return CAIRO_STATUS_SUCCESS;
1362
1363 do {
1364 if (spans[0].coverage)
1365 pixman_image_compositor_blt (r->compositor,
1366 spans[0].x, y,
1367 spans[1].x - spans[0].x, height,
1368 spans[0].coverage);
1369 spans++;
1370 } while (--num_spans > 1);
1371
1372 return CAIRO_STATUS_SUCCESS;
1373}
1374
1375static cairo_status_t
1376_cairo_image_bounded_spans (void *abstract_renderer,
1377 int y, int height,
1378 const cairo_half_open_span_t *spans,
1379 unsigned num_spans)
1380{
1381 cairo_image_span_renderer_t *r = abstract_renderer;
1382
1383 if (num_spans == 0)
1384 return CAIRO_STATUS_SUCCESS;
1385
1386 do {
1387 if (spans[0].coverage) {
1388 pixman_image_compositor_blt (r->compositor,
1389 spans[0].x, y,
1390 spans[1].x - spans[0].x, height,
1391 r->opacity * spans[0].coverage);
1392 }
1393 spans++;
1394 } while (--num_spans > 1);
1395
1396 return CAIRO_STATUS_SUCCESS;
1397}
1398
1399static cairo_status_t
1400_cairo_image_unbounded_spans (void *abstract_renderer,
1401 int y, int height,
1402 const cairo_half_open_span_t *spans,
1403 unsigned num_spans)
1404{
1405 cairo_image_span_renderer_t *r = abstract_renderer;
1406
1407 assert (y + height <= r->extents.height)((void) sizeof ((y + height <= r->extents.height) ? 1 :
0), __extension__ ({ if (y + height <= r->extents.height
) ; else __assert_fail ("y + height <= r->extents.height"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-image-compositor.c"
, 1407, __extension__ __PRETTY_FUNCTION__); }))
;
1408 if (y > r->extents.y) {
1409 pixman_image_compositor_blt (r->compositor,
1410 r->extents.x, r->extents.y,
1411 r->extents.width, y - r->extents.y,
1412 0);
1413 }
1414
1415 if (num_spans == 0) {
1416 pixman_image_compositor_blt (r->compositor,
1417 r->extents.x, y,
1418 r->extents.width, height,
1419 0);
1420 } else {
1421 if (spans[0].x != r->extents.x) {
1422 pixman_image_compositor_blt (r->compositor,
1423 r->extents.x, y,
1424 spans[0].x - r->extents.x,
1425 height,
1426 0);
1427 }
1428
1429 do {
1430 assert (spans[0].x < r->extents.x + r->extents.width)((void) sizeof ((spans[0].x < r->extents.x + r->extents
.width) ? 1 : 0), __extension__ ({ if (spans[0].x < r->
extents.x + r->extents.width) ; else __assert_fail ("spans[0].x < r->extents.x + r->extents.width"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-image-compositor.c"
, 1430, __extension__ __PRETTY_FUNCTION__); }))
;
1431 pixman_image_compositor_blt (r->compositor,
1432 spans[0].x, y,
1433 spans[1].x - spans[0].x, height,
1434 r->opacity * spans[0].coverage);
1435 spans++;
1436 } while (--num_spans > 1);
1437
1438 if (spans[0].x != r->extents.x + r->extents.width) {
1439 assert (spans[0].x < r->extents.x + r->extents.width)((void) sizeof ((spans[0].x < r->extents.x + r->extents
.width) ? 1 : 0), __extension__ ({ if (spans[0].x < r->
extents.x + r->extents.width) ; else __assert_fail ("spans[0].x < r->extents.x + r->extents.width"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-image-compositor.c"
, 1439, __extension__ __PRETTY_FUNCTION__); }))
;
1440 pixman_image_compositor_blt (r->compositor,
1441 spans[0].x, y,
1442 r->extents.x + r->extents.width - spans[0].x, height,
1443 0);
1444 }
1445 }
1446
1447 r->extents.y = y + height;
1448 return CAIRO_STATUS_SUCCESS;
1449}
1450
1451static cairo_status_t
1452_cairo_image_clipped_spans (void *abstract_renderer,
1453 int y, int height,
1454 const cairo_half_open_span_t *spans,
1455 unsigned num_spans)
1456{
1457 cairo_image_span_renderer_t *r = abstract_renderer;
1458
1459 assert (num_spans)((void) sizeof ((num_spans) ? 1 : 0), __extension__ ({ if (num_spans
) ; else __assert_fail ("num_spans", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-image-compositor.c"
, 1459, __extension__ __PRETTY_FUNCTION__); }))
;
1460
1461 do {
1462 if (! spans[0].inverse)
1463 pixman_image_compositor_blt (r->compositor,
1464 spans[0].x, y,
1465 spans[1].x - spans[0].x, height,
1466 r->opacity * spans[0].coverage);
1467 spans++;
1468 } while (--num_spans > 1);
1469
1470 r->extents.y = y + height;
1471 return CAIRO_STATUS_SUCCESS;
1472}
1473
1474static cairo_status_t
1475_cairo_image_finish_unbounded_spans (void *abstract_renderer)
1476{
1477 cairo_image_span_renderer_t *r = abstract_renderer;
1478
1479 if (r->extents.y < r->extents.height) {
1480 pixman_image_compositor_blt (r->compositor,
1481 r->extents.x, r->extents.y,
1482 r->extents.width,
1483 r->extents.height - r->extents.y,
1484 0);
1485 }
1486
1487 return CAIRO_STATUS_SUCCESS;
1488}
1489
1490static cairo_int_status_t
1491span_renderer_init (cairo_abstract_span_renderer_t *_r,
1492 const cairo_composite_rectangles_t *composite,
1493 cairo_bool_t needs_clip)
1494{
1495 cairo_image_span_renderer_t *r = (cairo_image_span_renderer_t *)_r;
1496 cairo_image_surface_t *dst = (cairo_image_surface_t *)composite->surface;
1497 const cairo_pattern_t *source = &composite->source_pattern.base;
1498 cairo_operator_t op = composite->op;
1499 int src_x, src_y;
1500 int mask_x, mask_y;
1501
1502 TRACE ((stderr, "%s\n", __FUNCTION__));
1503
1504 if (op == CAIRO_OPERATOR_CLEAR) {
1505 op = PIXMAN_OP_LERP_CLEAR;
1506 } else if (dst->base.is_clear &&
1507 (op == CAIRO_OPERATOR_SOURCE ||
1508 op == CAIRO_OPERATOR_OVER ||
1509 op == CAIRO_OPERATOR_ADD)) {
1510 op = PIXMAN_OP_SRC;
1511 } else if (op == CAIRO_OPERATOR_SOURCE) {
1512 op = PIXMAN_OP_LERP_SRC;
1513 } else {
1514 op = _pixman_operator (op);
1515 }
1516
1517 r->compositor = NULL((void*)0);
1518 r->mask = NULL((void*)0);
1519 r->src = _pixman_image_for_pattern (dst, source, FALSE0,
1520 &composite->unbounded,
1521 &composite->source_sample_area,
1522 &src_x, &src_y);
1523 if (unlikely (r->src == NULL)(__builtin_expect (!!(r->src == ((void*)0)), 0)))
1524 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1525
1526 r->opacity = 1.0;
1527 if (composite->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID) {
1528 r->opacity = composite->mask_pattern.solid.color.alpha;
1529 } else {
1530 r->mask = _pixman_image_for_pattern (dst,
1531 &composite->mask_pattern.base,
1532 TRUE1,
1533 &composite->unbounded,
1534 &composite->mask_sample_area,
1535 &mask_x, &mask_y);
1536 if (unlikely (r->mask == NULL)(__builtin_expect (!!(r->mask == ((void*)0)), 0)))
1537 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1538
1539 /* XXX Component-alpha? */
1540 if ((dst->base.content & CAIRO_CONTENT_COLOR) == 0 &&
1541 _cairo_pattern_is_opaque (source, &composite->source_sample_area))
1542 {
1543 pixman_image_unref_moz_pixman_image_unref (r->src);
1544 r->src = r->mask;
1545 src_x = mask_x;
1546 src_y = mask_y;
1547 r->mask = NULL((void*)0);
1548 }
1549 }
1550
1551 if (composite->is_bounded) {
1552 if (r->opacity == 1.)
1553 r->base.render_rows = _cairo_image_bounded_opaque_spans;
1554 else
1555 r->base.render_rows = _cairo_image_bounded_spans;
1556 r->base.finish = NULL((void*)0);
1557 } else {
1558 if (needs_clip)
1559 r->base.render_rows = _cairo_image_clipped_spans;
1560 else
1561 r->base.render_rows = _cairo_image_unbounded_spans;
1562 r->base.finish = _cairo_image_finish_unbounded_spans;
1563 r->extents = composite->unbounded;
1564 r->extents.height += r->extents.y;
1565 }
1566
1567 r->compositor =
1568 pixman_image_create_compositor (op, r->src, r->mask, dst->pixman_image,
1569 composite->unbounded.x + src_x,
1570 composite->unbounded.y + src_y,
1571 composite->unbounded.x + mask_x,
1572 composite->unbounded.y + mask_y,
1573 composite->unbounded.x,
1574 composite->unbounded.y,
1575 composite->unbounded.width,
1576 composite->unbounded.height);
1577 if (unlikely (r->compositor == NULL)(__builtin_expect (!!(r->compositor == ((void*)0)), 0)))
1578 return CAIRO_INT_STATUS_NOTHING_TO_DO;
1579
1580 return CAIRO_STATUS_SUCCESS;
1581}
1582
1583static void
1584span_renderer_fini (cairo_abstract_span_renderer_t *_r,
1585 cairo_int_status_t status)
1586{
1587 cairo_image_span_renderer_t *r = (cairo_image_span_renderer_t *) _r;
1588
1589 TRACE ((stderr, "%s\n", __FUNCTION__));
1590
1591 if (status == CAIRO_INT_STATUS_SUCCESS && r->base.finish)
1592 r->base.finish (r);
1593
1594 if (r->compositor)
1595 pixman_image_compositor_destroy (r->compositor);
1596
1597 if (r->src)
1598 pixman_image_unref_moz_pixman_image_unref (r->src);
1599 if (r->mask)
1600 pixman_image_unref_moz_pixman_image_unref (r->mask);
1601}
1602#else
1603typedef struct _cairo_image_span_renderer {
1604 cairo_span_renderer_t base;
1605
1606 const cairo_composite_rectangles_t *composite;
1607
1608 float opacity;
1609 uint8_t op;
1610 int bpp;
1611
1612 pixman_image_t *src, *mask;
1613 union {
1614 struct fill {
1615 ptrdiff_t stride;
1616 uint8_t *data;
1617 uint32_t pixel;
1618 } fill;
1619 struct blit {
1620 int stride;
1621 uint8_t *data;
1622 int src_stride;
1623 uint8_t *src_data;
1624 } blit;
1625 struct composite {
1626 pixman_image_t *dst;
1627 int src_x, src_y;
1628 int mask_x, mask_y;
1629 int run_length;
1630 } composite;
1631 struct finish {
1632 cairo_rectangle_int_t extents;
1633 int src_x, src_y;
1634 ptrdiff_t stride;
1635 uint8_t *data;
1636 } mask;
1637 } u;
1638 uint8_t _buf[0];
1639#define SZ_BUF(int)(sizeof (cairo_abstract_span_renderer_t) - sizeof (cairo_image_span_renderer_t
))
(int)(sizeof (cairo_abstract_span_renderer_t) - sizeof (cairo_image_span_renderer_t))
1640} cairo_image_span_renderer_t;
1641COMPILE_TIME_ASSERT (sizeof (cairo_image_span_renderer_t) <= sizeof (cairo_abstract_span_renderer_t))typedef int compile_time_assertion_at_line_1641_failed [(sizeof
(cairo_image_span_renderer_t) <= sizeof (cairo_abstract_span_renderer_t
))?1:-1]
;
1642
1643static cairo_status_t
1644_cairo_image_spans (void *abstract_renderer,
1645 int y, int height,
1646 const cairo_half_open_span_t *spans,
1647 unsigned num_spans)
1648{
1649 cairo_image_span_renderer_t *r = abstract_renderer;
1650 uint8_t *mask, *row;
1651 int len;
1652
1653 if (num_spans == 0)
1654 return CAIRO_STATUS_SUCCESS;
1655
1656 mask = r->u.mask.data + (y - r->u.mask.extents.y) * r->u.mask.stride;
1657 mask += spans[0].x - r->u.mask.extents.x;
1658 row = mask;
1659
1660 do {
1661 len = spans[1].x - spans[0].x;
1662 if (spans[0].coverage) {
1663 *row++ = r->opacity * spans[0].coverage;
1664 if (--len)
1665 memset (row, row[-1], len);
1666 }
1667 row += len;
1668 spans++;
1669 } while (--num_spans > 1);
1670
1671 len = row - mask;
1672 row = mask;
1673 while (--height) {
1674 mask += r->u.mask.stride;
1675 memcpy (mask, row, len);
1676 }
1677
1678 return CAIRO_STATUS_SUCCESS;
1679}
1680
1681static cairo_status_t
1682_cairo_image_spans_and_zero (void *abstract_renderer,
1683 int y, int height,
1684 const cairo_half_open_span_t *spans,
1685 unsigned num_spans)
1686{
1687 cairo_image_span_renderer_t *r = abstract_renderer;
1688 uint8_t *mask;
1689 int len;
1690
1691 mask = r->u.mask.data;
1692 if (y > r->u.mask.extents.y) {
1693 len = (y - r->u.mask.extents.y) * r->u.mask.stride;
1694 memset (mask, 0, len);
1695 mask += len;
1696 }
1697
1698 r->u.mask.extents.y = y + height;
1699 r->u.mask.data = mask + height * r->u.mask.stride;
1700 if (num_spans == 0) {
1701 memset (mask, 0, height * r->u.mask.stride);
1702 } else {
1703 uint8_t *row = mask;
1704
1705 if (spans[0].x != r->u.mask.extents.x) {
1706 len = spans[0].x - r->u.mask.extents.x;
1707 memset (row, 0, len);
1708 row += len;
1709 }
1710
1711 do {
1712 len = spans[1].x - spans[0].x;
1713 *row++ = r->opacity * spans[0].coverage;
1714 if (len > 1) {
1715 memset (row, row[-1], --len);
1716 row += len;
1717 }
1718 spans++;
1719 } while (--num_spans > 1);
1720
1721 if (spans[0].x != r->u.mask.extents.x + r->u.mask.extents.width) {
1722 len = r->u.mask.extents.x + r->u.mask.extents.width - spans[0].x;
1723 memset (row, 0, len);
1724 }
1725
1726 row = mask;
1727 while (--height) {
1728 mask += r->u.mask.stride;
1729 memcpy (mask, row, r->u.mask.extents.width);
1730 }
1731 }
1732
1733 return CAIRO_STATUS_SUCCESS;
1734}
1735
1736static cairo_status_t
1737_cairo_image_finish_spans_and_zero (void *abstract_renderer)
1738{
1739 cairo_image_span_renderer_t *r = abstract_renderer;
1740
1741 if (r->u.mask.extents.y < r->u.mask.extents.height)
1742 memset (r->u.mask.data, 0, (r->u.mask.extents.height - r->u.mask.extents.y) * r->u.mask.stride);
1743
1744 return CAIRO_STATUS_SUCCESS;
1745}
1746
1747static cairo_status_t
1748_fill8_spans (void *abstract_renderer, int y, int h,
1749 const cairo_half_open_span_t *spans, unsigned num_spans)
1750{
1751 cairo_image_span_renderer_t *r = abstract_renderer;
1752
1753 if (num_spans == 0)
1754 return CAIRO_STATUS_SUCCESS;
1755
1756 if (likely(h == 1)(__builtin_expect (!!(h == 1), 1))) {
1757 do {
1758 if (spans[0].coverage) {
1759 int len = spans[1].x - spans[0].x;
1760 uint8_t *d = r->u.fill.data + r->u.fill.stride*y + spans[0].x;
1761 if (len == 1)
1762 *d = r->u.fill.pixel;
1763 else
1764 memset(d, r->u.fill.pixel, len);
1765 }
1766 spans++;
1767 } while (--num_spans > 1);
1768 } else {
1769 do {
1770 if (spans[0].coverage) {
1771 int yy = y, hh = h;
1772 do {
1773 int len = spans[1].x - spans[0].x;
1774 uint8_t *d = r->u.fill.data + r->u.fill.stride*yy + spans[0].x;
1775 if (len == 1)
1776 *d = r->u.fill.pixel;
1777 else
1778 memset(d, r->u.fill.pixel, len);
1779 yy++;
1780 } while (--hh);
1781 }
1782 spans++;
1783 } while (--num_spans > 1);
1784 }
1785
1786 return CAIRO_STATUS_SUCCESS;
1787}
1788
1789static cairo_status_t
1790_fill16_spans (void *abstract_renderer, int y, int h,
1791 const cairo_half_open_span_t *spans, unsigned num_spans)
1792{
1793 cairo_image_span_renderer_t *r = abstract_renderer;
1794
1795 if (num_spans == 0)
1796 return CAIRO_STATUS_SUCCESS;
1797
1798 if (likely(h == 1)(__builtin_expect (!!(h == 1), 1))) {
1799 do {
1800 if (spans[0].coverage) {
1801 int len = spans[1].x - spans[0].x;
1802 uint16_t *d = (uint16_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*2);
1803 while (len-- > 0)
1804 *d++ = r->u.fill.pixel;
1805 }
1806 spans++;
1807 } while (--num_spans > 1);
1808 } else {
1809 do {
1810 if (spans[0].coverage) {
1811 int yy = y, hh = h;
1812 do {
1813 int len = spans[1].x - spans[0].x;
1814 uint16_t *d = (uint16_t*)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*2);
1815 while (len-- > 0)
1816 *d++ = r->u.fill.pixel;
1817 yy++;
1818 } while (--hh);
1819 }
1820 spans++;
1821 } while (--num_spans > 1);
1822 }
1823
1824 return CAIRO_STATUS_SUCCESS;
1825}
1826
1827static cairo_status_t
1828_fill32_spans (void *abstract_renderer, int y, int h,
1829 const cairo_half_open_span_t *spans, unsigned num_spans)
1830{
1831 cairo_image_span_renderer_t *r = abstract_renderer;
1832
1833 if (num_spans == 0)
1834 return CAIRO_STATUS_SUCCESS;
1835
1836 if (likely(h == 1)(__builtin_expect (!!(h == 1), 1))) {
1837 do {
1838 if (spans[0].coverage) {
1839 int len = spans[1].x - spans[0].x;
1840 if (len > 32) {
1841 pixman_fill_moz_pixman_fill ((uint32_t *)r->u.fill.data, r->u.fill.stride / sizeof(uint32_t), r->bpp,
1842 spans[0].x, y, len, 1, r->u.fill.pixel);
1843 } else {
1844 uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*4);
1845 while (len-- > 0)
1846 *d++ = r->u.fill.pixel;
1847 }
1848 }
1849 spans++;
1850 } while (--num_spans > 1);
1851 } else {
1852 do {
1853 if (spans[0].coverage) {
1854 if (spans[1].x - spans[0].x > 16) {
1855 pixman_fill_moz_pixman_fill ((uint32_t *)r->u.fill.data, r->u.fill.stride / sizeof(uint32_t), r->bpp,
1856 spans[0].x, y, spans[1].x - spans[0].x, h,
1857 r->u.fill.pixel);
1858 } else {
1859 int yy = y, hh = h;
1860 do {
1861 int len = spans[1].x - spans[0].x;
1862 uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*4);
1863 while (len-- > 0)
1864 *d++ = r->u.fill.pixel;
1865 yy++;
1866 } while (--hh);
1867 }
1868 }
1869 spans++;
1870 } while (--num_spans > 1);
1871 }
1872
1873 return CAIRO_STATUS_SUCCESS;
1874}
1875
1876#if 0
1877static cairo_status_t
1878_fill_spans (void *abstract_renderer, int y, int h,
1879 const cairo_half_open_span_t *spans, unsigned num_spans)
1880{
1881 cairo_image_span_renderer_t *r = abstract_renderer;
1882
1883 if (num_spans == 0)
1884 return CAIRO_STATUS_SUCCESS;
1885
1886 do {
1887 if (spans[0].coverage) {
1888 pixman_fill_moz_pixman_fill ((uint32_t *) r->data, r->stride, r->bpp,
1889 spans[0].x, y,
1890 spans[1].x - spans[0].x, h,
1891 r->pixel);
1892 }
1893 spans++;
1894 } while (--num_spans > 1);
1895
1896 return CAIRO_STATUS_SUCCESS;
1897}
1898#endif
1899
1900static cairo_status_t
1901_blit_spans (void *abstract_renderer, int y, int h,
1902 const cairo_half_open_span_t *spans, unsigned num_spans)
1903{
1904 cairo_image_span_renderer_t *r = abstract_renderer;
1905 int cpp;
1906
1907 if (num_spans == 0)
1908 return CAIRO_STATUS_SUCCESS;
1909
1910 cpp = r->bpp/8;
1911 if (likely (h == 1)(__builtin_expect (!!(h == 1), 1))) {
1912 uint8_t *src = r->u.blit.src_data + y*r->u.blit.src_stride;
1913 uint8_t *dst = r->u.blit.data + y*r->u.blit.stride;
1914 do {
1915 if (spans[0].coverage) {
1916 void *s = src + spans[0].x*cpp;
1917 void *d = dst + spans[0].x*cpp;
1918 int len = (spans[1].x - spans[0].x) * cpp;
1919 switch (len) {
1920 case 1:
1921 *(uint8_t *)d = *(uint8_t *)s;
1922 break;
1923 case 2:
1924 *(uint16_t *)d = *(uint16_t *)s;
1925 break;
1926 case 4:
1927 *(uint32_t *)d = *(uint32_t *)s;
1928 break;
1929#if HAVE_UINT64_T1
1930 case 8:
1931 *(uint64_t *)d = *(uint64_t *)s;
1932 break;
1933#endif
1934 default:
1935 memcpy(d, s, len);
1936 break;
1937 }
1938 }
1939 spans++;
1940 } while (--num_spans > 1);
1941 } else {
1942 do {
1943 if (spans[0].coverage) {
1944 int yy = y, hh = h;
1945 do {
1946 void *src = r->u.blit.src_data + yy*r->u.blit.src_stride + spans[0].x*cpp;
1947 void *dst = r->u.blit.data + yy*r->u.blit.stride + spans[0].x*cpp;
1948 int len = (spans[1].x - spans[0].x) * cpp;
1949 switch (len) {
1950 case 1:
1951 *(uint8_t *)dst = *(uint8_t *)src;
1952 break;
1953 case 2:
1954 *(uint16_t *)dst = *(uint16_t *)src;
1955 break;
1956 case 4:
1957 *(uint32_t *)dst = *(uint32_t *)src;
1958 break;
1959#if HAVE_UINT64_T1
1960 case 8:
1961 *(uint64_t *)dst = *(uint64_t *)src;
1962 break;
1963#endif
1964 default:
1965 memcpy(dst, src, len);
1966 break;
1967 }
1968 yy++;
1969 } while (--hh);
1970 }
1971 spans++;
1972 } while (--num_spans > 1);
1973 }
1974
1975 return CAIRO_STATUS_SUCCESS;
1976}
1977
1978static cairo_status_t
1979_mono_spans (void *abstract_renderer, int y, int h,
1980 const cairo_half_open_span_t *spans, unsigned num_spans)
1981{
1982 cairo_image_span_renderer_t *r = abstract_renderer;
1983
1984 if (num_spans == 0)
1985 return CAIRO_STATUS_SUCCESS;
1986
1987 do {
1988 if (spans[0].coverage) {
1989 pixman_image_composite32_moz_pixman_image_composite32 (r->op,
1990 r->src, NULL((void*)0), r->u.composite.dst,
1991 spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
1992 0, 0,
1993 spans[0].x, y,
1994 spans[1].x - spans[0].x, h);
1995 }
1996 spans++;
1997 } while (--num_spans > 1);
1998
1999 return CAIRO_STATUS_SUCCESS;
2000}
2001
2002static cairo_status_t
2003_mono_unbounded_spans (void *abstract_renderer, int y, int h,
2004 const cairo_half_open_span_t *spans, unsigned num_spans)
2005{
2006 cairo_image_span_renderer_t *r = abstract_renderer;
2007
2008 if (num_spans == 0) {
2009 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_CLEAR,
2010 r->src, NULL((void*)0), r->u.composite.dst,
2011 spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
2012 0, 0,
2013 r->composite->unbounded.x, y,
2014 r->composite->unbounded.width, h);
2015 r->u.composite.mask_y = y + h;
2016 return CAIRO_STATUS_SUCCESS;
2017 }
2018
2019 if (y != r->u.composite.mask_y) {
2020 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_CLEAR,
2021 r->src, NULL((void*)0), r->u.composite.dst,
2022 spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
2023 0, 0,
2024 r->composite->unbounded.x, r->u.composite.mask_y,
2025 r->composite->unbounded.width, y - r->u.composite.mask_y);
2026 }
2027
2028 if (spans[0].x != r->composite->unbounded.x) {
2029 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_CLEAR,
2030 r->src, NULL((void*)0), r->u.composite.dst,
2031 spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
2032 0, 0,
2033 r->composite->unbounded.x, y,
2034 spans[0].x - r->composite->unbounded.x, h);
2035 }
2036
2037 do {
2038 int op = spans[0].coverage ? r->op : PIXMAN_OP_CLEAR;
2039 pixman_image_composite32_moz_pixman_image_composite32 (op,
2040 r->src, NULL((void*)0), r->u.composite.dst,
2041 spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
2042 0, 0,
2043 spans[0].x, y,
2044 spans[1].x - spans[0].x, h);
2045 spans++;
2046 } while (--num_spans > 1);
2047
2048 if (spans[0].x != r->composite->unbounded.x + r->composite->unbounded.width) {
2049 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_CLEAR,
2050 r->src, NULL((void*)0), r->u.composite.dst,
2051 spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
2052 0, 0,
2053 spans[0].x, y,
2054 r->composite->unbounded.x + r->composite->unbounded.width - spans[0].x, h);
2055 }
2056
2057 r->u.composite.mask_y = y + h;
2058 return CAIRO_STATUS_SUCCESS;
2059}
2060
2061static cairo_status_t
2062_mono_finish_unbounded_spans (void *abstract_renderer)
2063{
2064 cairo_image_span_renderer_t *r = abstract_renderer;
2065
2066 if (r->u.composite.mask_y < r->composite->unbounded.y + r->composite->unbounded.height) {
2067 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_CLEAR,
2068 r->src, NULL((void*)0), r->u.composite.dst,
2069 r->composite->unbounded.x + r->u.composite.src_x, r->u.composite.mask_y + r->u.composite.src_y,
2070 0, 0,
2071 r->composite->unbounded.x, r->u.composite.mask_y,
2072 r->composite->unbounded.width,
2073 r->composite->unbounded.y + r->composite->unbounded.height - r->u.composite.mask_y);
2074 }
2075
2076 return CAIRO_STATUS_SUCCESS;
2077}
2078
2079static cairo_int_status_t
2080mono_renderer_init (cairo_image_span_renderer_t *r,
2081 const cairo_composite_rectangles_t *composite,
2082 cairo_antialias_t antialias,
2083 cairo_bool_t needs_clip)
2084{
2085 cairo_image_surface_t *dst = (cairo_image_surface_t *)composite->surface;
2086
2087 if (antialias != CAIRO_ANTIALIAS_NONE)
2088 return CAIRO_INT_STATUS_UNSUPPORTED;
2089
2090 if (!_cairo_pattern_is_opaque_solid (&composite->mask_pattern.base))
2091 return CAIRO_INT_STATUS_UNSUPPORTED;
2092
2093 r->base.render_rows = NULL((void*)0);
2094 if (composite->source_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID) {
2095 const cairo_color_t *color;
2096
2097 color = &composite->source_pattern.solid.color;
2098 if (composite->op == CAIRO_OPERATOR_CLEAR)
2099 color = CAIRO_COLOR_TRANSPARENT_cairo_stock_color (CAIRO_STOCK_TRANSPARENT);
2100
2101 if (fill_reduces_to_source (composite->op, color, dst, &r->u.fill.pixel)) {
2102 /* Use plain C for the fill operations as the span length is
2103 * typically small, too small to payback the startup overheads of
2104 * using SSE2 etc.
2105 */
2106 switch (PIXMAN_FORMAT_BPP(dst->pixman_format)(((dst->pixman_format >> (24)) & ((1 << (8
)) - 1)) << ((dst->pixman_format >> 22) & 3
))
) {
2107 case 8: r->base.render_rows = _fill8_spans; break;
2108 case 16: r->base.render_rows = _fill16_spans; break;
2109 case 32: r->base.render_rows = _fill32_spans; break;
2110 default: break;
2111 }
2112 r->u.fill.data = dst->data;
2113 r->u.fill.stride = dst->stride;
2114 }
2115 } else if ((composite->op == CAIRO_OPERATOR_SOURCE ||
2116 (composite->op == CAIRO_OPERATOR_OVER &&
2117 (dst->base.is_clear || (dst->base.content & CAIRO_CONTENT_ALPHA) == 0))) &&
2118 composite->source_pattern.base.type == CAIRO_PATTERN_TYPE_SURFACE &&
2119 composite->source_pattern.surface.surface->backend->type == CAIRO_SURFACE_TYPE_IMAGE &&
2120 to_image_surface(composite->source_pattern.surface.surface)((cairo_image_surface_t *)(composite->source_pattern.surface
.surface))
->format == dst->format)
2121 {
2122 cairo_image_surface_t *src =
2123 to_image_surface(composite->source_pattern.surface.surface)((cairo_image_surface_t *)(composite->source_pattern.surface
.surface))
;
2124 int tx, ty;
2125
2126 if (_cairo_matrix_is_integer_translation(&composite->source_pattern.base.matrix,
2127 &tx, &ty) &&
2128 composite->bounded.x + tx >= 0 &&
2129 composite->bounded.y + ty >= 0 &&
2130 composite->bounded.x + composite->bounded.width + tx <= src->width &&
2131 composite->bounded.y + composite->bounded.height + ty <= src->height) {
2132
2133 r->u.blit.stride = dst->stride;
2134 r->u.blit.data = dst->data;
2135 r->u.blit.src_stride = src->stride;
2136 r->u.blit.src_data = src->data + src->stride * ty + tx * 4;
2137 r->base.render_rows = _blit_spans;
2138 }
2139 }
2140
2141 if (r->base.render_rows == NULL((void*)0)) {
2142 r->src = _pixman_image_for_pattern (dst, &composite->source_pattern.base, FALSE0,
2143 &composite->unbounded,
2144 &composite->source_sample_area,
2145 &r->u.composite.src_x, &r->u.composite.src_y);
2146 if (unlikely (r->src == NULL)(__builtin_expect (!!(r->src == ((void*)0)), 0)))
2147 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2148
2149 r->u.composite.dst = to_pixman_image (composite->surface);
2150 r->op = _pixman_operator (composite->op);
2151 if (composite->is_bounded == 0) {
2152 r->base.render_rows = _mono_unbounded_spans;
2153 r->base.finish = _mono_finish_unbounded_spans;
2154 r->u.composite.mask_y = composite->unbounded.y;
2155 } else
2156 r->base.render_rows = _mono_spans;
2157 }
2158 r->bpp = PIXMAN_FORMAT_BPP(dst->pixman_format)(((dst->pixman_format >> (24)) & ((1 << (8
)) - 1)) << ((dst->pixman_format >> 22) & 3
))
;
2159
2160 return CAIRO_INT_STATUS_SUCCESS;
2161}
2162
2163#define ONE_HALF0x7f 0x7f
2164#define RB_MASK0x00ff00ff 0x00ff00ff
2165#define RB_ONE_HALF0x007f007f 0x007f007f
2166#define RB_MASK_PLUS_ONE0x01000100 0x01000100
2167#define G_SHIFT8 8
2168static inline uint32_t
2169mul8x2_8 (uint32_t a, uint8_t b)
2170{
2171 uint32_t t = (a & RB_MASK0x00ff00ff) * b + RB_ONE_HALF0x007f007f;
2172 return ((t + ((t >> G_SHIFT8) & RB_MASK0x00ff00ff)) >> G_SHIFT8) & RB_MASK0x00ff00ff;
2173}
2174
2175static inline uint32_t
2176add8x2_8x2 (uint32_t a, uint32_t b)
2177{
2178 uint32_t t = a + b;
2179 t |= RB_MASK_PLUS_ONE0x01000100 - ((t >> G_SHIFT8) & RB_MASK0x00ff00ff);
2180 return t & RB_MASK0x00ff00ff;
2181}
2182
2183static inline uint8_t
2184mul8_8 (uint8_t a, uint8_t b)
2185{
2186 uint16_t t = a * (uint16_t)b + ONE_HALF0x7f;
2187 return ((t >> G_SHIFT8) + t) >> G_SHIFT8;
2188}
2189
2190static inline uint32_t
2191lerp8x4 (uint32_t src, uint8_t a, uint32_t dst)
2192{
2193 return (add8x2_8x2 (mul8x2_8 (src, a),
2194 mul8x2_8 (dst, ~a)) |
2195 add8x2_8x2 (mul8x2_8 (src >> G_SHIFT8, a),
2196 mul8x2_8 (dst >> G_SHIFT8, ~a)) << G_SHIFT8);
2197}
2198
2199static cairo_status_t
2200_fill_a8_lerp_opaque_spans (void *abstract_renderer, int y, int h,
2201 const cairo_half_open_span_t *spans, unsigned num_spans)
2202{
2203 cairo_image_span_renderer_t *r = abstract_renderer;
2204
2205 if (num_spans == 0)
2206 return CAIRO_STATUS_SUCCESS;
2207
2208 if (likely(h == 1)(__builtin_expect (!!(h == 1), 1))) {
2209 uint8_t *d = r->u.fill.data + r->u.fill.stride*y;
2210 do {
2211 uint8_t a = spans[0].coverage;
2212 if (a) {
2213 int len = spans[1].x - spans[0].x;
2214 if (a == 0xff) {
2215 memset(d + spans[0].x, r->u.fill.pixel, len);
2216 } else {
2217 uint8_t s = mul8_8(a, r->u.fill.pixel);
2218 uint8_t *dst = d + spans[0].x;
2219 a = ~a;
2220 while (len-- > 0) {
2221 uint8_t t = mul8_8(*dst, a);
2222 *dst++ = t + s;
2223 }
2224 }
2225 }
2226 spans++;
2227 } while (--num_spans > 1);
2228 } else {
2229 do {
2230 uint8_t a = spans[0].coverage;
2231 if (a) {
2232 int yy = y, hh = h;
2233 if (a == 0xff) {
2234 do {
2235 int len = spans[1].x - spans[0].x;
2236 uint8_t *d = r->u.fill.data + r->u.fill.stride*yy + spans[0].x;
2237 memset(d, r->u.fill.pixel, len);
2238 yy++;
2239 } while (--hh);
2240 } else {
2241 uint8_t s = mul8_8(a, r->u.fill.pixel);
2242 a = ~a;
2243 do {
2244 int len = spans[1].x - spans[0].x;
2245 uint8_t *d = r->u.fill.data + r->u.fill.stride*yy + spans[0].x;
2246 while (len-- > 0) {
2247 uint8_t t = mul8_8(*d, a);
2248 *d++ = t + s;
2249 }
2250 yy++;
2251 } while (--hh);
2252 }
2253 }
2254 spans++;
2255 } while (--num_spans > 1);
2256 }
2257
2258 return CAIRO_STATUS_SUCCESS;
2259}
2260
2261static cairo_status_t
2262_fill_xrgb32_lerp_opaque_spans (void *abstract_renderer, int y, int h,
2263 const cairo_half_open_span_t *spans, unsigned num_spans)
2264{
2265 cairo_image_span_renderer_t *r = abstract_renderer;
2266
2267 if (num_spans == 0)
2268 return CAIRO_STATUS_SUCCESS;
2269
2270 if (likely(h == 1)(__builtin_expect (!!(h == 1), 1))) {
2271 do {
2272 uint8_t a = spans[0].coverage;
2273 if (a) {
2274 int len = spans[1].x - spans[0].x;
2275 uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*4);
2276 if (a == 0xff) {
2277 if (len > 31) {
2278 pixman_fill_moz_pixman_fill ((uint32_t *)r->u.fill.data, r->u.fill.stride / sizeof(uint32_t), 32,
2279 spans[0].x, y, len, 1, r->u.fill.pixel);
2280 } else {
2281 uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*4);
2282 while (len-- > 0)
2283 *d++ = r->u.fill.pixel;
2284 }
2285 } else while (len-- > 0) {
2286 *d = lerp8x4 (r->u.fill.pixel, a, *d);
2287 d++;
2288 }
2289 }
2290 spans++;
2291 } while (--num_spans > 1);
2292 } else {
2293 do {
2294 uint8_t a = spans[0].coverage;
2295 if (a) {
2296 if (a == 0xff) {
2297 if (spans[1].x - spans[0].x > 16) {
2298 pixman_fill_moz_pixman_fill ((uint32_t *)r->u.fill.data, r->u.fill.stride / sizeof(uint32_t), 32,
2299 spans[0].x, y, spans[1].x - spans[0].x, h,
2300 r->u.fill.pixel);
2301 } else {
2302 int yy = y, hh = h;
2303 do {
2304 int len = spans[1].x - spans[0].x;
2305 uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*4);
2306 while (len-- > 0)
2307 *d++ = r->u.fill.pixel;
2308 yy++;
2309 } while (--hh);
2310 }
2311 } else {
2312 int yy = y, hh = h;
2313 do {
2314 int len = spans[1].x - spans[0].x;
2315 uint32_t *d = (uint32_t *)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*4);
2316 while (len-- > 0) {
2317 *d = lerp8x4 (r->u.fill.pixel, a, *d);
2318 d++;
2319 }
2320 yy++;
2321 } while (--hh);
2322 }
2323 }
2324 spans++;
2325 } while (--num_spans > 1);
2326 }
2327
2328 return CAIRO_STATUS_SUCCESS;
2329}
2330
2331static cairo_status_t
2332_fill_a8_lerp_spans (void *abstract_renderer, int y, int h,
2333 const cairo_half_open_span_t *spans, unsigned num_spans)
2334{
2335 cairo_image_span_renderer_t *r = abstract_renderer;
2336
2337 if (num_spans == 0)
2338 return CAIRO_STATUS_SUCCESS;
2339
2340 if (likely(h == 1)(__builtin_expect (!!(h == 1), 1))) {
2341 do {
2342 uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
2343 if (a) {
2344 int len = spans[1].x - spans[0].x;
2345 uint8_t *d = r->u.fill.data + r->u.fill.stride*y + spans[0].x;
2346 uint16_t p = (uint16_t)a * r->u.fill.pixel + 0x7f;
2347 uint16_t ia = ~a;
2348 while (len-- > 0) {
2349 uint16_t t = *d*ia + p;
2350 *d++ = (t + (t>>8)) >> 8;
2351 }
2352 }
2353 spans++;
2354 } while (--num_spans > 1);
2355 } else {
2356 do {
2357 uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
2358 if (a) {
2359 int yy = y, hh = h;
2360 uint16_t p = (uint16_t)a * r->u.fill.pixel + 0x7f;
2361 uint16_t ia = ~a;
2362 do {
2363 int len = spans[1].x - spans[0].x;
2364 uint8_t *d = r->u.fill.data + r->u.fill.stride*yy + spans[0].x;
2365 while (len-- > 0) {
2366 uint16_t t = *d*ia + p;
2367 *d++ = (t + (t>>8)) >> 8;
2368 }
2369 yy++;
2370 } while (--hh);
2371 }
2372 spans++;
2373 } while (--num_spans > 1);
2374 }
2375
2376 return CAIRO_STATUS_SUCCESS;
2377}
2378
2379static cairo_status_t
2380_fill_xrgb32_lerp_spans (void *abstract_renderer, int y, int h,
2381 const cairo_half_open_span_t *spans, unsigned num_spans)
2382{
2383 cairo_image_span_renderer_t *r = abstract_renderer;
2384
2385 if (num_spans == 0)
2386 return CAIRO_STATUS_SUCCESS;
2387
2388 if (likely(h == 1)(__builtin_expect (!!(h == 1), 1))) {
2389 do {
2390 uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
2391 if (a) {
2392 int len = spans[1].x - spans[0].x;
2393 uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*4);
2394 while (len-- > 0) {
2395 *d = lerp8x4 (r->u.fill.pixel, a, *d);
2396 d++;
2397 }
2398 }
2399 spans++;
2400 } while (--num_spans > 1);
2401 } else {
2402 do {
2403 uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
2404 if (a) {
2405 int yy = y, hh = h;
2406 do {
2407 int len = spans[1].x - spans[0].x;
2408 uint32_t *d = (uint32_t *)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*4);
2409 while (len-- > 0) {
2410 *d = lerp8x4 (r->u.fill.pixel, a, *d);
2411 d++;
2412 }
2413 yy++;
2414 } while (--hh);
2415 }
2416 spans++;
2417 } while (--num_spans > 1);
2418 }
2419
2420 return CAIRO_STATUS_SUCCESS;
2421}
2422
2423static cairo_status_t
2424_blit_xrgb32_lerp_spans (void *abstract_renderer, int y, int h,
2425 const cairo_half_open_span_t *spans, unsigned num_spans)
2426{
2427 cairo_image_span_renderer_t *r = abstract_renderer;
2428
2429 if (num_spans == 0)
2430 return CAIRO_STATUS_SUCCESS;
2431
2432 if (likely(h == 1)(__builtin_expect (!!(h == 1), 1))) {
2433 uint8_t *src = r->u.blit.src_data + y*r->u.blit.src_stride;
2434 uint8_t *dst = r->u.blit.data + y*r->u.blit.stride;
2435 do {
2436 uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
2437 if (a) {
2438 uint32_t *s = (uint32_t*)src + spans[0].x;
2439 uint32_t *d = (uint32_t*)dst + spans[0].x;
2440 int len = spans[1].x - spans[0].x;
2441 if (a == 0xff) {
2442 if (len == 1)
2443 *d = *s;
2444 else
2445 memcpy(d, s, len*4);
2446 } else {
2447 while (len-- > 0) {
2448 *d = lerp8x4 (*s, a, *d);
2449 s++, d++;
2450 }
2451 }
2452 }
2453 spans++;
2454 } while (--num_spans > 1);
2455 } else {
2456 do {
2457 uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
2458 if (a) {
2459 int yy = y, hh = h;
2460 do {
2461 uint32_t *s = (uint32_t *)(r->u.blit.src_data + yy*r->u.blit.src_stride + spans[0].x * 4);
2462 uint32_t *d = (uint32_t *)(r->u.blit.data + yy*r->u.blit.stride + spans[0].x * 4);
2463 int len = spans[1].x - spans[0].x;
2464 if (a == 0xff) {
2465 if (len == 1)
2466 *d = *s;
2467 else
2468 memcpy(d, s, len * 4);
2469 } else {
2470 while (len-- > 0) {
2471 *d = lerp8x4 (*s, a, *d);
2472 s++, d++;
2473 }
2474 }
2475 yy++;
2476 } while (--hh);
2477 }
2478 spans++;
2479 } while (--num_spans > 1);
2480 }
2481
2482 return CAIRO_STATUS_SUCCESS;
2483}
2484
2485static cairo_status_t
2486_inplace_spans (void *abstract_renderer,
2487 int y, int h,
2488 const cairo_half_open_span_t *spans,
2489 unsigned num_spans)
2490{
2491 cairo_image_span_renderer_t *r = abstract_renderer;
2492 uint8_t *mask;
2493 int x0, x1;
2494
2495 if (num_spans == 0)
2496 return CAIRO_STATUS_SUCCESS;
2497
2498 if (num_spans == 2 && spans[0].coverage == 0xff) {
2499 pixman_image_composite32_moz_pixman_image_composite32 (r->op, r->src, NULL((void*)0), r->u.composite.dst,
2500 spans[0].x + r->u.composite.src_x,
2501 y + r->u.composite.src_y,
2502 0, 0,
2503 spans[0].x, y,
2504 spans[1].x - spans[0].x, h);
2505 return CAIRO_STATUS_SUCCESS;
2506 }
2507
2508 mask = (uint8_t *)pixman_image_get_data_moz_pixman_image_get_data (r->mask);
2509 x1 = x0 = spans[0].x;
2510 do {
2511 int len = spans[1].x - spans[0].x;
2512 *mask++ = spans[0].coverage;
2513 if (len > 1) {
2514 if (len >= r->u.composite.run_length && spans[0].coverage == 0xff) {
2515 if (x1 != x0) {
2516 pixman_image_composite32_moz_pixman_image_composite32 (r->op, r->src, r->mask, r->u.composite.dst,
2517 x0 + r->u.composite.src_x,
2518 y + r->u.composite.src_y,
2519 0, 0,
2520 x0, y,
2521 x1 - x0, h);
2522 }
2523 pixman_image_composite32_moz_pixman_image_composite32 (r->op, r->src, NULL((void*)0), r->u.composite.dst,
2524 spans[0].x + r->u.composite.src_x,
2525 y + r->u.composite.src_y,
2526 0, 0,
2527 spans[0].x, y,
2528 len, h);
2529 mask = (uint8_t *)pixman_image_get_data_moz_pixman_image_get_data (r->mask);
2530 x0 = spans[1].x;
2531 } else if (spans[0].coverage == 0x0 &&
2532 x1 - x0 > r->u.composite.run_length) {
2533 pixman_image_composite32_moz_pixman_image_composite32 (r->op, r->src, r->mask, r->u.composite.dst,
2534 x0 + r->u.composite.src_x,
2535 y + r->u.composite.src_y,
2536 0, 0,
2537 x0, y,
2538 x1 - x0, h);
2539 mask = (uint8_t *)pixman_image_get_data_moz_pixman_image_get_data (r->mask);
2540 x0 = spans[1].x;
2541 }else {
2542 memset (mask, spans[0].coverage, --len);
2543 mask += len;
2544 }
2545 }
2546 x1 = spans[1].x;
2547 spans++;
2548 } while (--num_spans > 1);
2549
2550 if (x1 != x0) {
2551 pixman_image_composite32_moz_pixman_image_composite32 (r->op, r->src, r->mask, r->u.composite.dst,
2552 x0 + r->u.composite.src_x,
2553 y + r->u.composite.src_y,
2554 0, 0,
2555 x0, y,
2556 x1 - x0, h);
2557 }
2558
2559 return CAIRO_STATUS_SUCCESS;
2560}
2561
2562static cairo_status_t
2563_inplace_opacity_spans (void *abstract_renderer, int y, int h,
2564 const cairo_half_open_span_t *spans,
2565 unsigned num_spans)
2566{
2567 cairo_image_span_renderer_t *r = abstract_renderer;
2568 uint8_t *mask;
2569 int x0, x1;
2570
2571 if (num_spans == 0)
2572 return CAIRO_STATUS_SUCCESS;
2573
2574 mask = (uint8_t *)pixman_image_get_data_moz_pixman_image_get_data (r->mask);
2575 x1 = x0 = spans[0].x;
2576 do {
2577 int len = spans[1].x - spans[0].x;
2578 uint8_t m = mul8_8(spans[0].coverage, r->bpp);
2579 *mask++ = m;
2580 if (len > 1) {
2581 if (m == 0 &&
2582 x1 - x0 > r->u.composite.run_length) {
2583 pixman_image_composite32_moz_pixman_image_composite32 (r->op, r->src, r->mask, r->u.composite.dst,
2584 x0 + r->u.composite.src_x,
2585 y + r->u.composite.src_y,
2586 0, 0,
2587 x0, y,
2588 x1 - x0, h);
2589 mask = (uint8_t *)pixman_image_get_data_moz_pixman_image_get_data (r->mask);
2590 x0 = spans[1].x;
2591 }else {
2592 memset (mask, m, --len);
2593 mask += len;
2594 }
2595 }
2596 x1 = spans[1].x;
2597 spans++;
2598 } while (--num_spans > 1);
2599
2600 if (x1 != x0) {
2601 pixman_image_composite32_moz_pixman_image_composite32 (r->op, r->src, r->mask, r->u.composite.dst,
2602 x0 + r->u.composite.src_x,
2603 y + r->u.composite.src_y,
2604 0, 0,
2605 x0, y,
2606 x1 - x0, h);
2607 }
2608
2609 return CAIRO_STATUS_SUCCESS;
2610}
2611
2612static cairo_status_t
2613_inplace_src_spans (void *abstract_renderer, int y, int h,
2614 const cairo_half_open_span_t *spans,
2615 unsigned num_spans)
2616{
2617 cairo_image_span_renderer_t *r = abstract_renderer;
2618 uint8_t *m, *base = (uint8_t*)pixman_image_get_data_moz_pixman_image_get_data(r->mask);
2619 int x0;
2620
2621 if (num_spans == 0)
2622 return CAIRO_STATUS_SUCCESS;
2623
2624 x0 = spans[0].x;
2625 m = base;
2626 do {
2627 int len = spans[1].x - spans[0].x;
2628 if (len >= r->u.composite.run_length && spans[0].coverage == 0xff) {
2629 if (spans[0].x != x0) {
2630#if PIXMAN_HAS_OP_LERP
2631 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
2632 r->src, r->mask, r->u.composite.dst,
2633 x0 + r->u.composite.src_x,
2634 y + r->u.composite.src_y,
2635 0, 0,
2636 x0, y,
2637 spans[0].x - x0, h);
2638#else
2639 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
2640 r->mask, NULL((void*)0), r->u.composite.dst,
2641 0, 0,
2642 0, 0,
2643 x0, y,
2644 spans[0].x - x0, h);
2645 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_ADD,
2646 r->src, r->mask, r->u.composite.dst,
2647 x0 + r->u.composite.src_x,
2648 y + r->u.composite.src_y,
2649 0, 0,
2650 x0, y,
2651 spans[0].x - x0, h);
2652#endif
2653 }
2654
2655 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_SRC,
2656 r->src, NULL((void*)0), r->u.composite.dst,
2657 spans[0].x + r->u.composite.src_x,
2658 y + r->u.composite.src_y,
2659 0, 0,
2660 spans[0].x, y,
2661 spans[1].x - spans[0].x, h);
2662
2663 m = base;
2664 x0 = spans[1].x;
2665 } else if (spans[0].coverage == 0x0) {
2666 if (spans[0].x != x0) {
2667#if PIXMAN_HAS_OP_LERP
2668 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
2669 r->src, r->mask, r->u.composite.dst,
2670 x0 + r->u.composite.src_x,
2671 y + r->u.composite.src_y,
2672 0, 0,
2673 x0, y,
2674 spans[0].x - x0, h);
2675#else
2676 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
2677 r->mask, NULL((void*)0), r->u.composite.dst,
2678 0, 0,
2679 0, 0,
2680 x0, y,
2681 spans[0].x - x0, h);
2682 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_ADD,
2683 r->src, r->mask, r->u.composite.dst,
2684 x0 + r->u.composite.src_x,
2685 y + r->u.composite.src_y,
2686 0, 0,
2687 x0, y,
2688 spans[0].x - x0, h);
2689#endif
2690 }
2691
2692 m = base;
2693 x0 = spans[1].x;
2694 } else {
2695 *m++ = spans[0].coverage;
2696 if (len > 1) {
2697 memset (m, spans[0].coverage, --len);
2698 m += len;
2699 }
2700 }
2701 spans++;
2702 } while (--num_spans > 1);
2703
2704 if (spans[0].x != x0) {
2705#if PIXMAN_HAS_OP_LERP
2706 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
2707 r->src, r->mask, r->u.composite.dst,
2708 x0 + r->u.composite.src_x,
2709 y + r->u.composite.src_y,
2710 0, 0,
2711 x0, y,
2712 spans[0].x - x0, h);
2713#else
2714 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
2715 r->mask, NULL((void*)0), r->u.composite.dst,
2716 0, 0,
2717 0, 0,
2718 x0, y,
2719 spans[0].x - x0, h);
2720 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_ADD,
2721 r->src, r->mask, r->u.composite.dst,
2722 x0 + r->u.composite.src_x,
2723 y + r->u.composite.src_y,
2724 0, 0,
2725 x0, y,
2726 spans[0].x - x0, h);
2727#endif
2728 }
2729
2730 return CAIRO_STATUS_SUCCESS;
2731}
2732
2733static cairo_status_t
2734_inplace_src_opacity_spans (void *abstract_renderer, int y, int h,
2735 const cairo_half_open_span_t *spans,
2736 unsigned num_spans)
2737{
2738 cairo_image_span_renderer_t *r = abstract_renderer;
2739 uint8_t *mask;
2740 int x0;
2741
2742 if (num_spans == 0)
2743 return CAIRO_STATUS_SUCCESS;
2744
2745 x0 = spans[0].x;
2746 mask = (uint8_t *)pixman_image_get_data_moz_pixman_image_get_data (r->mask);
2747 do {
2748 int len = spans[1].x - spans[0].x;
2749 uint8_t m = mul8_8(spans[0].coverage, r->bpp);
2750 if (m == 0) {
2751 if (spans[0].x != x0) {
2752#if PIXMAN_HAS_OP_LERP
2753 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
2754 r->src, r->mask, r->u.composite.dst,
2755 x0 + r->u.composite.src_x,
2756 y + r->u.composite.src_y,
2757 0, 0,
2758 x0, y,
2759 spans[0].x - x0, h);
2760#else
2761 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
2762 r->mask, NULL((void*)0), r->u.composite.dst,
2763 0, 0,
2764 0, 0,
2765 x0, y,
2766 spans[0].x - x0, h);
2767 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_ADD,
2768 r->src, r->mask, r->u.composite.dst,
2769 x0 + r->u.composite.src_x,
2770 y + r->u.composite.src_y,
2771 0, 0,
2772 x0, y,
2773 spans[0].x - x0, h);
2774#endif
2775 }
2776
2777 mask = (uint8_t *)pixman_image_get_data_moz_pixman_image_get_data (r->mask);
2778 x0 = spans[1].x;
2779 } else {
2780 *mask++ = m;
2781 if (len > 1) {
2782 memset (mask, m, --len);
2783 mask += len;
2784 }
2785 }
2786 spans++;
2787 } while (--num_spans > 1);
2788
2789 if (spans[0].x != x0) {
2790#if PIXMAN_HAS_OP_LERP
2791 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
2792 r->src, r->mask, r->u.composite.dst,
2793 x0 + r->u.composite.src_x,
2794 y + r->u.composite.src_y,
2795 0, 0,
2796 x0, y,
2797 spans[0].x - x0, h);
2798#else
2799 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
2800 r->mask, NULL((void*)0), r->u.composite.dst,
2801 0, 0,
2802 0, 0,
2803 x0, y,
2804 spans[0].x - x0, h);
2805 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_ADD,
2806 r->src, r->mask, r->u.composite.dst,
2807 x0 + r->u.composite.src_x,
2808 y + r->u.composite.src_y,
2809 0, 0,
2810 x0, y,
2811 spans[0].x - x0, h);
2812#endif
2813 }
2814
2815 return CAIRO_STATUS_SUCCESS;
2816}
2817
2818static void free_pixels (pixman_image_t *image, void *data)
2819{
2820 free (data);
2821}
2822
2823static cairo_int_status_t
2824inplace_renderer_init (cairo_image_span_renderer_t *r,
2825 const cairo_composite_rectangles_t *composite,
2826 cairo_antialias_t antialias,
2827 cairo_bool_t needs_clip)
2828{
2829 cairo_image_surface_t *dst = (cairo_image_surface_t *)composite->surface;
2830 uint8_t *buf;
2831
2832 if (composite->mask_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID)
2833 return CAIRO_INT_STATUS_UNSUPPORTED;
2834
2835 r->base.render_rows = NULL((void*)0);
2836 r->bpp = composite->mask_pattern.solid.color.alpha_short >> 8;
2837
2838 if (composite->source_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID) {
2839 const cairo_color_t *color;
2840
2841 color = &composite->source_pattern.solid.color;
2842 if (composite->op == CAIRO_OPERATOR_CLEAR)
2843 color = CAIRO_COLOR_TRANSPARENT_cairo_stock_color (CAIRO_STOCK_TRANSPARENT);
2844
2845 if (fill_reduces_to_source (composite->op, color, dst, &r->u.fill.pixel)) {
2846 /* Use plain C for the fill operations as the span length is
2847 * typically small, too small to payback the startup overheads of
2848 * using SSE2 etc.
2849 */
2850 if (r->bpp == 0xff) {
2851 switch (dst->format) {
2852 case CAIRO_FORMAT_A8:
2853 r->base.render_rows = _fill_a8_lerp_opaque_spans;
2854 break;
2855 case CAIRO_FORMAT_RGB24:
2856 case CAIRO_FORMAT_ARGB32:
2857 r->base.render_rows = _fill_xrgb32_lerp_opaque_spans;
2858 break;
2859 case CAIRO_FORMAT_A1:
2860 case CAIRO_FORMAT_RGB16_565:
2861 case CAIRO_FORMAT_RGB30:
2862 case CAIRO_FORMAT_RGB96F:
2863 case CAIRO_FORMAT_RGBA128F:
2864 case CAIRO_FORMAT_INVALID:
2865 default: break;
2866 }
2867 } else {
2868 switch (dst->format) {
2869 case CAIRO_FORMAT_A8:
2870 r->base.render_rows = _fill_a8_lerp_spans;
2871 break;
2872 case CAIRO_FORMAT_RGB24:
2873 case CAIRO_FORMAT_ARGB32:
2874 r->base.render_rows = _fill_xrgb32_lerp_spans;
2875 break;
2876 case CAIRO_FORMAT_A1:
2877 case CAIRO_FORMAT_RGB16_565:
2878 case CAIRO_FORMAT_RGB30:
2879 case CAIRO_FORMAT_RGB96F:
2880 case CAIRO_FORMAT_RGBA128F:
2881 case CAIRO_FORMAT_INVALID:
2882 default: break;
2883 }
2884 }
2885 r->u.fill.data = dst->data;
2886 r->u.fill.stride = dst->stride;
2887 }
2888 } else if ((dst->format == CAIRO_FORMAT_ARGB32 || dst->format == CAIRO_FORMAT_RGB24) &&
2889 (composite->op == CAIRO_OPERATOR_SOURCE ||
2890 (composite->op == CAIRO_OPERATOR_OVER &&
2891 (dst->base.is_clear || (dst->base.content & CAIRO_CONTENT_ALPHA) == 0))) &&
2892 composite->source_pattern.base.type == CAIRO_PATTERN_TYPE_SURFACE &&
2893 composite->source_pattern.surface.surface->backend->type == CAIRO_SURFACE_TYPE_IMAGE &&
2894 to_image_surface(composite->source_pattern.surface.surface)((cairo_image_surface_t *)(composite->source_pattern.surface
.surface))
->format == dst->format)
2895 {
2896 cairo_image_surface_t *src =
2897 to_image_surface(composite->source_pattern.surface.surface)((cairo_image_surface_t *)(composite->source_pattern.surface
.surface))
;
2898 int tx, ty;
2899
2900 if (_cairo_matrix_is_integer_translation(&composite->source_pattern.base.matrix,
2901 &tx, &ty) &&
2902 composite->bounded.x + tx >= 0 &&
2903 composite->bounded.y + ty >= 0 &&
2904 composite->bounded.x + composite->bounded.width + tx <= src->width &&
2905 composite->bounded.y + composite->bounded.height + ty <= src->height) {
2906
2907 assert(PIXMAN_FORMAT_BPP(dst->pixman_format) == 32)((void) sizeof (((((dst->pixman_format >> (24)) &
((1 << (8)) - 1)) << ((dst->pixman_format >>
22) & 3)) == 32) ? 1 : 0), __extension__ ({ if ((((dst->
pixman_format >> (24)) & ((1 << (8)) - 1)) <<
((dst->pixman_format >> 22) & 3)) == 32) ; else
__assert_fail ("PIXMAN_FORMAT_BPP(dst->pixman_format) == 32"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-image-compositor.c"
, 2907, __extension__ __PRETTY_FUNCTION__); }))
;
2908 r->u.blit.stride = dst->stride;
2909 r->u.blit.data = dst->data;
2910 r->u.blit.src_stride = src->stride;
2911 r->u.blit.src_data = src->data + src->stride * ty + tx * 4;
2912 r->base.render_rows = _blit_xrgb32_lerp_spans;
2913 }
2914 }
2915 if (r->base.render_rows == NULL((void*)0)) {
2916 const cairo_pattern_t *src = &composite->source_pattern.base;
2917 unsigned int width;
2918
2919 if (composite->is_bounded == 0)
2920 return CAIRO_INT_STATUS_UNSUPPORTED;
2921
2922 r->base.render_rows = r->bpp == 0xff ? _inplace_spans : _inplace_opacity_spans;
2923 width = (composite->bounded.width + 3) & ~3;
2924
2925 r->u.composite.run_length = 8;
2926 if (src->type == CAIRO_PATTERN_TYPE_LINEAR ||
2927 src->type == CAIRO_PATTERN_TYPE_RADIAL)
2928 r->u.composite.run_length = 256;
2929 if (dst->base.is_clear &&
2930 (composite->op == CAIRO_OPERATOR_SOURCE ||
2931 composite->op == CAIRO_OPERATOR_OVER ||
2932 composite->op == CAIRO_OPERATOR_ADD)) {
2933 r->op = PIXMAN_OP_SRC;
2934 } else if (composite->op == CAIRO_OPERATOR_SOURCE) {
2935 r->base.render_rows = r->bpp == 0xff ? _inplace_src_spans : _inplace_src_opacity_spans;
2936 r->u.composite.mask_y = r->composite->unbounded.y;
2937 width = (composite->unbounded.width + 3) & ~3;
2938 } else if (composite->op == CAIRO_OPERATOR_CLEAR) {
2939 r->op = PIXMAN_OP_OUT_REVERSE;
2940 src = NULL((void*)0);
2941 } else {
2942 r->op = _pixman_operator (composite->op);
2943 }
2944
2945 r->src = _pixman_image_for_pattern (dst, src, FALSE0,
2946 &composite->bounded,
2947 &composite->source_sample_area,
2948 &r->u.composite.src_x, &r->u.composite.src_y);
2949 if (unlikely (r->src == NULL)(__builtin_expect (!!(r->src == ((void*)0)), 0)))
2950 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2951
2952 /* Create an effectively unbounded mask by repeating the single line */
2953 buf = r->_buf;
2954 if (width > SZ_BUF(int)(sizeof (cairo_abstract_span_renderer_t) - sizeof (cairo_image_span_renderer_t
))
) {
2955 buf = _cairo_malloc (width)((width) != 0 ? malloc(width) : ((void*)0));
2956 if (unlikely (buf == NULL)(__builtin_expect (!!(buf == ((void*)0)), 0))) {
2957 pixman_image_unref_moz_pixman_image_unref (r->src);
2958 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2959 }
2960 }
2961 r->mask = pixman_image_create_bits_moz_pixman_image_create_bits (PIXMAN_a8,
2962 width, composite->unbounded.height,
2963 (uint32_t *)buf, 0);
2964 if (unlikely (r->mask == NULL)(__builtin_expect (!!(r->mask == ((void*)0)), 0))) {
2965 pixman_image_unref_moz_pixman_image_unref (r->src);
2966 if (buf != r->_buf)
2967 free (buf);
2968 return _cairo_error(CAIRO_STATUS_NO_MEMORY);
2969 }
2970
2971 if (buf != r->_buf)
2972 pixman_image_set_destroy_function_moz_pixman_image_set_destroy_function (r->mask, free_pixels, buf);
2973
2974 r->u.composite.dst = dst->pixman_image;
2975 }
2976
2977 return CAIRO_INT_STATUS_SUCCESS;
2978}
2979
2980static cairo_int_status_t
2981span_renderer_init (cairo_abstract_span_renderer_t *_r,
2982 const cairo_composite_rectangles_t *composite,
2983 cairo_antialias_t antialias,
2984 cairo_bool_t needs_clip)
2985{
2986 cairo_image_span_renderer_t *r = (cairo_image_span_renderer_t *)_r;
2987 cairo_image_surface_t *dst = (cairo_image_surface_t *)composite->surface;
2988 const cairo_pattern_t *source = &composite->source_pattern.base;
2989 cairo_operator_t op = composite->op;
2990 cairo_int_status_t status;
2991
2992 TRACE ((stderr, "%s: antialias=%d, needs_clip=%d\n", __FUNCTION__,
2993 antialias, needs_clip));
2994
2995 if (needs_clip)
2996 return CAIRO_INT_STATUS_UNSUPPORTED;
2997
2998 r->composite = composite;
2999 r->mask = NULL((void*)0);
3000 r->src = NULL((void*)0);
3001 r->base.finish = NULL((void*)0);
3002
3003 status = mono_renderer_init (r, composite, antialias, needs_clip);
3004 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3005 return status;
3006
3007 status = inplace_renderer_init (r, composite, antialias, needs_clip);
3008 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3009 return status;
3010
3011 r->bpp = 0;
3012
3013 if (op == CAIRO_OPERATOR_CLEAR) {
3014#if PIXMAN_HAS_OP_LERP
3015 op = PIXMAN_OP_LERP_CLEAR;
3016#else
3017 source = &_cairo_pattern_white.base;
3018 op = PIXMAN_OP_OUT_REVERSE;
3019#endif
3020 } else if (dst->base.is_clear &&
3021 (op == CAIRO_OPERATOR_SOURCE ||
3022 op == CAIRO_OPERATOR_OVER ||
3023 op == CAIRO_OPERATOR_ADD)) {
3024 op = PIXMAN_OP_SRC;
3025 } else if (op == CAIRO_OPERATOR_SOURCE) {
3026 if (_cairo_pattern_is_opaque (&composite->source_pattern.base,
3027 &composite->source_sample_area))
3028 {
3029 op = PIXMAN_OP_OVER;
3030 }
3031 else
3032 {
3033#if PIXMAN_HAS_OP_LERP
3034 op = PIXMAN_OP_LERP_SRC;
3035#else
3036 return CAIRO_INT_STATUS_UNSUPPORTED;
3037#endif
3038 }
3039 } else {
3040 op = _pixman_operator (op);
3041 }
3042 r->op = op;
3043
3044 r->src = _pixman_image_for_pattern (dst, source, FALSE0,
3045 &composite->unbounded,
3046 &composite->source_sample_area,
3047 &r->u.mask.src_x, &r->u.mask.src_y);
3048 if (unlikely (r->src == NULL)(__builtin_expect (!!(r->src == ((void*)0)), 0)))
3049 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3050
3051 r->opacity = 1.0;
3052 if (composite->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID) {
3053 r->opacity = composite->mask_pattern.solid.color.alpha;
3054 } else {
3055 pixman_image_t *mask;
3056 int mask_x, mask_y;
3057
3058 mask = _pixman_image_for_pattern (dst,
3059 &composite->mask_pattern.base,
3060 TRUE1,
3061 &composite->unbounded,
3062 &composite->mask_sample_area,
3063 &mask_x, &mask_y);
3064 if (unlikely (mask == NULL)(__builtin_expect (!!(mask == ((void*)0)), 0)))
3065 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3066
3067 /* XXX Component-alpha? */
3068 if ((dst->base.content & CAIRO_CONTENT_COLOR) == 0 &&
3069 _cairo_pattern_is_opaque (source, &composite->source_sample_area))
3070 {
3071 pixman_image_unref_moz_pixman_image_unref (r->src);
3072 r->src = mask;
3073 r->u.mask.src_x = mask_x;
3074 r->u.mask.src_y = mask_y;
3075 mask = NULL((void*)0);
3076 }
3077
3078 if (mask) {
3079 pixman_image_unref_moz_pixman_image_unref (mask);
3080 return CAIRO_INT_STATUS_UNSUPPORTED;
3081 }
3082 }
3083
3084 r->u.mask.extents = composite->unbounded;
3085 r->u.mask.stride = (r->u.mask.extents.width + 3) & ~3;
3086 if (r->u.mask.extents.height * r->u.mask.stride > SZ_BUF(int)(sizeof (cairo_abstract_span_renderer_t) - sizeof (cairo_image_span_renderer_t
))
) {
3087 r->mask = pixman_image_create_bits_moz_pixman_image_create_bits (PIXMAN_a8,
3088 r->u.mask.extents.width,
3089 r->u.mask.extents.height,
3090 NULL((void*)0), 0);
3091
3092 r->base.render_rows = _cairo_image_spans;
3093 r->base.finish = NULL((void*)0);
3094 } else {
3095 r->mask = pixman_image_create_bits_moz_pixman_image_create_bits (PIXMAN_a8,
3096 r->u.mask.extents.width,
3097 r->u.mask.extents.height,
3098 (uint32_t *)r->_buf, r->u.mask.stride);
3099
3100 r->base.render_rows = _cairo_image_spans_and_zero;
3101 r->base.finish = _cairo_image_finish_spans_and_zero;
3102 }
3103 if (unlikely (r->mask == NULL)(__builtin_expect (!!(r->mask == ((void*)0)), 0)))
3104 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3105
3106 r->u.mask.data = (uint8_t *) pixman_image_get_data_moz_pixman_image_get_data (r->mask);
3107 r->u.mask.stride = pixman_image_get_stride_moz_pixman_image_get_stride (r->mask);
3108
3109 r->u.mask.extents.height += r->u.mask.extents.y;
3110 return CAIRO_STATUS_SUCCESS;
3111}
3112
3113static void
3114span_renderer_fini (cairo_abstract_span_renderer_t *_r,
3115 cairo_int_status_t status)
3116{
3117 cairo_image_span_renderer_t *r = (cairo_image_span_renderer_t *) _r;
3118
3119 TRACE ((stderr, "%s\n", __FUNCTION__));
3120
3121 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
) {
3122 if (r->base.finish)
3123 r->base.finish (r);
3124 }
3125 if (likely (status == CAIRO_INT_STATUS_SUCCESS && r->bpp == 0)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS &&
r->bpp == 0), 1))
) {
3126 const cairo_composite_rectangles_t *composite = r->composite;
3127
3128 pixman_image_composite32_moz_pixman_image_composite32 (r->op, r->src, r->mask,
3129 to_pixman_image (composite->surface),
3130 composite->unbounded.x + r->u.mask.src_x,
3131 composite->unbounded.y + r->u.mask.src_y,
3132 0, 0,
3133 composite->unbounded.x,
3134 composite->unbounded.y,
3135 composite->unbounded.width,
3136 composite->unbounded.height);
3137 }
3138
3139 if (r->src)
3140 pixman_image_unref_moz_pixman_image_unref (r->src);
3141 if (r->mask)
3142 pixman_image_unref_moz_pixman_image_unref (r->mask);
3143}
3144#endif
3145
3146const cairo_compositor_t *
3147_cairo_image_spans_compositor_get (void)
3148{
3149 static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT(0);
3150 static cairo_spans_compositor_t spans;
3151 static cairo_compositor_t shape;
3152
3153 if (_cairo_atomic_init_once_enter(&once)) {
3154 _cairo_shape_mask_compositor_init (&shape,
3155 _cairo_image_traps_compositor_get());
3156 shape.glyphs = NULL((void*)0);
3157
3158 _cairo_spans_compositor_init (&spans, &shape);
3159
3160 spans.flags = 0;
3161#if PIXMAN_HAS_OP_LERP
3162 spans.flags |= CAIRO_SPANS_COMPOSITOR_HAS_LERP0x1;
3163#endif
3164
3165 //spans.acquire = acquire;
3166 //spans.release = release;
3167 spans.fill_boxes = fill_boxes;
3168 spans.draw_image_boxes = draw_image_boxes;
3169 //spans.copy_boxes = copy_boxes;
3170 spans.pattern_to_surface = _cairo_image_source_create_for_pattern;
3171 //spans.check_composite_boxes = check_composite_boxes;
3172 spans.composite_boxes = composite_boxes;
3173 //spans.check_span_renderer = check_span_renderer;
3174 spans.renderer_init = span_renderer_init;
3175 spans.renderer_fini = span_renderer_fini;
3176
3177 _cairo_atomic_init_once_leave(&once);
3178 }
3179
3180 return &spans.base;
3181}