Coverage Report

Created: 2025-12-08 09:28

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