Coverage Report

Created: 2025-07-07 10:01

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