tizen 2.3.1 release
[framework/graphics/cairo.git] / src / cairo-image-source.c
1 /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2 /* cairo - a vector graphics library with display and print output
3  *
4  * Copyright © 2003 University of Southern California
5  * Copyright © 2009,2010,2011 Intel Corporation
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it either under the terms of the GNU Lesser General Public
9  * License version 2.1 as published by the Free Software Foundation
10  * (the "LGPL") or, at your option, under the terms of the Mozilla
11  * Public License Version 1.1 (the "MPL"). If you do not alter this
12  * notice, a recipient may use your version of this file under either
13  * the MPL or the LGPL.
14  *
15  * You should have received a copy of the LGPL along with this library
16  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
18  * You should have received a copy of the MPL along with this library
19  * in the file COPYING-MPL-1.1
20  *
21  * The contents of this file are subject to the Mozilla Public License
22  * Version 1.1 (the "License"); you may not use this file except in
23  * compliance with the License. You may obtain a copy of the License at
24  * http://www.mozilla.org/MPL/
25  *
26  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28  * the specific language governing rights and limitations.
29  *
30  * The Original Code is the cairo graphics library.
31  *
32  * The Initial Developer of the Original Code is University of Southern
33  * California.
34  *
35  * Contributor(s):
36  *      Carl D. Worth <cworth@cworth.org>
37  *      Chris Wilson <chris@chris-wilson.co.uk>
38  */
39
40 /* The 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.
43  */
44
45 #include "cairoint.h"
46
47 #include "cairo-image-surface-private.h"
48
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"
58
59 #if CAIRO_HAS_TG_SURFACE
60 #include "cairo-tg-private.h"
61 #endif
62
63 #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
64
65 #if CAIRO_NO_MUTEX
66 #define PIXMAN_HAS_ATOMIC_OPS 1
67 #endif
68
69 #if PIXMAN_HAS_ATOMIC_OPS
70 static pixman_image_t *__pixman_transparent_image;
71 static pixman_image_t *__pixman_black_image;
72 static pixman_image_t *__pixman_white_image;
73
74 static pixman_image_t *
75 _pixman_transparent_image (void)
76 {
77     pixman_image_t *image;
78
79     TRACE ((stderr, "%s\n", __FUNCTION__));
80
81     image = __pixman_transparent_image;
82     if (unlikely (image == NULL)) {
83         pixman_color_t color;
84
85         color.red   = 0x00;
86         color.green = 0x00;
87         color.blue  = 0x00;
88         color.alpha = 0x00;
89
90         image = pixman_image_create_solid_fill (&color);
91         if (unlikely (image == NULL))
92             return NULL;
93
94         if (_cairo_atomic_ptr_cmpxchg (&__pixman_transparent_image,
95                                        NULL, image))
96         {
97             pixman_image_ref (image);
98         }
99     } else {
100         pixman_image_ref (image);
101     }
102
103     return image;
104 }
105
106 static pixman_image_t *
107 _pixman_black_image (void)
108 {
109     pixman_image_t *image;
110
111     TRACE ((stderr, "%s\n", __FUNCTION__));
112
113     image = __pixman_black_image;
114     if (unlikely (image == NULL)) {
115         pixman_color_t color;
116
117         color.red   = 0x00;
118         color.green = 0x00;
119         color.blue  = 0x00;
120         color.alpha = 0xffff;
121
122         image = pixman_image_create_solid_fill (&color);
123         if (unlikely (image == NULL))
124             return NULL;
125
126         if (_cairo_atomic_ptr_cmpxchg (&__pixman_black_image,
127                                        NULL, image))
128         {
129             pixman_image_ref (image);
130         }
131     } else {
132         pixman_image_ref (image);
133     }
134
135     return image;
136 }
137
138 static pixman_image_t *
139 _pixman_white_image (void)
140 {
141     pixman_image_t *image;
142
143     TRACE ((stderr, "%s\n", __FUNCTION__));
144
145     image = __pixman_white_image;
146     if (unlikely (image == NULL)) {
147         pixman_color_t color;
148
149         color.red   = 0xffff;
150         color.green = 0xffff;
151         color.blue  = 0xffff;
152         color.alpha = 0xffff;
153
154         image = pixman_image_create_solid_fill (&color);
155         if (unlikely (image == NULL))
156             return NULL;
157
158         if (_cairo_atomic_ptr_cmpxchg (&__pixman_white_image,
159                                        NULL, image))
160         {
161             pixman_image_ref (image);
162         }
163     } else {
164         pixman_image_ref (image);
165     }
166
167     return image;
168 }
169
170 static uint32_t
171 hars_petruska_f54_1_random (void)
172 {
173 #define rol(x,k) ((x << k) | (x >> (32-k)))
174     static uint32_t x;
175     return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
176 #undef rol
177 }
178
179 static struct {
180     cairo_color_t color;
181     pixman_image_t *image;
182 } cache[16];
183 static int n_cached;
184
185 #else  /* !PIXMAN_HAS_ATOMIC_OPS */
186 static pixman_image_t *
187 _pixman_transparent_image (void)
188 {
189     TRACE ((stderr, "%s\n", __FUNCTION__));
190     return _pixman_image_for_color (CAIRO_COLOR_TRANSPARENT);
191 }
192
193 static pixman_image_t *
194 _pixman_black_image (void)
195 {
196     TRACE ((stderr, "%s\n", __FUNCTION__));
197     return _pixman_image_for_color (CAIRO_COLOR_BLACK);
198 }
199
200 static pixman_image_t *
201 _pixman_white_image (void)
202 {
203     TRACE ((stderr, "%s\n", __FUNCTION__));
204     return _pixman_image_for_color (CAIRO_COLOR_WHITE);
205 }
206 #endif /* !PIXMAN_HAS_ATOMIC_OPS */
207
208
209 pixman_image_t *
210 _pixman_image_for_color (const cairo_color_t *cairo_color)
211 {
212     pixman_color_t color;
213     pixman_image_t *image;
214
215 #if PIXMAN_HAS_ATOMIC_OPS
216     int i;
217
218     if (CAIRO_COLOR_IS_CLEAR (cairo_color))
219         return _pixman_transparent_image ();
220
221     if (CAIRO_COLOR_IS_OPAQUE (cairo_color)) {
222         if (cairo_color->red_short <= 0x00ff &&
223             cairo_color->green_short <= 0x00ff &&
224             cairo_color->blue_short <= 0x00ff)
225         {
226             return _pixman_black_image ();
227         }
228
229         if (cairo_color->red_short >= 0xff00 &&
230             cairo_color->green_short >= 0xff00 &&
231             cairo_color->blue_short >= 0xff00)
232         {
233             return _pixman_white_image ();
234         }
235     }
236
237     CAIRO_MUTEX_LOCK (_cairo_image_solid_cache_mutex);
238     for (i = 0; i < n_cached; i++) {
239         if (_cairo_color_equal (&cache[i].color, cairo_color)) {
240             image = pixman_image_ref (cache[i].image);
241             goto UNLOCK;
242         }
243     }
244 #endif
245
246     color.red   = cairo_color->red_short;
247     color.green = cairo_color->green_short;
248     color.blue  = cairo_color->blue_short;
249     color.alpha = cairo_color->alpha_short;
250
251     image = pixman_image_create_solid_fill (&color);
252 #if PIXMAN_HAS_ATOMIC_OPS
253     if (image == NULL)
254         goto UNLOCK;
255
256     if (n_cached < ARRAY_LENGTH (cache)) {
257         i = n_cached++;
258     } else {
259         i = hars_petruska_f54_1_random () % ARRAY_LENGTH (cache);
260         pixman_image_unref (cache[i].image);
261     }
262     cache[i].image = pixman_image_ref (image);
263     cache[i].color = *cairo_color;
264
265 UNLOCK:
266     CAIRO_MUTEX_UNLOCK (_cairo_image_solid_cache_mutex);
267 #endif
268     return image;
269 }
270
271
272 void
273 _cairo_image_reset_static_data (void)
274 {
275 #if PIXMAN_HAS_ATOMIC_OPS
276     while (n_cached)
277         pixman_image_unref (cache[--n_cached].image);
278
279     if (__pixman_transparent_image) {
280         pixman_image_unref (__pixman_transparent_image);
281         __pixman_transparent_image = NULL;
282     }
283
284     if (__pixman_black_image) {
285         pixman_image_unref (__pixman_black_image);
286         __pixman_black_image = NULL;
287     }
288
289     if (__pixman_white_image) {
290         pixman_image_unref (__pixman_white_image);
291         __pixman_white_image = NULL;
292     }
293 #endif
294 }
295
296 static pixman_image_t *
297 _pixman_image_for_gradient (const cairo_gradient_pattern_t *pattern,
298                             const cairo_rectangle_int_t *extents,
299                             int *ix, int *iy)
300 {
301     pixman_image_t        *pixman_image;
302     pixman_gradient_stop_t pixman_stops_static[2];
303     pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
304     pixman_transform_t      pixman_transform;
305     cairo_matrix_t matrix;
306     cairo_circle_double_t extremes[2];
307     pixman_point_fixed_t p1, p2;
308     unsigned int i;
309     cairo_int_status_t status;
310
311     TRACE ((stderr, "%s\n", __FUNCTION__));
312
313     if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
314         pixman_stops = _cairo_malloc_ab (pattern->n_stops,
315                                          sizeof(pixman_gradient_stop_t));
316         if (unlikely (pixman_stops == NULL))
317             return NULL;
318     }
319
320     for (i = 0; i < pattern->n_stops; i++) {
321         pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
322         pixman_stops[i].color.red   = pattern->stops[i].color.red_short;
323         pixman_stops[i].color.green = pattern->stops[i].color.green_short;
324         pixman_stops[i].color.blue  = pattern->stops[i].color.blue_short;
325         pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
326     }
327
328     _cairo_gradient_pattern_fit_to_range (pattern, PIXMAN_MAX_INT >> 1, &matrix, extremes);
329
330     p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
331     p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
332     p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
333     p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
334
335     if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
336         pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
337                                                             pixman_stops,
338                                                             pattern->n_stops);
339     } else {
340         pixman_fixed_t r1, r2;
341
342         r1   = _cairo_fixed_16_16_from_double (extremes[0].radius);
343         r2   = _cairo_fixed_16_16_from_double (extremes[1].radius);
344
345         pixman_image = pixman_image_create_radial_gradient (&p1, &p2, r1, r2,
346                                                             pixman_stops,
347                                                             pattern->n_stops);
348     }
349
350     if (pixman_stops != pixman_stops_static)
351         free (pixman_stops);
352
353     if (unlikely (pixman_image == NULL))
354         return NULL;
355
356     *ix = *iy = 0;
357     status = _cairo_matrix_to_pixman_matrix_offset (&matrix, pattern->base.filter,
358                                                     extents->x + extents->width/2.,
359                                                     extents->y + extents->height/2.,
360                                                     &pixman_transform, ix, iy);
361     if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
362         if (unlikely (status != CAIRO_INT_STATUS_SUCCESS) ||
363             ! pixman_image_set_transform (pixman_image, &pixman_transform))
364         {
365             pixman_image_unref (pixman_image);
366             return NULL;
367         }
368     }
369
370     {
371         pixman_repeat_t pixman_repeat;
372
373         switch (pattern->base.extend) {
374         default:
375         case CAIRO_EXTEND_NONE:
376             pixman_repeat = PIXMAN_REPEAT_NONE;
377             break;
378         case CAIRO_EXTEND_REPEAT:
379             pixman_repeat = PIXMAN_REPEAT_NORMAL;
380             break;
381         case CAIRO_EXTEND_REFLECT:
382             pixman_repeat = PIXMAN_REPEAT_REFLECT;
383             break;
384         case CAIRO_EXTEND_PAD:
385             pixman_repeat = PIXMAN_REPEAT_PAD;
386             break;
387         }
388
389         pixman_image_set_repeat (pixman_image, pixman_repeat);
390     }
391
392     return pixman_image;
393 }
394
395 static pixman_image_t *
396 _pixman_image_for_mesh (const cairo_mesh_pattern_t *pattern,
397                         const cairo_rectangle_int_t *extents,
398                         int *tx, int *ty)
399 {
400     pixman_image_t *image;
401     int width, height;
402
403     TRACE ((stderr, "%s\n", __FUNCTION__));
404
405     *tx = -extents->x;
406     *ty = -extents->y;
407     width = extents->width;
408     height = extents->height;
409
410     image = pixman_image_create_bits (PIXMAN_a8r8g8b8, width, height, NULL, 0);
411     if (unlikely (image == NULL))
412         return NULL;
413
414     _cairo_mesh_pattern_rasterize (pattern,
415                                    pixman_image_get_data (image),
416                                    width, height,
417                                    pixman_image_get_stride (image),
418                                    *tx, *ty);
419     return image;
420 }
421
422 struct acquire_source_cleanup {
423     cairo_surface_t *surface;
424     cairo_image_surface_t *image;
425     void *image_extra;
426 };
427
428 static void
429 _acquire_source_cleanup (pixman_image_t *pixman_image,
430                          void *closure)
431 {
432     struct acquire_source_cleanup *data = closure;
433
434     _cairo_surface_release_source_image (data->surface,
435                                          data->image,
436                                          data->image_extra);
437     free (data);
438 }
439
440 static void
441 _defer_free_cleanup (pixman_image_t *pixman_image,
442                      void *closure)
443 {
444     cairo_surface_destroy (closure);
445 }
446
447 typedef struct _cairo_image_buffer
448 {
449     cairo_format_t          format;
450     unsigned char           *data;
451     int                     width;
452     int                     height;
453     int                     stride;
454     pixman_image_t          *pixman_image;
455     pixman_format_code_t    pixman_format;
456 } cairo_image_buffer_t;
457
458 static inline void
459 _get_image_buffer (cairo_surface_t *surface, cairo_image_buffer_t *image_buffer)
460 {
461     if (surface->backend->type == CAIRO_SURFACE_TYPE_IMAGE)
462     {
463         cairo_image_surface_t *image = (cairo_image_surface_t *)surface;
464
465         image_buffer->format = image->format;
466         image_buffer->data = image->data;
467         image_buffer->width = image->width;
468         image_buffer->height = image->height;
469         image_buffer->stride = image->stride;
470         image_buffer->pixman_image = image->pixman_image;
471         image_buffer->pixman_format = image->pixman_format;
472     }
473 #if CAIRO_HAS_TG_SURFACE
474     else if (surface->backend->type == CAIRO_SURFACE_TYPE_TG)
475     {
476         cairo_tg_surface_t *tg = (cairo_tg_surface_t *)surface;
477
478         image_buffer->format = tg->format;
479         image_buffer->data = tg->data;
480         image_buffer->width = tg->width;
481         image_buffer->height = tg->height;
482         image_buffer->stride = tg->stride;
483         image_buffer->pixman_image = ((cairo_image_surface_t *)(tg->image_surface))->pixman_image;
484         image_buffer->pixman_format = ((cairo_image_surface_t *)(tg->image_surface))->pixman_format;
485
486         /* flush the journal to make the memory image_buffer up-to-date. */
487         cairo_surface_flush (surface);
488     }
489 #endif
490 }
491
492 static uint16_t
493 expand_channel (uint16_t v, uint32_t bits)
494 {
495     int offset = 16 - bits;
496     while (offset > 0) {
497         v |= v >> bits;
498         offset -= bits;
499         bits += bits;
500     }
501     return v;
502 }
503
504 static pixman_image_t *
505 _pixel_to_solid (const cairo_image_buffer_t *image_buffer, int x, int y)
506 {
507     uint32_t pixel;
508     pixman_color_t color;
509
510     TRACE ((stderr, "%s\n", __FUNCTION__));
511
512     switch (image_buffer->format) {
513     default:
514     case CAIRO_FORMAT_INVALID:
515         ASSERT_NOT_REACHED;
516         return NULL;
517
518     case CAIRO_FORMAT_A1:
519         pixel = *(uint8_t *) (image_buffer->data + y * image_buffer->stride + x/8);
520         return pixel & (1 << (x&7)) ? _pixman_black_image () : _pixman_transparent_image ();
521
522     case CAIRO_FORMAT_A8:
523         color.alpha = *(uint8_t *) (image_buffer->data + y * image_buffer->stride + x);
524         color.alpha |= color.alpha << 8;
525         if (color.alpha == 0)
526             return _pixman_transparent_image ();
527         if (color.alpha == 0xffff)
528             return _pixman_black_image ();
529
530         color.red = color.green = color.blue = 0;
531         return pixman_image_create_solid_fill (&color);
532
533     case CAIRO_FORMAT_RGB16_565:
534         pixel = *(uint16_t *) (image_buffer->data + y * image_buffer->stride + 2 * x);
535         if (pixel == 0)
536             return _pixman_black_image ();
537         if (pixel == 0xffff)
538             return _pixman_white_image ();
539
540         color.alpha = 0xffff;
541         color.red = expand_channel ((pixel >> 11 & 0x1f) << 11, 5);
542         color.green = expand_channel ((pixel >> 5 & 0x3f) << 10, 6);
543         color.blue = expand_channel ((pixel & 0x1f) << 11, 5);
544         return pixman_image_create_solid_fill (&color);
545
546     case CAIRO_FORMAT_RGB30:
547         pixel = *(uint32_t *) (image_buffer->data + y * image_buffer->stride + 4 * x);
548         pixel &= 0x3fffffff; /* ignore alpha bits */
549         if (pixel == 0)
550             return _pixman_black_image ();
551         if (pixel == 0x3fffffff)
552             return _pixman_white_image ();
553
554         /* convert 10bpc to 16bpc */
555         color.alpha = 0xffff;
556         color.red = expand_channel((pixel >> 20) & 0x3fff, 10);
557         color.green = expand_channel((pixel >> 10) & 0x3fff, 10);
558         color.blue = expand_channel(pixel & 0x3fff, 10);
559         return pixman_image_create_solid_fill (&color);
560
561     case CAIRO_FORMAT_ARGB32:
562     case CAIRO_FORMAT_RGB24:
563         pixel = *(uint32_t *) (image_buffer->data + y * image_buffer->stride + 4 * x);
564         color.alpha = image_buffer->format == CAIRO_FORMAT_ARGB32 ? (pixel >> 24) | (pixel >> 16 & 0xff00) : 0xffff;
565         if (color.alpha == 0)
566             return _pixman_transparent_image ();
567         if (pixel == 0xffffffff)
568             return _pixman_white_image ();
569         if (color.alpha == 0xffff && (pixel & 0xffffff) == 0)
570             return _pixman_black_image ();
571
572         color.red = (pixel >> 16 & 0xff) | (pixel >> 8 & 0xff00);
573         color.green = (pixel >> 8 & 0xff) | (pixel & 0xff00);
574         color.blue = (pixel & 0xff) | (pixel << 8 & 0xff00);
575         return pixman_image_create_solid_fill (&color);
576     }
577 }
578
579 static cairo_bool_t
580 _pixman_image_set_properties (pixman_image_t *pixman_image,
581                               const cairo_pattern_t *pattern,
582                               const cairo_rectangle_int_t *extents,
583                               int *ix,int *iy)
584 {
585     pixman_transform_t pixman_transform;
586     cairo_int_status_t status;
587
588     status = _cairo_matrix_to_pixman_matrix_offset (&pattern->matrix,
589                                                     pattern->filter,
590                                                     extents->x + extents->width/2.,
591                                                     extents->y + extents->height/2.,
592                                                     &pixman_transform, ix, iy);
593     if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
594     {
595         /* If the transform is an identity, we don't need to set it
596          * and we can use any filtering, so choose the fastest one. */
597         pixman_image_set_filter (pixman_image, PIXMAN_FILTER_NEAREST, NULL, 0);
598     }
599     else if (unlikely (status != CAIRO_INT_STATUS_SUCCESS ||
600                        ! pixman_image_set_transform (pixman_image,
601                                                      &pixman_transform)))
602     {
603         return FALSE;
604     }
605     else
606     {
607         pixman_filter_t pixman_filter;
608
609         switch (pattern->filter) {
610         case CAIRO_FILTER_FAST:
611             pixman_filter = PIXMAN_FILTER_FAST;
612             break;
613         case CAIRO_FILTER_GOOD:
614             pixman_filter = PIXMAN_FILTER_GOOD;
615             break;
616         case CAIRO_FILTER_BEST:
617             pixman_filter = PIXMAN_FILTER_BEST;
618             break;
619         case CAIRO_FILTER_NEAREST:
620             pixman_filter = PIXMAN_FILTER_NEAREST;
621             break;
622         case CAIRO_FILTER_BILINEAR:
623             pixman_filter = PIXMAN_FILTER_BILINEAR;
624             break;
625         case CAIRO_FILTER_GAUSSIAN:
626             /* XXX: The GAUSSIAN value has no implementation in cairo
627              * whatsoever, so it was really a mistake to have it in the
628              * API. We could fix this by officially deprecating it, or
629              * else inventing semantics and providing an actual
630              * implementation for it. */
631         default:
632             pixman_filter = PIXMAN_FILTER_BEST;
633         }
634
635         pixman_image_set_filter (pixman_image, pixman_filter, NULL, 0);
636     }
637
638     {
639         pixman_repeat_t pixman_repeat;
640
641         switch (pattern->extend) {
642         default:
643         case CAIRO_EXTEND_NONE:
644             pixman_repeat = PIXMAN_REPEAT_NONE;
645             break;
646         case CAIRO_EXTEND_REPEAT:
647             pixman_repeat = PIXMAN_REPEAT_NORMAL;
648             break;
649         case CAIRO_EXTEND_REFLECT:
650             pixman_repeat = PIXMAN_REPEAT_REFLECT;
651             break;
652         case CAIRO_EXTEND_PAD:
653             pixman_repeat = PIXMAN_REPEAT_PAD;
654             break;
655         }
656
657         pixman_image_set_repeat (pixman_image, pixman_repeat);
658     }
659
660     if (pattern->has_component_alpha)
661         pixman_image_set_component_alpha (pixman_image, TRUE);
662
663     return TRUE;
664 }
665
666 struct proxy {
667     cairo_surface_t base;
668     cairo_surface_t *image;
669 };
670
671 static cairo_status_t
672 proxy_acquire_source_image (void                         *abstract_surface,
673                             cairo_image_surface_t       **image_out,
674                             void                        **image_extra)
675 {
676     struct proxy *proxy = abstract_surface;
677     return _cairo_surface_acquire_source_image (proxy->image, image_out, image_extra);
678 }
679
680 static void
681 proxy_release_source_image (void                        *abstract_surface,
682                             cairo_image_surface_t       *image,
683                             void                        *image_extra)
684 {
685     struct proxy *proxy = abstract_surface;
686     _cairo_surface_release_source_image (proxy->image, image, image_extra);
687 }
688
689 static cairo_status_t
690 proxy_finish (void *abstract_surface)
691 {
692     return CAIRO_STATUS_SUCCESS;
693 }
694
695 static const cairo_surface_backend_t proxy_backend  = {
696     CAIRO_INTERNAL_SURFACE_TYPE_NULL,
697     proxy_finish,
698     NULL,
699
700     NULL, /* create similar */
701     NULL, /* create similar image */
702     NULL, /* map to image */
703     NULL, /* unmap image */
704
705     _cairo_surface_default_source,
706     proxy_acquire_source_image,
707     proxy_release_source_image,
708 };
709
710 static cairo_surface_t *
711 attach_proxy (cairo_surface_t *source,
712               cairo_surface_t *image)
713 {
714     struct proxy *proxy;
715
716     proxy = malloc (sizeof (*proxy));
717     if (unlikely (proxy == NULL))
718         return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
719
720     _cairo_surface_init (&proxy->base, &proxy_backend, NULL, image->content);
721
722     proxy->image = image;
723     _cairo_surface_attach_snapshot (source, &proxy->base, NULL);
724
725     return &proxy->base;
726 }
727
728 static void
729 detach_proxy (cairo_surface_t *source,
730               cairo_surface_t *proxy)
731 {
732     cairo_surface_finish (proxy);
733     cairo_surface_destroy (proxy);
734 }
735
736 static cairo_surface_t *
737 get_proxy (cairo_surface_t *proxy)
738 {
739     return ((struct proxy *)proxy)->image;
740 }
741
742 static pixman_image_t *
743 _pixman_image_for_recording (cairo_image_surface_t *dst,
744                              const cairo_surface_pattern_t *pattern,
745                              cairo_bool_t is_mask,
746                              const cairo_rectangle_int_t *extents,
747                              const cairo_rectangle_int_t *sample,
748                              int *ix, int *iy)
749 {
750     cairo_surface_t *source, *clone, *proxy;
751     cairo_rectangle_int_t limit;
752     pixman_image_t *pixman_image;
753     cairo_status_t status;
754     cairo_extend_t extend;
755     cairo_matrix_t *m, matrix;
756     int tx = 0, ty = 0;
757     cairo_surface_t *blurred_surface;
758
759     TRACE ((stderr, "%s\n", __FUNCTION__));
760
761     *ix = *iy = 0;
762
763     source = _cairo_pattern_get_source (pattern, &limit);
764
765     extend = pattern->base.extend;
766     if (_cairo_rectangle_contains_rectangle (&limit, sample))
767         extend = CAIRO_EXTEND_NONE;
768     if (extend == CAIRO_EXTEND_NONE) {
769         if (! _cairo_rectangle_intersect (&limit, sample))
770             return _pixman_transparent_image ();
771
772         if (! _cairo_matrix_is_identity (&pattern->base.matrix)) {
773             double x1, y1, x2, y2;
774
775             matrix = pattern->base.matrix;
776             status = cairo_matrix_invert (&matrix);
777             assert (status == CAIRO_STATUS_SUCCESS);
778
779             x1 = limit.x;
780             y1 = limit.y;
781             x2 = limit.x + limit.width;
782             y2 = limit.y + limit.height;
783
784             _cairo_matrix_transform_bounding_box (&matrix,
785                                                   &x1, &y1, &x2, &y2, NULL);
786
787             limit.x = floor (x1);
788             limit.y = floor (y1);
789             limit.width  = ceil (x2) - limit.x;
790             limit.height = ceil (y2) - limit.y;
791         }
792     }
793     tx = limit.x;
794     ty = limit.y;
795
796     /* XXX transformations! */
797     proxy = _cairo_surface_has_snapshot (source, &proxy_backend);
798     if (proxy != NULL) {
799         clone = cairo_surface_reference (get_proxy (proxy));
800         goto done;
801     }
802
803     if (is_mask) {
804             clone = cairo_image_surface_create (CAIRO_FORMAT_A8,
805                                                 limit.width, limit.height);
806     } else {
807         if (dst->base.content == source->content)
808             clone = cairo_image_surface_create (dst->format,
809                                                 limit.width, limit.height);
810         else
811             clone = _cairo_image_surface_create_with_content (source->content,
812                                                               limit.width,
813                                                               limit.height);
814     }
815
816     m = NULL;
817     if (extend == CAIRO_EXTEND_NONE) {
818         matrix = pattern->base.matrix;
819         if (tx | ty)
820             cairo_matrix_translate (&matrix, tx, ty);
821         m = &matrix;
822     } else {
823         /* XXX extract scale factor for repeating patterns */
824     }
825
826     /* Handle recursion by returning future reads from the current image */
827     proxy = attach_proxy (source, clone);
828     status = _cairo_recording_surface_replay_with_clip (source, m, clone, NULL);
829     detach_proxy (source, proxy);
830     if (unlikely (status)) {
831         cairo_surface_destroy (clone);
832         return NULL;
833     }
834
835 done:
836     /* filter with gaussian */
837     blurred_surface = _cairo_image_gaussian_filter (clone,  &pattern->base);
838
839     pixman_image = pixman_image_ref (((cairo_image_surface_t *)blurred_surface)->pixman_image);
840     cairo_surface_destroy (blurred_surface);
841     cairo_surface_destroy (clone);
842
843     *ix = -limit.x;
844     *iy = -limit.y;
845     if (extend != CAIRO_EXTEND_NONE) {
846         if (! _pixman_image_set_properties (pixman_image,
847                                             &pattern->base, extents,
848                                             ix, iy)) {
849             pixman_image_unref (pixman_image);
850             pixman_image= NULL;
851         }
852     }
853
854     return pixman_image;
855 }
856
857 static inline cairo_bool_t
858 _surface_type_is_image_buffer (cairo_surface_type_t type)
859 {
860 #if CAIRO_HAS_TG_SURFACE
861     return type == CAIRO_SURFACE_TYPE_IMAGE || type == CAIRO_SURFACE_TYPE_TG;
862 #else
863     return type == CAIRO_SURFACE_TYPE_IMAGE;
864 #endif
865 }
866
867 static pixman_image_t *
868 _pixman_image_for_surface (cairo_image_surface_t *dst,
869                            const cairo_surface_pattern_t *pattern,
870                            cairo_bool_t is_mask,
871                            const cairo_rectangle_int_t *extents,
872                            const cairo_rectangle_int_t *sample,
873                            int *ix, int *iy)
874 {
875     cairo_extend_t extend = pattern->base.extend;
876     pixman_image_t *pixman_image = NULL;
877     pixman_image_t *blurred_pixman_image = NULL;
878     cairo_surface_t *blurred_surface = NULL;
879
880     TRACE ((stderr, "%s\n", __FUNCTION__));
881
882     *ix = *iy = 0;
883     pixman_image = NULL;
884     if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
885         return _pixman_image_for_recording(dst, pattern,
886                                            is_mask, extents, sample,
887                                            ix, iy);
888
889     if (_surface_type_is_image_buffer (pattern->surface->type) &&
890         (! is_mask || ! pattern->base.has_component_alpha ||
891          (pattern->surface->content & CAIRO_CONTENT_COLOR) == 0))
892     {
893         cairo_surface_t *defer_free = NULL;
894         cairo_image_surface_t *source = (cairo_image_surface_t *) pattern->surface;
895         cairo_image_buffer_t image_buffer;
896
897         if (_cairo_surface_is_snapshot (&source->base)) {
898             defer_free = _cairo_surface_snapshot_get_target (&source->base);
899             source = (cairo_image_surface_t *) defer_free;
900         }
901
902         if (_surface_type_is_image_buffer (source->base.backend->type)) {
903             _get_image_buffer (source, &image_buffer);
904
905             if (extend != CAIRO_EXTEND_NONE &&
906                 sample->x >= 0 &&
907                 sample->y >= 0 &&
908                 sample->x + sample->width  <= image_buffer.width &&
909                 sample->y + sample->height <= image_buffer.height)
910             {
911                 extend = CAIRO_EXTEND_NONE;
912             }
913
914             if (sample->width == 1 && sample->height == 1) {
915                 if (sample->x < 0 ||
916                     sample->y < 0 ||
917                     sample->x >= image_buffer.width ||
918                     sample->y >= image_buffer.height)
919                 {
920                     if (extend == CAIRO_EXTEND_NONE) {
921                         cairo_surface_destroy (defer_free);
922                         return _pixman_transparent_image ();
923                     }
924                 }
925                 else
926                 {
927                     pixman_image = _pixel_to_solid (&image_buffer, sample->x, sample->y);
928                     if (pixman_image) {
929                         cairo_surface_destroy (defer_free);
930                         return pixman_image;
931                     }
932                 }
933             }
934
935 #if PIXMAN_HAS_ATOMIC_OPS
936             /* avoid allocating a 'pattern' image if we can reuse the original */
937             if (extend == CAIRO_EXTEND_NONE &&
938                 _cairo_matrix_is_pixman_translation (&pattern->base.matrix,
939                                                      pattern->base.filter,
940                                                      ix, iy))
941             {
942                 cairo_surface_destroy (defer_free);
943                 /* filter with gaussian */
944                 if (pattern->filter == CAIRO_FILTER_GAUSSIAN) {
945                     blurred_surface = _cairo_image_gaussian_filter (&source->base,  &pattern->base);
946                     blurred_pixman_image = pixman_image_ref (((cairo_image_surface_t *)blurred_surface)->pixman_image);
947                     cairo_surface_destroy (blurred_surface);
948                     return blurred_pixman_image;
949                 }
950                 else
951                 return pixman_image_ref (image_buffer.pixman_image);
952             }
953 #endif
954
955             if (pattern->base.filter != CAIRO_FILTER_GAUSSIAN) {
956             pixman_image = pixman_image_create_bits (image_buffer.pixman_format,
957                                                      image_buffer.width,
958                                                      image_buffer.height,
959                                                      (uint32_t *) image_buffer.data,
960                                                      image_buffer.stride);
961                 if (unlikely (pixman_image == NULL)) {
962                     cairo_surface_destroy (defer_free);
963                     if (blurred_surface)
964                     cairo_surface_destroy (blurred_surface);
965                     if (blurred_pixman_image)
966                         pixman_image_unref (blurred_pixman_image);
967                     return NULL;
968                 }
969
970                 if (defer_free) {
971                     pixman_image_set_destroy_function (pixman_image,
972                                                        _defer_free_cleanup,
973                                                        defer_free);
974                 }
975             }
976             else
977                 blurred_surface = _cairo_image_gaussian_filter (&source->base,  &pattern->base);
978         } else if (source->base.backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
979             cairo_surface_subsurface_t *sub;
980             cairo_bool_t is_contained = FALSE;
981
982             sub = (cairo_surface_subsurface_t *) source;
983             source = sub->target;
984
985             _get_image_buffer (source, &image_buffer);
986
987             if (sample->x >= 0 &&
988                 sample->y >= 0 &&
989                 sample->x + sample->width  <= sub->extents.width &&
990                 sample->y + sample->height <= sub->extents.height)
991             {
992                 is_contained = TRUE;
993             }
994
995             if (sample->width == 1 && sample->height == 1) {
996                 if (is_contained) {
997                     pixman_image = _pixel_to_solid (&image_buffer,
998                                                     sub->extents.x + sample->x,
999                                                     sub->extents.y + sample->y);
1000                     if (pixman_image)
1001                         return pixman_image;
1002                 } else {
1003                     if (extend == CAIRO_EXTEND_NONE)
1004                         return _pixman_transparent_image ();
1005                 }
1006             }
1007
1008 #if PIXMAN_HAS_ATOMIC_OPS
1009             *ix = sub->extents.x;
1010             *iy = sub->extents.y;
1011             if (is_contained &&
1012                 _cairo_matrix_is_pixman_translation (&pattern->base.matrix,
1013                                                      pattern->base.filter,
1014                                                      ix, iy))
1015             {
1016                 /* filter with gaussian */
1017                 if (pattern->filter == CAIRO_FILTER_GAUSSIAN) {
1018                     blurred_surface = _cairo_image_gaussian_filter (&source->base,  &pattern->base);
1019                     blurred_pixman_image = pixman_image_ref (((cairo_image_surface_t *)blurred_surface)->pixman_image);
1020                     cairo_surface_destroy (blurred_surface);
1021                     return blurred_pixman_image;
1022                 }
1023             }
1024 #endif
1025
1026             /* Avoid sub-byte offsets, force a copy in that case. */
1027             if (pattern->base.filter != CAIRO_FILTER_GAUSSIAN) {
1028             if (PIXMAN_FORMAT_BPP (image_buffer.pixman_format) >= 8) {
1029                 if (is_contained) {
1030                     void *data = image_buffer.data
1031                         + sub->extents.x * PIXMAN_FORMAT_BPP(image_buffer.pixman_format)/8
1032                         + sub->extents.y * image_buffer.stride;
1033                     pixman_image = pixman_image_create_bits (image_buffer.pixman_format,
1034                                                              sub->extents.width,
1035                                                              sub->extents.height,
1036                                                              data,
1037                                                              image_buffer.stride);
1038                         if (unlikely (pixman_image == NULL)) {
1039                             if (blurred_surface)
1040                                 cairo_surface_destroy (blurred_surface);
1041                             if (blurred_pixman_image)
1042                                 pixman_image_unref (blurred_pixman_image);
1043                             return NULL;
1044                         }
1045                     } else {
1046                     /* XXX for a simple translation and EXTEND_NONE we can
1047                      * fix up the pattern matrix instead.
1048                      */
1049                     }
1050                 }
1051             }
1052             else
1053             /* filter */
1054                 blurred_surface = _cairo_image_gaussian_filter (&source->base,  &pattern->base);
1055         }
1056     }
1057
1058     if (pixman_image == NULL && blurred_surface == NULL) {
1059         struct acquire_source_cleanup *cleanup;
1060         cairo_image_surface_t *image;
1061         void *extra;
1062         cairo_status_t status;
1063
1064         status = _cairo_surface_acquire_source_image (pattern->surface, &image, &extra);
1065         if (unlikely (status)) {
1066             if (blurred_surface)
1067                 cairo_surface_destroy (blurred_surface);
1068             if (blurred_pixman_image)
1069                 pixman_image_unref (blurred_pixman_image);
1070             return NULL;
1071         }
1072
1073         if (pattern->base.filter != CAIRO_FILTER_GAUSSIAN) {
1074             pixman_image = pixman_image_create_bits (image->pixman_format,
1075                                                      image->width,
1076                                                      image->height,
1077                                                      (uint32_t *) image->data,
1078                                                      image->stride);
1079             if (unlikely (pixman_image == NULL)) {
1080                 _cairo_surface_release_source_image (pattern->surface, image, extra);
1081                 if (blurred_surface)
1082                     cairo_surface_destroy (blurred_surface);
1083                 if (blurred_pixman_image)
1084                     pixman_image_unref (blurred_pixman_image);
1085                 return NULL;
1086             }
1087         }
1088         else
1089         /* filter with gaussian */
1090                 blurred_surface = _cairo_image_gaussian_filter (&image->base,  &pattern->base);
1091
1092         cleanup = malloc (sizeof (*cleanup));
1093         if (unlikely (cleanup == NULL)) {
1094             _cairo_surface_release_source_image (pattern->surface, image, extra);
1095             if (pixman_image)
1096                 pixman_image_unref (pixman_image);
1097             if (blurred_surface)
1098                 cairo_surface_destroy (blurred_surface);
1099             if (blurred_pixman_image)
1100                 pixman_image_unref (blurred_pixman_image);
1101             return NULL;
1102         }
1103
1104         if (pixman_image) {
1105             cleanup->surface = pattern->surface;
1106             cleanup->image = image;
1107             cleanup->image_extra = extra;
1108             pixman_image_set_destroy_function (pixman_image,
1109                                                _acquire_source_cleanup, cleanup);
1110         }
1111     }
1112
1113     if (blurred_surface) {
1114         blurred_pixman_image = pixman_image_ref (((cairo_image_surface_t *)blurred_surface)->pixman_image);
1115         cairo_surface_destroy (blurred_surface);
1116     }
1117
1118     if (blurred_pixman_image) {
1119         if (! _pixman_image_set_properties (blurred_pixman_image,
1120                                             &pattern->base, extents,
1121                                             ix, iy)) {
1122             pixman_image_unref (blurred_pixman_image);
1123             blurred_pixman_image= NULL;
1124         }
1125     }
1126     if (pixman_image) {
1127         if (! _pixman_image_set_properties (pixman_image,
1128                                             &pattern->base, extents,
1129                                             ix, iy)) {
1130             pixman_image_unref (pixman_image);
1131             pixman_image= NULL;
1132         }
1133     }
1134
1135     if (blurred_pixman_image) {
1136         if (pixman_image)
1137             pixman_image_unref (pixman_image);
1138     }
1139     else
1140         blurred_pixman_image = pixman_image;
1141
1142     return blurred_pixman_image;
1143 }
1144
1145 struct raster_source_cleanup {
1146     const cairo_pattern_t *pattern;
1147     cairo_surface_t *surface;
1148     cairo_image_surface_t *image;
1149     void *image_extra;
1150 };
1151
1152 static void
1153 _raster_source_cleanup (pixman_image_t *pixman_image,
1154                         void *closure)
1155 {
1156     struct raster_source_cleanup *data = closure;
1157
1158     _cairo_surface_release_source_image (data->surface,
1159                                          data->image,
1160                                          data->image_extra);
1161
1162     _cairo_raster_source_pattern_release (data->pattern,
1163                                           data->surface);
1164
1165     free (data);
1166 }
1167
1168 static pixman_image_t *
1169 _pixman_image_for_raster (cairo_image_surface_t *dst,
1170                           const cairo_raster_source_pattern_t *pattern,
1171                           cairo_bool_t is_mask,
1172                           const cairo_rectangle_int_t *extents,
1173                           const cairo_rectangle_int_t *sample,
1174                           int *ix, int *iy)
1175 {
1176     pixman_image_t *pixman_image;
1177     struct raster_source_cleanup *cleanup;
1178     cairo_image_surface_t *image;
1179     void *extra;
1180     cairo_status_t status;
1181     cairo_surface_t *surface;
1182
1183     TRACE ((stderr, "%s\n", __FUNCTION__));
1184
1185     *ix = *iy = 0;
1186
1187     surface = _cairo_raster_source_pattern_acquire (&pattern->base,
1188                                                     &dst->base, NULL);
1189     if (unlikely (surface == NULL || surface->status))
1190         return NULL;
1191
1192     status = _cairo_surface_acquire_source_image (surface, &image, &extra);
1193     if (unlikely (status)) {
1194         _cairo_raster_source_pattern_release (&pattern->base, surface);
1195         return NULL;
1196     }
1197
1198     assert (image->width == pattern->extents.width);
1199     assert (image->height == pattern->extents.height);
1200
1201     pixman_image = pixman_image_create_bits (image->pixman_format,
1202                                              image->width,
1203                                              image->height,
1204                                              (uint32_t *) image->data,
1205                                              image->stride);
1206     if (unlikely (pixman_image == NULL)) {
1207         _cairo_surface_release_source_image (surface, image, extra);
1208         _cairo_raster_source_pattern_release (&pattern->base, surface);
1209         return NULL;
1210     }
1211
1212     cleanup = malloc (sizeof (*cleanup));
1213     if (unlikely (cleanup == NULL)) {
1214         pixman_image_unref (pixman_image);
1215         _cairo_surface_release_source_image (surface, image, extra);
1216         _cairo_raster_source_pattern_release (&pattern->base, surface);
1217         return NULL;
1218     }
1219
1220     cleanup->pattern = &pattern->base;
1221     cleanup->surface = surface;
1222     cleanup->image = image;
1223     cleanup->image_extra = extra;
1224     pixman_image_set_destroy_function (pixman_image,
1225                                        _raster_source_cleanup, cleanup);
1226
1227     if (! _pixman_image_set_properties (pixman_image,
1228                                         &pattern->base, extents,
1229                                         ix, iy)) {
1230         pixman_image_unref (pixman_image);
1231         pixman_image= NULL;
1232     }
1233
1234     return pixman_image;
1235 }
1236
1237 pixman_image_t *
1238 _pixman_image_for_pattern (cairo_image_surface_t *dst,
1239                            const cairo_pattern_t *pattern,
1240                            cairo_bool_t is_mask,
1241                            const cairo_rectangle_int_t *extents,
1242                            const cairo_rectangle_int_t *sample,
1243                            int *tx, int *ty)
1244 {
1245     *tx = *ty = 0;
1246
1247     TRACE ((stderr, "%s\n", __FUNCTION__));
1248
1249     if (pattern == NULL)
1250         return _pixman_white_image ();
1251
1252     switch (pattern->type) {
1253     default:
1254         ASSERT_NOT_REACHED;
1255     case CAIRO_PATTERN_TYPE_SOLID:
1256         return _pixman_image_for_color (&((const cairo_solid_pattern_t *) pattern)->color);
1257
1258     case CAIRO_PATTERN_TYPE_RADIAL:
1259     case CAIRO_PATTERN_TYPE_LINEAR:
1260         return _pixman_image_for_gradient ((const cairo_gradient_pattern_t *) pattern,
1261                                            extents, tx, ty);
1262
1263     case CAIRO_PATTERN_TYPE_MESH:
1264         return _pixman_image_for_mesh ((const cairo_mesh_pattern_t *) pattern,
1265                                            extents, tx, ty);
1266
1267     case CAIRO_PATTERN_TYPE_SURFACE:
1268         return _pixman_image_for_surface (dst,
1269                                           (const cairo_surface_pattern_t *) pattern,
1270                                           is_mask, extents, sample,
1271                                           tx, ty);
1272
1273     case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
1274         return _pixman_image_for_raster (dst,
1275                                          (const cairo_raster_source_pattern_t *) pattern,
1276                                          is_mask, extents, sample,
1277                                          tx, ty);
1278     }
1279 }
1280
1281 static cairo_status_t
1282 _cairo_image_source_finish (void *abstract_surface)
1283 {
1284     cairo_image_source_t *source = abstract_surface;
1285
1286     pixman_image_unref (source->pixman_image);
1287     return CAIRO_STATUS_SUCCESS;
1288 }
1289
1290 const cairo_surface_backend_t _cairo_image_source_backend = {
1291     CAIRO_SURFACE_TYPE_IMAGE,
1292     _cairo_image_source_finish,
1293     NULL, /* read-only wrapper */
1294 };
1295
1296 cairo_surface_t *
1297 _cairo_image_source_create_for_pattern (cairo_surface_t *dst,
1298                                          const cairo_pattern_t *pattern,
1299                                          cairo_bool_t is_mask,
1300                                          const cairo_rectangle_int_t *extents,
1301                                          const cairo_rectangle_int_t *sample,
1302                                          int *src_x, int *src_y)
1303 {
1304     cairo_image_source_t *source;
1305
1306     TRACE ((stderr, "%s\n", __FUNCTION__));
1307
1308     source = malloc (sizeof (cairo_image_source_t));
1309     if (unlikely (source == NULL))
1310         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1311
1312     source->pixman_image =
1313         _pixman_image_for_pattern ((cairo_image_surface_t *)dst,
1314                                    pattern, is_mask,
1315                                    extents, sample,
1316                                    src_x, src_y);
1317     if (unlikely (source->pixman_image == NULL)) {
1318         free (source);
1319         return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
1320     }
1321
1322     _cairo_surface_init (&source->base,
1323                          &_cairo_image_source_backend,
1324                          NULL, /* device */
1325                          CAIRO_CONTENT_COLOR_ALPHA);
1326
1327     source->is_opaque_solid =
1328         pattern == NULL || _cairo_pattern_is_opaque_solid (pattern);
1329
1330     return &source->base;
1331 }