beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-image-source.c
blob950053db2c1ebf594c911804380ba0c6c78fadb3
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
4 * Copyright © 2003 University of Southern California
5 * Copyright © 2009,2010,2011 Intel Corporation
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.
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
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/
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.
30 * The Original Code is the cairo graphics library.
32 * The Initial Developer of the Original Code is University of Southern
33 * California.
35 * Contributor(s):
36 * Carl D. Worth <cworth@cworth.org>
37 * Chris Wilson <chris@chris-wilson.co.uk>
40 /* The purpose of this file/surface is to simply translate a pattern
41 * to a pixman_image_t and thence to feed it back to the general
42 * compositor interface.
45 #include "cairoint.h"
47 #include "cairo-image-surface-private.h"
49 #include "cairo-compositor-private.h"
50 #include "cairo-error-private.h"
51 #include "cairo-pattern-inline.h"
52 #include "cairo-paginated-private.h"
53 #include "cairo-recording-surface-private.h"
54 #include "cairo-surface-observer-private.h"
55 #include "cairo-surface-snapshot-inline.h"
56 #include "cairo-surface-subsurface-private.h"
58 #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
60 #if CAIRO_NO_MUTEX
61 #define PIXMAN_HAS_ATOMIC_OPS 1
62 #endif
64 #if PIXMAN_HAS_ATOMIC_OPS
65 static pixman_image_t *__pixman_transparent_image;
66 static pixman_image_t *__pixman_black_image;
67 static pixman_image_t *__pixman_white_image;
69 static pixman_image_t *
70 _pixman_transparent_image (void)
72 pixman_image_t *image;
74 TRACE ((stderr, "%s\n", __FUNCTION__));
76 image = __pixman_transparent_image;
77 if (unlikely (image == NULL)) {
78 pixman_color_t color;
80 color.red = 0x00;
81 color.green = 0x00;
82 color.blue = 0x00;
83 color.alpha = 0x00;
85 image = pixman_image_create_solid_fill (&color);
86 if (unlikely (image == NULL))
87 return NULL;
89 if (_cairo_atomic_ptr_cmpxchg (&__pixman_transparent_image,
90 NULL, image))
92 pixman_image_ref (image);
94 } else {
95 pixman_image_ref (image);
98 return image;
101 static pixman_image_t *
102 _pixman_black_image (void)
104 pixman_image_t *image;
106 TRACE ((stderr, "%s\n", __FUNCTION__));
108 image = __pixman_black_image;
109 if (unlikely (image == NULL)) {
110 pixman_color_t color;
112 color.red = 0x00;
113 color.green = 0x00;
114 color.blue = 0x00;
115 color.alpha = 0xffff;
117 image = pixman_image_create_solid_fill (&color);
118 if (unlikely (image == NULL))
119 return NULL;
121 if (_cairo_atomic_ptr_cmpxchg (&__pixman_black_image,
122 NULL, image))
124 pixman_image_ref (image);
126 } else {
127 pixman_image_ref (image);
130 return image;
133 static pixman_image_t *
134 _pixman_white_image (void)
136 pixman_image_t *image;
138 TRACE ((stderr, "%s\n", __FUNCTION__));
140 image = __pixman_white_image;
141 if (unlikely (image == NULL)) {
142 pixman_color_t color;
144 color.red = 0xffff;
145 color.green = 0xffff;
146 color.blue = 0xffff;
147 color.alpha = 0xffff;
149 image = pixman_image_create_solid_fill (&color);
150 if (unlikely (image == NULL))
151 return NULL;
153 if (_cairo_atomic_ptr_cmpxchg (&__pixman_white_image,
154 NULL, image))
156 pixman_image_ref (image);
158 } else {
159 pixman_image_ref (image);
162 return image;
165 static uint32_t
166 hars_petruska_f54_1_random (void)
168 #define rol(x,k) ((x << k) | (x >> (32-k)))
169 static uint32_t x;
170 return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
171 #undef rol
174 static struct {
175 cairo_color_t color;
176 pixman_image_t *image;
177 } cache[16];
178 static int n_cached;
180 #else /* !PIXMAN_HAS_ATOMIC_OPS */
181 static pixman_image_t *
182 _pixman_transparent_image (void)
184 TRACE ((stderr, "%s\n", __FUNCTION__));
185 return _pixman_image_for_color (CAIRO_COLOR_TRANSPARENT);
188 static pixman_image_t *
189 _pixman_black_image (void)
191 TRACE ((stderr, "%s\n", __FUNCTION__));
192 return _pixman_image_for_color (CAIRO_COLOR_BLACK);
195 static pixman_image_t *
196 _pixman_white_image (void)
198 TRACE ((stderr, "%s\n", __FUNCTION__));
199 return _pixman_image_for_color (CAIRO_COLOR_WHITE);
201 #endif /* !PIXMAN_HAS_ATOMIC_OPS */
204 pixman_image_t *
205 _pixman_image_for_color (const cairo_color_t *cairo_color)
207 pixman_color_t color;
208 pixman_image_t *image;
210 #if PIXMAN_HAS_ATOMIC_OPS
211 int i;
213 if (CAIRO_COLOR_IS_CLEAR (cairo_color))
214 return _pixman_transparent_image ();
216 if (CAIRO_COLOR_IS_OPAQUE (cairo_color)) {
217 if (cairo_color->red_short <= 0x00ff &&
218 cairo_color->green_short <= 0x00ff &&
219 cairo_color->blue_short <= 0x00ff)
221 return _pixman_black_image ();
224 if (cairo_color->red_short >= 0xff00 &&
225 cairo_color->green_short >= 0xff00 &&
226 cairo_color->blue_short >= 0xff00)
228 return _pixman_white_image ();
232 CAIRO_MUTEX_LOCK (_cairo_image_solid_cache_mutex);
233 for (i = 0; i < n_cached; i++) {
234 if (_cairo_color_equal (&cache[i].color, cairo_color)) {
235 image = pixman_image_ref (cache[i].image);
236 goto UNLOCK;
239 #endif
241 color.red = cairo_color->red_short;
242 color.green = cairo_color->green_short;
243 color.blue = cairo_color->blue_short;
244 color.alpha = cairo_color->alpha_short;
246 image = pixman_image_create_solid_fill (&color);
247 #if PIXMAN_HAS_ATOMIC_OPS
248 if (image == NULL)
249 goto UNLOCK;
251 if (n_cached < ARRAY_LENGTH (cache)) {
252 i = n_cached++;
253 } else {
254 i = hars_petruska_f54_1_random () % ARRAY_LENGTH (cache);
255 pixman_image_unref (cache[i].image);
257 cache[i].image = pixman_image_ref (image);
258 cache[i].color = *cairo_color;
260 UNLOCK:
261 CAIRO_MUTEX_UNLOCK (_cairo_image_solid_cache_mutex);
262 #endif
263 return image;
267 void
268 _cairo_image_reset_static_data (void)
270 #if PIXMAN_HAS_ATOMIC_OPS
271 while (n_cached)
272 pixman_image_unref (cache[--n_cached].image);
274 if (__pixman_transparent_image) {
275 pixman_image_unref (__pixman_transparent_image);
276 __pixman_transparent_image = NULL;
279 if (__pixman_black_image) {
280 pixman_image_unref (__pixman_black_image);
281 __pixman_black_image = NULL;
284 if (__pixman_white_image) {
285 pixman_image_unref (__pixman_white_image);
286 __pixman_white_image = NULL;
288 #endif
291 static pixman_image_t *
292 _pixman_image_for_gradient (const cairo_gradient_pattern_t *pattern,
293 const cairo_rectangle_int_t *extents,
294 int *ix, int *iy)
296 pixman_image_t *pixman_image;
297 pixman_gradient_stop_t pixman_stops_static[2];
298 pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
299 pixman_transform_t pixman_transform;
300 cairo_matrix_t matrix;
301 cairo_circle_double_t extremes[2];
302 pixman_point_fixed_t p1, p2;
303 unsigned int i;
304 cairo_int_status_t status;
306 TRACE ((stderr, "%s\n", __FUNCTION__));
308 if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
309 pixman_stops = _cairo_malloc_ab (pattern->n_stops,
310 sizeof(pixman_gradient_stop_t));
311 if (unlikely (pixman_stops == NULL))
312 return NULL;
315 for (i = 0; i < pattern->n_stops; i++) {
316 pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
317 pixman_stops[i].color.red = pattern->stops[i].color.red_short;
318 pixman_stops[i].color.green = pattern->stops[i].color.green_short;
319 pixman_stops[i].color.blue = pattern->stops[i].color.blue_short;
320 pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
323 _cairo_gradient_pattern_fit_to_range (pattern, PIXMAN_MAX_INT >> 1, &matrix, extremes);
325 p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
326 p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
327 p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
328 p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
330 if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
331 pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
332 pixman_stops,
333 pattern->n_stops);
334 } else {
335 pixman_fixed_t r1, r2;
337 r1 = _cairo_fixed_16_16_from_double (extremes[0].radius);
338 r2 = _cairo_fixed_16_16_from_double (extremes[1].radius);
340 pixman_image = pixman_image_create_radial_gradient (&p1, &p2, r1, r2,
341 pixman_stops,
342 pattern->n_stops);
345 if (pixman_stops != pixman_stops_static)
346 free (pixman_stops);
348 if (unlikely (pixman_image == NULL))
349 return NULL;
351 *ix = *iy = 0;
352 status = _cairo_matrix_to_pixman_matrix_offset (&matrix, pattern->base.filter,
353 extents->x + extents->width/2.,
354 extents->y + extents->height/2.,
355 &pixman_transform, ix, iy);
356 if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
357 if (unlikely (status != CAIRO_INT_STATUS_SUCCESS) ||
358 ! pixman_image_set_transform (pixman_image, &pixman_transform))
360 pixman_image_unref (pixman_image);
361 return NULL;
366 pixman_repeat_t pixman_repeat;
368 switch (pattern->base.extend) {
369 default:
370 case CAIRO_EXTEND_NONE:
371 pixman_repeat = PIXMAN_REPEAT_NONE;
372 break;
373 case CAIRO_EXTEND_REPEAT:
374 pixman_repeat = PIXMAN_REPEAT_NORMAL;
375 break;
376 case CAIRO_EXTEND_REFLECT:
377 pixman_repeat = PIXMAN_REPEAT_REFLECT;
378 break;
379 case CAIRO_EXTEND_PAD:
380 pixman_repeat = PIXMAN_REPEAT_PAD;
381 break;
384 pixman_image_set_repeat (pixman_image, pixman_repeat);
387 return pixman_image;
390 static pixman_image_t *
391 _pixman_image_for_mesh (const cairo_mesh_pattern_t *pattern,
392 const cairo_rectangle_int_t *extents,
393 int *tx, int *ty)
395 pixman_image_t *image;
396 int width, height;
398 TRACE ((stderr, "%s\n", __FUNCTION__));
400 *tx = -extents->x;
401 *ty = -extents->y;
402 width = extents->width;
403 height = extents->height;
405 image = pixman_image_create_bits (PIXMAN_a8r8g8b8, width, height, NULL, 0);
406 if (unlikely (image == NULL))
407 return NULL;
409 _cairo_mesh_pattern_rasterize (pattern,
410 pixman_image_get_data (image),
411 width, height,
412 pixman_image_get_stride (image),
413 *tx, *ty);
414 return image;
417 struct acquire_source_cleanup {
418 cairo_surface_t *surface;
419 cairo_image_surface_t *image;
420 void *image_extra;
423 static void
424 _acquire_source_cleanup (pixman_image_t *pixman_image,
425 void *closure)
427 struct acquire_source_cleanup *data = closure;
429 _cairo_surface_release_source_image (data->surface,
430 data->image,
431 data->image_extra);
432 free (data);
435 static void
436 _defer_free_cleanup (pixman_image_t *pixman_image,
437 void *closure)
439 cairo_surface_destroy (closure);
442 static uint16_t
443 expand_channel (uint16_t v, uint32_t bits)
445 int offset = 16 - bits;
446 while (offset > 0) {
447 v |= v >> bits;
448 offset -= bits;
449 bits += bits;
451 return v;
454 static pixman_image_t *
455 _pixel_to_solid (cairo_image_surface_t *image, int x, int y)
457 uint32_t pixel;
458 pixman_color_t color;
460 TRACE ((stderr, "%s\n", __FUNCTION__));
462 switch (image->format) {
463 default:
464 case CAIRO_FORMAT_INVALID:
465 ASSERT_NOT_REACHED;
466 return NULL;
468 case CAIRO_FORMAT_A1:
469 pixel = *(uint8_t *) (image->data + y * image->stride + x/8);
470 return pixel & (1 << (x&7)) ? _pixman_black_image () : _pixman_transparent_image ();
472 case CAIRO_FORMAT_A8:
473 color.alpha = *(uint8_t *) (image->data + y * image->stride + x);
474 color.alpha |= color.alpha << 8;
475 if (color.alpha == 0)
476 return _pixman_transparent_image ();
477 if (color.alpha == 0xffff)
478 return _pixman_black_image ();
480 color.red = color.green = color.blue = 0;
481 return pixman_image_create_solid_fill (&color);
483 case CAIRO_FORMAT_RGB16_565:
484 pixel = *(uint16_t *) (image->data + y * image->stride + 2 * x);
485 if (pixel == 0)
486 return _pixman_black_image ();
487 if (pixel == 0xffff)
488 return _pixman_white_image ();
490 color.alpha = 0xffff;
491 color.red = expand_channel ((pixel >> 11 & 0x1f) << 11, 5);
492 color.green = expand_channel ((pixel >> 5 & 0x3f) << 10, 6);
493 color.blue = expand_channel ((pixel & 0x1f) << 11, 5);
494 return pixman_image_create_solid_fill (&color);
496 case CAIRO_FORMAT_RGB30:
497 pixel = *(uint32_t *) (image->data + y * image->stride + 4 * x);
498 pixel &= 0x3fffffff; /* ignore alpha bits */
499 if (pixel == 0)
500 return _pixman_black_image ();
501 if (pixel == 0x3fffffff)
502 return _pixman_white_image ();
504 /* convert 10bpc to 16bpc */
505 color.alpha = 0xffff;
506 color.red = expand_channel((pixel >> 20) & 0x3fff, 10);
507 color.green = expand_channel((pixel >> 10) & 0x3fff, 10);
508 color.blue = expand_channel(pixel & 0x3fff, 10);
509 return pixman_image_create_solid_fill (&color);
511 case CAIRO_FORMAT_ARGB32:
512 case CAIRO_FORMAT_RGB24:
513 pixel = *(uint32_t *) (image->data + y * image->stride + 4 * x);
514 color.alpha = image->format == CAIRO_FORMAT_ARGB32 ? (pixel >> 24) | (pixel >> 16 & 0xff00) : 0xffff;
515 if (color.alpha == 0)
516 return _pixman_transparent_image ();
517 if (pixel == 0xffffffff)
518 return _pixman_white_image ();
519 if (color.alpha == 0xffff && (pixel & 0xffffff) == 0)
520 return _pixman_black_image ();
522 color.red = (pixel >> 16 & 0xff) | (pixel >> 8 & 0xff00);
523 color.green = (pixel >> 8 & 0xff) | (pixel & 0xff00);
524 color.blue = (pixel & 0xff) | (pixel << 8 & 0xff00);
525 return pixman_image_create_solid_fill (&color);
529 /* ========================================================================== */
531 /* Index into filter table */
532 typedef enum
534 KERNEL_IMPULSE,
535 KERNEL_BOX,
536 KERNEL_LINEAR,
537 KERNEL_MITCHELL,
538 KERNEL_NOTCH,
539 KERNEL_CATMULL_ROM,
540 KERNEL_LANCZOS3,
541 KERNEL_LANCZOS3_STRETCHED,
542 KERNEL_TENT
543 } kernel_t;
545 /* Produce contribution of a filter of size r for pixel centered on x.
546 For a typical low-pass function this evaluates the function at x/r.
547 If the frequency is higher than 1/2, such as when r is less than 1,
548 this may need to integrate several samples, see cubic for examples.
550 typedef double (* kernel_func_t) (double x, double r);
552 /* Return maximum number of pixels that will be non-zero. Except for
553 impluse this is the maximum of 2 and the width of the non-zero part
554 of the filter rounded up to the next integer.
556 typedef int (* kernel_width_func_t) (double r);
558 /* Table of filters */
559 typedef struct
561 kernel_t kernel;
562 kernel_func_t func;
563 kernel_width_func_t width;
564 } filter_info_t;
566 /* PIXMAN_KERNEL_IMPULSE: Returns pixel nearest the center. This
567 matches PIXMAN_FILTER_NEAREST. This is useful if you wish to
568 combine the result of nearest in one direction with another filter
569 in the other.
572 static double
573 impulse_kernel (double x, double r)
575 return 1;
578 static int
579 impulse_width (double r)
581 return 1;
584 /* PIXMAN_KERNEL_BOX: Intersection of a box of width r with square
585 pixels. This is the smallest possible filter such that the output
586 image contains an equal contribution from all the input
587 pixels. Lots of software uses this. The function is a trapazoid of
588 width r+1, not a box.
590 When r == 1.0, PIXMAN_KERNEL_BOX, PIXMAN_KERNEL_LINEAR, and
591 PIXMAN_KERNEL_TENT all produce the same filter, allowing
592 them to be exchanged at this point.
595 static double
596 box_kernel (double x, double r)
598 return MAX (0.0, MIN (MIN (r, 1.0),
599 MIN ((r + 1) / 2 - x, (r + 1) / 2 + x)));
602 static int
603 box_width (double r)
605 return r < 1.0 ? 2 : ceil(r + 1);
608 /* PIXMAN_KERNEL_LINEAR: Weighted sum of the two pixels nearest the
609 center, or a triangle of width 2. This matches
610 PIXMAN_FILTER_BILINEAR. This is useful if you wish to combine the
611 result of bilinear in one direction with another filter in the
612 other. This is not a good filter if r > 1. You may actually want
613 PIXMAN_FILTER_TENT.
615 When r == 1.0, PIXMAN_KERNEL_BOX, PIXMAN_KERNEL_LINEAR, and
616 PIXMAN_KERNEL_TENT all produce the same filter, allowing
617 them to be exchanged at this point.
620 static double
621 linear_kernel (double x, double r)
623 return MAX (1.0 - fabs(x), 0.0);
626 static int
627 linear_width (double r)
629 return 2;
632 /* Cubic functions described in the Mitchell-Netravali paper.
633 http://mentallandscape.com/Papers_siggraph88.pdf. This describes
634 all possible cubic functions that can be used for sampling.
637 static double
638 general_cubic (double x, double r, double B, double C)
640 double ax;
641 if (r < 1.0)
642 return
643 general_cubic(x * 2 - .5, r * 2, B, C) +
644 general_cubic(x * 2 + .5, r * 2, B, C);
646 ax = fabs (x / r);
648 if (ax < 1)
650 return (((12 - 9 * B - 6 * C) * ax +
651 (-18 + 12 * B + 6 * C)) * ax * ax +
652 (6 - 2 * B)) / 6;
654 else if (ax < 2)
656 return ((((-B - 6 * C) * ax +
657 (6 * B + 30 * C)) * ax +
658 (-12 * B - 48 * C)) * ax +
659 (8 * B + 24 * C)) / 6;
661 else
663 return 0.0;
667 static int
668 cubic_width (double r)
670 return MAX (2, ceil (r * 4));
673 /* PIXMAN_KERNEL_CATMULL_ROM: Catmull-Rom interpolation. Often called
674 "cubic interpolation", "b-spline", or just "cubic" by other
675 software. This filter has negative values so it can produce ringing
676 and output pixels outside the range of input pixels. This is very
677 close to lanczos2 so there is no reason to supply that as well.
680 static double
681 cubic_kernel (double x, double r)
683 return general_cubic (x, r, 0.0, 0.5);
686 /* PIXMAN_KERNEL_MITCHELL: Cubic recommended by the Mitchell-Netravali
687 paper. This has negative values and because the values at +/-1 are
688 not zero it does not interpolate the pixels, meaning it will change
689 an image even if there is no translation.
692 static double
693 mitchell_kernel (double x, double r)
695 return general_cubic (x, r, 1/3.0, 1/3.0);
698 /* PIXMAN_KERNEL_NOTCH: Cubic recommended by the Mitchell-Netravali
699 paper to remove postaliasing artifacts. This does not remove
700 aliasing already present in the source image, though it may appear
701 to due to it's excessive blurriness. In any case this is more
702 useful than gaussian for image reconstruction.
705 static double
706 notch_kernel (double x, double r)
708 return general_cubic (x, r, 1.5, -0.25);
711 /* PIXMAN_KERNEL_LANCZOS3: lanczos windowed sinc function from -3 to
712 +3. Very popular with high-end software though I think any
713 advantage over cubics is hidden by quantization and programming
714 mistakes. You will see LANCZOS5 or even 7 sometimes.
717 static double
718 sinc (double x)
720 return x ? sin (M_PI * x) / (M_PI * x) : 1.0;
723 static double
724 lanczos (double x, double n)
726 return fabs (x) < n ? sinc (x) * sinc (x * (1.0 / n)) : 0.0;
729 static double
730 lanczos3_kernel (double x, double r)
732 if (r < 1.0)
733 return
734 lanczos3_kernel (x * 2 - .5, r * 2) +
735 lanczos3_kernel (x * 2 + .5, r * 2);
736 else
737 return lanczos (x / r, 3.0);
740 static int
741 lanczos3_width (double r)
743 return MAX (2, ceil (r * 6));
746 /* PIXMAN_KERNEL_LANCZOS3_STRETCHED - The LANCZOS3 kernel widened by
747 4/3. Recommended by Jim Blinn
748 http://graphics.cs.cmu.edu/nsp/course/15-462/Fall07/462/papers/jaggy.pdf
751 static double
752 nice_kernel (double x, double r)
754 return lanczos3_kernel (x, r * (4.0/3));
757 static int
758 nice_width (double r)
760 return MAX (2.0, ceil (r * 8));
763 /* PIXMAN_KERNEL_TENT: Triangle of width 2r. Lots of software uses
764 this as a "better" filter, twice the size of a box but smaller than
765 a cubic.
767 When r == 1.0, PIXMAN_KERNEL_BOX, PIXMAN_KERNEL_LINEAR, and
768 PIXMAN_KERNEL_TENT all produce the same filter, allowing
769 them to be exchanged at this point.
772 static double
773 tent_kernel (double x, double r)
775 if (r < 1.0)
776 return box_kernel(x, r);
777 else
778 return MAX (1.0 - fabs(x / r), 0.0);
781 static int
782 tent_width (double r)
784 return r < 1.0 ? 2 : ceil(2 * r);
788 static const filter_info_t filters[] =
790 { KERNEL_IMPULSE, impulse_kernel, impulse_width },
791 { KERNEL_BOX, box_kernel, box_width },
792 { KERNEL_LINEAR, linear_kernel, linear_width },
793 { KERNEL_MITCHELL, mitchell_kernel, cubic_width },
794 { KERNEL_NOTCH, notch_kernel, cubic_width },
795 { KERNEL_CATMULL_ROM, cubic_kernel, cubic_width },
796 { KERNEL_LANCZOS3, lanczos3_kernel, lanczos3_width },
797 { KERNEL_LANCZOS3_STRETCHED,nice_kernel, nice_width },
798 { KERNEL_TENT, tent_kernel, tent_width }
801 /* Fills in one dimension of the filter array */
802 static void get_filter(kernel_t filter, double r,
803 int width, int subsample,
804 pixman_fixed_t* out)
806 int i;
807 pixman_fixed_t *p = out;
808 int n_phases = 1 << subsample;
809 double step = 1.0 / n_phases;
810 kernel_func_t func = filters[filter].func;
812 /* special-case the impulse filter: */
813 if (width <= 1)
815 for (i = 0; i < n_phases; ++i)
816 *p++ = pixman_fixed_1;
817 return;
820 for (i = 0; i < n_phases; ++i)
822 double frac = (i + .5) * step;
823 /* Center of left-most pixel: */
824 double x1 = ceil (frac - width / 2.0 - 0.5) - frac + 0.5;
825 double total = 0;
826 pixman_fixed_t new_total = 0;
827 int j;
829 for (j = 0; j < width; ++j)
831 double v = func(x1 + j, r);
832 total += v;
833 p[j] = pixman_double_to_fixed (v);
836 /* Normalize */
837 total = 1 / total;
838 for (j = 0; j < width; ++j)
839 new_total += (p[j] *= total);
841 /* Put any error on center pixel */
842 p[width / 2] += (pixman_fixed_1 - new_total);
844 p += width;
849 /* Create the parameter list for a SEPARABLE_CONVOLUTION filter
850 * with the given kernels and scale parameters.
852 static pixman_fixed_t *
853 create_separable_convolution (int *n_values,
854 kernel_t xfilter,
855 double sx,
856 kernel_t yfilter,
857 double sy)
859 int xwidth, xsubsample, ywidth, ysubsample, size_x, size_y;
860 pixman_fixed_t *params;
862 xwidth = filters[xfilter].width(sx);
863 xsubsample = 0;
864 if (xwidth > 1)
865 while (sx * (1 << xsubsample) <= 128.0) xsubsample++;
866 size_x = (1 << xsubsample) * xwidth;
868 ywidth = filters[yfilter].width(sy);
869 ysubsample = 0;
870 if (ywidth > 1)
871 while (sy * (1 << ysubsample) <= 128.0) ysubsample++;
872 size_y = (1 << ysubsample) * ywidth;
874 *n_values = 4 + size_x + size_y;
875 params = malloc (*n_values * sizeof (pixman_fixed_t));
876 if (!params) return 0;
878 params[0] = pixman_int_to_fixed (xwidth);
879 params[1] = pixman_int_to_fixed (ywidth);
880 params[2] = pixman_int_to_fixed (xsubsample);
881 params[3] = pixman_int_to_fixed (ysubsample);
883 get_filter(xfilter, sx, xwidth, xsubsample, params + 4);
884 get_filter(yfilter, sy, ywidth, ysubsample, params + 4 + size_x);
886 return params;
889 /* ========================================================================== */
891 static cairo_bool_t
892 _pixman_image_set_properties (pixman_image_t *pixman_image,
893 const cairo_pattern_t *pattern,
894 const cairo_rectangle_int_t *extents,
895 int *ix,int *iy)
897 pixman_transform_t pixman_transform;
898 cairo_int_status_t status;
900 status = _cairo_matrix_to_pixman_matrix_offset (&pattern->matrix,
901 pattern->filter,
902 extents->x + extents->width/2.,
903 extents->y + extents->height/2.,
904 &pixman_transform, ix, iy);
905 if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
907 /* If the transform is an identity, we don't need to set it
908 * and we can use any filtering, so choose the fastest one. */
909 pixman_image_set_filter (pixman_image, PIXMAN_FILTER_NEAREST, NULL, 0);
911 else if (unlikely (status != CAIRO_INT_STATUS_SUCCESS ||
912 ! pixman_image_set_transform (pixman_image,
913 &pixman_transform)))
915 return FALSE;
917 else
919 pixman_filter_t pixman_filter;
920 kernel_t kernel;
921 double dx, dy;
923 /* Compute scale factors from the pattern matrix. These scale
924 * factors are from user to pattern space, and as such they
925 * are greater than 1.0 for downscaling and less than 1.0 for
926 * upscaling. The factors are the size of an axis-aligned
927 * rectangle with the same area as the parallelgram a 1x1
928 * square transforms to.
930 dx = hypot (pattern->matrix.xx, pattern->matrix.xy);
931 dy = hypot (pattern->matrix.yx, pattern->matrix.yy);
933 /* Clip at maximum pixman_fixed number. Besides making it
934 * passable to pixman, this avoids errors from inf and nan.
936 if (! (dx < 0x7FFF)) dx = 0x7FFF;
937 if (! (dy < 0x7FFF)) dy = 0x7FFF;
939 switch (pattern->filter) {
940 case CAIRO_FILTER_FAST:
941 pixman_filter = PIXMAN_FILTER_FAST;
942 break;
943 case CAIRO_FILTER_GOOD:
944 pixman_filter = PIXMAN_FILTER_SEPARABLE_CONVOLUTION;
945 kernel = KERNEL_BOX;
946 /* Clip the filter size to prevent extreme slowness. This
947 value could be raised if 2-pass filtering is done */
948 if (dx > 16.0) dx = 16.0;
949 if (dy > 16.0) dy = 16.0;
950 /* Match the bilinear filter for scales > .75: */
951 if (dx < 1.0/0.75) dx = 1.0;
952 if (dy < 1.0/0.75) dy = 1.0;
953 break;
954 case CAIRO_FILTER_BEST:
955 pixman_filter = PIXMAN_FILTER_SEPARABLE_CONVOLUTION;
956 kernel = KERNEL_CATMULL_ROM; /* LANCZOS3 is better but not much */
957 /* Clip the filter size to prevent extreme slowness. This
958 value could be raised if 2-pass filtering is done */
959 if (dx > 16.0) { dx = 16.0; kernel = KERNEL_BOX; }
960 /* blur up to 2x scale, then blend to square pixels for larger: */
961 else if (dx < 1.0) {
962 if (dx < 1.0/128) dx = 1.0/127;
963 else if (dx < 0.5) dx = 1.0 / (1.0 / dx - 1.0);
964 else dx = 1.0;
966 if (dy > 16.0) { dy = 16.0; kernel = KERNEL_BOX; }
967 else if (dy < 1.0) {
968 if (dy < 1.0/128) dy = 1.0/127;
969 else if (dy < 0.5) dy = 1.0 / (1.0 / dy - 1.0);
970 else dy = 1.0;
972 break;
973 case CAIRO_FILTER_NEAREST:
974 pixman_filter = PIXMAN_FILTER_NEAREST;
975 break;
976 case CAIRO_FILTER_BILINEAR:
977 pixman_filter = PIXMAN_FILTER_BILINEAR;
978 break;
979 case CAIRO_FILTER_GAUSSIAN:
980 /* XXX: The GAUSSIAN value has no implementation in cairo
981 * whatsoever, so it was really a mistake to have it in the
982 * API. We could fix this by officially deprecating it, or
983 * else inventing semantics and providing an actual
984 * implementation for it. */
985 default:
986 pixman_filter = PIXMAN_FILTER_BEST;
989 if (pixman_filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION) {
990 int n_params;
991 pixman_fixed_t *params;
992 params = create_separable_convolution
993 (&n_params, kernel, dx, kernel, dy);
994 pixman_image_set_filter (pixman_image, pixman_filter,
995 params, n_params);
996 free (params);
997 } else {
998 pixman_image_set_filter (pixman_image, pixman_filter, NULL, 0);
1003 pixman_repeat_t pixman_repeat;
1005 switch (pattern->extend) {
1006 default:
1007 case CAIRO_EXTEND_NONE:
1008 pixman_repeat = PIXMAN_REPEAT_NONE;
1009 break;
1010 case CAIRO_EXTEND_REPEAT:
1011 pixman_repeat = PIXMAN_REPEAT_NORMAL;
1012 break;
1013 case CAIRO_EXTEND_REFLECT:
1014 pixman_repeat = PIXMAN_REPEAT_REFLECT;
1015 break;
1016 case CAIRO_EXTEND_PAD:
1017 pixman_repeat = PIXMAN_REPEAT_PAD;
1018 break;
1021 pixman_image_set_repeat (pixman_image, pixman_repeat);
1024 if (pattern->has_component_alpha)
1025 pixman_image_set_component_alpha (pixman_image, TRUE);
1027 return TRUE;
1030 struct proxy {
1031 cairo_surface_t base;
1032 cairo_surface_t *image;
1035 static cairo_status_t
1036 proxy_acquire_source_image (void *abstract_surface,
1037 cairo_image_surface_t **image_out,
1038 void **image_extra)
1040 struct proxy *proxy = abstract_surface;
1041 return _cairo_surface_acquire_source_image (proxy->image, image_out, image_extra);
1044 static void
1045 proxy_release_source_image (void *abstract_surface,
1046 cairo_image_surface_t *image,
1047 void *image_extra)
1049 struct proxy *proxy = abstract_surface;
1050 _cairo_surface_release_source_image (proxy->image, image, image_extra);
1053 static cairo_status_t
1054 proxy_finish (void *abstract_surface)
1056 return CAIRO_STATUS_SUCCESS;
1059 static const cairo_surface_backend_t proxy_backend = {
1060 CAIRO_INTERNAL_SURFACE_TYPE_NULL,
1061 proxy_finish,
1062 NULL,
1064 NULL, /* create similar */
1065 NULL, /* create similar image */
1066 NULL, /* map to image */
1067 NULL, /* unmap image */
1069 _cairo_surface_default_source,
1070 proxy_acquire_source_image,
1071 proxy_release_source_image,
1074 static cairo_surface_t *
1075 attach_proxy (cairo_surface_t *source,
1076 cairo_surface_t *image)
1078 struct proxy *proxy;
1080 proxy = malloc (sizeof (*proxy));
1081 if (unlikely (proxy == NULL))
1082 return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
1084 _cairo_surface_init (&proxy->base, &proxy_backend, NULL, image->content);
1086 proxy->image = image;
1087 _cairo_surface_attach_snapshot (source, &proxy->base, NULL);
1089 return &proxy->base;
1092 static void
1093 detach_proxy (cairo_surface_t *source,
1094 cairo_surface_t *proxy)
1096 cairo_surface_finish (proxy);
1097 cairo_surface_destroy (proxy);
1100 static cairo_surface_t *
1101 get_proxy (cairo_surface_t *proxy)
1103 return ((struct proxy *)proxy)->image;
1106 static pixman_image_t *
1107 _pixman_image_for_recording (cairo_image_surface_t *dst,
1108 const cairo_surface_pattern_t *pattern,
1109 cairo_bool_t is_mask,
1110 const cairo_rectangle_int_t *extents,
1111 const cairo_rectangle_int_t *sample,
1112 int *ix, int *iy)
1114 cairo_surface_t *source, *clone, *proxy;
1115 cairo_rectangle_int_t limit;
1116 pixman_image_t *pixman_image;
1117 cairo_status_t status;
1118 cairo_extend_t extend;
1119 cairo_matrix_t *m, matrix;
1120 int tx = 0, ty = 0;
1122 TRACE ((stderr, "%s\n", __FUNCTION__));
1124 *ix = *iy = 0;
1126 source = _cairo_pattern_get_source (pattern, &limit);
1128 extend = pattern->base.extend;
1129 if (_cairo_rectangle_contains_rectangle (&limit, sample))
1130 extend = CAIRO_EXTEND_NONE;
1131 if (extend == CAIRO_EXTEND_NONE) {
1132 if (! _cairo_rectangle_intersect (&limit, sample))
1133 return _pixman_transparent_image ();
1135 if (! _cairo_matrix_is_identity (&pattern->base.matrix)) {
1136 double x1, y1, x2, y2;
1138 matrix = pattern->base.matrix;
1139 status = cairo_matrix_invert (&matrix);
1140 assert (status == CAIRO_STATUS_SUCCESS);
1142 x1 = limit.x;
1143 y1 = limit.y;
1144 x2 = limit.x + limit.width;
1145 y2 = limit.y + limit.height;
1147 _cairo_matrix_transform_bounding_box (&matrix,
1148 &x1, &y1, &x2, &y2, NULL);
1150 limit.x = floor (x1);
1151 limit.y = floor (y1);
1152 limit.width = ceil (x2) - limit.x;
1153 limit.height = ceil (y2) - limit.y;
1156 tx = limit.x;
1157 ty = limit.y;
1159 /* XXX transformations! */
1160 proxy = _cairo_surface_has_snapshot (source, &proxy_backend);
1161 if (proxy != NULL) {
1162 clone = cairo_surface_reference (get_proxy (proxy));
1163 goto done;
1166 if (is_mask) {
1167 clone = cairo_image_surface_create (CAIRO_FORMAT_A8,
1168 limit.width, limit.height);
1169 } else {
1170 if (dst->base.content == source->content)
1171 clone = cairo_image_surface_create (dst->format,
1172 limit.width, limit.height);
1173 else
1174 clone = _cairo_image_surface_create_with_content (source->content,
1175 limit.width,
1176 limit.height);
1179 m = NULL;
1180 if (extend == CAIRO_EXTEND_NONE) {
1181 matrix = pattern->base.matrix;
1182 if (tx | ty)
1183 cairo_matrix_translate (&matrix, tx, ty);
1184 m = &matrix;
1185 } else {
1186 /* XXX extract scale factor for repeating patterns */
1189 /* Handle recursion by returning future reads from the current image */
1190 proxy = attach_proxy (source, clone);
1191 status = _cairo_recording_surface_replay_with_clip (source, m, clone, NULL);
1192 detach_proxy (source, proxy);
1193 if (unlikely (status)) {
1194 cairo_surface_destroy (clone);
1195 return NULL;
1198 done:
1199 pixman_image = pixman_image_ref (((cairo_image_surface_t *)clone)->pixman_image);
1200 cairo_surface_destroy (clone);
1202 *ix = -limit.x;
1203 *iy = -limit.y;
1204 if (extend != CAIRO_EXTEND_NONE) {
1205 if (! _pixman_image_set_properties (pixman_image,
1206 &pattern->base, extents,
1207 ix, iy)) {
1208 pixman_image_unref (pixman_image);
1209 pixman_image= NULL;
1213 return pixman_image;
1216 static pixman_image_t *
1217 _pixman_image_for_surface (cairo_image_surface_t *dst,
1218 const cairo_surface_pattern_t *pattern,
1219 cairo_bool_t is_mask,
1220 const cairo_rectangle_int_t *extents,
1221 const cairo_rectangle_int_t *sample,
1222 int *ix, int *iy)
1224 cairo_extend_t extend = pattern->base.extend;
1225 pixman_image_t *pixman_image;
1227 TRACE ((stderr, "%s\n", __FUNCTION__));
1229 *ix = *iy = 0;
1230 pixman_image = NULL;
1231 if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
1232 return _pixman_image_for_recording(dst, pattern,
1233 is_mask, extents, sample,
1234 ix, iy);
1236 if (pattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE &&
1237 (! is_mask || ! pattern->base.has_component_alpha ||
1238 (pattern->surface->content & CAIRO_CONTENT_COLOR) == 0))
1240 cairo_surface_t *defer_free = NULL;
1241 cairo_image_surface_t *source = (cairo_image_surface_t *) pattern->surface;
1242 cairo_surface_type_t type;
1244 if (_cairo_surface_is_snapshot (&source->base)) {
1245 defer_free = _cairo_surface_snapshot_get_target (&source->base);
1246 source = (cairo_image_surface_t *) defer_free;
1249 type = source->base.backend->type;
1250 if (type == CAIRO_SURFACE_TYPE_IMAGE) {
1251 if (extend != CAIRO_EXTEND_NONE &&
1252 sample->x >= 0 &&
1253 sample->y >= 0 &&
1254 sample->x + sample->width <= source->width &&
1255 sample->y + sample->height <= source->height)
1257 extend = CAIRO_EXTEND_NONE;
1260 if (sample->width == 1 && sample->height == 1) {
1261 if (sample->x < 0 ||
1262 sample->y < 0 ||
1263 sample->x >= source->width ||
1264 sample->y >= source->height)
1266 if (extend == CAIRO_EXTEND_NONE) {
1267 cairo_surface_destroy (defer_free);
1268 return _pixman_transparent_image ();
1271 else
1273 pixman_image = _pixel_to_solid (source,
1274 sample->x, sample->y);
1275 if (pixman_image) {
1276 cairo_surface_destroy (defer_free);
1277 return pixman_image;
1282 #if PIXMAN_HAS_ATOMIC_OPS
1283 /* avoid allocating a 'pattern' image if we can reuse the original */
1284 if (extend == CAIRO_EXTEND_NONE &&
1285 _cairo_matrix_is_pixman_translation (&pattern->base.matrix,
1286 pattern->base.filter,
1287 ix, iy))
1289 cairo_surface_destroy (defer_free);
1290 return pixman_image_ref (source->pixman_image);
1292 #endif
1294 pixman_image = pixman_image_create_bits (source->pixman_format,
1295 source->width,
1296 source->height,
1297 (uint32_t *) source->data,
1298 source->stride);
1299 if (unlikely (pixman_image == NULL)) {
1300 cairo_surface_destroy (defer_free);
1301 return NULL;
1304 if (defer_free) {
1305 pixman_image_set_destroy_function (pixman_image,
1306 _defer_free_cleanup,
1307 defer_free);
1309 } else if (type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
1310 cairo_surface_subsurface_t *sub;
1311 cairo_bool_t is_contained = FALSE;
1313 sub = (cairo_surface_subsurface_t *) source;
1314 source = (cairo_image_surface_t *) sub->target;
1316 if (sample->x >= 0 &&
1317 sample->y >= 0 &&
1318 sample->x + sample->width <= sub->extents.width &&
1319 sample->y + sample->height <= sub->extents.height)
1321 is_contained = TRUE;
1324 if (sample->width == 1 && sample->height == 1) {
1325 if (is_contained) {
1326 pixman_image = _pixel_to_solid (source,
1327 sub->extents.x + sample->x,
1328 sub->extents.y + sample->y);
1329 if (pixman_image)
1330 return pixman_image;
1331 } else {
1332 if (extend == CAIRO_EXTEND_NONE)
1333 return _pixman_transparent_image ();
1337 #if PIXMAN_HAS_ATOMIC_OPS
1338 *ix = sub->extents.x;
1339 *iy = sub->extents.y;
1340 if (is_contained &&
1341 _cairo_matrix_is_pixman_translation (&pattern->base.matrix,
1342 pattern->base.filter,
1343 ix, iy))
1345 return pixman_image_ref (source->pixman_image);
1347 #endif
1349 /* Avoid sub-byte offsets, force a copy in that case. */
1350 if (PIXMAN_FORMAT_BPP (source->pixman_format) >= 8) {
1351 if (is_contained) {
1352 void *data = source->data
1353 + sub->extents.x * PIXMAN_FORMAT_BPP(source->pixman_format)/8
1354 + sub->extents.y * source->stride;
1355 pixman_image = pixman_image_create_bits (source->pixman_format,
1356 sub->extents.width,
1357 sub->extents.height,
1358 data,
1359 source->stride);
1360 if (unlikely (pixman_image == NULL))
1361 return NULL;
1362 } else {
1363 /* XXX for a simple translation and EXTEND_NONE we can
1364 * fix up the pattern matrix instead.
1371 if (pixman_image == NULL) {
1372 struct acquire_source_cleanup *cleanup;
1373 cairo_image_surface_t *image;
1374 void *extra;
1375 cairo_status_t status;
1377 status = _cairo_surface_acquire_source_image (pattern->surface, &image, &extra);
1378 if (unlikely (status))
1379 return NULL;
1381 pixman_image = pixman_image_create_bits (image->pixman_format,
1382 image->width,
1383 image->height,
1384 (uint32_t *) image->data,
1385 image->stride);
1386 if (unlikely (pixman_image == NULL)) {
1387 _cairo_surface_release_source_image (pattern->surface, image, extra);
1388 return NULL;
1391 cleanup = malloc (sizeof (*cleanup));
1392 if (unlikely (cleanup == NULL)) {
1393 _cairo_surface_release_source_image (pattern->surface, image, extra);
1394 pixman_image_unref (pixman_image);
1395 return NULL;
1398 cleanup->surface = pattern->surface;
1399 cleanup->image = image;
1400 cleanup->image_extra = extra;
1401 pixman_image_set_destroy_function (pixman_image,
1402 _acquire_source_cleanup, cleanup);
1405 if (! _pixman_image_set_properties (pixman_image,
1406 &pattern->base, extents,
1407 ix, iy)) {
1408 pixman_image_unref (pixman_image);
1409 pixman_image= NULL;
1412 return pixman_image;
1415 struct raster_source_cleanup {
1416 const cairo_pattern_t *pattern;
1417 cairo_surface_t *surface;
1418 cairo_image_surface_t *image;
1419 void *image_extra;
1422 static void
1423 _raster_source_cleanup (pixman_image_t *pixman_image,
1424 void *closure)
1426 struct raster_source_cleanup *data = closure;
1428 _cairo_surface_release_source_image (data->surface,
1429 data->image,
1430 data->image_extra);
1432 _cairo_raster_source_pattern_release (data->pattern,
1433 data->surface);
1435 free (data);
1438 static pixman_image_t *
1439 _pixman_image_for_raster (cairo_image_surface_t *dst,
1440 const cairo_raster_source_pattern_t *pattern,
1441 cairo_bool_t is_mask,
1442 const cairo_rectangle_int_t *extents,
1443 const cairo_rectangle_int_t *sample,
1444 int *ix, int *iy)
1446 pixman_image_t *pixman_image;
1447 struct raster_source_cleanup *cleanup;
1448 cairo_image_surface_t *image;
1449 void *extra;
1450 cairo_status_t status;
1451 cairo_surface_t *surface;
1453 TRACE ((stderr, "%s\n", __FUNCTION__));
1455 *ix = *iy = 0;
1457 surface = _cairo_raster_source_pattern_acquire (&pattern->base,
1458 &dst->base, NULL);
1459 if (unlikely (surface == NULL || surface->status))
1460 return NULL;
1462 status = _cairo_surface_acquire_source_image (surface, &image, &extra);
1463 if (unlikely (status)) {
1464 _cairo_raster_source_pattern_release (&pattern->base, surface);
1465 return NULL;
1468 assert (image->width == pattern->extents.width);
1469 assert (image->height == pattern->extents.height);
1471 pixman_image = pixman_image_create_bits (image->pixman_format,
1472 image->width,
1473 image->height,
1474 (uint32_t *) image->data,
1475 image->stride);
1476 if (unlikely (pixman_image == NULL)) {
1477 _cairo_surface_release_source_image (surface, image, extra);
1478 _cairo_raster_source_pattern_release (&pattern->base, surface);
1479 return NULL;
1482 cleanup = malloc (sizeof (*cleanup));
1483 if (unlikely (cleanup == NULL)) {
1484 pixman_image_unref (pixman_image);
1485 _cairo_surface_release_source_image (surface, image, extra);
1486 _cairo_raster_source_pattern_release (&pattern->base, surface);
1487 return NULL;
1490 cleanup->pattern = &pattern->base;
1491 cleanup->surface = surface;
1492 cleanup->image = image;
1493 cleanup->image_extra = extra;
1494 pixman_image_set_destroy_function (pixman_image,
1495 _raster_source_cleanup, cleanup);
1497 if (! _pixman_image_set_properties (pixman_image,
1498 &pattern->base, extents,
1499 ix, iy)) {
1500 pixman_image_unref (pixman_image);
1501 pixman_image= NULL;
1504 return pixman_image;
1507 pixman_image_t *
1508 _pixman_image_for_pattern (cairo_image_surface_t *dst,
1509 const cairo_pattern_t *pattern,
1510 cairo_bool_t is_mask,
1511 const cairo_rectangle_int_t *extents,
1512 const cairo_rectangle_int_t *sample,
1513 int *tx, int *ty)
1515 *tx = *ty = 0;
1517 TRACE ((stderr, "%s\n", __FUNCTION__));
1519 if (pattern == NULL)
1520 return _pixman_white_image ();
1522 switch (pattern->type) {
1523 default:
1524 ASSERT_NOT_REACHED;
1525 case CAIRO_PATTERN_TYPE_SOLID:
1526 return _pixman_image_for_color (&((const cairo_solid_pattern_t *) pattern)->color);
1528 case CAIRO_PATTERN_TYPE_RADIAL:
1529 case CAIRO_PATTERN_TYPE_LINEAR:
1530 return _pixman_image_for_gradient ((const cairo_gradient_pattern_t *) pattern,
1531 extents, tx, ty);
1533 case CAIRO_PATTERN_TYPE_MESH:
1534 return _pixman_image_for_mesh ((const cairo_mesh_pattern_t *) pattern,
1535 extents, tx, ty);
1537 case CAIRO_PATTERN_TYPE_SURFACE:
1538 return _pixman_image_for_surface (dst,
1539 (const cairo_surface_pattern_t *) pattern,
1540 is_mask, extents, sample,
1541 tx, ty);
1543 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
1544 return _pixman_image_for_raster (dst,
1545 (const cairo_raster_source_pattern_t *) pattern,
1546 is_mask, extents, sample,
1547 tx, ty);
1551 static cairo_status_t
1552 _cairo_image_source_finish (void *abstract_surface)
1554 cairo_image_source_t *source = abstract_surface;
1556 pixman_image_unref (source->pixman_image);
1557 return CAIRO_STATUS_SUCCESS;
1560 const cairo_surface_backend_t _cairo_image_source_backend = {
1561 CAIRO_SURFACE_TYPE_IMAGE,
1562 _cairo_image_source_finish,
1563 NULL, /* read-only wrapper */
1566 cairo_surface_t *
1567 _cairo_image_source_create_for_pattern (cairo_surface_t *dst,
1568 const cairo_pattern_t *pattern,
1569 cairo_bool_t is_mask,
1570 const cairo_rectangle_int_t *extents,
1571 const cairo_rectangle_int_t *sample,
1572 int *src_x, int *src_y)
1574 cairo_image_source_t *source;
1576 TRACE ((stderr, "%s\n", __FUNCTION__));
1578 source = malloc (sizeof (cairo_image_source_t));
1579 if (unlikely (source == NULL))
1580 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1582 source->pixman_image =
1583 _pixman_image_for_pattern ((cairo_image_surface_t *)dst,
1584 pattern, is_mask,
1585 extents, sample,
1586 src_x, src_y);
1587 if (unlikely (source->pixman_image == NULL)) {
1588 free (source);
1589 return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
1592 _cairo_surface_init (&source->base,
1593 &_cairo_image_source_backend,
1594 NULL, /* device */
1595 CAIRO_CONTENT_COLOR_ALPHA);
1597 source->is_opaque_solid =
1598 pattern == NULL || _cairo_pattern_is_opaque_solid (pattern);
1600 return &source->base;