Coverage Report

Created: 2026-09-28 10:59

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