Coverage Report

Created: 2025-07-07 10:01

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