Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/cairo/cairo/src/./../../../../../gfx/cairo/cairo/src/cairo-image-compositor.c
Warning:line 1096, 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 -O2 -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-23/lib/clang/23 -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 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-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -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-character-conversion -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 -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-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 (__assert_single_arg (!"reached")), __extension__
({ if (!"reached") ; else __assert_fail ("!\"reached\"", "./../../../../../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
699static void
700set_point (pixman_point_fixed_t *p, cairo_point_t *c)
701{
702 p->x = _cairo_fixed_to_16_16 (c->x);
703 p->y = _cairo_fixed_to_16_16 (c->y);
704}
705
706void
707_pixman_image_add_tristrip (pixman_image_t *image,
708 int dst_x, int dst_y,
709 cairo_tristrip_t *strip)
710{
711 pixman_triangle_t tri;
712 pixman_point_fixed_t *p[3] = {&tri.p1, &tri.p2, &tri.p3 };
713 int n;
714
715 set_point (p[0], &strip->points[0]);
716 set_point (p[1], &strip->points[1]);
717 set_point (p[2], &strip->points[2]);
718 pixman_add_triangles_moz_pixman_add_triangles (image, -dst_x, -dst_y, 1, &tri);
719 for (n = 3; n < strip->num_points; n++) {
720 set_point (p[n%3], &strip->points[n]);
721 pixman_add_triangles_moz_pixman_add_triangles (image, -dst_x, -dst_y, 1, &tri);
722 }
723}
724
725static cairo_int_status_t
726composite_tristrip (void *_dst,
727 cairo_operator_t op,
728 cairo_surface_t *abstract_src,
729 int src_x,
730 int src_y,
731 int dst_x,
732 int dst_y,
733 const cairo_rectangle_int_t *extents,
734 cairo_antialias_t antialias,
735 cairo_tristrip_t *strip)
736{
737 cairo_image_surface_t *dst = (cairo_image_surface_t *) _dst;
738 cairo_image_source_t *src = (cairo_image_source_t *) abstract_src;
739 pixman_image_t *mask;
740 pixman_format_code_t format;
741
742 TRACE ((stderr, "%s\n", __FUNCTION__));
743
744 if (strip->num_points < 3)
745 return CAIRO_STATUS_SUCCESS;
746
747 if (1) { /* pixman doesn't eliminate self-intersecting triangles/edges */
748 cairo_int_status_t status;
749 cairo_traps_t traps;
750 int n;
751
752 _cairo_traps_init (&traps);
753 for (n = 0; n < strip->num_points; n++) {
754 cairo_point_t p[4];
755
756 p[0] = strip->points[0];
757 p[1] = strip->points[1];
758 p[2] = strip->points[2];
759 p[3] = strip->points[0];
760
761 _cairo_traps_tessellate_convex_quad (&traps, p);
762 }
763 status = composite_traps (_dst, op, abstract_src,
764 src_x, src_y,
765 dst_x, dst_y,
766 extents, antialias, &traps);
767 _cairo_traps_fini (&traps);
768
769 return status;
770 }
771
772 format = antialias == CAIRO_ANTIALIAS_NONE ? PIXMAN_a1 : PIXMAN_a8;
773 if (dst->pixman_format == format &&
774 (abstract_src == NULL((void*)0) ||
775 (op == CAIRO_OPERATOR_ADD && src->is_opaque_solid)))
776 {
777 _pixman_image_add_tristrip (dst->pixman_image, dst_x, dst_y, strip);
778 return CAIRO_STATUS_SUCCESS;
779 }
780
781 mask = pixman_image_create_bits_moz_pixman_image_create_bits (format,
782 extents->width, extents->height,
783 NULL((void*)0), 0);
784 if (unlikely (mask == NULL)(__builtin_expect (!!(mask == ((void*)0)), 0)))
785 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
786
787 _pixman_image_add_tristrip (mask, extents->x, extents->y, strip);
788 pixman_image_composite32_moz_pixman_image_composite32 (_pixman_operator (op),
789 src->pixman_image, mask, dst->pixman_image,
790 extents->x + src_x, extents->y + src_y,
791 0, 0,
792 extents->x - dst_x, extents->y - dst_y,
793 extents->width, extents->height);
794
795 pixman_image_unref_moz_pixman_image_unref (mask);
796
797 return CAIRO_STATUS_SUCCESS;
798}
799
800static cairo_int_status_t
801check_composite_glyphs (const cairo_composite_rectangles_t *extents,
802 cairo_scaled_font_t *scaled_font,
803 cairo_glyph_t *glyphs,
804 int *num_glyphs)
805{
806 return CAIRO_STATUS_SUCCESS;
807}
808
809#if HAS_PIXMAN_GLYPHS
810static pixman_glyph_cache_t *global_glyph_cache;
811
812static inline pixman_glyph_cache_t *
813get_glyph_cache (void)
814{
815 if (!global_glyph_cache)
816 global_glyph_cache = pixman_glyph_cache_create_moz_pixman_glyph_cache_create ();
817
818 return global_glyph_cache;
819}
820
821void
822_cairo_image_compositor_reset_static_data (void)
823{
824 CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex)pthread_mutex_lock (&(_cairo_glyph_cache_mutex));
825
826 if (global_glyph_cache)
827 pixman_glyph_cache_destroy_moz_pixman_glyph_cache_destroy (global_glyph_cache);
828 global_glyph_cache = NULL((void*)0);
829
830 CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex)pthread_mutex_unlock (&(_cairo_glyph_cache_mutex));
831}
832
833void
834_cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
835 cairo_scaled_glyph_t *scaled_glyph)
836{
837 CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex)pthread_mutex_lock (&(_cairo_glyph_cache_mutex));
838
839 if (global_glyph_cache) {
840 pixman_glyph_cache_remove_moz_pixman_glyph_cache_remove (
841 global_glyph_cache, scaled_font,
842 (void *)scaled_glyph->hash_entry.hash);
843 }
844
845 CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex)pthread_mutex_unlock (&(_cairo_glyph_cache_mutex));
846}
847
848#define PHASE(x) ((int)(floor (4 * (x + 0.125)) - 4 * floor (x + 0.125)))
849#define POSITION(x) ((int) floor (x + 0.125))
850
851static cairo_int_status_t
852composite_glyphs (void *_dst,
853 cairo_operator_t op,
854 cairo_surface_t *_src,
855 int src_x,
856 int src_y,
857 int dst_x,
858 int dst_y,
859 cairo_composite_glyphs_info_t *info)
860{
861 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
862 pixman_glyph_cache_t *glyph_cache;
863 pixman_glyph_t pglyphs_stack[CAIRO_STACK_ARRAY_LENGTH (pixman_glyph_t)((512 * sizeof (int)) / sizeof(pixman_glyph_t))];
864 pixman_glyph_t *pglyphs = pglyphs_stack;
865 pixman_glyph_t *pg;
866 int i;
867
868 TRACE ((stderr, "%s\n", __FUNCTION__));
869
870 CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex)pthread_mutex_lock (&(_cairo_glyph_cache_mutex));
871
872 glyph_cache = get_glyph_cache();
873 if (unlikely (glyph_cache == NULL)(__builtin_expect (!!(glyph_cache == ((void*)0)), 0))) {
874 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
875 goto out_unlock;
876 }
877
878 pixman_glyph_cache_freeze_moz_pixman_glyph_cache_freeze (glyph_cache);
879
880 if (info->num_glyphs > ARRAY_LENGTH (pglyphs_stack)((int) (sizeof (pglyphs_stack) / sizeof (pglyphs_stack[0])))) {
881 pglyphs = _cairo_malloc_ab (info->num_glyphs, sizeof (pixman_glyph_t));
882 if (unlikely (pglyphs == NULL)(__builtin_expect (!!(pglyphs == ((void*)0)), 0))) {
883 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
884 goto out_thaw;
885 }
886 }
887
888 pg = pglyphs;
889 for (i = 0; i < info->num_glyphs; i++) {
890 unsigned long index = info->glyphs[i].index;
891 const void *glyph;
892 unsigned long xphase, yphase;
893
894 xphase = PHASE(info->glyphs[i].x);
895 yphase = PHASE(info->glyphs[i].y);
896
897 index = index | (xphase << 24) | (yphase << 26);
898
899 glyph = pixman_glyph_cache_lookup_moz_pixman_glyph_cache_lookup (glyph_cache, info->font, (void *)(uintptr_t)index);
900 if (!glyph) {
901 cairo_scaled_glyph_t *scaled_glyph;
902 cairo_image_surface_t *glyph_surface;
903
904 /* This call can actually end up recursing, so we have to
905 * drop the mutex around it.
906 */
907 CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex)pthread_mutex_unlock (&(_cairo_glyph_cache_mutex));
908 status = _cairo_scaled_glyph_lookup (info->font, index,
909 CAIRO_SCALED_GLYPH_INFO_SURFACE,
910 NULL((void*)0), /* foreground color */
911 &scaled_glyph);
912 CAIRO_MUTEX_LOCK (_cairo_glyph_cache_mutex)pthread_mutex_lock (&(_cairo_glyph_cache_mutex));
913
914 if (unlikely (status)(__builtin_expect (!!(status), 0)))
915 goto out_thaw;
916
917 glyph_surface = scaled_glyph->surface;
918 glyph = pixman_glyph_cache_insert_moz_pixman_glyph_cache_insert (glyph_cache, info->font, (void *)(uintptr_t)index,
919 glyph_surface->base.device_transform.x0,
920 glyph_surface->base.device_transform.y0,
921 glyph_surface->pixman_image);
922 if (unlikely (!glyph)(__builtin_expect (!!(!glyph), 0))) {
923 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
924 goto out_thaw;
925 }
926 }
927
928 pg->x = POSITION (info->glyphs[i].x);
929 pg->y = POSITION (info->glyphs[i].y);
930 pg->glyph = glyph;
931 pg++;
932 }
933
934 if (info->use_mask) {
935 pixman_format_code_t mask_format;
936
937 mask_format = pixman_glyph_get_mask_format_moz_pixman_glyph_get_mask_format (glyph_cache, pg - pglyphs, pglyphs);
938
939 pixman_composite_glyphs_moz_pixman_composite_glyphs (_pixman_operator (op),
940 ((cairo_image_source_t *)_src)->pixman_image,
941 to_pixman_image (_dst),
942 mask_format,
943 info->extents.x + src_x, info->extents.y + src_y,
944 info->extents.x, info->extents.y,
945 info->extents.x - dst_x, info->extents.y - dst_y,
946 info->extents.width, info->extents.height,
947 glyph_cache, pg - pglyphs, pglyphs);
948 } else {
949 pixman_composite_glyphs_no_mask_moz_pixman_composite_glyphs_no_mask (_pixman_operator (op),
950 ((cairo_image_source_t *)_src)->pixman_image,
951 to_pixman_image (_dst),
952 src_x, src_y,
953 - dst_x, - dst_y,
954 glyph_cache, pg - pglyphs, pglyphs);
955 }
956
957out_thaw:
958 pixman_glyph_cache_thaw_moz_pixman_glyph_cache_thaw (glyph_cache);
959
960 if (pglyphs != pglyphs_stack)
961 free(pglyphs);
962
963out_unlock:
964 CAIRO_MUTEX_UNLOCK (_cairo_glyph_cache_mutex)pthread_mutex_unlock (&(_cairo_glyph_cache_mutex));
965 return status;
966}
967#else
968void
969_cairo_image_compositor_reset_static_data (void)
970{
971}
972
973void
974_cairo_image_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
975 cairo_scaled_glyph_t *scaled_glyph)
976{
977}
978
979static cairo_int_status_t
980composite_one_glyph (void *_dst,
981 cairo_operator_t op,
982 cairo_surface_t *_src,
983 int src_x,
984 int src_y,
985 int dst_x,
986 int dst_y,
987 cairo_composite_glyphs_info_t *info)
988{
989 cairo_image_surface_t *glyph_surface;
990 cairo_scaled_glyph_t *scaled_glyph;
991 cairo_status_t status;
992 int x, y;
993
994 TRACE ((stderr, "%s\n", __FUNCTION__));
995
996 status = _cairo_scaled_glyph_lookup (info->font,
997 info->glyphs[0].index,
998 CAIRO_SCALED_GLYPH_INFO_SURFACE,
999 NULL((void*)0), /* foreground color */
1000 &scaled_glyph);
1001
1002 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1003 return status;
1004
1005 glyph_surface = scaled_glyph->surface;
1006 if (glyph_surface->width == 0 || glyph_surface->height == 0)
1007 return CAIRO_INT_STATUS_NOTHING_TO_DO;
1008
1009 /* round glyph locations to the nearest pixel */
1010 /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
1011 x = _cairo_lround (info->glyphs[0].x -
1012 glyph_surface->base.device_transform.x0);
1013 y = _cairo_lround (info->glyphs[0].y -
1014 glyph_surface->base.device_transform.y0);
1015
1016 pixman_image_composite32_moz_pixman_image_composite32 (_pixman_operator (op),
1017 ((cairo_image_source_t *)_src)->pixman_image,
1018 glyph_surface->pixman_image,
1019 to_pixman_image (_dst),
1020 x + src_x, y + src_y,
1021 0, 0,
1022 x - dst_x, y - dst_y,
1023 glyph_surface->width,
1024 glyph_surface->height);
1025
1026 return CAIRO_INT_STATUS_SUCCESS;
1027}
1028
1029static cairo_int_status_t
1030composite_glyphs_via_mask (void *_dst,
1031 cairo_operator_t op,
1032 cairo_surface_t *_src,
1033 int src_x,
1034 int src_y,
1035 int dst_x,
1036 int dst_y,
1037 cairo_composite_glyphs_info_t *info)
1038{
1039 cairo_scaled_glyph_t *glyph_cache[64];
1040 pixman_image_t *white = _pixman_image_for_color (CAIRO_COLOR_WHITE_cairo_stock_color (CAIRO_STOCK_WHITE));
1041 cairo_scaled_glyph_t *scaled_glyph;
1042 uint8_t buf[2048];
1043 pixman_image_t *mask;
1044 pixman_format_code_t format;
1045 cairo_status_t status;
1046 int i;
1047
1048 TRACE ((stderr, "%s\n", __FUNCTION__));
1049
1050 if (unlikely (white == NULL)(__builtin_expect (!!(white == ((void*)0)), 0)))
1051 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1052
1053 /* XXX convert the glyphs to common formats a8/a8r8g8b8 to hit
1054 * optimised paths through pixman. Should we increase the bit
1055 * depth of the target surface, we should reconsider the appropriate
1056 * mask formats.
1057 */
1058
1059 status = _cairo_scaled_glyph_lookup (info->font,
1060 info->glyphs[0].index,
1061 CAIRO_SCALED_GLYPH_INFO_SURFACE,
1062 NULL((void*)0), /* foreground color */
1063 &scaled_glyph);
1064 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
1065 pixman_image_unref_moz_pixman_image_unref (white);
1066 return status;
1067 }
1068
1069 memset (glyph_cache, 0, sizeof (glyph_cache));
1070 glyph_cache[info->glyphs[0].index % ARRAY_LENGTH (glyph_cache)((int) (sizeof (glyph_cache) / sizeof (glyph_cache[0])))] = scaled_glyph;
1071
1072 format = PIXMAN_a8;
1073 i = (info->extents.width + 3) & ~3;
1074 if (scaled_glyph->surface->base.content & CAIRO_CONTENT_COLOR) {
1075 format = PIXMAN_a8r8g8b8;
1076 i = info->extents.width * 4;
1077 }
1078
1079 if (i * info->extents.height > (int) sizeof (buf)) {
1080 mask = pixman_image_create_bits_moz_pixman_image_create_bits (format,
1081 info->extents.width,
1082 info->extents.height,
1083 NULL((void*)0), 0);
1084 } else {
1085 memset (buf, 0, i * info->extents.height);
1086 mask = pixman_image_create_bits_moz_pixman_image_create_bits (format,
1087 info->extents.width,
1088 info->extents.height,
1089 (uint32_t *)buf, i);
1090 }
1091 if (unlikely (mask == NULL)(__builtin_expect (!!(mask == ((void*)0)), 0))) {
1092 pixman_image_unref_moz_pixman_image_unref (white);
1093 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1094 }
1095
1096 status = CAIRO_STATUS_SUCCESS;
Value stored to 'status' is never read
1097 for (i = 0; i < info->num_glyphs; i++) {
1098 unsigned long glyph_index = info->glyphs[i].index;
1099 int cache_index = glyph_index % ARRAY_LENGTH (glyph_cache)((int) (sizeof (glyph_cache) / sizeof (glyph_cache[0])));
1100 cairo_image_surface_t *glyph_surface;
1101 int x, y;
1102
1103 scaled_glyph = glyph_cache[cache_index];
1104 if (scaled_glyph == NULL((void*)0) ||
1105 _cairo_scaled_glyph_index (scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
!= glyph_index)
1106 {
1107 status = _cairo_scaled_glyph_lookup (info->font, glyph_index,
1108 CAIRO_SCALED_GLYPH_INFO_SURFACE,
1109 NULL((void*)0), /* foreground color */
1110 &scaled_glyph);
1111
1112 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
1113 pixman_image_unref_moz_pixman_image_unref (mask);
1114 pixman_image_unref_moz_pixman_image_unref (white);
1115 return status;
1116 }
1117
1118 glyph_cache[cache_index] = scaled_glyph;
1119 }
1120
1121 glyph_surface = scaled_glyph->surface;
1122 if (glyph_surface->width && glyph_surface->height) {
1123 if (glyph_surface->base.content & CAIRO_CONTENT_COLOR &&
1124 format == PIXMAN_a8) {
1125 pixman_image_t *ca_mask;
1126
1127 format = PIXMAN_a8r8g8b8;
1128 ca_mask = pixman_image_create_bits_moz_pixman_image_create_bits (format,
1129 info->extents.width,
1130 info->extents.height,
1131 NULL((void*)0), 0);
1132 if (unlikely (ca_mask == NULL)(__builtin_expect (!!(ca_mask == ((void*)0)), 0))) {
1133 pixman_image_unref_moz_pixman_image_unref (mask);
1134 pixman_image_unref_moz_pixman_image_unref (white);
1135 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1136 }
1137
1138 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_SRC,
1139 white, mask, ca_mask,
1140 0, 0,
1141 0, 0,
1142 0, 0,
1143 info->extents.width,
1144 info->extents.height);
1145 pixman_image_unref_moz_pixman_image_unref (mask);
1146 mask = ca_mask;
1147 }
1148
1149 /* round glyph locations to the nearest pixel */
1150 /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
1151 x = _cairo_lround (info->glyphs[i].x -
1152 glyph_surface->base.device_transform.x0);
1153 y = _cairo_lround (info->glyphs[i].y -
1154 glyph_surface->base.device_transform.y0);
1155
1156 if (glyph_surface->pixman_format == format) {
1157 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_ADD,
1158 glyph_surface->pixman_image, NULL((void*)0), mask,
1159 0, 0,
1160 0, 0,
1161 x - info->extents.x, y - info->extents.y,
1162 glyph_surface->width,
1163 glyph_surface->height);
1164 } else {
1165 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_ADD,
1166 white, glyph_surface->pixman_image, mask,
1167 0, 0,
1168 0, 0,
1169 x - info->extents.x, y - info->extents.y,
1170 glyph_surface->width,
1171 glyph_surface->height);
1172 }
1173 }
1174 }
1175
1176 if (format == PIXMAN_a8r8g8b8)
1177 pixman_image_set_component_alpha_moz_pixman_image_set_component_alpha (mask, TRUE1);
1178
1179 pixman_image_composite32_moz_pixman_image_composite32 (_pixman_operator (op),
1180 ((cairo_image_source_t *)_src)->pixman_image,
1181 mask,
1182 to_pixman_image (_dst),
1183 info->extents.x + src_x, info->extents.y + src_y,
1184 0, 0,
1185 info->extents.x - dst_x, info->extents.y - dst_y,
1186 info->extents.width, info->extents.height);
1187 pixman_image_unref_moz_pixman_image_unref (mask);
1188 pixman_image_unref_moz_pixman_image_unref (white);
1189
1190 return CAIRO_STATUS_SUCCESS;
1191}
1192
1193static cairo_int_status_t
1194composite_glyphs (void *_dst,
1195 cairo_operator_t op,
1196 cairo_surface_t *_src,
1197 int src_x,
1198 int src_y,
1199 int dst_x,
1200 int dst_y,
1201 cairo_composite_glyphs_info_t *info)
1202{
1203 cairo_scaled_glyph_t *glyph_cache[64];
1204 pixman_image_t *dst, *src;
1205 cairo_status_t status;
1206 int i;
1207
1208 TRACE ((stderr, "%s\n", __FUNCTION__));
1209
1210 if (info->num_glyphs == 1)
1211 return composite_one_glyph(_dst, op, _src, src_x, src_y, dst_x, dst_y, info);
1212
1213 if (info->use_mask)
1214 return composite_glyphs_via_mask(_dst, op, _src, src_x, src_y, dst_x, dst_y, info);
1215
1216 op = _pixman_operator (op);
1217 dst = to_pixman_image (_dst);
1218 src = ((cairo_image_source_t *)_src)->pixman_image;
1219
1220 memset (glyph_cache, 0, sizeof (glyph_cache));
1221 status = CAIRO_STATUS_SUCCESS;
1222
1223 for (i = 0; i < info->num_glyphs; i++) {
1224 int x, y;
1225 cairo_image_surface_t *glyph_surface;
1226 cairo_scaled_glyph_t *scaled_glyph;
1227 unsigned long glyph_index = info->glyphs[i].index;
1228 int cache_index = glyph_index % ARRAY_LENGTH (glyph_cache)((int) (sizeof (glyph_cache) / sizeof (glyph_cache[0])));
1229
1230 scaled_glyph = glyph_cache[cache_index];
1231 if (scaled_glyph == NULL((void*)0) ||
1232 _cairo_scaled_glyph_index (scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
!= glyph_index)
1233 {
1234 status = _cairo_scaled_glyph_lookup (info->font, glyph_index,
1235 CAIRO_SCALED_GLYPH_INFO_SURFACE,
1236 NULL((void*)0), /* foreground color */
1237 &scaled_glyph);
1238
1239 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1240 break;
1241
1242 glyph_cache[cache_index] = scaled_glyph;
1243 }
1244
1245 glyph_surface = scaled_glyph->surface;
1246 if (glyph_surface->width && glyph_surface->height) {
1247 /* round glyph locations to the nearest pixel */
1248 /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
1249 x = _cairo_lround (info->glyphs[i].x -
1250 glyph_surface->base.device_transform.x0);
1251 y = _cairo_lround (info->glyphs[i].y -
1252 glyph_surface->base.device_transform.y0);
1253
1254 pixman_image_composite32_moz_pixman_image_composite32 (op, src, glyph_surface->pixman_image, dst,
1255 x + src_x, y + src_y,
1256 0, 0,
1257 x - dst_x, y - dst_y,
1258 glyph_surface->width,
1259 glyph_surface->height);
1260 }
1261 }
1262
1263 return status;
1264}
1265#endif
1266
1267static cairo_int_status_t
1268check_composite (const cairo_composite_rectangles_t *extents)
1269{
1270 return CAIRO_STATUS_SUCCESS;
1271}
1272
1273const cairo_compositor_t *
1274_cairo_image_traps_compositor_get (void)
1275{
1276 static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT(0);
1277 static cairo_traps_compositor_t compositor;
1278
1279 if (_cairo_atomic_init_once_enter(&once)) {
1280 _cairo_traps_compositor_init(&compositor,
1281 &__cairo_no_compositor);
1282 compositor.acquire = acquire;
1283 compositor.release = release;
1284 compositor.set_clip_region = set_clip_region;
1285 compositor.pattern_to_surface = _cairo_image_source_create_for_pattern;
1286 compositor.draw_image_boxes = draw_image_boxes;
1287 //compositor.copy_boxes = copy_boxes;
1288 compositor.fill_boxes = fill_boxes;
1289 compositor.check_composite = check_composite;
1290 compositor.composite = composite;
1291 compositor.lerp = lerp;
1292 //compositor.check_composite_boxes = check_composite_boxes;
1293 compositor.composite_boxes = composite_boxes;
1294 //compositor.check_composite_traps = check_composite_traps;
1295 compositor.composite_traps = composite_traps;
1296 //compositor.check_composite_tristrip = check_composite_traps;
1297 compositor.composite_tristrip = composite_tristrip;
1298 compositor.check_composite_glyphs = check_composite_glyphs;
1299 compositor.composite_glyphs = composite_glyphs;
1300
1301 _cairo_atomic_init_once_leave(&once);
1302 }
1303
1304 return &compositor.base;
1305}
1306
1307const cairo_compositor_t *
1308_cairo_image_mask_compositor_get (void)
1309{
1310 static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT(0);
1311 static cairo_mask_compositor_t compositor;
1312
1313 if (_cairo_atomic_init_once_enter(&once)) {
1314 _cairo_mask_compositor_init (&compositor,
1315 _cairo_image_traps_compositor_get ());
1316 compositor.acquire = acquire;
1317 compositor.release = release;
1318 compositor.set_clip_region = set_clip_region;
1319 compositor.pattern_to_surface = _cairo_image_source_create_for_pattern;
1320 compositor.draw_image_boxes = draw_image_boxes;
1321 compositor.fill_rectangles = fill_rectangles;
1322 compositor.fill_boxes = fill_boxes;
1323 compositor.check_composite = check_composite;
1324 compositor.composite = composite;
1325 //compositor.lerp = lerp;
1326 //compositor.check_composite_boxes = check_composite_boxes;
1327 compositor.composite_boxes = composite_boxes;
1328 compositor.check_composite_glyphs = check_composite_glyphs;
1329 compositor.composite_glyphs = composite_glyphs;
1330
1331 _cairo_atomic_init_once_leave(&once);
1332 }
1333
1334 return &compositor.base;
1335}
1336
1337#if PIXMAN_HAS_COMPOSITOR
1338typedef struct _cairo_image_span_renderer {
1339 cairo_span_renderer_t base;
1340
1341 pixman_image_compositor_t *compositor;
1342 pixman_image_t *src, *mask;
1343 float opacity;
1344 cairo_rectangle_int_t extents;
1345} cairo_image_span_renderer_t;
1346COMPILE_TIME_ASSERT (sizeof (cairo_image_span_renderer_t) <= sizeof (cairo_abstract_span_renderer_t))typedef int compile_time_assertion_at_line_1346_failed [(sizeof
(cairo_image_span_renderer_t) <= sizeof (cairo_abstract_span_renderer_t
))?1:-1]
;
1347
1348static cairo_status_t
1349_cairo_image_bounded_opaque_spans (void *abstract_renderer,
1350 int y, int height,
1351 const cairo_half_open_span_t *spans,
1352 unsigned num_spans)
1353{
1354 cairo_image_span_renderer_t *r = abstract_renderer;
1355
1356 if (num_spans == 0)
1357 return CAIRO_STATUS_SUCCESS;
1358
1359 do {
1360 if (spans[0].coverage)
1361 pixman_image_compositor_blt (r->compositor,
1362 spans[0].x, y,
1363 spans[1].x - spans[0].x, height,
1364 spans[0].coverage);
1365 spans++;
1366 } while (--num_spans > 1);
1367
1368 return CAIRO_STATUS_SUCCESS;
1369}
1370
1371static cairo_status_t
1372_cairo_image_bounded_spans (void *abstract_renderer,
1373 int y, int height,
1374 const cairo_half_open_span_t *spans,
1375 unsigned num_spans)
1376{
1377 cairo_image_span_renderer_t *r = abstract_renderer;
1378
1379 if (num_spans == 0)
1380 return CAIRO_STATUS_SUCCESS;
1381
1382 do {
1383 if (spans[0].coverage) {
1384 pixman_image_compositor_blt (r->compositor,
1385 spans[0].x, y,
1386 spans[1].x - spans[0].x, height,
1387 r->opacity * spans[0].coverage);
1388 }
1389 spans++;
1390 } while (--num_spans > 1);
1391
1392 return CAIRO_STATUS_SUCCESS;
1393}
1394
1395static cairo_status_t
1396_cairo_image_unbounded_spans (void *abstract_renderer,
1397 int y, int height,
1398 const cairo_half_open_span_t *spans,
1399 unsigned num_spans)
1400{
1401 cairo_image_span_renderer_t *r = abstract_renderer;
1402
1403 assert (y + height <= r->extents.height)((void) sizeof (__assert_single_arg (y + height <= r->extents
.height)), __extension__ ({ if (y + height <= r->extents
.height) ; else __assert_fail ("y + height <= r->extents.height"
, "./../../../../../gfx/cairo/cairo/src/cairo-image-compositor.c"
, 1403, __extension__ __PRETTY_FUNCTION__); }))
;
1404 if (y > r->extents.y) {
1405 pixman_image_compositor_blt (r->compositor,
1406 r->extents.x, r->extents.y,
1407 r->extents.width, y - r->extents.y,
1408 0);
1409 }
1410
1411 if (num_spans == 0) {
1412 pixman_image_compositor_blt (r->compositor,
1413 r->extents.x, y,
1414 r->extents.width, height,
1415 0);
1416 } else {
1417 if (spans[0].x != r->extents.x) {
1418 pixman_image_compositor_blt (r->compositor,
1419 r->extents.x, y,
1420 spans[0].x - r->extents.x,
1421 height,
1422 0);
1423 }
1424
1425 do {
1426 assert (spans[0].x < r->extents.x + r->extents.width)((void) sizeof (__assert_single_arg (spans[0].x < r->extents
.x + r->extents.width)), __extension__ ({ if (spans[0].x <
r->extents.x + r->extents.width) ; else __assert_fail (
"spans[0].x < r->extents.x + r->extents.width", "./../../../../../gfx/cairo/cairo/src/cairo-image-compositor.c"
, 1426, __extension__ __PRETTY_FUNCTION__); }))
;
1427 pixman_image_compositor_blt (r->compositor,
1428 spans[0].x, y,
1429 spans[1].x - spans[0].x, height,
1430 r->opacity * spans[0].coverage);
1431 spans++;
1432 } while (--num_spans > 1);
1433
1434 if (spans[0].x != r->extents.x + r->extents.width) {
1435 assert (spans[0].x < r->extents.x + r->extents.width)((void) sizeof (__assert_single_arg (spans[0].x < r->extents
.x + r->extents.width)), __extension__ ({ if (spans[0].x <
r->extents.x + r->extents.width) ; else __assert_fail (
"spans[0].x < r->extents.x + r->extents.width", "./../../../../../gfx/cairo/cairo/src/cairo-image-compositor.c"
, 1435, __extension__ __PRETTY_FUNCTION__); }))
;
1436 pixman_image_compositor_blt (r->compositor,
1437 spans[0].x, y,
1438 r->extents.x + r->extents.width - spans[0].x, height,
1439 0);
1440 }
1441 }
1442
1443 r->extents.y = y + height;
1444 return CAIRO_STATUS_SUCCESS;
1445}
1446
1447static cairo_status_t
1448_cairo_image_clipped_spans (void *abstract_renderer,
1449 int y, int height,
1450 const cairo_half_open_span_t *spans,
1451 unsigned num_spans)
1452{
1453 cairo_image_span_renderer_t *r = abstract_renderer;
1454
1455 assert (num_spans)((void) sizeof (__assert_single_arg (num_spans)), __extension__
({ if (num_spans) ; else __assert_fail ("num_spans", "./../../../../../gfx/cairo/cairo/src/cairo-image-compositor.c"
, 1455, __extension__ __PRETTY_FUNCTION__); }))
;
1456
1457 do {
1458 if (! spans[0].inverse)
1459 pixman_image_compositor_blt (r->compositor,
1460 spans[0].x, y,
1461 spans[1].x - spans[0].x, height,
1462 r->opacity * spans[0].coverage);
1463 spans++;
1464 } while (--num_spans > 1);
1465
1466 r->extents.y = y + height;
1467 return CAIRO_STATUS_SUCCESS;
1468}
1469
1470static cairo_status_t
1471_cairo_image_finish_unbounded_spans (void *abstract_renderer)
1472{
1473 cairo_image_span_renderer_t *r = abstract_renderer;
1474
1475 if (r->extents.y < r->extents.height) {
1476 pixman_image_compositor_blt (r->compositor,
1477 r->extents.x, r->extents.y,
1478 r->extents.width,
1479 r->extents.height - r->extents.y,
1480 0);
1481 }
1482
1483 return CAIRO_STATUS_SUCCESS;
1484}
1485
1486static cairo_int_status_t
1487span_renderer_init (cairo_abstract_span_renderer_t *_r,
1488 const cairo_composite_rectangles_t *composite,
1489 cairo_bool_t needs_clip)
1490{
1491 cairo_image_span_renderer_t *r = (cairo_image_span_renderer_t *)_r;
1492 cairo_image_surface_t *dst = (cairo_image_surface_t *)composite->surface;
1493 const cairo_pattern_t *source = &composite->source_pattern.base;
1494 cairo_operator_t op = composite->op;
1495 int src_x, src_y;
1496 int mask_x, mask_y;
1497
1498 TRACE ((stderr, "%s\n", __FUNCTION__));
1499
1500 if (op == CAIRO_OPERATOR_CLEAR) {
1501 op = PIXMAN_OP_LERP_CLEAR;
1502 } else if (dst->base.is_clear &&
1503 (op == CAIRO_OPERATOR_SOURCE ||
1504 op == CAIRO_OPERATOR_OVER ||
1505 op == CAIRO_OPERATOR_ADD)) {
1506 op = PIXMAN_OP_SRC;
1507 } else if (op == CAIRO_OPERATOR_SOURCE) {
1508 op = PIXMAN_OP_LERP_SRC;
1509 } else {
1510 op = _pixman_operator (op);
1511 }
1512
1513 r->compositor = NULL((void*)0);
1514 r->mask = NULL((void*)0);
1515 r->src = _pixman_image_for_pattern (dst, source, FALSE0,
1516 &composite->unbounded,
1517 &composite->source_sample_area,
1518 &src_x, &src_y);
1519 if (unlikely (r->src == NULL)(__builtin_expect (!!(r->src == ((void*)0)), 0)))
1520 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1521
1522 r->opacity = 1.0;
1523 if (composite->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID) {
1524 r->opacity = composite->mask_pattern.solid.color.alpha;
1525 } else {
1526 r->mask = _pixman_image_for_pattern (dst,
1527 &composite->mask_pattern.base,
1528 TRUE1,
1529 &composite->unbounded,
1530 &composite->mask_sample_area,
1531 &mask_x, &mask_y);
1532 if (unlikely (r->mask == NULL)(__builtin_expect (!!(r->mask == ((void*)0)), 0)))
1533 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1534
1535 /* XXX Component-alpha? */
1536 if ((dst->base.content & CAIRO_CONTENT_COLOR) == 0 &&
1537 _cairo_pattern_is_opaque (source, &composite->source_sample_area))
1538 {
1539 pixman_image_unref_moz_pixman_image_unref (r->src);
1540 r->src = r->mask;
1541 src_x = mask_x;
1542 src_y = mask_y;
1543 r->mask = NULL((void*)0);
1544 }
1545 }
1546
1547 if (composite->is_bounded) {
1548 if (r->opacity == 1.)
1549 r->base.render_rows = _cairo_image_bounded_opaque_spans;
1550 else
1551 r->base.render_rows = _cairo_image_bounded_spans;
1552 r->base.finish = NULL((void*)0);
1553 } else {
1554 if (needs_clip)
1555 r->base.render_rows = _cairo_image_clipped_spans;
1556 else
1557 r->base.render_rows = _cairo_image_unbounded_spans;
1558 r->base.finish = _cairo_image_finish_unbounded_spans;
1559 r->extents = composite->unbounded;
1560 r->extents.height += r->extents.y;
1561 }
1562
1563 r->compositor =
1564 pixman_image_create_compositor (op, r->src, r->mask, dst->pixman_image,
1565 composite->unbounded.x + src_x,
1566 composite->unbounded.y + src_y,
1567 composite->unbounded.x + mask_x,
1568 composite->unbounded.y + mask_y,
1569 composite->unbounded.x,
1570 composite->unbounded.y,
1571 composite->unbounded.width,
1572 composite->unbounded.height);
1573 if (unlikely (r->compositor == NULL)(__builtin_expect (!!(r->compositor == ((void*)0)), 0)))
1574 return CAIRO_INT_STATUS_NOTHING_TO_DO;
1575
1576 return CAIRO_STATUS_SUCCESS;
1577}
1578
1579static void
1580span_renderer_fini (cairo_abstract_span_renderer_t *_r,
1581 cairo_int_status_t status)
1582{
1583 cairo_image_span_renderer_t *r = (cairo_image_span_renderer_t *) _r;
1584
1585 TRACE ((stderr, "%s\n", __FUNCTION__));
1586
1587 if (status == CAIRO_INT_STATUS_SUCCESS && r->base.finish)
1588 r->base.finish (r);
1589
1590 if (r->compositor)
1591 pixman_image_compositor_destroy (r->compositor);
1592
1593 if (r->src)
1594 pixman_image_unref_moz_pixman_image_unref (r->src);
1595 if (r->mask)
1596 pixman_image_unref_moz_pixman_image_unref (r->mask);
1597}
1598#else
1599typedef struct _cairo_image_span_renderer {
1600 cairo_span_renderer_t base;
1601
1602 const cairo_composite_rectangles_t *composite;
1603
1604 float opacity;
1605 uint8_t op;
1606 int bpp;
1607
1608 pixman_image_t *src, *mask;
1609 union {
1610 struct fill {
1611 ptrdiff_t stride;
1612 uint8_t *data;
1613 uint32_t pixel;
1614 } fill;
1615 struct blit {
1616 int stride;
1617 uint8_t *data;
1618 int src_stride;
1619 uint8_t *src_data;
1620 } blit;
1621 struct composite {
1622 pixman_image_t *dst;
1623 int src_x, src_y;
1624 int mask_x, mask_y;
1625 int run_length;
1626 } composite;
1627 struct finish {
1628 cairo_rectangle_int_t extents;
1629 int src_x, src_y;
1630 ptrdiff_t stride;
1631 uint8_t *data;
1632 } mask;
1633 } u;
1634 uint8_t _buf[0];
1635#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))
1636} cairo_image_span_renderer_t;
1637COMPILE_TIME_ASSERT (sizeof (cairo_image_span_renderer_t) <= sizeof (cairo_abstract_span_renderer_t))typedef int compile_time_assertion_at_line_1637_failed [(sizeof
(cairo_image_span_renderer_t) <= sizeof (cairo_abstract_span_renderer_t
))?1:-1]
;
1638
1639static cairo_status_t
1640_cairo_image_spans (void *abstract_renderer,
1641 int y, int height,
1642 const cairo_half_open_span_t *spans,
1643 unsigned num_spans)
1644{
1645 cairo_image_span_renderer_t *r = abstract_renderer;
1646 uint8_t *mask, *row;
1647 int len;
1648
1649 if (num_spans == 0)
1650 return CAIRO_STATUS_SUCCESS;
1651
1652 mask = r->u.mask.data + (y - r->u.mask.extents.y) * r->u.mask.stride;
1653 mask += spans[0].x - r->u.mask.extents.x;
1654 row = mask;
1655
1656 do {
1657 len = spans[1].x - spans[0].x;
1658 if (spans[0].coverage) {
1659 *row++ = r->opacity * spans[0].coverage;
1660 if (--len)
1661 memset (row, row[-1], len);
1662 }
1663 row += len;
1664 spans++;
1665 } while (--num_spans > 1);
1666
1667 len = row - mask;
1668 row = mask;
1669 while (--height) {
1670 mask += r->u.mask.stride;
1671 memcpy (mask, row, len);
1672 }
1673
1674 return CAIRO_STATUS_SUCCESS;
1675}
1676
1677static cairo_status_t
1678_cairo_image_spans_and_zero (void *abstract_renderer,
1679 int y, int height,
1680 const cairo_half_open_span_t *spans,
1681 unsigned num_spans)
1682{
1683 cairo_image_span_renderer_t *r = abstract_renderer;
1684 uint8_t *mask;
1685 int len;
1686
1687 mask = r->u.mask.data;
1688 if (y > r->u.mask.extents.y) {
1689 len = (y - r->u.mask.extents.y) * r->u.mask.stride;
1690 memset (mask, 0, len);
1691 mask += len;
1692 }
1693
1694 r->u.mask.extents.y = y + height;
1695 r->u.mask.data = mask + height * r->u.mask.stride;
1696 if (num_spans == 0) {
1697 memset (mask, 0, height * r->u.mask.stride);
1698 } else {
1699 uint8_t *row = mask;
1700
1701 if (spans[0].x != r->u.mask.extents.x) {
1702 len = spans[0].x - r->u.mask.extents.x;
1703 memset (row, 0, len);
1704 row += len;
1705 }
1706
1707 do {
1708 len = spans[1].x - spans[0].x;
1709 *row++ = r->opacity * spans[0].coverage;
1710 if (len > 1) {
1711 memset (row, row[-1], --len);
1712 row += len;
1713 }
1714 spans++;
1715 } while (--num_spans > 1);
1716
1717 if (spans[0].x != r->u.mask.extents.x + r->u.mask.extents.width) {
1718 len = r->u.mask.extents.x + r->u.mask.extents.width - spans[0].x;
1719 memset (row, 0, len);
1720 }
1721
1722 row = mask;
1723 while (--height) {
1724 mask += r->u.mask.stride;
1725 memcpy (mask, row, r->u.mask.extents.width);
1726 }
1727 }
1728
1729 return CAIRO_STATUS_SUCCESS;
1730}
1731
1732static cairo_status_t
1733_cairo_image_finish_spans_and_zero (void *abstract_renderer)
1734{
1735 cairo_image_span_renderer_t *r = abstract_renderer;
1736
1737 if (r->u.mask.extents.y < r->u.mask.extents.height)
1738 memset (r->u.mask.data, 0, (r->u.mask.extents.height - r->u.mask.extents.y) * r->u.mask.stride);
1739
1740 return CAIRO_STATUS_SUCCESS;
1741}
1742
1743static cairo_status_t
1744_fill8_spans (void *abstract_renderer, int y, int h,
1745 const cairo_half_open_span_t *spans, unsigned num_spans)
1746{
1747 cairo_image_span_renderer_t *r = abstract_renderer;
1748
1749 if (num_spans == 0)
1750 return CAIRO_STATUS_SUCCESS;
1751
1752 if (likely(h == 1)(__builtin_expect (!!(h == 1), 1))) {
1753 do {
1754 if (spans[0].coverage) {
1755 int len = spans[1].x - spans[0].x;
1756 uint8_t *d = r->u.fill.data + r->u.fill.stride*y + spans[0].x;
1757 if (len == 1)
1758 *d = r->u.fill.pixel;
1759 else
1760 memset(d, r->u.fill.pixel, len);
1761 }
1762 spans++;
1763 } while (--num_spans > 1);
1764 } else {
1765 do {
1766 if (spans[0].coverage) {
1767 int yy = y, hh = h;
1768 do {
1769 int len = spans[1].x - spans[0].x;
1770 uint8_t *d = r->u.fill.data + r->u.fill.stride*yy + spans[0].x;
1771 if (len == 1)
1772 *d = r->u.fill.pixel;
1773 else
1774 memset(d, r->u.fill.pixel, len);
1775 yy++;
1776 } while (--hh);
1777 }
1778 spans++;
1779 } while (--num_spans > 1);
1780 }
1781
1782 return CAIRO_STATUS_SUCCESS;
1783}
1784
1785static cairo_status_t
1786_fill16_spans (void *abstract_renderer, int y, int h,
1787 const cairo_half_open_span_t *spans, unsigned num_spans)
1788{
1789 cairo_image_span_renderer_t *r = abstract_renderer;
1790
1791 if (num_spans == 0)
1792 return CAIRO_STATUS_SUCCESS;
1793
1794 if (likely(h == 1)(__builtin_expect (!!(h == 1), 1))) {
1795 do {
1796 if (spans[0].coverage) {
1797 int len = spans[1].x - spans[0].x;
1798 uint16_t *d = (uint16_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*2);
1799 while (len-- > 0)
1800 *d++ = r->u.fill.pixel;
1801 }
1802 spans++;
1803 } while (--num_spans > 1);
1804 } else {
1805 do {
1806 if (spans[0].coverage) {
1807 int yy = y, hh = h;
1808 do {
1809 int len = spans[1].x - spans[0].x;
1810 uint16_t *d = (uint16_t*)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*2);
1811 while (len-- > 0)
1812 *d++ = r->u.fill.pixel;
1813 yy++;
1814 } while (--hh);
1815 }
1816 spans++;
1817 } while (--num_spans > 1);
1818 }
1819
1820 return CAIRO_STATUS_SUCCESS;
1821}
1822
1823static cairo_status_t
1824_fill32_spans (void *abstract_renderer, int y, int h,
1825 const cairo_half_open_span_t *spans, unsigned num_spans)
1826{
1827 cairo_image_span_renderer_t *r = abstract_renderer;
1828
1829 if (num_spans == 0)
1830 return CAIRO_STATUS_SUCCESS;
1831
1832 if (likely(h == 1)(__builtin_expect (!!(h == 1), 1))) {
1833 do {
1834 if (spans[0].coverage) {
1835 int len = spans[1].x - spans[0].x;
1836 if (len > 32) {
1837 pixman_fill_moz_pixman_fill ((uint32_t *)r->u.fill.data, r->u.fill.stride / sizeof(uint32_t), r->bpp,
1838 spans[0].x, y, len, 1, r->u.fill.pixel);
1839 } else {
1840 uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*4);
1841 while (len-- > 0)
1842 *d++ = r->u.fill.pixel;
1843 }
1844 }
1845 spans++;
1846 } while (--num_spans > 1);
1847 } else {
1848 do {
1849 if (spans[0].coverage) {
1850 if (spans[1].x - spans[0].x > 16) {
1851 pixman_fill_moz_pixman_fill ((uint32_t *)r->u.fill.data, r->u.fill.stride / sizeof(uint32_t), r->bpp,
1852 spans[0].x, y, spans[1].x - spans[0].x, h,
1853 r->u.fill.pixel);
1854 } else {
1855 int yy = y, hh = h;
1856 do {
1857 int len = spans[1].x - spans[0].x;
1858 uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*4);
1859 while (len-- > 0)
1860 *d++ = r->u.fill.pixel;
1861 yy++;
1862 } while (--hh);
1863 }
1864 }
1865 spans++;
1866 } while (--num_spans > 1);
1867 }
1868
1869 return CAIRO_STATUS_SUCCESS;
1870}
1871
1872#if 0
1873static cairo_status_t
1874_fill_spans (void *abstract_renderer, int y, int h,
1875 const cairo_half_open_span_t *spans, unsigned num_spans)
1876{
1877 cairo_image_span_renderer_t *r = abstract_renderer;
1878
1879 if (num_spans == 0)
1880 return CAIRO_STATUS_SUCCESS;
1881
1882 do {
1883 if (spans[0].coverage) {
1884 pixman_fill_moz_pixman_fill ((uint32_t *) r->data, r->stride, r->bpp,
1885 spans[0].x, y,
1886 spans[1].x - spans[0].x, h,
1887 r->pixel);
1888 }
1889 spans++;
1890 } while (--num_spans > 1);
1891
1892 return CAIRO_STATUS_SUCCESS;
1893}
1894#endif
1895
1896static cairo_status_t
1897_blit_spans (void *abstract_renderer, int y, int h,
1898 const cairo_half_open_span_t *spans, unsigned num_spans)
1899{
1900 cairo_image_span_renderer_t *r = abstract_renderer;
1901 int cpp;
1902
1903 if (num_spans == 0)
1904 return CAIRO_STATUS_SUCCESS;
1905
1906 cpp = r->bpp/8;
1907 if (likely (h == 1)(__builtin_expect (!!(h == 1), 1))) {
1908 uint8_t *src = r->u.blit.src_data + y*r->u.blit.src_stride;
1909 uint8_t *dst = r->u.blit.data + y*r->u.blit.stride;
1910 do {
1911 if (spans[0].coverage) {
1912 void *s = src + spans[0].x*cpp;
1913 void *d = dst + spans[0].x*cpp;
1914 int len = (spans[1].x - spans[0].x) * cpp;
1915 switch (len) {
1916 case 1:
1917 *(uint8_t *)d = *(uint8_t *)s;
1918 break;
1919 case 2:
1920 *(uint16_t *)d = *(uint16_t *)s;
1921 break;
1922 case 4:
1923 *(uint32_t *)d = *(uint32_t *)s;
1924 break;
1925#if HAVE_UINT64_T1
1926 case 8:
1927 *(uint64_t *)d = *(uint64_t *)s;
1928 break;
1929#endif
1930 default:
1931 memcpy(d, s, len);
1932 break;
1933 }
1934 }
1935 spans++;
1936 } while (--num_spans > 1);
1937 } else {
1938 do {
1939 if (spans[0].coverage) {
1940 int yy = y, hh = h;
1941 do {
1942 void *src = r->u.blit.src_data + yy*r->u.blit.src_stride + spans[0].x*cpp;
1943 void *dst = r->u.blit.data + yy*r->u.blit.stride + spans[0].x*cpp;
1944 int len = (spans[1].x - spans[0].x) * cpp;
1945 switch (len) {
1946 case 1:
1947 *(uint8_t *)dst = *(uint8_t *)src;
1948 break;
1949 case 2:
1950 *(uint16_t *)dst = *(uint16_t *)src;
1951 break;
1952 case 4:
1953 *(uint32_t *)dst = *(uint32_t *)src;
1954 break;
1955#if HAVE_UINT64_T1
1956 case 8:
1957 *(uint64_t *)dst = *(uint64_t *)src;
1958 break;
1959#endif
1960 default:
1961 memcpy(dst, src, len);
1962 break;
1963 }
1964 yy++;
1965 } while (--hh);
1966 }
1967 spans++;
1968 } while (--num_spans > 1);
1969 }
1970
1971 return CAIRO_STATUS_SUCCESS;
1972}
1973
1974static cairo_status_t
1975_mono_spans (void *abstract_renderer, int y, int h,
1976 const cairo_half_open_span_t *spans, unsigned num_spans)
1977{
1978 cairo_image_span_renderer_t *r = abstract_renderer;
1979
1980 if (num_spans == 0)
1981 return CAIRO_STATUS_SUCCESS;
1982
1983 do {
1984 if (spans[0].coverage) {
1985 pixman_image_composite32_moz_pixman_image_composite32 (r->op,
1986 r->src, NULL((void*)0), r->u.composite.dst,
1987 spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
1988 0, 0,
1989 spans[0].x, y,
1990 spans[1].x - spans[0].x, h);
1991 }
1992 spans++;
1993 } while (--num_spans > 1);
1994
1995 return CAIRO_STATUS_SUCCESS;
1996}
1997
1998static cairo_status_t
1999_mono_unbounded_spans (void *abstract_renderer, int y, int h,
2000 const cairo_half_open_span_t *spans, unsigned num_spans)
2001{
2002 cairo_image_span_renderer_t *r = abstract_renderer;
2003
2004 if (num_spans == 0) {
2005 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_CLEAR,
2006 r->src, NULL((void*)0), r->u.composite.dst,
2007 spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
2008 0, 0,
2009 r->composite->unbounded.x, y,
2010 r->composite->unbounded.width, h);
2011 r->u.composite.mask_y = y + h;
2012 return CAIRO_STATUS_SUCCESS;
2013 }
2014
2015 if (y != r->u.composite.mask_y) {
2016 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_CLEAR,
2017 r->src, NULL((void*)0), r->u.composite.dst,
2018 spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
2019 0, 0,
2020 r->composite->unbounded.x, r->u.composite.mask_y,
2021 r->composite->unbounded.width, y - r->u.composite.mask_y);
2022 }
2023
2024 if (spans[0].x != r->composite->unbounded.x) {
2025 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_CLEAR,
2026 r->src, NULL((void*)0), r->u.composite.dst,
2027 spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
2028 0, 0,
2029 r->composite->unbounded.x, y,
2030 spans[0].x - r->composite->unbounded.x, h);
2031 }
2032
2033 do {
2034 int op = spans[0].coverage ? r->op : PIXMAN_OP_CLEAR;
2035 pixman_image_composite32_moz_pixman_image_composite32 (op,
2036 r->src, NULL((void*)0), r->u.composite.dst,
2037 spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
2038 0, 0,
2039 spans[0].x, y,
2040 spans[1].x - spans[0].x, h);
2041 spans++;
2042 } while (--num_spans > 1);
2043
2044 if (spans[0].x != r->composite->unbounded.x + r->composite->unbounded.width) {
2045 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_CLEAR,
2046 r->src, NULL((void*)0), r->u.composite.dst,
2047 spans[0].x + r->u.composite.src_x, y + r->u.composite.src_y,
2048 0, 0,
2049 spans[0].x, y,
2050 r->composite->unbounded.x + r->composite->unbounded.width - spans[0].x, h);
2051 }
2052
2053 r->u.composite.mask_y = y + h;
2054 return CAIRO_STATUS_SUCCESS;
2055}
2056
2057static cairo_status_t
2058_mono_finish_unbounded_spans (void *abstract_renderer)
2059{
2060 cairo_image_span_renderer_t *r = abstract_renderer;
2061
2062 if (r->u.composite.mask_y < r->composite->unbounded.y + r->composite->unbounded.height) {
2063 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_CLEAR,
2064 r->src, NULL((void*)0), r->u.composite.dst,
2065 r->composite->unbounded.x + r->u.composite.src_x, r->u.composite.mask_y + r->u.composite.src_y,
2066 0, 0,
2067 r->composite->unbounded.x, r->u.composite.mask_y,
2068 r->composite->unbounded.width,
2069 r->composite->unbounded.y + r->composite->unbounded.height - r->u.composite.mask_y);
2070 }
2071
2072 return CAIRO_STATUS_SUCCESS;
2073}
2074
2075static cairo_int_status_t
2076mono_renderer_init (cairo_image_span_renderer_t *r,
2077 const cairo_composite_rectangles_t *composite,
2078 cairo_antialias_t antialias,
2079 cairo_bool_t needs_clip)
2080{
2081 cairo_image_surface_t *dst = (cairo_image_surface_t *)composite->surface;
2082
2083 if (antialias != CAIRO_ANTIALIAS_NONE)
2084 return CAIRO_INT_STATUS_UNSUPPORTED;
2085
2086 if (!_cairo_pattern_is_opaque_solid (&composite->mask_pattern.base))
2087 return CAIRO_INT_STATUS_UNSUPPORTED;
2088
2089 r->base.render_rows = NULL((void*)0);
2090 if (composite->source_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID) {
2091 const cairo_color_t *color;
2092
2093 color = &composite->source_pattern.solid.color;
2094 if (composite->op == CAIRO_OPERATOR_CLEAR)
2095 color = CAIRO_COLOR_TRANSPARENT_cairo_stock_color (CAIRO_STOCK_TRANSPARENT);
2096
2097 if (fill_reduces_to_source (composite->op, color, dst, &r->u.fill.pixel)) {
2098 /* Use plain C for the fill operations as the span length is
2099 * typically small, too small to payback the startup overheads of
2100 * using SSE2 etc.
2101 */
2102 switch (PIXMAN_FORMAT_BPP(dst->pixman_format)(((dst->pixman_format >> (24)) & ((1 << (8
)) - 1)) << ((dst->pixman_format >> 22) & 3
))
) {
2103 case 8: r->base.render_rows = _fill8_spans; break;
2104 case 16: r->base.render_rows = _fill16_spans; break;
2105 case 32: r->base.render_rows = _fill32_spans; break;
2106 default: break;
2107 }
2108 r->u.fill.data = dst->data;
2109 r->u.fill.stride = dst->stride;
2110 }
2111 } else if ((composite->op == CAIRO_OPERATOR_SOURCE ||
2112 (composite->op == CAIRO_OPERATOR_OVER &&
2113 (dst->base.is_clear || (dst->base.content & CAIRO_CONTENT_ALPHA) == 0))) &&
2114 composite->source_pattern.base.type == CAIRO_PATTERN_TYPE_SURFACE &&
2115 composite->source_pattern.surface.surface->backend->type == CAIRO_SURFACE_TYPE_IMAGE &&
2116 to_image_surface(composite->source_pattern.surface.surface)((cairo_image_surface_t *)(composite->source_pattern.surface
.surface))
->format == dst->format)
2117 {
2118 cairo_image_surface_t *src =
2119 to_image_surface(composite->source_pattern.surface.surface)((cairo_image_surface_t *)(composite->source_pattern.surface
.surface))
;
2120 int tx, ty;
2121
2122 if (_cairo_matrix_is_integer_translation(&composite->source_pattern.base.matrix,
2123 &tx, &ty) &&
2124 composite->bounded.x + tx >= 0 &&
2125 composite->bounded.y + ty >= 0 &&
2126 composite->bounded.x + composite->bounded.width + tx <= src->width &&
2127 composite->bounded.y + composite->bounded.height + ty <= src->height) {
2128
2129 r->u.blit.stride = dst->stride;
2130 r->u.blit.data = dst->data;
2131 r->u.blit.src_stride = src->stride;
2132 r->u.blit.src_data = src->data + src->stride * ty + tx * 4;
2133 r->base.render_rows = _blit_spans;
2134 }
2135 }
2136
2137 if (r->base.render_rows == NULL((void*)0)) {
2138 r->src = _pixman_image_for_pattern (dst, &composite->source_pattern.base, FALSE0,
2139 &composite->unbounded,
2140 &composite->source_sample_area,
2141 &r->u.composite.src_x, &r->u.composite.src_y);
2142 if (unlikely (r->src == NULL)(__builtin_expect (!!(r->src == ((void*)0)), 0)))
2143 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2144
2145 r->u.composite.dst = to_pixman_image (composite->surface);
2146 r->op = _pixman_operator (composite->op);
2147 if (composite->is_bounded == 0) {
2148 r->base.render_rows = _mono_unbounded_spans;
2149 r->base.finish = _mono_finish_unbounded_spans;
2150 r->u.composite.mask_y = composite->unbounded.y;
2151 } else
2152 r->base.render_rows = _mono_spans;
2153 }
2154 r->bpp = PIXMAN_FORMAT_BPP(dst->pixman_format)(((dst->pixman_format >> (24)) & ((1 << (8
)) - 1)) << ((dst->pixman_format >> 22) & 3
))
;
2155
2156 return CAIRO_INT_STATUS_SUCCESS;
2157}
2158
2159#define ONE_HALF0x7f 0x7f
2160#define RB_MASK0x00ff00ff 0x00ff00ff
2161#define RB_ONE_HALF0x007f007f 0x007f007f
2162#define RB_MASK_PLUS_ONE0x01000100 0x01000100
2163#define G_SHIFT8 8
2164static inline uint32_t
2165mul8x2_8 (uint32_t a, uint8_t b)
2166{
2167 uint32_t t = (a & RB_MASK0x00ff00ff) * b + RB_ONE_HALF0x007f007f;
2168 return ((t + ((t >> G_SHIFT8) & RB_MASK0x00ff00ff)) >> G_SHIFT8) & RB_MASK0x00ff00ff;
2169}
2170
2171static inline uint32_t
2172add8x2_8x2 (uint32_t a, uint32_t b)
2173{
2174 uint32_t t = a + b;
2175 t |= RB_MASK_PLUS_ONE0x01000100 - ((t >> G_SHIFT8) & RB_MASK0x00ff00ff);
2176 return t & RB_MASK0x00ff00ff;
2177}
2178
2179static inline uint8_t
2180mul8_8 (uint8_t a, uint8_t b)
2181{
2182 uint16_t t = a * (uint16_t)b + ONE_HALF0x7f;
2183 return ((t >> G_SHIFT8) + t) >> G_SHIFT8;
2184}
2185
2186static inline uint32_t
2187lerp8x4 (uint32_t src, uint8_t a, uint32_t dst)
2188{
2189 return (add8x2_8x2 (mul8x2_8 (src, a),
2190 mul8x2_8 (dst, ~a)) |
2191 add8x2_8x2 (mul8x2_8 (src >> G_SHIFT8, a),
2192 mul8x2_8 (dst >> G_SHIFT8, ~a)) << G_SHIFT8);
2193}
2194
2195static cairo_status_t
2196_fill_a8_lerp_opaque_spans (void *abstract_renderer, int y, int h,
2197 const cairo_half_open_span_t *spans, unsigned num_spans)
2198{
2199 cairo_image_span_renderer_t *r = abstract_renderer;
2200
2201 if (num_spans == 0)
2202 return CAIRO_STATUS_SUCCESS;
2203
2204 if (likely(h == 1)(__builtin_expect (!!(h == 1), 1))) {
2205 uint8_t *d = r->u.fill.data + r->u.fill.stride*y;
2206 do {
2207 uint8_t a = spans[0].coverage;
2208 if (a) {
2209 int len = spans[1].x - spans[0].x;
2210 if (a == 0xff) {
2211 memset(d + spans[0].x, r->u.fill.pixel, len);
2212 } else {
2213 uint8_t s = mul8_8(a, r->u.fill.pixel);
2214 uint8_t *dst = d + spans[0].x;
2215 a = ~a;
2216 while (len-- > 0) {
2217 uint8_t t = mul8_8(*dst, a);
2218 *dst++ = t + s;
2219 }
2220 }
2221 }
2222 spans++;
2223 } while (--num_spans > 1);
2224 } else {
2225 do {
2226 uint8_t a = spans[0].coverage;
2227 if (a) {
2228 int yy = y, hh = h;
2229 if (a == 0xff) {
2230 do {
2231 int len = spans[1].x - spans[0].x;
2232 uint8_t *d = r->u.fill.data + r->u.fill.stride*yy + spans[0].x;
2233 memset(d, r->u.fill.pixel, len);
2234 yy++;
2235 } while (--hh);
2236 } else {
2237 uint8_t s = mul8_8(a, r->u.fill.pixel);
2238 a = ~a;
2239 do {
2240 int len = spans[1].x - spans[0].x;
2241 uint8_t *d = r->u.fill.data + r->u.fill.stride*yy + spans[0].x;
2242 while (len-- > 0) {
2243 uint8_t t = mul8_8(*d, a);
2244 *d++ = t + s;
2245 }
2246 yy++;
2247 } while (--hh);
2248 }
2249 }
2250 spans++;
2251 } while (--num_spans > 1);
2252 }
2253
2254 return CAIRO_STATUS_SUCCESS;
2255}
2256
2257static cairo_status_t
2258_fill_xrgb32_lerp_opaque_spans (void *abstract_renderer, int y, int h,
2259 const cairo_half_open_span_t *spans, unsigned num_spans)
2260{
2261 cairo_image_span_renderer_t *r = abstract_renderer;
2262
2263 if (num_spans == 0)
2264 return CAIRO_STATUS_SUCCESS;
2265
2266 if (likely(h == 1)(__builtin_expect (!!(h == 1), 1))) {
2267 do {
2268 uint8_t a = spans[0].coverage;
2269 if (a) {
2270 int len = spans[1].x - spans[0].x;
2271 uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*4);
2272 if (a == 0xff) {
2273 if (len > 31) {
2274 pixman_fill_moz_pixman_fill ((uint32_t *)r->u.fill.data, r->u.fill.stride / sizeof(uint32_t), 32,
2275 spans[0].x, y, len, 1, r->u.fill.pixel);
2276 } else {
2277 uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*4);
2278 while (len-- > 0)
2279 *d++ = r->u.fill.pixel;
2280 }
2281 } else while (len-- > 0) {
2282 *d = lerp8x4 (r->u.fill.pixel, a, *d);
2283 d++;
2284 }
2285 }
2286 spans++;
2287 } while (--num_spans > 1);
2288 } else {
2289 do {
2290 uint8_t a = spans[0].coverage;
2291 if (a) {
2292 if (a == 0xff) {
2293 if (spans[1].x - spans[0].x > 16) {
2294 pixman_fill_moz_pixman_fill ((uint32_t *)r->u.fill.data, r->u.fill.stride / sizeof(uint32_t), 32,
2295 spans[0].x, y, spans[1].x - spans[0].x, h,
2296 r->u.fill.pixel);
2297 } else {
2298 int yy = y, hh = h;
2299 do {
2300 int len = spans[1].x - spans[0].x;
2301 uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*4);
2302 while (len-- > 0)
2303 *d++ = r->u.fill.pixel;
2304 yy++;
2305 } while (--hh);
2306 }
2307 } else {
2308 int yy = y, hh = h;
2309 do {
2310 int len = spans[1].x - spans[0].x;
2311 uint32_t *d = (uint32_t *)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*4);
2312 while (len-- > 0) {
2313 *d = lerp8x4 (r->u.fill.pixel, a, *d);
2314 d++;
2315 }
2316 yy++;
2317 } while (--hh);
2318 }
2319 }
2320 spans++;
2321 } while (--num_spans > 1);
2322 }
2323
2324 return CAIRO_STATUS_SUCCESS;
2325}
2326
2327static cairo_status_t
2328_fill_a8_lerp_spans (void *abstract_renderer, int y, int h,
2329 const cairo_half_open_span_t *spans, unsigned num_spans)
2330{
2331 cairo_image_span_renderer_t *r = abstract_renderer;
2332
2333 if (num_spans == 0)
2334 return CAIRO_STATUS_SUCCESS;
2335
2336 if (likely(h == 1)(__builtin_expect (!!(h == 1), 1))) {
2337 do {
2338 uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
2339 if (a) {
2340 int len = spans[1].x - spans[0].x;
2341 uint8_t *d = r->u.fill.data + r->u.fill.stride*y + spans[0].x;
2342 uint16_t p = (uint16_t)a * r->u.fill.pixel + 0x7f;
2343 uint16_t ia = ~a;
2344 while (len-- > 0) {
2345 uint16_t t = *d*ia + p;
2346 *d++ = (t + (t>>8)) >> 8;
2347 }
2348 }
2349 spans++;
2350 } while (--num_spans > 1);
2351 } else {
2352 do {
2353 uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
2354 if (a) {
2355 int yy = y, hh = h;
2356 uint16_t p = (uint16_t)a * r->u.fill.pixel + 0x7f;
2357 uint16_t ia = ~a;
2358 do {
2359 int len = spans[1].x - spans[0].x;
2360 uint8_t *d = r->u.fill.data + r->u.fill.stride*yy + spans[0].x;
2361 while (len-- > 0) {
2362 uint16_t t = *d*ia + p;
2363 *d++ = (t + (t>>8)) >> 8;
2364 }
2365 yy++;
2366 } while (--hh);
2367 }
2368 spans++;
2369 } while (--num_spans > 1);
2370 }
2371
2372 return CAIRO_STATUS_SUCCESS;
2373}
2374
2375static cairo_status_t
2376_fill_xrgb32_lerp_spans (void *abstract_renderer, int y, int h,
2377 const cairo_half_open_span_t *spans, unsigned num_spans)
2378{
2379 cairo_image_span_renderer_t *r = abstract_renderer;
2380
2381 if (num_spans == 0)
2382 return CAIRO_STATUS_SUCCESS;
2383
2384 if (likely(h == 1)(__builtin_expect (!!(h == 1), 1))) {
2385 do {
2386 uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
2387 if (a) {
2388 int len = spans[1].x - spans[0].x;
2389 uint32_t *d = (uint32_t*)(r->u.fill.data + r->u.fill.stride*y + spans[0].x*4);
2390 while (len-- > 0) {
2391 *d = lerp8x4 (r->u.fill.pixel, a, *d);
2392 d++;
2393 }
2394 }
2395 spans++;
2396 } while (--num_spans > 1);
2397 } else {
2398 do {
2399 uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
2400 if (a) {
2401 int yy = y, hh = h;
2402 do {
2403 int len = spans[1].x - spans[0].x;
2404 uint32_t *d = (uint32_t *)(r->u.fill.data + r->u.fill.stride*yy + spans[0].x*4);
2405 while (len-- > 0) {
2406 *d = lerp8x4 (r->u.fill.pixel, a, *d);
2407 d++;
2408 }
2409 yy++;
2410 } while (--hh);
2411 }
2412 spans++;
2413 } while (--num_spans > 1);
2414 }
2415
2416 return CAIRO_STATUS_SUCCESS;
2417}
2418
2419static cairo_status_t
2420_blit_xrgb32_lerp_spans (void *abstract_renderer, int y, int h,
2421 const cairo_half_open_span_t *spans, unsigned num_spans)
2422{
2423 cairo_image_span_renderer_t *r = abstract_renderer;
2424
2425 if (num_spans == 0)
2426 return CAIRO_STATUS_SUCCESS;
2427
2428 if (likely(h == 1)(__builtin_expect (!!(h == 1), 1))) {
2429 uint8_t *src = r->u.blit.src_data + y*r->u.blit.src_stride;
2430 uint8_t *dst = r->u.blit.data + y*r->u.blit.stride;
2431 do {
2432 uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
2433 if (a) {
2434 uint32_t *s = (uint32_t*)src + spans[0].x;
2435 uint32_t *d = (uint32_t*)dst + spans[0].x;
2436 int len = spans[1].x - spans[0].x;
2437 if (a == 0xff) {
2438 if (len == 1)
2439 *d = *s;
2440 else
2441 memcpy(d, s, len*4);
2442 } else {
2443 while (len-- > 0) {
2444 *d = lerp8x4 (*s, a, *d);
2445 s++, d++;
2446 }
2447 }
2448 }
2449 spans++;
2450 } while (--num_spans > 1);
2451 } else {
2452 do {
2453 uint8_t a = mul8_8 (spans[0].coverage, r->bpp);
2454 if (a) {
2455 int yy = y, hh = h;
2456 do {
2457 uint32_t *s = (uint32_t *)(r->u.blit.src_data + yy*r->u.blit.src_stride + spans[0].x * 4);
2458 uint32_t *d = (uint32_t *)(r->u.blit.data + yy*r->u.blit.stride + spans[0].x * 4);
2459 int len = spans[1].x - spans[0].x;
2460 if (a == 0xff) {
2461 if (len == 1)
2462 *d = *s;
2463 else
2464 memcpy(d, s, len * 4);
2465 } else {
2466 while (len-- > 0) {
2467 *d = lerp8x4 (*s, a, *d);
2468 s++, d++;
2469 }
2470 }
2471 yy++;
2472 } while (--hh);
2473 }
2474 spans++;
2475 } while (--num_spans > 1);
2476 }
2477
2478 return CAIRO_STATUS_SUCCESS;
2479}
2480
2481static cairo_status_t
2482_inplace_spans (void *abstract_renderer,
2483 int y, int h,
2484 const cairo_half_open_span_t *spans,
2485 unsigned num_spans)
2486{
2487 cairo_image_span_renderer_t *r = abstract_renderer;
2488 uint8_t *mask;
2489 int x0, x1;
2490
2491 if (num_spans == 0)
2492 return CAIRO_STATUS_SUCCESS;
2493
2494 if (num_spans == 2 && spans[0].coverage == 0xff) {
2495 pixman_image_composite32_moz_pixman_image_composite32 (r->op, r->src, NULL((void*)0), r->u.composite.dst,
2496 spans[0].x + r->u.composite.src_x,
2497 y + r->u.composite.src_y,
2498 0, 0,
2499 spans[0].x, y,
2500 spans[1].x - spans[0].x, h);
2501 return CAIRO_STATUS_SUCCESS;
2502 }
2503
2504 mask = (uint8_t *)pixman_image_get_data_moz_pixman_image_get_data (r->mask);
2505 x1 = x0 = spans[0].x;
2506 do {
2507 int len = spans[1].x - spans[0].x;
2508 *mask++ = spans[0].coverage;
2509 if (len > 1) {
2510 if (len >= r->u.composite.run_length && spans[0].coverage == 0xff) {
2511 if (x1 != x0) {
2512 pixman_image_composite32_moz_pixman_image_composite32 (r->op, r->src, r->mask, r->u.composite.dst,
2513 x0 + r->u.composite.src_x,
2514 y + r->u.composite.src_y,
2515 0, 0,
2516 x0, y,
2517 x1 - x0, h);
2518 }
2519 pixman_image_composite32_moz_pixman_image_composite32 (r->op, r->src, NULL((void*)0), r->u.composite.dst,
2520 spans[0].x + r->u.composite.src_x,
2521 y + r->u.composite.src_y,
2522 0, 0,
2523 spans[0].x, y,
2524 len, h);
2525 mask = (uint8_t *)pixman_image_get_data_moz_pixman_image_get_data (r->mask);
2526 x0 = spans[1].x;
2527 } else if (spans[0].coverage == 0x0 &&
2528 x1 - x0 > r->u.composite.run_length) {
2529 pixman_image_composite32_moz_pixman_image_composite32 (r->op, r->src, r->mask, r->u.composite.dst,
2530 x0 + r->u.composite.src_x,
2531 y + r->u.composite.src_y,
2532 0, 0,
2533 x0, y,
2534 x1 - x0, h);
2535 mask = (uint8_t *)pixman_image_get_data_moz_pixman_image_get_data (r->mask);
2536 x0 = spans[1].x;
2537 }else {
2538 memset (mask, spans[0].coverage, --len);
2539 mask += len;
2540 }
2541 }
2542 x1 = spans[1].x;
2543 spans++;
2544 } while (--num_spans > 1);
2545
2546 if (x1 != x0) {
2547 pixman_image_composite32_moz_pixman_image_composite32 (r->op, r->src, r->mask, r->u.composite.dst,
2548 x0 + r->u.composite.src_x,
2549 y + r->u.composite.src_y,
2550 0, 0,
2551 x0, y,
2552 x1 - x0, h);
2553 }
2554
2555 return CAIRO_STATUS_SUCCESS;
2556}
2557
2558static cairo_status_t
2559_inplace_opacity_spans (void *abstract_renderer, int y, int h,
2560 const cairo_half_open_span_t *spans,
2561 unsigned num_spans)
2562{
2563 cairo_image_span_renderer_t *r = abstract_renderer;
2564 uint8_t *mask;
2565 int x0, x1;
2566
2567 if (num_spans == 0)
2568 return CAIRO_STATUS_SUCCESS;
2569
2570 mask = (uint8_t *)pixman_image_get_data_moz_pixman_image_get_data (r->mask);
2571 x1 = x0 = spans[0].x;
2572 do {
2573 int len = spans[1].x - spans[0].x;
2574 uint8_t m = mul8_8(spans[0].coverage, r->bpp);
2575 *mask++ = m;
2576 if (len > 1) {
2577 if (m == 0 &&
2578 x1 - x0 > r->u.composite.run_length) {
2579 pixman_image_composite32_moz_pixman_image_composite32 (r->op, r->src, r->mask, r->u.composite.dst,
2580 x0 + r->u.composite.src_x,
2581 y + r->u.composite.src_y,
2582 0, 0,
2583 x0, y,
2584 x1 - x0, h);
2585 mask = (uint8_t *)pixman_image_get_data_moz_pixman_image_get_data (r->mask);
2586 x0 = spans[1].x;
2587 }else {
2588 memset (mask, m, --len);
2589 mask += len;
2590 }
2591 }
2592 x1 = spans[1].x;
2593 spans++;
2594 } while (--num_spans > 1);
2595
2596 if (x1 != x0) {
2597 pixman_image_composite32_moz_pixman_image_composite32 (r->op, r->src, r->mask, r->u.composite.dst,
2598 x0 + r->u.composite.src_x,
2599 y + r->u.composite.src_y,
2600 0, 0,
2601 x0, y,
2602 x1 - x0, h);
2603 }
2604
2605 return CAIRO_STATUS_SUCCESS;
2606}
2607
2608static cairo_status_t
2609_inplace_src_spans (void *abstract_renderer, int y, int h,
2610 const cairo_half_open_span_t *spans,
2611 unsigned num_spans)
2612{
2613 cairo_image_span_renderer_t *r = abstract_renderer;
2614 uint8_t *m, *base = (uint8_t*)pixman_image_get_data_moz_pixman_image_get_data(r->mask);
2615 int x0;
2616
2617 if (num_spans == 0)
2618 return CAIRO_STATUS_SUCCESS;
2619
2620 x0 = spans[0].x;
2621 m = base;
2622 do {
2623 int len = spans[1].x - spans[0].x;
2624 if (len >= r->u.composite.run_length && spans[0].coverage == 0xff) {
2625 if (spans[0].x != x0) {
2626#if PIXMAN_HAS_OP_LERP
2627 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
2628 r->src, r->mask, r->u.composite.dst,
2629 x0 + r->u.composite.src_x,
2630 y + r->u.composite.src_y,
2631 0, 0,
2632 x0, y,
2633 spans[0].x - x0, h);
2634#else
2635 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
2636 r->mask, NULL((void*)0), r->u.composite.dst,
2637 0, 0,
2638 0, 0,
2639 x0, y,
2640 spans[0].x - x0, h);
2641 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_ADD,
2642 r->src, r->mask, r->u.composite.dst,
2643 x0 + r->u.composite.src_x,
2644 y + r->u.composite.src_y,
2645 0, 0,
2646 x0, y,
2647 spans[0].x - x0, h);
2648#endif
2649 }
2650
2651 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_SRC,
2652 r->src, NULL((void*)0), r->u.composite.dst,
2653 spans[0].x + r->u.composite.src_x,
2654 y + r->u.composite.src_y,
2655 0, 0,
2656 spans[0].x, y,
2657 spans[1].x - spans[0].x, h);
2658
2659 m = base;
2660 x0 = spans[1].x;
2661 } else if (spans[0].coverage == 0x0) {
2662 if (spans[0].x != x0) {
2663#if PIXMAN_HAS_OP_LERP
2664 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
2665 r->src, r->mask, r->u.composite.dst,
2666 x0 + r->u.composite.src_x,
2667 y + r->u.composite.src_y,
2668 0, 0,
2669 x0, y,
2670 spans[0].x - x0, h);
2671#else
2672 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
2673 r->mask, NULL((void*)0), r->u.composite.dst,
2674 0, 0,
2675 0, 0,
2676 x0, y,
2677 spans[0].x - x0, h);
2678 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_ADD,
2679 r->src, r->mask, r->u.composite.dst,
2680 x0 + r->u.composite.src_x,
2681 y + r->u.composite.src_y,
2682 0, 0,
2683 x0, y,
2684 spans[0].x - x0, h);
2685#endif
2686 }
2687
2688 m = base;
2689 x0 = spans[1].x;
2690 } else {
2691 *m++ = spans[0].coverage;
2692 if (len > 1) {
2693 memset (m, spans[0].coverage, --len);
2694 m += len;
2695 }
2696 }
2697 spans++;
2698 } while (--num_spans > 1);
2699
2700 if (spans[0].x != x0) {
2701#if PIXMAN_HAS_OP_LERP
2702 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
2703 r->src, r->mask, r->u.composite.dst,
2704 x0 + r->u.composite.src_x,
2705 y + r->u.composite.src_y,
2706 0, 0,
2707 x0, y,
2708 spans[0].x - x0, h);
2709#else
2710 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
2711 r->mask, NULL((void*)0), r->u.composite.dst,
2712 0, 0,
2713 0, 0,
2714 x0, y,
2715 spans[0].x - x0, h);
2716 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_ADD,
2717 r->src, r->mask, r->u.composite.dst,
2718 x0 + r->u.composite.src_x,
2719 y + r->u.composite.src_y,
2720 0, 0,
2721 x0, y,
2722 spans[0].x - x0, h);
2723#endif
2724 }
2725
2726 return CAIRO_STATUS_SUCCESS;
2727}
2728
2729static cairo_status_t
2730_inplace_src_opacity_spans (void *abstract_renderer, int y, int h,
2731 const cairo_half_open_span_t *spans,
2732 unsigned num_spans)
2733{
2734 cairo_image_span_renderer_t *r = abstract_renderer;
2735 uint8_t *mask;
2736 int x0;
2737
2738 if (num_spans == 0)
2739 return CAIRO_STATUS_SUCCESS;
2740
2741 x0 = spans[0].x;
2742 mask = (uint8_t *)pixman_image_get_data_moz_pixman_image_get_data (r->mask);
2743 do {
2744 int len = spans[1].x - spans[0].x;
2745 uint8_t m = mul8_8(spans[0].coverage, r->bpp);
2746 if (m == 0) {
2747 if (spans[0].x != x0) {
2748#if PIXMAN_HAS_OP_LERP
2749 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
2750 r->src, r->mask, r->u.composite.dst,
2751 x0 + r->u.composite.src_x,
2752 y + r->u.composite.src_y,
2753 0, 0,
2754 x0, y,
2755 spans[0].x - x0, h);
2756#else
2757 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
2758 r->mask, NULL((void*)0), r->u.composite.dst,
2759 0, 0,
2760 0, 0,
2761 x0, y,
2762 spans[0].x - x0, h);
2763 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_ADD,
2764 r->src, r->mask, r->u.composite.dst,
2765 x0 + r->u.composite.src_x,
2766 y + r->u.composite.src_y,
2767 0, 0,
2768 x0, y,
2769 spans[0].x - x0, h);
2770#endif
2771 }
2772
2773 mask = (uint8_t *)pixman_image_get_data_moz_pixman_image_get_data (r->mask);
2774 x0 = spans[1].x;
2775 } else {
2776 *mask++ = m;
2777 if (len > 1) {
2778 memset (mask, m, --len);
2779 mask += len;
2780 }
2781 }
2782 spans++;
2783 } while (--num_spans > 1);
2784
2785 if (spans[0].x != x0) {
2786#if PIXMAN_HAS_OP_LERP
2787 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_LERP_SRC,
2788 r->src, r->mask, r->u.composite.dst,
2789 x0 + r->u.composite.src_x,
2790 y + r->u.composite.src_y,
2791 0, 0,
2792 x0, y,
2793 spans[0].x - x0, h);
2794#else
2795 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE,
2796 r->mask, NULL((void*)0), r->u.composite.dst,
2797 0, 0,
2798 0, 0,
2799 x0, y,
2800 spans[0].x - x0, h);
2801 pixman_image_composite32_moz_pixman_image_composite32 (PIXMAN_OP_ADD,
2802 r->src, r->mask, r->u.composite.dst,
2803 x0 + r->u.composite.src_x,
2804 y + r->u.composite.src_y,
2805 0, 0,
2806 x0, y,
2807 spans[0].x - x0, h);
2808#endif
2809 }
2810
2811 return CAIRO_STATUS_SUCCESS;
2812}
2813
2814static void free_pixels (pixman_image_t *image, void *data)
2815{
2816 free (data);
2817}
2818
2819static cairo_int_status_t
2820inplace_renderer_init (cairo_image_span_renderer_t *r,
2821 const cairo_composite_rectangles_t *composite,
2822 cairo_antialias_t antialias,
2823 cairo_bool_t needs_clip)
2824{
2825 cairo_image_surface_t *dst = (cairo_image_surface_t *)composite->surface;
2826 uint8_t *buf;
2827
2828 if (composite->mask_pattern.base.type != CAIRO_PATTERN_TYPE_SOLID)
2829 return CAIRO_INT_STATUS_UNSUPPORTED;
2830
2831 r->base.render_rows = NULL((void*)0);
2832 r->bpp = composite->mask_pattern.solid.color.alpha_short >> 8;
2833
2834 if (composite->source_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID) {
2835 const cairo_color_t *color;
2836
2837 color = &composite->source_pattern.solid.color;
2838 if (composite->op == CAIRO_OPERATOR_CLEAR)
2839 color = CAIRO_COLOR_TRANSPARENT_cairo_stock_color (CAIRO_STOCK_TRANSPARENT);
2840
2841 if (fill_reduces_to_source (composite->op, color, dst, &r->u.fill.pixel)) {
2842 /* Use plain C for the fill operations as the span length is
2843 * typically small, too small to payback the startup overheads of
2844 * using SSE2 etc.
2845 */
2846 if (r->bpp == 0xff) {
2847 switch (dst->format) {
2848 case CAIRO_FORMAT_A8:
2849 r->base.render_rows = _fill_a8_lerp_opaque_spans;
2850 break;
2851 case CAIRO_FORMAT_RGB24:
2852 case CAIRO_FORMAT_ARGB32:
2853 r->base.render_rows = _fill_xrgb32_lerp_opaque_spans;
2854 break;
2855 case CAIRO_FORMAT_A1:
2856 case CAIRO_FORMAT_RGB16_565:
2857 case CAIRO_FORMAT_RGB30:
2858 case CAIRO_FORMAT_RGB96F:
2859 case CAIRO_FORMAT_RGBA128F:
2860 case CAIRO_FORMAT_INVALID:
2861 default: break;
2862 }
2863 } else {
2864 switch (dst->format) {
2865 case CAIRO_FORMAT_A8:
2866 r->base.render_rows = _fill_a8_lerp_spans;
2867 break;
2868 case CAIRO_FORMAT_RGB24:
2869 case CAIRO_FORMAT_ARGB32:
2870 r->base.render_rows = _fill_xrgb32_lerp_spans;
2871 break;
2872 case CAIRO_FORMAT_A1:
2873 case CAIRO_FORMAT_RGB16_565:
2874 case CAIRO_FORMAT_RGB30:
2875 case CAIRO_FORMAT_RGB96F:
2876 case CAIRO_FORMAT_RGBA128F:
2877 case CAIRO_FORMAT_INVALID:
2878 default: break;
2879 }
2880 }
2881 r->u.fill.data = dst->data;
2882 r->u.fill.stride = dst->stride;
2883 }
2884 } else if ((dst->format == CAIRO_FORMAT_ARGB32 || dst->format == CAIRO_FORMAT_RGB24) &&
2885 (composite->op == CAIRO_OPERATOR_SOURCE ||
2886 (composite->op == CAIRO_OPERATOR_OVER &&
2887 (dst->base.is_clear || (dst->base.content & CAIRO_CONTENT_ALPHA) == 0))) &&
2888 composite->source_pattern.base.type == CAIRO_PATTERN_TYPE_SURFACE &&
2889 composite->source_pattern.surface.surface->backend->type == CAIRO_SURFACE_TYPE_IMAGE &&
2890 to_image_surface(composite->source_pattern.surface.surface)((cairo_image_surface_t *)(composite->source_pattern.surface
.surface))
->format == dst->format)
2891 {
2892 cairo_image_surface_t *src =
2893 to_image_surface(composite->source_pattern.surface.surface)((cairo_image_surface_t *)(composite->source_pattern.surface
.surface))
;
2894 int tx, ty;
2895
2896 if (_cairo_matrix_is_integer_translation(&composite->source_pattern.base.matrix,
2897 &tx, &ty) &&
2898 composite->bounded.x + tx >= 0 &&
2899 composite->bounded.y + ty >= 0 &&
2900 composite->bounded.x + composite->bounded.width + tx <= src->width &&
2901 composite->bounded.y + composite->bounded.height + ty <= src->height) {
2902
2903 assert(PIXMAN_FORMAT_BPP(dst->pixman_format) == 32)((void) sizeof (__assert_single_arg ((((dst->pixman_format
>> (24)) & ((1 << (8)) - 1)) << ((dst->
pixman_format >> 22) & 3)) == 32)), __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"
, "./../../../../../gfx/cairo/cairo/src/cairo-image-compositor.c"
, 2903, __extension__ __PRETTY_FUNCTION__); }))
;
2904 r->u.blit.stride = dst->stride;
2905 r->u.blit.data = dst->data;
2906 r->u.blit.src_stride = src->stride;
2907 r->u.blit.src_data = src->data + src->stride * ty + tx * 4;
2908 r->base.render_rows = _blit_xrgb32_lerp_spans;
2909 }
2910 }
2911 if (r->base.render_rows == NULL((void*)0)) {
2912 const cairo_pattern_t *src = &composite->source_pattern.base;
2913 unsigned int width;
2914
2915 if (composite->is_bounded == 0)
2916 return CAIRO_INT_STATUS_UNSUPPORTED;
2917
2918 r->base.render_rows = r->bpp == 0xff ? _inplace_spans : _inplace_opacity_spans;
2919 width = (composite->bounded.width + 3) & ~3;
2920
2921 r->u.composite.run_length = 8;
2922 if (src->type == CAIRO_PATTERN_TYPE_LINEAR ||
2923 src->type == CAIRO_PATTERN_TYPE_RADIAL)
2924 r->u.composite.run_length = 256;
2925 if (dst->base.is_clear &&
2926 (composite->op == CAIRO_OPERATOR_SOURCE ||
2927 composite->op == CAIRO_OPERATOR_OVER ||
2928 composite->op == CAIRO_OPERATOR_ADD)) {
2929 r->op = PIXMAN_OP_SRC;
2930 } else if (composite->op == CAIRO_OPERATOR_SOURCE) {
2931 r->base.render_rows = r->bpp == 0xff ? _inplace_src_spans : _inplace_src_opacity_spans;
2932 r->u.composite.mask_y = r->composite->unbounded.y;
2933 width = (composite->unbounded.width + 3) & ~3;
2934 } else if (composite->op == CAIRO_OPERATOR_CLEAR) {
2935 r->op = PIXMAN_OP_OUT_REVERSE;
2936 src = NULL((void*)0);
2937 } else {
2938 r->op = _pixman_operator (composite->op);
2939 }
2940
2941 r->src = _pixman_image_for_pattern (dst, src, FALSE0,
2942 &composite->bounded,
2943 &composite->source_sample_area,
2944 &r->u.composite.src_x, &r->u.composite.src_y);
2945 if (unlikely (r->src == NULL)(__builtin_expect (!!(r->src == ((void*)0)), 0)))
2946 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2947
2948 /* Create an effectively unbounded mask by repeating the single line */
2949 buf = r->_buf;
2950 if (width > SZ_BUF(int)(sizeof (cairo_abstract_span_renderer_t) - sizeof (cairo_image_span_renderer_t
))
) {
2951 buf = _cairo_malloc (width)((width) != 0 ? malloc(width) : ((void*)0));
2952 if (unlikely (buf == NULL)(__builtin_expect (!!(buf == ((void*)0)), 0))) {
2953 pixman_image_unref_moz_pixman_image_unref (r->src);
2954 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2955 }
2956 }
2957 r->mask = pixman_image_create_bits_moz_pixman_image_create_bits (PIXMAN_a8,
2958 width, composite->unbounded.height,
2959 (uint32_t *)buf, 0);
2960 if (unlikely (r->mask == NULL)(__builtin_expect (!!(r->mask == ((void*)0)), 0))) {
2961 pixman_image_unref_moz_pixman_image_unref (r->src);
2962 if (buf != r->_buf)
2963 free (buf);
2964 return _cairo_error(CAIRO_STATUS_NO_MEMORY);
2965 }
2966
2967 if (buf != r->_buf)
2968 pixman_image_set_destroy_function_moz_pixman_image_set_destroy_function (r->mask, free_pixels, buf);
2969
2970 r->u.composite.dst = dst->pixman_image;
2971 }
2972
2973 return CAIRO_INT_STATUS_SUCCESS;
2974}
2975
2976static cairo_int_status_t
2977span_renderer_init (cairo_abstract_span_renderer_t *_r,
2978 const cairo_composite_rectangles_t *composite,
2979 cairo_antialias_t antialias,
2980 cairo_bool_t needs_clip)
2981{
2982 cairo_image_span_renderer_t *r = (cairo_image_span_renderer_t *)_r;
2983 cairo_image_surface_t *dst = (cairo_image_surface_t *)composite->surface;
2984 const cairo_pattern_t *source = &composite->source_pattern.base;
2985 cairo_operator_t op = composite->op;
2986 cairo_int_status_t status;
2987
2988 TRACE ((stderr, "%s: antialias=%d, needs_clip=%d\n", __FUNCTION__,
2989 antialias, needs_clip));
2990
2991 if (needs_clip)
2992 return CAIRO_INT_STATUS_UNSUPPORTED;
2993
2994 r->composite = composite;
2995 r->mask = NULL((void*)0);
2996 r->src = NULL((void*)0);
2997 r->base.finish = NULL((void*)0);
2998
2999 status = mono_renderer_init (r, composite, antialias, needs_clip);
3000 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3001 return status;
3002
3003 status = inplace_renderer_init (r, composite, antialias, needs_clip);
3004 if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3005 return status;
3006
3007 r->bpp = 0;
3008
3009 if (op == CAIRO_OPERATOR_CLEAR) {
3010#if PIXMAN_HAS_OP_LERP
3011 op = PIXMAN_OP_LERP_CLEAR;
3012#else
3013 source = &_cairo_pattern_white.base;
3014 op = PIXMAN_OP_OUT_REVERSE;
3015#endif
3016 } else if (dst->base.is_clear &&
3017 (op == CAIRO_OPERATOR_SOURCE ||
3018 op == CAIRO_OPERATOR_OVER ||
3019 op == CAIRO_OPERATOR_ADD)) {
3020 op = PIXMAN_OP_SRC;
3021 } else if (op == CAIRO_OPERATOR_SOURCE) {
3022 if (_cairo_pattern_is_opaque (&composite->source_pattern.base,
3023 &composite->source_sample_area))
3024 {
3025 op = PIXMAN_OP_OVER;
3026 }
3027 else
3028 {
3029#if PIXMAN_HAS_OP_LERP
3030 op = PIXMAN_OP_LERP_SRC;
3031#else
3032 return CAIRO_INT_STATUS_UNSUPPORTED;
3033#endif
3034 }
3035 } else {
3036 op = _pixman_operator (op);
3037 }
3038 r->op = op;
3039
3040 r->src = _pixman_image_for_pattern (dst, source, FALSE0,
3041 &composite->unbounded,
3042 &composite->source_sample_area,
3043 &r->u.mask.src_x, &r->u.mask.src_y);
3044 if (unlikely (r->src == NULL)(__builtin_expect (!!(r->src == ((void*)0)), 0)))
3045 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3046
3047 r->opacity = 1.0;
3048 if (composite->mask_pattern.base.type == CAIRO_PATTERN_TYPE_SOLID) {
3049 r->opacity = composite->mask_pattern.solid.color.alpha;
3050 } else {
3051 pixman_image_t *mask;
3052 int mask_x, mask_y;
3053
3054 mask = _pixman_image_for_pattern (dst,
3055 &composite->mask_pattern.base,
3056 TRUE1,
3057 &composite->unbounded,
3058 &composite->mask_sample_area,
3059 &mask_x, &mask_y);
3060 if (unlikely (mask == NULL)(__builtin_expect (!!(mask == ((void*)0)), 0)))
3061 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3062
3063 /* XXX Component-alpha? */
3064 if ((dst->base.content & CAIRO_CONTENT_COLOR) == 0 &&
3065 _cairo_pattern_is_opaque (source, &composite->source_sample_area))
3066 {
3067 pixman_image_unref_moz_pixman_image_unref (r->src);
3068 r->src = mask;
3069 r->u.mask.src_x = mask_x;
3070 r->u.mask.src_y = mask_y;
3071 mask = NULL((void*)0);
3072 }
3073
3074 if (mask) {
3075 pixman_image_unref_moz_pixman_image_unref (mask);
3076 return CAIRO_INT_STATUS_UNSUPPORTED;
3077 }
3078 }
3079
3080 r->u.mask.extents = composite->unbounded;
3081 r->u.mask.stride = (r->u.mask.extents.width + 3) & ~3;
3082 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
))
) {
3083 r->mask = pixman_image_create_bits_moz_pixman_image_create_bits (PIXMAN_a8,
3084 r->u.mask.extents.width,
3085 r->u.mask.extents.height,
3086 NULL((void*)0), 0);
3087
3088 r->base.render_rows = _cairo_image_spans;
3089 r->base.finish = NULL((void*)0);
3090 } else {
3091 r->mask = pixman_image_create_bits_moz_pixman_image_create_bits (PIXMAN_a8,
3092 r->u.mask.extents.width,
3093 r->u.mask.extents.height,
3094 (uint32_t *)r->_buf, r->u.mask.stride);
3095
3096 r->base.render_rows = _cairo_image_spans_and_zero;
3097 r->base.finish = _cairo_image_finish_spans_and_zero;
3098 }
3099 if (unlikely (r->mask == NULL)(__builtin_expect (!!(r->mask == ((void*)0)), 0)))
3100 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3101
3102 r->u.mask.data = (uint8_t *) pixman_image_get_data_moz_pixman_image_get_data (r->mask);
3103 r->u.mask.stride = pixman_image_get_stride_moz_pixman_image_get_stride (r->mask);
3104
3105 r->u.mask.extents.height += r->u.mask.extents.y;
3106 return CAIRO_STATUS_SUCCESS;
3107}
3108
3109static void
3110span_renderer_fini (cairo_abstract_span_renderer_t *_r,
3111 cairo_int_status_t status)
3112{
3113 cairo_image_span_renderer_t *r = (cairo_image_span_renderer_t *) _r;
3114
3115 TRACE ((stderr, "%s\n", __FUNCTION__));
3116
3117 if (likely (status == CAIRO_INT_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS), 1)
)
) {
3118 if (r->base.finish)
3119 r->base.finish (r);
3120 }
3121 if (likely (status == CAIRO_INT_STATUS_SUCCESS && r->bpp == 0)(__builtin_expect (!!(status == CAIRO_INT_STATUS_SUCCESS &&
r->bpp == 0), 1))
) {
3122 const cairo_composite_rectangles_t *composite = r->composite;
3123
3124 pixman_image_composite32_moz_pixman_image_composite32 (r->op, r->src, r->mask,
3125 to_pixman_image (composite->surface),
3126 composite->unbounded.x + r->u.mask.src_x,
3127 composite->unbounded.y + r->u.mask.src_y,
3128 0, 0,
3129 composite->unbounded.x,
3130 composite->unbounded.y,
3131 composite->unbounded.width,
3132 composite->unbounded.height);
3133 }
3134
3135 if (r->src)
3136 pixman_image_unref_moz_pixman_image_unref (r->src);
3137 if (r->mask)
3138 pixman_image_unref_moz_pixman_image_unref (r->mask);
3139}
3140#endif
3141
3142const cairo_compositor_t *
3143_cairo_image_spans_compositor_get (void)
3144{
3145 static cairo_atomic_once_t once = CAIRO_ATOMIC_ONCE_INIT(0);
3146 static cairo_spans_compositor_t spans;
3147 static cairo_compositor_t shape;
3148
3149 if (_cairo_atomic_init_once_enter(&once)) {
3150 _cairo_shape_mask_compositor_init (&shape,
3151 _cairo_image_traps_compositor_get());
3152 shape.glyphs = NULL((void*)0);
3153
3154 _cairo_spans_compositor_init (&spans, &shape);
3155
3156 spans.flags = 0;
3157#if PIXMAN_HAS_OP_LERP
3158 spans.flags |= CAIRO_SPANS_COMPOSITOR_HAS_LERP0x1;
3159#endif
3160
3161 //spans.acquire = acquire;
3162 //spans.release = release;
3163 spans.fill_boxes = fill_boxes;
3164 spans.draw_image_boxes = draw_image_boxes;
3165 //spans.copy_boxes = copy_boxes;
3166 spans.pattern_to_surface = _cairo_image_source_create_for_pattern;
3167 //spans.check_composite_boxes = check_composite_boxes;
3168 spans.composite_boxes = composite_boxes;
3169 //spans.check_span_renderer = check_span_renderer;
3170 spans.renderer_init = span_renderer_init;
3171 spans.renderer_fini = span_renderer_fini;
3172
3173 _cairo_atomic_init_once_leave(&once);
3174 }
3175
3176 return &spans.base;
3177}