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