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
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.
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"
57 #include "cairo-image-filters-private.h"
59 #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
62 #define PIXMAN_HAS_ATOMIC_OPS 1
65 #define SEPARABLE_CONVOLUTION 0
67 #if PIXMAN_HAS_ATOMIC_OPS
68 static pixman_image_t *__pixman_transparent_image;
69 static pixman_image_t *__pixman_black_image;
70 static pixman_image_t *__pixman_white_image;
72 static pixman_image_t *
73 _pixman_transparent_image (void)
75 pixman_image_t *image;
77 TRACE ((stderr, "%s\n", __FUNCTION__));
79 image = __pixman_transparent_image;
80 if (unlikely (image == NULL)) {
88 image = pixman_image_create_solid_fill (&color);
89 if (unlikely (image == NULL))
92 if (_cairo_atomic_ptr_cmpxchg (&__pixman_transparent_image,
95 pixman_image_ref (image);
98 pixman_image_ref (image);
104 static pixman_image_t *
105 _pixman_black_image (void)
107 pixman_image_t *image;
109 TRACE ((stderr, "%s\n", __FUNCTION__));
111 image = __pixman_black_image;
112 if (unlikely (image == NULL)) {
113 pixman_color_t color;
118 color.alpha = 0xffff;
120 image = pixman_image_create_solid_fill (&color);
121 if (unlikely (image == NULL))
124 if (_cairo_atomic_ptr_cmpxchg (&__pixman_black_image,
127 pixman_image_ref (image);
130 pixman_image_ref (image);
136 static pixman_image_t *
137 _pixman_white_image (void)
139 pixman_image_t *image;
141 TRACE ((stderr, "%s\n", __FUNCTION__));
143 image = __pixman_white_image;
144 if (unlikely (image == NULL)) {
145 pixman_color_t color;
148 color.green = 0xffff;
150 color.alpha = 0xffff;
152 image = pixman_image_create_solid_fill (&color);
153 if (unlikely (image == NULL))
156 if (_cairo_atomic_ptr_cmpxchg (&__pixman_white_image,
159 pixman_image_ref (image);
162 pixman_image_ref (image);
169 hars_petruska_f54_1_random (void)
171 #define rol(x,k) ((x << k) | (x >> (32-k)))
173 return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
179 pixman_image_t *image;
183 #else /* !PIXMAN_HAS_ATOMIC_OPS */
184 static pixman_image_t *
185 _pixman_transparent_image (void)
187 TRACE ((stderr, "%s\n", __FUNCTION__));
188 return _pixman_image_for_color (CAIRO_COLOR_TRANSPARENT);
191 static pixman_image_t *
192 _pixman_black_image (void)
194 TRACE ((stderr, "%s\n", __FUNCTION__));
195 return _pixman_image_for_color (CAIRO_COLOR_BLACK);
198 static pixman_image_t *
199 _pixman_white_image (void)
201 TRACE ((stderr, "%s\n", __FUNCTION__));
202 return _pixman_image_for_color (CAIRO_COLOR_WHITE);
204 #endif /* !PIXMAN_HAS_ATOMIC_OPS */
208 _pixman_image_for_color (const cairo_color_t *cairo_color)
210 pixman_color_t color;
211 pixman_image_t *image;
213 #if PIXMAN_HAS_ATOMIC_OPS
216 if (CAIRO_COLOR_IS_CLEAR (cairo_color))
217 return _pixman_transparent_image ();
219 if (CAIRO_COLOR_IS_OPAQUE (cairo_color)) {
220 if (cairo_color->red_short <= 0x00ff &&
221 cairo_color->green_short <= 0x00ff &&
222 cairo_color->blue_short <= 0x00ff)
224 return _pixman_black_image ();
227 if (cairo_color->red_short >= 0xff00 &&
228 cairo_color->green_short >= 0xff00 &&
229 cairo_color->blue_short >= 0xff00)
231 return _pixman_white_image ();
235 CAIRO_MUTEX_LOCK (_cairo_image_solid_cache_mutex);
236 for (i = 0; i < n_cached; i++) {
237 if (_cairo_color_equal (&cache[i].color, cairo_color)) {
238 image = pixman_image_ref (cache[i].image);
244 color.red = cairo_color->red_short;
245 color.green = cairo_color->green_short;
246 color.blue = cairo_color->blue_short;
247 color.alpha = cairo_color->alpha_short;
249 image = pixman_image_create_solid_fill (&color);
250 #if PIXMAN_HAS_ATOMIC_OPS
254 if (n_cached < ARRAY_LENGTH (cache)) {
257 i = hars_petruska_f54_1_random () % ARRAY_LENGTH (cache);
258 pixman_image_unref (cache[i].image);
260 cache[i].image = pixman_image_ref (image);
261 cache[i].color = *cairo_color;
264 CAIRO_MUTEX_UNLOCK (_cairo_image_solid_cache_mutex);
271 _cairo_image_reset_static_data (void)
273 #if PIXMAN_HAS_ATOMIC_OPS
275 pixman_image_unref (cache[--n_cached].image);
277 if (__pixman_transparent_image) {
278 pixman_image_unref (__pixman_transparent_image);
279 __pixman_transparent_image = NULL;
282 if (__pixman_black_image) {
283 pixman_image_unref (__pixman_black_image);
284 __pixman_black_image = NULL;
287 if (__pixman_white_image) {
288 pixman_image_unref (__pixman_white_image);
289 __pixman_white_image = NULL;
294 static pixman_image_t *
295 _pixman_image_for_gradient (const cairo_gradient_pattern_t *pattern,
296 const cairo_rectangle_int_t *extents,
299 pixman_image_t *pixman_image;
300 pixman_gradient_stop_t pixman_stops_static[2];
301 pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
302 pixman_transform_t pixman_transform;
303 cairo_matrix_t matrix;
304 cairo_circle_double_t extremes[2];
305 pixman_point_fixed_t p1, p2;
307 cairo_int_status_t status;
309 TRACE ((stderr, "%s\n", __FUNCTION__));
311 if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
312 pixman_stops = _cairo_malloc_ab (pattern->n_stops,
313 sizeof(pixman_gradient_stop_t));
314 if (unlikely (pixman_stops == NULL))
318 for (i = 0; i < pattern->n_stops; i++) {
319 pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
320 pixman_stops[i].color.red = pattern->stops[i].color.red_short;
321 pixman_stops[i].color.green = pattern->stops[i].color.green_short;
322 pixman_stops[i].color.blue = pattern->stops[i].color.blue_short;
323 pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
326 _cairo_gradient_pattern_fit_to_range (pattern, PIXMAN_MAX_INT >> 1, &matrix, extremes);
328 p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
329 p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
330 p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
331 p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
333 if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
334 pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
338 pixman_fixed_t r1, r2;
340 r1 = _cairo_fixed_16_16_from_double (extremes[0].radius);
341 r2 = _cairo_fixed_16_16_from_double (extremes[1].radius);
343 pixman_image = pixman_image_create_radial_gradient (&p1, &p2, r1, r2,
348 if (pixman_stops != pixman_stops_static)
351 if (unlikely (pixman_image == NULL))
355 status = _cairo_matrix_to_pixman_matrix_offset (&matrix, pattern->base.filter,
356 extents->x + extents->width/2.,
357 extents->y + extents->height/2.,
358 &pixman_transform, ix, iy);
359 if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
360 if (unlikely (status != CAIRO_INT_STATUS_SUCCESS) ||
361 ! pixman_image_set_transform (pixman_image, &pixman_transform))
363 pixman_image_unref (pixman_image);
369 pixman_repeat_t pixman_repeat;
371 switch (pattern->base.extend) {
373 case CAIRO_EXTEND_NONE:
374 pixman_repeat = PIXMAN_REPEAT_NONE;
376 case CAIRO_EXTEND_REPEAT:
377 pixman_repeat = PIXMAN_REPEAT_NORMAL;
379 case CAIRO_EXTEND_REFLECT:
380 pixman_repeat = PIXMAN_REPEAT_REFLECT;
382 case CAIRO_EXTEND_PAD:
383 pixman_repeat = PIXMAN_REPEAT_PAD;
387 pixman_image_set_repeat (pixman_image, pixman_repeat);
393 static pixman_image_t *
394 _pixman_image_for_mesh (const cairo_mesh_pattern_t *pattern,
395 const cairo_rectangle_int_t *extents,
398 pixman_image_t *image;
401 TRACE ((stderr, "%s\n", __FUNCTION__));
405 width = extents->width;
406 height = extents->height;
408 image = pixman_image_create_bits (PIXMAN_a8r8g8b8, width, height, NULL, 0);
409 if (unlikely (image == NULL))
412 _cairo_mesh_pattern_rasterize (pattern,
413 pixman_image_get_data (image),
415 pixman_image_get_stride (image),
420 struct acquire_source_cleanup {
421 cairo_surface_t *surface;
422 cairo_image_surface_t *image;
427 _acquire_source_cleanup (pixman_image_t *pixman_image,
430 struct acquire_source_cleanup *data = closure;
432 _cairo_surface_release_source_image (data->surface,
439 _defer_free_cleanup (pixman_image_t *pixman_image,
442 cairo_surface_destroy (closure);
446 expand_channel (uint16_t v, uint32_t bits)
448 int offset = 16 - bits;
457 static pixman_image_t *
458 _pixel_to_solid (cairo_image_surface_t *image, int x, int y)
461 pixman_color_t color;
463 TRACE ((stderr, "%s\n", __FUNCTION__));
465 switch (image->format) {
467 case CAIRO_FORMAT_INVALID:
471 case CAIRO_FORMAT_A1:
472 pixel = *(uint8_t *) (image->data + y * image->stride + x/8);
473 return pixel & (1 << (x&7)) ? _pixman_black_image () : _pixman_transparent_image ();
475 case CAIRO_FORMAT_A8:
476 color.alpha = *(uint8_t *) (image->data + y * image->stride + x);
477 color.alpha |= color.alpha << 8;
478 if (color.alpha == 0)
479 return _pixman_transparent_image ();
480 if (color.alpha == 0xffff)
481 return _pixman_black_image ();
483 color.red = color.green = color.blue = 0;
484 return pixman_image_create_solid_fill (&color);
486 case CAIRO_FORMAT_RGB16_565:
487 pixel = *(uint16_t *) (image->data + y * image->stride + 2 * x);
489 return _pixman_black_image ();
491 return _pixman_white_image ();
493 color.alpha = 0xffff;
494 color.red = expand_channel ((pixel >> 11 & 0x1f) << 11, 5);
495 color.green = expand_channel ((pixel >> 5 & 0x3f) << 10, 6);
496 color.blue = expand_channel ((pixel & 0x1f) << 11, 5);
497 return pixman_image_create_solid_fill (&color);
499 case CAIRO_FORMAT_RGB30:
500 pixel = *(uint32_t *) (image->data + y * image->stride + 4 * x);
501 pixel &= 0x3fffffff; /* ignore alpha bits */
503 return _pixman_black_image ();
504 if (pixel == 0x3fffffff)
505 return _pixman_white_image ();
507 /* convert 10bpc to 16bpc */
508 color.alpha = 0xffff;
509 color.red = expand_channel((pixel >> 20) & 0x3fff, 10);
510 color.green = expand_channel((pixel >> 10) & 0x3fff, 10);
511 color.blue = expand_channel(pixel & 0x3fff, 10);
512 return pixman_image_create_solid_fill (&color);
514 case CAIRO_FORMAT_ARGB32:
515 case CAIRO_FORMAT_RGB24:
516 pixel = *(uint32_t *) (image->data + y * image->stride + 4 * x);
517 color.alpha = image->format == CAIRO_FORMAT_ARGB32 ? (pixel >> 24) | (pixel >> 16 & 0xff00) : 0xffff;
518 if (color.alpha == 0)
519 return _pixman_transparent_image ();
520 if (pixel == 0xffffffff)
521 return _pixman_white_image ();
522 if (color.alpha == 0xffff && (pixel & 0xffffff) == 0)
523 return _pixman_black_image ();
525 color.red = (pixel >> 16 & 0xff) | (pixel >> 8 & 0xff00);
526 color.green = (pixel >> 8 & 0xff) | (pixel & 0xff00);
527 color.blue = (pixel & 0xff) | (pixel << 8 & 0xff00);
528 return pixman_image_create_solid_fill (&color);
532 /* ========================================================================== */
534 /* Index into filter table */
544 KERNEL_LANCZOS3_STRETCHED,
548 /* Produce contribution of a filter of size r for pixel centered on x.
549 For a typical low-pass function this evaluates the function at x/r.
550 If the frequency is higher than 1/2, such as when r is less than 1,
551 this may need to integrate several samples, see cubic for examples.
553 typedef double (* kernel_func_t) (double x, double r);
555 /* Return maximum number of pixels that will be non-zero. Except for
556 impluse this is the maximum of 2 and the width of the non-zero part
557 of the filter rounded up to the next integer.
559 typedef int (* kernel_width_func_t) (double r);
561 /* Table of filters */
566 kernel_width_func_t width;
569 /* PIXMAN_KERNEL_IMPULSE: Returns pixel nearest the center. This
570 matches PIXMAN_FILTER_NEAREST. This is useful if you wish to
571 combine the result of nearest in one direction with another filter
576 impulse_kernel (double x, double r)
582 impulse_width (double r)
587 /* PIXMAN_KERNEL_BOX: Intersection of a box of width r with square
588 pixels. This is the smallest possible filter such that the output
589 image contains an equal contribution from all the input
590 pixels. Lots of software uses this. The function is a trapazoid of
591 width r+1, not a box.
593 When r == 1.0, PIXMAN_KERNEL_BOX, PIXMAN_KERNEL_LINEAR, and
594 PIXMAN_KERNEL_TENT all produce the same filter, allowing
595 them to be exchanged at this point.
599 box_kernel (double x, double r)
601 return MAX (0.0, MIN (MIN (r, 1.0),
602 MIN ((r + 1) / 2 - x, (r + 1) / 2 + x)));
608 return r < 1.0 ? 2 : ceil(r + 1);
611 /* PIXMAN_KERNEL_LINEAR: Weighted sum of the two pixels nearest the
612 center, or a triangle of width 2. This matches
613 PIXMAN_FILTER_BILINEAR. This is useful if you wish to combine the
614 result of bilinear in one direction with another filter in the
615 other. This is not a good filter if r > 1. You may actually want
618 When r == 1.0, PIXMAN_KERNEL_BOX, PIXMAN_KERNEL_LINEAR, and
619 PIXMAN_KERNEL_TENT all produce the same filter, allowing
620 them to be exchanged at this point.
624 linear_kernel (double x, double r)
626 return MAX (1.0 - fabs(x), 0.0);
630 linear_width (double r)
635 /* Cubic functions described in the Mitchell-Netravali paper.
636 http://mentallandscape.com/Papers_siggraph88.pdf. This describes
637 all possible cubic functions that can be used for sampling.
641 general_cubic (double x, double r, double B, double C)
646 general_cubic(x * 2 - .5, r * 2, B, C) +
647 general_cubic(x * 2 + .5, r * 2, B, C);
653 return (((12 - 9 * B - 6 * C) * ax +
654 (-18 + 12 * B + 6 * C)) * ax * ax +
659 return ((((-B - 6 * C) * ax +
660 (6 * B + 30 * C)) * ax +
661 (-12 * B - 48 * C)) * ax +
662 (8 * B + 24 * C)) / 6;
671 cubic_width (double r)
673 return MAX (2, ceil (r * 4));
676 /* PIXMAN_KERNEL_CATMULL_ROM: Catmull-Rom interpolation. Often called
677 "cubic interpolation", "b-spline", or just "cubic" by other
678 software. This filter has negative values so it can produce ringing
679 and output pixels outside the range of input pixels. This is very
680 close to lanczos2 so there is no reason to supply that as well.
684 cubic_kernel (double x, double r)
686 return general_cubic (x, r, 0.0, 0.5);
689 /* PIXMAN_KERNEL_MITCHELL: Cubic recommended by the Mitchell-Netravali
690 paper. This has negative values and because the values at +/-1 are
691 not zero it does not interpolate the pixels, meaning it will change
692 an image even if there is no translation.
696 mitchell_kernel (double x, double r)
698 return general_cubic (x, r, 1/3.0, 1/3.0);
701 /* PIXMAN_KERNEL_NOTCH: Cubic recommended by the Mitchell-Netravali
702 paper to remove postaliasing artifacts. This does not remove
703 aliasing already present in the source image, though it may appear
704 to due to it's excessive blurriness. In any case this is more
705 useful than gaussian for image reconstruction.
709 notch_kernel (double x, double r)
711 return general_cubic (x, r, 1.5, -0.25);
714 /* PIXMAN_KERNEL_LANCZOS3: lanczos windowed sinc function from -3 to
715 +3. Very popular with high-end software though I think any
716 advantage over cubics is hidden by quantization and programming
717 mistakes. You will see LANCZOS5 or even 7 sometimes.
723 return x ? sin (M_PI * x) / (M_PI * x) : 1.0;
727 lanczos (double x, double n)
729 return fabs (x) < n ? sinc (x) * sinc (x * (1.0 / n)) : 0.0;
733 lanczos3_kernel (double x, double r)
737 lanczos3_kernel (x * 2 - .5, r * 2) +
738 lanczos3_kernel (x * 2 + .5, r * 2);
740 return lanczos (x / r, 3.0);
744 lanczos3_width (double r)
746 return MAX (2, ceil (r * 6));
749 /* PIXMAN_KERNEL_LANCZOS3_STRETCHED - The LANCZOS3 kernel widened by
750 4/3. Recommended by Jim Blinn
751 http://graphics.cs.cmu.edu/nsp/course/15-462/Fall07/462/papers/jaggy.pdf
755 nice_kernel (double x, double r)
757 return lanczos3_kernel (x, r * (4.0/3));
761 nice_width (double r)
763 return MAX (2.0, ceil (r * 8));
766 /* PIXMAN_KERNEL_TENT: Triangle of width 2r. Lots of software uses
767 this as a "better" filter, twice the size of a box but smaller than
770 When r == 1.0, PIXMAN_KERNEL_BOX, PIXMAN_KERNEL_LINEAR, and
771 PIXMAN_KERNEL_TENT all produce the same filter, allowing
772 them to be exchanged at this point.
776 tent_kernel (double x, double r)
779 return box_kernel(x, r);
781 return MAX (1.0 - fabs(x / r), 0.0);
785 tent_width (double r)
787 return r < 1.0 ? 2 : ceil(2 * r);
791 static const filter_info_t filters[] =
793 { KERNEL_IMPULSE, impulse_kernel, impulse_width },
794 { KERNEL_BOX, box_kernel, box_width },
795 { KERNEL_LINEAR, linear_kernel, linear_width },
796 { KERNEL_MITCHELL, mitchell_kernel, cubic_width },
797 { KERNEL_NOTCH, notch_kernel, cubic_width },
798 { KERNEL_CATMULL_ROM, cubic_kernel, cubic_width },
799 { KERNEL_LANCZOS3, lanczos3_kernel, lanczos3_width },
800 { KERNEL_LANCZOS3_STRETCHED,nice_kernel, nice_width },
801 { KERNEL_TENT, tent_kernel, tent_width }
804 /* Fills in one dimension of the filter array */
805 static void get_filter(kernel_t filter, double r,
806 int width, int subsample,
810 pixman_fixed_t *p = out;
811 int n_phases = 1 << subsample;
812 double step = 1.0 / n_phases;
813 kernel_func_t func = filters[filter].func;
815 /* special-case the impulse filter: */
818 for (i = 0; i < n_phases; ++i)
819 *p++ = pixman_fixed_1;
823 for (i = 0; i < n_phases; ++i)
825 double frac = (i + .5) * step;
826 /* Center of left-most pixel: */
827 double x1 = ceil (frac - width / 2.0 - 0.5) - frac + 0.5;
829 pixman_fixed_t new_total = 0;
832 for (j = 0; j < width; ++j)
834 double v = func(x1 + j, r);
836 p[j] = pixman_double_to_fixed (v);
841 for (j = 0; j < width; ++j)
842 new_total += (p[j] *= total);
844 /* Put any error on center pixel */
845 p[width / 2] += (pixman_fixed_1 - new_total);
852 /* Create the parameter list for a SEPARABLE_CONVOLUTION filter
853 * with the given kernels and scale parameters.
855 static pixman_fixed_t *
856 create_separable_convolution (int *n_values,
862 int xwidth, xsubsample, ywidth, ysubsample, size_x, size_y;
863 pixman_fixed_t *params;
865 xwidth = filters[xfilter].width(sx);
868 while (sx * (1 << xsubsample) <= 128.0) xsubsample++;
869 size_x = (1 << xsubsample) * xwidth;
871 ywidth = filters[yfilter].width(sy);
874 while (sy * (1 << ysubsample) <= 128.0) ysubsample++;
875 size_y = (1 << ysubsample) * ywidth;
877 *n_values = 4 + size_x + size_y;
878 params = malloc (*n_values * sizeof (pixman_fixed_t));
879 if (!params) return 0;
881 params[0] = pixman_int_to_fixed (xwidth);
882 params[1] = pixman_int_to_fixed (ywidth);
883 params[2] = pixman_int_to_fixed (xsubsample);
884 params[3] = pixman_int_to_fixed (ysubsample);
886 get_filter(xfilter, sx, xwidth, xsubsample, params + 4);
887 get_filter(yfilter, sy, ywidth, ysubsample, params + 4 + size_x);
892 /* ========================================================================== */
895 _pixman_image_set_properties (pixman_image_t *pixman_image,
896 const cairo_pattern_t *pattern,
897 const cairo_rectangle_int_t *extents,
900 pixman_transform_t pixman_transform;
901 cairo_int_status_t status;
903 status = _cairo_matrix_to_pixman_matrix_offset (&pattern->matrix,
905 extents->x + extents->width/2.,
906 extents->y + extents->height/2.,
907 &pixman_transform, ix, iy);
908 if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
910 /* If the transform is an identity, we don't need to set it
911 * and we can use any filtering, so choose the fastest one. */
912 pixman_image_set_filter (pixman_image, PIXMAN_FILTER_NEAREST, NULL, 0);
914 else if (unlikely (status != CAIRO_INT_STATUS_SUCCESS ||
915 ! pixman_image_set_transform (pixman_image,
922 pixman_filter_t pixman_filter;
926 /* Compute scale factors from the pattern matrix. These scale
927 * factors are from user to pattern space, and as such they
928 * are greater than 1.0 for downscaling and less than 1.0 for
929 * upscaling. The factors are the size of an axis-aligned
930 * rectangle with the same area as the parallelgram a 1x1
931 * square transforms to.
933 dx = hypot (pattern->matrix.xx, pattern->matrix.xy);
934 dy = hypot (pattern->matrix.yx, pattern->matrix.yy);
936 /* Clip at maximum pixman_fixed number. Besides making it
937 * passable to pixman, this avoids errors from inf and nan.
939 if (! (dx < 0x7FFF)) dx = 0x7FFF;
940 if (! (dy < 0x7FFF)) dy = 0x7FFF;
942 switch (pattern->filter) {
943 case CAIRO_FILTER_FAST:
944 pixman_filter = PIXMAN_FILTER_FAST;
946 /* In order to prevent performance drop, Disable PIXMAN_FILTER_SEPERABLE_CONVOLTION
947 * same as cairo 1.12.14 in Tizen2.4
949 #if SEPARABLE_CONVOLUTION
950 case CAIRO_FILTER_GOOD:
951 pixman_filter = PIXMAN_FILTER_SEPARABLE_CONVOLUTION;
953 /* Clip the filter size to prevent extreme slowness. This
954 value could be raised if 2-pass filtering is done */
955 if (dx > 16.0) dx = 16.0;
956 if (dy > 16.0) dy = 16.0;
957 /* Match the bilinear filter for scales > .75: */
958 if (dx < 1.0/0.75) dx = 1.0;
959 if (dy < 1.0/0.75) dy = 1.0;
961 case CAIRO_FILTER_BEST:
962 pixman_filter = PIXMAN_FILTER_SEPARABLE_CONVOLUTION;
963 kernel = KERNEL_CATMULL_ROM; /* LANCZOS3 is better but not much */
964 /* Clip the filter size to prevent extreme slowness. This
965 value could be raised if 2-pass filtering is done */
966 if (dx > 16.0) { dx = 16.0; kernel = KERNEL_BOX; }
967 /* blur up to 2x scale, then blend to square pixels for larger: */
969 if (dx < 1.0/128) dx = 1.0/127;
970 else if (dx < 0.5) dx = 1.0 / (1.0 / dx - 1.0);
973 if (dy > 16.0) { dy = 16.0; kernel = KERNEL_BOX; }
975 if (dy < 1.0/128) dy = 1.0/127;
976 else if (dy < 0.5) dy = 1.0 / (1.0 / dy - 1.0);
981 case CAIRO_FILTER_GOOD:
982 pixman_filter = PIXMAN_FILTER_GOOD;
984 case CAIRO_FILTER_BEST:
985 pixman_filter = PIXMAN_FILTER_BEST;
988 case CAIRO_FILTER_NEAREST:
989 pixman_filter = PIXMAN_FILTER_NEAREST;
991 case CAIRO_FILTER_BILINEAR:
992 pixman_filter = PIXMAN_FILTER_BILINEAR;
994 case CAIRO_FILTER_GAUSSIAN:
995 /* XXX: The GAUSSIAN value has no implementation in cairo
996 * whatsoever, so it was really a mistake to have it in the
997 * API. We could fix this by officially deprecating it, or
998 * else inventing semantics and providing an actual
999 * implementation for it. */
1001 pixman_filter = PIXMAN_FILTER_BEST;
1004 if (pixman_filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION) {
1006 pixman_fixed_t *params;
1007 params = create_separable_convolution
1008 (&n_params, kernel, dx, kernel, dy);
1009 pixman_image_set_filter (pixman_image, pixman_filter,
1013 pixman_image_set_filter (pixman_image, pixman_filter, NULL, 0);
1018 pixman_repeat_t pixman_repeat;
1020 switch (pattern->extend) {
1022 case CAIRO_EXTEND_NONE:
1023 pixman_repeat = PIXMAN_REPEAT_NONE;
1025 case CAIRO_EXTEND_REPEAT:
1026 pixman_repeat = PIXMAN_REPEAT_NORMAL;
1028 case CAIRO_EXTEND_REFLECT:
1029 pixman_repeat = PIXMAN_REPEAT_REFLECT;
1031 case CAIRO_EXTEND_PAD:
1032 pixman_repeat = PIXMAN_REPEAT_PAD;
1036 pixman_image_set_repeat (pixman_image, pixman_repeat);
1039 if (pattern->has_component_alpha)
1040 pixman_image_set_component_alpha (pixman_image, TRUE);
1046 cairo_surface_t base;
1047 cairo_surface_t *image;
1050 static cairo_status_t
1051 proxy_acquire_source_image (void *abstract_surface,
1052 cairo_image_surface_t **image_out,
1055 struct proxy *proxy = abstract_surface;
1056 return _cairo_surface_acquire_source_image (proxy->image, image_out, image_extra);
1060 proxy_release_source_image (void *abstract_surface,
1061 cairo_image_surface_t *image,
1064 struct proxy *proxy = abstract_surface;
1065 _cairo_surface_release_source_image (proxy->image, image, image_extra);
1068 static cairo_status_t
1069 proxy_finish (void *abstract_surface)
1071 return CAIRO_STATUS_SUCCESS;
1074 static const cairo_surface_backend_t proxy_backend = {
1075 CAIRO_INTERNAL_SURFACE_TYPE_NULL,
1079 NULL, /* create similar */
1080 NULL, /* create similar image */
1081 NULL, /* map to image */
1082 NULL, /* unmap image */
1084 _cairo_surface_default_source,
1085 proxy_acquire_source_image,
1086 proxy_release_source_image,
1089 static cairo_surface_t *
1090 attach_proxy (cairo_surface_t *source,
1091 cairo_surface_t *image)
1093 struct proxy *proxy;
1095 proxy = malloc (sizeof (*proxy));
1096 if (unlikely (proxy == NULL))
1097 return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
1099 _cairo_surface_init (&proxy->base, &proxy_backend, NULL, image->content);
1101 proxy->image = image;
1102 _cairo_surface_attach_snapshot (source, &proxy->base, NULL);
1104 return &proxy->base;
1108 detach_proxy (cairo_surface_t *source,
1109 cairo_surface_t *proxy)
1111 cairo_surface_finish (proxy);
1112 cairo_surface_destroy (proxy);
1115 static cairo_surface_t *
1116 get_proxy (cairo_surface_t *proxy)
1118 return ((struct proxy *)proxy)->image;
1121 static pixman_image_t *
1122 _pixman_image_for_recording (cairo_image_surface_t *dst,
1123 const cairo_surface_pattern_t *pattern,
1124 cairo_bool_t is_mask,
1125 const cairo_rectangle_int_t *extents,
1126 const cairo_rectangle_int_t *sample,
1129 cairo_surface_t *source, *clone, *proxy;
1130 cairo_rectangle_int_t limit;
1131 pixman_image_t *pixman_image;
1132 cairo_status_t status;
1133 cairo_extend_t extend;
1134 cairo_matrix_t *m, matrix;
1136 cairo_surface_t *blurred_surface;
1138 TRACE ((stderr, "%s\n", __FUNCTION__));
1142 source = _cairo_pattern_get_source (pattern, &limit);
1144 extend = pattern->base.extend;
1145 if (_cairo_rectangle_contains_rectangle (&limit, sample))
1146 extend = CAIRO_EXTEND_NONE;
1147 if (extend == CAIRO_EXTEND_NONE) {
1148 if (! _cairo_rectangle_intersect (&limit, sample))
1149 return _pixman_transparent_image ();
1151 if (! _cairo_matrix_is_identity (&pattern->base.matrix)) {
1152 double x1, y1, x2, y2;
1154 matrix = pattern->base.matrix;
1155 status = cairo_matrix_invert (&matrix);
1156 assert (status == CAIRO_STATUS_SUCCESS);
1160 x2 = limit.x + limit.width;
1161 y2 = limit.y + limit.height;
1163 _cairo_matrix_transform_bounding_box (&matrix,
1164 &x1, &y1, &x2, &y2, NULL);
1166 limit.x = floor (x1);
1167 limit.y = floor (y1);
1168 limit.width = ceil (x2) - limit.x;
1169 limit.height = ceil (y2) - limit.y;
1175 /* XXX transformations! */
1176 proxy = _cairo_surface_has_snapshot (source, &proxy_backend);
1177 if (proxy != NULL) {
1178 clone = cairo_surface_reference (get_proxy (proxy));
1183 clone = cairo_image_surface_create (CAIRO_FORMAT_A8,
1184 limit.width, limit.height);
1186 if (dst->base.content == source->content)
1187 clone = cairo_image_surface_create (dst->format,
1188 limit.width, limit.height);
1190 clone = _cairo_image_surface_create_with_content (source->content,
1196 if (extend == CAIRO_EXTEND_NONE) {
1197 matrix = pattern->base.matrix;
1199 cairo_matrix_translate (&matrix, tx, ty);
1202 /* XXX extract scale factor for repeating patterns */
1205 /* Handle recursion by returning future reads from the current image */
1206 proxy = attach_proxy (source, clone);
1207 status = _cairo_recording_surface_replay_with_clip (source, m, clone, NULL);
1208 detach_proxy (source, proxy);
1209 if (unlikely (status)) {
1210 cairo_surface_destroy (clone);
1215 /* filter with gaussian */
1216 blurred_surface = _cairo_image_gaussian_filter (clone, &pattern->base);
1218 pixman_image = pixman_image_ref (((cairo_image_surface_t *)blurred_surface)->pixman_image);
1219 cairo_surface_destroy (blurred_surface);
1220 cairo_surface_destroy (clone);
1224 if (extend != CAIRO_EXTEND_NONE) {
1225 if (! _pixman_image_set_properties (pixman_image,
1226 &pattern->base, extents,
1228 pixman_image_unref (pixman_image);
1233 return pixman_image;
1236 static pixman_image_t *
1237 _pixman_image_for_surface (cairo_image_surface_t *dst,
1238 const cairo_surface_pattern_t *pattern,
1239 cairo_bool_t is_mask,
1240 const cairo_rectangle_int_t *extents,
1241 const cairo_rectangle_int_t *sample,
1244 cairo_extend_t extend = pattern->base.extend;
1245 pixman_image_t *pixman_image = NULL;
1246 pixman_image_t *blurred_pixman_image = NULL;
1247 cairo_surface_t *blurred_surface = NULL;
1249 TRACE ((stderr, "%s\n", __FUNCTION__));
1252 pixman_image = NULL;
1253 if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
1254 return _pixman_image_for_recording(dst, pattern,
1255 is_mask, extents, sample,
1258 if (pattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE &&
1259 (! is_mask || ! pattern->base.has_component_alpha ||
1260 (pattern->surface->content & CAIRO_CONTENT_COLOR) == 0))
1262 cairo_surface_t *defer_free = NULL;
1263 cairo_image_surface_t *source = (cairo_image_surface_t *) pattern->surface;
1264 cairo_surface_type_t type;
1266 if (_cairo_surface_is_snapshot (&source->base)) {
1267 defer_free = _cairo_surface_snapshot_get_target (&source->base);
1268 source = (cairo_image_surface_t *) defer_free;
1271 type = source->base.backend->type;
1272 if (type == CAIRO_SURFACE_TYPE_IMAGE) {
1273 if (extend != CAIRO_EXTEND_NONE &&
1276 sample->x + sample->width <= source->width &&
1277 sample->y + sample->height <= source->height)
1279 extend = CAIRO_EXTEND_NONE;
1282 if (sample->width == 1 && sample->height == 1) {
1283 if (sample->x < 0 ||
1285 sample->x >= source->width ||
1286 sample->y >= source->height)
1288 if (extend == CAIRO_EXTEND_NONE) {
1289 cairo_surface_destroy (defer_free);
1290 return _pixman_transparent_image ();
1295 pixman_image = _pixel_to_solid (source,
1296 sample->x, sample->y);
1298 cairo_surface_destroy (defer_free);
1299 return pixman_image;
1304 #if PIXMAN_HAS_ATOMIC_OPS
1305 /* avoid allocating a 'pattern' image if we can reuse the original */
1306 if (extend == CAIRO_EXTEND_NONE &&
1307 _cairo_matrix_is_pixman_translation (&pattern->base.matrix,
1308 pattern->base.filter,
1311 cairo_surface_destroy (defer_free);
1312 /* filter with gaussian */
1313 if (pattern->filter == CAIRO_FILTER_GAUSSIAN) {
1314 blurred_surface = _cairo_image_gaussian_filter (&source->base, &pattern->base);
1315 blurred_pixman_image = pixman_image_ref (((cairo_image_surface_t *)blurred_surface)->pixman_image);
1316 cairo_surface_destroy (blurred_surface);
1317 return blurred_pixman_image;
1320 return pixman_image_ref (source->pixman_image);
1324 if (pattern->base.filter != CAIRO_FILTER_GAUSSIAN) {
1325 pixman_image = pixman_image_create_bits (source->pixman_format,
1328 (uint32_t *) source->data,
1330 if (unlikely (pixman_image == NULL)) {
1331 cairo_surface_destroy (defer_free);
1332 if (blurred_surface)
1333 cairo_surface_destroy (blurred_surface);
1334 if (blurred_pixman_image)
1335 pixman_image_unref (blurred_pixman_image);
1340 pixman_image_set_destroy_function (pixman_image,
1341 _defer_free_cleanup,
1346 blurred_surface = _cairo_image_gaussian_filter (&source->base, &pattern->base);
1347 } else if (type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
1348 cairo_surface_subsurface_t *sub;
1349 cairo_bool_t is_contained = FALSE;
1351 sub = (cairo_surface_subsurface_t *) source;
1352 source = (cairo_image_surface_t *) sub->target;
1354 if (sample->x >= 0 &&
1356 sample->x + sample->width <= sub->extents.width &&
1357 sample->y + sample->height <= sub->extents.height)
1359 is_contained = TRUE;
1362 if (sample->width == 1 && sample->height == 1) {
1364 pixman_image = _pixel_to_solid (source,
1365 sub->extents.x + sample->x,
1366 sub->extents.y + sample->y);
1368 return pixman_image;
1370 if (extend == CAIRO_EXTEND_NONE)
1371 return _pixman_transparent_image ();
1375 #if PIXMAN_HAS_ATOMIC_OPS
1376 *ix = sub->extents.x;
1377 *iy = sub->extents.y;
1379 _cairo_matrix_is_pixman_translation (&pattern->base.matrix,
1380 pattern->base.filter,
1383 /* filter with gaussian */
1384 if (pattern->filter == CAIRO_FILTER_GAUSSIAN) {
1385 blurred_surface = _cairo_image_gaussian_filter (&source->base, &pattern->base);
1386 blurred_pixman_image = pixman_image_ref (((cairo_image_surface_t *)blurred_surface)->pixman_image);
1387 cairo_surface_destroy (blurred_surface);
1388 return blurred_pixman_image;
1393 /* Avoid sub-byte offsets, force a copy in that case. */
1394 if (pattern->base.filter != CAIRO_FILTER_GAUSSIAN) {
1395 if (PIXMAN_FORMAT_BPP (source->pixman_format) >= 8) {
1397 void *data = source->data
1398 + sub->extents.x * PIXMAN_FORMAT_BPP(source->pixman_format)/8
1399 + sub->extents.y * source->stride;
1400 pixman_image = pixman_image_create_bits (source->pixman_format,
1402 sub->extents.height,
1405 if (unlikely (pixman_image == NULL)) {
1406 if (blurred_surface)
1407 cairo_surface_destroy (blurred_surface);
1408 if (blurred_pixman_image)
1409 pixman_image_unref (blurred_pixman_image);
1413 /* XXX for a simple translation and EXTEND_NONE we can
1414 * fix up the pattern matrix instead.
1421 blurred_surface = _cairo_image_gaussian_filter (&source->base, &pattern->base);
1425 if (pixman_image == NULL && blurred_surface == NULL) {
1426 struct acquire_source_cleanup *cleanup;
1427 cairo_image_surface_t *image;
1429 cairo_status_t status;
1431 status = _cairo_surface_acquire_source_image (pattern->surface, &image, &extra);
1432 if (unlikely (status)) {
1433 if (blurred_surface)
1434 cairo_surface_destroy (blurred_surface);
1435 if (blurred_pixman_image)
1436 pixman_image_unref (blurred_pixman_image);
1440 if (pattern->base.filter != CAIRO_FILTER_GAUSSIAN) {
1441 pixman_image = pixman_image_create_bits (image->pixman_format,
1444 (uint32_t *) image->data,
1446 if (unlikely (pixman_image == NULL)) {
1447 _cairo_surface_release_source_image (pattern->surface, image, extra);
1448 if (blurred_surface)
1449 cairo_surface_destroy (blurred_surface);
1450 if (blurred_pixman_image)
1451 pixman_image_unref (blurred_pixman_image);
1456 /* filter with gaussian */
1457 blurred_surface = _cairo_image_gaussian_filter (&image->base, &pattern->base);
1459 cleanup = malloc (sizeof (*cleanup));
1460 if (unlikely (cleanup == NULL)) {
1461 _cairo_surface_release_source_image (pattern->surface, image, extra);
1463 pixman_image_unref (pixman_image);
1464 if (blurred_surface)
1465 cairo_surface_destroy (blurred_surface);
1466 if (blurred_pixman_image)
1467 pixman_image_unref (blurred_pixman_image);
1472 cleanup->surface = pattern->surface;
1473 cleanup->image = image;
1474 cleanup->image_extra = extra;
1475 pixman_image_set_destroy_function (pixman_image,
1476 _acquire_source_cleanup, cleanup);
1480 if (blurred_surface) {
1481 blurred_pixman_image = pixman_image_ref (((cairo_image_surface_t *)blurred_surface)->pixman_image);
1482 cairo_surface_destroy (blurred_surface);
1485 if (blurred_pixman_image) {
1486 if (! _pixman_image_set_properties (blurred_pixman_image,
1487 &pattern->base, extents,
1489 pixman_image_unref (blurred_pixman_image);
1490 blurred_pixman_image= NULL;
1494 if (! _pixman_image_set_properties (pixman_image,
1495 &pattern->base, extents,
1497 pixman_image_unref (pixman_image);
1502 if (blurred_pixman_image) {
1504 pixman_image_unref (pixman_image);
1507 blurred_pixman_image = pixman_image;
1509 return blurred_pixman_image;
1512 struct raster_source_cleanup {
1513 const cairo_pattern_t *pattern;
1514 cairo_surface_t *surface;
1515 cairo_image_surface_t *image;
1520 _raster_source_cleanup (pixman_image_t *pixman_image,
1523 struct raster_source_cleanup *data = closure;
1525 _cairo_surface_release_source_image (data->surface,
1529 _cairo_raster_source_pattern_release (data->pattern,
1535 static pixman_image_t *
1536 _pixman_image_for_raster (cairo_image_surface_t *dst,
1537 const cairo_raster_source_pattern_t *pattern,
1538 cairo_bool_t is_mask,
1539 const cairo_rectangle_int_t *extents,
1540 const cairo_rectangle_int_t *sample,
1543 pixman_image_t *pixman_image;
1544 struct raster_source_cleanup *cleanup;
1545 cairo_image_surface_t *image;
1547 cairo_status_t status;
1548 cairo_surface_t *surface;
1550 TRACE ((stderr, "%s\n", __FUNCTION__));
1554 surface = _cairo_raster_source_pattern_acquire (&pattern->base,
1556 if (unlikely (surface == NULL || surface->status))
1559 status = _cairo_surface_acquire_source_image (surface, &image, &extra);
1560 if (unlikely (status)) {
1561 _cairo_raster_source_pattern_release (&pattern->base, surface);
1565 assert (image->width == pattern->extents.width);
1566 assert (image->height == pattern->extents.height);
1568 pixman_image = pixman_image_create_bits (image->pixman_format,
1571 (uint32_t *) image->data,
1573 if (unlikely (pixman_image == NULL)) {
1574 _cairo_surface_release_source_image (surface, image, extra);
1575 _cairo_raster_source_pattern_release (&pattern->base, surface);
1579 cleanup = malloc (sizeof (*cleanup));
1580 if (unlikely (cleanup == NULL)) {
1581 pixman_image_unref (pixman_image);
1582 _cairo_surface_release_source_image (surface, image, extra);
1583 _cairo_raster_source_pattern_release (&pattern->base, surface);
1587 cleanup->pattern = &pattern->base;
1588 cleanup->surface = surface;
1589 cleanup->image = image;
1590 cleanup->image_extra = extra;
1591 pixman_image_set_destroy_function (pixman_image,
1592 _raster_source_cleanup, cleanup);
1594 if (! _pixman_image_set_properties (pixman_image,
1595 &pattern->base, extents,
1597 pixman_image_unref (pixman_image);
1601 return pixman_image;
1605 _pixman_image_for_pattern (cairo_image_surface_t *dst,
1606 const cairo_pattern_t *pattern,
1607 cairo_bool_t is_mask,
1608 const cairo_rectangle_int_t *extents,
1609 const cairo_rectangle_int_t *sample,
1614 TRACE ((stderr, "%s\n", __FUNCTION__));
1616 if (pattern == NULL)
1617 return _pixman_white_image ();
1619 switch (pattern->type) {
1622 case CAIRO_PATTERN_TYPE_SOLID:
1623 return _pixman_image_for_color (&((const cairo_solid_pattern_t *) pattern)->color);
1625 case CAIRO_PATTERN_TYPE_RADIAL:
1626 case CAIRO_PATTERN_TYPE_LINEAR:
1627 return _pixman_image_for_gradient ((const cairo_gradient_pattern_t *) pattern,
1630 case CAIRO_PATTERN_TYPE_MESH:
1631 return _pixman_image_for_mesh ((const cairo_mesh_pattern_t *) pattern,
1634 case CAIRO_PATTERN_TYPE_SURFACE:
1635 return _pixman_image_for_surface (dst,
1636 (const cairo_surface_pattern_t *) pattern,
1637 is_mask, extents, sample,
1640 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
1641 return _pixman_image_for_raster (dst,
1642 (const cairo_raster_source_pattern_t *) pattern,
1643 is_mask, extents, sample,
1648 static cairo_status_t
1649 _cairo_image_source_finish (void *abstract_surface)
1651 cairo_image_source_t *source = abstract_surface;
1653 pixman_image_unref (source->pixman_image);
1654 return CAIRO_STATUS_SUCCESS;
1657 const cairo_surface_backend_t _cairo_image_source_backend = {
1658 CAIRO_SURFACE_TYPE_IMAGE,
1659 _cairo_image_source_finish,
1660 NULL, /* read-only wrapper */
1664 _cairo_image_source_create_for_pattern (cairo_surface_t *dst,
1665 const cairo_pattern_t *pattern,
1666 cairo_bool_t is_mask,
1667 const cairo_rectangle_int_t *extents,
1668 const cairo_rectangle_int_t *sample,
1669 int *src_x, int *src_y)
1671 cairo_image_source_t *source;
1673 TRACE ((stderr, "%s\n", __FUNCTION__));
1675 source = malloc (sizeof (cairo_image_source_t));
1676 if (unlikely (source == NULL))
1677 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1679 source->pixman_image =
1680 _pixman_image_for_pattern ((cairo_image_surface_t *)dst,
1684 if (unlikely (source->pixman_image == NULL)) {
1686 return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
1689 _cairo_surface_init (&source->base,
1690 &_cairo_image_source_backend,
1692 CAIRO_CONTENT_COLOR_ALPHA);
1694 source->is_opaque_solid =
1695 pattern == NULL || _cairo_pattern_is_opaque_solid (pattern);
1697 return &source->base;