Coverage Report

Created: 2025-12-31 07:23

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cairo/src/cairo-image-source.c
Line
Count
Source
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
58
12
#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
59
60
#if CAIRO_NO_MUTEX
61
#define PIXMAN_HAS_ATOMIC_OPS 1
62
#endif
63
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;
68
69
static pixman_image_t *
70
_pixman_transparent_image (void)
71
{
72
    pixman_image_t *image;
73
74
    TRACE ((stderr, "%s\n", __FUNCTION__));
75
76
    image = __pixman_transparent_image;
77
    if (unlikely (image == NULL)) {
78
  pixman_color_t color;
79
80
  color.red   = 0x00;
81
  color.green = 0x00;
82
  color.blue  = 0x00;
83
  color.alpha = 0x00;
84
85
  image = pixman_image_create_solid_fill (&color);
86
  if (unlikely (image == NULL))
87
      return NULL;
88
89
  if (_cairo_atomic_ptr_cmpxchg (&__pixman_transparent_image,
90
               NULL, image))
91
  {
92
      pixman_image_ref (image);
93
  }
94
    } else {
95
  pixman_image_ref (image);
96
    }
97
98
    return image;
99
}
100
101
static pixman_image_t *
102
_pixman_black_image (void)
103
{
104
    pixman_image_t *image;
105
106
    TRACE ((stderr, "%s\n", __FUNCTION__));
107
108
    image = __pixman_black_image;
109
    if (unlikely (image == NULL)) {
110
  pixman_color_t color;
111
112
  color.red   = 0x00;
113
  color.green = 0x00;
114
  color.blue  = 0x00;
115
  color.alpha = 0xffff;
116
117
  image = pixman_image_create_solid_fill (&color);
118
  if (unlikely (image == NULL))
119
      return NULL;
120
121
  if (_cairo_atomic_ptr_cmpxchg (&__pixman_black_image,
122
               NULL, image))
123
  {
124
      pixman_image_ref (image);
125
  }
126
    } else {
127
  pixman_image_ref (image);
128
    }
129
130
    return image;
131
}
132
133
static pixman_image_t *
134
_pixman_white_image (void)
135
{
136
    pixman_image_t *image;
137
138
    TRACE ((stderr, "%s\n", __FUNCTION__));
139
140
    image = __pixman_white_image;
141
    if (unlikely (image == NULL)) {
142
  pixman_color_t color;
143
144
  color.red   = 0xffff;
145
  color.green = 0xffff;
146
  color.blue  = 0xffff;
147
  color.alpha = 0xffff;
148
149
  image = pixman_image_create_solid_fill (&color);
150
  if (unlikely (image == NULL))
151
      return NULL;
152
153
  if (_cairo_atomic_ptr_cmpxchg (&__pixman_white_image,
154
               NULL, image))
155
  {
156
      pixman_image_ref (image);
157
  }
158
    } else {
159
  pixman_image_ref (image);
160
    }
161
162
    return image;
163
}
164
165
static uint32_t
166
hars_petruska_f54_1_random (void)
167
{
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
172
}
173
174
static struct {
175
    cairo_color_t color;
176
    pixman_image_t *image;
177
} cache[16];
178
static int n_cached;
179
180
#else  /* !PIXMAN_HAS_ATOMIC_OPS */
181
static pixman_image_t *
182
_pixman_transparent_image (void)
183
0
{
184
0
    TRACE ((stderr, "%s\n", __FUNCTION__));
185
0
    return _pixman_image_for_color (CAIRO_COLOR_TRANSPARENT);
186
0
}
187
188
static pixman_image_t *
189
_pixman_black_image (void)
190
0
{
191
0
    TRACE ((stderr, "%s\n", __FUNCTION__));
192
0
    return _pixman_image_for_color (CAIRO_COLOR_BLACK);
193
0
}
194
195
static pixman_image_t *
196
_pixman_white_image (void)
197
0
{
198
0
    TRACE ((stderr, "%s\n", __FUNCTION__));
199
0
    return _pixman_image_for_color (CAIRO_COLOR_WHITE);
200
0
}
201
#endif /* !PIXMAN_HAS_ATOMIC_OPS */
202
203
204
pixman_image_t *
205
_pixman_image_for_color (const cairo_color_t *cairo_color)
206
24
{
207
24
    pixman_color_t color;
208
24
    pixman_image_t *image;
209
210
#if PIXMAN_HAS_ATOMIC_OPS
211
    int i;
212
213
    if (CAIRO_COLOR_IS_CLEAR (cairo_color))
214
  return _pixman_transparent_image ();
215
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)
220
  {
221
      return _pixman_black_image ();
222
  }
223
224
  if (cairo_color->red_short >= 0xff00 &&
225
      cairo_color->green_short >= 0xff00 &&
226
      cairo_color->blue_short >= 0xff00)
227
  {
228
      return _pixman_white_image ();
229
  }
230
    }
231
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;
237
  }
238
    }
239
#endif
240
241
24
    color.red   = cairo_color->red_short;
242
24
    color.green = cairo_color->green_short;
243
24
    color.blue  = cairo_color->blue_short;
244
24
    color.alpha = cairo_color->alpha_short;
245
246
24
    image = pixman_image_create_solid_fill (&color);
247
#if PIXMAN_HAS_ATOMIC_OPS
248
    if (image == NULL)
249
  goto UNLOCK;
250
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);
256
    }
257
    cache[i].image = pixman_image_ref (image);
258
    cache[i].color = *cairo_color;
259
260
UNLOCK:
261
    CAIRO_MUTEX_UNLOCK (_cairo_image_solid_cache_mutex);
262
#endif
263
24
    return image;
264
24
}
265
266
267
void
268
_cairo_image_reset_static_data (void)
269
0
{
270
#if PIXMAN_HAS_ATOMIC_OPS
271
    while (n_cached)
272
  pixman_image_unref (cache[--n_cached].image);
273
274
    if (__pixman_transparent_image) {
275
  pixman_image_unref (__pixman_transparent_image);
276
  __pixman_transparent_image = NULL;
277
    }
278
279
    if (__pixman_black_image) {
280
  pixman_image_unref (__pixman_black_image);
281
  __pixman_black_image = NULL;
282
    }
283
284
    if (__pixman_white_image) {
285
  pixman_image_unref (__pixman_white_image);
286
  __pixman_white_image = NULL;
287
    }
288
#endif
289
0
}
290
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)
295
12
{
296
12
    pixman_image_t    *pixman_image;
297
12
    pixman_gradient_stop_t pixman_stops_static[2];
298
12
    pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
299
12
    pixman_transform_t      pixman_transform;
300
12
    cairo_matrix_t matrix;
301
12
    cairo_circle_double_t extremes[2];
302
12
    pixman_point_fixed_t p1, p2;
303
12
    unsigned int i;
304
12
    cairo_int_status_t status;
305
306
12
    TRACE ((stderr, "%s\n", __FUNCTION__));
307
308
12
    if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
309
12
  pixman_stops = _cairo_malloc_ab (pattern->n_stops,
310
12
           sizeof(pixman_gradient_stop_t));
311
12
  if (unlikely (pixman_stops == NULL))
312
0
      return NULL;
313
12
    }
314
315
1.86k
    for (i = 0; i < pattern->n_stops; i++) {
316
1.85k
  pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
317
1.85k
  pixman_stops[i].color.red   = pattern->stops[i].color.red_short;
318
1.85k
  pixman_stops[i].color.green = pattern->stops[i].color.green_short;
319
1.85k
  pixman_stops[i].color.blue  = pattern->stops[i].color.blue_short;
320
1.85k
  pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
321
1.85k
    }
322
323
12
    _cairo_gradient_pattern_fit_to_range (pattern, PIXMAN_MAX_INT >> 1, &matrix, extremes);
324
325
12
    p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
326
12
    p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
327
12
    p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
328
12
    p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
329
330
12
    if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
331
12
  pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
332
12
                  pixman_stops,
333
12
                  pattern->n_stops);
334
12
    } else {
335
0
  pixman_fixed_t r1, r2;
336
337
0
  r1   = _cairo_fixed_16_16_from_double (extremes[0].radius);
338
0
  r2   = _cairo_fixed_16_16_from_double (extremes[1].radius);
339
340
0
  pixman_image = pixman_image_create_radial_gradient (&p1, &p2, r1, r2,
341
0
                  pixman_stops,
342
0
                  pattern->n_stops);
343
0
    }
344
345
12
    if (pixman_stops != pixman_stops_static)
346
12
  free (pixman_stops);
347
348
12
    if (unlikely (pixman_image == NULL))
349
0
  return NULL;
350
351
12
    *ix = *iy = 0;
352
12
    status = _cairo_matrix_to_pixman_matrix_offset (&matrix, pattern->base.filter,
353
12
                extents->x + extents->width/2.,
354
12
                extents->y + extents->height/2.,
355
12
                &pixman_transform, ix, iy);
356
12
    if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
357
12
  if (unlikely (status != CAIRO_INT_STATUS_SUCCESS) ||
358
12
      ! pixman_image_set_transform (pixman_image, &pixman_transform))
359
0
  {
360
0
      pixman_image_unref (pixman_image);
361
0
      return NULL;
362
0
  }
363
12
    }
364
365
12
    {
366
12
  pixman_repeat_t pixman_repeat;
367
368
12
  switch (pattern->base.extend) {
369
0
  default:
370
0
  case CAIRO_EXTEND_NONE:
371
0
      pixman_repeat = PIXMAN_REPEAT_NONE;
372
0
      break;
373
0
  case CAIRO_EXTEND_REPEAT:
374
0
      pixman_repeat = PIXMAN_REPEAT_NORMAL;
375
0
      break;
376
0
  case CAIRO_EXTEND_REFLECT:
377
0
      pixman_repeat = PIXMAN_REPEAT_REFLECT;
378
0
      break;
379
12
  case CAIRO_EXTEND_PAD:
380
12
      pixman_repeat = PIXMAN_REPEAT_PAD;
381
12
      break;
382
12
  }
383
384
12
  pixman_image_set_repeat (pixman_image, pixman_repeat);
385
12
    }
386
387
0
    return pixman_image;
388
12
}
389
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)
394
0
{
395
0
    pixman_image_t *image;
396
0
    int width, height;
397
398
0
    TRACE ((stderr, "%s\n", __FUNCTION__));
399
400
0
    *tx = -extents->x;
401
0
    *ty = -extents->y;
402
0
    width = extents->width;
403
0
    height = extents->height;
404
405
0
    image = pixman_image_create_bits (PIXMAN_a8r8g8b8, width, height, NULL, 0);
406
0
    if (unlikely (image == NULL))
407
0
  return NULL;
408
409
0
    _cairo_mesh_pattern_rasterize (pattern,
410
0
           pixman_image_get_data (image),
411
0
           width, height,
412
0
           pixman_image_get_stride (image),
413
0
           *tx, *ty);
414
0
    return image;
415
0
}
416
417
struct acquire_source_cleanup {
418
    cairo_surface_t *surface;
419
    cairo_image_surface_t *image;
420
    void *image_extra;
421
};
422
423
static void
424
_acquire_source_cleanup (pixman_image_t *pixman_image,
425
       void *closure)
426
0
{
427
0
    struct acquire_source_cleanup *data = closure;
428
429
0
    _cairo_surface_release_source_image (data->surface,
430
0
           data->image,
431
0
           data->image_extra);
432
0
    free (data);
433
0
}
434
435
static void
436
_defer_free_cleanup (pixman_image_t *pixman_image,
437
         void *closure)
438
28
{
439
28
    cairo_surface_destroy (closure);
440
28
}
441
442
static uint16_t
443
expand_channel (uint16_t v, uint32_t bits)
444
0
{
445
0
    int offset = 16 - bits;
446
0
    while (offset > 0) {
447
0
  v |= v >> bits;
448
0
  offset -= bits;
449
0
  bits += bits;
450
0
    }
451
0
    return v;
452
0
}
453
454
static pixman_image_t *
455
_pixel_to_solid (cairo_image_surface_t *image, int x, int y)
456
0
{
457
0
    uint32_t pixel;
458
0
    float *rgba;
459
0
    pixman_color_t color;
460
461
0
    TRACE ((stderr, "%s\n", __FUNCTION__));
462
463
0
    switch (image->format) {
464
0
    default:
465
0
    case CAIRO_FORMAT_INVALID:
466
0
  ASSERT_NOT_REACHED;
467
0
  return NULL;
468
469
0
    case CAIRO_FORMAT_A1:
470
0
  pixel = *(uint8_t *) (image->data + y * image->stride + x/8);
471
0
  return pixel & (1 << (x&7)) ? _pixman_black_image () : _pixman_transparent_image ();
472
473
0
    case CAIRO_FORMAT_A8:
474
0
  color.alpha = *(uint8_t *) (image->data + y * image->stride + x);
475
0
  color.alpha |= color.alpha << 8;
476
0
  if (color.alpha == 0)
477
0
      return _pixman_transparent_image ();
478
0
  if (color.alpha == 0xffff)
479
0
      return _pixman_black_image ();
480
481
0
  color.red = color.green = color.blue = 0;
482
0
  return pixman_image_create_solid_fill (&color);
483
484
0
    case CAIRO_FORMAT_RGB16_565:
485
0
  pixel = *(uint16_t *) (image->data + y * image->stride + 2 * x);
486
0
  if (pixel == 0)
487
0
      return _pixman_black_image ();
488
0
  if (pixel == 0xffff)
489
0
      return _pixman_white_image ();
490
491
0
  color.alpha = 0xffff;
492
0
  color.red = expand_channel ((pixel >> 11 & 0x1f) << 11, 5);
493
0
  color.green = expand_channel ((pixel >> 5 & 0x3f) << 10, 6);
494
0
  color.blue = expand_channel ((pixel & 0x1f) << 11, 5);
495
0
  return pixman_image_create_solid_fill (&color);
496
497
0
    case CAIRO_FORMAT_RGB30:
498
0
  pixel = *(uint32_t *) (image->data + y * image->stride + 4 * x);
499
0
  pixel &= 0x3fffffff; /* ignore alpha bits */
500
0
  if (pixel == 0)
501
0
      return _pixman_black_image ();
502
0
  if (pixel == 0x3fffffff)
503
0
      return _pixman_white_image ();
504
505
  /* convert 10bpc to 16bpc */
506
0
  color.alpha = 0xffff;
507
0
  color.red = expand_channel((pixel >> 20) & 0x3fff, 10);
508
0
  color.green = expand_channel((pixel >> 10) & 0x3fff, 10);
509
0
  color.blue = expand_channel(pixel & 0x3fff, 10);
510
0
  return pixman_image_create_solid_fill (&color);
511
512
0
    case CAIRO_FORMAT_ARGB32:
513
0
    case CAIRO_FORMAT_RGB24:
514
0
  pixel = *(uint32_t *) (image->data + y * image->stride + 4 * x);
515
0
  color.alpha = image->format == CAIRO_FORMAT_ARGB32 ? (pixel >> 24) | (pixel >> 16 & 0xff00) : 0xffff;
516
0
  if (color.alpha == 0)
517
0
      return _pixman_transparent_image ();
518
0
  if (pixel == 0xffffffff)
519
0
      return _pixman_white_image ();
520
0
  if (color.alpha == 0xffff && (pixel & 0xffffff) == 0)
521
0
      return _pixman_black_image ();
522
523
0
  color.red = (pixel >> 16 & 0xff) | (pixel >> 8 & 0xff00);
524
0
  color.green = (pixel >> 8 & 0xff) | (pixel & 0xff00);
525
0
  color.blue = (pixel & 0xff) | (pixel << 8 & 0xff00);
526
0
  return pixman_image_create_solid_fill (&color);
527
528
0
    case CAIRO_FORMAT_RGB96F:
529
0
    case CAIRO_FORMAT_RGBA128F:
530
0
  if (image->format == CAIRO_FORMAT_RGBA128F)
531
0
  {
532
0
      rgba = (float *)&image->data[y * image->stride + 16 * x];
533
0
      color.alpha = 65535.f * rgba[3];
534
535
0
      if (color.alpha == 0)
536
0
    return _pixman_transparent_image ();
537
0
  }
538
0
  else
539
0
  {
540
0
      rgba = (float *)&image->data[y * image->stride + 12 * x];
541
0
      color.alpha = 0xffff;
542
0
  }
543
544
0
  if (color.alpha == 0xffff && rgba[0] == 0.f && rgba[1] == 0.f && rgba[2] == 0.f)
545
0
      return _pixman_black_image ();
546
0
  if (color.alpha == 0xffff && rgba[0] == 1.f && rgba[1] == 1.f && rgba[2] == 1.f)
547
0
      return _pixman_white_image ();
548
549
0
  color.red = rgba[0] * 65535.f;
550
0
  color.green = rgba[1] * 65535.f;
551
0
  color.blue = rgba[2] * 65535.f;
552
0
  return pixman_image_create_solid_fill (&color);
553
0
    }
554
0
}
555
556
/* ========================================================================== */
557
558
/* Index into filter table */
559
typedef enum
560
{
561
    KERNEL_IMPULSE,
562
    KERNEL_BOX,
563
    KERNEL_LINEAR,
564
    KERNEL_MITCHELL,
565
    KERNEL_NOTCH,
566
    KERNEL_CATMULL_ROM,
567
    KERNEL_LANCZOS3,
568
    KERNEL_LANCZOS3_STRETCHED,
569
    KERNEL_TENT
570
} kernel_t;
571
572
/* Produce contribution of a filter of size r for pixel centered on x.
573
   For a typical low-pass function this evaluates the function at x/r.
574
   If the frequency is higher than 1/2, such as when r is less than 1,
575
   this may need to integrate several samples, see cubic for examples.
576
*/
577
typedef double (* kernel_func_t) (double x, double r);
578
579
/* Return maximum number of pixels that will be non-zero. Except for
580
   impluse this is the maximum of 2 and the width of the non-zero part
581
   of the filter rounded up to the next integer.
582
*/
583
typedef int (* kernel_width_func_t) (double r);
584
585
/* Table of filters */
586
typedef struct
587
{
588
    kernel_t    kernel;
589
    kernel_func_t func;
590
    kernel_width_func_t width;
591
} filter_info_t;
592
593
/* PIXMAN_KERNEL_IMPULSE: Returns pixel nearest the center.  This
594
   matches PIXMAN_FILTER_NEAREST. This is useful if you wish to
595
   combine the result of nearest in one direction with another filter
596
   in the other.
597
*/
598
599
static double
600
impulse_kernel (double x, double r)
601
0
{
602
0
    return 1;
603
0
}
604
605
static int
606
impulse_width (double r)
607
0
{
608
0
    return 1;
609
0
}
610
611
/* PIXMAN_KERNEL_BOX: Intersection of a box of width r with square
612
   pixels. This is the smallest possible filter such that the output
613
   image contains an equal contribution from all the input
614
   pixels. Lots of software uses this. The function is a trapazoid of
615
   width r+1, not a box.
616
617
   When r == 1.0, PIXMAN_KERNEL_BOX, PIXMAN_KERNEL_LINEAR, and
618
   PIXMAN_KERNEL_TENT all produce the same filter, allowing
619
   them to be exchanged at this point.
620
*/
621
622
static double
623
box_kernel (double x, double r)
624
0
{
625
0
    return MAX (0.0, MIN (MIN (r, 1.0),
626
0
        MIN ((r + 1) / 2 - x, (r + 1) / 2 + x)));
627
0
}
628
629
static int
630
box_width (double r)
631
0
{
632
0
    return r < 1.0 ? 2 : ceil(r + 1);
633
0
}
634
635
/* PIXMAN_KERNEL_LINEAR: Weighted sum of the two pixels nearest the
636
   center, or a triangle of width 2. This matches
637
   PIXMAN_FILTER_BILINEAR. This is useful if you wish to combine the
638
   result of bilinear in one direction with another filter in the
639
   other.  This is not a good filter if r > 1. You may actually want
640
   PIXMAN_FILTER_TENT.
641
642
   When r == 1.0, PIXMAN_KERNEL_BOX, PIXMAN_KERNEL_LINEAR, and
643
   PIXMAN_KERNEL_TENT all produce the same filter, allowing
644
   them to be exchanged at this point.
645
*/
646
647
static double
648
linear_kernel (double x, double r)
649
0
{
650
0
    return MAX (1.0 - fabs(x), 0.0);
651
0
}
652
653
static int
654
linear_width (double r)
655
0
{
656
0
    return 2;
657
0
}
658
659
/* Cubic functions described in the Mitchell-Netravali paper.
660
   http://mentallandscape.com/Papers_siggraph88.pdf. This describes
661
   all possible cubic functions that can be used for sampling.
662
*/
663
664
static double
665
general_cubic (double x, double r, double B, double C)
666
0
{
667
0
    double ax;
668
0
    if (r < 1.0)
669
0
  return
670
0
      general_cubic(x * 2 - .5, r * 2, B, C) +
671
0
      general_cubic(x * 2 + .5, r * 2, B, C);
672
673
0
    ax = fabs (x / r);
674
675
0
    if (ax < 1)
676
0
    {
677
0
  return (((12 - 9 * B - 6 * C) * ax +
678
0
     (-18 + 12 * B + 6 * C)) * ax * ax +
679
0
    (6 - 2 * B)) / 6;
680
0
    }
681
0
    else if (ax < 2)
682
0
    {
683
0
  return ((((-B - 6 * C) * ax +
684
0
     (6 * B + 30 * C)) * ax +
685
0
    (-12 * B - 48 * C)) * ax +
686
0
    (8 * B + 24 * C)) / 6;
687
0
    }
688
0
    else
689
0
    {
690
0
  return 0.0;
691
0
    }
692
0
}
693
694
static int
695
cubic_width (double r)
696
0
{
697
0
    return MAX (2, ceil (r * 4));
698
0
}
699
700
/* PIXMAN_KERNEL_CATMULL_ROM: Catmull-Rom interpolation. Often called
701
   "cubic interpolation", "b-spline", or just "cubic" by other
702
   software. This filter has negative values so it can produce ringing
703
   and output pixels outside the range of input pixels. This is very
704
   close to lanczos2 so there is no reason to supply that as well.
705
*/
706
707
static double
708
cubic_kernel (double x, double r)
709
0
{
710
0
    return general_cubic (x, r, 0.0, 0.5);
711
0
}
712
713
/* PIXMAN_KERNEL_MITCHELL: Cubic recommended by the Mitchell-Netravali
714
   paper.  This has negative values and because the values at +/-1 are
715
   not zero it does not interpolate the pixels, meaning it will change
716
   an image even if there is no translation.
717
*/
718
719
static double
720
mitchell_kernel (double x, double r)
721
0
{
722
0
    return general_cubic (x, r, 1/3.0, 1/3.0);
723
0
}
724
725
/* PIXMAN_KERNEL_NOTCH: Cubic recommended by the Mitchell-Netravali
726
   paper to remove postaliasing artifacts. This does not remove
727
   aliasing already present in the source image, though it may appear
728
   to due to it's excessive blurriness. In any case this is more
729
   useful than gaussian for image reconstruction.
730
*/
731
732
static double
733
notch_kernel (double x, double r)
734
0
{
735
0
    return general_cubic (x, r, 1.5, -0.25);
736
0
}
737
738
/* PIXMAN_KERNEL_LANCZOS3: lanczos windowed sinc function from -3 to
739
   +3. Very popular with high-end software though I think any
740
   advantage over cubics is hidden by quantization and programming
741
   mistakes. You will see LANCZOS5 or even 7 sometimes.
742
*/
743
744
static double
745
sinc (double x)
746
0
{
747
0
    return x ? sin (M_PI * x) / (M_PI * x) : 1.0;
748
0
}
749
750
static double
751
lanczos (double x, double n)
752
0
{
753
0
    return fabs (x) < n ? sinc (x) * sinc (x * (1.0 / n)) : 0.0;
754
0
}
755
756
static double
757
lanczos3_kernel (double x, double r)
758
0
{
759
0
    if (r < 1.0)
760
0
  return
761
0
      lanczos3_kernel (x * 2 - .5, r * 2) +
762
0
      lanczos3_kernel (x * 2 + .5, r * 2);
763
0
    else
764
0
  return lanczos (x / r, 3.0);
765
0
}
766
767
static int
768
lanczos3_width (double r)
769
0
{
770
0
    return MAX (2, ceil (r * 6));
771
0
}
772
773
/* PIXMAN_KERNEL_LANCZOS3_STRETCHED - The LANCZOS3 kernel widened by
774
   4/3.  Recommended by Jim Blinn
775
   http://graphics.cs.cmu.edu/nsp/course/15-462/Fall07/462/papers/jaggy.pdf
776
*/
777
778
static double
779
nice_kernel (double x, double r)
780
0
{
781
0
    return lanczos3_kernel (x, r * (4.0/3));
782
0
}
783
784
static int
785
nice_width (double r)
786
0
{
787
0
    return MAX (2.0, ceil (r * 8));
788
0
}
789
790
/* PIXMAN_KERNEL_TENT: Triangle of width 2r. Lots of software uses
791
   this as a "better" filter, twice the size of a box but smaller than
792
   a cubic.
793
794
   When r == 1.0, PIXMAN_KERNEL_BOX, PIXMAN_KERNEL_LINEAR, and
795
   PIXMAN_KERNEL_TENT all produce the same filter, allowing
796
   them to be exchanged at this point.
797
*/
798
799
static double
800
tent_kernel (double x, double r)
801
0
{
802
0
    if (r < 1.0)
803
0
  return box_kernel(x, r);
804
0
    else
805
0
  return MAX (1.0 - fabs(x / r), 0.0);
806
0
}
807
808
static int
809
tent_width (double r)
810
0
{
811
0
    return r < 1.0 ? 2 : ceil(2 * r);
812
0
}
813
814
815
static const filter_info_t filters[] =
816
{
817
    { KERNEL_IMPULSE,   impulse_kernel,   impulse_width },
818
    { KERNEL_BOX,   box_kernel,       box_width },
819
    { KERNEL_LINEAR,    linear_kernel,    linear_width },
820
    { KERNEL_MITCHELL,    mitchell_kernel,  cubic_width },
821
    { KERNEL_NOTCH,   notch_kernel,     cubic_width },
822
    { KERNEL_CATMULL_ROM, cubic_kernel,     cubic_width },
823
    { KERNEL_LANCZOS3,    lanczos3_kernel,  lanczos3_width },
824
    { KERNEL_LANCZOS3_STRETCHED,nice_kernel,      nice_width },
825
    { KERNEL_TENT,    tent_kernel,    tent_width }
826
};
827
828
/* Fills in one dimension of the filter array */
829
static void get_filter(kernel_t filter, double r,
830
           int width, int subsample,
831
           pixman_fixed_t* out)
832
0
{
833
0
    int i;
834
0
    pixman_fixed_t *p = out;
835
0
    int n_phases = 1 << subsample;
836
0
    double step = 1.0 / n_phases;
837
0
    kernel_func_t func = filters[filter].func;
838
839
    /* special-case the impulse filter: */
840
0
    if (width <= 1)
841
0
    {
842
0
  for (i = 0; i < n_phases; ++i)
843
0
      *p++ = pixman_fixed_1;
844
0
  return;
845
0
    }
846
847
0
    for (i = 0; i < n_phases; ++i)
848
0
    {
849
0
  double frac = (i + .5) * step;
850
  /* Center of left-most pixel: */
851
0
  double x1 = ceil (frac - width / 2.0 - 0.5) - frac + 0.5;
852
0
  double total = 0;
853
0
  pixman_fixed_t new_total = 0;
854
0
  int j;
855
856
0
  for (j = 0; j < width; ++j)
857
0
  {
858
0
      double v = func(x1 + j, r);
859
0
      total += v;
860
0
      p[j] = pixman_double_to_fixed (v);
861
0
  }
862
863
  /* Normalize */
864
0
        total = 1 / total;
865
0
  for (j = 0; j < width; ++j)
866
0
      new_total += (p[j] *= total);
867
868
  /* Put any error on center pixel */
869
0
  p[width / 2] += (pixman_fixed_1 - new_total);
870
871
0
  p += width;
872
0
    }
873
0
}
874
875
876
/* Create the parameter list for a SEPARABLE_CONVOLUTION filter
877
 * with the given kernels and scale parameters. 
878
 */
879
static pixman_fixed_t *
880
create_separable_convolution (int *n_values,
881
            kernel_t xfilter,
882
            double sx,
883
            kernel_t yfilter,
884
            double sy)
885
0
{
886
0
    int xwidth, xsubsample, ywidth, ysubsample, size_x, size_y;
887
0
    pixman_fixed_t *params;
888
889
0
    xwidth = filters[xfilter].width(sx);
890
0
    xsubsample = 0;
891
0
    if (xwidth > 1)
892
0
  while (sx * (1 << xsubsample) <= 128.0) xsubsample++;
893
0
    size_x = (1 << xsubsample) * xwidth;
894
895
0
    ywidth = filters[yfilter].width(sy);
896
0
    ysubsample = 0;
897
0
    if (ywidth > 1)
898
0
  while (sy * (1 << ysubsample) <= 128.0) ysubsample++;
899
0
    size_y = (1 << ysubsample) * ywidth;
900
901
0
    *n_values = 4 + size_x + size_y;
902
0
    params = _cairo_malloc (*n_values * sizeof (pixman_fixed_t));
903
0
    if (!params) return 0;
904
905
0
    params[0] = pixman_int_to_fixed (xwidth);
906
0
    params[1] = pixman_int_to_fixed (ywidth);
907
0
    params[2] = pixman_int_to_fixed (xsubsample);
908
0
    params[3] = pixman_int_to_fixed (ysubsample);
909
910
0
    get_filter(xfilter, sx, xwidth, xsubsample, params + 4);
911
0
    get_filter(yfilter, sy, ywidth, ysubsample, params + 4 + size_x);
912
913
0
    return params;
914
0
}
915
916
/* ========================================================================== */
917
918
static cairo_bool_t
919
_pixman_image_set_properties (pixman_image_t *pixman_image,
920
            const cairo_pattern_t *pattern,
921
            const cairo_rectangle_int_t *extents,
922
            int *ix,int *iy)
923
28
{
924
28
    pixman_transform_t pixman_transform;
925
28
    cairo_int_status_t status;
926
927
28
    status = _cairo_matrix_to_pixman_matrix_offset (&pattern->matrix,
928
28
                pattern->filter,
929
28
                extents->x + extents->width/2.,
930
28
                extents->y + extents->height/2.,
931
28
                &pixman_transform, ix, iy);
932
28
    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
933
16
    {
934
  /* If the transform is an identity, we don't need to set it
935
   * and we can use any filtering, so choose the fastest one. */
936
16
  pixman_image_set_filter (pixman_image, PIXMAN_FILTER_NEAREST, NULL, 0);
937
16
    }
938
12
    else if (unlikely (status != CAIRO_INT_STATUS_SUCCESS ||
939
12
           ! pixman_image_set_transform (pixman_image,
940
12
                 &pixman_transform)))
941
0
    {
942
0
  return FALSE;
943
0
    }
944
12
    else
945
12
    {
946
12
  pixman_filter_t pixman_filter;
947
12
  kernel_t kernel;
948
12
  double dx, dy;
949
950
  /* Compute scale factors from the pattern matrix. These scale
951
   * factors are from user to pattern space, and as such they
952
   * are greater than 1.0 for downscaling and less than 1.0 for
953
   * upscaling. The factors are the size of an axis-aligned
954
   * rectangle with the same area as the parallelgram a 1x1
955
   * square transforms to.
956
   */
957
12
  dx = hypot (pattern->matrix.xx, pattern->matrix.xy);
958
12
  dy = hypot (pattern->matrix.yx, pattern->matrix.yy);
959
960
  /* Clip at maximum pixman_fixed number. Besides making it
961
   * passable to pixman, this avoids errors from inf and nan.
962
   */
963
12
  if (! (dx < 0x7FFF)) dx = 0x7FFF;
964
12
  if (! (dy < 0x7FFF)) dy = 0x7FFF;
965
966
12
  switch (pattern->filter) {
967
0
  case CAIRO_FILTER_FAST:
968
0
      pixman_filter = PIXMAN_FILTER_FAST;
969
0
      break;
970
0
  case CAIRO_FILTER_GOOD:
971
0
      pixman_filter = PIXMAN_FILTER_SEPARABLE_CONVOLUTION;
972
0
      kernel = KERNEL_BOX;
973
      /* Clip the filter size to prevent extreme slowness. This
974
         value could be raised if 2-pass filtering is done */
975
0
      if (dx > 16.0) dx = 16.0;
976
0
      if (dy > 16.0) dy = 16.0;
977
      /* Match the bilinear filter for scales > .75: */
978
0
      if (dx < 1.0/0.75) dx = 1.0;
979
0
      if (dy < 1.0/0.75) dy = 1.0;
980
0
      break;
981
0
  case CAIRO_FILTER_BEST:
982
0
      pixman_filter = PIXMAN_FILTER_SEPARABLE_CONVOLUTION;
983
0
      kernel = KERNEL_CATMULL_ROM; /* LANCZOS3 is better but not much */
984
      /* Clip the filter size to prevent extreme slowness. This
985
         value could be raised if 2-pass filtering is done */
986
0
      if (dx > 16.0) { dx = 16.0; kernel = KERNEL_BOX; }
987
      /* blur up to 2x scale, then blend to square pixels for larger: */
988
0
      else if (dx < 1.0) {
989
0
    if (dx < 1.0/128) dx = 1.0/127;
990
0
    else if (dx < 0.5) dx = 1.0 / (1.0 / dx - 1.0);
991
0
    else dx = 1.0;
992
0
      }
993
0
      if (dy > 16.0) { dy = 16.0; kernel = KERNEL_BOX; }
994
0
      else if (dy < 1.0) {
995
0
    if (dy < 1.0/128) dy = 1.0/127;
996
0
    else if (dy < 0.5) dy = 1.0 / (1.0 / dy - 1.0);
997
0
    else dy = 1.0;
998
0
      }
999
0
      break;
1000
12
  case CAIRO_FILTER_NEAREST:
1001
12
      pixman_filter = PIXMAN_FILTER_NEAREST;
1002
12
      break;
1003
0
  case CAIRO_FILTER_BILINEAR:
1004
0
      pixman_filter = PIXMAN_FILTER_BILINEAR;
1005
0
      break;
1006
0
  case CAIRO_FILTER_GAUSSIAN:
1007
      /* XXX: The GAUSSIAN value has no implementation in cairo
1008
       * whatsoever, so it was really a mistake to have it in the
1009
       * API. We could fix this by officially deprecating it, or
1010
       * else inventing semantics and providing an actual
1011
       * implementation for it. */
1012
0
  default:
1013
0
      pixman_filter = PIXMAN_FILTER_BEST;
1014
12
  }
1015
1016
12
  if (pixman_filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION) {
1017
0
      int n_params;
1018
0
      pixman_fixed_t *params;
1019
0
      params = create_separable_convolution
1020
0
    (&n_params, kernel, dx, kernel, dy);
1021
0
      pixman_image_set_filter (pixman_image, pixman_filter,
1022
0
             params, n_params);
1023
0
      free (params);
1024
12
  } else {
1025
12
      pixman_image_set_filter (pixman_image, pixman_filter, NULL, 0);
1026
12
  }
1027
12
    }
1028
1029
28
    {
1030
28
  pixman_repeat_t pixman_repeat;
1031
1032
28
  switch (pattern->extend) {
1033
0
  default:
1034
28
  case CAIRO_EXTEND_NONE:
1035
28
      pixman_repeat = PIXMAN_REPEAT_NONE;
1036
28
      break;
1037
0
  case CAIRO_EXTEND_REPEAT:
1038
0
      pixman_repeat = PIXMAN_REPEAT_NORMAL;
1039
0
      break;
1040
0
  case CAIRO_EXTEND_REFLECT:
1041
0
      pixman_repeat = PIXMAN_REPEAT_REFLECT;
1042
0
      break;
1043
0
  case CAIRO_EXTEND_PAD:
1044
0
      pixman_repeat = PIXMAN_REPEAT_PAD;
1045
0
      break;
1046
28
  }
1047
1048
28
  pixman_image_set_repeat (pixman_image, pixman_repeat);
1049
28
    }
1050
1051
28
    if (pattern->has_component_alpha)
1052
0
  pixman_image_set_component_alpha (pixman_image, TRUE);
1053
1054
28
    return TRUE;
1055
28
}
1056
1057
struct proxy {
1058
    cairo_surface_t base;
1059
    cairo_surface_t *image;
1060
};
1061
1062
static cairo_status_t
1063
proxy_acquire_source_image (void       *abstract_surface,
1064
          cairo_image_surface_t **image_out,
1065
          void      **image_extra)
1066
0
{
1067
0
    struct proxy *proxy = abstract_surface;
1068
0
    return _cairo_surface_acquire_source_image (proxy->image, image_out, image_extra);
1069
0
}
1070
1071
static void
1072
proxy_release_source_image (void      *abstract_surface,
1073
          cairo_image_surface_t *image,
1074
          void      *image_extra)
1075
0
{
1076
0
    struct proxy *proxy = abstract_surface;
1077
0
    _cairo_surface_release_source_image (proxy->image, image, image_extra);
1078
0
}
1079
1080
static cairo_status_t
1081
proxy_finish (void *abstract_surface)
1082
51
{
1083
51
    return CAIRO_STATUS_SUCCESS;
1084
51
}
1085
1086
static const cairo_surface_backend_t proxy_backend  = {
1087
    CAIRO_INTERNAL_SURFACE_TYPE_NULL,
1088
    proxy_finish,
1089
    NULL,
1090
1091
    NULL, /* create similar */
1092
    NULL, /* create similar image */
1093
    NULL, /* map to image */
1094
    NULL, /* unmap image */
1095
1096
    _cairo_surface_default_source,
1097
    proxy_acquire_source_image,
1098
    proxy_release_source_image,
1099
};
1100
1101
static cairo_surface_t *
1102
attach_proxy (cairo_surface_t *source,
1103
        cairo_surface_t *image)
1104
51
{
1105
51
    struct proxy *proxy;
1106
1107
51
    proxy = _cairo_calloc (sizeof (*proxy));
1108
51
    if (unlikely (proxy == NULL))
1109
0
  return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
1110
1111
51
    _cairo_surface_init (&proxy->base, &proxy_backend, NULL, image->content, FALSE);
1112
1113
51
    proxy->image = image;
1114
51
    _cairo_surface_attach_snapshot (source, &proxy->base, NULL);
1115
1116
51
    return &proxy->base;
1117
51
}
1118
1119
static void
1120
detach_proxy (cairo_surface_t *source,
1121
        cairo_surface_t *proxy)
1122
51
{
1123
51
    cairo_surface_finish (proxy);
1124
51
    cairo_surface_destroy (proxy);
1125
51
}
1126
1127
static cairo_surface_t *
1128
get_proxy (cairo_surface_t *proxy)
1129
0
{
1130
0
    return ((struct proxy *)proxy)->image;
1131
0
}
1132
1133
static pixman_image_t *
1134
_pixman_image_for_recording (cairo_image_surface_t *dst,
1135
           const cairo_surface_pattern_t *pattern,
1136
           cairo_bool_t is_mask,
1137
           const cairo_rectangle_int_t *extents,
1138
           const cairo_rectangle_int_t *sample,
1139
           int *ix, int *iy)
1140
51
{
1141
51
    cairo_surface_t *source, *clone, *proxy;
1142
51
    cairo_rectangle_int_t limit;
1143
51
    cairo_rectangle_int_t src_limit;
1144
51
    pixman_image_t *pixman_image;
1145
51
    cairo_status_t status;
1146
51
    cairo_extend_t extend;
1147
51
    cairo_matrix_t *m, matrix;
1148
51
    double sx = 1.0, sy = 1.0;
1149
51
    int tx = 0, ty = 0;
1150
1151
51
    TRACE ((stderr, "%s\n", __FUNCTION__));
1152
1153
51
    *ix = *iy = 0;
1154
1155
51
    source = _cairo_pattern_get_source (pattern, &limit);
1156
51
    src_limit = limit;
1157
1158
51
    extend = pattern->base.extend;
1159
51
    if (_cairo_rectangle_contains_rectangle (&limit, sample))
1160
51
  extend = CAIRO_EXTEND_NONE;
1161
1162
51
    if (extend == CAIRO_EXTEND_NONE) {
1163
51
  if (! _cairo_rectangle_intersect (&limit, sample))
1164
0
      return _pixman_transparent_image ();
1165
51
    }
1166
1167
51
    if (! _cairo_matrix_is_identity (&pattern->base.matrix)) {
1168
32
  double x1, y1, x2, y2;
1169
1170
32
  matrix = pattern->base.matrix;
1171
32
  status = cairo_matrix_invert (&matrix);
1172
32
  assert (status == CAIRO_STATUS_SUCCESS);
1173
1174
32
  x1 = limit.x;
1175
32
  y1 = limit.y;
1176
32
  x2 = limit.x + limit.width;
1177
32
  y2 = limit.y + limit.height;
1178
1179
32
  _cairo_matrix_transform_bounding_box (&matrix,
1180
32
                &x1, &y1, &x2, &y2, NULL);
1181
1182
32
  limit.x = floor (x1);
1183
32
  limit.y = floor (y1);
1184
32
  limit.width  = ceil (x2) - limit.x;
1185
32
  limit.height = ceil (y2) - limit.y;
1186
32
  sx = (double)src_limit.width / limit.width;
1187
32
  sy = (double)src_limit.height / limit.height;
1188
32
    }
1189
51
    tx = limit.x;
1190
51
    ty = limit.y;
1191
1192
    /* XXX transformations! */
1193
51
    proxy = _cairo_surface_has_snapshot (source, &proxy_backend);
1194
51
    if (proxy != NULL) {
1195
0
  clone = cairo_surface_reference (get_proxy (proxy));
1196
0
  goto done;
1197
0
    }
1198
1199
51
    if (is_mask) {
1200
0
      clone = cairo_image_surface_create (CAIRO_FORMAT_A8,
1201
0
            limit.width, limit.height);
1202
51
    } else {
1203
51
  if (dst->base.content == source->content)
1204
51
      clone = cairo_image_surface_create (dst->format,
1205
51
            limit.width, limit.height);
1206
0
  else
1207
0
      clone = _cairo_image_surface_create_with_content (source->content,
1208
0
                    limit.width,
1209
0
                    limit.height);
1210
51
  if (dst->base.foreground_source)
1211
0
      clone->foreground_source = cairo_pattern_reference (dst->base.foreground_source);
1212
51
    }
1213
1214
51
    m = NULL;
1215
51
    if (extend == CAIRO_EXTEND_NONE) {
1216
51
  matrix = pattern->base.matrix;
1217
51
  if (tx | ty)
1218
32
      cairo_matrix_translate (&matrix, tx, ty);
1219
51
  m = &matrix;
1220
51
    } else {
1221
0
  cairo_matrix_init_scale (&matrix, sx, sy);
1222
0
  cairo_matrix_translate (&matrix, src_limit.x/sx, src_limit.y/sy);
1223
0
  m = &matrix;
1224
0
    }
1225
1226
    /* Handle recursion by returning future reads from the current image */
1227
51
    proxy = attach_proxy (source, clone);
1228
51
    status = _cairo_recording_surface_replay_with_clip (source, m, clone, NULL);
1229
51
    if (clone->foreground_used)
1230
0
  dst->base.foreground_used = clone->foreground_used;
1231
51
    detach_proxy (source, proxy);
1232
51
    if (unlikely (status)) {
1233
0
  cairo_surface_destroy (clone);
1234
0
  return NULL;
1235
0
    }
1236
1237
51
done:
1238
51
    pixman_image = pixman_image_ref (((cairo_image_surface_t *)clone)->pixman_image);
1239
51
    cairo_surface_destroy (clone);
1240
1241
51
    if (extend == CAIRO_EXTEND_NONE) {
1242
51
  *ix = -limit.x;
1243
51
  *iy = -limit.y;
1244
51
    } else {
1245
0
  cairo_pattern_union_t tmp_pattern;
1246
0
  _cairo_pattern_init_static_copy (&tmp_pattern.base, &pattern->base);
1247
0
  matrix = pattern->base.matrix;
1248
0
  status = cairo_matrix_invert(&matrix);
1249
0
  assert (status == CAIRO_STATUS_SUCCESS);
1250
0
  cairo_matrix_translate (&matrix, src_limit.x, src_limit.y);
1251
0
  cairo_matrix_scale (&matrix, sx, sy);
1252
0
  status = cairo_matrix_invert(&matrix);
1253
0
  assert (status == CAIRO_STATUS_SUCCESS);
1254
0
  cairo_pattern_set_matrix (&tmp_pattern.base, &matrix);
1255
0
  if (! _pixman_image_set_properties (pixman_image,
1256
0
              &tmp_pattern.base, extents,
1257
0
              ix, iy)) {
1258
0
      pixman_image_unref (pixman_image);
1259
0
      pixman_image= NULL;
1260
0
  }
1261
0
    }
1262
1263
51
    return pixman_image;
1264
51
}
1265
1266
static pixman_image_t *
1267
_pixman_image_for_surface (cairo_image_surface_t *dst,
1268
         const cairo_surface_pattern_t *pattern,
1269
         cairo_bool_t is_mask,
1270
         const cairo_rectangle_int_t *extents,
1271
         const cairo_rectangle_int_t *sample,
1272
         int *ix, int *iy)
1273
79
{
1274
79
    cairo_extend_t extend = pattern->base.extend;
1275
79
    pixman_image_t *pixman_image;
1276
1277
79
    TRACE ((stderr, "%s\n", __FUNCTION__));
1278
1279
79
    *ix = *iy = 0;
1280
79
    pixman_image = NULL;
1281
79
    if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
1282
51
  return _pixman_image_for_recording(dst, pattern,
1283
51
             is_mask, extents, sample,
1284
51
             ix, iy);
1285
1286
28
    if (pattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE &&
1287
28
  (! is_mask || ! pattern->base.has_component_alpha ||
1288
0
   (pattern->surface->content & CAIRO_CONTENT_COLOR) == 0))
1289
28
    {
1290
28
  cairo_surface_t *defer_free = NULL;
1291
28
  cairo_image_surface_t *source = (cairo_image_surface_t *) pattern->surface;
1292
28
  cairo_surface_type_t type;
1293
1294
28
  if (_cairo_surface_is_snapshot (&source->base)) {
1295
28
      defer_free = _cairo_surface_snapshot_get_target (&source->base);
1296
28
      source = (cairo_image_surface_t *) defer_free;
1297
28
  }
1298
1299
28
  type = source->base.backend->type;
1300
28
  if (type == CAIRO_SURFACE_TYPE_IMAGE) {
1301
28
      if (extend != CAIRO_EXTEND_NONE &&
1302
0
    sample->x >= 0 &&
1303
0
    sample->y >= 0 &&
1304
0
    sample->x + sample->width  <= source->width &&
1305
0
    sample->y + sample->height <= source->height)
1306
0
      {
1307
0
    extend = CAIRO_EXTEND_NONE;
1308
0
      }
1309
1310
28
      if (sample->width == 1 && sample->height == 1) {
1311
0
    if (sample->x < 0 ||
1312
0
        sample->y < 0 ||
1313
0
        sample->x >= source->width ||
1314
0
        sample->y >= source->height)
1315
0
    {
1316
0
        if (extend == CAIRO_EXTEND_NONE) {
1317
0
      cairo_surface_destroy (defer_free);
1318
0
      return _pixman_transparent_image ();
1319
0
        }
1320
0
    }
1321
0
    else
1322
0
    {
1323
0
        pixman_image = _pixel_to_solid (source,
1324
0
                sample->x, sample->y);
1325
0
                    if (pixman_image) {
1326
0
      cairo_surface_destroy (defer_free);
1327
0
                        return pixman_image;
1328
0
        }
1329
0
    }
1330
0
      }
1331
1332
#if PIXMAN_HAS_ATOMIC_OPS
1333
      /* avoid allocating a 'pattern' image if we can reuse the original */
1334
      if (extend == CAIRO_EXTEND_NONE &&
1335
    _cairo_matrix_is_pixman_translation (&pattern->base.matrix,
1336
                 pattern->base.filter,
1337
                 ix, iy))
1338
      {
1339
    cairo_surface_destroy (defer_free);
1340
    return pixman_image_ref (source->pixman_image);
1341
      }
1342
#endif
1343
1344
28
      pixman_image = pixman_image_create_bits (source->pixman_format,
1345
28
                 source->width,
1346
28
                 source->height,
1347
28
                 (uint32_t *) source->data,
1348
28
                 source->stride);
1349
28
      if (unlikely (pixman_image == NULL)) {
1350
0
    cairo_surface_destroy (defer_free);
1351
0
    return NULL;
1352
0
      }
1353
1354
28
      if (defer_free) {
1355
28
    pixman_image_set_destroy_function (pixman_image,
1356
28
               _defer_free_cleanup,
1357
28
               defer_free);
1358
28
      }
1359
28
  } else if (type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
1360
0
      cairo_surface_subsurface_t *sub;
1361
0
      cairo_bool_t is_contained = FALSE;
1362
1363
0
      sub = (cairo_surface_subsurface_t *) source;
1364
0
      source = (cairo_image_surface_t *) sub->target;
1365
1366
0
      if (sample->x >= 0 &&
1367
0
    sample->y >= 0 &&
1368
0
    sample->x + sample->width  <= sub->extents.width &&
1369
0
    sample->y + sample->height <= sub->extents.height)
1370
0
      {
1371
0
    is_contained = TRUE;
1372
0
      }
1373
1374
0
      if (sample->width == 1 && sample->height == 1) {
1375
0
    if (is_contained) {
1376
0
        pixman_image = _pixel_to_solid (source,
1377
0
                                                    sub->extents.x + sample->x,
1378
0
                                                    sub->extents.y + sample->y);
1379
0
                    if (pixman_image)
1380
0
                        return pixman_image;
1381
0
    } else {
1382
0
        if (extend == CAIRO_EXTEND_NONE)
1383
0
      return _pixman_transparent_image ();
1384
0
    }
1385
0
      }
1386
1387
#if PIXMAN_HAS_ATOMIC_OPS
1388
      *ix = sub->extents.x;
1389
      *iy = sub->extents.y;
1390
      if (is_contained &&
1391
    _cairo_matrix_is_pixman_translation (&pattern->base.matrix,
1392
                 pattern->base.filter,
1393
                 ix, iy))
1394
      {
1395
    return pixman_image_ref (source->pixman_image);
1396
      }
1397
#endif
1398
1399
      /* Avoid sub-byte offsets, force a copy in that case. */
1400
0
      if (PIXMAN_FORMAT_BPP (source->pixman_format) >= 8) {
1401
0
    if (is_contained) {
1402
0
        void *data = source->data
1403
0
      + sub->extents.x * PIXMAN_FORMAT_BPP(source->pixman_format)/8
1404
0
      + sub->extents.y * source->stride;
1405
0
        pixman_image = pixman_image_create_bits (source->pixman_format,
1406
0
                   sub->extents.width,
1407
0
                   sub->extents.height,
1408
0
                   data,
1409
0
                   source->stride);
1410
0
        if (unlikely (pixman_image == NULL))
1411
0
      return NULL;
1412
0
    } else {
1413
        /* XXX for a simple translation and EXTEND_NONE we can
1414
         * fix up the pattern matrix instead.
1415
         */
1416
0
    }
1417
0
      }
1418
0
  }
1419
28
    }
1420
1421
28
    if (pixman_image == NULL) {
1422
0
  struct acquire_source_cleanup *cleanup;
1423
0
  cairo_image_surface_t *image;
1424
0
  void *extra;
1425
0
  cairo_status_t status;
1426
1427
0
  status = _cairo_surface_acquire_source_image (pattern->surface, &image, &extra);
1428
0
  if (unlikely (status))
1429
0
      return NULL;
1430
1431
0
  pixman_image = pixman_image_create_bits (image->pixman_format,
1432
0
             image->width,
1433
0
             image->height,
1434
0
             (uint32_t *) image->data,
1435
0
             image->stride);
1436
0
  if (unlikely (pixman_image == NULL)) {
1437
0
      _cairo_surface_release_source_image (pattern->surface, image, extra);
1438
0
      return NULL;
1439
0
  }
1440
1441
0
  cleanup = _cairo_malloc (sizeof (*cleanup));
1442
0
  if (unlikely (cleanup == NULL)) {
1443
0
      _cairo_surface_release_source_image (pattern->surface, image, extra);
1444
0
      pixman_image_unref (pixman_image);
1445
0
      return NULL;
1446
0
  }
1447
1448
0
  cleanup->surface = pattern->surface;
1449
0
  cleanup->image = image;
1450
0
  cleanup->image_extra = extra;
1451
0
  pixman_image_set_destroy_function (pixman_image,
1452
0
             _acquire_source_cleanup, cleanup);
1453
0
    }
1454
1455
28
    if (! _pixman_image_set_properties (pixman_image,
1456
28
          &pattern->base, extents,
1457
28
          ix, iy)) {
1458
0
  pixman_image_unref (pixman_image);
1459
0
  pixman_image= NULL;
1460
0
    }
1461
1462
28
    return pixman_image;
1463
28
}
1464
1465
struct raster_source_cleanup {
1466
    const cairo_pattern_t *pattern;
1467
    cairo_surface_t *surface;
1468
    cairo_image_surface_t *image;
1469
    void *image_extra;
1470
};
1471
1472
static void
1473
_raster_source_cleanup (pixman_image_t *pixman_image,
1474
      void *closure)
1475
0
{
1476
0
    struct raster_source_cleanup *data = closure;
1477
1478
0
    _cairo_surface_release_source_image (data->surface,
1479
0
           data->image,
1480
0
           data->image_extra);
1481
1482
0
    _cairo_raster_source_pattern_release (data->pattern,
1483
0
            data->surface);
1484
1485
0
    free (data);
1486
0
}
1487
1488
static pixman_image_t *
1489
_pixman_image_for_raster (cairo_image_surface_t *dst,
1490
        const cairo_raster_source_pattern_t *pattern,
1491
        cairo_bool_t is_mask,
1492
        const cairo_rectangle_int_t *extents,
1493
        const cairo_rectangle_int_t *sample,
1494
        int *ix, int *iy)
1495
0
{
1496
0
    pixman_image_t *pixman_image;
1497
0
    struct raster_source_cleanup *cleanup;
1498
0
    cairo_image_surface_t *image;
1499
0
    void *extra;
1500
0
    cairo_status_t status;
1501
0
    cairo_surface_t *surface;
1502
1503
0
    TRACE ((stderr, "%s\n", __FUNCTION__));
1504
1505
0
    *ix = *iy = 0;
1506
1507
0
    surface = _cairo_raster_source_pattern_acquire (&pattern->base,
1508
0
                &dst->base, NULL);
1509
0
    if (unlikely (surface == NULL || surface->status))
1510
0
  return NULL;
1511
1512
0
    status = _cairo_surface_acquire_source_image (surface, &image, &extra);
1513
0
    if (unlikely (status)) {
1514
0
  _cairo_raster_source_pattern_release (&pattern->base, surface);
1515
0
  return NULL;
1516
0
    }
1517
1518
0
    assert (image->width == pattern->extents.width);
1519
0
    assert (image->height == pattern->extents.height);
1520
1521
0
    pixman_image = pixman_image_create_bits (image->pixman_format,
1522
0
               image->width,
1523
0
               image->height,
1524
0
               (uint32_t *) image->data,
1525
0
               image->stride);
1526
0
    if (unlikely (pixman_image == NULL)) {
1527
0
  _cairo_surface_release_source_image (surface, image, extra);
1528
0
  _cairo_raster_source_pattern_release (&pattern->base, surface);
1529
0
  return NULL;
1530
0
    }
1531
1532
0
    cleanup = _cairo_calloc (sizeof (*cleanup));
1533
0
    if (unlikely (cleanup == NULL)) {
1534
0
  pixman_image_unref (pixman_image);
1535
0
  _cairo_surface_release_source_image (surface, image, extra);
1536
0
  _cairo_raster_source_pattern_release (&pattern->base, surface);
1537
0
  return NULL;
1538
0
    }
1539
1540
0
    cleanup->pattern = &pattern->base;
1541
0
    cleanup->surface = surface;
1542
0
    cleanup->image = image;
1543
0
    cleanup->image_extra = extra;
1544
0
    pixman_image_set_destroy_function (pixman_image,
1545
0
               _raster_source_cleanup, cleanup);
1546
1547
0
    if (! _pixman_image_set_properties (pixman_image,
1548
0
          &pattern->base, extents,
1549
0
          ix, iy)) {
1550
0
  pixman_image_unref (pixman_image);
1551
0
  pixman_image= NULL;
1552
0
    }
1553
1554
0
    return pixman_image;
1555
0
}
1556
1557
pixman_image_t *
1558
_pixman_image_for_pattern (cairo_image_surface_t *dst,
1559
         const cairo_pattern_t *pattern,
1560
         cairo_bool_t is_mask,
1561
         const cairo_rectangle_int_t *extents,
1562
         const cairo_rectangle_int_t *sample,
1563
         int *tx, int *ty)
1564
115
{
1565
115
    *tx = *ty = 0;
1566
1567
115
    TRACE ((stderr, "%s\n", __FUNCTION__));
1568
1569
115
    if (pattern == NULL)
1570
0
  return _pixman_white_image ();
1571
1572
115
    switch (pattern->type) {
1573
0
    default:
1574
0
  ASSERT_NOT_REACHED;
1575
24
    case CAIRO_PATTERN_TYPE_SOLID:
1576
24
  return _pixman_image_for_color (&((const cairo_solid_pattern_t *) pattern)->color);
1577
1578
0
    case CAIRO_PATTERN_TYPE_RADIAL:
1579
12
    case CAIRO_PATTERN_TYPE_LINEAR:
1580
12
  return _pixman_image_for_gradient ((const cairo_gradient_pattern_t *) pattern,
1581
12
             extents, tx, ty);
1582
1583
0
    case CAIRO_PATTERN_TYPE_MESH:
1584
0
  return _pixman_image_for_mesh ((const cairo_mesh_pattern_t *) pattern,
1585
0
             extents, tx, ty);
1586
1587
79
    case CAIRO_PATTERN_TYPE_SURFACE:
1588
79
  return _pixman_image_for_surface (dst,
1589
79
            (const cairo_surface_pattern_t *) pattern,
1590
79
            is_mask, extents, sample,
1591
79
            tx, ty);
1592
1593
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
1594
0
  return _pixman_image_for_raster (dst,
1595
0
           (const cairo_raster_source_pattern_t *) pattern,
1596
0
           is_mask, extents, sample,
1597
0
           tx, ty);
1598
115
    }
1599
115
}
1600
1601
static cairo_status_t
1602
_cairo_image_source_finish (void *abstract_surface)
1603
64
{
1604
64
    cairo_image_source_t *source = abstract_surface;
1605
1606
64
    pixman_image_unref (source->pixman_image);
1607
64
    return CAIRO_STATUS_SUCCESS;
1608
64
}
1609
1610
const cairo_surface_backend_t _cairo_image_source_backend = {
1611
    CAIRO_SURFACE_TYPE_IMAGE,
1612
    _cairo_image_source_finish,
1613
    NULL, /* read-only wrapper */
1614
};
1615
1616
cairo_surface_t *
1617
_cairo_image_source_create_for_pattern (cairo_surface_t *dst,
1618
           const cairo_pattern_t *pattern,
1619
           cairo_bool_t is_mask,
1620
           const cairo_rectangle_int_t *extents,
1621
           const cairo_rectangle_int_t *sample,
1622
           int *src_x, int *src_y)
1623
64
{
1624
64
    cairo_image_source_t *source;
1625
1626
64
    TRACE ((stderr, "%s\n", __FUNCTION__));
1627
1628
64
    source = _cairo_calloc (sizeof (cairo_image_source_t));
1629
64
    if (unlikely (source == NULL))
1630
0
  return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1631
1632
64
    source->pixman_image =
1633
64
  _pixman_image_for_pattern ((cairo_image_surface_t *)dst,
1634
64
           pattern, is_mask,
1635
64
           extents, sample,
1636
64
           src_x, src_y);
1637
64
    if (unlikely (source->pixman_image == NULL)) {
1638
0
  free (source);
1639
0
  return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
1640
0
    }
1641
1642
64
    _cairo_surface_init (&source->base,
1643
64
       &_cairo_image_source_backend,
1644
64
       NULL, /* device */
1645
64
       CAIRO_CONTENT_COLOR_ALPHA,
1646
64
       FALSE); /* is_vector */
1647
1648
64
    source->is_opaque_solid =
1649
64
  pattern == NULL || _cairo_pattern_is_opaque_solid (pattern);
1650
1651
64
    return &source->base;
1652
64
}