Coverage Report

Created: 2026-03-31 11:00

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.07k
#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
29
{
184
29
    TRACE ((stderr, "%s\n", __FUNCTION__));
185
29
    return _pixman_image_for_color (CAIRO_COLOR_TRANSPARENT);
186
29
}
187
188
static pixman_image_t *
189
_pixman_black_image (void)
190
476
{
191
476
    TRACE ((stderr, "%s\n", __FUNCTION__));
192
476
    return _pixman_image_for_color (CAIRO_COLOR_BLACK);
193
476
}
194
195
static pixman_image_t *
196
_pixman_white_image (void)
197
27
{
198
27
    TRACE ((stderr, "%s\n", __FUNCTION__));
199
27
    return _pixman_image_for_color (CAIRO_COLOR_WHITE);
200
27
}
201
#endif /* !PIXMAN_HAS_ATOMIC_OPS */
202
203
204
pixman_image_t *
205
_pixman_image_for_color (const cairo_color_t *cairo_color)
206
50.3k
{
207
50.3k
    pixman_color_t color;
208
50.3k
    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
50.3k
    color.red   = cairo_color->red_short;
242
50.3k
    color.green = cairo_color->green_short;
243
50.3k
    color.blue  = cairo_color->blue_short;
244
50.3k
    color.alpha = cairo_color->alpha_short;
245
246
50.3k
    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
50.3k
    return image;
264
50.3k
}
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.07k
{
296
2.07k
    pixman_image_t    *pixman_image;
297
2.07k
    pixman_gradient_stop_t pixman_stops_static[2];
298
2.07k
    pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
299
2.07k
    pixman_transform_t      pixman_transform;
300
2.07k
    cairo_matrix_t matrix;
301
2.07k
    cairo_circle_double_t extremes[2];
302
2.07k
    pixman_point_fixed_t p1, p2;
303
2.07k
    unsigned int i;
304
2.07k
    cairo_int_status_t status;
305
306
2.07k
    TRACE ((stderr, "%s\n", __FUNCTION__));
307
308
2.07k
    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
6.21k
    for (i = 0; i < pattern->n_stops; i++) {
316
4.14k
  pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
317
4.14k
  pixman_stops[i].color.red   = pattern->stops[i].color.red_short;
318
4.14k
  pixman_stops[i].color.green = pattern->stops[i].color.green_short;
319
4.14k
  pixman_stops[i].color.blue  = pattern->stops[i].color.blue_short;
320
4.14k
  pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
321
4.14k
    }
322
323
2.07k
    _cairo_gradient_pattern_fit_to_range (pattern, PIXMAN_MAX_INT >> 1, &matrix, extremes);
324
325
2.07k
    p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
326
2.07k
    p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
327
2.07k
    p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
328
2.07k
    p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
329
330
2.07k
    if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
331
658
  pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
332
658
                  pixman_stops,
333
658
                  pattern->n_stops);
334
1.41k
    } else {
335
1.41k
  pixman_fixed_t r1, r2;
336
337
1.41k
  r1   = _cairo_fixed_16_16_from_double (extremes[0].radius);
338
1.41k
  r2   = _cairo_fixed_16_16_from_double (extremes[1].radius);
339
340
1.41k
  pixman_image = pixman_image_create_radial_gradient (&p1, &p2, r1, r2,
341
1.41k
                  pixman_stops,
342
1.41k
                  pattern->n_stops);
343
1.41k
    }
344
345
2.07k
    if (pixman_stops != pixman_stops_static)
346
0
  free (pixman_stops);
347
348
2.07k
    if (unlikely (pixman_image == NULL))
349
0
  return NULL;
350
351
2.07k
    *ix = *iy = 0;
352
2.07k
    status = _cairo_matrix_to_pixman_matrix_offset (&matrix, pattern->base.filter,
353
2.07k
                extents->x + extents->width/2.,
354
2.07k
                extents->y + extents->height/2.,
355
2.07k
                &pixman_transform, ix, iy);
356
2.07k
    if (status != CAIRO_INT_STATUS_NOTHING_TO_DO) {
357
1.15k
  if (unlikely (status != CAIRO_INT_STATUS_SUCCESS) ||
358
1.15k
      ! 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.15k
    }
364
365
2.07k
    {
366
2.07k
  pixman_repeat_t pixman_repeat;
367
368
2.07k
  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.07k
  case CAIRO_EXTEND_PAD:
380
2.07k
      pixman_repeat = PIXMAN_REPEAT_PAD;
381
2.07k
      break;
382
2.07k
  }
383
384
2.07k
  pixman_image_set_repeat (pixman_image, pixman_repeat);
385
2.07k
    }
386
387
0
    return pixman_image;
388
2.07k
}
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
537
{
457
537
    uint32_t pixel;
458
537
    float *rgba;
459
537
    pixman_color_t color;
460
461
537
    TRACE ((stderr, "%s\n", __FUNCTION__));
462
463
537
    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
537
    case CAIRO_FORMAT_ARGB32:
526
537
    case CAIRO_FORMAT_RGB24:
527
537
  pixel = *(uint32_t *) (image->data + y * image->stride + 4 * x);
528
537
  color.alpha = image->format == CAIRO_FORMAT_ARGB32 ? (pixel >> 24) | (pixel >> 16 & 0xff00) : 0xffff;
529
537
  if (color.alpha == 0)
530
29
      return _pixman_transparent_image ();
531
508
  if (pixel == 0xffffffff)
532
27
      return _pixman_white_image ();
533
481
  if (color.alpha == 0xffff && (pixel & 0xffffff) == 0)
534
476
      return _pixman_black_image ();
535
536
5
  color.red = (pixel >> 16 & 0xff) | (pixel >> 8 & 0xff00);
537
5
  color.green = (pixel >> 8 & 0xff) | (pixel & 0xff00);
538
5
  color.blue = (pixel & 0xff) | (pixel << 8 & 0xff00);
539
5
  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
537
    }
567
537
}
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
150k
{
638
150k
    return MAX (0.0, MIN (MIN (r, 1.0),
639
150k
        MIN ((r + 1) / 2 - x, (r + 1) / 2 + x)));
640
150k
}
641
642
static int
643
box_width (double r)
644
430
{
645
430
    return r < 1.0 ? 2 : ceil(r + 1);
646
430
}
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
430
{
846
430
    int i;
847
430
    pixman_fixed_t *p = out;
848
430
    int n_phases = 1 << subsample;
849
430
    double step = 1.0 / n_phases;
850
430
    kernel_func_t func = filters[filter].func;
851
852
    /* special-case the impulse filter: */
853
430
    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
59.2k
    for (i = 0; i < n_phases; ++i)
861
58.8k
    {
862
58.8k
  double frac = (i + .5) * step;
863
  /* Center of left-most pixel: */
864
58.8k
  double x1 = ceil (frac - width / 2.0 - 0.5) - frac + 0.5;
865
58.8k
  double total = 0;
866
58.8k
  pixman_fixed_t new_total = 0;
867
58.8k
  int j;
868
869
209k
  for (j = 0; j < width; ++j)
870
150k
  {
871
150k
      double v = func(x1 + j, r);
872
150k
      total += v;
873
150k
      p[j] = pixman_double_to_fixed (v);
874
150k
  }
875
876
  /* Normalize */
877
58.8k
        total = 1 / total;
878
209k
  for (j = 0; j < width; ++j)
879
150k
      new_total += (p[j] *= total);
880
881
  /* Put any error on center pixel */
882
58.8k
  p[width / 2] += (pixman_fixed_1 - new_total);
883
884
58.8k
  p += width;
885
58.8k
    }
886
430
}
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
215
{
899
215
    int xwidth, xsubsample, ywidth, ysubsample, size_x, size_y;
900
215
    pixman_fixed_t *params;
901
902
215
    xwidth = filters[xfilter].width(sx);
903
215
    xsubsample = 0;
904
215
    if (xwidth > 1)
905
1.31k
  while (sx * (1 << xsubsample) <= 128.0) xsubsample++;
906
215
    size_x = (1 << xsubsample) * xwidth;
907
908
215
    ywidth = filters[yfilter].width(sy);
909
215
    ysubsample = 0;
910
215
    if (ywidth > 1)
911
1.86k
  while (sy * (1 << ysubsample) <= 128.0) ysubsample++;
912
215
    size_y = (1 << ysubsample) * ywidth;
913
914
215
    *n_values = 4 + size_x + size_y;
915
215
    params = _cairo_malloc (*n_values * sizeof (pixman_fixed_t));
916
215
    if (!params) return 0;
917
918
215
    params[0] = pixman_int_to_fixed (xwidth);
919
215
    params[1] = pixman_int_to_fixed (ywidth);
920
215
    params[2] = pixman_int_to_fixed (xsubsample);
921
215
    params[3] = pixman_int_to_fixed (ysubsample);
922
923
215
    get_filter(xfilter, sx, xwidth, xsubsample, params + 4);
924
215
    get_filter(yfilter, sy, ywidth, ysubsample, params + 4 + size_x);
925
926
215
    return params;
927
215
}
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
365
{
937
365
    pixman_transform_t pixman_transform;
938
365
    cairo_int_status_t status;
939
940
365
    status = _cairo_matrix_to_pixman_matrix_offset (&pattern->matrix,
941
365
                pattern->filter,
942
365
                extents->x + extents->width/2.,
943
365
                extents->y + extents->height/2.,
944
365
                &pixman_transform, ix, iy);
945
365
    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
365
    else if (unlikely (status != CAIRO_INT_STATUS_SUCCESS ||
952
365
           ! pixman_image_set_transform (pixman_image,
953
365
                 &pixman_transform)))
954
5
    {
955
5
  return FALSE;
956
5
    }
957
360
    else
958
360
    {
959
360
  pixman_filter_t pixman_filter;
960
360
  kernel_t kernel;
961
360
  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
360
  dx = hypot (pattern->matrix.xx, pattern->matrix.xy);
971
360
  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
360
  if (! (dx < 0x7FFF)) dx = 0x7FFF;
977
360
  if (! (dy < 0x7FFF)) dy = 0x7FFF;
978
979
360
  switch (pattern->filter) {
980
0
  case CAIRO_FILTER_FAST:
981
0
      pixman_filter = PIXMAN_FILTER_FAST;
982
0
      break;
983
215
  case CAIRO_FILTER_GOOD:
984
215
      pixman_filter = PIXMAN_FILTER_SEPARABLE_CONVOLUTION;
985
215
      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
215
      if (dx > 16.0) dx = 16.0;
989
215
      if (dy > 16.0) dy = 16.0;
990
      /* Match the bilinear filter for scales > .75: */
991
215
      if (dx < 1.0/0.75) dx = 1.0;
992
215
      if (dy < 1.0/0.75) dy = 1.0;
993
215
      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
29
  case CAIRO_FILTER_NEAREST:
1014
29
      pixman_filter = PIXMAN_FILTER_NEAREST;
1015
29
      break;
1016
116
  case CAIRO_FILTER_BILINEAR:
1017
116
      pixman_filter = PIXMAN_FILTER_BILINEAR;
1018
116
      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
360
  }
1028
1029
360
  if (pixman_filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION) {
1030
215
      int n_params;
1031
215
      pixman_fixed_t *params;
1032
215
      params = create_separable_convolution
1033
215
    (&n_params, kernel, dx, kernel, dy);
1034
215
      pixman_image_set_filter (pixman_image, pixman_filter,
1035
215
             params, n_params);
1036
215
      free (params);
1037
215
  } else {
1038
145
      pixman_image_set_filter (pixman_image, pixman_filter, NULL, 0);
1039
145
  }
1040
360
    }
1041
1042
360
    {
1043
360
  pixman_repeat_t pixman_repeat;
1044
1045
360
  switch (pattern->extend) {
1046
0
  default:
1047
4
  case CAIRO_EXTEND_NONE:
1048
4
      pixman_repeat = PIXMAN_REPEAT_NONE;
1049
4
      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
356
  case CAIRO_EXTEND_PAD:
1057
356
      pixman_repeat = PIXMAN_REPEAT_PAD;
1058
356
      break;
1059
360
  }
1060
1061
360
  pixman_image_set_repeat (pixman_image, pixman_repeat);
1062
360
    }
1063
1064
360
    if (pattern->has_component_alpha)
1065
0
  pixman_image_set_component_alpha (pixman_image, TRUE);
1066
1067
360
    return TRUE;
1068
360
}
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
902
{
1287
902
    cairo_extend_t extend = pattern->base.extend;
1288
902
    pixman_image_t *pixman_image;
1289
1290
902
    TRACE ((stderr, "%s\n", __FUNCTION__));
1291
1292
902
    *ix = *iy = 0;
1293
902
    pixman_image = NULL;
1294
902
    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
902
    if (pattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE &&
1300
902
  (! is_mask || ! pattern->base.has_component_alpha ||
1301
0
   (pattern->surface->content & CAIRO_CONTENT_COLOR) == 0))
1302
902
    {
1303
902
  cairo_surface_t *defer_free = NULL;
1304
902
  cairo_image_surface_t *source = (cairo_image_surface_t *) pattern->surface;
1305
902
  cairo_surface_type_t type;
1306
1307
902
  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
902
  type = source->base.backend->type;
1313
902
  if (type == CAIRO_SURFACE_TYPE_IMAGE) {
1314
902
      if (extend != CAIRO_EXTEND_NONE &&
1315
898
    sample->x >= 0 &&
1316
783
    sample->y >= 0 &&
1317
560
    sample->x + sample->width  <= source->width &&
1318
560
    sample->y + sample->height <= source->height)
1319
559
      {
1320
559
    extend = CAIRO_EXTEND_NONE;
1321
559
      }
1322
1323
902
      if (sample->width == 1 && sample->height == 1) {
1324
542
    if (sample->x < 0 ||
1325
537
        sample->y < 0 ||
1326
537
        sample->x >= source->width ||
1327
537
        sample->y >= source->height)
1328
5
    {
1329
5
        if (extend == CAIRO_EXTEND_NONE) {
1330
0
      cairo_surface_destroy (defer_free);
1331
0
      return _pixman_transparent_image ();
1332
0
        }
1333
5
    }
1334
537
    else
1335
537
    {
1336
537
        pixman_image = _pixel_to_solid (source,
1337
537
                sample->x, sample->y);
1338
537
                    if (pixman_image) {
1339
537
      cairo_surface_destroy (defer_free);
1340
537
                        return pixman_image;
1341
537
        }
1342
537
    }
1343
542
      }
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
365
      pixman_image = pixman_image_create_bits (source->pixman_format,
1358
365
                 source->width,
1359
365
                 source->height,
1360
365
                 (uint32_t *) source->data,
1361
365
                 source->stride);
1362
365
      if (unlikely (pixman_image == NULL)) {
1363
0
    cairo_surface_destroy (defer_free);
1364
0
    return NULL;
1365
0
      }
1366
1367
365
      if (defer_free) {
1368
0
    pixman_image_set_destroy_function (pixman_image,
1369
0
               _defer_free_cleanup,
1370
0
               defer_free);
1371
0
      }
1372
365
  } 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
902
    }
1433
1434
365
    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
365
    if (! _pixman_image_set_properties (pixman_image,
1469
365
          &pattern->base, extents,
1470
365
          ix, iy)) {
1471
5
  pixman_image_unref (pixman_image);
1472
5
  pixman_image= NULL;
1473
5
    }
1474
1475
365
    return pixman_image;
1476
365
}
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
52.4k
{
1578
52.4k
    *tx = *ty = 0;
1579
1580
52.4k
    TRACE ((stderr, "%s\n", __FUNCTION__));
1581
1582
52.4k
    if (pattern == NULL)
1583
0
  return _pixman_white_image ();
1584
1585
52.4k
    switch (pattern->type) {
1586
0
    default:
1587
0
  ASSERT_NOT_REACHED;
1588
49.4k
    case CAIRO_PATTERN_TYPE_SOLID:
1589
49.4k
  return _pixman_image_for_color (&((const cairo_solid_pattern_t *) pattern)->color);
1590
1591
1.41k
    case CAIRO_PATTERN_TYPE_RADIAL:
1592
2.07k
    case CAIRO_PATTERN_TYPE_LINEAR:
1593
2.07k
  return _pixman_image_for_gradient ((const cairo_gradient_pattern_t *) pattern,
1594
2.07k
             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
902
    case CAIRO_PATTERN_TYPE_SURFACE:
1601
902
  return _pixman_image_for_surface (dst,
1602
902
            (const cairo_surface_pattern_t *) pattern,
1603
902
            is_mask, extents, sample,
1604
902
            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
52.4k
    }
1612
52.4k
}
1613
1614
static cairo_status_t
1615
_cairo_image_source_finish (void *abstract_surface)
1616
52.4k
{
1617
52.4k
    cairo_image_source_t *source = abstract_surface;
1618
1619
52.4k
    pixman_image_unref (source->pixman_image);
1620
52.4k
    return CAIRO_STATUS_SUCCESS;
1621
52.4k
}
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
52.4k
{
1637
52.4k
    cairo_image_source_t *source;
1638
1639
52.4k
    TRACE ((stderr, "%s\n", __FUNCTION__));
1640
1641
52.4k
    source = _cairo_calloc (sizeof (cairo_image_source_t));
1642
52.4k
    if (unlikely (source == NULL))
1643
0
  return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1644
1645
52.4k
    source->pixman_image =
1646
52.4k
  _pixman_image_for_pattern ((cairo_image_surface_t *)dst,
1647
52.4k
           pattern, is_mask,
1648
52.4k
           extents, sample,
1649
52.4k
           src_x, src_y);
1650
52.4k
    if (unlikely (source->pixman_image == NULL)) {
1651
5
  free (source);
1652
5
  return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
1653
5
    }
1654
1655
52.4k
    _cairo_surface_init (&source->base,
1656
52.4k
       &_cairo_image_source_backend,
1657
52.4k
       NULL, /* device */
1658
52.4k
       CAIRO_CONTENT_COLOR_ALPHA,
1659
52.4k
       FALSE); /* is_vector */
1660
1661
52.4k
    source->is_opaque_solid =
1662
52.4k
  pattern == NULL || _cairo_pattern_is_opaque_solid (pattern);
1663
1664
52.4k
    return &source->base;
1665
52.4k
}