Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/work/workdir/UnpackedTarball/cairo/src/cairo-pattern.c
Line
Count
Source
1
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2
/* cairo - a vector graphics library with display and print output
3
 *
4
 * Copyright © 2004 David Reveman
5
 * Copyright © 2005 Red Hat, Inc.
6
 *
7
 * Permission to use, copy, modify, distribute, and sell this software
8
 * and its documentation for any purpose is hereby granted without
9
 * fee, provided that the above copyright notice appear in all copies
10
 * and that both that copyright notice and this permission notice
11
 * appear in supporting documentation, and that the name of David
12
 * Reveman not be used in advertising or publicity pertaining to
13
 * distribution of the software without specific, written prior
14
 * permission. David Reveman makes no representations about the
15
 * suitability of this software for any purpose.  It is provided "as
16
 * is" without express or implied warranty.
17
 *
18
 * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
19
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
20
 * FITNESS, IN NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL,
21
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
22
 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
23
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
24
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
 *
26
 * Authors: David Reveman <davidr@novell.com>
27
 *      Keith Packard <keithp@keithp.com>
28
 *      Carl Worth <cworth@cworth.org>
29
 */
30
31
#include "cairoint.h"
32
33
#include "cairo-array-private.h"
34
#include "cairo-error-private.h"
35
#include "cairo-freed-pool-private.h"
36
#include "cairo-image-surface-private.h"
37
#include "cairo-list-inline.h"
38
#include "cairo-path-private.h"
39
#include "cairo-pattern-private.h"
40
#include "cairo-recording-surface-inline.h"
41
#include "cairo-surface-snapshot-inline.h"
42
43
#include <float.h>
44
45
#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
46
47
/**
48
 * SECTION:cairo-pattern
49
 * @Title: cairo_pattern_t
50
 * @Short_Description: Sources for drawing
51
 * @See_Also: #cairo_t, #cairo_surface_t
52
 *
53
 * #cairo_pattern_t is the paint with which cairo draws.
54
 * The primary use of patterns is as the source for all cairo drawing
55
 * operations, although they can also be used as masks, that is, as the
56
 * brush too.
57
 *
58
 * A cairo pattern is created by using one of the many constructors,
59
 * of the form
60
 * <function>cairo_pattern_create_<emphasis>type</emphasis>()</function>
61
 * or implicitly through
62
 * <function>cairo_set_source_<emphasis>type</emphasis>()</function>
63
 * functions.
64
 **/
65
66
/**
67
 * CAIRO_HAS_MIME_SURFACE:
68
 *
69
 * Unused symbol, always defined.
70
 *
71
 * Since: 1.12
72
 **/
73
74
static freed_pool_t freed_pattern_pool[5];
75
76
static const cairo_solid_pattern_t _cairo_pattern_nil = {
77
    {
78
      CAIRO_REFERENCE_COUNT_INVALID,  /* ref_count */
79
      CAIRO_STATUS_NO_MEMORY,   /* status */
80
      { 0, 0, 0, NULL },    /* user_data */
81
      { NULL, NULL },     /* observers */
82
83
      CAIRO_PATTERN_TYPE_SOLID,   /* type */
84
      CAIRO_FILTER_DEFAULT,   /* filter */
85
      CAIRO_EXTEND_GRADIENT_DEFAULT,  /* extend */
86
      FALSE,        /* has component alpha */
87
      FALSE,        /* is_foreground_marker */
88
      CAIRO_DITHER_DEFAULT,   /* dither */
89
      { 1., 0., 0., 1., 0., 0., },  /* matrix */
90
      1.0                               /* opacity */
91
    }
92
};
93
94
static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = {
95
    {
96
      CAIRO_REFERENCE_COUNT_INVALID,  /* ref_count */
97
      CAIRO_STATUS_NULL_POINTER,  /* status */
98
      { 0, 0, 0, NULL },    /* user_data */
99
      { NULL, NULL },     /* observers */
100
101
      CAIRO_PATTERN_TYPE_SOLID,   /* type */
102
      CAIRO_FILTER_DEFAULT,   /* filter */
103
      CAIRO_EXTEND_GRADIENT_DEFAULT,  /* extend */
104
      FALSE,        /* has component alpha */
105
      FALSE,        /* is_foreground_marker */
106
      CAIRO_DITHER_DEFAULT,   /* dither */
107
      { 1., 0., 0., 1., 0., 0., },  /* matrix */
108
      1.0                               /* opacity */
109
    }
110
};
111
112
const cairo_solid_pattern_t _cairo_pattern_black = {
113
    {
114
      CAIRO_REFERENCE_COUNT_INVALID,  /* ref_count */
115
      CAIRO_STATUS_SUCCESS,   /* status */
116
      { 0, 0, 0, NULL },    /* user_data */
117
      { NULL, NULL },     /* observers */
118
119
      CAIRO_PATTERN_TYPE_SOLID,   /* type */
120
      CAIRO_FILTER_NEAREST,   /* filter */
121
      CAIRO_EXTEND_REPEAT,    /* extend */
122
      FALSE,        /* has component alpha */
123
      FALSE,        /* is_foreground_marker */
124
      CAIRO_DITHER_DEFAULT,   /* dither */
125
      { 1., 0., 0., 1., 0., 0., },  /* matrix */
126
      1.0                               /* opacity */
127
    },
128
    { 0., 0., 0., 1., 0, 0, 0, 0xffff },/* color (double rgba, short rgba) */
129
};
130
131
const cairo_solid_pattern_t _cairo_pattern_clear = {
132
    {
133
      CAIRO_REFERENCE_COUNT_INVALID,  /* ref_count */
134
      CAIRO_STATUS_SUCCESS,   /* status */
135
      { 0, 0, 0, NULL },    /* user_data */
136
      { NULL, NULL },     /* observers */
137
138
      CAIRO_PATTERN_TYPE_SOLID,   /* type */
139
      CAIRO_FILTER_NEAREST,   /* filter */
140
      CAIRO_EXTEND_REPEAT,    /* extend */
141
      FALSE,        /* has component alpha */
142
      FALSE,        /* is_foreground_marker */
143
      CAIRO_DITHER_DEFAULT,   /* dither */
144
      { 1., 0., 0., 1., 0., 0., },  /* matrix */
145
      1.0                               /* opacity */
146
    },
147
    { 0., 0., 0., 0., 0, 0, 0, 0 },/* color (double rgba, short rgba) */
148
};
149
150
const cairo_solid_pattern_t _cairo_pattern_white = {
151
    {
152
      CAIRO_REFERENCE_COUNT_INVALID,  /* ref_count */
153
      CAIRO_STATUS_SUCCESS,   /* status */
154
      { 0, 0, 0, NULL },    /* user_data */
155
      { NULL, NULL },     /* observers */
156
157
      CAIRO_PATTERN_TYPE_SOLID,   /* type */
158
      CAIRO_FILTER_NEAREST,   /* filter */
159
      CAIRO_EXTEND_REPEAT,    /* extend */
160
      FALSE,        /* has component alpha */
161
      FALSE,        /* is_foreground_marker */
162
      CAIRO_DITHER_DEFAULT,   /* dither */
163
      { 1., 0., 0., 1., 0., 0., },  /* matrix */
164
      1.0                               /* opacity */
165
    },
166
    { 1., 1., 1., 1., 0xffff, 0xffff, 0xffff, 0xffff },/* color (double rgba, short rgba) */
167
};
168
169
static void
170
_cairo_pattern_notify_observers (cairo_pattern_t *pattern,
171
         unsigned int flags)
172
535k
{
173
535k
    cairo_pattern_observer_t *pos;
174
175
535k
    cairo_list_foreach_entry (pos, cairo_pattern_observer_t, &pattern->observers, link)
176
0
  pos->notify (pos, pattern, flags);
177
535k
}
178
179
/**
180
 * _cairo_pattern_set_error:
181
 * @pattern: a pattern
182
 * @status: a status value indicating an error
183
 *
184
 * Atomically sets pattern->status to @status and calls _cairo_error;
185
 * Does nothing if status is %CAIRO_STATUS_SUCCESS.
186
 *
187
 * All assignments of an error status to pattern->status should happen
188
 * through _cairo_pattern_set_error(). Note that due to the nature of
189
 * the atomic operation, it is not safe to call this function on the nil
190
 * objects.
191
 *
192
 * The purpose of this function is to allow the user to set a
193
 * breakpoint in _cairo_error() to generate a stack trace for when the
194
 * user causes cairo to detect an error.
195
 **/
196
static cairo_status_t
197
_cairo_pattern_set_error (cairo_pattern_t *pattern,
198
        cairo_status_t status)
199
0
{
200
0
    if (status == CAIRO_STATUS_SUCCESS)
201
0
  return status;
202
203
    /* Don't overwrite an existing error. This preserves the first
204
     * error, which is the most significant. */
205
0
    _cairo_status_set_error (&pattern->status, status);
206
207
0
    return _cairo_error (status);
208
0
}
209
210
void
211
_cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
212
6.10M
{
213
#if HAVE_VALGRIND
214
    switch (type) {
215
    case CAIRO_PATTERN_TYPE_SOLID:
216
  VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t));
217
  break;
218
    case CAIRO_PATTERN_TYPE_SURFACE:
219
  VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t));
220
  break;
221
    case CAIRO_PATTERN_TYPE_LINEAR:
222
  VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t));
223
  break;
224
    case CAIRO_PATTERN_TYPE_RADIAL:
225
  VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t));
226
  break;
227
    case CAIRO_PATTERN_TYPE_MESH:
228
  VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t));
229
  break;
230
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
231
  break;
232
    }
233
#endif
234
235
6.10M
    pattern->type      = type;
236
6.10M
    pattern->status    = CAIRO_STATUS_SUCCESS;
237
238
    /* Set the reference count to zero for on-stack patterns.
239
     * Callers needs to explicitly increment the count for heap allocations. */
240
6.10M
    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
241
242
6.10M
    _cairo_user_data_array_init (&pattern->user_data);
243
244
6.10M
    if (type == CAIRO_PATTERN_TYPE_SURFACE ||
245
5.58M
  type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
246
516k
  pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
247
5.58M
    else
248
5.58M
  pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT;
249
250
6.10M
    pattern->filter    = CAIRO_FILTER_DEFAULT;
251
6.10M
    pattern->opacity   = 1.0;
252
253
6.10M
    pattern->has_component_alpha = FALSE;
254
6.10M
    pattern->is_foreground_marker = FALSE;
255
256
6.10M
    pattern->dither    = CAIRO_DITHER_DEFAULT;
257
258
6.10M
    cairo_matrix_init_identity (&pattern->matrix);
259
260
6.10M
    cairo_list_init (&pattern->observers);
261
6.10M
}
262
263
static cairo_status_t
264
_cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t   *pattern,
265
           const cairo_gradient_pattern_t *other)
266
0
{
267
0
    if (CAIRO_INJECT_FAULT ())
268
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
269
270
0
    if (other->base.type == CAIRO_PATTERN_TYPE_LINEAR)
271
0
    {
272
0
  cairo_linear_pattern_t *dst = (cairo_linear_pattern_t *) pattern;
273
0
  cairo_linear_pattern_t *src = (cairo_linear_pattern_t *) other;
274
275
0
  *dst = *src;
276
0
    }
277
0
    else
278
0
    {
279
0
  cairo_radial_pattern_t *dst = (cairo_radial_pattern_t *) pattern;
280
0
  cairo_radial_pattern_t *src = (cairo_radial_pattern_t *) other;
281
282
0
  *dst = *src;
283
0
    }
284
285
0
    if (other->stops == other->stops_embedded)
286
0
  pattern->stops = pattern->stops_embedded;
287
0
    else if (other->stops)
288
0
    {
289
0
  pattern->stops = _cairo_malloc_ab (other->stops_size,
290
0
             sizeof (cairo_gradient_stop_t));
291
0
  if (unlikely (pattern->stops == NULL)) {
292
0
      pattern->stops_size = 0;
293
0
      pattern->n_stops = 0;
294
0
      return _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
295
0
  }
296
297
0
  memcpy (pattern->stops, other->stops,
298
0
    other->n_stops * sizeof (cairo_gradient_stop_t));
299
0
    }
300
301
0
    return CAIRO_STATUS_SUCCESS;
302
0
}
303
304
static cairo_status_t
305
_cairo_mesh_pattern_init_copy (cairo_mesh_pattern_t       *pattern,
306
             const cairo_mesh_pattern_t *other)
307
0
{
308
0
    *pattern = *other;
309
310
0
    _cairo_array_init (&pattern->patches,  sizeof (cairo_mesh_patch_t));
311
0
    return _cairo_array_append_multiple (&pattern->patches,
312
0
           _cairo_array_index_const (&other->patches, 0),
313
0
           _cairo_array_num_elements (&other->patches));
314
0
}
315
316
cairo_status_t
317
_cairo_pattern_init_copy (cairo_pattern_t *pattern,
318
        const cairo_pattern_t *other)
319
0
{
320
0
    cairo_status_t status;
321
322
0
    if (other->status)
323
0
  return _cairo_pattern_set_error (pattern, other->status);
324
325
0
    switch (other->type) {
326
0
    case CAIRO_PATTERN_TYPE_SOLID: {
327
0
  cairo_solid_pattern_t *dst = (cairo_solid_pattern_t *) pattern;
328
0
  cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) other;
329
330
0
  VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t)));
331
332
0
  *dst = *src;
333
0
    } break;
334
0
    case CAIRO_PATTERN_TYPE_SURFACE: {
335
0
  cairo_surface_pattern_t *dst = (cairo_surface_pattern_t *) pattern;
336
0
  cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) other;
337
338
0
  VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t)));
339
340
0
  *dst = *src;
341
0
  cairo_surface_reference (dst->surface);
342
0
    } break;
343
0
    case CAIRO_PATTERN_TYPE_LINEAR:
344
0
    case CAIRO_PATTERN_TYPE_RADIAL: {
345
0
  cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern;
346
0
  cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other;
347
348
0
  if (other->type == CAIRO_PATTERN_TYPE_LINEAR) {
349
0
      VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t)));
350
0
  } else {
351
0
      VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t)));
352
0
  }
353
354
0
  status = _cairo_gradient_pattern_init_copy (dst, src);
355
0
  if (unlikely (status))
356
0
      return status;
357
358
0
    } break;
359
0
    case CAIRO_PATTERN_TYPE_MESH: {
360
0
  cairo_mesh_pattern_t *dst = (cairo_mesh_pattern_t *) pattern;
361
0
  cairo_mesh_pattern_t *src = (cairo_mesh_pattern_t *) other;
362
363
0
  VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t)));
364
365
0
  status = _cairo_mesh_pattern_init_copy (dst, src);
366
0
  if (unlikely (status))
367
0
      return status;
368
369
0
    } break;
370
371
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE: {
372
0
  status = _cairo_raster_source_pattern_init_copy (pattern, other);
373
0
  if (unlikely (status))
374
0
      return status;
375
0
    } break;
376
0
    }
377
378
    /* The reference count and user_data array are unique to the copy. */
379
0
    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
380
0
    _cairo_user_data_array_init (&pattern->user_data);
381
0
    cairo_list_init (&pattern->observers);
382
383
0
    return CAIRO_STATUS_SUCCESS;
384
0
}
385
386
void
387
_cairo_pattern_init_static_copy (cairo_pattern_t  *pattern,
388
         const cairo_pattern_t *other)
389
26.3M
{
390
26.3M
    int size;
391
392
26.3M
    assert (other->status == CAIRO_STATUS_SUCCESS);
393
394
26.3M
    switch (other->type) {
395
0
    default:
396
0
  ASSERT_NOT_REACHED;
397
25.3M
    case CAIRO_PATTERN_TYPE_SOLID:
398
25.3M
  size = sizeof (cairo_solid_pattern_t);
399
25.3M
  break;
400
1.02M
    case CAIRO_PATTERN_TYPE_SURFACE:
401
1.02M
  size = sizeof (cairo_surface_pattern_t);
402
1.02M
  break;
403
1.20k
    case CAIRO_PATTERN_TYPE_LINEAR:
404
1.20k
  size = sizeof (cairo_linear_pattern_t);
405
1.20k
  break;
406
3.82k
    case CAIRO_PATTERN_TYPE_RADIAL:
407
3.82k
  size = sizeof (cairo_radial_pattern_t);
408
3.82k
  break;
409
0
    case CAIRO_PATTERN_TYPE_MESH:
410
0
  size = sizeof (cairo_mesh_pattern_t);
411
0
  break;
412
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
413
0
  size = sizeof (cairo_raster_source_pattern_t);
414
0
  break;
415
26.3M
    }
416
417
26.3M
    memcpy (pattern, other, size);
418
419
26.3M
    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
420
26.3M
    _cairo_user_data_array_init (&pattern->user_data);
421
26.3M
    cairo_list_init (&pattern->observers);
422
26.3M
}
423
424
cairo_status_t
425
_cairo_pattern_init_snapshot (cairo_pattern_t       *pattern,
426
            const cairo_pattern_t *other)
427
0
{
428
0
    cairo_status_t status;
429
430
    /* We don't bother doing any fancy copy-on-write implementation
431
     * for the pattern's data. It's generally quite tiny. */
432
0
    status = _cairo_pattern_init_copy (pattern, other);
433
0
    if (unlikely (status))
434
0
  return status;
435
436
    /* But we do let the surface snapshot stuff be as fancy as it
437
     * would like to be. */
438
0
    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
439
0
  cairo_surface_pattern_t *surface_pattern =
440
0
      (cairo_surface_pattern_t *) pattern;
441
0
  cairo_surface_t *surface = surface_pattern->surface;
442
443
0
  surface_pattern->surface = _cairo_surface_snapshot (surface);
444
445
0
  cairo_surface_destroy (surface);
446
447
0
  status = surface_pattern->surface->status;
448
0
    } else if (pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
449
0
  status = _cairo_raster_source_pattern_snapshot (pattern);
450
451
0
    return status;
452
0
}
453
454
void
455
_cairo_pattern_fini (cairo_pattern_t *pattern)
456
6.07M
{
457
6.07M
    _cairo_user_data_array_fini (&pattern->user_data);
458
459
6.07M
    switch (pattern->type) {
460
5.55M
    case CAIRO_PATTERN_TYPE_SOLID:
461
5.55M
  break;
462
516k
    case CAIRO_PATTERN_TYPE_SURFACE: {
463
516k
  cairo_surface_pattern_t *surface_pattern =
464
516k
      (cairo_surface_pattern_t *) pattern;
465
466
516k
  cairo_surface_destroy (surface_pattern->surface);
467
516k
    } break;
468
4.62k
    case CAIRO_PATTERN_TYPE_LINEAR:
469
6.53k
    case CAIRO_PATTERN_TYPE_RADIAL: {
470
6.53k
  cairo_gradient_pattern_t *gradient =
471
6.53k
      (cairo_gradient_pattern_t *) pattern;
472
473
6.53k
  if (gradient->stops && gradient->stops != gradient->stops_embedded)
474
0
      free (gradient->stops);
475
6.53k
    } break;
476
0
    case CAIRO_PATTERN_TYPE_MESH: {
477
0
  cairo_mesh_pattern_t *mesh =
478
0
      (cairo_mesh_pattern_t *) pattern;
479
480
0
  _cairo_array_fini (&mesh->patches);
481
0
    } break;
482
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
483
0
  _cairo_raster_source_pattern_finish (pattern);
484
0
  break;
485
6.07M
    }
486
487
#if HAVE_VALGRIND
488
    switch (pattern->type) {
489
    case CAIRO_PATTERN_TYPE_SOLID:
490
  VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t));
491
  break;
492
    case CAIRO_PATTERN_TYPE_SURFACE:
493
  VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t));
494
  break;
495
    case CAIRO_PATTERN_TYPE_LINEAR:
496
  VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t));
497
  break;
498
    case CAIRO_PATTERN_TYPE_RADIAL:
499
  VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t));
500
  break;
501
    case CAIRO_PATTERN_TYPE_MESH:
502
  VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t));
503
  break;
504
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
505
  break;
506
    }
507
#endif
508
6.07M
}
509
510
cairo_status_t
511
_cairo_pattern_create_copy (cairo_pattern_t   **pattern_out,
512
          const cairo_pattern_t  *other)
513
0
{
514
0
    cairo_pattern_t *pattern;
515
0
    cairo_status_t status;
516
517
0
    if (other->status)
518
0
  return other->status;
519
520
0
    switch (other->type) {
521
0
    case CAIRO_PATTERN_TYPE_SOLID:
522
0
  pattern = _cairo_malloc (sizeof (cairo_solid_pattern_t));
523
0
  break;
524
0
    case CAIRO_PATTERN_TYPE_SURFACE:
525
0
  pattern = _cairo_malloc (sizeof (cairo_surface_pattern_t));
526
0
  break;
527
0
    case CAIRO_PATTERN_TYPE_LINEAR:
528
0
  pattern = _cairo_malloc (sizeof (cairo_linear_pattern_t));
529
0
  break;
530
0
    case CAIRO_PATTERN_TYPE_RADIAL:
531
0
  pattern = _cairo_malloc (sizeof (cairo_radial_pattern_t));
532
0
  break;
533
0
    case CAIRO_PATTERN_TYPE_MESH:
534
0
  pattern = _cairo_malloc (sizeof (cairo_mesh_pattern_t));
535
0
  break;
536
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
537
0
  pattern = _cairo_malloc (sizeof (cairo_raster_source_pattern_t));
538
0
  break;
539
0
    default:
540
0
  ASSERT_NOT_REACHED;
541
0
  return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
542
0
    }
543
0
    if (unlikely (pattern == NULL))
544
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
545
546
0
    status = _cairo_pattern_init_copy (pattern, other);
547
0
    if (unlikely (status)) {
548
0
  free (pattern);
549
0
  return status;
550
0
    }
551
552
0
    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
553
0
    *pattern_out = pattern;
554
0
    return CAIRO_STATUS_SUCCESS;
555
0
}
556
557
void
558
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
559
         const cairo_color_t   *color)
560
5.58M
{
561
5.58M
    _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
562
5.58M
    pattern->color = *color;
563
5.58M
}
564
565
void
566
_cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern,
567
         cairo_surface_t   *surface)
568
516k
{
569
516k
    if (surface->status) {
570
  /* Force to solid to simplify the pattern_fini process. */
571
0
  _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
572
0
  _cairo_pattern_set_error (&pattern->base, surface->status);
573
0
  return;
574
0
    }
575
576
516k
    _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SURFACE);
577
578
516k
    pattern->surface = cairo_surface_reference (surface);
579
516k
    pattern->region_array_id = 0;
580
516k
}
581
582
static void
583
_cairo_pattern_init_gradient (cairo_gradient_pattern_t *pattern,
584
            cairo_pattern_type_t     type)
585
6.53k
{
586
6.53k
    _cairo_pattern_init (&pattern->base, type);
587
588
6.53k
    pattern->n_stops    = 0;
589
6.53k
    pattern->stops_size = 0;
590
6.53k
    pattern->stops      = NULL;
591
6.53k
}
592
593
static void
594
_cairo_pattern_init_linear (cairo_linear_pattern_t *pattern,
595
          double x0, double y0, double x1, double y1)
596
4.62k
{
597
4.62k
    _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_LINEAR);
598
599
4.62k
    pattern->pd1.x = x0;
600
4.62k
    pattern->pd1.y = y0;
601
4.62k
    pattern->pd2.x = x1;
602
4.62k
    pattern->pd2.y = y1;
603
4.62k
}
604
605
static void
606
_cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
607
          double cx0, double cy0, double radius0,
608
          double cx1, double cy1, double radius1)
609
1.91k
{
610
1.91k
    _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL);
611
612
1.91k
    pattern->cd1.center.x = cx0;
613
1.91k
    pattern->cd1.center.y = cy0;
614
1.91k
    pattern->cd1.radius   = fabs (radius0);
615
1.91k
    pattern->cd2.center.x = cx1;
616
1.91k
    pattern->cd2.center.y = cy1;
617
1.91k
    pattern->cd2.radius   = fabs (radius1);
618
1.91k
}
619
620
cairo_pattern_t *
621
_cairo_pattern_create_solid (const cairo_color_t *color)
622
5.55M
{
623
5.55M
    cairo_solid_pattern_t *pattern;
624
625
5.55M
    pattern =
626
5.55M
  _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SOLID]);
627
5.55M
    if (unlikely (pattern == NULL)) {
628
  /* None cached, need to create a new pattern. */
629
5
  pattern = _cairo_calloc (sizeof (cairo_solid_pattern_t));
630
5
  if (unlikely (pattern == NULL)) {
631
0
      _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
632
0
      return (cairo_pattern_t *) &_cairo_pattern_nil;
633
0
  }
634
5
    }
635
636
5.55M
    _cairo_pattern_init_solid (pattern, color);
637
5.55M
    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
638
639
5.55M
    return &pattern->base;
640
5.55M
}
641
642
cairo_pattern_t *
643
_cairo_pattern_create_foreground_marker (void)
644
0
{
645
0
    cairo_pattern_t *pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
646
0
    pattern->is_foreground_marker = TRUE;
647
0
    return pattern;
648
0
}
649
650
cairo_pattern_t *
651
_cairo_pattern_create_in_error (cairo_status_t status)
652
0
{
653
0
    cairo_pattern_t *pattern;
654
655
0
    if (status == CAIRO_STATUS_NO_MEMORY)
656
0
  return (cairo_pattern_t *)&_cairo_pattern_nil.base;
657
658
0
    CAIRO_MUTEX_INITIALIZE ();
659
660
0
    pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
661
0
    if (pattern->status == CAIRO_STATUS_SUCCESS)
662
0
  status = _cairo_pattern_set_error (pattern, status);
663
664
0
    return pattern;
665
0
}
666
667
/**
668
 * cairo_pattern_create_rgb:
669
 * @red: red component of the color
670
 * @green: green component of the color
671
 * @blue: blue component of the color
672
 *
673
 * Creates a new #cairo_pattern_t corresponding to an opaque color.  The
674
 * color components are floating point numbers in the range 0 to 1.
675
 * If the values passed in are outside that range, they will be
676
 * clamped.
677
 *
678
 * Return value: the newly created #cairo_pattern_t if successful, or
679
 * an error pattern in case of no memory.  The caller owns the
680
 * returned object and should call cairo_pattern_destroy() when
681
 * finished with it.
682
 *
683
 * This function will always return a valid pointer, but if an error
684
 * occurred the pattern status will be set to an error.  To inspect
685
 * the status of a pattern use cairo_pattern_status().
686
 *
687
 * Since: 1.0
688
 **/
689
cairo_pattern_t *
690
cairo_pattern_create_rgb (double red, double green, double blue)
691
0
{
692
0
    return cairo_pattern_create_rgba (red, green, blue, 1.0);
693
0
}
694
695
/**
696
 * cairo_pattern_create_rgba:
697
 * @red: red component of the color
698
 * @green: green component of the color
699
 * @blue: blue component of the color
700
 * @alpha: alpha component of the color
701
 *
702
 * Creates a new #cairo_pattern_t corresponding to a translucent color.
703
 * The color components are floating point numbers in the range 0 to
704
 * 1.  If the values passed in are outside that range, they will be
705
 * clamped.
706
 *
707
 * The color is specified in the same way as in cairo_set_source_rgb().
708
 *
709
 * Return value: the newly created #cairo_pattern_t if successful, or
710
 * an error pattern in case of no memory.  The caller owns the
711
 * returned object and should call cairo_pattern_destroy() when
712
 * finished with it.
713
 *
714
 * This function will always return a valid pointer, but if an error
715
 * occurred the pattern status will be set to an error.  To inspect
716
 * the status of a pattern use cairo_pattern_status().
717
 *
718
 * Since: 1.0
719
 **/
720
cairo_pattern_t *
721
cairo_pattern_create_rgba (double red, double green, double blue,
722
         double alpha)
723
5.55M
{
724
5.55M
    cairo_color_t color;
725
726
5.55M
    red   = _cairo_restrict_value (red,   0.0, 1.0);
727
5.55M
    green = _cairo_restrict_value (green, 0.0, 1.0);
728
5.55M
    blue  = _cairo_restrict_value (blue,  0.0, 1.0);
729
5.55M
    alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
730
731
5.55M
    _cairo_color_init_rgba (&color, red, green, blue, alpha);
732
733
5.55M
    CAIRO_MUTEX_INITIALIZE ();
734
735
5.55M
    return _cairo_pattern_create_solid (&color);
736
5.55M
}
737
738
/**
739
 * cairo_pattern_create_for_surface:
740
 * @surface: the surface
741
 *
742
 * Create a new #cairo_pattern_t for the given surface.
743
 *
744
 * Return value: the newly created #cairo_pattern_t if successful, or
745
 * an error pattern in case of no memory.  The caller owns the
746
 * returned object and should call cairo_pattern_destroy() when
747
 * finished with it.
748
 *
749
 * This function will always return a valid pointer, but if an error
750
 * occurred the pattern status will be set to an error.  To inspect
751
 * the status of a pattern use cairo_pattern_status().
752
 *
753
 * Since: 1.0
754
 **/
755
cairo_pattern_t *
756
cairo_pattern_create_for_surface (cairo_surface_t *surface)
757
516k
{
758
516k
    cairo_surface_pattern_t *pattern;
759
760
516k
    if (surface == NULL) {
761
0
  _cairo_error_throw (CAIRO_STATUS_NULL_POINTER);
762
0
  return (cairo_pattern_t*) &_cairo_pattern_nil_null_pointer;
763
0
    }
764
765
516k
    if (surface->status)
766
0
  return _cairo_pattern_create_in_error (surface->status);
767
768
516k
    pattern =
769
516k
  _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SURFACE]);
770
516k
    if (unlikely (pattern == NULL)) {
771
3
  pattern = _cairo_calloc (sizeof (cairo_surface_pattern_t));
772
3
  if (unlikely (pattern == NULL)) {
773
0
      _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
774
0
      return (cairo_pattern_t *)&_cairo_pattern_nil.base;
775
0
  }
776
3
    }
777
778
516k
    CAIRO_MUTEX_INITIALIZE ();
779
780
516k
    _cairo_pattern_init_for_surface (pattern, surface);
781
516k
    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
782
783
516k
    return &pattern->base;
784
516k
}
785
786
/**
787
 * cairo_pattern_create_linear:
788
 * @x0: x coordinate of the start point
789
 * @y0: y coordinate of the start point
790
 * @x1: x coordinate of the end point
791
 * @y1: y coordinate of the end point
792
 *
793
 * Create a new linear gradient #cairo_pattern_t along the line defined
794
 * by (x0, y0) and (x1, y1).  Before using the gradient pattern, a
795
 * number of color stops should be defined using
796
 * cairo_pattern_add_color_stop_rgb() or
797
 * cairo_pattern_add_color_stop_rgba().
798
 *
799
 * Note: The coordinates here are in pattern space. For a new pattern,
800
 * pattern space is identical to user space, but the relationship
801
 * between the spaces can be changed with cairo_pattern_set_matrix().
802
 *
803
 * Return value: the newly created #cairo_pattern_t if successful, or
804
 * an error pattern in case of no memory.  The caller owns the
805
 * returned object and should call cairo_pattern_destroy() when
806
 * finished with it.
807
 *
808
 * This function will always return a valid pointer, but if an error
809
 * occurred the pattern status will be set to an error.  To inspect
810
 * the status of a pattern use cairo_pattern_status().
811
 *
812
 * Since: 1.0
813
 **/
814
cairo_pattern_t *
815
cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
816
4.62k
{
817
4.62k
    cairo_linear_pattern_t *pattern;
818
819
4.62k
    pattern =
820
4.62k
  _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_LINEAR]);
821
4.62k
    if (unlikely (pattern == NULL)) {
822
1
  pattern = _cairo_calloc (sizeof (cairo_linear_pattern_t));
823
1
  if (unlikely (pattern == NULL)) {
824
0
      _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
825
0
      return (cairo_pattern_t *) &_cairo_pattern_nil.base;
826
0
  }
827
1
    }
828
829
4.62k
    CAIRO_MUTEX_INITIALIZE ();
830
831
4.62k
    _cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
832
4.62k
    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
833
834
4.62k
    return &pattern->base.base;
835
4.62k
}
836
837
/**
838
 * cairo_pattern_create_radial:
839
 * @cx0: x coordinate for the center of the start circle
840
 * @cy0: y coordinate for the center of the start circle
841
 * @radius0: radius of the start circle
842
 * @cx1: x coordinate for the center of the end circle
843
 * @cy1: y coordinate for the center of the end circle
844
 * @radius1: radius of the end circle
845
 *
846
 * Creates a new radial gradient #cairo_pattern_t between the two
847
 * circles defined by (cx0, cy0, radius0) and (cx1, cy1, radius1).  Before using the
848
 * gradient pattern, a number of color stops should be defined using
849
 * cairo_pattern_add_color_stop_rgb() or
850
 * cairo_pattern_add_color_stop_rgba().
851
 *
852
 * Note: The coordinates here are in pattern space. For a new pattern,
853
 * pattern space is identical to user space, but the relationship
854
 * between the spaces can be changed with cairo_pattern_set_matrix().
855
 *
856
 * Return value: the newly created #cairo_pattern_t if successful, or
857
 * an error pattern in case of no memory.  The caller owns the
858
 * returned object and should call cairo_pattern_destroy() when
859
 * finished with it.
860
 *
861
 * This function will always return a valid pointer, but if an error
862
 * occurred the pattern status will be set to an error.  To inspect
863
 * the status of a pattern use cairo_pattern_status().
864
 *
865
 * Since: 1.0
866
 **/
867
cairo_pattern_t *
868
cairo_pattern_create_radial (double cx0, double cy0, double radius0,
869
           double cx1, double cy1, double radius1)
870
1.91k
{
871
1.91k
    cairo_radial_pattern_t *pattern;
872
873
1.91k
    pattern =
874
1.91k
  _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_RADIAL]);
875
1.91k
    if (unlikely (pattern == NULL)) {
876
1
  pattern = _cairo_calloc (sizeof (cairo_radial_pattern_t));
877
1
  if (unlikely (pattern == NULL)) {
878
0
      _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
879
0
      return (cairo_pattern_t *) &_cairo_pattern_nil.base;
880
0
  }
881
1
    }
882
883
1.91k
    CAIRO_MUTEX_INITIALIZE ();
884
885
1.91k
    _cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
886
1.91k
    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
887
888
1.91k
    return &pattern->base.base;
889
1.91k
}
890
891
/* This order is specified in the diagram in the documentation for
892
 * cairo_pattern_create_mesh() */
893
static const int mesh_path_point_i[12] = { 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1 };
894
static const int mesh_path_point_j[12] = { 0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0 };
895
static const int mesh_control_point_i[4] = { 1, 1, 2, 2 };
896
static const int mesh_control_point_j[4] = { 1, 2, 2, 1 };
897
898
/**
899
 * cairo_pattern_create_mesh:
900
 *
901
 * Create a new mesh pattern.
902
 *
903
 * Mesh patterns are tensor-product patch meshes (type 7 shadings in
904
 * PDF). Mesh patterns may also be used to create other types of
905
 * shadings that are special cases of tensor-product patch meshes such
906
 * as Coons patch meshes (type 6 shading in PDF) and Gouraud-shaded
907
 * triangle meshes (type 4 and 5 shadings in PDF).
908
 *
909
 * Mesh patterns consist of one or more tensor-product patches, which
910
 * should be defined before using the mesh pattern. Using a mesh
911
 * pattern with a partially defined patch as source or mask will put
912
 * the context in an error status with a status of
913
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
914
 *
915
 * A tensor-product patch is defined by 4 Bézier curves (side 0, 1, 2,
916
 * 3) and by 4 additional control points (P0, P1, P2, P3) that provide
917
 * further control over the patch and complete the definition of the
918
 * tensor-product patch. The corner C0 is the first point of the
919
 * patch.
920
 *
921
 * Degenerate sides are permitted so straight lines may be used. A
922
 * zero length line on one side may be used to create 3 sided patches.
923
 *
924
 * <informalexample><screen>
925
 *       C1     Side 1       C2
926
 *        +---------------+
927
 *        |               |
928
 *        |  P1       P2  |
929
 *        |               |
930
 * Side 0 |               | Side 2
931
 *        |               |
932
 *        |               |
933
 *        |  P0       P3  |
934
 *        |               |
935
 *        +---------------+
936
 *      C0     Side 3        C3
937
 * </screen></informalexample>
938
 *
939
 * Each patch is constructed by first calling
940
 * cairo_mesh_pattern_begin_patch(), then cairo_mesh_pattern_move_to()
941
 * to specify the first point in the patch (C0). Then the sides are
942
 * specified with calls to cairo_mesh_pattern_curve_to() and
943
 * cairo_mesh_pattern_line_to().
944
 *
945
 * The four additional control points (P0, P1, P2, P3) in a patch can
946
 * be specified with cairo_mesh_pattern_set_control_point().
947
 *
948
 * At each corner of the patch (C0, C1, C2, C3) a color may be
949
 * specified with cairo_mesh_pattern_set_corner_color_rgb() or
950
 * cairo_mesh_pattern_set_corner_color_rgba(). Any corner whose color
951
 * is not explicitly specified defaults to transparent black.
952
 *
953
 * A Coons patch is a special case of the tensor-product patch where
954
 * the control points are implicitly defined by the sides of the
955
 * patch. The default value for any control point not specified is the
956
 * implicit value for a Coons patch, i.e. if no control points are
957
 * specified the patch is a Coons patch.
958
 *
959
 * A triangle is a special case of the tensor-product patch where the
960
 * control points are implicitly defined by the sides of the patch,
961
 * all the sides are lines and one of them has length 0, i.e. if the
962
 * patch is specified using just 3 lines, it is a triangle. If the
963
 * corners connected by the 0-length side have the same color, the
964
 * patch is a Gouraud-shaded triangle.
965
 *
966
 * Patches may be oriented differently to the above diagram. For
967
 * example the first point could be at the top left. The diagram only
968
 * shows the relationship between the sides, corners and control
969
 * points. Regardless of where the first point is located, when
970
 * specifying colors, corner 0 will always be the first point, corner
971
 * 1 the point between side 0 and side 1 etc.
972
 *
973
 * Calling cairo_mesh_pattern_end_patch() completes the current
974
 * patch. If less than 4 sides have been defined, the first missing
975
 * side is defined as a line from the current point to the first point
976
 * of the patch (C0) and the other sides are degenerate lines from C0
977
 * to C0. The corners between the added sides will all be coincident
978
 * with C0 of the patch and their color will be set to be the same as
979
 * the color of C0.
980
 *
981
 * Additional patches may be added with additional calls to
982
 * cairo_mesh_pattern_begin_patch()/cairo_mesh_pattern_end_patch().
983
 *
984
 * <informalexample><programlisting>
985
 * cairo_pattern_t *pattern = cairo_pattern_create_mesh ();
986
 *
987
 * /&ast; Add a Coons patch &ast;/
988
 * cairo_mesh_pattern_begin_patch (pattern);
989
 * cairo_mesh_pattern_move_to (pattern, 0, 0);
990
 * cairo_mesh_pattern_curve_to (pattern, 30, -30,  60,  30, 100, 0);
991
 * cairo_mesh_pattern_curve_to (pattern, 60,  30, 130,  60, 100, 100);
992
 * cairo_mesh_pattern_curve_to (pattern, 60,  70,  30, 130,   0, 100);
993
 * cairo_mesh_pattern_curve_to (pattern, 30,  70, -30,  30,   0, 0);
994
 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 0, 1, 0, 0);
995
 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 1, 0, 1, 0);
996
 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 2, 0, 0, 1);
997
 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 3, 1, 1, 0);
998
 * cairo_mesh_pattern_end_patch (pattern);
999
 *
1000
 * /&ast; Add a Gouraud-shaded triangle &ast;/
1001
 * cairo_mesh_pattern_begin_patch (pattern)
1002
 * cairo_mesh_pattern_move_to (pattern, 100, 100);
1003
 * cairo_mesh_pattern_line_to (pattern, 130, 130);
1004
 * cairo_mesh_pattern_line_to (pattern, 130,  70);
1005
 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 0, 1, 0, 0);
1006
 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 1, 0, 1, 0);
1007
 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 2, 0, 0, 1);
1008
 * cairo_mesh_pattern_end_patch (pattern)
1009
 * </programlisting></informalexample>
1010
 *
1011
 * When two patches overlap, the last one that has been added is drawn
1012
 * over the first one.
1013
 *
1014
 * When a patch folds over itself, points are sorted depending on
1015
 * their parameter coordinates inside the patch. The v coordinate
1016
 * ranges from 0 to 1 when moving from side 3 to side 1; the u
1017
 * coordinate ranges from 0 to 1 when going from side 0 to side
1018
 * 2. Points with higher v coordinate hide points with lower v
1019
 * coordinate. When two points have the same v coordinate, the one
1020
 * with higher u coordinate is above. This means that points nearer to
1021
 * side 1 are above points nearer to side 3; when this is not
1022
 * sufficient to decide which point is above (for example when both
1023
 * points belong to side 1 or side 3) points nearer to side 2 are
1024
 * above points nearer to side 0.
1025
 *
1026
 * For a complete definition of tensor-product patches, see the PDF
1027
 * specification (ISO32000), which describes the parametrization in
1028
 * detail.
1029
 *
1030
 * Note: The coordinates are always in pattern space. For a new
1031
 * pattern, pattern space is identical to user space, but the
1032
 * relationship between the spaces can be changed with
1033
 * cairo_pattern_set_matrix().
1034
 *
1035
 * Return value: the newly created #cairo_pattern_t if successful, or
1036
 * an error pattern in case of no memory. The caller owns the returned
1037
 * object and should call cairo_pattern_destroy() when finished with
1038
 * it.
1039
 *
1040
 * This function will always return a valid pointer, but if an error
1041
 * occurred the pattern status will be set to an error. To inspect the
1042
 * status of a pattern use cairo_pattern_status().
1043
 *
1044
 * Since: 1.12
1045
 **/
1046
cairo_pattern_t *
1047
cairo_pattern_create_mesh (void)
1048
0
{
1049
0
    cairo_mesh_pattern_t *pattern;
1050
1051
0
    pattern =
1052
0
  _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_MESH]);
1053
0
    if (unlikely (pattern == NULL)) {
1054
0
  pattern = _cairo_calloc (sizeof (cairo_mesh_pattern_t));
1055
0
  if (unlikely (pattern == NULL)) {
1056
0
      _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1057
0
      return (cairo_pattern_t *) &_cairo_pattern_nil.base;
1058
0
  }
1059
0
    }
1060
1061
0
    CAIRO_MUTEX_INITIALIZE ();
1062
1063
0
    _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_MESH);
1064
0
    _cairo_array_init (&pattern->patches, sizeof (cairo_mesh_patch_t));
1065
0
    pattern->current_patch = NULL;
1066
0
    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
1067
1068
0
    return &pattern->base;
1069
0
}
1070
1071
/**
1072
 * cairo_pattern_reference:
1073
 * @pattern: a #cairo_pattern_t
1074
 *
1075
 * Increases the reference count on @pattern by one. This prevents
1076
 * @pattern from being destroyed until a matching call to
1077
 * cairo_pattern_destroy() is made.
1078
 *
1079
 * Use cairo_pattern_get_reference_count() to get the number of
1080
 * references to a #cairo_pattern_t.
1081
 *
1082
 * Return value: the referenced #cairo_pattern_t.
1083
 *
1084
 * Since: 1.0
1085
 **/
1086
cairo_pattern_t *
1087
cairo_pattern_reference (cairo_pattern_t *pattern)
1088
12.1M
{
1089
12.1M
    if (pattern == NULL ||
1090
12.1M
      CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1091
6.08M
  return pattern;
1092
1093
12.1M
    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
1094
1095
6.07M
    _cairo_reference_count_inc (&pattern->ref_count);
1096
1097
6.07M
    return pattern;
1098
6.07M
}
1099
1100
/**
1101
 * cairo_pattern_get_type:
1102
 * @pattern: a #cairo_pattern_t
1103
 *
1104
 * Get the pattern's type.  See #cairo_pattern_type_t for available
1105
 * types.
1106
 *
1107
 * Return value: The type of @pattern.
1108
 *
1109
 * Since: 1.2
1110
 **/
1111
cairo_pattern_type_t
1112
cairo_pattern_get_type (cairo_pattern_t *pattern)
1113
0
{
1114
0
    return pattern->type;
1115
0
}
1116
1117
/**
1118
 * cairo_pattern_status:
1119
 * @pattern: a #cairo_pattern_t
1120
 *
1121
 * Checks whether an error has previously occurred for this
1122
 * pattern.
1123
 *
1124
 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NO_MEMORY,
1125
 * %CAIRO_STATUS_INVALID_MATRIX, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH,
1126
 * or %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1127
 *
1128
 * Since: 1.0
1129
 **/
1130
cairo_status_t
1131
cairo_pattern_status (cairo_pattern_t *pattern)
1132
0
{
1133
0
    return pattern->status;
1134
0
}
1135
1136
/**
1137
 * cairo_pattern_destroy:
1138
 * @pattern: a #cairo_pattern_t
1139
 *
1140
 * Decreases the reference count on @pattern by one. If the result is
1141
 * zero, then @pattern and all associated resources are freed.  See
1142
 * cairo_pattern_reference().
1143
 *
1144
 * Since: 1.0
1145
 **/
1146
void
1147
cairo_pattern_destroy (cairo_pattern_t *pattern)
1148
32.8M
{
1149
32.8M
    cairo_pattern_type_t type;
1150
1151
32.8M
    if (pattern == NULL ||
1152
32.8M
      CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1153
20.6M
  return;
1154
1155
32.8M
    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
1156
1157
12.1M
    if (! _cairo_reference_count_dec_and_test (&pattern->ref_count))
1158
6.07M
  return;
1159
1160
6.07M
    type = pattern->type;
1161
6.07M
    _cairo_pattern_fini (pattern);
1162
1163
    /* maintain a small cache of freed patterns */
1164
6.07M
    if (type < ARRAY_LENGTH (freed_pattern_pool))
1165
6.07M
  _freed_pool_put (&freed_pattern_pool[type], pattern);
1166
0
    else
1167
0
  free (pattern);
1168
6.07M
}
1169
1170
/**
1171
 * cairo_pattern_get_reference_count:
1172
 * @pattern: a #cairo_pattern_t
1173
 *
1174
 * Returns the current reference count of @pattern.
1175
 *
1176
 * Return value: the current reference count of @pattern.  If the
1177
 * object is a nil object, 0 will be returned.
1178
 *
1179
 * Since: 1.4
1180
 **/
1181
unsigned int
1182
cairo_pattern_get_reference_count (cairo_pattern_t *pattern)
1183
0
{
1184
0
    if (pattern == NULL ||
1185
0
      CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1186
0
  return 0;
1187
1188
0
    return CAIRO_REFERENCE_COUNT_GET_VALUE (&pattern->ref_count);
1189
0
}
1190
1191
/**
1192
 * cairo_pattern_get_user_data:
1193
 * @pattern: a #cairo_pattern_t
1194
 * @key: the address of the #cairo_user_data_key_t the user data was
1195
 * attached to
1196
 *
1197
 * Return user data previously attached to @pattern using the
1198
 * specified key.  If no user data has been attached with the given
1199
 * key this function returns %NULL.
1200
 *
1201
 * Return value: the user data previously attached or %NULL.
1202
 *
1203
 * Since: 1.4
1204
 **/
1205
void *
1206
cairo_pattern_get_user_data (cairo_pattern_t     *pattern,
1207
           const cairo_user_data_key_t *key)
1208
0
{
1209
0
    return _cairo_user_data_array_get_data (&pattern->user_data,
1210
0
              key);
1211
0
}
1212
1213
/**
1214
 * cairo_pattern_set_user_data:
1215
 * @pattern: a #cairo_pattern_t
1216
 * @key: the address of a #cairo_user_data_key_t to attach the user data to
1217
 * @user_data: the user data to attach to the #cairo_pattern_t
1218
 * @destroy: a #cairo_destroy_func_t which will be called when the
1219
 * #cairo_t is destroyed or when new user data is attached using the
1220
 * same key.
1221
 *
1222
 * Attach user data to @pattern.  To remove user data from a surface,
1223
 * call this function with the key that was used to set it and %NULL
1224
 * for @data.
1225
 *
1226
 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
1227
 * slot could not be allocated for the user data.
1228
 *
1229
 * Since: 1.4
1230
 **/
1231
cairo_status_t
1232
cairo_pattern_set_user_data (cairo_pattern_t     *pattern,
1233
           const cairo_user_data_key_t *key,
1234
           void      *user_data,
1235
           cairo_destroy_func_t   destroy)
1236
0
{
1237
0
    if (CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1238
0
  return pattern->status;
1239
1240
0
    return _cairo_user_data_array_set_data (&pattern->user_data,
1241
0
              key, user_data, destroy);
1242
0
}
1243
1244
/**
1245
 * cairo_mesh_pattern_begin_patch:
1246
 * @pattern: a #cairo_pattern_t
1247
 *
1248
 * Begin a patch in a mesh pattern.
1249
 *
1250
 * After calling this function, the patch shape should be defined with
1251
 * cairo_mesh_pattern_move_to(), cairo_mesh_pattern_line_to() and
1252
 * cairo_mesh_pattern_curve_to().
1253
 *
1254
 * After defining the patch, cairo_mesh_pattern_end_patch() must be
1255
 * called before using @pattern as a source or mask.
1256
 *
1257
 * Note: If @pattern is not a mesh pattern then @pattern will be put
1258
 * into an error status with a status of
1259
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern already has a
1260
 * current patch, it will be put into an error status with a status of
1261
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1262
 *
1263
 * Since: 1.12
1264
 **/
1265
void
1266
cairo_mesh_pattern_begin_patch (cairo_pattern_t *pattern)
1267
0
{
1268
0
    cairo_mesh_pattern_t *mesh;
1269
0
    cairo_status_t status;
1270
0
    cairo_mesh_patch_t *current_patch;
1271
0
    int i;
1272
1273
0
    if (unlikely (pattern->status))
1274
0
  return;
1275
1276
0
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1277
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1278
0
  return;
1279
0
    }
1280
1281
0
    mesh = (cairo_mesh_pattern_t *) pattern;
1282
0
    if (unlikely (mesh->current_patch)) {
1283
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1284
0
  return;
1285
0
    }
1286
1287
0
    status = _cairo_array_allocate (&mesh->patches, 1, (void **) &current_patch);
1288
0
    if (unlikely (status)) {
1289
0
  _cairo_pattern_set_error (pattern, status);
1290
0
  return;
1291
0
    }
1292
1293
0
    mesh->current_patch = current_patch;
1294
0
    mesh->current_side = -2; /* no current point */
1295
1296
0
    for (i = 0; i < 4; i++)
1297
0
  mesh->has_control_point[i] = FALSE;
1298
1299
0
    for (i = 0; i < 4; i++)
1300
0
  mesh->has_color[i] = FALSE;
1301
0
}
1302
1303
static void
1304
_calc_control_point (cairo_mesh_patch_t *patch, int control_point)
1305
0
{
1306
    /* The Coons patch is a special case of the Tensor Product patch
1307
     * where the four control points are:
1308
     *
1309
     * P11 = S(1/3, 1/3)
1310
     * P12 = S(1/3, 2/3)
1311
     * P21 = S(2/3, 1/3)
1312
     * P22 = S(2/3, 2/3)
1313
     *
1314
     * where S is the gradient surface.
1315
     *
1316
     * When one or more control points has not been specified
1317
     * calculated the Coons patch control points are substituted. If
1318
     * no control points are specified the gradient will be a Coons
1319
     * patch.
1320
     *
1321
     * The equations below are defined in the ISO32000 standard.
1322
     */
1323
0
    cairo_point_double_t *p[3][3];
1324
0
    int cp_i, cp_j, i, j;
1325
1326
0
    cp_i = mesh_control_point_i[control_point];
1327
0
    cp_j = mesh_control_point_j[control_point];
1328
1329
0
    for (i = 0; i < 3; i++)
1330
0
  for (j = 0; j < 3; j++)
1331
0
      p[i][j] = &patch->points[cp_i ^ i][cp_j ^ j];
1332
1333
0
    p[0][0]->x = (- 4 * p[1][1]->x
1334
0
      + 6 * (p[1][0]->x + p[0][1]->x)
1335
0
      - 2 * (p[1][2]->x + p[2][1]->x)
1336
0
      + 3 * (p[2][0]->x + p[0][2]->x)
1337
0
      - 1 * p[2][2]->x) * (1. / 9);
1338
1339
0
    p[0][0]->y = (- 4 * p[1][1]->y
1340
0
      + 6 * (p[1][0]->y + p[0][1]->y)
1341
0
      - 2 * (p[1][2]->y + p[2][1]->y)
1342
0
      + 3 * (p[2][0]->y + p[0][2]->y)
1343
0
      - 1 * p[2][2]->y) * (1. / 9);
1344
0
}
1345
1346
/**
1347
 * cairo_mesh_pattern_end_patch:
1348
 * @pattern: a #cairo_pattern_t
1349
 *
1350
 * Indicates the end of the current patch in a mesh pattern.
1351
 *
1352
 * If the current patch has less than 4 sides, it is closed with a
1353
 * straight line from the current point to the first point of the
1354
 * patch as if cairo_mesh_pattern_line_to() was used.
1355
 *
1356
 * Note: If @pattern is not a mesh pattern then @pattern will be put
1357
 * into an error status with a status of
1358
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
1359
 * patch or the current patch has no current point, @pattern will be
1360
 * put into an error status with a status of
1361
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1362
 *
1363
 * Since: 1.12
1364
 **/
1365
void
1366
cairo_mesh_pattern_end_patch (cairo_pattern_t *pattern)
1367
0
{
1368
0
    cairo_mesh_pattern_t *mesh;
1369
0
    cairo_mesh_patch_t *current_patch;
1370
0
    int i;
1371
1372
0
    if (unlikely (pattern->status))
1373
0
  return;
1374
1375
0
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1376
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1377
0
  return;
1378
0
    }
1379
1380
0
    mesh = (cairo_mesh_pattern_t *) pattern;
1381
0
    current_patch = mesh->current_patch;
1382
0
    if (unlikely (!current_patch)) {
1383
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1384
0
  return;
1385
0
    }
1386
1387
0
    if (unlikely (mesh->current_side == -2)) {
1388
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1389
0
  return;
1390
0
    }
1391
1392
0
    while (mesh->current_side < 3) {
1393
0
  int corner_num;
1394
1395
0
  cairo_mesh_pattern_line_to (pattern,
1396
0
            current_patch->points[0][0].x,
1397
0
            current_patch->points[0][0].y);
1398
1399
0
  corner_num = mesh->current_side + 1;
1400
0
  if (corner_num < 4 && ! mesh->has_color[corner_num]) {
1401
0
      current_patch->colors[corner_num] = current_patch->colors[0];
1402
0
      mesh->has_color[corner_num] = TRUE;
1403
0
  }
1404
0
    }
1405
1406
0
    for (i = 0; i < 4; i++) {
1407
0
  if (! mesh->has_control_point[i])
1408
0
      _calc_control_point (current_patch, i);
1409
0
    }
1410
1411
0
    for (i = 0; i < 4; i++) {
1412
0
  if (! mesh->has_color[i])
1413
0
      current_patch->colors[i] = *CAIRO_COLOR_TRANSPARENT;
1414
0
    }
1415
1416
0
    mesh->current_patch = NULL;
1417
0
}
1418
1419
/**
1420
 * cairo_mesh_pattern_curve_to:
1421
 * @pattern: a #cairo_pattern_t
1422
 * @x1: the X coordinate of the first control point
1423
 * @y1: the Y coordinate of the first control point
1424
 * @x2: the X coordinate of the second control point
1425
 * @y2: the Y coordinate of the second control point
1426
 * @x3: the X coordinate of the end of the curve
1427
 * @y3: the Y coordinate of the end of the curve
1428
 *
1429
 * Adds a cubic Bézier spline to the current patch from the current
1430
 * point to position (@x3, @y3) in pattern-space coordinates, using
1431
 * (@x1, @y1) and (@x2, @y2) as the control points.
1432
 *
1433
 * If the current patch has no current point before the call to
1434
 * cairo_mesh_pattern_curve_to(), this function will behave as if
1435
 * preceded by a call to cairo_mesh_pattern_move_to(@pattern, @x1,
1436
 * @y1).
1437
 *
1438
 * After this call the current point will be (@x3, @y3).
1439
 *
1440
 * Note: If @pattern is not a mesh pattern then @pattern will be put
1441
 * into an error status with a status of
1442
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
1443
 * patch or the current patch already has 4 sides, @pattern will be
1444
 * put into an error status with a status of
1445
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1446
 *
1447
 * Since: 1.12
1448
 **/
1449
void
1450
cairo_mesh_pattern_curve_to (cairo_pattern_t *pattern,
1451
           double x1, double y1,
1452
           double x2, double y2,
1453
           double x3, double y3)
1454
0
{
1455
0
    cairo_mesh_pattern_t *mesh;
1456
0
    int current_point, i, j;
1457
1458
0
    if (unlikely (pattern->status))
1459
0
  return;
1460
1461
0
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1462
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1463
0
  return;
1464
0
    }
1465
1466
0
    mesh = (cairo_mesh_pattern_t *) pattern;
1467
0
    if (unlikely (!mesh->current_patch)) {
1468
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1469
0
  return;
1470
0
    }
1471
1472
0
    if (unlikely (mesh->current_side == 3)) {
1473
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1474
0
  return;
1475
0
    }
1476
1477
0
    if (mesh->current_side == -2)
1478
0
  cairo_mesh_pattern_move_to (pattern, x1, y1);
1479
1480
0
    assert (mesh->current_side >= -1);
1481
0
    assert (pattern->status == CAIRO_STATUS_SUCCESS);
1482
1483
0
    mesh->current_side++;
1484
1485
0
    current_point = 3 * mesh->current_side;
1486
1487
0
    current_point++;
1488
0
    i = mesh_path_point_i[current_point];
1489
0
    j = mesh_path_point_j[current_point];
1490
0
    mesh->current_patch->points[i][j].x = x1;
1491
0
    mesh->current_patch->points[i][j].y = y1;
1492
1493
0
    current_point++;
1494
0
    i = mesh_path_point_i[current_point];
1495
0
    j = mesh_path_point_j[current_point];
1496
0
    mesh->current_patch->points[i][j].x = x2;
1497
0
    mesh->current_patch->points[i][j].y = y2;
1498
1499
0
    current_point++;
1500
0
    if (current_point < 12) {
1501
0
  i = mesh_path_point_i[current_point];
1502
0
  j = mesh_path_point_j[current_point];
1503
0
  mesh->current_patch->points[i][j].x = x3;
1504
0
  mesh->current_patch->points[i][j].y = y3;
1505
0
    }
1506
0
}
1507
1508
/**
1509
 * cairo_mesh_pattern_line_to:
1510
 * @pattern: a #cairo_pattern_t
1511
 * @x: the X coordinate of the end of the new line
1512
 * @y: the Y coordinate of the end of the new line
1513
 *
1514
 * Adds a line to the current patch from the current point to position
1515
 * (@x, @y) in pattern-space coordinates.
1516
 *
1517
 * If there is no current point before the call to
1518
 * cairo_mesh_pattern_line_to() this function will behave as
1519
 * cairo_mesh_pattern_move_to(@pattern, @x, @y).
1520
 *
1521
 * After this call the current point will be (@x, @y).
1522
 *
1523
 * Note: If @pattern is not a mesh pattern then @pattern will be put
1524
 * into an error status with a status of
1525
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
1526
 * patch or the current patch already has 4 sides, @pattern will be
1527
 * put into an error status with a status of
1528
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1529
 *
1530
 * Since: 1.12
1531
 **/
1532
void
1533
cairo_mesh_pattern_line_to (cairo_pattern_t *pattern,
1534
          double x, double y)
1535
0
{
1536
0
    cairo_mesh_pattern_t *mesh;
1537
0
    cairo_point_double_t last_point;
1538
0
    int last_point_idx, i, j;
1539
1540
0
    if (unlikely (pattern->status))
1541
0
  return;
1542
1543
0
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1544
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1545
0
  return;
1546
0
    }
1547
1548
0
    mesh = (cairo_mesh_pattern_t *) pattern;
1549
0
    if (unlikely (!mesh->current_patch)) {
1550
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1551
0
  return;
1552
0
    }
1553
1554
0
    if (unlikely (mesh->current_side == 3)) {
1555
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1556
0
  return;
1557
0
    }
1558
1559
0
    if (mesh->current_side == -2) {
1560
0
  cairo_mesh_pattern_move_to (pattern, x, y);
1561
0
  return;
1562
0
    }
1563
1564
0
    last_point_idx = 3 * (mesh->current_side + 1);
1565
0
    i = mesh_path_point_i[last_point_idx];
1566
0
    j = mesh_path_point_j[last_point_idx];
1567
1568
0
    last_point = mesh->current_patch->points[i][j];
1569
1570
0
    cairo_mesh_pattern_curve_to (pattern,
1571
0
         (2 * last_point.x + x) * (1. / 3),
1572
0
         (2 * last_point.y + y) * (1. / 3),
1573
0
         (last_point.x + 2 * x) * (1. / 3),
1574
0
         (last_point.y + 2 * y) * (1. / 3),
1575
0
         x, y);
1576
0
}
1577
1578
/**
1579
 * cairo_mesh_pattern_move_to:
1580
 * @pattern: a #cairo_pattern_t
1581
 * @x: the X coordinate of the new position
1582
 * @y: the Y coordinate of the new position
1583
 *
1584
 * Define the first point of the current patch in a mesh pattern.
1585
 *
1586
 * After this call the current point will be (@x, @y).
1587
 *
1588
 * Note: If @pattern is not a mesh pattern then @pattern will be put
1589
 * into an error status with a status of
1590
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
1591
 * patch or the current patch already has at least one side, @pattern
1592
 * will be put into an error status with a status of
1593
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1594
 *
1595
 * Since: 1.12
1596
 **/
1597
void
1598
cairo_mesh_pattern_move_to (cairo_pattern_t *pattern,
1599
          double x, double y)
1600
0
{
1601
0
    cairo_mesh_pattern_t *mesh;
1602
1603
0
    if (unlikely (pattern->status))
1604
0
  return;
1605
1606
0
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1607
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1608
0
  return;
1609
0
    }
1610
1611
0
    mesh = (cairo_mesh_pattern_t *) pattern;
1612
0
    if (unlikely (!mesh->current_patch)) {
1613
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1614
0
  return;
1615
0
    }
1616
1617
0
    if (unlikely (mesh->current_side >= 0)) {
1618
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1619
0
  return;
1620
0
    }
1621
1622
0
    mesh->current_side = -1;
1623
0
    mesh->current_patch->points[0][0].x = x;
1624
0
    mesh->current_patch->points[0][0].y = y;
1625
0
}
1626
1627
/**
1628
 * cairo_mesh_pattern_set_control_point:
1629
 * @pattern: a #cairo_pattern_t
1630
 * @point_num: the control point to set the position for
1631
 * @x: the X coordinate of the control point
1632
 * @y: the Y coordinate of the control point
1633
 *
1634
 * Set an internal control point of the current patch.
1635
 *
1636
 * Valid values for @point_num are from 0 to 3 and identify the
1637
 * control points as explained in cairo_pattern_create_mesh().
1638
 *
1639
 * Note: If @pattern is not a mesh pattern then @pattern will be put
1640
 * into an error status with a status of
1641
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @point_num is not valid,
1642
 * @pattern will be put into an error status with a status of
1643
 * %CAIRO_STATUS_INVALID_INDEX.  If @pattern has no current patch,
1644
 * @pattern will be put into an error status with a status of
1645
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1646
 *
1647
 * Since: 1.12
1648
 **/
1649
void
1650
cairo_mesh_pattern_set_control_point (cairo_pattern_t *pattern,
1651
              unsigned int     point_num,
1652
              double           x,
1653
              double           y)
1654
0
{
1655
0
    cairo_mesh_pattern_t *mesh;
1656
0
    int i, j;
1657
1658
0
    if (unlikely (pattern->status))
1659
0
  return;
1660
1661
0
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1662
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1663
0
  return;
1664
0
    }
1665
1666
0
    if (unlikely (point_num > 3)) {
1667
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_INDEX);
1668
0
  return;
1669
0
    }
1670
1671
0
    mesh = (cairo_mesh_pattern_t *) pattern;
1672
0
    if (unlikely (!mesh->current_patch)) {
1673
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1674
0
  return;
1675
0
    }
1676
1677
0
    i = mesh_control_point_i[point_num];
1678
0
    j = mesh_control_point_j[point_num];
1679
1680
0
    mesh->current_patch->points[i][j].x = x;
1681
0
    mesh->current_patch->points[i][j].y = y;
1682
0
    mesh->has_control_point[point_num] = TRUE;
1683
0
}
1684
1685
/* make room for at least one more color stop */
1686
static cairo_status_t
1687
_cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
1688
6.53k
{
1689
6.53k
    cairo_gradient_stop_t *new_stops;
1690
6.53k
    int old_size = pattern->stops_size;
1691
6.53k
    int embedded_size = ARRAY_LENGTH (pattern->stops_embedded);
1692
6.53k
    int new_size = 2 * MAX (old_size, 4);
1693
1694
    /* we have a local buffer at pattern->stops_embedded.  try to fulfill the request
1695
     * from there. */
1696
6.53k
    if (old_size < embedded_size) {
1697
6.53k
  pattern->stops = pattern->stops_embedded;
1698
6.53k
  pattern->stops_size = embedded_size;
1699
6.53k
  return CAIRO_STATUS_SUCCESS;
1700
6.53k
    }
1701
1702
0
    if (CAIRO_INJECT_FAULT ())
1703
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1704
1705
0
    assert (pattern->n_stops <= pattern->stops_size);
1706
1707
0
    if (pattern->stops == pattern->stops_embedded) {
1708
0
  new_stops = _cairo_malloc_ab (new_size, sizeof (cairo_gradient_stop_t));
1709
0
  if (new_stops)
1710
0
      memcpy (new_stops, pattern->stops, old_size * sizeof (cairo_gradient_stop_t));
1711
0
    } else {
1712
0
  new_stops = _cairo_realloc_ab (pattern->stops,
1713
0
               new_size,
1714
0
               sizeof (cairo_gradient_stop_t));
1715
0
    }
1716
1717
0
    if (unlikely (new_stops == NULL))
1718
0
  return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1719
1720
0
    pattern->stops = new_stops;
1721
0
    pattern->stops_size = new_size;
1722
1723
0
    return CAIRO_STATUS_SUCCESS;
1724
0
}
1725
1726
static void
1727
_cairo_mesh_pattern_set_corner_color (cairo_mesh_pattern_t *mesh,
1728
              unsigned int     corner_num,
1729
              double red, double green, double blue,
1730
              double alpha)
1731
0
{
1732
0
    cairo_color_t *color;
1733
1734
0
    assert (mesh->current_patch);
1735
0
    assert (corner_num <= 3);
1736
1737
0
    color = &mesh->current_patch->colors[corner_num];
1738
0
    color->red   = red;
1739
0
    color->green = green;
1740
0
    color->blue  = blue;
1741
0
    color->alpha = alpha;
1742
1743
0
    color->red_short   = _cairo_color_double_to_short (red);
1744
0
    color->green_short = _cairo_color_double_to_short (green);
1745
0
    color->blue_short  = _cairo_color_double_to_short (blue);
1746
0
    color->alpha_short = _cairo_color_double_to_short (alpha);
1747
1748
0
    mesh->has_color[corner_num] = TRUE;
1749
0
}
1750
1751
/**
1752
 * cairo_mesh_pattern_set_corner_color_rgb:
1753
 * @pattern: a #cairo_pattern_t
1754
 * @corner_num: the corner to set the color for
1755
 * @red: red component of color
1756
 * @green: green component of color
1757
 * @blue: blue component of color
1758
 *
1759
 * Sets the color of a corner of the current patch in a mesh pattern.
1760
 *
1761
 * The color is specified in the same way as in cairo_set_source_rgb().
1762
 *
1763
 * Valid values for @corner_num are from 0 to 3 and identify the
1764
 * corners as explained in cairo_pattern_create_mesh().
1765
 *
1766
 * Note: If @pattern is not a mesh pattern then @pattern will be put
1767
 * into an error status with a status of
1768
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @corner_num is not valid,
1769
 * @pattern will be put into an error status with a status of
1770
 * %CAIRO_STATUS_INVALID_INDEX.  If @pattern has no current patch,
1771
 * @pattern will be put into an error status with a status of
1772
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1773
 *
1774
 * Since: 1.12
1775
 **/
1776
void
1777
cairo_mesh_pattern_set_corner_color_rgb (cairo_pattern_t *pattern,
1778
           unsigned int     corner_num,
1779
           double red, double green, double blue)
1780
0
{
1781
0
    cairo_mesh_pattern_set_corner_color_rgba (pattern, corner_num, red, green, blue, 1.0);
1782
0
}
1783
1784
/**
1785
 * cairo_mesh_pattern_set_corner_color_rgba:
1786
 * @pattern: a #cairo_pattern_t
1787
 * @corner_num: the corner to set the color for
1788
 * @red: red component of color
1789
 * @green: green component of color
1790
 * @blue: blue component of color
1791
 * @alpha: alpha component of color
1792
 *
1793
 * Sets the color of a corner of the current patch in a mesh pattern.
1794
 *
1795
 * The color is specified in the same way as in cairo_set_source_rgba().
1796
 *
1797
 * Valid values for @corner_num are from 0 to 3 and identify the
1798
 * corners as explained in cairo_pattern_create_mesh().
1799
 *
1800
 * Note: If @pattern is not a mesh pattern then @pattern will be put
1801
 * into an error status with a status of
1802
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @corner_num is not valid,
1803
 * @pattern will be put into an error status with a status of
1804
 * %CAIRO_STATUS_INVALID_INDEX.  If @pattern has no current patch,
1805
 * @pattern will be put into an error status with a status of
1806
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1807
 *
1808
 * Since: 1.12
1809
 **/
1810
void
1811
cairo_mesh_pattern_set_corner_color_rgba (cairo_pattern_t *pattern,
1812
            unsigned int     corner_num,
1813
            double red, double green, double blue,
1814
            double alpha)
1815
0
{
1816
0
    cairo_mesh_pattern_t *mesh;
1817
1818
0
    if (unlikely (pattern->status))
1819
0
  return;
1820
1821
0
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1822
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1823
0
  return;
1824
0
    }
1825
1826
0
    if (unlikely (corner_num > 3)) {
1827
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_INDEX);
1828
0
  return;
1829
0
    }
1830
1831
0
    mesh = (cairo_mesh_pattern_t *) pattern;
1832
0
    if (unlikely (!mesh->current_patch)) {
1833
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1834
0
  return;
1835
0
    }
1836
1837
0
    red    = _cairo_restrict_value (red,    0.0, 1.0);
1838
0
    green  = _cairo_restrict_value (green,  0.0, 1.0);
1839
0
    blue   = _cairo_restrict_value (blue,   0.0, 1.0);
1840
0
    alpha  = _cairo_restrict_value (alpha,  0.0, 1.0);
1841
1842
0
    _cairo_mesh_pattern_set_corner_color (mesh, corner_num, red, green, blue, alpha);
1843
0
}
1844
1845
static void
1846
_cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
1847
             double      offset,
1848
             double      red,
1849
             double      green,
1850
             double      blue,
1851
             double      alpha)
1852
13.0k
{
1853
13.0k
    cairo_gradient_stop_t *stops;
1854
13.0k
    unsigned int     i;
1855
1856
13.0k
    if (pattern->n_stops >= pattern->stops_size) {
1857
6.53k
        cairo_status_t status = _cairo_pattern_gradient_grow (pattern);
1858
6.53k
  if (unlikely (status)) {
1859
0
      status = _cairo_pattern_set_error (&pattern->base, status);
1860
0
      return;
1861
0
  }
1862
6.53k
    }
1863
1864
13.0k
    stops = pattern->stops;
1865
1866
19.6k
    for (i = 0; i < pattern->n_stops; i++)
1867
6.53k
    {
1868
6.53k
  if (offset < stops[i].offset)
1869
0
  {
1870
0
      memmove (&stops[i + 1], &stops[i],
1871
0
         sizeof (cairo_gradient_stop_t) * (pattern->n_stops - i));
1872
1873
0
      break;
1874
0
  }
1875
6.53k
    }
1876
1877
13.0k
    stops[i].offset = offset;
1878
1879
13.0k
    stops[i].color.red   = red;
1880
13.0k
    stops[i].color.green = green;
1881
13.0k
    stops[i].color.blue  = blue;
1882
13.0k
    stops[i].color.alpha = alpha;
1883
1884
13.0k
    stops[i].color.red_short   = _cairo_color_double_to_short (red);
1885
13.0k
    stops[i].color.green_short = _cairo_color_double_to_short (green);
1886
13.0k
    stops[i].color.blue_short  = _cairo_color_double_to_short (blue);
1887
13.0k
    stops[i].color.alpha_short = _cairo_color_double_to_short (alpha);
1888
1889
13.0k
    pattern->n_stops++;
1890
13.0k
}
1891
1892
/**
1893
 * cairo_pattern_add_color_stop_rgb:
1894
 * @pattern: a #cairo_pattern_t
1895
 * @offset: an offset in the range [0.0 .. 1.0]
1896
 * @red: red component of color
1897
 * @green: green component of color
1898
 * @blue: blue component of color
1899
 *
1900
 * Adds an opaque color stop to a gradient pattern. The offset
1901
 * specifies the location along the gradient's control vector. For
1902
 * example, a linear gradient's control vector is from (x0,y0) to
1903
 * (x1,y1) while a radial gradient's control vector is from any point
1904
 * on the start circle to the corresponding point on the end circle.
1905
 *
1906
 * The color is specified in the same way as in cairo_set_source_rgb().
1907
 *
1908
 * If two (or more) stops are specified with identical offset values,
1909
 * they will be sorted according to the order in which the stops are
1910
 * added, (stops added earlier will compare less than stops added
1911
 * later). This can be useful for reliably making sharp color
1912
 * transitions instead of the typical blend.
1913
 *
1914
 *
1915
 * Note: If the pattern is not a gradient pattern, (eg. a linear or
1916
 * radial pattern), then the pattern will be put into an error status
1917
 * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
1918
 *
1919
 * Since: 1.0
1920
 **/
1921
void
1922
cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
1923
          double     offset,
1924
          double     red,
1925
          double     green,
1926
          double     blue)
1927
0
{
1928
0
    cairo_pattern_add_color_stop_rgba (pattern, offset, red, green, blue, 1.0);
1929
0
}
1930
1931
/**
1932
 * cairo_pattern_add_color_stop_rgba:
1933
 * @pattern: a #cairo_pattern_t
1934
 * @offset: an offset in the range [0.0 .. 1.0]
1935
 * @red: red component of color
1936
 * @green: green component of color
1937
 * @blue: blue component of color
1938
 * @alpha: alpha component of color
1939
 *
1940
 * Adds a translucent color stop to a gradient pattern. The offset
1941
 * specifies the location along the gradient's control vector. For
1942
 * example, a linear gradient's control vector is from (x0,y0) to
1943
 * (x1,y1) while a radial gradient's control vector is from any point
1944
 * on the start circle to the corresponding point on the end circle.
1945
 *
1946
 * The color is specified in the same way as in cairo_set_source_rgba().
1947
 *
1948
 * If two (or more) stops are specified with identical offset values,
1949
 * they will be sorted according to the order in which the stops are
1950
 * added, (stops added earlier will compare less than stops added
1951
 * later). This can be useful for reliably making sharp color
1952
 * transitions instead of the typical blend.
1953
 *
1954
 * Note: If the pattern is not a gradient pattern, (eg. a linear or
1955
 * radial pattern), then the pattern will be put into an error status
1956
 * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
1957
 *
1958
 * Since: 1.0
1959
 **/
1960
void
1961
cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
1962
           double    offset,
1963
           double    red,
1964
           double    green,
1965
           double    blue,
1966
           double    alpha)
1967
13.0k
{
1968
13.0k
    if (pattern->status)
1969
0
  return;
1970
1971
13.0k
    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
1972
3.82k
  pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
1973
0
    {
1974
0
  _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1975
0
  return;
1976
0
    }
1977
1978
13.0k
    offset = _cairo_restrict_value (offset, 0.0, 1.0);
1979
13.0k
    red    = _cairo_restrict_value (red,    0.0, 1.0);
1980
13.0k
    green  = _cairo_restrict_value (green,  0.0, 1.0);
1981
13.0k
    blue   = _cairo_restrict_value (blue,   0.0, 1.0);
1982
13.0k
    alpha  = _cairo_restrict_value (alpha,  0.0, 1.0);
1983
1984
13.0k
    _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
1985
13.0k
           offset, red, green, blue, alpha);
1986
13.0k
}
1987
1988
/**
1989
 * cairo_pattern_set_matrix:
1990
 * @pattern: a #cairo_pattern_t
1991
 * @matrix: a #cairo_matrix_t
1992
 *
1993
 * Sets the pattern's transformation matrix to @matrix. This matrix is
1994
 * a transformation from user space to pattern space.
1995
 *
1996
 * When a pattern is first created it always has the identity matrix
1997
 * for its transformation matrix, which means that pattern space is
1998
 * initially identical to user space.
1999
 *
2000
 * Important: Please note that the direction of this transformation
2001
 * matrix is from user space to pattern space. This means that if you
2002
 * imagine the flow from a pattern to user space (and on to device
2003
 * space), then coordinates in that flow will be transformed by the
2004
 * inverse of the pattern matrix.
2005
 *
2006
 * For example, if you want to make a pattern appear twice as large as
2007
 * it does by default the correct code to use is:
2008
 *
2009
 * <informalexample><programlisting>
2010
 * cairo_matrix_init_scale (&amp;matrix, 0.5, 0.5);
2011
 * cairo_pattern_set_matrix (pattern, &amp;matrix);
2012
 * </programlisting></informalexample>
2013
 *
2014
 * Meanwhile, using values of 2.0 rather than 0.5 in the code above
2015
 * would cause the pattern to appear at half of its default size.
2016
 *
2017
 * Also, please note the discussion of the user-space locking
2018
 * semantics of cairo_set_source().
2019
 *
2020
 * Since: 1.0
2021
 **/
2022
void
2023
cairo_pattern_set_matrix (cairo_pattern_t      *pattern,
2024
        const cairo_matrix_t *matrix)
2025
516k
{
2026
516k
    cairo_matrix_t inverse;
2027
516k
    cairo_status_t status;
2028
2029
516k
    if (pattern->status)
2030
0
  return;
2031
2032
516k
    if (memcmp (&pattern->matrix, matrix, sizeof (cairo_matrix_t)) == 0)
2033
0
  return;
2034
2035
516k
    pattern->matrix = *matrix;
2036
516k
    _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_MATRIX);
2037
2038
516k
    inverse = *matrix;
2039
516k
    status = cairo_matrix_invert (&inverse);
2040
516k
    if (unlikely (status))
2041
0
  status = _cairo_pattern_set_error (pattern, status);
2042
516k
}
2043
2044
/**
2045
 * cairo_pattern_get_matrix:
2046
 * @pattern: a #cairo_pattern_t
2047
 * @matrix: return value for the matrix
2048
 *
2049
 * Stores the pattern's transformation matrix into @matrix.
2050
 *
2051
 * Since: 1.0
2052
 **/
2053
void
2054
cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
2055
0
{
2056
0
    *matrix = pattern->matrix;
2057
0
}
2058
2059
/**
2060
 * cairo_pattern_set_filter:
2061
 * @pattern: a #cairo_pattern_t
2062
 * @filter: a #cairo_filter_t describing the filter to use for resizing
2063
 * the pattern
2064
 *
2065
 * Sets the filter to be used for resizing when using this pattern.
2066
 * See #cairo_filter_t for details on each filter.
2067
 *
2068
 * * Note that you might want to control filtering even when you do not
2069
 * have an explicit #cairo_pattern_t object, (for example when using
2070
 * cairo_set_source_surface()). In these cases, it is convenient to
2071
 * use cairo_get_source() to get access to the pattern that cairo
2072
 * creates implicitly. For example:
2073
 *
2074
 * <informalexample><programlisting>
2075
 * cairo_set_source_surface (cr, image, x, y);
2076
 * cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
2077
 * </programlisting></informalexample>
2078
 *
2079
 * Since: 1.0
2080
 **/
2081
void
2082
cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
2083
1
{
2084
1
    if (pattern->status)
2085
0
  return;
2086
2087
1
    pattern->filter = filter;
2088
1
    _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_FILTER);
2089
1
}
2090
2091
/**
2092
 * cairo_pattern_get_filter:
2093
 * @pattern: a #cairo_pattern_t
2094
 *
2095
 * Gets the current filter for a pattern.  See #cairo_filter_t
2096
 * for details on each filter.
2097
 *
2098
 * Return value: the current filter used for resizing the pattern.
2099
 *
2100
 * Since: 1.0
2101
 **/
2102
cairo_filter_t
2103
cairo_pattern_get_filter (cairo_pattern_t *pattern)
2104
0
{
2105
0
    return pattern->filter;
2106
0
}
2107
2108
/**
2109
 * cairo_pattern_get_dither:
2110
 * @pattern: a #cairo_pattern_t
2111
 *
2112
 * Gets the current dithering mode, as set by
2113
 * cairo_pattern_set_dither().
2114
 *
2115
 * Return value: the current dithering mode.
2116
 *
2117
 * Since: 1.18
2118
 **/
2119
cairo_dither_t
2120
cairo_pattern_get_dither (cairo_pattern_t *pattern)
2121
0
{
2122
0
    return pattern->dither;
2123
0
}
2124
2125
/**
2126
 * cairo_pattern_set_dither:
2127
 * @pattern: a #cairo_pattern_t
2128
 * @dither: a #cairo_dither_t describing the new dithering mode
2129
 *
2130
 * Set the dithering mode of the rasterizer used for drawing shapes.
2131
 * This value is a hint, and a particular backend may or may not support
2132
 * a particular value.  At the current time, only pixman is supported.
2133
 *
2134
 * Since: 1.18
2135
 **/
2136
void
2137
cairo_pattern_set_dither (cairo_pattern_t *pattern, cairo_dither_t dither)
2138
0
{
2139
0
    if (pattern->status)
2140
0
        return;
2141
2142
0
    pattern->dither = dither;
2143
0
    _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_DITHER);
2144
2145
0
}
2146
2147
/**
2148
 * cairo_pattern_set_extend:
2149
 * @pattern: a #cairo_pattern_t
2150
 * @extend: a #cairo_extend_t describing how the area outside of the
2151
 * pattern will be drawn
2152
 *
2153
 * Sets the mode to be used for drawing outside the area of a pattern.
2154
 * See #cairo_extend_t for details on the semantics of each extend
2155
 * strategy.
2156
 *
2157
 * The default extend mode is %CAIRO_EXTEND_NONE for surface patterns
2158
 * and %CAIRO_EXTEND_PAD for gradient patterns.
2159
 *
2160
 * Since: 1.0
2161
 **/
2162
void
2163
cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
2164
19.2k
{
2165
19.2k
    if (pattern->status)
2166
0
  return;
2167
2168
19.2k
    pattern->extend = extend;
2169
19.2k
    _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_EXTEND);
2170
19.2k
}
2171
2172
/**
2173
 * cairo_pattern_get_extend:
2174
 * @pattern: a #cairo_pattern_t
2175
 *
2176
 * Gets the current extend mode for a pattern.  See #cairo_extend_t
2177
 * for details on the semantics of each extend strategy.
2178
 *
2179
 * Return value: the current extend strategy used for drawing the
2180
 * pattern.
2181
 *
2182
 * Since: 1.0
2183
 **/
2184
cairo_extend_t
2185
cairo_pattern_get_extend (cairo_pattern_t *pattern)
2186
0
{
2187
0
    return pattern->extend;
2188
0
}
2189
2190
void
2191
_cairo_pattern_pretransform (cairo_pattern_t  *pattern,
2192
           const cairo_matrix_t  *ctm)
2193
1
{
2194
1
    if (pattern->status)
2195
0
  return;
2196
2197
1
    cairo_matrix_multiply (&pattern->matrix, &pattern->matrix, ctm);
2198
1
}
2199
2200
void
2201
_cairo_pattern_transform (cairo_pattern_t *pattern,
2202
        const cairo_matrix_t  *ctm_inverse)
2203
79.2k
{
2204
79.2k
    if (pattern->status)
2205
0
  return;
2206
2207
79.2k
    cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
2208
79.2k
}
2209
2210
static cairo_bool_t
2211
_linear_pattern_is_degenerate (const cairo_linear_pattern_t *linear)
2212
4.32k
{
2213
4.32k
    return fabs (linear->pd1.x - linear->pd2.x) < DBL_EPSILON &&
2214
3.73k
     fabs (linear->pd1.y - linear->pd2.y) < DBL_EPSILON;
2215
4.32k
}
2216
2217
static cairo_bool_t
2218
_radial_pattern_is_degenerate (const cairo_radial_pattern_t *radial)
2219
5.73k
{
2220
    /* A radial pattern is considered degenerate if it can be
2221
     * represented as a solid or clear pattern.  This corresponds to
2222
     * one of the two cases:
2223
     *
2224
     * 1) The radii are both very small:
2225
     *      |dr| < DBL_EPSILON && min (r0, r1) < DBL_EPSILON
2226
     *
2227
     * 2) The two circles have about the same radius and are very
2228
     *    close to each other (approximately a cylinder gradient that
2229
     *    doesn't move with the parameter):
2230
     *      |dr| < DBL_EPSILON && max (|dx|, |dy|) < 2 * DBL_EPSILON
2231
     *
2232
     * These checks are consistent with the assumptions used in
2233
     * _cairo_radial_pattern_box_to_parameter ().
2234
     */
2235
2236
5.73k
    return fabs (radial->cd1.radius - radial->cd2.radius) < DBL_EPSILON &&
2237
0
  (MIN (radial->cd1.radius, radial->cd2.radius) < DBL_EPSILON ||
2238
0
   MAX (fabs (radial->cd1.center.x - radial->cd2.center.x),
2239
0
        fabs (radial->cd1.center.y - radial->cd2.center.y)) < 2 * DBL_EPSILON);
2240
5.73k
}
2241
2242
static void
2243
_cairo_linear_pattern_box_to_parameter (const cairo_linear_pattern_t *linear,
2244
          double x0, double y0,
2245
          double x1, double y1,
2246
          double range[2])
2247
0
{
2248
0
    double t0, tdx, tdy;
2249
0
    double p1x, p1y, pdx, pdy, invsqnorm;
2250
2251
0
    assert (! _linear_pattern_is_degenerate (linear));
2252
2253
    /*
2254
     * Linear gradients are othrogonal to the line passing through
2255
     * their extremes. Because of convexity, the parameter range can
2256
     * be computed as the convex hull (one the real line) of the
2257
     * parameter values of the 4 corners of the box.
2258
     *
2259
     * The parameter value t for a point (x,y) can be computed as:
2260
     *
2261
     *   t = (p2 - p1) . (x,y) / |p2 - p1|^2
2262
     *
2263
     * t0  is the t value for the top left corner
2264
     * tdx is the difference between left and right corners
2265
     * tdy is the difference between top and bottom corners
2266
     */
2267
2268
0
    p1x = linear->pd1.x;
2269
0
    p1y = linear->pd1.y;
2270
0
    pdx = linear->pd2.x - p1x;
2271
0
    pdy = linear->pd2.y - p1y;
2272
0
    invsqnorm = 1.0 / (pdx * pdx + pdy * pdy);
2273
0
    pdx *= invsqnorm;
2274
0
    pdy *= invsqnorm;
2275
2276
0
    t0 = (x0 - p1x) * pdx + (y0 - p1y) * pdy;
2277
0
    tdx = (x1 - x0) * pdx;
2278
0
    tdy = (y1 - y0) * pdy;
2279
2280
    /*
2281
     * Because of the linearity of the t value, tdx can simply be
2282
     * added the t0 to move along the top edge. After this, range[0]
2283
     * and range[1] represent the parameter range for the top edge, so
2284
     * extending it to include the whole box simply requires adding
2285
     * tdy to the correct extreme.
2286
     */
2287
2288
0
    range[0] = range[1] = t0;
2289
0
    if (tdx < 0)
2290
0
  range[0] += tdx;
2291
0
    else
2292
0
  range[1] += tdx;
2293
2294
0
    if (tdy < 0)
2295
0
  range[0] += tdy;
2296
0
    else
2297
0
  range[1] += tdy;
2298
0
}
2299
2300
static cairo_bool_t
2301
_extend_range (double range[2], double value, cairo_bool_t valid)
2302
0
{
2303
0
    if (!valid)
2304
0
  range[0] = range[1] = value;
2305
0
    else if (value < range[0])
2306
0
  range[0] = value;
2307
0
    else if (value > range[1])
2308
0
  range[1] = value;
2309
2310
0
    return TRUE;
2311
0
}
2312
2313
/*
2314
 * _cairo_radial_pattern_focus_is_inside:
2315
 *
2316
 * Returns %TRUE if and only if the focus point exists and is
2317
 * contained in one of the two extreme circles. This condition is
2318
 * equivalent to one of the two extreme circles being completely
2319
 * contained in the other one.
2320
 *
2321
 * Note: if the focus is on the border of one of the two circles (in
2322
 * which case the circles are tangent in the focus point), it is not
2323
 * considered as contained in the circle, hence this function returns
2324
 * %FALSE.
2325
 *
2326
 */
2327
cairo_bool_t
2328
_cairo_radial_pattern_focus_is_inside (const cairo_radial_pattern_t *radial)
2329
0
{
2330
0
    double cx, cy, cr, dx, dy, dr;
2331
2332
0
    cx = radial->cd1.center.x;
2333
0
    cy = radial->cd1.center.y;
2334
0
    cr = radial->cd1.radius;
2335
0
    dx = radial->cd2.center.x - cx;
2336
0
    dy = radial->cd2.center.y - cy;
2337
0
    dr = radial->cd2.radius   - cr;
2338
2339
0
    return dx*dx + dy*dy < dr*dr;
2340
0
}
2341
2342
static void
2343
_cairo_radial_pattern_box_to_parameter (const cairo_radial_pattern_t *radial,
2344
          double x0, double y0,
2345
          double x1, double y1,
2346
          double tolerance,
2347
          double range[2])
2348
0
{
2349
0
    double cx, cy, cr, dx, dy, dr;
2350
0
    double a, x_focus, y_focus;
2351
0
    double mindr, minx, miny, maxx, maxy;
2352
0
    cairo_bool_t valid;
2353
2354
0
    assert (! _radial_pattern_is_degenerate (radial));
2355
0
    assert (x0 < x1);
2356
0
    assert (y0 < y1);
2357
2358
0
    tolerance = MAX (tolerance, DBL_EPSILON);
2359
2360
0
    range[0] = range[1] = 0;
2361
0
    valid = FALSE;
2362
2363
0
    x_focus = y_focus = 0; /* silence gcc */
2364
2365
0
    cx = radial->cd1.center.x;
2366
0
    cy = radial->cd1.center.y;
2367
0
    cr = radial->cd1.radius;
2368
0
    dx = radial->cd2.center.x - cx;
2369
0
    dy = radial->cd2.center.y - cy;
2370
0
    dr = radial->cd2.radius   - cr;
2371
2372
    /* translate by -(cx, cy) to simplify computations */
2373
0
    x0 -= cx;
2374
0
    y0 -= cy;
2375
0
    x1 -= cx;
2376
0
    y1 -= cy;
2377
2378
    /* enlarge boundaries slightly to avoid rounding problems in the
2379
     * parameter range computation */
2380
0
    x0 -= DBL_EPSILON;
2381
0
    y0 -= DBL_EPSILON;
2382
0
    x1 += DBL_EPSILON;
2383
0
    y1 += DBL_EPSILON;
2384
2385
    /* enlarge boundaries even more to avoid rounding problems when
2386
     * testing if a point belongs to the box */
2387
0
    minx = x0 - DBL_EPSILON;
2388
0
    miny = y0 - DBL_EPSILON;
2389
0
    maxx = x1 + DBL_EPSILON;
2390
0
    maxy = y1 + DBL_EPSILON;
2391
2392
    /* we don't allow negative radiuses, so we will be checking that
2393
     * t*dr >= mindr to consider t valid */
2394
0
    mindr = -(cr + DBL_EPSILON);
2395
2396
    /*
2397
     * After the previous transformations, the start circle is
2398
     * centered in the origin and has radius cr. A 1-unit change in
2399
     * the t parameter corresponds to dx,dy,dr changes in the x,y,r of
2400
     * the circle (center coordinates, radius).
2401
     *
2402
     * To compute the minimum range needed to correctly draw the
2403
     * pattern, we start with an empty range and extend it to include
2404
     * the circles touching the bounding box or within it.
2405
     */
2406
2407
    /*
2408
     * Focus, the point where the circle has radius == 0.
2409
     *
2410
     * r = cr + t * dr = 0
2411
     * t = -cr / dr
2412
     *
2413
     * If the radius is constant (dr == 0) there is no focus (the
2414
     * gradient represents a cylinder instead of a cone).
2415
     */
2416
0
    if (fabs (dr) >= DBL_EPSILON) {
2417
0
  double t_focus;
2418
2419
0
  t_focus = -cr / dr;
2420
0
  x_focus = t_focus * dx;
2421
0
  y_focus = t_focus * dy;
2422
0
  if (minx <= x_focus && x_focus <= maxx &&
2423
0
      miny <= y_focus && y_focus <= maxy)
2424
0
  {
2425
0
      valid = _extend_range (range, t_focus, valid);
2426
0
  }
2427
0
    }
2428
2429
    /*
2430
     * Circles externally tangent to box edges.
2431
     *
2432
     * All circles have center in (dx, dy) * t
2433
     *
2434
     * If the circle is tangent to the line defined by the edge of the
2435
     * box, then at least one of the following holds true:
2436
     *
2437
     *   (dx*t) + (cr + dr*t) == x0 (left   edge)
2438
     *   (dx*t) - (cr + dr*t) == x1 (right  edge)
2439
     *   (dy*t) + (cr + dr*t) == y0 (top    edge)
2440
     *   (dy*t) - (cr + dr*t) == y1 (bottom edge)
2441
     *
2442
     * The solution is only valid if the tangent point is actually on
2443
     * the edge, i.e. if its y coordinate is in [y0,y1] for left/right
2444
     * edges and if its x coordinate is in [x0,x1] for top/bottom
2445
     * edges.
2446
     *
2447
     * For the first equation:
2448
     *
2449
     *   (dx + dr) * t = x0 - cr
2450
     *   t = (x0 - cr) / (dx + dr)
2451
     *   y = dy * t
2452
     *
2453
     * in the code this becomes:
2454
     *
2455
     *   t_edge = (num) / (den)
2456
     *   v = (delta) * t_edge
2457
     *
2458
     * If the denominator in t is 0, the pattern is tangent to a line
2459
     * parallel to the edge under examination. The corner-case where
2460
     * the boundary line is the same as the edge is handled by the
2461
     * focus point case and/or by the a==0 case.
2462
     */
2463
0
#define T_EDGE(num,den,delta,lower,upper)       \
2464
0
    if (fabs (den) >= DBL_EPSILON) {         \
2465
0
  double t_edge, v;           \
2466
0
                  \
2467
0
  t_edge = (num) / (den);           \
2468
0
  v = t_edge * (delta);           \
2469
0
  if (t_edge * dr >= mindr && (lower) <= v && v <= (upper)) \
2470
0
      valid = _extend_range (range, t_edge, valid);   \
2471
0
    }
2472
2473
    /* circles tangent (externally) to left/right/top/bottom edge */
2474
0
    T_EDGE (x0 - cr, dx + dr, dy, miny, maxy);
2475
0
    T_EDGE (x1 + cr, dx - dr, dy, miny, maxy);
2476
0
    T_EDGE (y0 - cr, dy + dr, dx, minx, maxx);
2477
0
    T_EDGE (y1 + cr, dy - dr, dx, minx, maxx);
2478
2479
0
#undef T_EDGE
2480
2481
    /*
2482
     * Circles passing through a corner.
2483
     *
2484
     * A circle passing through the point (x,y) satisfies:
2485
     *
2486
     * (x-t*dx)^2 + (y-t*dy)^2 == (cr + t*dr)^2
2487
     *
2488
     * If we set:
2489
     *   a = dx^2 + dy^2 - dr^2
2490
     *   b = x*dx + y*dy + cr*dr
2491
     *   c = x^2 + y^2 - cr^2
2492
     * we have:
2493
     *   a*t^2 - 2*b*t + c == 0
2494
     */
2495
0
    a = dx * dx + dy * dy - dr * dr;
2496
0
    if (fabs (a) < DBL_EPSILON * DBL_EPSILON) {
2497
0
  double b, maxd2;
2498
2499
  /* Ensure that gradients with both a and dr small are
2500
   * considered degenerate.
2501
   * The floating point version of the degeneracy test implemented
2502
   * in _radial_pattern_is_degenerate() is:
2503
   *
2504
   *  1) The circles are practically the same size:
2505
   *     |dr| < DBL_EPSILON
2506
   *  AND
2507
   *  2a) The circles are both very small:
2508
   *      min (r0, r1) < DBL_EPSILON
2509
   *   OR
2510
   *  2b) The circles are very close to each other:
2511
   *      max (|dx|, |dy|) < 2 * DBL_EPSILON
2512
   *
2513
   * Assuming that the gradient is not degenerate, we want to
2514
   * show that |a| < DBL_EPSILON^2 implies |dr| >= DBL_EPSILON.
2515
   *
2516
   * If the gradient is not degenerate yet it has |dr| <
2517
   * DBL_EPSILON, (2b) is false, thus:
2518
   *
2519
   *   max (|dx|, |dy|) >= 2*DBL_EPSILON
2520
   * which implies:
2521
   *   4*DBL_EPSILON^2 <= max (|dx|, |dy|)^2 <= dx^2 + dy^2
2522
   *
2523
   * From the definition of a, we get:
2524
   *   a = dx^2 + dy^2 - dr^2 < DBL_EPSILON^2
2525
   *   dx^2 + dy^2 - DBL_EPSILON^2 < dr^2
2526
   *   3*DBL_EPSILON^2 < dr^2
2527
   *
2528
   * which is inconsistent with the hypotheses, thus |dr| <
2529
   * DBL_EPSILON is false or the gradient is degenerate.
2530
   */
2531
0
  assert (fabs (dr) >= DBL_EPSILON);
2532
2533
  /*
2534
   * If a == 0, all the circles are tangent to a line in the
2535
   * focus point. If this line is within the box extents, we
2536
   * should add the circle with infinite radius, but this would
2537
   * make the range unbounded, so we add the smallest circle whose
2538
   * distance to the desired (degenerate) circle within the
2539
   * bounding box does not exceed tolerance.
2540
   *
2541
   * The equation of the line is b==0, i.e.:
2542
   *   x*dx + y*dy + cr*dr == 0
2543
   *
2544
   * We compute the intersection of the line with the box and
2545
   * keep the intersection with maximum square distance (maxd2)
2546
   * from the focus point.
2547
   *
2548
   * In the code the intersection is represented in another
2549
   * coordinate system, whose origin is the focus point and
2550
   * which has a u,v axes, which are respectively orthogonal and
2551
   * parallel to the edge being intersected.
2552
   *
2553
   * The intersection is valid only if it belongs to the box,
2554
   * otherwise it is ignored.
2555
   *
2556
   * For example:
2557
   *
2558
   *   y = y0
2559
   *   x*dx + y0*dy + cr*dr == 0
2560
   *   x = -(y0*dy + cr*dr) / dx
2561
   *
2562
   * which in (u,v) is:
2563
   *   u = y0 - y_focus
2564
   *   v = -(y0*dy + cr*dr) / dx - x_focus
2565
   *
2566
   * In the code:
2567
   *   u = (edge) - (u_origin)
2568
   *   v = -((edge) * (delta) + cr*dr) / (den) - v_focus
2569
   */
2570
0
#define T_EDGE(edge,delta,den,lower,upper,u_origin,v_origin)  \
2571
0
  if (fabs (den) >= DBL_EPSILON) {     \
2572
0
      double v;           \
2573
0
                \
2574
0
      v = -((edge) * (delta) + cr * dr) / (den);    \
2575
0
      if ((lower) <= v && v <= (upper)) {     \
2576
0
    double u, d2;         \
2577
0
                \
2578
0
    u = (edge) - (u_origin);      \
2579
0
    v -= (v_origin);        \
2580
0
    d2 = u*u + v*v;         \
2581
0
    if (maxd2 < d2)         \
2582
0
        maxd2 = d2;         \
2583
0
      }             \
2584
0
  }
2585
2586
0
  maxd2 = 0;
2587
2588
  /* degenerate circles (lines) passing through each edge */
2589
0
  T_EDGE (y0, dy, dx, minx, maxx, y_focus, x_focus);
2590
0
  T_EDGE (y1, dy, dx, minx, maxx, y_focus, x_focus);
2591
0
  T_EDGE (x0, dx, dy, miny, maxy, x_focus, y_focus);
2592
0
  T_EDGE (x1, dx, dy, miny, maxy, x_focus, y_focus);
2593
2594
0
#undef T_EDGE
2595
2596
  /*
2597
   * The limit circle can be transformed rigidly to the y=0 line
2598
   * and the circles tangent to it in (0,0) are:
2599
   *
2600
   *   x^2 + (y-r)^2 = r^2  <=>  x^2 + y^2 - 2*y*r = 0
2601
   *
2602
   * y is the distance from the line, in our case tolerance;
2603
   * x is the distance along the line, i.e. sqrt(maxd2),
2604
   * so:
2605
   *
2606
   *   r = cr + dr * t = (maxd2 + tolerance^2) / (2*tolerance)
2607
   *   t = (r - cr) / dr =
2608
   *       (maxd2 + tolerance^2 - 2*tolerance*cr) / (2*tolerance*dr)
2609
   */
2610
0
  if (maxd2 > 0) {
2611
0
      double t_limit = maxd2 + tolerance*tolerance - 2*tolerance*cr;
2612
0
      t_limit /= 2 * tolerance * dr;
2613
0
      valid = _extend_range (range, t_limit, valid);
2614
0
  }
2615
2616
  /*
2617
   * Nondegenerate, nonlimit circles passing through the corners.
2618
   *
2619
   * a == 0 && a*t^2 - 2*b*t + c == 0
2620
   *
2621
   * t = c / (2*b)
2622
   *
2623
   * The b == 0 case has just been handled, so we only have to
2624
   * compute this if b != 0.
2625
   */
2626
0
#define T_CORNER(x,y)             \
2627
0
  b = (x) * dx + (y) * dy + cr * dr;        \
2628
0
  if (fabs (b) >= DBL_EPSILON) {         \
2629
0
      double t_corner;            \
2630
0
      double x2 = (x) * (x);          \
2631
0
      double y2 = (y) * (y);          \
2632
0
      double cr2 = (cr) * (cr);         \
2633
0
      double c = x2 + y2 - cr2;         \
2634
0
                      \
2635
0
      t_corner = 0.5 * c / b;         \
2636
0
      if (t_corner * dr >= mindr)         \
2637
0
    valid = _extend_range (range, t_corner, valid);   \
2638
0
  }
2639
2640
  /* circles touching each corner */
2641
0
  T_CORNER (x0, y0);
2642
0
  T_CORNER (x0, y1);
2643
0
  T_CORNER (x1, y0);
2644
0
  T_CORNER (x1, y1);
2645
2646
0
#undef T_CORNER
2647
0
    } else {
2648
0
  double inva, b, c, d;
2649
2650
0
  inva = 1 / a;
2651
2652
  /*
2653
   * Nondegenerate, nonlimit circles passing through the corners.
2654
   *
2655
   * a != 0 && a*t^2 - 2*b*t + c == 0
2656
   *
2657
   * t = (b +- sqrt (b*b - a*c)) / a
2658
   *
2659
   * If the argument of sqrt() is negative, then no circle
2660
   * passes through the corner.
2661
   */
2662
0
#define T_CORNER(x,y)             \
2663
0
  b = (x) * dx + (y) * dy + cr * dr;        \
2664
0
  c = (x) * (x) + (y) * (y) - cr * cr;        \
2665
0
  d = b * b - a * c;            \
2666
0
  if (d >= 0) {             \
2667
0
      double t_corner;            \
2668
0
                  \
2669
0
      d = sqrt (d);           \
2670
0
      t_corner = (b + d) * inva;          \
2671
0
      if (t_corner * dr >= mindr)         \
2672
0
    valid = _extend_range (range, t_corner, valid);   \
2673
0
      t_corner = (b - d) * inva;          \
2674
0
      if (t_corner * dr >= mindr)         \
2675
0
    valid = _extend_range (range, t_corner, valid);   \
2676
0
  }
2677
2678
  /* circles touching each corner */
2679
0
  T_CORNER (x0, y0);
2680
0
  T_CORNER (x0, y1);
2681
0
  T_CORNER (x1, y0);
2682
0
  T_CORNER (x1, y1);
2683
2684
0
#undef T_CORNER
2685
0
    }
2686
0
}
2687
2688
/**
2689
 * _cairo_gradient_pattern_box_to_parameter:
2690
 *
2691
 * Compute a interpolation range sufficient to draw (within the given
2692
 * tolerance) the gradient in the given box getting the same result as
2693
 * using the (-inf, +inf) range.
2694
 *
2695
 * Assumes that the pattern is not degenerate. This can be guaranteed
2696
 * by simplifying it to a solid clear if _cairo_pattern_is_clear or to
2697
 * a solid color if _cairo_gradient_pattern_is_solid.
2698
 *
2699
 * The range isn't guaranteed to be minimal, but it tries to.
2700
 **/
2701
void
2702
_cairo_gradient_pattern_box_to_parameter (const cairo_gradient_pattern_t *gradient,
2703
            double x0, double y0,
2704
            double x1, double y1,
2705
            double tolerance,
2706
            double out_range[2])
2707
0
{
2708
0
    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
2709
0
      gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
2710
2711
0
    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
2712
0
  _cairo_linear_pattern_box_to_parameter ((cairo_linear_pattern_t *) gradient,
2713
0
            x0, y0, x1, y1, out_range);
2714
0
    } else {
2715
0
  _cairo_radial_pattern_box_to_parameter ((cairo_radial_pattern_t *) gradient,
2716
0
            x0, y0, x1, y1, tolerance, out_range);
2717
0
    }
2718
0
}
2719
2720
/**
2721
 * _cairo_gradient_pattern_interpolate:
2722
 *
2723
 * Interpolate between the start and end objects of linear or radial
2724
 * gradients.  The interpolated object is stored in out_circle, with
2725
 * the radius being zero in the linear gradient case.
2726
 **/
2727
void
2728
_cairo_gradient_pattern_interpolate (const cairo_gradient_pattern_t *gradient,
2729
             double          t,
2730
             cairo_circle_double_t      *out_circle)
2731
0
{
2732
0
    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
2733
0
      gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
2734
2735
0
#define lerp(a,b) (a)*(1-t) + (b)*t
2736
2737
0
    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
2738
0
  cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
2739
0
  out_circle->center.x = lerp (linear->pd1.x, linear->pd2.x);
2740
0
  out_circle->center.y = lerp (linear->pd1.y, linear->pd2.y);
2741
0
  out_circle->radius = 0;
2742
0
    } else {
2743
0
  cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
2744
0
  out_circle->center.x = lerp (radial->cd1.center.x, radial->cd2.center.x);
2745
0
  out_circle->center.y = lerp (radial->cd1.center.y, radial->cd2.center.y);
2746
0
  out_circle->radius   = lerp (radial->cd1.radius  , radial->cd2.radius);
2747
0
    }
2748
2749
0
#undef lerp
2750
0
}
2751
2752
/**
2753
 * _cairo_gradient_pattern_fit_to_range:
2754
 *
2755
 * Scale the extremes of a gradient to guarantee that the coordinates
2756
 * and their deltas are within the range (-max_value, max_value). The
2757
 * new extremes are stored in out_circle.
2758
 *
2759
 * The pattern matrix is scaled to guarantee that the aspect of the
2760
 * gradient is the same and the result is stored in out_matrix.
2761
 *
2762
 **/
2763
void
2764
_cairo_gradient_pattern_fit_to_range (const cairo_gradient_pattern_t *gradient,
2765
              double            max_value,
2766
              cairo_matrix_t                 *out_matrix,
2767
              cairo_circle_double_t       out_circle[2])
2768
2.47k
{
2769
2.47k
    double dim;
2770
2771
2.47k
    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
2772
2.47k
      gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
2773
2774
2.47k
    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
2775
603
  cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
2776
2777
603
  out_circle[0].center = linear->pd1;
2778
603
  out_circle[0].radius = 0;
2779
603
  out_circle[1].center = linear->pd2;
2780
603
  out_circle[1].radius = 0;
2781
2782
603
  dim = fabs (linear->pd1.x);
2783
603
  dim = MAX (dim, fabs (linear->pd1.y));
2784
603
  dim = MAX (dim, fabs (linear->pd2.x));
2785
603
  dim = MAX (dim, fabs (linear->pd2.y));
2786
603
  dim = MAX (dim, fabs (linear->pd1.x - linear->pd2.x));
2787
603
  dim = MAX (dim, fabs (linear->pd1.y - linear->pd2.y));
2788
1.86k
    } else {
2789
1.86k
  cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
2790
2791
1.86k
  out_circle[0] = radial->cd1;
2792
1.86k
  out_circle[1] = radial->cd2;
2793
2794
1.86k
  dim = fabs (radial->cd1.center.x);
2795
1.86k
  dim = MAX (dim, fabs (radial->cd1.center.y));
2796
1.86k
  dim = MAX (dim, fabs (radial->cd1.radius));
2797
1.86k
  dim = MAX (dim, fabs (radial->cd2.center.x));
2798
1.86k
  dim = MAX (dim, fabs (radial->cd2.center.y));
2799
1.86k
  dim = MAX (dim, fabs (radial->cd2.radius));
2800
1.86k
  dim = MAX (dim, fabs (radial->cd1.center.x - radial->cd2.center.x));
2801
1.86k
  dim = MAX (dim, fabs (radial->cd1.center.y - radial->cd2.center.y));
2802
1.86k
  dim = MAX (dim, fabs (radial->cd1.radius   - radial->cd2.radius));
2803
1.86k
    }
2804
2.47k
    dim = MAX (dim, fabs (gradient->base.matrix.xx));
2805
2.47k
    dim = MAX (dim, fabs (gradient->base.matrix.xy));
2806
2.47k
    dim = MAX (dim, fabs (gradient->base.matrix.x0));
2807
2.47k
    dim = MAX (dim, fabs (gradient->base.matrix.yx));
2808
2.47k
    dim = MAX (dim, fabs (gradient->base.matrix.yy));
2809
2.47k
    dim = MAX (dim, fabs (gradient->base.matrix.y0));
2810
2811
2.47k
    if (unlikely (dim > max_value)) {
2812
1.80k
  cairo_matrix_t scale;
2813
2814
1.80k
  dim = max_value / dim;
2815
2816
1.80k
  out_circle[0].center.x *= dim;
2817
1.80k
  out_circle[0].center.y *= dim;
2818
1.80k
  out_circle[0].radius   *= dim;
2819
1.80k
  out_circle[1].center.x *= dim;
2820
1.80k
  out_circle[1].center.y *= dim;
2821
1.80k
  out_circle[1].radius   *= dim;
2822
2823
1.80k
  cairo_matrix_init_scale (&scale, dim, dim);
2824
1.80k
  cairo_matrix_multiply (out_matrix, &gradient->base.matrix, &scale);
2825
1.80k
    } else {
2826
668
  *out_matrix = gradient->base.matrix;
2827
668
    }
2828
2.47k
}
2829
2830
static cairo_bool_t
2831
_gradient_is_clear (const cairo_gradient_pattern_t *gradient,
2832
        const cairo_rectangle_int_t *extents)
2833
8.75k
{
2834
8.75k
    unsigned int i;
2835
2836
8.75k
    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
2837
8.75k
      gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
2838
2839
8.75k
    if (gradient->n_stops == 0 ||
2840
8.75k
  (gradient->base.extend == CAIRO_EXTEND_NONE &&
2841
0
   gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
2842
0
  return TRUE;
2843
2844
8.75k
    if (gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL) {
2845
  /* degenerate radial gradients are clear */
2846
3.82k
  if (_radial_pattern_is_degenerate ((cairo_radial_pattern_t *) gradient))
2847
0
      return TRUE;
2848
4.92k
    } else if (gradient->base.extend == CAIRO_EXTEND_NONE) {
2849
  /* EXTEND_NONE degenerate linear gradients are clear */
2850
0
  if (_linear_pattern_is_degenerate ((cairo_linear_pattern_t *) gradient))
2851
0
      return TRUE;
2852
0
    }
2853
2854
    /* Check if the extents intersect the drawn part of the pattern. */
2855
8.75k
    if (extents != NULL &&
2856
0
  (gradient->base.extend == CAIRO_EXTEND_NONE ||
2857
0
   gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL))
2858
0
    {
2859
0
  double t[2];
2860
2861
0
  _cairo_gradient_pattern_box_to_parameter (gradient,
2862
0
              extents->x,
2863
0
              extents->y,
2864
0
              extents->x + extents->width,
2865
0
              extents->y + extents->height,
2866
0
              DBL_EPSILON,
2867
0
              t);
2868
2869
0
  if (gradient->base.extend == CAIRO_EXTEND_NONE &&
2870
0
      (t[0] >= gradient->stops[gradient->n_stops - 1].offset ||
2871
0
       t[1] <= gradient->stops[0].offset))
2872
0
  {
2873
0
    return TRUE;
2874
0
  }
2875
2876
0
  if (t[0] == t[1])
2877
0
      return TRUE;
2878
0
    }
2879
2880
8.75k
    for (i = 0; i < gradient->n_stops; i++)
2881
8.75k
  if (! CAIRO_COLOR_IS_CLEAR (&gradient->stops[i].color))
2882
8.75k
      return FALSE;
2883
2884
0
    return TRUE;
2885
8.75k
}
2886
2887
static void
2888
_gradient_color_average (const cairo_gradient_pattern_t *gradient,
2889
       cairo_color_t *color)
2890
0
{
2891
0
    double delta0, delta1;
2892
0
    double r, g, b, a;
2893
0
    unsigned int i, start = 1, end;
2894
2895
0
    assert (gradient->n_stops > 0);
2896
0
    assert (gradient->base.extend != CAIRO_EXTEND_NONE);
2897
2898
0
    if (gradient->n_stops == 1) {
2899
0
  _cairo_color_init_rgba (color,
2900
0
        gradient->stops[0].color.red,
2901
0
        gradient->stops[0].color.green,
2902
0
        gradient->stops[0].color.blue,
2903
0
        gradient->stops[0].color.alpha);
2904
0
  return;
2905
0
    }
2906
2907
0
    end = gradient->n_stops - 1;
2908
2909
0
    switch (gradient->base.extend) {
2910
0
    case CAIRO_EXTEND_REPEAT:
2911
      /*
2912
       * Sa, Sb and Sy, Sz are the first two and last two stops respectively.
2913
       * The weight of the first and last stop can be computed as the area of
2914
       * the following triangles (taken with height 1, since the whole [0-1]
2915
       * will have total weight 1 this way): b*h/2
2916
       *
2917
       *              +                   +
2918
       *            / |\                / | \
2919
       *          /   | \             /   |   \
2920
       *        /     |  \          /     |     \
2921
       * ~~~~~+---+---+---+~~~~~~~+-------+---+---+~~~~~
2922
       *   -1+Sz  0  Sa   Sb      Sy     Sz   1  1+Sa
2923
       *
2924
       * For the first stop: (Sb-(-1+Sz)/2 = (1+Sb-Sz)/2
2925
       * For the last stop: ((1+Sa)-Sy)/2 = (1+Sa-Sy)/2
2926
       * Halving the result is done after summing up all the areas.
2927
       */
2928
0
  delta0 = 1.0 + gradient->stops[1].offset - gradient->stops[end].offset;
2929
0
  delta1 = 1.0 + gradient->stops[0].offset - gradient->stops[end-1].offset;
2930
0
  break;
2931
2932
0
    case CAIRO_EXTEND_REFLECT:
2933
      /*
2934
       * Sa, Sb and Sy, Sz are the first two and last two stops respectively.
2935
       * The weight of the first and last stop can be computed as the area of
2936
       * the following trapezoids (taken with height 1, since the whole [0-1]
2937
       * will have total weight 1 this way): (b+B)*h/2
2938
       *
2939
       * +-------+                   +---+
2940
       * |       |\                / |   |
2941
       * |       | \             /   |   |
2942
       * |       |  \          /     |   |
2943
       * +-------+---+~~~~~~~+-------+---+
2944
       * 0      Sa   Sb      Sy     Sz   1
2945
       *
2946
       * For the first stop: (Sa+Sb)/2
2947
       * For the last stop: ((1-Sz) + (1-Sy))/2 = (2-Sy-Sz)/2
2948
       * Halving the result is done after summing up all the areas.
2949
       */
2950
0
  delta0 = gradient->stops[0].offset + gradient->stops[1].offset;
2951
0
  delta1 = 2.0 - gradient->stops[end-1].offset - gradient->stops[end].offset;
2952
0
  break;
2953
2954
0
    case CAIRO_EXTEND_PAD:
2955
      /* PAD is computed as the average of the first and last stop:
2956
       *  - take both of them with weight 1 (they will be halved
2957
       *    after the whole sum has been computed).
2958
       *  - avoid summing any of the inner stops.
2959
       */
2960
0
  delta0 = delta1 = 1.0;
2961
0
  start = end;
2962
0
  break;
2963
2964
0
    case CAIRO_EXTEND_NONE:
2965
0
    default:
2966
0
  ASSERT_NOT_REACHED;
2967
0
  _cairo_color_init_rgba (color, 0, 0, 0, 0);
2968
0
  return;
2969
0
    }
2970
2971
0
    r = delta0 * gradient->stops[0].color.red;
2972
0
    g = delta0 * gradient->stops[0].color.green;
2973
0
    b = delta0 * gradient->stops[0].color.blue;
2974
0
    a = delta0 * gradient->stops[0].color.alpha;
2975
2976
0
    for (i = start; i < end; ++i) {
2977
      /* Inner stops weight is the same as the area of the triangle they influence
2978
       * (which goes from the stop before to the stop after), again with height 1
2979
       * since the whole must sum up to 1: b*h/2
2980
       * Halving is done after the whole sum has been computed.
2981
       */
2982
0
  double delta = gradient->stops[i+1].offset - gradient->stops[i-1].offset;
2983
0
  r += delta * gradient->stops[i].color.red;
2984
0
  g += delta * gradient->stops[i].color.green;
2985
0
  b += delta * gradient->stops[i].color.blue;
2986
0
  a += delta * gradient->stops[i].color.alpha;
2987
0
    }
2988
2989
0
    r += delta1 * gradient->stops[end].color.red;
2990
0
    g += delta1 * gradient->stops[end].color.green;
2991
0
    b += delta1 * gradient->stops[end].color.blue;
2992
0
    a += delta1 * gradient->stops[end].color.alpha;
2993
2994
0
    _cairo_color_init_rgba (color, r * .5, g * .5, b * .5, a * .5);
2995
0
}
2996
2997
/**
2998
 * _cairo_pattern_alpha_range:
2999
 *
3000
 * Convenience function to determine the minimum and maximum alpha in
3001
 * the drawn part of a pattern (i.e. ignoring clear parts caused by
3002
 * extend modes and/or pattern shape).
3003
 *
3004
 * If not NULL, out_min and out_max will be set respectively to the
3005
 * minimum and maximum alpha value of the pattern.
3006
 **/
3007
void
3008
_cairo_pattern_alpha_range (const cairo_pattern_t *pattern,
3009
          double                *out_min,
3010
          double                *out_max)
3011
0
{
3012
0
    double alpha_min, alpha_max;
3013
3014
0
    switch (pattern->type) {
3015
0
    case CAIRO_PATTERN_TYPE_SOLID: {
3016
0
  const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
3017
0
  alpha_min = alpha_max = solid->color.alpha;
3018
0
  break;
3019
0
    }
3020
3021
0
    case CAIRO_PATTERN_TYPE_LINEAR:
3022
0
    case CAIRO_PATTERN_TYPE_RADIAL: {
3023
0
  const cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
3024
0
  unsigned int i;
3025
3026
0
  assert (gradient->n_stops >= 1);
3027
3028
0
  alpha_min = alpha_max = gradient->stops[0].color.alpha;
3029
0
  for (i = 1; i < gradient->n_stops; i++) {
3030
0
      if (alpha_min > gradient->stops[i].color.alpha)
3031
0
    alpha_min = gradient->stops[i].color.alpha;
3032
0
      else if (alpha_max < gradient->stops[i].color.alpha)
3033
0
    alpha_max = gradient->stops[i].color.alpha;
3034
0
  }
3035
3036
0
  break;
3037
0
    }
3038
3039
0
    case CAIRO_PATTERN_TYPE_MESH: {
3040
0
  const cairo_mesh_pattern_t *mesh = (const cairo_mesh_pattern_t *) pattern;
3041
0
  const cairo_mesh_patch_t *patch = _cairo_array_index_const (&mesh->patches, 0);
3042
0
  unsigned int i, j, n = _cairo_array_num_elements (&mesh->patches);
3043
3044
0
  assert (n >= 1);
3045
3046
0
  alpha_min = alpha_max = patch[0].colors[0].alpha;
3047
0
  for (i = 0; i < n; i++) {
3048
0
      for (j = 0; j < 4; j++) {
3049
0
    if (patch[i].colors[j].alpha < alpha_min)
3050
0
        alpha_min = patch[i].colors[j].alpha;
3051
0
    else if (patch[i].colors[j].alpha > alpha_max)
3052
0
        alpha_max = patch[i].colors[j].alpha;
3053
0
      }
3054
0
  }
3055
3056
0
  break;
3057
0
    }
3058
3059
0
    default:
3060
0
  ASSERT_NOT_REACHED;
3061
  /* fall through */
3062
3063
0
    case CAIRO_PATTERN_TYPE_SURFACE:
3064
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3065
0
  alpha_min = 0;
3066
0
  alpha_max = 1;
3067
0
  break;
3068
0
    }
3069
3070
0
    if (out_min)
3071
0
  *out_min = alpha_min;
3072
0
    if (out_max)
3073
0
  *out_max = alpha_max;
3074
0
}
3075
3076
/**
3077
 * _cairo_mesh_pattern_coord_box:
3078
 *
3079
 * Convenience function to determine the range of the coordinates of
3080
 * the points used to define the patches of the mesh.
3081
 *
3082
 * This is guaranteed to contain the pattern extents, but might not be
3083
 * tight, just like a Bezier curve is always inside the convex hull of
3084
 * the control points.
3085
 *
3086
 * This function cannot be used while the mesh is being constructed.
3087
 *
3088
 * The function returns TRUE and sets the output parameters to define
3089
 * the coordinate range if the mesh pattern contains at least one
3090
 * patch, otherwise it returns FALSE.
3091
 **/
3092
cairo_bool_t
3093
_cairo_mesh_pattern_coord_box (const cairo_mesh_pattern_t *mesh,
3094
             double                     *out_xmin,
3095
             double                     *out_ymin,
3096
             double                     *out_xmax,
3097
             double                     *out_ymax)
3098
0
{
3099
0
    const cairo_mesh_patch_t *patch;
3100
0
    unsigned int num_patches, i, j, k;
3101
0
    double x0, y0, x1, y1;
3102
3103
0
    assert (mesh->current_patch == NULL);
3104
3105
0
    num_patches = _cairo_array_num_elements (&mesh->patches);
3106
3107
0
    if (num_patches == 0)
3108
0
  return FALSE;
3109
3110
0
    patch = _cairo_array_index_const (&mesh->patches, 0);
3111
0
    x0 = x1 = patch->points[0][0].x;
3112
0
    y0 = y1 = patch->points[0][0].y;
3113
3114
0
    for (i = 0; i < num_patches; i++) {
3115
0
  for (j = 0; j < 4; j++) {
3116
0
      for (k = 0; k < 4; k++) {
3117
0
    x0 = MIN (x0, patch[i].points[j][k].x);
3118
0
    y0 = MIN (y0, patch[i].points[j][k].y);
3119
0
    x1 = MAX (x1, patch[i].points[j][k].x);
3120
0
    y1 = MAX (y1, patch[i].points[j][k].y);
3121
0
      }
3122
0
  }
3123
0
    }
3124
3125
0
    *out_xmin = x0;
3126
0
    *out_ymin = y0;
3127
0
    *out_xmax = x1;
3128
0
    *out_ymax = y1;
3129
3130
0
    return TRUE;
3131
0
}
3132
3133
/**
3134
 * _cairo_gradient_pattern_is_solid:
3135
 *
3136
 * Convenience function to determine whether a gradient pattern is
3137
 * a solid color within the given extents. In this case the color
3138
 * argument is initialized to the color the pattern represents.
3139
 * This functions doesn't handle completely transparent gradients,
3140
 * thus it should be called only after _cairo_pattern_is_clear has
3141
 * returned FALSE.
3142
 *
3143
 * Return value: %TRUE if the pattern is a solid color.
3144
 **/
3145
cairo_bool_t
3146
_cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient,
3147
          const cairo_rectangle_int_t *extents,
3148
          cairo_color_t *color)
3149
6.23k
{
3150
6.23k
    unsigned int i;
3151
3152
6.23k
    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
3153
6.23k
      gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
3154
3155
    /* TODO: radial */
3156
6.23k
    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
3157
4.32k
  cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
3158
4.32k
  if (_linear_pattern_is_degenerate (linear)) {
3159
0
      _gradient_color_average (gradient, color);
3160
0
      return TRUE;
3161
0
  }
3162
3163
4.32k
  if (gradient->base.extend == CAIRO_EXTEND_NONE) {
3164
0
      double t[2];
3165
3166
      /* We already know that the pattern is not clear, thus if some
3167
       * part of it is clear, the whole is not solid.
3168
       */
3169
3170
0
      if (extents == NULL)
3171
0
    return FALSE;
3172
3173
0
      _cairo_linear_pattern_box_to_parameter (linear,
3174
0
                extents->x,
3175
0
                extents->y,
3176
0
                extents->x + extents->width,
3177
0
                extents->y + extents->height,
3178
0
                t);
3179
3180
0
      if (t[0] < 0.0 || t[1] > 1.0)
3181
0
    return FALSE;
3182
0
  }
3183
4.32k
    } else
3184
1.91k
  return FALSE;
3185
3186
8.04k
    for (i = 1; i < gradient->n_stops; i++)
3187
4.32k
  if (! _cairo_color_stop_equal (&gradient->stops[0].color,
3188
4.32k
               &gradient->stops[i].color))
3189
603
      return FALSE;
3190
3191
3.72k
    _cairo_color_init_rgba (color,
3192
3.72k
          gradient->stops[0].color.red,
3193
3.72k
          gradient->stops[0].color.green,
3194
3.72k
          gradient->stops[0].color.blue,
3195
3.72k
          gradient->stops[0].color.alpha);
3196
3197
3.72k
    return TRUE;
3198
4.32k
}
3199
3200
/**
3201
 * _cairo_pattern_is_constant_alpha:
3202
 *
3203
 * Convenience function to determine whether a pattern has constant
3204
 * alpha within the given extents. In this case the alpha argument is
3205
 * initialized to the alpha within the extents.
3206
 *
3207
 * Return value: %TRUE if the pattern has constant alpha.
3208
 **/
3209
cairo_bool_t
3210
_cairo_pattern_is_constant_alpha (const cairo_pattern_t         *abstract_pattern,
3211
          const cairo_rectangle_int_t   *extents,
3212
          double                        *alpha)
3213
0
{
3214
0
    const cairo_pattern_union_t *pattern;
3215
0
    cairo_color_t color;
3216
3217
0
    if (_cairo_pattern_is_clear (abstract_pattern)) {
3218
0
  *alpha = 0.0;
3219
0
  return TRUE;
3220
0
    }
3221
3222
0
    if (_cairo_pattern_is_opaque (abstract_pattern, extents)) {
3223
0
  *alpha = 1.0;
3224
0
  return TRUE;
3225
0
    }
3226
3227
0
    pattern = (cairo_pattern_union_t *) abstract_pattern;
3228
0
    switch (pattern->base.type) {
3229
0
    case CAIRO_PATTERN_TYPE_SOLID:
3230
0
  *alpha = pattern->solid.color.alpha;
3231
0
  return TRUE;
3232
3233
0
    case CAIRO_PATTERN_TYPE_LINEAR:
3234
0
    case CAIRO_PATTERN_TYPE_RADIAL:
3235
0
  if (_cairo_gradient_pattern_is_solid (&pattern->gradient.base, extents, &color)) {
3236
0
      *alpha = color.alpha;
3237
0
      return TRUE;
3238
0
  } else {
3239
0
      return FALSE;
3240
0
  }
3241
3242
  /* TODO: need to test these as well */
3243
0
    case CAIRO_PATTERN_TYPE_SURFACE:
3244
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3245
0
    case CAIRO_PATTERN_TYPE_MESH:
3246
0
  return FALSE;
3247
0
    }
3248
3249
0
    ASSERT_NOT_REACHED;
3250
0
    return FALSE;
3251
0
}
3252
3253
static cairo_bool_t
3254
_mesh_is_clear (const cairo_mesh_pattern_t *mesh)
3255
0
{
3256
0
    double x1, y1, x2, y2;
3257
0
    cairo_bool_t is_valid;
3258
3259
0
    is_valid = _cairo_mesh_pattern_coord_box (mesh, &x1, &y1, &x2, &y2);
3260
0
    if (!is_valid)
3261
0
  return TRUE;
3262
3263
0
    if (x2 - x1 < DBL_EPSILON || y2 - y1 < DBL_EPSILON)
3264
0
  return TRUE;
3265
3266
0
    return FALSE;
3267
0
}
3268
3269
/**
3270
 * _cairo_pattern_is_opaque_solid:
3271
 *
3272
 * Convenience function to determine whether a pattern is an opaque
3273
 * (alpha==1.0) solid color pattern. This is done by testing whether
3274
 * the pattern's alpha value when converted to a byte is 255, so if a
3275
 * backend actually supported deep alpha channels this function might
3276
 * not do the right thing.
3277
 *
3278
 * Return value: %TRUE if the pattern is an opaque, solid color.
3279
 **/
3280
cairo_bool_t
3281
_cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern)
3282
679k
{
3283
679k
    cairo_solid_pattern_t *solid;
3284
3285
679k
    if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
3286
2.92k
  return FALSE;
3287
3288
676k
    solid = (cairo_solid_pattern_t *) pattern;
3289
3290
676k
    return CAIRO_COLOR_IS_OPAQUE (&solid->color);
3291
679k
}
3292
3293
static cairo_bool_t
3294
_surface_is_opaque (const cairo_surface_pattern_t *pattern,
3295
        const cairo_rectangle_int_t *sample)
3296
419
{
3297
419
    cairo_rectangle_int_t extents;
3298
3299
419
    if (pattern->surface->content & CAIRO_CONTENT_ALPHA)
3300
419
  return FALSE;
3301
3302
0
    if (pattern->base.extend != CAIRO_EXTEND_NONE)
3303
0
  return TRUE;
3304
3305
0
    if (! _cairo_surface_get_extents (pattern->surface, &extents))
3306
0
  return TRUE;
3307
3308
0
    if (sample == NULL)
3309
0
  return FALSE;
3310
3311
0
    return _cairo_rectangle_contains_rectangle (&extents, sample);
3312
0
}
3313
3314
static cairo_bool_t
3315
_raster_source_is_opaque (const cairo_raster_source_pattern_t *pattern,
3316
        const cairo_rectangle_int_t *sample)
3317
0
{
3318
0
    if (pattern->content & CAIRO_CONTENT_ALPHA)
3319
0
  return FALSE;
3320
3321
0
    if (pattern->base.extend != CAIRO_EXTEND_NONE)
3322
0
  return TRUE;
3323
3324
0
    if (sample == NULL)
3325
0
  return FALSE;
3326
3327
0
    return _cairo_rectangle_contains_rectangle (&pattern->extents, sample);
3328
0
}
3329
3330
static cairo_bool_t
3331
_surface_is_clear (const cairo_surface_pattern_t *pattern)
3332
1.03M
{
3333
1.03M
    cairo_rectangle_int_t extents;
3334
3335
1.03M
    if (_cairo_surface_get_extents (pattern->surface, &extents) &&
3336
1.03M
  (extents.width == 0 || extents.height == 0))
3337
0
  return TRUE;
3338
3339
1.03M
    return pattern->surface->is_clear &&
3340
0
  pattern->surface->content & CAIRO_CONTENT_ALPHA;
3341
1.03M
}
3342
3343
static cairo_bool_t
3344
_raster_source_is_clear (const cairo_raster_source_pattern_t *pattern)
3345
0
{
3346
0
    return pattern->extents.width == 0 || pattern->extents.height == 0;
3347
0
}
3348
3349
static cairo_bool_t
3350
_gradient_is_opaque (const cairo_gradient_pattern_t *gradient,
3351
         const cairo_rectangle_int_t *sample)
3352
2.23k
{
3353
2.23k
    unsigned int i;
3354
3355
2.23k
    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
3356
2.23k
      gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
3357
3358
2.23k
    if (gradient->n_stops == 0 ||
3359
2.23k
  (gradient->base.extend == CAIRO_EXTEND_NONE &&
3360
0
   gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
3361
0
  return FALSE;
3362
3363
2.23k
    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
3364
511
  if (gradient->base.extend == CAIRO_EXTEND_NONE) {
3365
0
      double t[2];
3366
0
      cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
3367
3368
      /* EXTEND_NONE degenerate radial gradients are clear */
3369
0
      if (_linear_pattern_is_degenerate (linear))
3370
0
    return FALSE;
3371
3372
0
      if (sample == NULL)
3373
0
    return FALSE;
3374
3375
0
      _cairo_linear_pattern_box_to_parameter (linear,
3376
0
                sample->x,
3377
0
                sample->y,
3378
0
                sample->x + sample->width,
3379
0
                sample->y + sample->height,
3380
0
                t);
3381
3382
0
      if (t[0] < 0.0 || t[1] > 1.0)
3383
0
    return FALSE;
3384
0
  }
3385
511
    } else
3386
1.72k
  return FALSE; /* TODO: check actual intersection */
3387
3388
1.53k
    for (i = 0; i < gradient->n_stops; i++)
3389
1.02k
  if (! CAIRO_COLOR_IS_OPAQUE (&gradient->stops[i].color))
3390
0
      return FALSE;
3391
3392
511
    return TRUE;
3393
511
}
3394
3395
/**
3396
 * _cairo_pattern_is_opaque:
3397
 *
3398
 * Convenience function to determine whether a pattern is an opaque
3399
 * pattern (of any type). The same caveats that apply to
3400
 * _cairo_pattern_is_opaque_solid apply here as well.
3401
 *
3402
 * Return value: %TRUE if the pattern is a opaque.
3403
 **/
3404
cairo_bool_t
3405
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern,
3406
        const cairo_rectangle_int_t *sample)
3407
466k
{
3408
466k
    const cairo_pattern_union_t *pattern;
3409
3410
466k
    if (abstract_pattern->has_component_alpha)
3411
0
  return FALSE;
3412
3413
466k
    pattern = (cairo_pattern_union_t *) abstract_pattern;
3414
466k
    switch (pattern->base.type) {
3415
463k
    case CAIRO_PATTERN_TYPE_SOLID:
3416
463k
  return _cairo_pattern_is_opaque_solid (abstract_pattern);
3417
419
    case CAIRO_PATTERN_TYPE_SURFACE:
3418
419
  return _surface_is_opaque (&pattern->surface, sample);
3419
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3420
0
  return _raster_source_is_opaque (&pattern->raster_source, sample);
3421
511
    case CAIRO_PATTERN_TYPE_LINEAR:
3422
2.23k
    case CAIRO_PATTERN_TYPE_RADIAL:
3423
2.23k
  return _gradient_is_opaque (&pattern->gradient.base, sample);
3424
0
    case CAIRO_PATTERN_TYPE_MESH:
3425
0
  return FALSE;
3426
466k
    }
3427
3428
0
    ASSERT_NOT_REACHED;
3429
0
    return FALSE;
3430
0
}
3431
3432
cairo_bool_t
3433
_cairo_pattern_is_clear (const cairo_pattern_t *abstract_pattern)
3434
26.4M
{
3435
26.4M
    const cairo_pattern_union_t *pattern;
3436
3437
26.4M
    if (abstract_pattern->has_component_alpha)
3438
0
  return FALSE;
3439
3440
26.4M
    pattern = (cairo_pattern_union_t *) abstract_pattern;
3441
26.4M
    switch (abstract_pattern->type) {
3442
25.3M
    case CAIRO_PATTERN_TYPE_SOLID:
3443
25.3M
  return CAIRO_COLOR_IS_CLEAR (&pattern->solid.color);
3444
1.03M
    case CAIRO_PATTERN_TYPE_SURFACE:
3445
1.03M
  return _surface_is_clear (&pattern->surface);
3446
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3447
0
  return _raster_source_is_clear (&pattern->raster_source);
3448
4.92k
    case CAIRO_PATTERN_TYPE_LINEAR:
3449
8.75k
    case CAIRO_PATTERN_TYPE_RADIAL:
3450
8.75k
  return _gradient_is_clear (&pattern->gradient.base, NULL);
3451
0
    case CAIRO_PATTERN_TYPE_MESH:
3452
0
  return _mesh_is_clear (&pattern->mesh);
3453
26.4M
    }
3454
3455
0
    ASSERT_NOT_REACHED;
3456
0
    return FALSE;
3457
0
}
3458
3459
/*
3460
 * Will given row of back-translation matrix work with bilinear scale?
3461
 * This is true for scales larger than 1. Also it was judged acceptable
3462
 * for scales larger than .75. And if there is integer translation
3463
 * then a scale of exactly .5 works.
3464
 */
3465
static int
3466
use_bilinear(double x, double y, double t)
3467
390
{
3468
    /* This is the inverse matrix! */
3469
390
    double h = x*x + y*y;
3470
390
    if (h < 1.0 / (0.75 * 0.75))
3471
291
  return TRUE; /* scale > .75 */
3472
99
    if ((h > 3.99 && h < 4.01) /* scale is 1/2 */
3473
3
  && !_cairo_fixed_from_double(x*y) /* parallel to an axis */
3474
3
  && _cairo_fixed_is_integer (_cairo_fixed_from_double (t)))
3475
3
  return TRUE;
3476
96
    return FALSE;
3477
99
}
3478
3479
/**
3480
 * _cairo_pattern_analyze_filter:
3481
 * @pattern: surface pattern
3482
 *
3483
 * Possibly optimize the filter to a simpler value depending on transformation
3484
 *
3485
 * Returns: the optimized #cairo_filter_t to use with @pattern.
3486
 **/
3487
cairo_filter_t
3488
_cairo_pattern_analyze_filter (const cairo_pattern_t *pattern)
3489
515k
{
3490
515k
    switch (pattern->filter) {
3491
515k
    case CAIRO_FILTER_GOOD:
3492
515k
    case CAIRO_FILTER_BEST:
3493
515k
    case CAIRO_FILTER_BILINEAR:
3494
515k
    case CAIRO_FILTER_FAST:
3495
  /* If source pixels map 1:1 onto destination pixels, we do
3496
   * not need to filter (and do not want to filter, since it
3497
   * will cause blurriness)
3498
   */
3499
515k
  if (_cairo_matrix_is_pixel_exact (&pattern->matrix)) {
3500
515k
      return CAIRO_FILTER_NEAREST;
3501
515k
  } else {
3502
      /* Use BILINEAR for any scale greater than .75 instead
3503
       * of GOOD. For scales of 1 and larger this is identical,
3504
       * for the smaller sizes it was judged that the artifacts
3505
       * were not worse than the artifacts from a box filer.
3506
       * BILINEAR can also be used if the scale is exactly .5
3507
       * and the translation in that direction is an integer.
3508
       */
3509
241
      if (pattern->filter == CAIRO_FILTER_GOOD &&
3510
241
    use_bilinear (pattern->matrix.xx, pattern->matrix.xy,
3511
241
            pattern->matrix.x0) &&
3512
149
    use_bilinear (pattern->matrix.yx, pattern->matrix.yy,
3513
149
            pattern->matrix.y0))
3514
145
    return CAIRO_FILTER_BILINEAR;
3515
241
  }
3516
96
  break;
3517
3518
96
    case CAIRO_FILTER_NEAREST:
3519
0
    case CAIRO_FILTER_GAUSSIAN:
3520
0
    default:
3521
0
  break;
3522
515k
    }
3523
3524
96
    return pattern->filter;
3525
515k
}
3526
3527
/**
3528
 * _cairo_hypot:
3529
 * Returns: value similar to hypot(@x,@y)
3530
 *
3531
 * May want to replace this with Manhattan distance (abs(x)+abs(y)) if
3532
 * hypot is too slow, as there is no need for accuracy here.
3533
 **/
3534
static inline double
3535
_cairo_hypot(double x, double y)
3536
194
{
3537
194
    return hypot(x, y);
3538
194
}
3539
3540
/**
3541
 * _cairo_pattern_sampled_area:
3542
 *
3543
 * Return region of @pattern that will be sampled to fill @extents,
3544
 * based on the transformation and filter.
3545
 *
3546
 * This does not include pixels that are mulitiplied by values very
3547
 * close to zero by the ends of filters. This is so that transforms
3548
 * that should be the identity or 90 degree rotations do not expand
3549
 * the source unexpectedly.
3550
 *
3551
 * XXX: We don't actually have any way of querying the backend for
3552
 *      the filter radius, so we just guess base on what we know that
3553
 *      backends do currently (see bug #10508)
3554
 **/
3555
void
3556
_cairo_pattern_sampled_area (const cairo_pattern_t *pattern,
3557
           const cairo_rectangle_int_t *extents,
3558
           cairo_rectangle_int_t *sample)
3559
515k
{
3560
515k
    double x1, x2, y1, y2;
3561
515k
    double padx, pady;
3562
3563
    /* Assume filters are interpolating, which means identity
3564
       cannot change the image */
3565
515k
    if (_cairo_matrix_is_identity (&pattern->matrix)) {
3566
33.5k
  *sample = *extents;
3567
33.5k
  return;
3568
33.5k
    }
3569
3570
    /* Transform the centers of the corner pixels */
3571
482k
    x1 = extents->x + 0.5;
3572
482k
    y1 = extents->y + 0.5;
3573
482k
    x2 = x1 + (extents->width - 1);
3574
482k
    y2 = y1 + (extents->height - 1);
3575
482k
    _cairo_matrix_transform_bounding_box (&pattern->matrix,
3576
482k
            &x1, &y1, &x2, &y2,
3577
482k
            NULL);
3578
3579
    /* How far away from center will it actually sample?
3580
     * This is the distance from a transformed pixel center to the
3581
     * furthest sample of reasonable size.
3582
     */
3583
482k
    switch (pattern->filter) {
3584
482k
    case CAIRO_FILTER_NEAREST:
3585
482k
    case CAIRO_FILTER_FAST:
3586
  /* Correct value is zero, but when the sample is on an integer
3587
   * it is unknown if the backend will sample the pixel to the
3588
   * left or right. This value makes it include both possible pixels.
3589
   */
3590
482k
  padx = pady = 0.004;
3591
482k
  break;
3592
145
    case CAIRO_FILTER_BILINEAR:
3593
145
    case CAIRO_FILTER_GAUSSIAN:
3594
145
    default:
3595
  /* Correct value is .5 */
3596
145
  padx = pady = 0.495;
3597
145
  break;
3598
96
    case CAIRO_FILTER_GOOD:
3599
  /* Correct value is max(width,1)*.5 */
3600
96
  padx = _cairo_hypot (pattern->matrix.xx, pattern->matrix.xy);
3601
96
  if (padx <= 1.0) padx = 0.495;
3602
92
  else if (padx >= 16.0) padx = 7.92;
3603
64
  else padx *= 0.495;
3604
96
  pady = _cairo_hypot (pattern->matrix.yx, pattern->matrix.yy);
3605
96
  if (pady <= 1.0) pady = 0.495;
3606
11
  else if (pady >= 16.0) pady = 7.92;
3607
6
  else pady *= 0.495;
3608
96
  break;
3609
0
    case CAIRO_FILTER_BEST:
3610
  /* Correct value is width*2 */
3611
0
  padx = _cairo_hypot (pattern->matrix.xx, pattern->matrix.xy) * 1.98;
3612
0
  if (padx > 7.92) padx = 7.92;
3613
0
  pady = _cairo_hypot (pattern->matrix.yx, pattern->matrix.yy) * 1.98;
3614
0
  if (pady > 7.92) pady = 7.92;
3615
0
  break;
3616
482k
    }
3617
3618
    /* round furthest samples to edge of pixels */
3619
482k
    x1 = floor (x1 - padx);
3620
482k
    if (x1 < CAIRO_RECT_INT_MIN) x1 = CAIRO_RECT_INT_MIN;
3621
482k
    sample->x = x1;
3622
3623
482k
    y1 = floor (y1 - pady);
3624
482k
    if (y1 < CAIRO_RECT_INT_MIN) y1 = CAIRO_RECT_INT_MIN;
3625
482k
    sample->y = y1;
3626
3627
482k
    x2 = floor (x2 + padx) + 1.0;
3628
482k
    if (x2 > CAIRO_RECT_INT_MAX) x2 = CAIRO_RECT_INT_MAX;
3629
482k
    sample->width = x2 - x1;
3630
3631
482k
    y2 = floor (y2 + pady) + 1.0;
3632
482k
    if (y2 > CAIRO_RECT_INT_MAX) y2 = CAIRO_RECT_INT_MAX;
3633
482k
    sample->height = y2 - y1;
3634
482k
}
3635
3636
/**
3637
 * _cairo_pattern_get_extents:
3638
 *
3639
 * Return the "target-space" extents of @pattern in @extents.
3640
 *
3641
 * For unbounded patterns, the @extents will be initialized with
3642
 * "infinite" extents, (minimum and maximum fixed-point values).
3643
 *
3644
 * When is_vector is TRUE, avoid rounding to zero widths or heights that
3645
 * are less than 1 unit.
3646
 *
3647
 * XXX: Currently, bounded gradient patterns will also return
3648
 * "infinite" extents, though it would be possible to optimize these
3649
 * with a little more work.
3650
 **/
3651
void
3652
_cairo_pattern_get_extents (const cairo_pattern_t         *pattern,
3653
          cairo_rectangle_int_t         *extents,
3654
          cairo_bool_t                   is_vector)
3655
13.1M
{
3656
13.1M
    double x1, y1, x2, y2;
3657
13.1M
    int ix1, ix2, iy1, iy2;
3658
13.1M
    cairo_bool_t round_x = FALSE;
3659
13.1M
    cairo_bool_t round_y = FALSE;
3660
3661
13.1M
    switch (pattern->type) {
3662
12.6M
    case CAIRO_PATTERN_TYPE_SOLID:
3663
12.6M
  goto UNBOUNDED;
3664
3665
513k
    case CAIRO_PATTERN_TYPE_SURFACE:
3666
513k
  {
3667
513k
      cairo_rectangle_int_t surface_extents;
3668
513k
      const cairo_surface_pattern_t *surface_pattern =
3669
513k
    (const cairo_surface_pattern_t *) pattern;
3670
513k
      cairo_surface_t *surface = surface_pattern->surface;
3671
3672
513k
      if (! _cairo_surface_get_extents (surface, &surface_extents))
3673
0
    goto UNBOUNDED;
3674
3675
513k
      if (surface_extents.width == 0 || surface_extents.height == 0)
3676
0
    goto EMPTY;
3677
3678
513k
      if (pattern->extend != CAIRO_EXTEND_NONE)
3679
16.4k
    goto UNBOUNDED;
3680
3681
496k
      x1 = surface_extents.x;
3682
496k
      y1 = surface_extents.y;
3683
496k
      x2 = surface_extents.x + (int) surface_extents.width;
3684
496k
      y2 = surface_extents.y + (int) surface_extents.height;
3685
3686
496k
      goto HANDLE_FILTER;
3687
513k
  }
3688
0
  break;
3689
3690
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3691
0
  {
3692
0
      const cairo_raster_source_pattern_t *raster =
3693
0
    (const cairo_raster_source_pattern_t *) pattern;
3694
3695
0
      if (raster->extents.width == 0 || raster->extents.height == 0)
3696
0
    goto EMPTY;
3697
3698
0
      if (pattern->extend != CAIRO_EXTEND_NONE)
3699
0
    goto UNBOUNDED;
3700
3701
0
      x1 = raster->extents.x;
3702
0
      y1 = raster->extents.y;
3703
0
      x2 = raster->extents.x + (int) raster->extents.width;
3704
0
      y2 = raster->extents.y + (int) raster->extents.height;
3705
0
  }
3706
496k
    HANDLE_FILTER:
3707
496k
  switch (pattern->filter) {
3708
496k
  case CAIRO_FILTER_NEAREST:
3709
496k
  case CAIRO_FILTER_FAST:
3710
496k
      round_x = round_y = TRUE;
3711
      /* We don't know which way .5 will go, so fudge it slightly. */
3712
496k
      x1 -= 0.004;
3713
496k
      y1 -= 0.004;
3714
496k
      x2 += 0.004;
3715
496k
      y2 += 0.004;
3716
496k
      break;
3717
0
  case CAIRO_FILTER_BEST:
3718
      /* Assume best filter will produce nice antialiased edges */
3719
0
      break;
3720
0
  case CAIRO_FILTER_BILINEAR:
3721
0
  case CAIRO_FILTER_GAUSSIAN:
3722
1
  case CAIRO_FILTER_GOOD:
3723
1
  default:
3724
      /* These filters can blur the edge out 1/2 pixel when scaling up */
3725
1
      if (_cairo_hypot (pattern->matrix.xx, pattern->matrix.yx) < 1.0) {
3726
0
    x1 -= 0.5;
3727
0
    x2 += 0.5;
3728
0
    round_x = TRUE;
3729
0
      }
3730
1
      if (_cairo_hypot (pattern->matrix.xy, pattern->matrix.yy) < 1.0) {
3731
0
    y1 -= 0.5;
3732
0
    y2 += 0.5;
3733
0
    round_y = TRUE;
3734
0
      }
3735
1
      break;
3736
496k
  }
3737
496k
  break;
3738
3739
496k
    case CAIRO_PATTERN_TYPE_RADIAL:
3740
1.91k
  {
3741
1.91k
      const cairo_radial_pattern_t *radial =
3742
1.91k
    (const cairo_radial_pattern_t *) pattern;
3743
1.91k
      double cx1, cy1;
3744
1.91k
      double cx2, cy2;
3745
1.91k
      double r1, r2;
3746
3747
1.91k
      if (_radial_pattern_is_degenerate (radial)) {
3748
    /* cairo-gstate should have optimised degenerate
3749
     * patterns to solid clear patterns, so we can ignore
3750
     * them here. */
3751
0
    goto EMPTY;
3752
0
      }
3753
3754
      /* TODO: in some cases (focus outside/on the circle) it is
3755
       * half-bounded. */
3756
1.91k
      if (pattern->extend != CAIRO_EXTEND_NONE)
3757
1.91k
    goto UNBOUNDED;
3758
3759
0
      cx1 = radial->cd1.center.x;
3760
0
      cy1 = radial->cd1.center.y;
3761
0
      r1  = radial->cd1.radius;
3762
3763
0
      cx2 = radial->cd2.center.x;
3764
0
      cy2 = radial->cd2.center.y;
3765
0
      r2  = radial->cd2.radius;
3766
3767
0
      x1 = MIN (cx1 - r1, cx2 - r2);
3768
0
      y1 = MIN (cy1 - r1, cy2 - r2);
3769
0
      x2 = MAX (cx1 + r1, cx2 + r2);
3770
0
      y2 = MAX (cy1 + r1, cy2 + r2);
3771
0
  }
3772
0
  break;
3773
3774
603
    case CAIRO_PATTERN_TYPE_LINEAR:
3775
603
  {
3776
603
      const cairo_linear_pattern_t *linear =
3777
603
    (const cairo_linear_pattern_t *) pattern;
3778
3779
603
      if (pattern->extend != CAIRO_EXTEND_NONE)
3780
603
    goto UNBOUNDED;
3781
3782
0
      if (_linear_pattern_is_degenerate (linear)) {
3783
    /* cairo-gstate should have optimised degenerate
3784
     * patterns to solid ones, so we can again ignore
3785
     * them here. */
3786
0
    goto EMPTY;
3787
0
      }
3788
3789
      /* TODO: to get tight extents, use the matrix to transform
3790
       * the pattern instead of transforming the extents later. */
3791
0
      if (pattern->matrix.xy != 0. || pattern->matrix.yx != 0.)
3792
0
    goto UNBOUNDED;
3793
3794
0
      if (linear->pd1.x == linear->pd2.x) {
3795
0
    x1 = -HUGE_VAL;
3796
0
    x2 = HUGE_VAL;
3797
0
    y1 = MIN (linear->pd1.y, linear->pd2.y);
3798
0
    y2 = MAX (linear->pd1.y, linear->pd2.y);
3799
0
      } else if (linear->pd1.y == linear->pd2.y) {
3800
0
    x1 = MIN (linear->pd1.x, linear->pd2.x);
3801
0
    x2 = MAX (linear->pd1.x, linear->pd2.x);
3802
0
    y1 = -HUGE_VAL;
3803
0
    y2 = HUGE_VAL;
3804
0
      } else {
3805
0
    goto  UNBOUNDED;
3806
0
      }
3807
3808
      /* The current linear renderer just point-samples in the middle
3809
         of the pixels, similar to the NEAREST filter: */
3810
0
      round_x = round_y = TRUE;
3811
0
  }
3812
0
  break;
3813
3814
0
    case CAIRO_PATTERN_TYPE_MESH:
3815
0
  {
3816
0
      const cairo_mesh_pattern_t *mesh =
3817
0
    (const cairo_mesh_pattern_t *) pattern;
3818
0
      if (! _cairo_mesh_pattern_coord_box (mesh, &x1, &y1, &x2, &y2))
3819
0
    goto EMPTY;
3820
0
  }
3821
0
  break;
3822
3823
0
    default:
3824
0
  ASSERT_NOT_REACHED;
3825
13.1M
    }
3826
3827
496k
    if (_cairo_matrix_is_translation (&pattern->matrix)) {
3828
496k
  x1 -= pattern->matrix.x0; x2 -= pattern->matrix.x0;
3829
496k
  y1 -= pattern->matrix.y0; y2 -= pattern->matrix.y0;
3830
496k
    } else {
3831
1
  cairo_matrix_t imatrix;
3832
1
  cairo_status_t status;
3833
3834
1
  imatrix = pattern->matrix;
3835
1
  status = cairo_matrix_invert (&imatrix);
3836
  /* cairo_pattern_set_matrix ensures the matrix is invertible */
3837
1
  assert (status == CAIRO_STATUS_SUCCESS);
3838
3839
1
  _cairo_matrix_transform_bounding_box (&imatrix,
3840
1
                &x1, &y1, &x2, &y2,
3841
1
                NULL);
3842
1
    }
3843
3844
496k
    if (!round_x) {
3845
1
  x1 -= 0.5;
3846
1
  x2 += 0.5;
3847
1
    }
3848
496k
    if (x1 < CAIRO_RECT_INT_MIN)
3849
0
  ix1 = CAIRO_RECT_INT_MIN;
3850
496k
    else 
3851
496k
  ix1 = _cairo_lround (x1);
3852
496k
    if (x2 > CAIRO_RECT_INT_MAX)
3853
0
  ix2 = CAIRO_RECT_INT_MAX;
3854
496k
    else
3855
496k
  ix2 = _cairo_lround (x2);
3856
496k
    extents->x = ix1; extents->width  = ix2 - ix1;
3857
496k
    if (is_vector && extents->width == 0 && x1 != x2)
3858
0
  extents->width += 1;
3859
3860
496k
    if (!round_y) {
3861
1
  y1 -= 0.5;
3862
1
  y2 += 0.5;
3863
1
    }
3864
496k
    if (y1 < CAIRO_RECT_INT_MIN)
3865
0
  iy1 = CAIRO_RECT_INT_MIN;
3866
496k
    else
3867
496k
  iy1 = _cairo_lround (y1);
3868
496k
    if (y2 > CAIRO_RECT_INT_MAX)
3869
0
  iy2 = CAIRO_RECT_INT_MAX;
3870
496k
    else
3871
496k
  iy2 = _cairo_lround (y2);
3872
496k
    extents->y = iy1; extents->height = iy2 - iy1;
3873
496k
    if (is_vector && extents->height == 0 && y1 != y2)
3874
0
  extents->height += 1;
3875
3876
496k
    return;
3877
3878
12.6M
  UNBOUNDED:
3879
    /* unbounded patterns -> 'infinite' extents */
3880
12.6M
    _cairo_unbounded_rectangle_init (extents);
3881
12.6M
    return;
3882
3883
0
  EMPTY:
3884
0
    extents->x = extents->y = 0;
3885
0
    extents->width = extents->height = 0;
3886
0
    return;
3887
496k
}
3888
3889
/**
3890
 * _cairo_pattern_get_ink_extents:
3891
 *
3892
 * Return the "target-space" inked extents of @pattern in @extents.
3893
 **/
3894
cairo_int_status_t
3895
_cairo_pattern_get_ink_extents (const cairo_pattern_t         *pattern,
3896
        cairo_rectangle_int_t         *extents)
3897
0
{
3898
0
    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE &&
3899
0
  pattern->extend == CAIRO_EXTEND_NONE)
3900
0
    {
3901
0
  const cairo_surface_pattern_t *surface_pattern =
3902
0
      (const cairo_surface_pattern_t *) pattern;
3903
0
  cairo_surface_t *surface = surface_pattern->surface;
3904
3905
0
  surface = _cairo_surface_get_source (surface, NULL);
3906
0
  if (_cairo_surface_is_recording (surface)) {
3907
0
      cairo_matrix_t imatrix;
3908
0
      cairo_box_t box;
3909
0
      cairo_status_t status;
3910
3911
0
      imatrix = pattern->matrix;
3912
0
      status = cairo_matrix_invert (&imatrix);
3913
      /* cairo_pattern_set_matrix ensures the matrix is invertible */
3914
0
      assert (status == CAIRO_STATUS_SUCCESS);
3915
3916
0
      status = _cairo_recording_surface_get_ink_bbox ((cairo_recording_surface_t *)surface,
3917
0
               &box, &imatrix);
3918
0
      if (unlikely (status))
3919
0
    return status;
3920
3921
0
      _cairo_box_round_to_rectangle (&box, extents);
3922
0
      return CAIRO_STATUS_SUCCESS;
3923
0
  }
3924
0
    }
3925
3926
0
    _cairo_pattern_get_extents (pattern, extents, TRUE);
3927
0
    return CAIRO_STATUS_SUCCESS;
3928
0
}
3929
3930
static uintptr_t
3931
_cairo_solid_pattern_hash (uintptr_t hash,
3932
         const cairo_solid_pattern_t *solid)
3933
0
{
3934
0
    hash = _cairo_hash_bytes (hash, &solid->color, sizeof (solid->color));
3935
3936
0
    return hash;
3937
0
}
3938
3939
static uintptr_t
3940
_cairo_gradient_color_stops_hash (uintptr_t hash,
3941
          const cairo_gradient_pattern_t *gradient)
3942
0
{
3943
0
    unsigned int n;
3944
3945
0
    hash = _cairo_hash_bytes (hash,
3946
0
            &gradient->n_stops,
3947
0
            sizeof (gradient->n_stops));
3948
3949
0
    for (n = 0; n < gradient->n_stops; n++) {
3950
0
  hash = _cairo_hash_bytes (hash,
3951
0
          &gradient->stops[n].offset,
3952
0
          sizeof (double));
3953
0
  hash = _cairo_hash_bytes (hash,
3954
0
          &gradient->stops[n].color,
3955
0
          sizeof (cairo_color_stop_t));
3956
0
    }
3957
3958
0
    return hash;
3959
0
}
3960
3961
uintptr_t
3962
_cairo_linear_pattern_hash (uintptr_t hash,
3963
          const cairo_linear_pattern_t *linear)
3964
0
{
3965
0
    hash = _cairo_hash_bytes (hash, &linear->pd1, sizeof (linear->pd1));
3966
0
    hash = _cairo_hash_bytes (hash, &linear->pd2, sizeof (linear->pd2));
3967
3968
0
    return _cairo_gradient_color_stops_hash (hash, &linear->base);
3969
0
}
3970
3971
uintptr_t
3972
_cairo_radial_pattern_hash (uintptr_t hash,
3973
          const cairo_radial_pattern_t *radial)
3974
0
{
3975
0
    hash = _cairo_hash_bytes (hash, &radial->cd1.center, sizeof (radial->cd1.center));
3976
0
    hash = _cairo_hash_bytes (hash, &radial->cd1.radius, sizeof (radial->cd1.radius));
3977
0
    hash = _cairo_hash_bytes (hash, &radial->cd2.center, sizeof (radial->cd2.center));
3978
0
    hash = _cairo_hash_bytes (hash, &radial->cd2.radius, sizeof (radial->cd2.radius));
3979
3980
0
    return _cairo_gradient_color_stops_hash (hash, &radial->base);
3981
0
}
3982
3983
static uintptr_t
3984
_cairo_mesh_pattern_hash (uintptr_t hash, const cairo_mesh_pattern_t *mesh)
3985
0
{
3986
0
    const cairo_mesh_patch_t *patch = _cairo_array_index_const (&mesh->patches, 0);
3987
0
    unsigned int i, n = _cairo_array_num_elements (&mesh->patches);
3988
3989
0
    for (i = 0; i < n; i++)
3990
0
       hash = _cairo_hash_bytes (hash, patch + i, sizeof (cairo_mesh_patch_t));
3991
3992
0
    return hash;
3993
0
}
3994
3995
static uintptr_t
3996
_cairo_surface_pattern_hash (uintptr_t hash,
3997
           const cairo_surface_pattern_t *surface)
3998
0
{
3999
0
    hash ^= surface->surface->unique_id;
4000
4001
0
    return hash;
4002
0
}
4003
4004
static uintptr_t
4005
_cairo_raster_source_pattern_hash (uintptr_t hash,
4006
           const cairo_raster_source_pattern_t *raster)
4007
0
{
4008
0
    hash ^= (uintptr_t)raster->user_data;
4009
4010
0
    return hash;
4011
0
}
4012
4013
uintptr_t
4014
_cairo_pattern_hash (const cairo_pattern_t *pattern)
4015
0
{
4016
0
    uintptr_t hash = _CAIRO_HASH_INIT_VALUE;
4017
4018
0
    if (pattern->status)
4019
0
  return 0;
4020
4021
0
    hash = _cairo_hash_bytes (hash, &pattern->type, sizeof (pattern->type));
4022
0
    if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
4023
0
  hash = _cairo_hash_bytes (hash,
4024
0
          &pattern->matrix, sizeof (pattern->matrix));
4025
0
  hash = _cairo_hash_bytes (hash,
4026
0
          &pattern->filter, sizeof (pattern->filter));
4027
0
  hash = _cairo_hash_bytes (hash,
4028
0
          &pattern->extend, sizeof (pattern->extend));
4029
0
  hash = _cairo_hash_bytes (hash,
4030
0
          &pattern->has_component_alpha,
4031
0
          sizeof (pattern->has_component_alpha));
4032
0
    }
4033
4034
0
    switch (pattern->type) {
4035
0
    case CAIRO_PATTERN_TYPE_SOLID:
4036
0
  return _cairo_solid_pattern_hash (hash, (cairo_solid_pattern_t *) pattern);
4037
0
    case CAIRO_PATTERN_TYPE_LINEAR:
4038
0
  return _cairo_linear_pattern_hash (hash, (cairo_linear_pattern_t *) pattern);
4039
0
    case CAIRO_PATTERN_TYPE_RADIAL:
4040
0
  return _cairo_radial_pattern_hash (hash, (cairo_radial_pattern_t *) pattern);
4041
0
    case CAIRO_PATTERN_TYPE_MESH:
4042
0
  return _cairo_mesh_pattern_hash (hash, (cairo_mesh_pattern_t *) pattern);
4043
0
    case CAIRO_PATTERN_TYPE_SURFACE:
4044
0
  return _cairo_surface_pattern_hash (hash, (cairo_surface_pattern_t *) pattern);
4045
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4046
0
  return _cairo_raster_source_pattern_hash (hash, (cairo_raster_source_pattern_t *) pattern);
4047
0
    default:
4048
0
  ASSERT_NOT_REACHED;
4049
0
  return FALSE;
4050
0
    }
4051
0
}
4052
4053
static cairo_bool_t
4054
_cairo_solid_pattern_equal (const cairo_solid_pattern_t *a,
4055
          const cairo_solid_pattern_t *b)
4056
0
{
4057
0
    return _cairo_color_equal (&a->color, &b->color);
4058
0
}
4059
4060
static cairo_bool_t
4061
_cairo_gradient_color_stops_equal (const cairo_gradient_pattern_t *a,
4062
           const cairo_gradient_pattern_t *b)
4063
0
{
4064
0
    unsigned int n;
4065
4066
0
    if (a->n_stops != b->n_stops)
4067
0
  return FALSE;
4068
4069
0
    for (n = 0; n < a->n_stops; n++) {
4070
0
  if (a->stops[n].offset != b->stops[n].offset)
4071
0
      return FALSE;
4072
0
  if (! _cairo_color_stop_equal (&a->stops[n].color, &b->stops[n].color))
4073
0
      return FALSE;
4074
0
    }
4075
4076
0
    return TRUE;
4077
0
}
4078
4079
cairo_bool_t
4080
_cairo_linear_pattern_equal (const cairo_linear_pattern_t *a,
4081
           const cairo_linear_pattern_t *b)
4082
0
{
4083
0
    if (a->pd1.x != b->pd1.x)
4084
0
  return FALSE;
4085
4086
0
    if (a->pd1.y != b->pd1.y)
4087
0
  return FALSE;
4088
4089
0
    if (a->pd2.x != b->pd2.x)
4090
0
  return FALSE;
4091
4092
0
    if (a->pd2.y != b->pd2.y)
4093
0
  return FALSE;
4094
4095
0
    return _cairo_gradient_color_stops_equal (&a->base, &b->base);
4096
0
}
4097
4098
cairo_bool_t
4099
_cairo_radial_pattern_equal (const cairo_radial_pattern_t *a,
4100
           const cairo_radial_pattern_t *b)
4101
0
{
4102
0
    if (a->cd1.center.x != b->cd1.center.x)
4103
0
  return FALSE;
4104
4105
0
    if (a->cd1.center.y != b->cd1.center.y)
4106
0
  return FALSE;
4107
4108
0
    if (a->cd1.radius != b->cd1.radius)
4109
0
  return FALSE;
4110
4111
0
    if (a->cd2.center.x != b->cd2.center.x)
4112
0
  return FALSE;
4113
4114
0
    if (a->cd2.center.y != b->cd2.center.y)
4115
0
  return FALSE;
4116
4117
0
    if (a->cd2.radius != b->cd2.radius)
4118
0
  return FALSE;
4119
4120
0
    return _cairo_gradient_color_stops_equal (&a->base, &b->base);
4121
0
}
4122
4123
static cairo_bool_t
4124
_cairo_mesh_pattern_equal (const cairo_mesh_pattern_t *a,
4125
         const cairo_mesh_pattern_t *b)
4126
0
{
4127
0
    const cairo_mesh_patch_t *patch_a, *patch_b;
4128
0
    unsigned int i, num_patches_a, num_patches_b;
4129
4130
0
    num_patches_a = _cairo_array_num_elements (&a->patches);
4131
0
    num_patches_b = _cairo_array_num_elements (&b->patches);
4132
4133
0
    if (num_patches_a != num_patches_b)
4134
0
  return FALSE;
4135
4136
0
    for (i = 0; i < num_patches_a; i++) {
4137
0
  patch_a = _cairo_array_index_const (&a->patches, i);
4138
0
  patch_b = _cairo_array_index_const (&b->patches, i);
4139
0
  if (memcmp (patch_a, patch_b, sizeof(cairo_mesh_patch_t)) != 0)
4140
0
      return FALSE;
4141
0
    }
4142
4143
0
    return TRUE;
4144
0
}
4145
4146
static cairo_bool_t
4147
_cairo_surface_pattern_equal (const cairo_surface_pattern_t *a,
4148
            const cairo_surface_pattern_t *b)
4149
0
{
4150
0
    return a->surface->unique_id == b->surface->unique_id;
4151
0
}
4152
4153
static cairo_bool_t
4154
_cairo_raster_source_pattern_equal (const cairo_raster_source_pattern_t *a,
4155
            const cairo_raster_source_pattern_t *b)
4156
0
{
4157
0
    return a->user_data == b->user_data;
4158
0
}
4159
4160
cairo_bool_t
4161
_cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b)
4162
0
{
4163
0
    if (a->status || b->status)
4164
0
  return FALSE;
4165
4166
0
    if (a == b)
4167
0
  return TRUE;
4168
4169
0
    if (a->type != b->type)
4170
0
  return FALSE;
4171
4172
0
    if (a->has_component_alpha != b->has_component_alpha)
4173
0
  return FALSE;
4174
4175
0
    if (a->type != CAIRO_PATTERN_TYPE_SOLID) {
4176
0
  if (memcmp (&a->matrix, &b->matrix, sizeof (cairo_matrix_t)))
4177
0
      return FALSE;
4178
4179
0
  if (a->filter != b->filter)
4180
0
      return FALSE;
4181
4182
0
  if (a->extend != b->extend)
4183
0
      return FALSE;
4184
0
    }
4185
4186
0
    switch (a->type) {
4187
0
    case CAIRO_PATTERN_TYPE_SOLID:
4188
0
  return _cairo_solid_pattern_equal ((cairo_solid_pattern_t *) a,
4189
0
             (cairo_solid_pattern_t *) b);
4190
0
    case CAIRO_PATTERN_TYPE_LINEAR:
4191
0
  return _cairo_linear_pattern_equal ((cairo_linear_pattern_t *) a,
4192
0
              (cairo_linear_pattern_t *) b);
4193
0
    case CAIRO_PATTERN_TYPE_RADIAL:
4194
0
  return _cairo_radial_pattern_equal ((cairo_radial_pattern_t *) a,
4195
0
              (cairo_radial_pattern_t *) b);
4196
0
    case CAIRO_PATTERN_TYPE_MESH:
4197
0
  return _cairo_mesh_pattern_equal ((cairo_mesh_pattern_t *) a,
4198
0
            (cairo_mesh_pattern_t *) b);
4199
0
    case CAIRO_PATTERN_TYPE_SURFACE:
4200
0
  return _cairo_surface_pattern_equal ((cairo_surface_pattern_t *) a,
4201
0
               (cairo_surface_pattern_t *) b);
4202
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4203
0
  return _cairo_raster_source_pattern_equal ((cairo_raster_source_pattern_t *) a,
4204
0
               (cairo_raster_source_pattern_t *) b);
4205
0
    default:
4206
0
  ASSERT_NOT_REACHED;
4207
0
  return FALSE;
4208
0
    }
4209
0
}
4210
4211
/**
4212
 * cairo_pattern_get_rgba:
4213
 * @pattern: a #cairo_pattern_t
4214
 * @red: return value for red component of color, or %NULL
4215
 * @green: return value for green component of color, or %NULL
4216
 * @blue: return value for blue component of color, or %NULL
4217
 * @alpha: return value for alpha component of color, or %NULL
4218
 *
4219
 * Gets the solid color for a solid color pattern.
4220
 *
4221
 * Note that the color and alpha values are not premultiplied.
4222
 *
4223
 * Return value: %CAIRO_STATUS_SUCCESS, or
4224
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid
4225
 * color pattern.
4226
 *
4227
 * Since: 1.4
4228
 **/
4229
cairo_status_t
4230
cairo_pattern_get_rgba (cairo_pattern_t *pattern,
4231
      double *red, double *green,
4232
      double *blue, double *alpha)
4233
0
{
4234
0
    cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
4235
0
    double r0, g0, b0, a0;
4236
4237
0
    if (pattern->status)
4238
0
  return pattern->status;
4239
4240
0
    if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
4241
0
  return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4242
4243
0
    _cairo_color_get_rgba (&solid->color, &r0, &g0, &b0, &a0);
4244
4245
0
    if (red)
4246
0
  *red = r0;
4247
0
    if (green)
4248
0
  *green = g0;
4249
0
    if (blue)
4250
0
  *blue = b0;
4251
0
    if (alpha)
4252
0
  *alpha = a0;
4253
4254
0
    return CAIRO_STATUS_SUCCESS;
4255
0
}
4256
4257
/**
4258
 * cairo_pattern_get_surface:
4259
 * @pattern: a #cairo_pattern_t
4260
 * @surface: return value for surface of pattern, or %NULL
4261
 *
4262
 * Gets the surface of a surface pattern.  The reference returned in
4263
 * @surface is owned by the pattern; the caller should call
4264
 * cairo_surface_reference() if the surface is to be retained.
4265
 *
4266
 * Return value: %CAIRO_STATUS_SUCCESS, or
4267
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a surface
4268
 * pattern.
4269
 *
4270
 * Since: 1.4
4271
 **/
4272
cairo_status_t
4273
cairo_pattern_get_surface (cairo_pattern_t *pattern,
4274
         cairo_surface_t **surface)
4275
0
{
4276
0
    cairo_surface_pattern_t *spat = (cairo_surface_pattern_t*) pattern;
4277
4278
0
    if (pattern->status)
4279
0
  return pattern->status;
4280
4281
0
    if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
4282
0
  return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4283
4284
0
    if (surface)
4285
0
  *surface = spat->surface;
4286
4287
0
    return CAIRO_STATUS_SUCCESS;
4288
0
}
4289
4290
/**
4291
 * cairo_pattern_get_color_stop_rgba:
4292
 * @pattern: a #cairo_pattern_t
4293
 * @index: index of the stop to return data for
4294
 * @offset: return value for the offset of the stop, or %NULL
4295
 * @red: return value for red component of color, or %NULL
4296
 * @green: return value for green component of color, or %NULL
4297
 * @blue: return value for blue component of color, or %NULL
4298
 * @alpha: return value for alpha component of color, or %NULL
4299
 *
4300
 * Gets the color and offset information at the given @index for a
4301
 * gradient pattern.  Values of @index range from 0 to n-1
4302
 * where n is the number returned
4303
 * by cairo_pattern_get_color_stop_count().
4304
 *
4305
 * Note that the color and alpha values are not premultiplied.
4306
 *
4307
 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
4308
 * if @index is not valid for the given pattern.  If the pattern is
4309
 * not a gradient pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
4310
 * returned.
4311
 *
4312
 * Since: 1.4
4313
 **/
4314
cairo_status_t
4315
cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
4316
           int index, double *offset,
4317
           double *red, double *green,
4318
           double *blue, double *alpha)
4319
0
{
4320
0
    cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
4321
4322
0
    if (pattern->status)
4323
0
  return pattern->status;
4324
4325
0
    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
4326
0
  pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
4327
0
  return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4328
4329
0
    if (index < 0 || (unsigned int) index >= gradient->n_stops)
4330
0
  return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4331
4332
0
    if (offset)
4333
0
  *offset = gradient->stops[index].offset;
4334
0
    if (red)
4335
0
  *red = gradient->stops[index].color.red;
4336
0
    if (green)
4337
0
  *green = gradient->stops[index].color.green;
4338
0
    if (blue)
4339
0
  *blue = gradient->stops[index].color.blue;
4340
0
    if (alpha)
4341
0
  *alpha = gradient->stops[index].color.alpha;
4342
4343
0
    return CAIRO_STATUS_SUCCESS;
4344
0
}
4345
4346
/**
4347
 * cairo_pattern_get_color_stop_count:
4348
 * @pattern: a #cairo_pattern_t
4349
 * @count: return value for the number of color stops, or %NULL
4350
 *
4351
 * Gets the number of color stops specified in the given gradient
4352
 * pattern.
4353
 *
4354
 * Return value: %CAIRO_STATUS_SUCCESS, or
4355
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
4356
 * pattern.
4357
 *
4358
 * Since: 1.4
4359
 **/
4360
cairo_status_t
4361
cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
4362
            int *count)
4363
0
{
4364
0
    cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
4365
4366
0
    if (pattern->status)
4367
0
  return pattern->status;
4368
4369
0
    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
4370
0
  pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
4371
0
  return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4372
4373
0
    if (count)
4374
0
  *count = gradient->n_stops;
4375
4376
0
    return CAIRO_STATUS_SUCCESS;
4377
0
}
4378
4379
/**
4380
 * cairo_pattern_get_linear_points:
4381
 * @pattern: a #cairo_pattern_t
4382
 * @x0: return value for the x coordinate of the first point, or %NULL
4383
 * @y0: return value for the y coordinate of the first point, or %NULL
4384
 * @x1: return value for the x coordinate of the second point, or %NULL
4385
 * @y1: return value for the y coordinate of the second point, or %NULL
4386
 *
4387
 * Gets the gradient endpoints for a linear gradient.
4388
 *
4389
 * Return value: %CAIRO_STATUS_SUCCESS, or
4390
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a linear
4391
 * gradient pattern.
4392
 *
4393
 * Since: 1.4
4394
 **/
4395
cairo_status_t
4396
cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
4397
         double *x0, double *y0,
4398
         double *x1, double *y1)
4399
0
{
4400
0
    cairo_linear_pattern_t *linear = (cairo_linear_pattern_t*) pattern;
4401
4402
0
    if (pattern->status)
4403
0
  return pattern->status;
4404
4405
0
    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR)
4406
0
  return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4407
4408
0
    if (x0)
4409
0
  *x0 = linear->pd1.x;
4410
0
    if (y0)
4411
0
  *y0 = linear->pd1.y;
4412
0
    if (x1)
4413
0
  *x1 = linear->pd2.x;
4414
0
    if (y1)
4415
0
  *y1 = linear->pd2.y;
4416
4417
0
    return CAIRO_STATUS_SUCCESS;
4418
0
}
4419
4420
/**
4421
 * cairo_pattern_get_radial_circles:
4422
 * @pattern: a #cairo_pattern_t
4423
 * @x0: return value for the x coordinate of the center of the first circle, or %NULL
4424
 * @y0: return value for the y coordinate of the center of the first circle, or %NULL
4425
 * @r0: return value for the radius of the first circle, or %NULL
4426
 * @x1: return value for the x coordinate of the center of the second circle, or %NULL
4427
 * @y1: return value for the y coordinate of the center of the second circle, or %NULL
4428
 * @r1: return value for the radius of the second circle, or %NULL
4429
 *
4430
 * Gets the gradient endpoint circles for a radial gradient, each
4431
 * specified as a center coordinate and a radius.
4432
 *
4433
 * Return value: %CAIRO_STATUS_SUCCESS, or
4434
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial
4435
 * gradient pattern.
4436
 *
4437
 * Since: 1.4
4438
 **/
4439
cairo_status_t
4440
cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
4441
          double *x0, double *y0, double *r0,
4442
          double *x1, double *y1, double *r1)
4443
0
{
4444
0
    cairo_radial_pattern_t *radial = (cairo_radial_pattern_t*) pattern;
4445
4446
0
    if (pattern->status)
4447
0
  return pattern->status;
4448
4449
0
    if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
4450
0
  return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4451
4452
0
    if (x0)
4453
0
  *x0 = radial->cd1.center.x;
4454
0
    if (y0)
4455
0
  *y0 = radial->cd1.center.y;
4456
0
    if (r0)
4457
0
  *r0 = radial->cd1.radius;
4458
0
    if (x1)
4459
0
  *x1 = radial->cd2.center.x;
4460
0
    if (y1)
4461
0
  *y1 = radial->cd2.center.y;
4462
0
    if (r1)
4463
0
  *r1 = radial->cd2.radius;
4464
4465
0
    return CAIRO_STATUS_SUCCESS;
4466
0
}
4467
4468
/**
4469
 * cairo_mesh_pattern_get_patch_count:
4470
 * @pattern: a #cairo_pattern_t
4471
 * @count: return value for the number patches, or %NULL
4472
 *
4473
 * Gets the number of patches specified in the given mesh pattern.
4474
 *
4475
 * The number only includes patches which have been finished by
4476
 * calling cairo_mesh_pattern_end_patch(). For example it will be 0
4477
 * during the definition of the first patch.
4478
 *
4479
 * Return value: %CAIRO_STATUS_SUCCESS, or
4480
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a mesh
4481
 * pattern.
4482
 *
4483
 * Since: 1.12
4484
 **/
4485
cairo_status_t
4486
cairo_mesh_pattern_get_patch_count (cairo_pattern_t *pattern,
4487
            unsigned int *count)
4488
0
{
4489
0
    cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
4490
4491
0
    if (unlikely (pattern->status))
4492
0
  return pattern->status;
4493
4494
0
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH))
4495
0
  return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4496
4497
0
    if (count) {
4498
0
  *count = _cairo_array_num_elements (&mesh->patches);
4499
0
  if (mesh->current_patch)
4500
0
      *count -= 1;
4501
0
    }
4502
4503
0
    return CAIRO_STATUS_SUCCESS;
4504
0
}
4505
4506
/**
4507
 * cairo_mesh_pattern_get_path:
4508
 * @pattern: a #cairo_pattern_t
4509
 * @patch_num: the patch number to return data for
4510
 *
4511
 * Gets path defining the patch @patch_num for a mesh
4512
 * pattern.
4513
 *
4514
 * @patch_num can range from 0 to n-1 where n is the number returned by
4515
 * cairo_mesh_pattern_get_patch_count().
4516
 *
4517
 * Return value: the path defining the patch, or a path with status
4518
 * %CAIRO_STATUS_INVALID_INDEX if @patch_num or @point_num is not
4519
 * valid for @pattern. If @pattern is not a mesh pattern, a path with
4520
 * status %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is returned.
4521
 *
4522
 * Since: 1.12
4523
 **/
4524
cairo_path_t *
4525
cairo_mesh_pattern_get_path (cairo_pattern_t *pattern,
4526
           unsigned int patch_num)
4527
0
{
4528
0
    cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
4529
0
    const cairo_mesh_patch_t *patch;
4530
0
    cairo_path_t *path;
4531
0
    cairo_path_data_t *data;
4532
0
    unsigned int patch_count;
4533
0
    int l, current_point;
4534
4535
0
    if (unlikely (pattern->status))
4536
0
  return _cairo_path_create_in_error (pattern->status);
4537
4538
0
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH))
4539
0
  return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH));
4540
4541
0
    patch_count = _cairo_array_num_elements (&mesh->patches);
4542
0
    if (mesh->current_patch)
4543
0
  patch_count--;
4544
4545
0
    if (unlikely (patch_num >= patch_count))
4546
0
  return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_INDEX));
4547
4548
0
    patch = _cairo_array_index_const (&mesh->patches, patch_num);
4549
4550
0
    path = _cairo_calloc (sizeof (cairo_path_t));
4551
0
    if (path == NULL)
4552
0
  return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
4553
4554
0
    path->num_data = 18;
4555
0
    path->data = _cairo_calloc_ab (path->num_data,
4556
0
           sizeof (cairo_path_data_t));
4557
0
    if (path->data == NULL) {
4558
0
  free (path);
4559
0
  return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
4560
0
    }
4561
4562
0
    data = path->data;
4563
0
    data[0].header.type = CAIRO_PATH_MOVE_TO;
4564
0
    data[0].header.length = 2;
4565
0
    data[1].point.x = patch->points[0][0].x;
4566
0
    data[1].point.y = patch->points[0][0].y;
4567
0
    data += data[0].header.length;
4568
4569
0
    current_point = 0;
4570
4571
0
    for (l = 0; l < 4; l++) {
4572
0
  int i, j, k;
4573
4574
0
  data[0].header.type = CAIRO_PATH_CURVE_TO;
4575
0
  data[0].header.length = 4;
4576
4577
0
  for (k = 1; k < 4; k++) {
4578
0
      current_point = (current_point + 1) % 12;
4579
0
      i = mesh_path_point_i[current_point];
4580
0
      j = mesh_path_point_j[current_point];
4581
0
      data[k].point.x = patch->points[i][j].x;
4582
0
      data[k].point.y = patch->points[i][j].y;
4583
0
  }
4584
4585
0
  data += data[0].header.length;
4586
0
    }
4587
4588
0
    path->status = CAIRO_STATUS_SUCCESS;
4589
4590
0
    return path;
4591
0
}
4592
4593
/**
4594
 * cairo_mesh_pattern_get_corner_color_rgba:
4595
 * @pattern: a #cairo_pattern_t
4596
 * @patch_num: the patch number to return data for
4597
 * @corner_num: the corner number to return data for
4598
 * @red: return value for red component of color, or %NULL
4599
 * @green: return value for green component of color, or %NULL
4600
 * @blue: return value for blue component of color, or %NULL
4601
 * @alpha: return value for alpha component of color, or %NULL
4602
 *
4603
 * Gets the color information in corner @corner_num of patch
4604
 * @patch_num for a mesh pattern.
4605
 *
4606
 * @patch_num can range from 0 to n-1 where n is the number returned by
4607
 * cairo_mesh_pattern_get_patch_count().
4608
 *
4609
 * Valid values for @corner_num are from 0 to 3 and identify the
4610
 * corners as explained in cairo_pattern_create_mesh().
4611
 *
4612
 * Note that the color and alpha values are not premultiplied.
4613
 *
4614
 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
4615
 * if @patch_num or @corner_num is not valid for @pattern. If
4616
 * @pattern is not a mesh pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH
4617
 * is returned.
4618
 *
4619
 * Since: 1.12
4620
 **/
4621
cairo_status_t
4622
cairo_mesh_pattern_get_corner_color_rgba (cairo_pattern_t *pattern,
4623
            unsigned int patch_num,
4624
            unsigned int corner_num,
4625
            double *red, double *green,
4626
            double *blue, double *alpha)
4627
0
{
4628
0
    cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
4629
0
    unsigned int patch_count;
4630
0
    const cairo_mesh_patch_t *patch;
4631
4632
0
    if (unlikely (pattern->status))
4633
0
  return pattern->status;
4634
4635
0
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH))
4636
0
  return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4637
4638
0
    if (unlikely (corner_num > 3))
4639
0
  return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4640
4641
0
    patch_count = _cairo_array_num_elements (&mesh->patches);
4642
0
    if (mesh->current_patch)
4643
0
  patch_count--;
4644
4645
0
    if (unlikely (patch_num >= patch_count))
4646
0
  return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4647
4648
0
    patch = _cairo_array_index_const (&mesh->patches, patch_num);
4649
4650
0
    if (red)
4651
0
  *red = patch->colors[corner_num].red;
4652
0
    if (green)
4653
0
  *green = patch->colors[corner_num].green;
4654
0
    if (blue)
4655
0
  *blue = patch->colors[corner_num].blue;
4656
0
    if (alpha)
4657
0
  *alpha = patch->colors[corner_num].alpha;
4658
4659
0
    return CAIRO_STATUS_SUCCESS;
4660
0
}
4661
4662
/**
4663
 * cairo_mesh_pattern_get_control_point:
4664
 * @pattern: a #cairo_pattern_t
4665
 * @patch_num: the patch number to return data for
4666
 * @point_num: the control point number to return data for
4667
 * @x: return value for the x coordinate of the control point, or %NULL
4668
 * @y: return value for the y coordinate of the control point, or %NULL
4669
 *
4670
 * Gets the control point @point_num of patch @patch_num for a mesh
4671
 * pattern.
4672
 *
4673
 * @patch_num can range from 0 to n-1 where n is the number returned by
4674
 * cairo_mesh_pattern_get_patch_count().
4675
 *
4676
 * Valid values for @point_num are from 0 to 3 and identify the
4677
 * control points as explained in cairo_pattern_create_mesh().
4678
 *
4679
 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
4680
 * if @patch_num or @point_num is not valid for @pattern. If @pattern
4681
 * is not a mesh pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
4682
 * returned.
4683
 *
4684
 * Since: 1.12
4685
 **/
4686
cairo_status_t
4687
cairo_mesh_pattern_get_control_point (cairo_pattern_t *pattern,
4688
              unsigned int patch_num,
4689
              unsigned int point_num,
4690
              double *x, double *y)
4691
0
{
4692
0
    cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
4693
0
    const cairo_mesh_patch_t *patch;
4694
0
    unsigned int patch_count;
4695
0
    int i, j;
4696
4697
0
    if (pattern->status)
4698
0
  return pattern->status;
4699
4700
0
    if (pattern->type != CAIRO_PATTERN_TYPE_MESH)
4701
0
  return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4702
4703
0
    if (point_num > 3)
4704
0
  return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4705
4706
0
    patch_count = _cairo_array_num_elements (&mesh->patches);
4707
0
    if (mesh->current_patch)
4708
0
  patch_count--;
4709
4710
0
    if (unlikely (patch_num >= patch_count))
4711
0
  return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4712
4713
0
    patch = _cairo_array_index_const (&mesh->patches, patch_num);
4714
4715
0
    i = mesh_control_point_i[point_num];
4716
0
    j = mesh_control_point_j[point_num];
4717
4718
0
    if (x)
4719
0
  *x = patch->points[i][j].x;
4720
0
    if (y)
4721
0
  *y = patch->points[i][j].y;
4722
4723
0
    return CAIRO_STATUS_SUCCESS;
4724
0
}
4725
4726
void
4727
_cairo_pattern_reset_static_data (void)
4728
0
{
4729
0
    int i;
4730
4731
0
    for (i = 0; i < ARRAY_LENGTH (freed_pattern_pool); i++)
4732
0
  _freed_pool_reset (&freed_pattern_pool[i]);
4733
0
}
4734
4735
static void
4736
_cairo_debug_print_surface_pattern (FILE *file,
4737
            const cairo_surface_pattern_t *pattern)
4738
0
{
4739
0
    const char *s;
4740
0
    switch (pattern->surface->type) {
4741
0
    case CAIRO_SURFACE_TYPE_IMAGE: s = "image"; break;
4742
0
    case CAIRO_SURFACE_TYPE_PDF: s = "pdf"; break;
4743
0
    case CAIRO_SURFACE_TYPE_PS: s = "ps"; break;
4744
0
    case CAIRO_SURFACE_TYPE_XLIB: s = "xlib"; break;
4745
0
    case CAIRO_SURFACE_TYPE_XCB: s = "xcb"; break;
4746
0
    case CAIRO_SURFACE_TYPE_GLITZ: s = "glitz"; break;
4747
0
    case CAIRO_SURFACE_TYPE_QUARTZ: s = "quartz"; break;
4748
0
    case CAIRO_SURFACE_TYPE_WIN32: s = "win32"; break;
4749
0
    case CAIRO_SURFACE_TYPE_BEOS: s = "beos"; break;
4750
0
    case CAIRO_SURFACE_TYPE_DIRECTFB: s = "directfb"; break;
4751
0
    case CAIRO_SURFACE_TYPE_SVG: s = "svg"; break;
4752
0
    case CAIRO_SURFACE_TYPE_OS2: s = "os2"; break;
4753
0
    case CAIRO_SURFACE_TYPE_WIN32_PRINTING: s = "win32_printing"; break;
4754
0
    case CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: s = "quartz_image"; break;
4755
0
    case CAIRO_SURFACE_TYPE_SCRIPT: s = "script"; break;
4756
0
    case CAIRO_SURFACE_TYPE_QT: s = "qt"; break;
4757
0
    case CAIRO_SURFACE_TYPE_RECORDING: s = "recording"; break;
4758
0
    case CAIRO_SURFACE_TYPE_VG: s = "vg"; break;
4759
0
    case CAIRO_SURFACE_TYPE_GL: s = "gl"; break;
4760
0
    case CAIRO_SURFACE_TYPE_DRM: s = "drm"; break;
4761
0
    case CAIRO_SURFACE_TYPE_TEE: s = "tee"; break;
4762
0
    case CAIRO_SURFACE_TYPE_XML: s = "xml"; break;
4763
0
    case CAIRO_SURFACE_TYPE_SKIA: s = "skia"; break; /* Deprecated */
4764
0
    case CAIRO_SURFACE_TYPE_SUBSURFACE: s = "subsurface"; break;
4765
0
    case CAIRO_SURFACE_TYPE_COGL: s = "cogl"; break;
4766
0
    default: s = "invalid"; ASSERT_NOT_REACHED; break;
4767
0
    }
4768
0
    fprintf (file, "  surface type: %s\n", s);
4769
0
}
4770
4771
static void
4772
_cairo_debug_print_raster_source_pattern (FILE *file,
4773
            const cairo_raster_source_pattern_t *raster)
4774
0
{
4775
0
    fprintf (file, "  content: %x, size %dx%d\n", raster->content, raster->extents.width, raster->extents.height);
4776
0
}
4777
4778
static void
4779
_cairo_debug_print_linear_pattern (FILE *file,
4780
            const cairo_linear_pattern_t *pattern)
4781
0
{
4782
0
}
4783
4784
static void
4785
_cairo_debug_print_radial_pattern (FILE *file,
4786
           const cairo_radial_pattern_t *pattern)
4787
0
{
4788
0
}
4789
4790
static void
4791
_cairo_debug_print_mesh_pattern (FILE *file,
4792
         const cairo_mesh_pattern_t *pattern)
4793
0
{
4794
0
}
4795
4796
void
4797
_cairo_debug_print_pattern (FILE *file, const cairo_pattern_t *pattern)
4798
0
{
4799
0
    const char *s;
4800
0
    switch (pattern->type) {
4801
0
    case CAIRO_PATTERN_TYPE_SOLID: s = "solid"; break;
4802
0
    case CAIRO_PATTERN_TYPE_SURFACE: s = "surface"; break;
4803
0
    case CAIRO_PATTERN_TYPE_LINEAR: s = "linear"; break;
4804
0
    case CAIRO_PATTERN_TYPE_RADIAL: s = "radial"; break;
4805
0
    case CAIRO_PATTERN_TYPE_MESH: s = "mesh"; break;
4806
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE: s = "raster"; break;
4807
0
    default: s = "invalid"; ASSERT_NOT_REACHED; break;
4808
0
    }
4809
4810
0
    fprintf (file, "pattern: %s\n", s);
4811
0
    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
4812
0
  return;
4813
4814
0
    switch (pattern->extend) {
4815
0
    case CAIRO_EXTEND_NONE: s = "none"; break;
4816
0
    case CAIRO_EXTEND_REPEAT: s = "repeat"; break;
4817
0
    case CAIRO_EXTEND_REFLECT: s = "reflect"; break;
4818
0
    case CAIRO_EXTEND_PAD: s = "pad"; break;
4819
0
    default: s = "invalid"; ASSERT_NOT_REACHED; break;
4820
0
    }
4821
0
    fprintf (file, "  extend: %s\n", s);
4822
4823
0
    switch (pattern->filter) {
4824
0
    case CAIRO_FILTER_FAST: s = "fast"; break;
4825
0
    case CAIRO_FILTER_GOOD: s = "good"; break;
4826
0
    case CAIRO_FILTER_BEST: s = "best"; break;
4827
0
    case CAIRO_FILTER_NEAREST: s = "nearest"; break;
4828
0
    case CAIRO_FILTER_BILINEAR: s = "bilinear"; break;
4829
0
    case CAIRO_FILTER_GAUSSIAN: s = "gaussian"; break;
4830
0
    default: s = "invalid"; ASSERT_NOT_REACHED; break;
4831
0
    }
4832
0
    fprintf (file, "  filter: %s\n", s);
4833
0
    fprintf (file, "  matrix: [%g %g %g %g %g %g]\n",
4834
0
       pattern->matrix.xx, pattern->matrix.yx,
4835
0
       pattern->matrix.xy, pattern->matrix.yy,
4836
0
       pattern->matrix.x0, pattern->matrix.y0);
4837
0
    switch (pattern->type) {
4838
0
    default:
4839
0
    case CAIRO_PATTERN_TYPE_SOLID:
4840
0
  break;
4841
0
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4842
0
  _cairo_debug_print_raster_source_pattern (file, (cairo_raster_source_pattern_t *)pattern);
4843
0
  break;
4844
0
    case CAIRO_PATTERN_TYPE_SURFACE:
4845
0
  _cairo_debug_print_surface_pattern (file, (cairo_surface_pattern_t *)pattern);
4846
0
  break;
4847
0
    case CAIRO_PATTERN_TYPE_LINEAR:
4848
0
  _cairo_debug_print_linear_pattern (file, (cairo_linear_pattern_t *)pattern);
4849
0
  break;
4850
0
    case CAIRO_PATTERN_TYPE_RADIAL:
4851
0
  _cairo_debug_print_radial_pattern (file, (cairo_radial_pattern_t *)pattern);
4852
0
  break;
4853
0
    case CAIRO_PATTERN_TYPE_MESH:
4854
0
  _cairo_debug_print_mesh_pattern (file, (cairo_mesh_pattern_t *)pattern);
4855
0
  break;
4856
0
    }
4857
0
}