Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/workdir/UnpackedTarball/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
2.47k
#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 ((cairo_atomic_intptr_t *) &__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 ((cairo_atomic_intptr_t *) &__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 ((cairo_atomic_intptr_t *) &__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
165
{
184
165
    TRACE ((stderr, "%s\n", __FUNCTION__));
185
165
    return _pixman_image_for_color (CAIRO_COLOR_TRANSPARENT);
186
165
}
187
188
static pixman_image_t *
189
_pixman_black_image (void)
190
71
{
191
71
    TRACE ((stderr, "%s\n", __FUNCTION__));
192
71
    return _pixman_image_for_color (CAIRO_COLOR_BLACK);
193
71
}
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
28.6k
{
207
28.6k
    pixman_color_t color;
208
28.6k
    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
28.6k
    color.red   = cairo_color->red_short;
242
28.6k
    color.green = cairo_color->green_short;
243
28.6k
    color.blue  = cairo_color->blue_short;
244
28.6k
    color.alpha = cairo_color->alpha_short;
245
246
28.6k
    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
28.6k
    return image;
264
28.6k
}
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
2.47k
{
296
2.47k
    pixman_image_t    *pixman_image;
297
2.47k
    pixman_gradient_stop_t pixman_stops_static[2];
298
2.47k
    pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
299
2.47k
    pixman_transform_t      pixman_transform;
300
2.47k
    cairo_matrix_t matrix;
301
2.47k
    cairo_circle_double_t extremes[2];
302
2.47k
    pixman_point_fixed_t p1, p2;
303
2.47k
    unsigned int i;
304
2.47k
    cairo_int_status_t status;
305
306
2.47k
    TRACE ((stderr, "%s\n", __FUNCTION__));
307
308
2.47k
    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
7.41k
    for (i = 0; i < pattern->n_stops; i++) {
316
4.94k
  pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
317
4.94k
  pixman_stops[i].color.red   = pattern->stops[i].color.red_short;
318
4.94k
  pixman_stops[i].color.green = pattern->stops[i].color.green_short;
319
4.94k
  pixman_stops[i].color.blue  = pattern->stops[i].color.blue_short;
320
4.94k
  pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
321
4.94k
    }
322
323
2.47k
    _cairo_gradient_pattern_fit_to_range (pattern, PIXMAN_MAX_INT >> 1, &matrix, extremes);
324
325
2.47k
    p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
326
2.47k
    p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
327
2.47k
    p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
328
2.47k
    p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
329
330
2.47k
    if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
331
603
  pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
332
603
                  pixman_stops,
333
603
                  pattern->n_stops);
334
1.86k
    } else {
335
1.86k
  pixman_fixed_t r1, r2;
336
337
1.86k
  r1   = _cairo_fixed_16_16_from_double (extremes[0].radius);
338
1.86k
  r2   = _cairo_fixed_16_16_from_double (extremes[1].radius);
339
340
1.86k
  pixman_image = pixman_image_create_radial_gradient (&p1, &p2, r1, r2,
341
1.86k
                  pixman_stops,
342
1.86k
                  pattern->n_stops);
343
1.86k
    }
344
345
2.47k
    if (pixman_stops != pixman_stops_static)
346
0
  free (pixman_stops);
347
348
2.47k
    if (unlikely (pixman_image == NULL))
349
0
  return NULL;
350
351
2.47k
    *ix = *iy = 0;
352
2.47k
    status = _cairo_matrix_to_pixman_matrix_offset (&matrix, pattern->base.filter,
353
2.47k
                extents->x + extents->width/2.,
354
2.47k
                extents->y + extents->height/2.,
355
2.47k
                &pixman_transform, ix, iy);
356
2.47k
    if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
357
1.80k
  if (unlikely (status != CAIRO_INT_STATUS_SUCCESS) ||
358
1.80k
      ! pixman_image_set_transform (pixman_image, &pixman_transform))
359
0
  {
360
0
      pixman_image_unref (pixman_image);
361
0
      return NULL;
362
0
  }
363
1.80k
    }
364
365
2.47k
    {
366
2.47k
  pixman_repeat_t pixman_repeat;
367
368
2.47k
  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
2.47k
  case CAIRO_EXTEND_PAD:
380
2.47k
      pixman_repeat = PIXMAN_REPEAT_PAD;
381
2.47k
      break;
382
2.47k
  }
383
384
2.47k
  pixman_image_set_repeat (pixman_image, pixman_repeat);
385
2.47k
    }
386
387
0
    return pixman_image;
388
2.47k
}
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
242
{
457
242
    uint32_t pixel;
458
242
    float *rgba;
459
242
    pixman_color_t color;
460
461
242
    TRACE ((stderr, "%s\n", __FUNCTION__));
462
463
242
    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_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
242
    case CAIRO_FORMAT_ARGB32:
526
242
    case CAIRO_FORMAT_RGB24:
527
242
  pixel = *(uint32_t *) (image->data + y * image->stride + 4 * x);
528
242
  color.alpha = image->format == CAIRO_FORMAT_ARGB32 ? (pixel >> 24) | (pixel >> 16 & 0xff00) : 0xffff;
529
242
  if (color.alpha == 0)
530
165
      return _pixman_transparent_image ();
531
77
  if (pixel == 0xffffffff)
532
4
      return _pixman_white_image ();
533
73
  if (color.alpha == 0xffff && (pixel & 0xffffff) == 0)
534
71
      return _pixman_black_image ();
535
536
2
  color.red = (pixel >> 16 & 0xff) | (pixel >> 8 & 0xff00);
537
2
  color.green = (pixel >> 8 & 0xff) | (pixel & 0xff00);
538
2
  color.blue = (pixel & 0xff) | (pixel << 8 & 0xff00);
539
2
  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
242
    }
567
242
}
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
74.5k
{
638
74.5k
    return MAX (0.0, MIN (MIN (r, 1.0),
639
74.5k
        MIN ((r + 1) / 2 - x, (r + 1) / 2 + x)));
640
74.5k
}
641
642
static int
643
box_width (double r)
644
186
{
645
186
    return r < 1.0 ? 2 : ceil(r + 1);
646
186
}
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
186
{
846
186
    int i;
847
186
    pixman_fixed_t *p = out;
848
186
    int n_phases = 1 << subsample;
849
186
    double step = 1.0 / n_phases;
850
186
    kernel_func_t func = filters[filter].func;
851
852
    /* special-case the impulse filter: */
853
186
    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
28.8k
    for (i = 0; i < n_phases; ++i)
861
28.6k
    {
862
28.6k
  double frac = (i + .5) * step;
863
  /* Center of left-most pixel: */
864
28.6k
  double x1 = ceil (frac - width / 2.0 - 0.5) - frac + 0.5;
865
28.6k
  double total = 0;
866
28.6k
  pixman_fixed_t new_total = 0;
867
28.6k
  int j;
868
869
103k
  for (j = 0; j < width; ++j)
870
74.5k
  {
871
74.5k
      double v = func(x1 + j, r);
872
74.5k
      total += v;
873
74.5k
      p[j] = pixman_double_to_fixed (v);
874
74.5k
  }
875
876
  /* Normalize */
877
28.6k
        total = 1 / total;
878
103k
  for (j = 0; j < width; ++j)
879
74.5k
      new_total += (p[j] *= total);
880
881
  /* Put any error on center pixel */
882
28.6k
  p[width / 2] += (pixman_fixed_1 - new_total);
883
884
28.6k
  p += width;
885
28.6k
    }
886
186
}
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
93
{
899
93
    int xwidth, xsubsample, ywidth, ysubsample, size_x, size_y;
900
93
    pixman_fixed_t *params;
901
902
93
    xwidth = filters[xfilter].width(sx);
903
93
    xsubsample = 0;
904
93
    if (xwidth > 1)
905
620
  while (sx * (1 << xsubsample) <= 128.0) xsubsample++;
906
93
    size_x = (1 << xsubsample) * xwidth;
907
908
93
    ywidth = filters[yfilter].width(sy);
909
93
    ysubsample = 0;
910
93
    if (ywidth > 1)
911
804
  while (sy * (1 << ysubsample) <= 128.0) ysubsample++;
912
93
    size_y = (1 << ysubsample) * ywidth;
913
914
93
    *n_values = 4 + size_x + size_y;
915
93
    params = _cairo_malloc (*n_values * sizeof (pixman_fixed_t));
916
93
    if (!params) return 0;
917
918
93
    params[0] = pixman_int_to_fixed (xwidth);
919
93
    params[1] = pixman_int_to_fixed (ywidth);
920
93
    params[2] = pixman_int_to_fixed (xsubsample);
921
93
    params[3] = pixman_int_to_fixed (ysubsample);
922
923
93
    get_filter(xfilter, sx, xwidth, xsubsample, params + 4);
924
93
    get_filter(yfilter, sy, ywidth, ysubsample, params + 4 + size_x);
925
926
93
    return params;
927
93
}
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
248
{
937
248
    pixman_transform_t pixman_transform;
938
248
    cairo_int_status_t status;
939
940
248
    status = _cairo_matrix_to_pixman_matrix_offset (&pattern->matrix,
941
248
                pattern->filter,
942
248
                extents->x + extents->width/2.,
943
248
                extents->y + extents->height/2.,
944
248
                &pixman_transform, ix, iy);
945
248
    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
248
    else if (unlikely (status != CAIRO_INT_STATUS_SUCCESS ||
952
248
           ! pixman_image_set_transform (pixman_image,
953
248
                 &pixman_transform)))
954
42
    {
955
42
  return FALSE;
956
42
    }
957
206
    else
958
206
    {
959
206
  pixman_filter_t pixman_filter;
960
206
  kernel_t kernel;
961
206
  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
206
  dx = hypot (pattern->matrix.xx, pattern->matrix.xy);
971
206
  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
206
  if (! (dx < 0x7FFF)) dx = 0x7FFF;
977
206
  if (! (dy < 0x7FFF)) dy = 0x7FFF;
978
979
206
  switch (pattern->filter) {
980
0
  case CAIRO_FILTER_FAST:
981
0
      pixman_filter = PIXMAN_FILTER_FAST;
982
0
      break;
983
93
  case CAIRO_FILTER_GOOD:
984
93
      pixman_filter = PIXMAN_FILTER_SEPARABLE_CONVOLUTION;
985
93
      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
93
      if (dx > 16.0) dx = 16.0;
989
93
      if (dy > 16.0) dy = 16.0;
990
      /* Match the bilinear filter for scales > .75: */
991
93
      if (dx < 1.0/0.75) dx = 1.0;
992
93
      if (dy < 1.0/0.75) dy = 1.0;
993
93
      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
7
  case CAIRO_FILTER_NEAREST:
1014
7
      pixman_filter = PIXMAN_FILTER_NEAREST;
1015
7
      break;
1016
106
  case CAIRO_FILTER_BILINEAR:
1017
106
      pixman_filter = PIXMAN_FILTER_BILINEAR;
1018
106
      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
206
  }
1028
1029
206
  if (pixman_filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION) {
1030
93
      int n_params;
1031
93
      pixman_fixed_t *params;
1032
93
      params = create_separable_convolution
1033
93
    (&n_params, kernel, dx, kernel, dy);
1034
93
      pixman_image_set_filter (pixman_image, pixman_filter,
1035
93
             params, n_params);
1036
93
      free (params);
1037
113
  } else {
1038
113
      pixman_image_set_filter (pixman_image, pixman_filter, NULL, 0);
1039
113
  }
1040
206
    }
1041
1042
206
    {
1043
206
  pixman_repeat_t pixman_repeat;
1044
1045
206
  switch (pattern->extend) {
1046
0
  default:
1047
1
  case CAIRO_EXTEND_NONE:
1048
1
      pixman_repeat = PIXMAN_REPEAT_NONE;
1049
1
      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
205
  case CAIRO_EXTEND_PAD:
1057
205
      pixman_repeat = PIXMAN_REPEAT_PAD;
1058
205
      break;
1059
206
  }
1060
1061
206
  pixman_image_set_repeat (pixman_image, pixman_repeat);
1062
206
    }
1063
1064
206
    if (pattern->has_component_alpha)
1065
0
  pixman_image_set_component_alpha (pixman_image, TRUE);
1066
1067
206
    return TRUE;
1068
206
}
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_calloc (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
  if (dst->base.foreground_source)
1224
0
      clone->foreground_source = cairo_pattern_reference (dst->base.foreground_source);
1225
0
    }
1226
1227
0
    m = NULL;
1228
0
    if (extend == CAIRO_EXTEND_NONE) {
1229
0
  matrix = pattern->base.matrix;
1230
0
  if (tx | ty)
1231
0
      cairo_matrix_translate (&matrix, tx, ty);
1232
0
  m = &matrix;
1233
0
    } else {
1234
0
  cairo_matrix_init_scale (&matrix, sx, sy);
1235
0
  cairo_matrix_translate (&matrix, src_limit.x/sx, src_limit.y/sy);
1236
0
  m = &matrix;
1237
0
    }
1238
1239
    /* Handle recursion by returning future reads from the current image */
1240
0
    proxy = attach_proxy (source, clone);
1241
0
    status = _cairo_recording_surface_replay_with_clip (source, m, clone, NULL);
1242
0
    if (clone->foreground_used)
1243
0
  dst->base.foreground_used = clone->foreground_used;
1244
0
    detach_proxy (source, proxy);
1245
0
    if (unlikely (status)) {
1246
0
  cairo_surface_destroy (clone);
1247
0
  return NULL;
1248
0
    }
1249
1250
0
done:
1251
0
    pixman_image = pixman_image_ref (((cairo_image_surface_t *)clone)->pixman_image);
1252
0
    cairo_surface_destroy (clone);
1253
1254
0
    if (extend == CAIRO_EXTEND_NONE) {
1255
0
  *ix = -limit.x;
1256
0
  *iy = -limit.y;
1257
0
    } else {
1258
0
  cairo_pattern_union_t tmp_pattern;
1259
0
  _cairo_pattern_init_static_copy (&tmp_pattern.base, &pattern->base);
1260
0
  matrix = pattern->base.matrix;
1261
0
  status = cairo_matrix_invert(&matrix);
1262
0
  assert (status == CAIRO_STATUS_SUCCESS);
1263
0
  cairo_matrix_translate (&matrix, src_limit.x, src_limit.y);
1264
0
  cairo_matrix_scale (&matrix, sx, sy);
1265
0
  status = cairo_matrix_invert(&matrix);
1266
0
  assert (status == CAIRO_STATUS_SUCCESS);
1267
0
  cairo_pattern_set_matrix (&tmp_pattern.base, &matrix);
1268
0
  if (! _pixman_image_set_properties (pixman_image,
1269
0
              &tmp_pattern.base, extents,
1270
0
              ix, iy)) {
1271
0
      pixman_image_unref (pixman_image);
1272
0
      pixman_image= NULL;
1273
0
  }
1274
0
    }
1275
1276
0
    return pixman_image;
1277
0
}
1278
1279
static pixman_image_t *
1280
_pixman_image_for_surface (cairo_image_surface_t *dst,
1281
         const cairo_surface_pattern_t *pattern,
1282
         cairo_bool_t is_mask,
1283
         const cairo_rectangle_int_t *extents,
1284
         const cairo_rectangle_int_t *sample,
1285
         int *ix, int *iy)
1286
490
{
1287
490
    cairo_extend_t extend = pattern->base.extend;
1288
490
    pixman_image_t *pixman_image;
1289
1290
490
    TRACE ((stderr, "%s\n", __FUNCTION__));
1291
1292
490
    *ix = *iy = 0;
1293
490
    pixman_image = NULL;
1294
490
    if (pattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
1295
0
  return _pixman_image_for_recording(dst, pattern,
1296
0
             is_mask, extents, sample,
1297
0
             ix, iy);
1298
1299
490
    if (pattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE &&
1300
490
  (! is_mask || ! pattern->base.has_component_alpha ||
1301
0
   (pattern->surface->content & CAIRO_CONTENT_COLOR) == 0))
1302
490
    {
1303
490
  cairo_surface_t *defer_free = NULL;
1304
490
  cairo_image_surface_t *source = (cairo_image_surface_t *) pattern->surface;
1305
490
  cairo_surface_type_t type;
1306
1307
490
  if (_cairo_surface_is_snapshot (&source->base)) {
1308
0
      defer_free = _cairo_surface_snapshot_get_target (&source->base);
1309
0
      source = (cairo_image_surface_t *) defer_free;
1310
0
  }
1311
1312
490
  type = source->base.backend->type;
1313
490
  if (type == CAIRO_SURFACE_TYPE_IMAGE) {
1314
490
      if (extend != CAIRO_EXTEND_NONE &&
1315
489
    sample->x >= 0 &&
1316
354
    sample->y >= 0 &&
1317
277
    sample->x + sample->width  <= source->width &&
1318
277
    sample->y + sample->height <= source->height)
1319
277
      {
1320
277
    extend = CAIRO_EXTEND_NONE;
1321
277
      }
1322
1323
490
      if (sample->width == 1 && sample->height == 1) {
1324
242
    if (sample->x < 0 ||
1325
242
        sample->y < 0 ||
1326
242
        sample->x >= source->width ||
1327
242
        sample->y >= source->height)
1328
0
    {
1329
0
        if (extend == CAIRO_EXTEND_NONE) {
1330
0
      cairo_surface_destroy (defer_free);
1331
0
      return _pixman_transparent_image ();
1332
0
        }
1333
0
    }
1334
242
    else
1335
242
    {
1336
242
        pixman_image = _pixel_to_solid (source,
1337
242
                sample->x, sample->y);
1338
242
                    if (pixman_image) {
1339
242
      cairo_surface_destroy (defer_free);
1340
242
                        return pixman_image;
1341
242
        }
1342
242
    }
1343
242
      }
1344
1345
#if PIXMAN_HAS_ATOMIC_OPS
1346
      /* avoid allocating a 'pattern' image if we can reuse the original */
1347
      if (extend == CAIRO_EXTEND_NONE &&
1348
    _cairo_matrix_is_pixman_translation (&pattern->base.matrix,
1349
                 pattern->base.filter,
1350
                 ix, iy))
1351
      {
1352
    cairo_surface_destroy (defer_free);
1353
    return pixman_image_ref (source->pixman_image);
1354
      }
1355
#endif
1356
1357
248
      pixman_image = pixman_image_create_bits (source->pixman_format,
1358
248
                 source->width,
1359
248
                 source->height,
1360
248
                 (uint32_t *) source->data,
1361
248
                 source->stride);
1362
248
      if (unlikely (pixman_image == NULL)) {
1363
0
    cairo_surface_destroy (defer_free);
1364
0
    return NULL;
1365
0
      }
1366
1367
248
      if (defer_free) {
1368
0
    pixman_image_set_destroy_function (pixman_image,
1369
0
               _defer_free_cleanup,
1370
0
               defer_free);
1371
0
      }
1372
248
  } else if (type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
1373
0
      cairo_surface_subsurface_t *sub;
1374
0
      cairo_bool_t is_contained = FALSE;
1375
1376
0
      sub = (cairo_surface_subsurface_t *) source;
1377
0
      source = (cairo_image_surface_t *) sub->target;
1378
1379
0
      if (sample->x >= 0 &&
1380
0
    sample->y >= 0 &&
1381
0
    sample->x + sample->width  <= sub->extents.width &&
1382
0
    sample->y + sample->height <= sub->extents.height)
1383
0
      {
1384
0
    is_contained = TRUE;
1385
0
      }
1386
1387
0
      if (sample->width == 1 && sample->height == 1) {
1388
0
    if (is_contained) {
1389
0
        pixman_image = _pixel_to_solid (source,
1390
0
                                                    sub->extents.x + sample->x,
1391
0
                                                    sub->extents.y + sample->y);
1392
0
                    if (pixman_image)
1393
0
                        return pixman_image;
1394
0
    } else {
1395
0
        if (extend == CAIRO_EXTEND_NONE)
1396
0
      return _pixman_transparent_image ();
1397
0
    }
1398
0
      }
1399
1400
#if PIXMAN_HAS_ATOMIC_OPS
1401
      *ix = sub->extents.x;
1402
      *iy = sub->extents.y;
1403
      if (is_contained &&
1404
    _cairo_matrix_is_pixman_translation (&pattern->base.matrix,
1405
                 pattern->base.filter,
1406
                 ix, iy))
1407
      {
1408
    return pixman_image_ref (source->pixman_image);
1409
      }
1410
#endif
1411
1412
      /* Avoid sub-byte offsets, force a copy in that case. */
1413
0
      if (PIXMAN_FORMAT_BPP (source->pixman_format) >= 8) {
1414
0
    if (is_contained) {
1415
0
        void *data = source->data
1416
0
      + sub->extents.x * PIXMAN_FORMAT_BPP(source->pixman_format)/8
1417
0
      + sub->extents.y * source->stride;
1418
0
        pixman_image = pixman_image_create_bits (source->pixman_format,
1419
0
                   sub->extents.width,
1420
0
                   sub->extents.height,
1421
0
                   data,
1422
0
                   source->stride);
1423
0
        if (unlikely (pixman_image == NULL))
1424
0
      return NULL;
1425
0
    } else {
1426
        /* XXX for a simple translation and EXTEND_NONE we can
1427
         * fix up the pattern matrix instead.
1428
         */
1429
0
    }
1430
0
      }
1431
0
  }
1432
490
    }
1433
1434
248
    if (pixman_image == NULL) {
1435
0
  struct acquire_source_cleanup *cleanup;
1436
0
  cairo_image_surface_t *image;
1437
0
  void *extra;
1438
0
  cairo_status_t status;
1439
1440
0
  status = _cairo_surface_acquire_source_image (pattern->surface, &image, &extra);
1441
0
  if (unlikely (status))
1442
0
      return NULL;
1443
1444
0
  pixman_image = pixman_image_create_bits (image->pixman_format,
1445
0
             image->width,
1446
0
             image->height,
1447
0
             (uint32_t *) image->data,
1448
0
             image->stride);
1449
0
  if (unlikely (pixman_image == NULL)) {
1450
0
      _cairo_surface_release_source_image (pattern->surface, image, extra);
1451
0
      return NULL;
1452
0
  }
1453
1454
0
  cleanup = _cairo_malloc (sizeof (*cleanup));
1455
0
  if (unlikely (cleanup == NULL)) {
1456
0
      _cairo_surface_release_source_image (pattern->surface, image, extra);
1457
0
      pixman_image_unref (pixman_image);
1458
0
      return NULL;
1459
0
  }
1460
1461
0
  cleanup->surface = pattern->surface;
1462
0
  cleanup->image = image;
1463
0
  cleanup->image_extra = extra;
1464
0
  pixman_image_set_destroy_function (pixman_image,
1465
0
             _acquire_source_cleanup, cleanup);
1466
0
    }
1467
1468
248
    if (! _pixman_image_set_properties (pixman_image,
1469
248
          &pattern->base, extents,
1470
248
          ix, iy)) {
1471
42
  pixman_image_unref (pixman_image);
1472
42
  pixman_image= NULL;
1473
42
    }
1474
1475
248
    return pixman_image;
1476
248
}
1477
1478
struct raster_source_cleanup {
1479
    const cairo_pattern_t *pattern;
1480
    cairo_surface_t *surface;
1481
    cairo_image_surface_t *image;
1482
    void *image_extra;
1483
};
1484
1485
static void
1486
_raster_source_cleanup (pixman_image_t *pixman_image,
1487
      void *closure)
1488
0
{
1489
0
    struct raster_source_cleanup *data = closure;
1490
1491
0
    _cairo_surface_release_source_image (data->surface,
1492
0
           data->image,
1493
0
           data->image_extra);
1494
1495
0
    _cairo_raster_source_pattern_release (data->pattern,
1496
0
            data->surface);
1497
1498
0
    free (data);
1499
0
}
1500
1501
static pixman_image_t *
1502
_pixman_image_for_raster (cairo_image_surface_t *dst,
1503
        const cairo_raster_source_pattern_t *pattern,
1504
        cairo_bool_t is_mask,
1505
        const cairo_rectangle_int_t *extents,
1506
        const cairo_rectangle_int_t *sample,
1507
        int *ix, int *iy)
1508
0
{
1509
0
    pixman_image_t *pixman_image;
1510
0
    struct raster_source_cleanup *cleanup;
1511
0
    cairo_image_surface_t *image;
1512
0
    void *extra;
1513
0
    cairo_status_t status;
1514
0
    cairo_surface_t *surface;
1515
1516
0
    TRACE ((stderr, "%s\n", __FUNCTION__));
1517
1518
0
    *ix = *iy = 0;
1519
1520
0
    surface = _cairo_raster_source_pattern_acquire (&pattern->base,
1521
0
                &dst->base, NULL);
1522
0
    if (unlikely (surface == NULL || surface->status))
1523
0
  return NULL;
1524
1525
0
    status = _cairo_surface_acquire_source_image (surface, &image, &extra);
1526
0
    if (unlikely (status)) {
1527
0
  _cairo_raster_source_pattern_release (&pattern->base, surface);
1528
0
  return NULL;
1529
0
    }
1530
1531
0
    assert (image->width == pattern->extents.width);
1532
0
    assert (image->height == pattern->extents.height);
1533
1534
0
    pixman_image = pixman_image_create_bits (image->pixman_format,
1535
0
               image->width,
1536
0
               image->height,
1537
0
               (uint32_t *) image->data,
1538
0
               image->stride);
1539
0
    if (unlikely (pixman_image == NULL)) {
1540
0
  _cairo_surface_release_source_image (surface, image, extra);
1541
0
  _cairo_raster_source_pattern_release (&pattern->base, surface);
1542
0
  return NULL;
1543
0
    }
1544
1545
0
    cleanup = _cairo_calloc (sizeof (*cleanup));
1546
0
    if (unlikely (cleanup == NULL)) {
1547
0
  pixman_image_unref (pixman_image);
1548
0
  _cairo_surface_release_source_image (surface, image, extra);
1549
0
  _cairo_raster_source_pattern_release (&pattern->base, surface);
1550
0
  return NULL;
1551
0
    }
1552
1553
0
    cleanup->pattern = &pattern->base;
1554
0
    cleanup->surface = surface;
1555
0
    cleanup->image = image;
1556
0
    cleanup->image_extra = extra;
1557
0
    pixman_image_set_destroy_function (pixman_image,
1558
0
               _raster_source_cleanup, cleanup);
1559
1560
0
    if (! _pixman_image_set_properties (pixman_image,
1561
0
          &pattern->base, extents,
1562
0
          ix, iy)) {
1563
0
  pixman_image_unref (pixman_image);
1564
0
  pixman_image= NULL;
1565
0
    }
1566
1567
0
    return pixman_image;
1568
0
}
1569
1570
pixman_image_t *
1571
_pixman_image_for_pattern (cairo_image_surface_t *dst,
1572
         const cairo_pattern_t *pattern,
1573
         cairo_bool_t is_mask,
1574
         const cairo_rectangle_int_t *extents,
1575
         const cairo_rectangle_int_t *sample,
1576
         int *tx, int *ty)
1577
31.3k
{
1578
31.3k
    *tx = *ty = 0;
1579
1580
31.3k
    TRACE ((stderr, "%s\n", __FUNCTION__));
1581
1582
31.3k
    if (pattern == NULL)
1583
0
  return _pixman_white_image ();
1584
1585
31.3k
    switch (pattern->type) {
1586
0
    default:
1587
0
  ASSERT_NOT_REACHED;
1588
28.3k
    case CAIRO_PATTERN_TYPE_SOLID:
1589
28.3k
  return _pixman_image_for_color (&((const cairo_solid_pattern_t *) pattern)->color);
1590
1591
1.86k
    case CAIRO_PATTERN_TYPE_RADIAL:
1592
2.47k
    case CAIRO_PATTERN_TYPE_LINEAR:
1593
2.47k
  return _pixman_image_for_gradient ((const cairo_gradient_pattern_t *) pattern,
1594
2.47k
             extents, tx, ty);
1595
1596
0
    case CAIRO_PATTERN_TYPE_MESH:
1597
0
  return _pixman_image_for_mesh ((const cairo_mesh_pattern_t *) pattern,
1598
0
             extents, tx, ty);
1599
1600
490
    case CAIRO_PATTERN_TYPE_SURFACE:
1601
490
  return _pixman_image_for_surface (dst,
1602
490
            (const cairo_surface_pattern_t *) pattern,
1603
490
            is_mask, extents, sample,
1604
490
            tx, ty);
1605
1606
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
1607
0
  return _pixman_image_for_raster (dst,
1608
0
           (const cairo_raster_source_pattern_t *) pattern,
1609
0
           is_mask, extents, sample,
1610
0
           tx, ty);
1611
31.3k
    }
1612
31.3k
}
1613
1614
static cairo_status_t
1615
_cairo_image_source_finish (void *abstract_surface)
1616
31.2k
{
1617
31.2k
    cairo_image_source_t *source = abstract_surface;
1618
1619
31.2k
    pixman_image_unref (source->pixman_image);
1620
31.2k
    return CAIRO_STATUS_SUCCESS;
1621
31.2k
}
1622
1623
const cairo_surface_backend_t _cairo_image_source_backend = {
1624
    CAIRO_SURFACE_TYPE_IMAGE,
1625
    _cairo_image_source_finish,
1626
    NULL, /* read-only wrapper */
1627
};
1628
1629
cairo_surface_t *
1630
_cairo_image_source_create_for_pattern (cairo_surface_t *dst,
1631
           const cairo_pattern_t *pattern,
1632
           cairo_bool_t is_mask,
1633
           const cairo_rectangle_int_t *extents,
1634
           const cairo_rectangle_int_t *sample,
1635
           int *src_x, int *src_y)
1636
31.3k
{
1637
31.3k
    cairo_image_source_t *source;
1638
1639
31.3k
    TRACE ((stderr, "%s\n", __FUNCTION__));
1640
1641
31.3k
    source = _cairo_calloc (sizeof (cairo_image_source_t));
1642
31.3k
    if (unlikely (source == NULL))
1643
0
  return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1644
1645
31.3k
    source->pixman_image =
1646
31.3k
  _pixman_image_for_pattern ((cairo_image_surface_t *)dst,
1647
31.3k
           pattern, is_mask,
1648
31.3k
           extents, sample,
1649
31.3k
           src_x, src_y);
1650
31.3k
    if (unlikely (source->pixman_image == NULL)) {
1651
42
  free (source);
1652
42
  return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
1653
42
    }
1654
1655
31.2k
    _cairo_surface_init (&source->base,
1656
31.2k
       &_cairo_image_source_backend,
1657
31.2k
       NULL, /* device */
1658
31.2k
       CAIRO_CONTENT_COLOR_ALPHA,
1659
31.2k
       FALSE); /* is_vector */
1660
1661
31.2k
    source->is_opaque_solid =
1662
31.2k
  pattern == NULL || _cairo_pattern_is_opaque_solid (pattern);
1663
1664
31.2k
    return &source->base;
1665
31.3k
}