1
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2
/* cairo - a vector graphics library with display and print output
3
 *
4
 * Copyright © 2004 David Reveman
5
 * Copyright © 2005 Red Hat, Inc.
6
 *
7
 * Permission to use, copy, modify, distribute, and sell this software
8
 * and its documentation for any purpose is hereby granted without
9
 * fee, provided that the above copyright notice appear in all copies
10
 * and that both that copyright notice and this permission notice
11
 * appear in supporting documentation, and that the name of David
12
 * Reveman not be used in advertising or publicity pertaining to
13
 * distribution of the software without specific, written prior
14
 * permission. David Reveman makes no representations about the
15
 * suitability of this software for any purpose.  It is provided "as
16
 * is" without express or implied warranty.
17
 *
18
 * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
19
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
20
 * FITNESS, IN NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL,
21
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
22
 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
23
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
24
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25
 *
26
 * Authors: David Reveman <davidr@novell.com>
27
 *	    Keith Packard <keithp@keithp.com>
28
 *	    Carl Worth <cworth@cworth.org>
29
 */
30

            
31
#include "cairoint.h"
32

            
33
#include "cairo-array-private.h"
34
#include "cairo-error-private.h"
35
#include "cairo-freed-pool-private.h"
36
#include "cairo-image-surface-private.h"
37
#include "cairo-list-inline.h"
38
#include "cairo-path-private.h"
39
#include "cairo-pattern-private.h"
40
#include "cairo-recording-surface-inline.h"
41
#include "cairo-surface-snapshot-inline.h"
42

            
43
#include <float.h>
44

            
45
#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
46

            
47
/**
48
 * SECTION:cairo-pattern
49
 * @Title: cairo_pattern_t
50
 * @Short_Description: Sources for drawing
51
 * @See_Also: #cairo_t, #cairo_surface_t
52
 *
53
 * #cairo_pattern_t is the paint with which cairo draws.
54
 * The primary use of patterns is as the source for all cairo drawing
55
 * operations, although they can also be used as masks, that is, as the
56
 * brush too.
57
 *
58
 * A cairo pattern is created by using one of the many constructors,
59
 * of the form
60
 * <function>cairo_pattern_create_<emphasis>type</emphasis>()</function>
61
 * or implicitly through
62
 * <function>cairo_set_source_<emphasis>type</emphasis>()</function>
63
 * functions.
64
 **/
65

            
66
/**
67
 * CAIRO_HAS_MIME_SURFACE:
68
 *
69
 * Unused symbol, always defined.
70
 *
71
 * Since: 1.12
72
 **/
73

            
74
static freed_pool_t freed_pattern_pool[5];
75

            
76
static const cairo_solid_pattern_t _cairo_pattern_nil = {
77
    {
78
      CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
79
      CAIRO_STATUS_NO_MEMORY,		/* status */
80
      { 0, 0, 0, NULL },		/* user_data */
81
      { NULL, NULL },			/* observers */
82

            
83
      CAIRO_PATTERN_TYPE_SOLID,		/* type */
84
      CAIRO_FILTER_DEFAULT,		/* filter */
85
      CAIRO_EXTEND_GRADIENT_DEFAULT,	/* extend */
86
      FALSE,				/* has component alpha */
87
      FALSE,				/* is_foreground_marker */
88
      CAIRO_DITHER_DEFAULT,		/* dither */
89
      { 1., 0., 0., 1., 0., 0., },	/* matrix */
90
      1.0                               /* opacity */
91
    }
92
};
93

            
94
static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = {
95
    {
96
      CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
97
      CAIRO_STATUS_NULL_POINTER,	/* status */
98
      { 0, 0, 0, NULL },		/* user_data */
99
      { NULL, NULL },			/* observers */
100

            
101
      CAIRO_PATTERN_TYPE_SOLID,		/* type */
102
      CAIRO_FILTER_DEFAULT,		/* filter */
103
      CAIRO_EXTEND_GRADIENT_DEFAULT,	/* extend */
104
      FALSE,				/* has component alpha */
105
      FALSE,				/* is_foreground_marker */
106
      CAIRO_DITHER_DEFAULT,		/* dither */
107
      { 1., 0., 0., 1., 0., 0., },	/* matrix */
108
      1.0                               /* opacity */
109
    }
110
};
111

            
112
const cairo_solid_pattern_t _cairo_pattern_black = {
113
    {
114
      CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
115
      CAIRO_STATUS_SUCCESS,		/* status */
116
      { 0, 0, 0, NULL },		/* user_data */
117
      { NULL, NULL },			/* observers */
118

            
119
      CAIRO_PATTERN_TYPE_SOLID,		/* type */
120
      CAIRO_FILTER_NEAREST,		/* filter */
121
      CAIRO_EXTEND_REPEAT,		/* extend */
122
      FALSE,				/* has component alpha */
123
      FALSE,				/* is_foreground_marker */
124
      CAIRO_DITHER_DEFAULT,		/* dither */
125
      { 1., 0., 0., 1., 0., 0., },	/* matrix */
126
      1.0                               /* opacity */
127
    },
128
    { 0., 0., 0., 1., 0, 0, 0, 0xffff },/* color (double rgba, short rgba) */
129
};
130

            
131
const cairo_solid_pattern_t _cairo_pattern_clear = {
132
    {
133
      CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
134
      CAIRO_STATUS_SUCCESS,		/* status */
135
      { 0, 0, 0, NULL },		/* user_data */
136
      { NULL, NULL },			/* observers */
137

            
138
      CAIRO_PATTERN_TYPE_SOLID,		/* type */
139
      CAIRO_FILTER_NEAREST,		/* filter */
140
      CAIRO_EXTEND_REPEAT,		/* extend */
141
      FALSE,				/* has component alpha */
142
      FALSE,				/* is_foreground_marker */
143
      CAIRO_DITHER_DEFAULT,		/* dither */
144
      { 1., 0., 0., 1., 0., 0., },	/* matrix */
145
      1.0                               /* opacity */
146
    },
147
    { 0., 0., 0., 0., 0, 0, 0, 0 },/* color (double rgba, short rgba) */
148
};
149

            
150
const cairo_solid_pattern_t _cairo_pattern_white = {
151
    {
152
      CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
153
      CAIRO_STATUS_SUCCESS,		/* status */
154
      { 0, 0, 0, NULL },		/* user_data */
155
      { NULL, NULL },			/* observers */
156

            
157
      CAIRO_PATTERN_TYPE_SOLID,		/* type */
158
      CAIRO_FILTER_NEAREST,		/* filter */
159
      CAIRO_EXTEND_REPEAT,		/* extend */
160
      FALSE,				/* has component alpha */
161
      FALSE,				/* is_foreground_marker */
162
      CAIRO_DITHER_DEFAULT,		/* dither */
163
      { 1., 0., 0., 1., 0., 0., },	/* matrix */
164
      1.0                               /* opacity */
165
    },
166
    { 1., 1., 1., 1., 0xffff, 0xffff, 0xffff, 0xffff },/* color (double rgba, short rgba) */
167
};
168

            
169
static void
170
9400
_cairo_pattern_notify_observers (cairo_pattern_t *pattern,
171
				 unsigned int flags)
172
{
173
    cairo_pattern_observer_t *pos;
174

            
175
9400
    cairo_list_foreach_entry (pos, cairo_pattern_observer_t, &pattern->observers, link)
176
	pos->notify (pos, pattern, flags);
177
9400
}
178

            
179
/**
180
 * _cairo_pattern_set_error:
181
 * @pattern: a pattern
182
 * @status: a status value indicating an error
183
 *
184
 * Atomically sets pattern->status to @status and calls _cairo_error;
185
 * Does nothing if status is %CAIRO_STATUS_SUCCESS.
186
 *
187
 * All assignments of an error status to pattern->status should happen
188
 * through _cairo_pattern_set_error(). Note that due to the nature of
189
 * the atomic operation, it is not safe to call this function on the nil
190
 * objects.
191
 *
192
 * The purpose of this function is to allow the user to set a
193
 * breakpoint in _cairo_error() to generate a stack trace for when the
194
 * user causes cairo to detect an error.
195
 **/
196
static cairo_status_t
197
43
_cairo_pattern_set_error (cairo_pattern_t *pattern,
198
			  cairo_status_t status)
199
{
200
43
    if (status == CAIRO_STATUS_SUCCESS)
201
	return status;
202

            
203
    /* Don't overwrite an existing error. This preserves the first
204
     * error, which is the most significant. */
205
43
    _cairo_status_set_error (&pattern->status, status);
206

            
207
43
    return _cairo_error (status);
208
}
209

            
210
void
211
134403
_cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
212
{
213
#if HAVE_VALGRIND
214
    switch (type) {
215
    case CAIRO_PATTERN_TYPE_SOLID:
216
	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t));
217
	break;
218
    case CAIRO_PATTERN_TYPE_SURFACE:
219
	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t));
220
	break;
221
    case CAIRO_PATTERN_TYPE_LINEAR:
222
	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t));
223
	break;
224
    case CAIRO_PATTERN_TYPE_RADIAL:
225
	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t));
226
	break;
227
    case CAIRO_PATTERN_TYPE_MESH:
228
	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t));
229
	break;
230
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
231
	break;
232
    }
233
#endif
234

            
235
134403
    pattern->type      = type;
236
134403
    pattern->status    = CAIRO_STATUS_SUCCESS;
237

            
238
    /* Set the reference count to zero for on-stack patterns.
239
     * Callers needs to explicitly increment the count for heap allocations. */
240
134403
    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
241

            
242
134403
    _cairo_user_data_array_init (&pattern->user_data);
243

            
244
134403
    if (type == CAIRO_PATTERN_TYPE_SURFACE ||
245
	type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
246
7213
	pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
247
    else
248
127190
	pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT;
249

            
250
134403
    pattern->filter    = CAIRO_FILTER_DEFAULT;
251
134403
    pattern->opacity   = 1.0;
252

            
253
134403
    pattern->has_component_alpha = FALSE;
254
134403
    pattern->is_foreground_marker = FALSE;
255

            
256
134403
    pattern->dither    = CAIRO_DITHER_DEFAULT;
257

            
258
134403
    cairo_matrix_init_identity (&pattern->matrix);
259

            
260
134403
    cairo_list_init (&pattern->observers);
261
134403
}
262

            
263
static cairo_status_t
264
153
_cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t	  *pattern,
265
				   const cairo_gradient_pattern_t *other)
266
{
267
    if (CAIRO_INJECT_FAULT ())
268
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
269

            
270
153
    if (other->base.type == CAIRO_PATTERN_TYPE_LINEAR)
271
    {
272
120
	cairo_linear_pattern_t *dst = (cairo_linear_pattern_t *) pattern;
273
120
	cairo_linear_pattern_t *src = (cairo_linear_pattern_t *) other;
274

            
275
120
	*dst = *src;
276
    }
277
    else
278
    {
279
33
	cairo_radial_pattern_t *dst = (cairo_radial_pattern_t *) pattern;
280
33
	cairo_radial_pattern_t *src = (cairo_radial_pattern_t *) other;
281

            
282
33
	*dst = *src;
283
    }
284

            
285
153
    if (other->stops == other->stops_embedded)
286
	pattern->stops = pattern->stops_embedded;
287
153
    else if (other->stops)
288
    {
289
153
	pattern->stops = _cairo_malloc_ab (other->stops_size,
290
					   sizeof (cairo_gradient_stop_t));
291
153
	if (unlikely (pattern->stops == NULL)) {
292
	    pattern->stops_size = 0;
293
	    pattern->n_stops = 0;
294
	    return _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
295
	}
296

            
297
153
	memcpy (pattern->stops, other->stops,
298
153
		other->n_stops * sizeof (cairo_gradient_stop_t));
299
    }
300

            
301
153
    return CAIRO_STATUS_SUCCESS;
302
}
303

            
304
static cairo_status_t
305
3
_cairo_mesh_pattern_init_copy (cairo_mesh_pattern_t       *pattern,
306
			       const cairo_mesh_pattern_t *other)
307
{
308
3
    *pattern = *other;
309

            
310
3
    _cairo_array_init (&pattern->patches,  sizeof (cairo_mesh_patch_t));
311
3
    return _cairo_array_append_multiple (&pattern->patches,
312
					 _cairo_array_index_const (&other->patches, 0),
313
					 _cairo_array_num_elements (&other->patches));
314
}
315

            
316
cairo_status_t
317
3144
_cairo_pattern_init_copy (cairo_pattern_t	*pattern,
318
			  const cairo_pattern_t *other)
319
{
320
    cairo_status_t status;
321

            
322
3144
    if (other->status)
323
	return _cairo_pattern_set_error (pattern, other->status);
324

            
325
3144
    switch (other->type) {
326
2537
    case CAIRO_PATTERN_TYPE_SOLID: {
327
2537
	cairo_solid_pattern_t *dst = (cairo_solid_pattern_t *) pattern;
328
2537
	cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) other;
329

            
330
	VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t)));
331

            
332
2537
	*dst = *src;
333
2537
    } break;
334
451
    case CAIRO_PATTERN_TYPE_SURFACE: {
335
451
	cairo_surface_pattern_t *dst = (cairo_surface_pattern_t *) pattern;
336
451
	cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) other;
337

            
338
	VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t)));
339

            
340
451
	*dst = *src;
341
451
	cairo_surface_reference (dst->surface);
342
451
    } break;
343
153
    case CAIRO_PATTERN_TYPE_LINEAR:
344
    case CAIRO_PATTERN_TYPE_RADIAL: {
345
153
	cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern;
346
153
	cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other;
347

            
348
153
	if (other->type == CAIRO_PATTERN_TYPE_LINEAR) {
349
	    VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t)));
350
	} else {
351
	    VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t)));
352
	}
353

            
354
153
	status = _cairo_gradient_pattern_init_copy (dst, src);
355
153
	if (unlikely (status))
356
	    return status;
357

            
358
153
    } break;
359
3
    case CAIRO_PATTERN_TYPE_MESH: {
360
3
	cairo_mesh_pattern_t *dst = (cairo_mesh_pattern_t *) pattern;
361
3
	cairo_mesh_pattern_t *src = (cairo_mesh_pattern_t *) other;
362

            
363
	VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t)));
364

            
365
3
	status = _cairo_mesh_pattern_init_copy (dst, src);
366
3
	if (unlikely (status))
367
	    return status;
368

            
369
3
    } break;
370

            
371
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE: {
372
	status = _cairo_raster_source_pattern_init_copy (pattern, other);
373
	if (unlikely (status))
374
	    return status;
375
    } break;
376
    }
377

            
378
    /* The reference count and user_data array are unique to the copy. */
379
3144
    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
380
3144
    _cairo_user_data_array_init (&pattern->user_data);
381
3144
    cairo_list_init (&pattern->observers);
382

            
383
3144
    return CAIRO_STATUS_SUCCESS;
384
}
385

            
386
void
387
2255347
_cairo_pattern_init_static_copy (cairo_pattern_t	*pattern,
388
				 const cairo_pattern_t *other)
389
{
390
    int size;
391

            
392
2255347
    assert (other->status == CAIRO_STATUS_SUCCESS);
393

            
394
2255347
    switch (other->type) {
395
    default:
396
	ASSERT_NOT_REACHED;
397
    case CAIRO_PATTERN_TYPE_SOLID:
398
1577582
	size = sizeof (cairo_solid_pattern_t);
399
1577582
	break;
400
657755
    case CAIRO_PATTERN_TYPE_SURFACE:
401
657755
	size = sizeof (cairo_surface_pattern_t);
402
657755
	break;
403
1908
    case CAIRO_PATTERN_TYPE_LINEAR:
404
1908
	size = sizeof (cairo_linear_pattern_t);
405
1908
	break;
406
1077
    case CAIRO_PATTERN_TYPE_RADIAL:
407
1077
	size = sizeof (cairo_radial_pattern_t);
408
1077
	break;
409
16929
    case CAIRO_PATTERN_TYPE_MESH:
410
16929
	size = sizeof (cairo_mesh_pattern_t);
411
16929
	break;
412
96
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
413
96
	size = sizeof (cairo_raster_source_pattern_t);
414
96
	break;
415
    }
416

            
417
2255347
    memcpy (pattern, other, size);
418

            
419
2255347
    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
420
2255347
    _cairo_user_data_array_init (&pattern->user_data);
421
2255347
    cairo_list_init (&pattern->observers);
422
2255347
}
423

            
424
cairo_status_t
425
2711
_cairo_pattern_init_snapshot (cairo_pattern_t       *pattern,
426
			      const cairo_pattern_t *other)
427
{
428
    cairo_status_t status;
429

            
430
    /* We don't bother doing any fancy copy-on-write implementation
431
     * for the pattern's data. It's generally quite tiny. */
432
2711
    status = _cairo_pattern_init_copy (pattern, other);
433
2711
    if (unlikely (status))
434
	return status;
435

            
436
    /* But we do let the surface snapshot stuff be as fancy as it
437
     * would like to be. */
438
2711
    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
439
414
	cairo_surface_pattern_t *surface_pattern =
440
	    (cairo_surface_pattern_t *) pattern;
441
414
	cairo_surface_t *surface = surface_pattern->surface;
442

            
443
414
	surface_pattern->surface = _cairo_surface_snapshot (surface);
444

            
445
414
	cairo_surface_destroy (surface);
446

            
447
414
	status = surface_pattern->surface->status;
448
2297
    } else if (pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
449
	status = _cairo_raster_source_pattern_snapshot (pattern);
450

            
451
2711
    return status;
452
}
453

            
454
void
455
126588
_cairo_pattern_fini (cairo_pattern_t *pattern)
456
{
457
126588
    _cairo_user_data_array_fini (&pattern->user_data);
458

            
459
126588
    switch (pattern->type) {
460
117694
    case CAIRO_PATTERN_TYPE_SOLID:
461
117694
	break;
462
7493
    case CAIRO_PATTERN_TYPE_SURFACE: {
463
7493
	cairo_surface_pattern_t *surface_pattern =
464
	    (cairo_surface_pattern_t *) pattern;
465

            
466
7493
	cairo_surface_destroy (surface_pattern->surface);
467
7493
    } break;
468
1364
    case CAIRO_PATTERN_TYPE_LINEAR:
469
    case CAIRO_PATTERN_TYPE_RADIAL: {
470
1364
	cairo_gradient_pattern_t *gradient =
471
	    (cairo_gradient_pattern_t *) pattern;
472

            
473
1364
	if (gradient->stops && gradient->stops != gradient->stops_embedded)
474
543
	    free (gradient->stops);
475
1364
    } break;
476
31
    case CAIRO_PATTERN_TYPE_MESH: {
477
31
	cairo_mesh_pattern_t *mesh =
478
	    (cairo_mesh_pattern_t *) pattern;
479

            
480
31
	_cairo_array_fini (&mesh->patches);
481
31
    } break;
482
6
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
483
6
	_cairo_raster_source_pattern_finish (pattern);
484
6
	break;
485
    }
486

            
487
#if HAVE_VALGRIND
488
    switch (pattern->type) {
489
    case CAIRO_PATTERN_TYPE_SOLID:
490
	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t));
491
	break;
492
    case CAIRO_PATTERN_TYPE_SURFACE:
493
	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t));
494
	break;
495
    case CAIRO_PATTERN_TYPE_LINEAR:
496
	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t));
497
	break;
498
    case CAIRO_PATTERN_TYPE_RADIAL:
499
	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t));
500
	break;
501
    case CAIRO_PATTERN_TYPE_MESH:
502
	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t));
503
	break;
504
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
505
	break;
506
    }
507
#endif
508
126588
}
509

            
510
cairo_status_t
511
_cairo_pattern_create_copy (cairo_pattern_t	  **pattern_out,
512
			    const cairo_pattern_t  *other)
513
{
514
    cairo_pattern_t *pattern;
515
    cairo_status_t status;
516

            
517
    if (other->status)
518
	return other->status;
519

            
520
    switch (other->type) {
521
    case CAIRO_PATTERN_TYPE_SOLID:
522
	pattern = _cairo_malloc (sizeof (cairo_solid_pattern_t));
523
	break;
524
    case CAIRO_PATTERN_TYPE_SURFACE:
525
	pattern = _cairo_malloc (sizeof (cairo_surface_pattern_t));
526
	break;
527
    case CAIRO_PATTERN_TYPE_LINEAR:
528
	pattern = _cairo_malloc (sizeof (cairo_linear_pattern_t));
529
	break;
530
    case CAIRO_PATTERN_TYPE_RADIAL:
531
	pattern = _cairo_malloc (sizeof (cairo_radial_pattern_t));
532
	break;
533
    case CAIRO_PATTERN_TYPE_MESH:
534
	pattern = _cairo_malloc (sizeof (cairo_mesh_pattern_t));
535
	break;
536
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
537
	pattern = _cairo_malloc (sizeof (cairo_raster_source_pattern_t));
538
	break;
539
    default:
540
	ASSERT_NOT_REACHED;
541
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
542
    }
543
    if (unlikely (pattern == NULL))
544
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
545

            
546
    status = _cairo_pattern_init_copy (pattern, other);
547
    if (unlikely (status)) {
548
	free (pattern);
549
	return status;
550
    }
551

            
552
    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
553
    *pattern_out = pattern;
554
    return CAIRO_STATUS_SUCCESS;
555
}
556

            
557
void
558
125804
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
559
			   const cairo_color_t	 *color)
560
{
561
125804
    _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
562
125804
    pattern->color = *color;
563
125804
}
564

            
565
void
566
7207
_cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern,
567
				 cairo_surface_t	 *surface)
568
{
569
7207
    if (surface->status) {
570
	/* Force to solid to simplify the pattern_fini process. */
571
	_cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
572
	_cairo_pattern_set_error (&pattern->base, surface->status);
573
	return;
574
    }
575

            
576
7207
    _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SURFACE);
577

            
578
7207
    pattern->surface = cairo_surface_reference (surface);
579
7207
    pattern->region_array_id = 0;
580
}
581

            
582
static void
583
1358
_cairo_pattern_init_gradient (cairo_gradient_pattern_t *pattern,
584
			      cairo_pattern_type_t     type)
585
{
586
1358
    _cairo_pattern_init (&pattern->base, type);
587

            
588
1358
    pattern->n_stops    = 0;
589
1358
    pattern->stops_size = 0;
590
1358
    pattern->stops      = NULL;
591
1358
}
592

            
593
static void
594
778
_cairo_pattern_init_linear (cairo_linear_pattern_t *pattern,
595
			    double x0, double y0, double x1, double y1)
596
{
597
778
    _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_LINEAR);
598

            
599
778
    pattern->pd1.x = x0;
600
778
    pattern->pd1.y = y0;
601
778
    pattern->pd2.x = x1;
602
778
    pattern->pd2.y = y1;
603
778
}
604

            
605
static void
606
580
_cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
607
			    double cx0, double cy0, double radius0,
608
			    double cx1, double cy1, double radius1)
609
{
610
580
    _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL);
611

            
612
580
    pattern->cd1.center.x = cx0;
613
580
    pattern->cd1.center.y = cy0;
614
580
    pattern->cd1.radius   = fabs (radius0);
615
580
    pattern->cd2.center.x = cx1;
616
580
    pattern->cd2.center.y = cy1;
617
580
    pattern->cd2.radius   = fabs (radius1);
618
580
}
619

            
620
cairo_pattern_t *
621
116210
_cairo_pattern_create_solid (const cairo_color_t *color)
622
{
623
    cairo_solid_pattern_t *pattern;
624

            
625
    pattern =
626
116210
	_freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SOLID]);
627
116210
    if (unlikely (pattern == NULL)) {
628
	/* None cached, need to create a new pattern. */
629
2160
	pattern = _cairo_calloc (sizeof (cairo_solid_pattern_t));
630
2160
	if (unlikely (pattern == NULL)) {
631
	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
632
	    return (cairo_pattern_t *) &_cairo_pattern_nil;
633
	}
634
    }
635

            
636
116210
    _cairo_pattern_init_solid (pattern, color);
637
116210
    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
638

            
639
116210
    return &pattern->base;
640
}
641

            
642
cairo_pattern_t *
643
354
_cairo_pattern_create_foreground_marker (void)
644
{
645
354
    cairo_pattern_t *pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
646
354
    pattern->is_foreground_marker = TRUE;
647
354
    return pattern;
648
}
649

            
650
cairo_pattern_t *
651
34
_cairo_pattern_create_in_error (cairo_status_t status)
652
{
653
    cairo_pattern_t *pattern;
654

            
655
34
    if (status == CAIRO_STATUS_NO_MEMORY)
656
	return (cairo_pattern_t *)&_cairo_pattern_nil.base;
657

            
658
    CAIRO_MUTEX_INITIALIZE ();
659

            
660
34
    pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
661
34
    if (pattern->status == CAIRO_STATUS_SUCCESS)
662
34
	status = _cairo_pattern_set_error (pattern, status);
663

            
664
34
    return pattern;
665
}
666

            
667
/**
668
 * cairo_pattern_create_rgb:
669
 * @red: red component of the color
670
 * @green: green component of the color
671
 * @blue: blue component of the color
672
 *
673
 * Creates a new #cairo_pattern_t corresponding to an opaque color.  The
674
 * color components are floating point numbers in the range 0 to 1.
675
 * If the values passed in are outside that range, they will be
676
 * clamped.
677
 *
678
 * Return value: the newly created #cairo_pattern_t if successful, or
679
 * an error pattern in case of no memory.  The caller owns the
680
 * returned object and should call cairo_pattern_destroy() when
681
 * finished with it.
682
 *
683
 * This function will always return a valid pointer, but if an error
684
 * occurred the pattern status will be set to an error.  To inspect
685
 * the status of a pattern use cairo_pattern_status().
686
 *
687
 * Since: 1.0
688
 **/
689
cairo_pattern_t *
690
116
cairo_pattern_create_rgb (double red, double green, double blue)
691
{
692
116
    return cairo_pattern_create_rgba (red, green, blue, 1.0);
693
}
694

            
695
/**
696
 * cairo_pattern_create_rgba:
697
 * @red: red component of the color
698
 * @green: green component of the color
699
 * @blue: blue component of the color
700
 * @alpha: alpha component of the color
701
 *
702
 * Creates a new #cairo_pattern_t corresponding to a translucent color.
703
 * The color components are floating point numbers in the range 0 to
704
 * 1.  If the values passed in are outside that range, they will be
705
 * clamped.
706
 *
707
 * The color is specified in the same way as in cairo_set_source_rgb().
708
 *
709
 * Return value: the newly created #cairo_pattern_t if successful, or
710
 * an error pattern in case of no memory.  The caller owns the
711
 * returned object and should call cairo_pattern_destroy() when
712
 * finished with it.
713
 *
714
 * This function will always return a valid pointer, but if an error
715
 * occurred the pattern status will be set to an error.  To inspect
716
 * the status of a pattern use cairo_pattern_status().
717
 *
718
 * Since: 1.0
719
 **/
720
cairo_pattern_t *
721
112822
cairo_pattern_create_rgba (double red, double green, double blue,
722
			   double alpha)
723
{
724
    cairo_color_t color;
725

            
726
112822
    red   = _cairo_restrict_value (red,   0.0, 1.0);
727
112822
    green = _cairo_restrict_value (green, 0.0, 1.0);
728
112822
    blue  = _cairo_restrict_value (blue,  0.0, 1.0);
729
112822
    alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
730

            
731
112822
    _cairo_color_init_rgba (&color, red, green, blue, alpha);
732

            
733
    CAIRO_MUTEX_INITIALIZE ();
734

            
735
112822
    return _cairo_pattern_create_solid (&color);
736
}
737

            
738
/**
739
 * cairo_pattern_create_for_surface:
740
 * @surface: the surface
741
 *
742
 * Create a new #cairo_pattern_t for the given surface.
743
 *
744
 * Return value: the newly created #cairo_pattern_t if successful, or
745
 * an error pattern in case of no memory.  The caller owns the
746
 * returned object and should call cairo_pattern_destroy() when
747
 * finished with it.
748
 *
749
 * This function will always return a valid pointer, but if an error
750
 * occurred the pattern status will be set to an error.  To inspect
751
 * the status of a pattern use cairo_pattern_status().
752
 *
753
 * Since: 1.0
754
 **/
755
cairo_pattern_t *
756
6938
cairo_pattern_create_for_surface (cairo_surface_t *surface)
757
{
758
    cairo_surface_pattern_t *pattern;
759

            
760
6938
    if (surface == NULL) {
761
3
	_cairo_error_throw (CAIRO_STATUS_NULL_POINTER);
762
3
	return (cairo_pattern_t*) &_cairo_pattern_nil_null_pointer;
763
    }
764

            
765
6935
    if (surface->status)
766
3
	return _cairo_pattern_create_in_error (surface->status);
767

            
768
    pattern =
769
6932
	_freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SURFACE]);
770
6932
    if (unlikely (pattern == NULL)) {
771
1791
	pattern = _cairo_calloc (sizeof (cairo_surface_pattern_t));
772
1791
	if (unlikely (pattern == NULL)) {
773
	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
774
	    return (cairo_pattern_t *)&_cairo_pattern_nil.base;
775
	}
776
    }
777

            
778
    CAIRO_MUTEX_INITIALIZE ();
779

            
780
6932
    _cairo_pattern_init_for_surface (pattern, surface);
781
6932
    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
782

            
783
6932
    return &pattern->base;
784
}
785

            
786
/**
787
 * cairo_pattern_create_linear:
788
 * @x0: x coordinate of the start point
789
 * @y0: y coordinate of the start point
790
 * @x1: x coordinate of the end point
791
 * @y1: y coordinate of the end point
792
 *
793
 * Create a new linear gradient #cairo_pattern_t along the line defined
794
 * by (x0, y0) and (x1, y1).  Before using the gradient pattern, a
795
 * number of color stops should be defined using
796
 * cairo_pattern_add_color_stop_rgb() or
797
 * cairo_pattern_add_color_stop_rgba().
798
 *
799
 * Note: The coordinates here are in pattern space. For a new pattern,
800
 * pattern space is identical to user space, but the relationship
801
 * between the spaces can be changed with cairo_pattern_set_matrix().
802
 *
803
 * Return value: the newly created #cairo_pattern_t if successful, or
804
 * an error pattern in case of no memory.  The caller owns the
805
 * returned object and should call cairo_pattern_destroy() when
806
 * finished with it.
807
 *
808
 * This function will always return a valid pointer, but if an error
809
 * occurred the pattern status will be set to an error.  To inspect
810
 * the status of a pattern use cairo_pattern_status().
811
 *
812
 * Since: 1.0
813
 **/
814
cairo_pattern_t *
815
778
cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
816
{
817
    cairo_linear_pattern_t *pattern;
818

            
819
    pattern =
820
778
	_freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_LINEAR]);
821
778
    if (unlikely (pattern == NULL)) {
822
208
	pattern = _cairo_calloc (sizeof (cairo_linear_pattern_t));
823
208
	if (unlikely (pattern == NULL)) {
824
	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
825
	    return (cairo_pattern_t *) &_cairo_pattern_nil.base;
826
	}
827
    }
828

            
829
    CAIRO_MUTEX_INITIALIZE ();
830

            
831
778
    _cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
832
778
    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
833

            
834
778
    return &pattern->base.base;
835
}
836

            
837
/**
838
 * cairo_pattern_create_radial:
839
 * @cx0: x coordinate for the center of the start circle
840
 * @cy0: y coordinate for the center of the start circle
841
 * @radius0: radius of the start circle
842
 * @cx1: x coordinate for the center of the end circle
843
 * @cy1: y coordinate for the center of the end circle
844
 * @radius1: radius of the end circle
845
 *
846
 * Creates a new radial gradient #cairo_pattern_t between the two
847
 * circles defined by (cx0, cy0, radius0) and (cx1, cy1, radius1).  Before using the
848
 * gradient pattern, a number of color stops should be defined using
849
 * cairo_pattern_add_color_stop_rgb() or
850
 * cairo_pattern_add_color_stop_rgba().
851
 *
852
 * Note: The coordinates here are in pattern space. For a new pattern,
853
 * pattern space is identical to user space, but the relationship
854
 * between the spaces can be changed with cairo_pattern_set_matrix().
855
 *
856
 * Return value: the newly created #cairo_pattern_t if successful, or
857
 * an error pattern in case of no memory.  The caller owns the
858
 * returned object and should call cairo_pattern_destroy() when
859
 * finished with it.
860
 *
861
 * This function will always return a valid pointer, but if an error
862
 * occurred the pattern status will be set to an error.  To inspect
863
 * the status of a pattern use cairo_pattern_status().
864
 *
865
 * Since: 1.0
866
 **/
867
cairo_pattern_t *
868
580
cairo_pattern_create_radial (double cx0, double cy0, double radius0,
869
			     double cx1, double cy1, double radius1)
870
{
871
    cairo_radial_pattern_t *pattern;
872

            
873
    pattern =
874
580
	_freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_RADIAL]);
875
580
    if (unlikely (pattern == NULL)) {
876
61
	pattern = _cairo_calloc (sizeof (cairo_radial_pattern_t));
877
61
	if (unlikely (pattern == NULL)) {
878
	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
879
	    return (cairo_pattern_t *) &_cairo_pattern_nil.base;
880
	}
881
    }
882

            
883
    CAIRO_MUTEX_INITIALIZE ();
884

            
885
580
    _cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
886
580
    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
887

            
888
580
    return &pattern->base.base;
889
}
890

            
891
/* This order is specified in the diagram in the documentation for
892
 * cairo_pattern_create_mesh() */
893
static const int mesh_path_point_i[12] = { 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1 };
894
static const int mesh_path_point_j[12] = { 0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0 };
895
static const int mesh_control_point_i[4] = { 1, 1, 2, 2 };
896
static const int mesh_control_point_j[4] = { 1, 2, 2, 1 };
897

            
898
/**
899
 * cairo_pattern_create_mesh:
900
 *
901
 * Create a new mesh pattern.
902
 *
903
 * Mesh patterns are tensor-product patch meshes (type 7 shadings in
904
 * PDF). Mesh patterns may also be used to create other types of
905
 * shadings that are special cases of tensor-product patch meshes such
906
 * as Coons patch meshes (type 6 shading in PDF) and Gouraud-shaded
907
 * triangle meshes (type 4 and 5 shadings in PDF).
908
 *
909
 * Mesh patterns consist of one or more tensor-product patches, which
910
 * should be defined before using the mesh pattern. Using a mesh
911
 * pattern with a partially defined patch as source or mask will put
912
 * the context in an error status with a status of
913
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
914
 *
915
 * A tensor-product patch is defined by 4 Bézier curves (side 0, 1, 2,
916
 * 3) and by 4 additional control points (P0, P1, P2, P3) that provide
917
 * further control over the patch and complete the definition of the
918
 * tensor-product patch. The corner C0 is the first point of the
919
 * patch.
920
 *
921
 * Degenerate sides are permitted so straight lines may be used. A
922
 * zero length line on one side may be used to create 3 sided patches.
923
 *
924
 * <informalexample><screen>
925
 *       C1     Side 1       C2
926
 *        +---------------+
927
 *        |               |
928
 *        |  P1       P2  |
929
 *        |               |
930
 * Side 0 |               | Side 2
931
 *        |               |
932
 *        |               |
933
 *        |  P0       P3  |
934
 *        |               |
935
 *        +---------------+
936
 *      C0     Side 3        C3
937
 * </screen></informalexample>
938
 *
939
 * Each patch is constructed by first calling
940
 * cairo_mesh_pattern_begin_patch(), then cairo_mesh_pattern_move_to()
941
 * to specify the first point in the patch (C0). Then the sides are
942
 * specified with calls to cairo_mesh_pattern_curve_to() and
943
 * cairo_mesh_pattern_line_to().
944
 *
945
 * The four additional control points (P0, P1, P2, P3) in a patch can
946
 * be specified with cairo_mesh_pattern_set_control_point().
947
 *
948
 * At each corner of the patch (C0, C1, C2, C3) a color may be
949
 * specified with cairo_mesh_pattern_set_corner_color_rgb() or
950
 * cairo_mesh_pattern_set_corner_color_rgba(). Any corner whose color
951
 * is not explicitly specified defaults to transparent black.
952
 *
953
 * A Coons patch is a special case of the tensor-product patch where
954
 * the control points are implicitly defined by the sides of the
955
 * patch. The default value for any control point not specified is the
956
 * implicit value for a Coons patch, i.e. if no control points are
957
 * specified the patch is a Coons patch.
958
 *
959
 * A triangle is a special case of the tensor-product patch where the
960
 * control points are implicitly defined by the sides of the patch,
961
 * all the sides are lines and one of them has length 0, i.e. if the
962
 * patch is specified using just 3 lines, it is a triangle. If the
963
 * corners connected by the 0-length side have the same color, the
964
 * patch is a Gouraud-shaded triangle.
965
 *
966
 * Patches may be oriented differently to the above diagram. For
967
 * example the first point could be at the top left. The diagram only
968
 * shows the relationship between the sides, corners and control
969
 * points. Regardless of where the first point is located, when
970
 * specifying colors, corner 0 will always be the first point, corner
971
 * 1 the point between side 0 and side 1 etc.
972
 *
973
 * Calling cairo_mesh_pattern_end_patch() completes the current
974
 * patch. If less than 4 sides have been defined, the first missing
975
 * side is defined as a line from the current point to the first point
976
 * of the patch (C0) and the other sides are degenerate lines from C0
977
 * to C0. The corners between the added sides will all be coincident
978
 * with C0 of the patch and their color will be set to be the same as
979
 * the color of C0.
980
 *
981
 * Additional patches may be added with additional calls to
982
 * cairo_mesh_pattern_begin_patch()/cairo_mesh_pattern_end_patch().
983
 *
984
 * <informalexample><programlisting>
985
 * cairo_pattern_t *pattern = cairo_pattern_create_mesh ();
986
 *
987
 * /&ast; Add a Coons patch &ast;/
988
 * cairo_mesh_pattern_begin_patch (pattern);
989
 * cairo_mesh_pattern_move_to (pattern, 0, 0);
990
 * cairo_mesh_pattern_curve_to (pattern, 30, -30,  60,  30, 100, 0);
991
 * cairo_mesh_pattern_curve_to (pattern, 60,  30, 130,  60, 100, 100);
992
 * cairo_mesh_pattern_curve_to (pattern, 60,  70,  30, 130,   0, 100);
993
 * cairo_mesh_pattern_curve_to (pattern, 30,  70, -30,  30,   0, 0);
994
 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 0, 1, 0, 0);
995
 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 1, 0, 1, 0);
996
 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 2, 0, 0, 1);
997
 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 3, 1, 1, 0);
998
 * cairo_mesh_pattern_end_patch (pattern);
999
 *
 * /&ast; Add a Gouraud-shaded triangle &ast;/
 * cairo_mesh_pattern_begin_patch (pattern)
 * cairo_mesh_pattern_move_to (pattern, 100, 100);
 * cairo_mesh_pattern_line_to (pattern, 130, 130);
 * cairo_mesh_pattern_line_to (pattern, 130,  70);
 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 0, 1, 0, 0);
 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 1, 0, 1, 0);
 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 2, 0, 0, 1);
 * cairo_mesh_pattern_end_patch (pattern)
 * </programlisting></informalexample>
 *
 * When two patches overlap, the last one that has been added is drawn
 * over the first one.
 *
 * When a patch folds over itself, points are sorted depending on
 * their parameter coordinates inside the patch. The v coordinate
 * ranges from 0 to 1 when moving from side 3 to side 1; the u
 * coordinate ranges from 0 to 1 when going from side 0 to side
 * 2. Points with higher v coordinate hide points with lower v
 * coordinate. When two points have the same v coordinate, the one
 * with higher u coordinate is above. This means that points nearer to
 * side 1 are above points nearer to side 3; when this is not
 * sufficient to decide which point is above (for example when both
 * points belong to side 1 or side 3) points nearer to side 2 are
 * above points nearer to side 0.
 *
 * For a complete definition of tensor-product patches, see the PDF
 * specification (ISO32000), which describes the parametrization in
 * detail.
 *
 * Note: The coordinates are always in pattern space. For a new
 * pattern, pattern space is identical to user space, but the
 * relationship between the spaces can be changed with
 * cairo_pattern_set_matrix().
 *
 * Return value: the newly created #cairo_pattern_t if successful, or
 * an error pattern in case of no memory. The caller owns the returned
 * object and should call cairo_pattern_destroy() when finished with
 * it.
 *
 * This function will always return a valid pointer, but if an error
 * occurred the pattern status will be set to an error. To inspect the
 * status of a pattern use cairo_pattern_status().
 *
 * Since: 1.12
 **/
cairo_pattern_t *
28
cairo_pattern_create_mesh (void)
{
    cairo_mesh_pattern_t *pattern;
    pattern =
28
	_freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_MESH]);
28
    if (unlikely (pattern == NULL)) {
28
	pattern = _cairo_calloc (sizeof (cairo_mesh_pattern_t));
28
	if (unlikely (pattern == NULL)) {
	    _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
	    return (cairo_pattern_t *) &_cairo_pattern_nil.base;
	}
    }
    CAIRO_MUTEX_INITIALIZE ();
28
    _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_MESH);
28
    _cairo_array_init (&pattern->patches, sizeof (cairo_mesh_patch_t));
28
    pattern->current_patch = NULL;
28
    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
28
    return &pattern->base;
}
/**
 * cairo_pattern_reference:
 * @pattern: a #cairo_pattern_t
 *
 * Increases the reference count on @pattern by one. This prevents
 * @pattern from being destroyed until a matching call to
 * cairo_pattern_destroy() is made.
 *
 * Use cairo_pattern_get_reference_count() to get the number of
 * references to a #cairo_pattern_t.
 *
 * Return value: the referenced #cairo_pattern_t.
 *
 * Since: 1.0
 **/
cairo_pattern_t *
315798
cairo_pattern_reference (cairo_pattern_t *pattern)
{
315798
    if (pattern == NULL ||
631596
	    CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
138754
	return pattern;
354088
    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
177044
    _cairo_reference_count_inc (&pattern->ref_count);
177044
    return pattern;
}
/**
 * cairo_pattern_get_type:
 * @pattern: a #cairo_pattern_t
 *
 * Get the pattern's type.  See #cairo_pattern_type_t for available
 * types.
 *
 * Return value: The type of @pattern.
 *
 * Since: 1.2
 **/
cairo_pattern_type_t
186
cairo_pattern_get_type (cairo_pattern_t *pattern)
{
186
    return pattern->type;
}
/**
 * cairo_pattern_status:
 * @pattern: a #cairo_pattern_t
 *
 * Checks whether an error has previously occurred for this
 * pattern.
 *
 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NO_MEMORY,
 * %CAIRO_STATUS_INVALID_MATRIX, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH,
 * or %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
 *
 * Since: 1.0
 **/
cairo_status_t
20
cairo_pattern_status (cairo_pattern_t *pattern)
{
20
    return pattern->status;
}
/**
 * cairo_pattern_destroy:
 * @pattern: a #cairo_pattern_t
 *
 * Decreases the reference count on @pattern by one. If the result is
 * zero, then @pattern and all associated resources are freed.  See
 * cairo_pattern_reference().
 *
 * Since: 1.0
 **/
void
473511
cairo_pattern_destroy (cairo_pattern_t *pattern)
{
    cairo_pattern_type_t type;
473511
    if (pattern == NULL ||
947022
	    CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
172184
	return;
602654
    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
301327
    if (! _cairo_reference_count_dec_and_test (&pattern->ref_count))
177038
	return;
124289
    type = pattern->type;
124289
    _cairo_pattern_fini (pattern);
    /* maintain a small cache of freed patterns */
124289
    if (type < ARRAY_LENGTH (freed_pattern_pool))
124283
	_freed_pool_put (&freed_pattern_pool[type], pattern);
    else
6
	free (pattern);
}
/**
 * cairo_pattern_get_reference_count:
 * @pattern: a #cairo_pattern_t
 *
 * Returns the current reference count of @pattern.
 *
 * Return value: the current reference count of @pattern.  If the
 * object is a nil object, 0 will be returned.
 *
 * Since: 1.4
 **/
unsigned int
cairo_pattern_get_reference_count (cairo_pattern_t *pattern)
{
    if (pattern == NULL ||
	    CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
	return 0;
    return CAIRO_REFERENCE_COUNT_GET_VALUE (&pattern->ref_count);
}
/**
 * cairo_pattern_get_user_data:
 * @pattern: a #cairo_pattern_t
 * @key: the address of the #cairo_user_data_key_t the user data was
 * attached to
 *
 * Return user data previously attached to @pattern using the
 * specified key.  If no user data has been attached with the given
 * key this function returns %NULL.
 *
 * Return value: the user data previously attached or %NULL.
 *
 * Since: 1.4
 **/
void *
cairo_pattern_get_user_data (cairo_pattern_t		 *pattern,
			     const cairo_user_data_key_t *key)
{
    return _cairo_user_data_array_get_data (&pattern->user_data,
					    key);
}
/**
 * cairo_pattern_set_user_data:
 * @pattern: a #cairo_pattern_t
 * @key: the address of a #cairo_user_data_key_t to attach the user data to
 * @user_data: the user data to attach to the #cairo_pattern_t
 * @destroy: a #cairo_destroy_func_t which will be called when the
 * #cairo_t is destroyed or when new user data is attached using the
 * same key.
 *
 * Attach user data to @pattern.  To remove user data from a surface,
 * call this function with the key that was used to set it and %NULL
 * for @data.
 *
 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
 * slot could not be allocated for the user data.
 *
 * Since: 1.4
 **/
cairo_status_t
cairo_pattern_set_user_data (cairo_pattern_t		 *pattern,
			     const cairo_user_data_key_t *key,
			     void			 *user_data,
			     cairo_destroy_func_t	  destroy)
{
    if (CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
	return pattern->status;
    return _cairo_user_data_array_set_data (&pattern->user_data,
					    key, user_data, destroy);
}
/**
 * cairo_mesh_pattern_begin_patch:
 * @pattern: a #cairo_pattern_t
 *
 * Begin a patch in a mesh pattern.
 *
 * After calling this function, the patch shape should be defined with
 * cairo_mesh_pattern_move_to(), cairo_mesh_pattern_line_to() and
 * cairo_mesh_pattern_curve_to().
 *
 * After defining the patch, cairo_mesh_pattern_end_patch() must be
 * called before using @pattern as a source or mask.
 *
 * Note: If @pattern is not a mesh pattern then @pattern will be put
 * into an error status with a status of
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern already has a
 * current patch, it will be put into an error status with a status of
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
 *
 * Since: 1.12
 **/
void
66
cairo_mesh_pattern_begin_patch (cairo_pattern_t *pattern)
{
    cairo_mesh_pattern_t *mesh;
    cairo_status_t status;
    cairo_mesh_patch_t *current_patch;
    int i;
66
    if (unlikely (pattern->status))
	return;
66
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
	return;
    }
66
    mesh = (cairo_mesh_pattern_t *) pattern;
66
    if (unlikely (mesh->current_patch)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
	return;
    }
66
    status = _cairo_array_allocate (&mesh->patches, 1, (void **) &current_patch);
66
    if (unlikely (status)) {
	_cairo_pattern_set_error (pattern, status);
	return;
    }
66
    mesh->current_patch = current_patch;
66
    mesh->current_side = -2; /* no current point */
330
    for (i = 0; i < 4; i++)
264
	mesh->has_control_point[i] = FALSE;
330
    for (i = 0; i < 4; i++)
264
	mesh->has_color[i] = FALSE;
}
static void
240
_calc_control_point (cairo_mesh_patch_t *patch, int control_point)
{
    /* The Coons patch is a special case of the Tensor Product patch
     * where the four control points are:
     *
     * P11 = S(1/3, 1/3)
     * P12 = S(1/3, 2/3)
     * P21 = S(2/3, 1/3)
     * P22 = S(2/3, 2/3)
     *
     * where S is the gradient surface.
     *
     * When one or more control points has not been specified
     * calculated the Coons patch control points are substituted. If
     * no control points are specified the gradient will be a Coons
     * patch.
     *
     * The equations below are defined in the ISO32000 standard.
     */
    cairo_point_double_t *p[3][3];
    int cp_i, cp_j, i, j;
240
    cp_i = mesh_control_point_i[control_point];
240
    cp_j = mesh_control_point_j[control_point];
960
    for (i = 0; i < 3; i++)
2880
	for (j = 0; j < 3; j++)
2160
	    p[i][j] = &patch->points[cp_i ^ i][cp_j ^ j];
240
    p[0][0]->x = (- 4 * p[1][1]->x
240
		  + 6 * (p[1][0]->x + p[0][1]->x)
240
		  - 2 * (p[1][2]->x + p[2][1]->x)
240
		  + 3 * (p[2][0]->x + p[0][2]->x)
240
		  - 1 * p[2][2]->x) * (1. / 9);
240
    p[0][0]->y = (- 4 * p[1][1]->y
240
		  + 6 * (p[1][0]->y + p[0][1]->y)
240
		  - 2 * (p[1][2]->y + p[2][1]->y)
240
		  + 3 * (p[2][0]->y + p[0][2]->y)
240
		  - 1 * p[2][2]->y) * (1. / 9);
240
}
/**
 * cairo_mesh_pattern_end_patch:
 * @pattern: a #cairo_pattern_t
 *
 * Indicates the end of the current patch in a mesh pattern.
 *
 * If the current patch has less than 4 sides, it is closed with a
 * straight line from the current point to the first point of the
 * patch as if cairo_mesh_pattern_line_to() was used.
 *
 * Note: If @pattern is not a mesh pattern then @pattern will be put
 * into an error status with a status of
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
 * patch or the current patch has no current point, @pattern will be
 * put into an error status with a status of
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
 *
 * Since: 1.12
 **/
void
66
cairo_mesh_pattern_end_patch (cairo_pattern_t *pattern)
{
    cairo_mesh_pattern_t *mesh;
    cairo_mesh_patch_t *current_patch;
    int i;
66
    if (unlikely (pattern->status))
	return;
66
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
	return;
    }
66
    mesh = (cairo_mesh_pattern_t *) pattern;
66
    current_patch = mesh->current_patch;
66
    if (unlikely (!current_patch)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
	return;
    }
66
    if (unlikely (mesh->current_side == -2)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
	return;
    }
135
    while (mesh->current_side < 3) {
	int corner_num;
69
	cairo_mesh_pattern_line_to (pattern,
				    current_patch->points[0][0].x,
				    current_patch->points[0][0].y);
69
	corner_num = mesh->current_side + 1;
69
	if (corner_num < 4 && ! mesh->has_color[corner_num]) {
27
	    current_patch->colors[corner_num] = current_patch->colors[0];
27
	    mesh->has_color[corner_num] = TRUE;
	}
    }
330
    for (i = 0; i < 4; i++) {
264
	if (! mesh->has_control_point[i])
240
	    _calc_control_point (current_patch, i);
    }
330
    for (i = 0; i < 4; i++) {
264
	if (! mesh->has_color[i])
18
	    current_patch->colors[i] = *CAIRO_COLOR_TRANSPARENT;
    }
66
    mesh->current_patch = NULL;
}
/**
 * cairo_mesh_pattern_curve_to:
 * @pattern: a #cairo_pattern_t
 * @x1: the X coordinate of the first control point
 * @y1: the Y coordinate of the first control point
 * @x2: the X coordinate of the second control point
 * @y2: the Y coordinate of the second control point
 * @x3: the X coordinate of the end of the curve
 * @y3: the Y coordinate of the end of the curve
 *
 * Adds a cubic Bézier spline to the current patch from the current
 * point to position (@x3, @y3) in pattern-space coordinates, using
 * (@x1, @y1) and (@x2, @y2) as the control points.
 *
 * If the current patch has no current point before the call to
 * cairo_mesh_pattern_curve_to(), this function will behave as if
 * preceded by a call to cairo_mesh_pattern_move_to(@pattern, @x1,
 * @y1).
 *
 * After this call the current point will be (@x3, @y3).
 *
 * Note: If @pattern is not a mesh pattern then @pattern will be put
 * into an error status with a status of
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
 * patch or the current patch already has 4 sides, @pattern will be
 * put into an error status with a status of
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
 *
 * Since: 1.12
 **/
void
264
cairo_mesh_pattern_curve_to (cairo_pattern_t *pattern,
			     double x1, double y1,
			     double x2, double y2,
			     double x3, double y3)
{
    cairo_mesh_pattern_t *mesh;
    int current_point, i, j;
264
    if (unlikely (pattern->status))
	return;
264
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
	return;
    }
264
    mesh = (cairo_mesh_pattern_t *) pattern;
264
    if (unlikely (!mesh->current_patch)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
	return;
    }
264
    if (unlikely (mesh->current_side == 3)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
	return;
    }
264
    if (mesh->current_side == -2)
	cairo_mesh_pattern_move_to (pattern, x1, y1);
264
    assert (mesh->current_side >= -1);
264
    assert (pattern->status == CAIRO_STATUS_SUCCESS);
264
    mesh->current_side++;
264
    current_point = 3 * mesh->current_side;
264
    current_point++;
264
    i = mesh_path_point_i[current_point];
264
    j = mesh_path_point_j[current_point];
264
    mesh->current_patch->points[i][j].x = x1;
264
    mesh->current_patch->points[i][j].y = y1;
264
    current_point++;
264
    i = mesh_path_point_i[current_point];
264
    j = mesh_path_point_j[current_point];
264
    mesh->current_patch->points[i][j].x = x2;
264
    mesh->current_patch->points[i][j].y = y2;
264
    current_point++;
264
    if (current_point < 12) {
198
	i = mesh_path_point_i[current_point];
198
	j = mesh_path_point_j[current_point];
198
	mesh->current_patch->points[i][j].x = x3;
198
	mesh->current_patch->points[i][j].y = y3;
    }
}
/**
 * cairo_mesh_pattern_line_to:
 * @pattern: a #cairo_pattern_t
 * @x: the X coordinate of the end of the new line
 * @y: the Y coordinate of the end of the new line
 *
 * Adds a line to the current patch from the current point to position
 * (@x, @y) in pattern-space coordinates.
 *
 * If there is no current point before the call to
 * cairo_mesh_pattern_line_to() this function will behave as
 * cairo_mesh_pattern_move_to(@pattern, @x, @y).
 *
 * After this call the current point will be (@x, @y).
 *
 * Note: If @pattern is not a mesh pattern then @pattern will be put
 * into an error status with a status of
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
 * patch or the current patch already has 4 sides, @pattern will be
 * put into an error status with a status of
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
 *
 * Since: 1.12
 **/
void
144
cairo_mesh_pattern_line_to (cairo_pattern_t *pattern,
			    double x, double y)
{
    cairo_mesh_pattern_t *mesh;
    cairo_point_double_t last_point;
    int last_point_idx, i, j;
144
    if (unlikely (pattern->status))
	return;
144
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
	return;
    }
144
    mesh = (cairo_mesh_pattern_t *) pattern;
144
    if (unlikely (!mesh->current_patch)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
	return;
    }
144
    if (unlikely (mesh->current_side == 3)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
	return;
    }
144
    if (mesh->current_side == -2) {
	cairo_mesh_pattern_move_to (pattern, x, y);
	return;
    }
144
    last_point_idx = 3 * (mesh->current_side + 1);
144
    i = mesh_path_point_i[last_point_idx];
144
    j = mesh_path_point_j[last_point_idx];
144
    last_point = mesh->current_patch->points[i][j];
144
    cairo_mesh_pattern_curve_to (pattern,
144
				 (2 * last_point.x + x) * (1. / 3),
144
				 (2 * last_point.y + y) * (1. / 3),
144
				 (last_point.x + 2 * x) * (1. / 3),
144
				 (last_point.y + 2 * y) * (1. / 3),
				 x, y);
}
/**
 * cairo_mesh_pattern_move_to:
 * @pattern: a #cairo_pattern_t
 * @x: the X coordinate of the new position
 * @y: the Y coordinate of the new position
 *
 * Define the first point of the current patch in a mesh pattern.
 *
 * After this call the current point will be (@x, @y).
 *
 * Note: If @pattern is not a mesh pattern then @pattern will be put
 * into an error status with a status of
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
 * patch or the current patch already has at least one side, @pattern
 * will be put into an error status with a status of
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
 *
 * Since: 1.12
 **/
void
66
cairo_mesh_pattern_move_to (cairo_pattern_t *pattern,
			    double x, double y)
{
    cairo_mesh_pattern_t *mesh;
66
    if (unlikely (pattern->status))
	return;
66
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
	return;
    }
66
    mesh = (cairo_mesh_pattern_t *) pattern;
66
    if (unlikely (!mesh->current_patch)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
	return;
    }
66
    if (unlikely (mesh->current_side >= 0)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
	return;
    }
66
    mesh->current_side = -1;
66
    mesh->current_patch->points[0][0].x = x;
66
    mesh->current_patch->points[0][0].y = y;
}
/**
 * cairo_mesh_pattern_set_control_point:
 * @pattern: a #cairo_pattern_t
 * @point_num: the control point to set the position for
 * @x: the X coordinate of the control point
 * @y: the Y coordinate of the control point
 *
 * Set an internal control point of the current patch.
 *
 * Valid values for @point_num are from 0 to 3 and identify the
 * control points as explained in cairo_pattern_create_mesh().
 *
 * Note: If @pattern is not a mesh pattern then @pattern will be put
 * into an error status with a status of
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @point_num is not valid,
 * @pattern will be put into an error status with a status of
 * %CAIRO_STATUS_INVALID_INDEX.  If @pattern has no current patch,
 * @pattern will be put into an error status with a status of
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
 *
 * Since: 1.12
 **/
void
24
cairo_mesh_pattern_set_control_point (cairo_pattern_t *pattern,
				      unsigned int     point_num,
				      double           x,
				      double           y)
{
    cairo_mesh_pattern_t *mesh;
    int i, j;
24
    if (unlikely (pattern->status))
	return;
24
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
	return;
    }
24
    if (unlikely (point_num > 3)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_INDEX);
	return;
    }
24
    mesh = (cairo_mesh_pattern_t *) pattern;
24
    if (unlikely (!mesh->current_patch)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
	return;
    }
24
    i = mesh_control_point_i[point_num];
24
    j = mesh_control_point_j[point_num];
24
    mesh->current_patch->points[i][j].x = x;
24
    mesh->current_patch->points[i][j].y = y;
24
    mesh->has_control_point[point_num] = TRUE;
}
/* make room for at least one more color stop */
static cairo_status_t
1818
_cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
{
    cairo_gradient_stop_t *new_stops;
1818
    int old_size = pattern->stops_size;
1818
    int embedded_size = ARRAY_LENGTH (pattern->stops_embedded);
1818
    int new_size = 2 * MAX (old_size, 4);
    /* we have a local buffer at pattern->stops_embedded.  try to fulfill the request
     * from there. */
1818
    if (old_size < embedded_size) {
1320
	pattern->stops = pattern->stops_embedded;
1320
	pattern->stops_size = embedded_size;
1320
	return CAIRO_STATUS_SUCCESS;
    }
    if (CAIRO_INJECT_FAULT ())
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
498
    assert (pattern->n_stops <= pattern->stops_size);
498
    if (pattern->stops == pattern->stops_embedded) {
498
	new_stops = _cairo_malloc_ab (new_size, sizeof (cairo_gradient_stop_t));
498
	if (new_stops)
498
	    memcpy (new_stops, pattern->stops, old_size * sizeof (cairo_gradient_stop_t));
    } else {
	new_stops = _cairo_realloc_ab (pattern->stops,
				       new_size,
				       sizeof (cairo_gradient_stop_t));
    }
498
    if (unlikely (new_stops == NULL))
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
498
    pattern->stops = new_stops;
498
    pattern->stops_size = new_size;
498
    return CAIRO_STATUS_SUCCESS;
}
static void
219
_cairo_mesh_pattern_set_corner_color (cairo_mesh_pattern_t *mesh,
				      unsigned int     corner_num,
				      double red, double green, double blue,
				      double alpha)
{
    cairo_color_t *color;
219
    assert (mesh->current_patch);
219
    assert (corner_num <= 3);
219
    color = &mesh->current_patch->colors[corner_num];
219
    color->red   = red;
219
    color->green = green;
219
    color->blue  = blue;
219
    color->alpha = alpha;
219
    color->red_short   = _cairo_color_double_to_short (red);
219
    color->green_short = _cairo_color_double_to_short (green);
219
    color->blue_short  = _cairo_color_double_to_short (blue);
219
    color->alpha_short = _cairo_color_double_to_short (alpha);
219
    mesh->has_color[corner_num] = TRUE;
219
}
/**
 * cairo_mesh_pattern_set_corner_color_rgb:
 * @pattern: a #cairo_pattern_t
 * @corner_num: the corner to set the color for
 * @red: red component of color
 * @green: green component of color
 * @blue: blue component of color
 *
 * Sets the color of a corner of the current patch in a mesh pattern.
 *
 * The color is specified in the same way as in cairo_set_source_rgb().
 *
 * Valid values for @corner_num are from 0 to 3 and identify the
 * corners as explained in cairo_pattern_create_mesh().
 *
 * Note: If @pattern is not a mesh pattern then @pattern will be put
 * into an error status with a status of
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @corner_num is not valid,
 * @pattern will be put into an error status with a status of
 * %CAIRO_STATUS_INVALID_INDEX.  If @pattern has no current patch,
 * @pattern will be put into an error status with a status of
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
 *
 * Since: 1.12
 **/
void
201
cairo_mesh_pattern_set_corner_color_rgb (cairo_pattern_t *pattern,
					 unsigned int     corner_num,
					 double red, double green, double blue)
{
201
    cairo_mesh_pattern_set_corner_color_rgba (pattern, corner_num, red, green, blue, 1.0);
201
}
/**
 * cairo_mesh_pattern_set_corner_color_rgba:
 * @pattern: a #cairo_pattern_t
 * @corner_num: the corner to set the color for
 * @red: red component of color
 * @green: green component of color
 * @blue: blue component of color
 * @alpha: alpha component of color
 *
 * Sets the color of a corner of the current patch in a mesh pattern.
 *
 * The color is specified in the same way as in cairo_set_source_rgba().
 *
 * Valid values for @corner_num are from 0 to 3 and identify the
 * corners as explained in cairo_pattern_create_mesh().
 *
 * Note: If @pattern is not a mesh pattern then @pattern will be put
 * into an error status with a status of
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @corner_num is not valid,
 * @pattern will be put into an error status with a status of
 * %CAIRO_STATUS_INVALID_INDEX.  If @pattern has no current patch,
 * @pattern will be put into an error status with a status of
 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
 *
 * Since: 1.12
 **/
void
219
cairo_mesh_pattern_set_corner_color_rgba (cairo_pattern_t *pattern,
					  unsigned int     corner_num,
					  double red, double green, double blue,
					  double alpha)
{
    cairo_mesh_pattern_t *mesh;
219
    if (unlikely (pattern->status))
	return;
219
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
	return;
    }
219
    if (unlikely (corner_num > 3)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_INDEX);
	return;
    }
219
    mesh = (cairo_mesh_pattern_t *) pattern;
219
    if (unlikely (!mesh->current_patch)) {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
	return;
    }
219
    red    = _cairo_restrict_value (red,    0.0, 1.0);
219
    green  = _cairo_restrict_value (green,  0.0, 1.0);
219
    blue   = _cairo_restrict_value (blue,   0.0, 1.0);
219
    alpha  = _cairo_restrict_value (alpha,  0.0, 1.0);
219
    _cairo_mesh_pattern_set_corner_color (mesh, corner_num, red, green, blue, alpha);
}
static void
3075
_cairo_pattern_add_color_stop (cairo_gradient_pattern_t	*pattern,
			       double			 offset,
			       double			 red,
			       double			 green,
			       double			 blue,
			       double			 alpha)
{
    cairo_gradient_stop_t *stops;
    unsigned int	   i;
3075
    if (pattern->n_stops >= pattern->stops_size) {
1818
        cairo_status_t status = _cairo_pattern_gradient_grow (pattern);
1818
	if (unlikely (status)) {
	    status = _cairo_pattern_set_error (&pattern->base, status);
	    return;
	}
    }
3075
    stops = pattern->stops;
5457
    for (i = 0; i < pattern->n_stops; i++)
    {
2388
	if (offset < stops[i].offset)
	{
6
	    memmove (&stops[i + 1], &stops[i],
6
		     sizeof (cairo_gradient_stop_t) * (pattern->n_stops - i));
6
	    break;
	}
    }
3075
    stops[i].offset = offset;
3075
    stops[i].color.red   = red;
3075
    stops[i].color.green = green;
3075
    stops[i].color.blue  = blue;
3075
    stops[i].color.alpha = alpha;
3075
    stops[i].color.red_short   = _cairo_color_double_to_short (red);
3075
    stops[i].color.green_short = _cairo_color_double_to_short (green);
3075
    stops[i].color.blue_short  = _cairo_color_double_to_short (blue);
3075
    stops[i].color.alpha_short = _cairo_color_double_to_short (alpha);
3075
    pattern->n_stops++;
}
/**
 * cairo_pattern_add_color_stop_rgb:
 * @pattern: a #cairo_pattern_t
 * @offset: an offset in the range [0.0 .. 1.0]
 * @red: red component of color
 * @green: green component of color
 * @blue: blue component of color
 *
 * Adds an opaque color stop to a gradient pattern. The offset
 * specifies the location along the gradient's control vector. For
 * example, a linear gradient's control vector is from (x0,y0) to
 * (x1,y1) while a radial gradient's control vector is from any point
 * on the start circle to the corresponding point on the end circle.
 *
 * The color is specified in the same way as in cairo_set_source_rgb().
 *
 * If two (or more) stops are specified with identical offset values,
 * they will be sorted according to the order in which the stops are
 * added, (stops added earlier will compare less than stops added
 * later). This can be useful for reliably making sharp color
 * transitions instead of the typical blend.
 *
 *
 * Note: If the pattern is not a gradient pattern, (eg. a linear or
 * radial pattern), then the pattern will be put into an error status
 * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
 *
 * Since: 1.0
 **/
void
576
cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
				  double	   offset,
				  double	   red,
				  double	   green,
				  double	   blue)
{
576
    cairo_pattern_add_color_stop_rgba (pattern, offset, red, green, blue, 1.0);
576
}
/**
 * cairo_pattern_add_color_stop_rgba:
 * @pattern: a #cairo_pattern_t
 * @offset: an offset in the range [0.0 .. 1.0]
 * @red: red component of color
 * @green: green component of color
 * @blue: blue component of color
 * @alpha: alpha component of color
 *
 * Adds a translucent color stop to a gradient pattern. The offset
 * specifies the location along the gradient's control vector. For
 * example, a linear gradient's control vector is from (x0,y0) to
 * (x1,y1) while a radial gradient's control vector is from any point
 * on the start circle to the corresponding point on the end circle.
 *
 * The color is specified in the same way as in cairo_set_source_rgba().
 *
 * If two (or more) stops are specified with identical offset values,
 * they will be sorted according to the order in which the stops are
 * added, (stops added earlier will compare less than stops added
 * later). This can be useful for reliably making sharp color
 * transitions instead of the typical blend.
 *
 * Note: If the pattern is not a gradient pattern, (eg. a linear or
 * radial pattern), then the pattern will be put into an error status
 * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
 *
 * Since: 1.0
 **/
void
3075
cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
				   double	   offset,
				   double	   red,
				   double	   green,
				   double	   blue,
				   double	   alpha)
{
3075
    if (pattern->status)
	return;
3075
    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
1449
	pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
    {
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
	return;
    }
3075
    offset = _cairo_restrict_value (offset, 0.0, 1.0);
3075
    red    = _cairo_restrict_value (red,    0.0, 1.0);
3075
    green  = _cairo_restrict_value (green,  0.0, 1.0);
3075
    blue   = _cairo_restrict_value (blue,   0.0, 1.0);
3075
    alpha  = _cairo_restrict_value (alpha,  0.0, 1.0);
3075
    _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
				   offset, red, green, blue, alpha);
}
/**
 * cairo_pattern_set_matrix:
 * @pattern: a #cairo_pattern_t
 * @matrix: a #cairo_matrix_t
 *
 * Sets the pattern's transformation matrix to @matrix. This matrix is
 * a transformation from user space to pattern space.
 *
 * When a pattern is first created it always has the identity matrix
 * for its transformation matrix, which means that pattern space is
 * initially identical to user space.
 *
 * Important: Please note that the direction of this transformation
 * matrix is from user space to pattern space. This means that if you
 * imagine the flow from a pattern to user space (and on to device
 * space), then coordinates in that flow will be transformed by the
 * inverse of the pattern matrix.
 *
 * For example, if you want to make a pattern appear twice as large as
 * it does by default the correct code to use is:
 *
 * <informalexample><programlisting>
 * cairo_matrix_init_scale (&amp;matrix, 0.5, 0.5);
 * cairo_pattern_set_matrix (pattern, &amp;matrix);
 * </programlisting></informalexample>
 *
 * Meanwhile, using values of 2.0 rather than 0.5 in the code above
 * would cause the pattern to appear at half of its default size.
 *
 * Also, please note the discussion of the user-space locking
 * semantics of cairo_set_source().
 *
 * Since: 1.0
 **/
void
18469
cairo_pattern_set_matrix (cairo_pattern_t      *pattern,
			  const cairo_matrix_t *matrix)
{
    cairo_matrix_t inverse;
    cairo_status_t status;
18469
    if (pattern->status)
11445
	return;
18469
    if (memcmp (&pattern->matrix, matrix, sizeof (cairo_matrix_t)) == 0)
11445
	return;
7024
    pattern->matrix = *matrix;
7024
    _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_MATRIX);
7024
    inverse = *matrix;
7024
    status = cairo_matrix_invert (&inverse);
7024
    if (unlikely (status))
9
	status = _cairo_pattern_set_error (pattern, status);
}
/**
 * cairo_pattern_get_matrix:
 * @pattern: a #cairo_pattern_t
 * @matrix: return value for the matrix
 *
 * Stores the pattern's transformation matrix into @matrix.
 *
 * Since: 1.0
 **/
void
cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
{
    *matrix = pattern->matrix;
}
/**
 * cairo_pattern_set_filter:
 * @pattern: a #cairo_pattern_t
 * @filter: a #cairo_filter_t describing the filter to use for resizing
 * the pattern
 *
 * Sets the filter to be used for resizing when using this pattern.
 * See #cairo_filter_t for details on each filter.
 *
 * * Note that you might want to control filtering even when you do not
 * have an explicit #cairo_pattern_t object, (for example when using
 * cairo_set_source_surface()). In these cases, it is convenient to
 * use cairo_get_source() to get access to the pattern that cairo
 * creates implicitly. For example:
 *
 * <informalexample><programlisting>
 * cairo_set_source_surface (cr, image, x, y);
 * cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
 * </programlisting></informalexample>
 *
 * Since: 1.0
 **/
void
1008
cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
{
1008
    if (pattern->status)
	return;
1008
    pattern->filter = filter;
1008
    _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_FILTER);
}
/**
 * cairo_pattern_get_filter:
 * @pattern: a #cairo_pattern_t
 *
 * Gets the current filter for a pattern.  See #cairo_filter_t
 * for details on each filter.
 *
 * Return value: the current filter used for resizing the pattern.
 *
 * Since: 1.0
 **/
cairo_filter_t
cairo_pattern_get_filter (cairo_pattern_t *pattern)
{
    return pattern->filter;
}
/**
 * cairo_pattern_get_dither:
 * @pattern: a #cairo_pattern_t
 *
 * Gets the current dithering mode, as set by
 * cairo_pattern_set_dither().
 *
 * Return value: the current dithering mode.
 *
 * Since: 1.18
 **/
cairo_dither_t
cairo_pattern_get_dither (cairo_pattern_t *pattern)
{
    return pattern->dither;
}
/**
 * cairo_pattern_set_dither:
 * @pattern: a #cairo_pattern_t
 * @dither: a #cairo_dither_t describing the new dithering mode
 *
 * Set the dithering mode of the rasterizer used for drawing shapes.
 * This value is a hint, and a particular backend may or may not support
 * a particular value.  At the current time, only pixman is supported.
 *
 * Since: 1.18
 **/
void
6
cairo_pattern_set_dither (cairo_pattern_t *pattern, cairo_dither_t dither)
{
6
    if (pattern->status)
        return;
6
    pattern->dither = dither;
6
    _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_DITHER);
}
/**
 * cairo_pattern_set_extend:
 * @pattern: a #cairo_pattern_t
 * @extend: a #cairo_extend_t describing how the area outside of the
 * pattern will be drawn
 *
 * Sets the mode to be used for drawing outside the area of a pattern.
 * See #cairo_extend_t for details on the semantics of each extend
 * strategy.
 *
 * The default extend mode is %CAIRO_EXTEND_NONE for surface patterns
 * and %CAIRO_EXTEND_PAD for gradient patterns.
 *
 * Since: 1.0
 **/
void
1362
cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
{
1362
    if (pattern->status)
	return;
1362
    pattern->extend = extend;
1362
    _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_EXTEND);
}
/**
 * cairo_pattern_get_extend:
 * @pattern: a #cairo_pattern_t
 *
 * Gets the current extend mode for a pattern.  See #cairo_extend_t
 * for details on the semantics of each extend strategy.
 *
 * Return value: the current extend strategy used for drawing the
 * pattern.
 *
 * Since: 1.0
 **/
cairo_extend_t
7
cairo_pattern_get_extend (cairo_pattern_t *pattern)
{
7
    return pattern->extend;
}
void
339
_cairo_pattern_pretransform (cairo_pattern_t	*pattern,
			     const cairo_matrix_t  *ctm)
{
339
    if (pattern->status)
	return;
339
    cairo_matrix_multiply (&pattern->matrix, &pattern->matrix, ctm);
}
void
462692
_cairo_pattern_transform (cairo_pattern_t	*pattern,
			  const cairo_matrix_t  *ctm_inverse)
{
462692
    if (pattern->status)
	return;
462692
    cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
}
static cairo_bool_t
972
_linear_pattern_is_degenerate (const cairo_linear_pattern_t *linear)
{
1104
    return fabs (linear->pd1.x - linear->pd2.x) < DBL_EPSILON &&
132
	   fabs (linear->pd1.y - linear->pd2.y) < DBL_EPSILON;
}
static cairo_bool_t
1890
_radial_pattern_is_degenerate (const cairo_radial_pattern_t *radial)
{
    /* A radial pattern is considered degenerate if it can be
     * represented as a solid or clear pattern.  This corresponds to
     * one of the two cases:
     *
     * 1) The radii are both very small:
     *      |dr| < DBL_EPSILON && min (r0, r1) < DBL_EPSILON
     *
     * 2) The two circles have about the same radius and are very
     *    close to each other (approximately a cylinder gradient that
     *    doesn't move with the parameter):
     *      |dr| < DBL_EPSILON && max (|dx|, |dy|) < 2 * DBL_EPSILON
     *
     * These checks are consistent with the assumptions used in
     * _cairo_radial_pattern_box_to_parameter ().
     */
2121
    return fabs (radial->cd1.radius - radial->cd2.radius) < DBL_EPSILON &&
231
	(MIN (radial->cd1.radius, radial->cd2.radius) < DBL_EPSILON ||
207
	 MAX (fabs (radial->cd1.center.x - radial->cd2.center.x),
12
	      fabs (radial->cd1.center.y - radial->cd2.center.y)) < 2 * DBL_EPSILON);
}
static void
3
_cairo_linear_pattern_box_to_parameter (const cairo_linear_pattern_t *linear,
					double x0, double y0,
					double x1, double y1,
					double range[2])
{
    double t0, tdx, tdy;
    double p1x, p1y, pdx, pdy, invsqnorm;
3
    assert (! _linear_pattern_is_degenerate (linear));
    /*
     * Linear gradients are othrogonal to the line passing through
     * their extremes. Because of convexity, the parameter range can
     * be computed as the convex hull (one the real line) of the
     * parameter values of the 4 corners of the box.
     *
     * The parameter value t for a point (x,y) can be computed as:
     *
     *   t = (p2 - p1) . (x,y) / |p2 - p1|^2
     *
     * t0  is the t value for the top left corner
     * tdx is the difference between left and right corners
     * tdy is the difference between top and bottom corners
     */
3
    p1x = linear->pd1.x;
3
    p1y = linear->pd1.y;
3
    pdx = linear->pd2.x - p1x;
3
    pdy = linear->pd2.y - p1y;
3
    invsqnorm = 1.0 / (pdx * pdx + pdy * pdy);
3
    pdx *= invsqnorm;
3
    pdy *= invsqnorm;
3
    t0 = (x0 - p1x) * pdx + (y0 - p1y) * pdy;
3
    tdx = (x1 - x0) * pdx;
3
    tdy = (y1 - y0) * pdy;
    /*
     * Because of the linearity of the t value, tdx can simply be
     * added the t0 to move along the top edge. After this, range[0]
     * and range[1] represent the parameter range for the top edge, so
     * extending it to include the whole box simply requires adding
     * tdy to the correct extreme.
     */
3
    range[0] = range[1] = t0;
3
    if (tdx < 0)
	range[0] += tdx;
    else
3
	range[1] += tdx;
3
    if (tdy < 0)
	range[0] += tdy;
    else
3
	range[1] += tdy;
3
}
static cairo_bool_t
_extend_range (double range[2], double value, cairo_bool_t valid)
{
    if (!valid)
	range[0] = range[1] = value;
    else if (value < range[0])
	range[0] = value;
    else if (value > range[1])
	range[1] = value;
    return TRUE;
}
/*
 * _cairo_radial_pattern_focus_is_inside:
 *
 * Returns %TRUE if and only if the focus point exists and is
 * contained in one of the two extreme circles. This condition is
 * equivalent to one of the two extreme circles being completely
 * contained in the other one.
 *
 * Note: if the focus is on the border of one of the two circles (in
 * which case the circles are tangent in the focus point), it is not
 * considered as contained in the circle, hence this function returns
 * %FALSE.
 *
 */
cairo_bool_t
_cairo_radial_pattern_focus_is_inside (const cairo_radial_pattern_t *radial)
{
    double cx, cy, cr, dx, dy, dr;
    cx = radial->cd1.center.x;
    cy = radial->cd1.center.y;
    cr = radial->cd1.radius;
    dx = radial->cd2.center.x - cx;
    dy = radial->cd2.center.y - cy;
    dr = radial->cd2.radius   - cr;
    return dx*dx + dy*dy < dr*dr;
}
static void
_cairo_radial_pattern_box_to_parameter (const cairo_radial_pattern_t *radial,
					double x0, double y0,
					double x1, double y1,
					double tolerance,
					double range[2])
{
    double cx, cy, cr, dx, dy, dr;
    double a, x_focus, y_focus;
    double mindr, minx, miny, maxx, maxy;
    cairo_bool_t valid;
    assert (! _radial_pattern_is_degenerate (radial));
    assert (x0 < x1);
    assert (y0 < y1);
    tolerance = MAX (tolerance, DBL_EPSILON);
    range[0] = range[1] = 0;
    valid = FALSE;
    x_focus = y_focus = 0; /* silence gcc */
    cx = radial->cd1.center.x;
    cy = radial->cd1.center.y;
    cr = radial->cd1.radius;
    dx = radial->cd2.center.x - cx;
    dy = radial->cd2.center.y - cy;
    dr = radial->cd2.radius   - cr;
    /* translate by -(cx, cy) to simplify computations */
    x0 -= cx;
    y0 -= cy;
    x1 -= cx;
    y1 -= cy;
    /* enlarge boundaries slightly to avoid rounding problems in the
     * parameter range computation */
    x0 -= DBL_EPSILON;
    y0 -= DBL_EPSILON;
    x1 += DBL_EPSILON;
    y1 += DBL_EPSILON;
    /* enlarge boundaries even more to avoid rounding problems when
     * testing if a point belongs to the box */
    minx = x0 - DBL_EPSILON;
    miny = y0 - DBL_EPSILON;
    maxx = x1 + DBL_EPSILON;
    maxy = y1 + DBL_EPSILON;
    /* we don't allow negative radiuses, so we will be checking that
     * t*dr >= mindr to consider t valid */
    mindr = -(cr + DBL_EPSILON);
    /*
     * After the previous transformations, the start circle is
     * centered in the origin and has radius cr. A 1-unit change in
     * the t parameter corresponds to dx,dy,dr changes in the x,y,r of
     * the circle (center coordinates, radius).
     *
     * To compute the minimum range needed to correctly draw the
     * pattern, we start with an empty range and extend it to include
     * the circles touching the bounding box or within it.
     */
    /*
     * Focus, the point where the circle has radius == 0.
     *
     * r = cr + t * dr = 0
     * t = -cr / dr
     *
     * If the radius is constant (dr == 0) there is no focus (the
     * gradient represents a cylinder instead of a cone).
     */
    if (fabs (dr) >= DBL_EPSILON) {
	double t_focus;
	t_focus = -cr / dr;
	x_focus = t_focus * dx;
	y_focus = t_focus * dy;
	if (minx <= x_focus && x_focus <= maxx &&
	    miny <= y_focus && y_focus <= maxy)
	{
	    valid = _extend_range (range, t_focus, valid);
	}
    }
    /*
     * Circles externally tangent to box edges.
     *
     * All circles have center in (dx, dy) * t
     *
     * If the circle is tangent to the line defined by the edge of the
     * box, then at least one of the following holds true:
     *
     *   (dx*t) + (cr + dr*t) == x0 (left   edge)
     *   (dx*t) - (cr + dr*t) == x1 (right  edge)
     *   (dy*t) + (cr + dr*t) == y0 (top    edge)
     *   (dy*t) - (cr + dr*t) == y1 (bottom edge)
     *
     * The solution is only valid if the tangent point is actually on
     * the edge, i.e. if its y coordinate is in [y0,y1] for left/right
     * edges and if its x coordinate is in [x0,x1] for top/bottom
     * edges.
     *
     * For the first equation:
     *
     *   (dx + dr) * t = x0 - cr
     *   t = (x0 - cr) / (dx + dr)
     *   y = dy * t
     *
     * in the code this becomes:
     *
     *   t_edge = (num) / (den)
     *   v = (delta) * t_edge
     *
     * If the denominator in t is 0, the pattern is tangent to a line
     * parallel to the edge under examination. The corner-case where
     * the boundary line is the same as the edge is handled by the
     * focus point case and/or by the a==0 case.
     */
#define T_EDGE(num,den,delta,lower,upper)				\
    if (fabs (den) >= DBL_EPSILON) {					\
	double t_edge, v;						\
									\
	t_edge = (num) / (den);						\
	v = t_edge * (delta);						\
	if (t_edge * dr >= mindr && (lower) <= v && v <= (upper))	\
	    valid = _extend_range (range, t_edge, valid);		\
    }
    /* circles tangent (externally) to left/right/top/bottom edge */
    T_EDGE (x0 - cr, dx + dr, dy, miny, maxy);
    T_EDGE (x1 + cr, dx - dr, dy, miny, maxy);
    T_EDGE (y0 - cr, dy + dr, dx, minx, maxx);
    T_EDGE (y1 + cr, dy - dr, dx, minx, maxx);
#undef T_EDGE
    /*
     * Circles passing through a corner.
     *
     * A circle passing through the point (x,y) satisfies:
     *
     * (x-t*dx)^2 + (y-t*dy)^2 == (cr + t*dr)^2
     *
     * If we set:
     *   a = dx^2 + dy^2 - dr^2
     *   b = x*dx + y*dy + cr*dr
     *   c = x^2 + y^2 - cr^2
     * we have:
     *   a*t^2 - 2*b*t + c == 0
     */
    a = dx * dx + dy * dy - dr * dr;
    if (fabs (a) < DBL_EPSILON * DBL_EPSILON) {
	double b, maxd2;
	/* Ensure that gradients with both a and dr small are
	 * considered degenerate.
	 * The floating point version of the degeneracy test implemented
	 * in _radial_pattern_is_degenerate() is:
	 *
	 *  1) The circles are practically the same size:
	 *     |dr| < DBL_EPSILON
	 *  AND
	 *  2a) The circles are both very small:
	 *      min (r0, r1) < DBL_EPSILON
	 *   OR
	 *  2b) The circles are very close to each other:
	 *      max (|dx|, |dy|) < 2 * DBL_EPSILON
	 *
	 * Assuming that the gradient is not degenerate, we want to
	 * show that |a| < DBL_EPSILON^2 implies |dr| >= DBL_EPSILON.
	 *
	 * If the gradient is not degenerate yet it has |dr| <
	 * DBL_EPSILON, (2b) is false, thus:
	 *
	 *   max (|dx|, |dy|) >= 2*DBL_EPSILON
	 * which implies:
	 *   4*DBL_EPSILON^2 <= max (|dx|, |dy|)^2 <= dx^2 + dy^2
	 *
	 * From the definition of a, we get:
	 *   a = dx^2 + dy^2 - dr^2 < DBL_EPSILON^2
	 *   dx^2 + dy^2 - DBL_EPSILON^2 < dr^2
	 *   3*DBL_EPSILON^2 < dr^2
	 *
	 * which is inconsistent with the hypotheses, thus |dr| <
	 * DBL_EPSILON is false or the gradient is degenerate.
	 */
	assert (fabs (dr) >= DBL_EPSILON);
	/*
	 * If a == 0, all the circles are tangent to a line in the
	 * focus point. If this line is within the box extents, we
	 * should add the circle with infinite radius, but this would
	 * make the range unbounded, so we add the smallest circle whose
	 * distance to the desired (degenerate) circle within the
	 * bounding box does not exceed tolerance.
	 *
	 * The equation of the line is b==0, i.e.:
	 *   x*dx + y*dy + cr*dr == 0
	 *
	 * We compute the intersection of the line with the box and
	 * keep the intersection with maximum square distance (maxd2)
	 * from the focus point.
	 *
	 * In the code the intersection is represented in another
	 * coordinate system, whose origin is the focus point and
	 * which has a u,v axes, which are respectively orthogonal and
	 * parallel to the edge being intersected.
	 *
	 * The intersection is valid only if it belongs to the box,
	 * otherwise it is ignored.
	 *
	 * For example:
	 *
	 *   y = y0
	 *   x*dx + y0*dy + cr*dr == 0
	 *   x = -(y0*dy + cr*dr) / dx
	 *
	 * which in (u,v) is:
	 *   u = y0 - y_focus
	 *   v = -(y0*dy + cr*dr) / dx - x_focus
	 *
	 * In the code:
	 *   u = (edge) - (u_origin)
	 *   v = -((edge) * (delta) + cr*dr) / (den) - v_focus
	 */
#define T_EDGE(edge,delta,den,lower,upper,u_origin,v_origin)	\
	if (fabs (den) >= DBL_EPSILON) {			\
	    double v;						\
								\
	    v = -((edge) * (delta) + cr * dr) / (den);		\
	    if ((lower) <= v && v <= (upper)) {			\
		double u, d2;					\
								\
		u = (edge) - (u_origin);			\
		v -= (v_origin);				\
		d2 = u*u + v*v;					\
		if (maxd2 < d2)					\
		    maxd2 = d2;					\
	    }							\
	}
	maxd2 = 0;
	/* degenerate circles (lines) passing through each edge */
	T_EDGE (y0, dy, dx, minx, maxx, y_focus, x_focus);
	T_EDGE (y1, dy, dx, minx, maxx, y_focus, x_focus);
	T_EDGE (x0, dx, dy, miny, maxy, x_focus, y_focus);
	T_EDGE (x1, dx, dy, miny, maxy, x_focus, y_focus);
#undef T_EDGE
	/*
	 * The limit circle can be transformed rigidly to the y=0 line
	 * and the circles tangent to it in (0,0) are:
	 *
	 *   x^2 + (y-r)^2 = r^2  <=>  x^2 + y^2 - 2*y*r = 0
	 *
	 * y is the distance from the line, in our case tolerance;
	 * x is the distance along the line, i.e. sqrt(maxd2),
	 * so:
	 *
	 *   r = cr + dr * t = (maxd2 + tolerance^2) / (2*tolerance)
	 *   t = (r - cr) / dr =
	 *       (maxd2 + tolerance^2 - 2*tolerance*cr) / (2*tolerance*dr)
	 */
	if (maxd2 > 0) {
	    double t_limit = maxd2 + tolerance*tolerance - 2*tolerance*cr;
	    t_limit /= 2 * tolerance * dr;
	    valid = _extend_range (range, t_limit, valid);
	}
	/*
	 * Nondegenerate, nonlimit circles passing through the corners.
	 *
	 * a == 0 && a*t^2 - 2*b*t + c == 0
	 *
	 * t = c / (2*b)
	 *
	 * The b == 0 case has just been handled, so we only have to
	 * compute this if b != 0.
	 */
#define T_CORNER(x,y)							\
	b = (x) * dx + (y) * dy + cr * dr;				\
	if (fabs (b) >= DBL_EPSILON) {					\
	    double t_corner;						\
	    double x2 = (x) * (x);					\
	    double y2 = (y) * (y);					\
	    double cr2 = (cr) * (cr);					\
	    double c = x2 + y2 - cr2;					\
	    								\
	    t_corner = 0.5 * c / b;					\
	    if (t_corner * dr >= mindr)					\
		valid = _extend_range (range, t_corner, valid);		\
	}
	/* circles touching each corner */
	T_CORNER (x0, y0);
	T_CORNER (x0, y1);
	T_CORNER (x1, y0);
	T_CORNER (x1, y1);
#undef T_CORNER
    } else {
	double inva, b, c, d;
	inva = 1 / a;
	/*
	 * Nondegenerate, nonlimit circles passing through the corners.
	 *
	 * a != 0 && a*t^2 - 2*b*t + c == 0
	 *
	 * t = (b +- sqrt (b*b - a*c)) / a
	 *
	 * If the argument of sqrt() is negative, then no circle
	 * passes through the corner.
	 */
#define T_CORNER(x,y)							\
	b = (x) * dx + (y) * dy + cr * dr;				\
	c = (x) * (x) + (y) * (y) - cr * cr;				\
	d = b * b - a * c;						\
	if (d >= 0) {							\
	    double t_corner;						\
									\
	    d = sqrt (d);						\
	    t_corner = (b + d) * inva;					\
	    if (t_corner * dr >= mindr)					\
		valid = _extend_range (range, t_corner, valid);		\
	    t_corner = (b - d) * inva;					\
	    if (t_corner * dr >= mindr)					\
		valid = _extend_range (range, t_corner, valid);		\
	}
	/* circles touching each corner */
	T_CORNER (x0, y0);
	T_CORNER (x0, y1);
	T_CORNER (x1, y0);
	T_CORNER (x1, y1);
#undef T_CORNER
    }
}
/**
 * _cairo_gradient_pattern_box_to_parameter:
 *
 * Compute a interpolation range sufficient to draw (within the given
 * tolerance) the gradient in the given box getting the same result as
 * using the (-inf, +inf) range.
 *
 * Assumes that the pattern is not degenerate. This can be guaranteed
 * by simplifying it to a solid clear if _cairo_pattern_is_clear or to
 * a solid color if _cairo_gradient_pattern_is_solid.
 *
 * The range isn't guaranteed to be minimal, but it tries to.
 **/
void
_cairo_gradient_pattern_box_to_parameter (const cairo_gradient_pattern_t *gradient,
					  double x0, double y0,
					  double x1, double y1,
					  double tolerance,
					  double out_range[2])
{
    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
	    gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
	_cairo_linear_pattern_box_to_parameter ((cairo_linear_pattern_t *) gradient,
						x0, y0, x1, y1, out_range);
    } else {
	_cairo_radial_pattern_box_to_parameter ((cairo_radial_pattern_t *) gradient,
						x0, y0, x1, y1, tolerance, out_range);
    }
}
/**
 * _cairo_gradient_pattern_interpolate:
 *
 * Interpolate between the start and end objects of linear or radial
 * gradients.  The interpolated object is stored in out_circle, with
 * the radius being zero in the linear gradient case.
 **/
void
_cairo_gradient_pattern_interpolate (const cairo_gradient_pattern_t *gradient,
				     double			     t,
				     cairo_circle_double_t	    *out_circle)
{
    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
	    gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
#define lerp(a,b) (a)*(1-t) + (b)*t
    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
	cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
	out_circle->center.x = lerp (linear->pd1.x, linear->pd2.x);
	out_circle->center.y = lerp (linear->pd1.y, linear->pd2.y);
	out_circle->radius = 0;
    } else {
	cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
	out_circle->center.x = lerp (radial->cd1.center.x, radial->cd2.center.x);
	out_circle->center.y = lerp (radial->cd1.center.y, radial->cd2.center.y);
	out_circle->radius   = lerp (radial->cd1.radius  , radial->cd2.radius);
    }
#undef lerp
}
/**
 * _cairo_gradient_pattern_fit_to_range:
 *
 * Scale the extremes of a gradient to guarantee that the coordinates
 * and their deltas are within the range (-max_value, max_value). The
 * new extremes are stored in out_circle.
 *
 * The pattern matrix is scaled to guarantee that the aspect of the
 * gradient is the same and the result is stored in out_matrix.
 *
 **/
void
1554
_cairo_gradient_pattern_fit_to_range (const cairo_gradient_pattern_t *gradient,
				      double			      max_value,
				      cairo_matrix_t                 *out_matrix,
				      cairo_circle_double_t	      out_circle[2])
{
    double dim;
1554
    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
	    gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
1554
    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
879
	cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
879
	out_circle[0].center = linear->pd1;
879
	out_circle[0].radius = 0;
879
	out_circle[1].center = linear->pd2;
879
	out_circle[1].radius = 0;
879
	dim = fabs (linear->pd1.x);
879
	dim = MAX (dim, fabs (linear->pd1.y));
879
	dim = MAX (dim, fabs (linear->pd2.x));
879
	dim = MAX (dim, fabs (linear->pd2.y));
879
	dim = MAX (dim, fabs (linear->pd1.x - linear->pd2.x));
879
	dim = MAX (dim, fabs (linear->pd1.y - linear->pd2.y));
    } else {
675
	cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
675
	out_circle[0] = radial->cd1;
675
	out_circle[1] = radial->cd2;
675
	dim = fabs (radial->cd1.center.x);
675
	dim = MAX (dim, fabs (radial->cd1.center.y));
675
	dim = MAX (dim, fabs (radial->cd1.radius));
675
	dim = MAX (dim, fabs (radial->cd2.center.x));
675
	dim = MAX (dim, fabs (radial->cd2.center.y));
675
	dim = MAX (dim, fabs (radial->cd2.radius));
675
	dim = MAX (dim, fabs (radial->cd1.center.x - radial->cd2.center.x));
675
	dim = MAX (dim, fabs (radial->cd1.center.y - radial->cd2.center.y));
675
	dim = MAX (dim, fabs (radial->cd1.radius   - radial->cd2.radius));
    }
1554
    dim = MAX (dim, fabs (gradient->base.matrix.xx));
1554
    dim = MAX (dim, fabs (gradient->base.matrix.xy));
1554
    dim = MAX (dim, fabs (gradient->base.matrix.x0));
1554
    dim = MAX (dim, fabs (gradient->base.matrix.yx));
1554
    dim = MAX (dim, fabs (gradient->base.matrix.yy));
1554
    dim = MAX (dim, fabs (gradient->base.matrix.y0));
1554
    if (unlikely (dim > max_value)) {
	cairo_matrix_t scale;
6
	dim = max_value / dim;
6
	out_circle[0].center.x *= dim;
6
	out_circle[0].center.y *= dim;
6
	out_circle[0].radius   *= dim;
6
	out_circle[1].center.x *= dim;
6
	out_circle[1].center.y *= dim;
6
	out_circle[1].radius   *= dim;
6
	cairo_matrix_init_scale (&scale, dim, dim);
6
	cairo_matrix_multiply (out_matrix, &gradient->base.matrix, &scale);
    } else {
1548
	*out_matrix = gradient->base.matrix;
    }
1554
}
static cairo_bool_t
3414
_gradient_is_clear (const cairo_gradient_pattern_t *gradient,
		    const cairo_rectangle_int_t *extents)
{
    unsigned int i;
3414
    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
	    gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
3414
    if (gradient->n_stops == 0 ||
3375
	(gradient->base.extend == CAIRO_EXTEND_NONE &&
285
	 gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
69
	return TRUE;
3345
    if (gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL) {
	/* degenerate radial gradients are clear */
1323
	if (_radial_pattern_is_degenerate ((cairo_radial_pattern_t *) gradient))
36
	    return TRUE;
2022
    } else if (gradient->base.extend == CAIRO_EXTEND_NONE) {
	/* EXTEND_NONE degenerate linear gradients are clear */
21
	if (_linear_pattern_is_degenerate ((cairo_linear_pattern_t *) gradient))
6
	    return TRUE;
    }
    /* Check if the extents intersect the drawn part of the pattern. */
3303
    if (extents != NULL &&
	(gradient->base.extend == CAIRO_EXTEND_NONE ||
	 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL))
    {
	double t[2];
	_cairo_gradient_pattern_box_to_parameter (gradient,
						  extents->x,
						  extents->y,
						  extents->x + extents->width,
						  extents->y + extents->height,
						  DBL_EPSILON,
						  t);
	if (gradient->base.extend == CAIRO_EXTEND_NONE &&
	    (t[0] >= gradient->stops[gradient->n_stops - 1].offset ||
	     t[1] <= gradient->stops[0].offset))
	{
		return TRUE;
	}
	if (t[0] == t[1])
	    return TRUE;
    }
3447
    for (i = 0; i < gradient->n_stops; i++)
3420
	if (! CAIRO_COLOR_IS_CLEAR (&gradient->stops[i].color))
3276
	    return FALSE;
27
    return TRUE;
}
static void
12
_gradient_color_average (const cairo_gradient_pattern_t *gradient,
			 cairo_color_t *color)
{
    double delta0, delta1;
    double r, g, b, a;
12
    unsigned int i, start = 1, end;
12
    assert (gradient->n_stops > 0);
12
    assert (gradient->base.extend != CAIRO_EXTEND_NONE);
12
    if (gradient->n_stops == 1) {
	_cairo_color_init_rgba (color,
				gradient->stops[0].color.red,
				gradient->stops[0].color.green,
				gradient->stops[0].color.blue,
				gradient->stops[0].color.alpha);
	return;
    }
12
    end = gradient->n_stops - 1;
12
    switch (gradient->base.extend) {
3
    case CAIRO_EXTEND_REPEAT:
      /*
       * Sa, Sb and Sy, Sz are the first two and last two stops respectively.
       * The weight of the first and last stop can be computed as the area of
       * the following triangles (taken with height 1, since the whole [0-1]
       * will have total weight 1 this way): b*h/2
       *
       *              +                   +
       *            / |\                / | \
       *          /   | \             /   |   \
       *        /     |  \          /     |     \
       * ~~~~~+---+---+---+~~~~~~~+-------+---+---+~~~~~
       *   -1+Sz  0  Sa   Sb      Sy     Sz   1  1+Sa
       *
       * For the first stop: (Sb-(-1+Sz)/2 = (1+Sb-Sz)/2
       * For the last stop: ((1+Sa)-Sy)/2 = (1+Sa-Sy)/2
       * Halving the result is done after summing up all the areas.
       */
3
	delta0 = 1.0 + gradient->stops[1].offset - gradient->stops[end].offset;
3
	delta1 = 1.0 + gradient->stops[0].offset - gradient->stops[end-1].offset;
3
	break;
3
    case CAIRO_EXTEND_REFLECT:
      /*
       * Sa, Sb and Sy, Sz are the first two and last two stops respectively.
       * The weight of the first and last stop can be computed as the area of
       * the following trapezoids (taken with height 1, since the whole [0-1]
       * will have total weight 1 this way): (b+B)*h/2
       *
       * +-------+                   +---+
       * |       |\                / |   |
       * |       | \             /   |   |
       * |       |  \          /     |   |
       * +-------+---+~~~~~~~+-------+---+
       * 0      Sa   Sb      Sy     Sz   1
       *
       * For the first stop: (Sa+Sb)/2
       * For the last stop: ((1-Sz) + (1-Sy))/2 = (2-Sy-Sz)/2
       * Halving the result is done after summing up all the areas.
       */
3
	delta0 = gradient->stops[0].offset + gradient->stops[1].offset;
3
	delta1 = 2.0 - gradient->stops[end-1].offset - gradient->stops[end].offset;
3
	break;
6
    case CAIRO_EXTEND_PAD:
      /* PAD is computed as the average of the first and last stop:
       *  - take both of them with weight 1 (they will be halved
       *    after the whole sum has been computed).
       *  - avoid summing any of the inner stops.
       */
6
	delta0 = delta1 = 1.0;
6
	start = end;
6
	break;
    case CAIRO_EXTEND_NONE:
    default:
	ASSERT_NOT_REACHED;
	_cairo_color_init_rgba (color, 0, 0, 0, 0);
	return;
    }
12
    r = delta0 * gradient->stops[0].color.red;
12
    g = delta0 * gradient->stops[0].color.green;
12
    b = delta0 * gradient->stops[0].color.blue;
12
    a = delta0 * gradient->stops[0].color.alpha;
18
    for (i = start; i < end; ++i) {
      /* Inner stops weight is the same as the area of the triangle they influence
       * (which goes from the stop before to the stop after), again with height 1
       * since the whole must sum up to 1: b*h/2
       * Halving is done after the whole sum has been computed.
       */
6
	double delta = gradient->stops[i+1].offset - gradient->stops[i-1].offset;
6
	r += delta * gradient->stops[i].color.red;
6
	g += delta * gradient->stops[i].color.green;
6
	b += delta * gradient->stops[i].color.blue;
6
	a += delta * gradient->stops[i].color.alpha;
    }
12
    r += delta1 * gradient->stops[end].color.red;
12
    g += delta1 * gradient->stops[end].color.green;
12
    b += delta1 * gradient->stops[end].color.blue;
12
    a += delta1 * gradient->stops[end].color.alpha;
12
    _cairo_color_init_rgba (color, r * .5, g * .5, b * .5, a * .5);
}
/**
 * _cairo_pattern_alpha_range:
 *
 * Convenience function to determine the minimum and maximum alpha in
 * the drawn part of a pattern (i.e. ignoring clear parts caused by
 * extend modes and/or pattern shape).
 *
 * If not NULL, out_min and out_max will be set respectively to the
 * minimum and maximum alpha value of the pattern.
 **/
void
20
_cairo_pattern_alpha_range (const cairo_pattern_t *pattern,
			    double                *out_min,
			    double                *out_max)
{
    double alpha_min, alpha_max;
20
    switch (pattern->type) {
20
    case CAIRO_PATTERN_TYPE_SOLID: {
20
	const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
20
	alpha_min = alpha_max = solid->color.alpha;
20
	break;
    }
    case CAIRO_PATTERN_TYPE_LINEAR:
    case CAIRO_PATTERN_TYPE_RADIAL: {
	const cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
	unsigned int i;
	assert (gradient->n_stops >= 1);
	alpha_min = alpha_max = gradient->stops[0].color.alpha;
	for (i = 1; i < gradient->n_stops; i++) {
	    if (alpha_min > gradient->stops[i].color.alpha)
		alpha_min = gradient->stops[i].color.alpha;
	    else if (alpha_max < gradient->stops[i].color.alpha)
		alpha_max = gradient->stops[i].color.alpha;
	}
	break;
    }
    case CAIRO_PATTERN_TYPE_MESH: {
	const cairo_mesh_pattern_t *mesh = (const cairo_mesh_pattern_t *) pattern;
	const cairo_mesh_patch_t *patch = _cairo_array_index_const (&mesh->patches, 0);
	unsigned int i, j, n = _cairo_array_num_elements (&mesh->patches);
	assert (n >= 1);
	alpha_min = alpha_max = patch[0].colors[0].alpha;
	for (i = 0; i < n; i++) {
	    for (j = 0; j < 4; j++) {
		if (patch[i].colors[j].alpha < alpha_min)
		    alpha_min = patch[i].colors[j].alpha;
		else if (patch[i].colors[j].alpha > alpha_max)
		    alpha_max = patch[i].colors[j].alpha;
	    }
	}
	break;
    }
    default:
	ASSERT_NOT_REACHED;
	/* fall through */
    case CAIRO_PATTERN_TYPE_SURFACE:
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
	alpha_min = 0;
	alpha_max = 1;
	break;
    }
20
    if (out_min)
20
	*out_min = alpha_min;
20
    if (out_max)
	*out_max = alpha_max;
20
}
/**
 * _cairo_mesh_pattern_coord_box:
 *
 * Convenience function to determine the range of the coordinates of
 * the points used to define the patches of the mesh.
 *
 * This is guaranteed to contain the pattern extents, but might not be
 * tight, just like a Bezier curve is always inside the convex hull of
 * the control points.
 *
 * This function cannot be used while the mesh is being constructed.
 *
 * The function returns TRUE and sets the output parameters to define
 * the coordinate range if the mesh pattern contains at least one
 * patch, otherwise it returns FALSE.
 **/
cairo_bool_t
33831
_cairo_mesh_pattern_coord_box (const cairo_mesh_pattern_t *mesh,
			       double                     *out_xmin,
			       double                     *out_ymin,
			       double                     *out_xmax,
			       double                     *out_ymax)
{
    const cairo_mesh_patch_t *patch;
    unsigned int num_patches, i, j, k;
    double x0, y0, x1, y1;
33831
    assert (mesh->current_patch == NULL);
33831
    num_patches = _cairo_array_num_elements (&mesh->patches);
33831
    if (num_patches == 0)
	return FALSE;
33831
    patch = _cairo_array_index_const (&mesh->patches, 0);
33831
    x0 = x1 = patch->points[0][0].x;
33831
    y0 = y1 = patch->points[0][0].y;
101529
    for (i = 0; i < num_patches; i++) {
338490
	for (j = 0; j < 4; j++) {
1353960
	    for (k = 0; k < 4; k++) {
1083168
		x0 = MIN (x0, patch[i].points[j][k].x);
1083168
		y0 = MIN (y0, patch[i].points[j][k].y);
1083168
		x1 = MAX (x1, patch[i].points[j][k].x);
1083168
		y1 = MAX (y1, patch[i].points[j][k].y);
	    }
	}
    }
33831
    *out_xmin = x0;
33831
    *out_ymin = y0;
33831
    *out_xmax = x1;
33831
    *out_ymax = y1;
33831
    return TRUE;
}
/**
 * _cairo_gradient_pattern_is_solid:
 *
 * Convenience function to determine whether a gradient pattern is
 * a solid color within the given extents. In this case the color
 * argument is initialized to the color the pattern represents.
 * This functions doesn't handle completely transparent gradients,
 * thus it should be called only after _cairo_pattern_is_clear has
 * returned FALSE.
 *
 * Return value: %TRUE if the pattern is a solid color.
 **/
cairo_bool_t
1449
_cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient,
				  const cairo_rectangle_int_t *extents,
				  cairo_color_t *color)
{
    unsigned int i;
1449
    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
	    gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
    /* TODO: radial */
1449
    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
936
	cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
936
	if (_linear_pattern_is_degenerate (linear)) {
12
	    _gradient_color_average (gradient, color);
12
	    return TRUE;
	}
924
	if (gradient->base.extend == CAIRO_EXTEND_NONE) {
	    double t[2];
	    /* We already know that the pattern is not clear, thus if some
	     * part of it is clear, the whole is not solid.
	     */
6
	    if (extents == NULL)
6
		return FALSE;
	    _cairo_linear_pattern_box_to_parameter (linear,
						    extents->x,
						    extents->y,
						    extents->x + extents->width,
						    extents->y + extents->height,
						    t);
	    if (t[0] < 0.0 || t[1] > 1.0)
		return FALSE;
	}
    } else
513
	return FALSE;
936
    for (i = 1; i < gradient->n_stops; i++)
894
	if (! _cairo_color_stop_equal (&gradient->stops[0].color,
894
				       &gradient->stops[i].color))
876
	    return FALSE;
42
    _cairo_color_init_rgba (color,
42
			    gradient->stops[0].color.red,
42
			    gradient->stops[0].color.green,
42
			    gradient->stops[0].color.blue,
42
			    gradient->stops[0].color.alpha);
42
    return TRUE;
}
/**
 * _cairo_pattern_is_constant_alpha:
 *
 * Convenience function to determine whether a pattern has constant
 * alpha within the given extents. In this case the alpha argument is
 * initialized to the alpha within the extents.
 *
 * Return value: %TRUE if the pattern has constant alpha.
 **/
cairo_bool_t
_cairo_pattern_is_constant_alpha (const cairo_pattern_t         *abstract_pattern,
				  const cairo_rectangle_int_t   *extents,
				  double                        *alpha)
{
    const cairo_pattern_union_t *pattern;
    cairo_color_t color;
    if (_cairo_pattern_is_clear (abstract_pattern)) {
	*alpha = 0.0;
	return TRUE;
    }
    if (_cairo_pattern_is_opaque (abstract_pattern, extents)) {
	*alpha = 1.0;
	return TRUE;
    }
    pattern = (cairo_pattern_union_t *) abstract_pattern;
    switch (pattern->base.type) {
    case CAIRO_PATTERN_TYPE_SOLID:
	*alpha = pattern->solid.color.alpha;
	return TRUE;
    case CAIRO_PATTERN_TYPE_LINEAR:
    case CAIRO_PATTERN_TYPE_RADIAL:
	if (_cairo_gradient_pattern_is_solid (&pattern->gradient.base, extents, &color)) {
	    *alpha = color.alpha;
	    return TRUE;
	} else {
	    return FALSE;
	}
	/* TODO: need to test these as well */
    case CAIRO_PATTERN_TYPE_SURFACE:
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
    case CAIRO_PATTERN_TYPE_MESH:
	return FALSE;
    }
    ASSERT_NOT_REACHED;
    return FALSE;
}
static cairo_bool_t
16929
_mesh_is_clear (const cairo_mesh_pattern_t *mesh)
{
    double x1, y1, x2, y2;
    cairo_bool_t is_valid;
16929
    is_valid = _cairo_mesh_pattern_coord_box (mesh, &x1, &y1, &x2, &y2);
16929
    if (!is_valid)
	return TRUE;
16929
    if (x2 - x1 < DBL_EPSILON || y2 - y1 < DBL_EPSILON)
	return TRUE;
16929
    return FALSE;
}
/**
 * _cairo_pattern_is_opaque_solid:
 *
 * Convenience function to determine whether a pattern is an opaque
 * (alpha==1.0) solid color pattern. This is done by testing whether
 * the pattern's alpha value when converted to a byte is 255, so if a
 * backend actually supported deep alpha channels this function might
 * not do the right thing.
 *
 * Return value: %TRUE if the pattern is an opaque, solid color.
 **/
cairo_bool_t
335245
_cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern)
{
    cairo_solid_pattern_t *solid;
335245
    if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
88433
	return FALSE;
246812
    solid = (cairo_solid_pattern_t *) pattern;
246812
    return CAIRO_COLOR_IS_OPAQUE (&solid->color);
}
static cairo_bool_t
37722
_surface_is_opaque (const cairo_surface_pattern_t *pattern,
		    const cairo_rectangle_int_t *sample)
{
    cairo_rectangle_int_t extents;
37722
    if (pattern->surface->content & CAIRO_CONTENT_ALPHA)
14989
	return FALSE;
22733
    if (pattern->base.extend != CAIRO_EXTEND_NONE)
22120
	return TRUE;
613
    if (! _cairo_surface_get_extents (pattern->surface, &extents))
	return TRUE;
613
    if (sample == NULL)
18
	return FALSE;
595
    return _cairo_rectangle_contains_rectangle (&extents, sample);
}
static cairo_bool_t
48
_raster_source_is_opaque (const cairo_raster_source_pattern_t *pattern,
			  const cairo_rectangle_int_t *sample)
{
48
    if (pattern->content & CAIRO_CONTENT_ALPHA)
24
	return FALSE;
24
    if (pattern->base.extend != CAIRO_EXTEND_NONE)
	return TRUE;
24
    if (sample == NULL)
	return FALSE;
24
    return _cairo_rectangle_contains_rectangle (&pattern->extents, sample);
}
static cairo_bool_t
695841
_surface_is_clear (const cairo_surface_pattern_t *pattern)
{
    cairo_rectangle_int_t extents;
695841
    if (_cairo_surface_get_extents (pattern->surface, &extents) &&
96301
	(extents.width == 0 || extents.height == 0))
30
	return TRUE;
696094
    return pattern->surface->is_clear &&
283
	pattern->surface->content & CAIRO_CONTENT_ALPHA;
}
static cairo_bool_t
96
_raster_source_is_clear (const cairo_raster_source_pattern_t *pattern)
{
96
    return pattern->extents.width == 0 || pattern->extents.height == 0;
}
static cairo_bool_t
1038
_gradient_is_opaque (const cairo_gradient_pattern_t *gradient,
		     const cairo_rectangle_int_t *sample)
{
    unsigned int i;
1038
    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
	    gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
1038
    if (gradient->n_stops == 0 ||
1011
	(gradient->base.extend == CAIRO_EXTEND_NONE &&
75
	 gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
27
	return FALSE;
1011
    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
603
	if (gradient->base.extend == CAIRO_EXTEND_NONE) {
	    double t[2];
6
	    cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
	    /* EXTEND_NONE degenerate radial gradients are clear */
6
	    if (_linear_pattern_is_degenerate (linear))
3
		return FALSE;
6
	    if (sample == NULL)
3
		return FALSE;
3
	    _cairo_linear_pattern_box_to_parameter (linear,
3
						    sample->x,
3
						    sample->y,
3
						    sample->x + sample->width,
3
						    sample->y + sample->height,
						    t);
3
	    if (t[0] < 0.0 || t[1] > 1.0)
		return FALSE;
	}
    } else
408
	return FALSE; /* TODO: check actual intersection */
1341
    for (i = 0; i < gradient->n_stops; i++)
1236
	if (! CAIRO_COLOR_IS_OPAQUE (&gradient->stops[i].color))
495
	    return FALSE;
105
    return TRUE;
}
/**
 * _cairo_pattern_is_opaque:
 *
 * Convenience function to determine whether a pattern is an opaque
 * pattern (of any type). The same caveats that apply to
 * _cairo_pattern_is_opaque_solid apply here as well.
 *
 * Return value: %TRUE if the pattern is a opaque.
 **/
cairo_bool_t
242735
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern,
			  const cairo_rectangle_int_t *sample)
{
    const cairo_pattern_union_t *pattern;
242735
    if (abstract_pattern->has_component_alpha)
	return FALSE;
242735
    pattern = (cairo_pattern_union_t *) abstract_pattern;
242735
    switch (pattern->base.type) {
187028
    case CAIRO_PATTERN_TYPE_SOLID:
187028
	return _cairo_pattern_is_opaque_solid (abstract_pattern);
37722
    case CAIRO_PATTERN_TYPE_SURFACE:
37722
	return _surface_is_opaque (&pattern->surface, sample);
48
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
48
	return _raster_source_is_opaque (&pattern->raster_source, sample);
1038
    case CAIRO_PATTERN_TYPE_LINEAR:
    case CAIRO_PATTERN_TYPE_RADIAL:
1038
	return _gradient_is_opaque (&pattern->gradient.base, sample);
16899
    case CAIRO_PATTERN_TYPE_MESH:
16899
	return FALSE;
    }
    ASSERT_NOT_REACHED;
    return FALSE;
}
cairo_bool_t
2114675
_cairo_pattern_is_clear (const cairo_pattern_t *abstract_pattern)
{
    const cairo_pattern_union_t *pattern;
2114675
    if (abstract_pattern->has_component_alpha)
	return FALSE;
2114675
    pattern = (cairo_pattern_union_t *) abstract_pattern;
2114675
    switch (abstract_pattern->type) {
1398395
    case CAIRO_PATTERN_TYPE_SOLID:
1398395
	return CAIRO_COLOR_IS_CLEAR (&pattern->solid.color);
695841
    case CAIRO_PATTERN_TYPE_SURFACE:
695841
	return _surface_is_clear (&pattern->surface);
96
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
96
	return _raster_source_is_clear (&pattern->raster_source);
3414
    case CAIRO_PATTERN_TYPE_LINEAR:
    case CAIRO_PATTERN_TYPE_RADIAL:
3414
	return _gradient_is_clear (&pattern->gradient.base, NULL);
16929
    case CAIRO_PATTERN_TYPE_MESH:
16929
	return _mesh_is_clear (&pattern->mesh);
    }
    ASSERT_NOT_REACHED;
    return FALSE;
}
/*
 * Will given row of back-translation matrix work with bilinear scale?
 * This is true for scales larger than 1. Also it was judged acceptable
 * for scales larger than .75. And if there is integer translation
 * then a scale of exactly .5 works.
 */
static int
168864
use_bilinear(double x, double y, double t)
{
    /* This is the inverse matrix! */
168864
    double h = x*x + y*y;
168864
    if (h < 1.0 / (0.75 * 0.75))
168726
	return TRUE; /* scale > .75 */
138
    if ((h > 3.99 && h < 4.01) /* scale is 1/2 */
72
	&& !_cairo_fixed_from_double(x*y) /* parallel to an axis */
45
	&& _cairo_fixed_is_integer (_cairo_fixed_from_double (t)))
42
	return TRUE;
96
    return FALSE;
}
/**
 * _cairo_pattern_analyze_filter:
 * @pattern: surface pattern
 *
 * Possibly optimize the filter to a simpler value depending on transformation
 *
 * Returns: the optimized #cairo_filter_t to use with @pattern.
 **/
cairo_filter_t
317914
_cairo_pattern_analyze_filter (const cairo_pattern_t *pattern)
{
317914
    switch (pattern->filter) {
289404
    case CAIRO_FILTER_GOOD:
    case CAIRO_FILTER_BEST:
    case CAIRO_FILTER_BILINEAR:
    case CAIRO_FILTER_FAST:
	/* If source pixels map 1:1 onto destination pixels, we do
	 * not need to filter (and do not want to filter, since it
	 * will cause blurriness)
	 */
289404
	if (_cairo_matrix_is_pixel_exact (&pattern->matrix)) {
198756
	    return CAIRO_FILTER_NEAREST;
	} else {
	    /* Use BILINEAR for any scale greater than .75 instead
	     * of GOOD. For scales of 1 and larger this is identical,
	     * for the smaller sizes it was judged that the artifacts
	     * were not worse than the artifacts from a box filer.
	     * BILINEAR can also be used if the scale is exactly .5
	     * and the translation in that direction is an integer.
	     */
175128
	    if (pattern->filter == CAIRO_FILTER_GOOD &&
84480
		use_bilinear (pattern->matrix.xx, pattern->matrix.xy,
168864
			      pattern->matrix.x0) &&
84384
		use_bilinear (pattern->matrix.yx, pattern->matrix.yy,
84384
			      pattern->matrix.y0))
84384
		return CAIRO_FILTER_BILINEAR;
	}
6264
	break;
28510
    case CAIRO_FILTER_NEAREST:
    case CAIRO_FILTER_GAUSSIAN:
    default:
28510
	break;
    }
34774
    return pattern->filter;
}
/**
 * _cairo_hypot:
 * Returns: value similar to hypot(@x,@y)
 *
 * May want to replace this with Manhattan distance (abs(x)+abs(y)) if
 * hypot is too slow, as there is no need for accuracy here.
 **/
static inline double
3756
_cairo_hypot(double x, double y)
{
3756
    return hypot(x, y);
}
/**
 * _cairo_pattern_sampled_area:
 *
 * Return region of @pattern that will be sampled to fill @extents,
 * based on the transformation and filter.
 *
 * This does not include pixels that are mulitiplied by values very
 * close to zero by the ends of filters. This is so that transforms
 * that should be the identity or 90 degree rotations do not expand
 * the source unexpectedly.
 *
 * XXX: We don't actually have any way of querying the backend for
 *      the filter radius, so we just guess base on what we know that
 *      backends do currently (see bug #10508)
 **/
void
317629
_cairo_pattern_sampled_area (const cairo_pattern_t *pattern,
			     const cairo_rectangle_int_t *extents,
			     cairo_rectangle_int_t *sample)
{
    double x1, x2, y1, y2;
    double padx, pady;
    /* Assume filters are interpolating, which means identity
       cannot change the image */
317629
    if (_cairo_matrix_is_identity (&pattern->matrix)) {
120374
	*sample = *extents;
120374
	return;
    }
    /* Transform the centers of the corner pixels */
197255
    x1 = extents->x + 0.5;
197255
    y1 = extents->y + 0.5;
197255
    x2 = x1 + (extents->width - 1);
197255
    y2 = y1 + (extents->height - 1);
197255
    _cairo_matrix_transform_bounding_box (&pattern->matrix,
					  &x1, &y1, &x2, &y2,
					  NULL);
    /* How far away from center will it actually sample?
     * This is the distance from a transformed pixel center to the
     * furthest sample of reasonable size.
     */
197255
    switch (pattern->filter) {
106910
    case CAIRO_FILTER_NEAREST:
    case CAIRO_FILTER_FAST:
	/* Correct value is zero, but when the sample is on an integer
	 * it is unknown if the backend will sample the pixel to the
	 * left or right. This value makes it include both possible pixels.
	 */
106910
	padx = pady = 0.004;
106910
	break;
90243
    case CAIRO_FILTER_BILINEAR:
    case CAIRO_FILTER_GAUSSIAN:
    default:
	/* Correct value is .5 */
90243
	padx = pady = 0.495;
90243
	break;
96
    case CAIRO_FILTER_GOOD:
	/* Correct value is max(width,1)*.5 */
96
	padx = _cairo_hypot (pattern->matrix.xx, pattern->matrix.xy);
96
	if (padx <= 1.0) padx = 0.495;
96
	else if (padx >= 16.0) padx = 7.92;
69
	else padx *= 0.495;
96
	pady = _cairo_hypot (pattern->matrix.yx, pattern->matrix.yy);
96
	if (pady <= 1.0) pady = 0.495;
93
	else if (pady >= 16.0) pady = 7.92;
75
	else pady *= 0.495;
96
	break;
6
    case CAIRO_FILTER_BEST:
	/* Correct value is width*2 */
6
	padx = _cairo_hypot (pattern->matrix.xx, pattern->matrix.xy) * 1.98;
6
	if (padx > 7.92) padx = 7.92;
6
	pady = _cairo_hypot (pattern->matrix.yx, pattern->matrix.yy) * 1.98;
6
	if (pady > 7.92) pady = 7.92;
6
	break;
    }
    /* round furthest samples to edge of pixels */
197255
    x1 = floor (x1 - padx);
197255
    if (x1 < CAIRO_RECT_INT_MIN) x1 = CAIRO_RECT_INT_MIN;
197255
    sample->x = x1;
197255
    y1 = floor (y1 - pady);
197255
    if (y1 < CAIRO_RECT_INT_MIN) y1 = CAIRO_RECT_INT_MIN;
197255
    sample->y = y1;
197255
    x2 = floor (x2 + padx) + 1.0;
197255
    if (x2 > CAIRO_RECT_INT_MAX) x2 = CAIRO_RECT_INT_MAX;
197255
    sample->width = x2 - x1;
197255
    y2 = floor (y2 + pady) + 1.0;
197255
    if (y2 > CAIRO_RECT_INT_MAX) y2 = CAIRO_RECT_INT_MAX;
197255
    sample->height = y2 - y1;
}
/**
 * _cairo_pattern_get_extents:
 *
 * Return the "target-space" extents of @pattern in @extents.
 *
 * For unbounded patterns, the @extents will be initialized with
 * "infinite" extents, (minimum and maximum fixed-point values).
 *
 * When is_vector is TRUE, avoid rounding to zero widths or heights that
 * are less than 1 unit.
 *
 * XXX: Currently, bounded gradient patterns will also return
 * "infinite" extents, though it would be possible to optimize these
 * with a little more work.
 **/
void
1184880
_cairo_pattern_get_extents (const cairo_pattern_t         *pattern,
			    cairo_rectangle_int_t         *extents,
			    cairo_bool_t                   is_vector)
{
    double x1, y1, x2, y2;
    int ix1, ix2, iy1, iy2;
1184880
    cairo_bool_t round_x = FALSE;
1184880
    cairo_bool_t round_y = FALSE;
1184880
    switch (pattern->type) {
866646
    case CAIRO_PATTERN_TYPE_SOLID:
866646
	goto UNBOUNDED;
299676
    case CAIRO_PATTERN_TYPE_SURFACE:
	{
	    cairo_rectangle_int_t surface_extents;
299676
	    const cairo_surface_pattern_t *surface_pattern =
		(const cairo_surface_pattern_t *) pattern;
299676
	    cairo_surface_t *surface = surface_pattern->surface;
299676
	    if (! _cairo_surface_get_extents (surface, &surface_extents))
286785
		goto UNBOUNDED;
75768
	    if (surface_extents.width == 0 || surface_extents.height == 0)
		goto EMPTY;
75768
	    if (pattern->extend != CAIRO_EXTEND_NONE)
62877
		goto UNBOUNDED;
12891
	    x1 = surface_extents.x;
12891
	    y1 = surface_extents.y;
12891
	    x2 = surface_extents.x + (int) surface_extents.width;
12891
	    y2 = surface_extents.y + (int) surface_extents.height;
12891
	    goto HANDLE_FILTER;
	}
	break;
48
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
	{
48
	    const cairo_raster_source_pattern_t *raster =
		(const cairo_raster_source_pattern_t *) pattern;
48
	    if (raster->extents.width == 0 || raster->extents.height == 0)
		goto EMPTY;
48
	    if (pattern->extend != CAIRO_EXTEND_NONE)
		goto UNBOUNDED;
48
	    x1 = raster->extents.x;
48
	    y1 = raster->extents.y;
48
	    x2 = raster->extents.x + (int) raster->extents.width;
48
	    y2 = raster->extents.y + (int) raster->extents.height;
	}
12939
    HANDLE_FILTER:
12939
	switch (pattern->filter) {
11157
	case CAIRO_FILTER_NEAREST:
	case CAIRO_FILTER_FAST:
11157
	    round_x = round_y = TRUE;
	    /* We don't know which way .5 will go, so fudge it slightly. */
11157
	    x1 -= 0.004;
11157
	    y1 -= 0.004;
11157
	    x2 += 0.004;
11157
	    y2 += 0.004;
11157
	    break;
6
	case CAIRO_FILTER_BEST:
	    /* Assume best filter will produce nice antialiased edges */
6
	    break;
1776
	case CAIRO_FILTER_BILINEAR:
	case CAIRO_FILTER_GAUSSIAN:
	case CAIRO_FILTER_GOOD:
	default:
	    /* These filters can blur the edge out 1/2 pixel when scaling up */
1776
	    if (_cairo_hypot (pattern->matrix.xx, pattern->matrix.yx) < 1.0) {
126
		x1 -= 0.5;
126
		x2 += 0.5;
126
		round_x = TRUE;
	    }
1776
	    if (_cairo_hypot (pattern->matrix.xy, pattern->matrix.yy) < 1.0) {
123
		y1 -= 0.5;
123
		y2 += 0.5;
123
		round_y = TRUE;
	    }
1776
	    break;
	}
12939
	break;
567
    case CAIRO_PATTERN_TYPE_RADIAL:
	{
567
	    const cairo_radial_pattern_t *radial =
		(const cairo_radial_pattern_t *) pattern;
	    double cx1, cy1;
	    double cx2, cy2;
	    double r1, r2;
567
	    if (_radial_pattern_is_degenerate (radial)) {
		/* cairo-gstate should have optimised degenerate
		 * patterns to solid clear patterns, so we can ignore
		 * them here. */
		goto EMPTY;
	    }
	    /* TODO: in some cases (focus outside/on the circle) it is
	     * half-bounded. */
567
	    if (pattern->extend != CAIRO_EXTEND_NONE)
477
		goto UNBOUNDED;
90
	    cx1 = radial->cd1.center.x;
90
	    cy1 = radial->cd1.center.y;
90
	    r1  = radial->cd1.radius;
90
	    cx2 = radial->cd2.center.x;
90
	    cy2 = radial->cd2.center.y;
90
	    r2  = radial->cd2.radius;
90
	    x1 = MIN (cx1 - r1, cx2 - r2);
90
	    y1 = MIN (cy1 - r1, cy2 - r2);
90
	    x2 = MAX (cx1 + r1, cx2 + r2);
90
	    y2 = MAX (cy1 + r1, cy2 + r2);
	}
90
	break;
1041
    case CAIRO_PATTERN_TYPE_LINEAR:
	{
1041
	    const cairo_linear_pattern_t *linear =
		(const cairo_linear_pattern_t *) pattern;
1041
	    if (pattern->extend != CAIRO_EXTEND_NONE)
1035
		goto UNBOUNDED;
6
	    if (_linear_pattern_is_degenerate (linear)) {
		/* cairo-gstate should have optimised degenerate
		 * patterns to solid ones, so we can again ignore
		 * them here. */
		goto EMPTY;
	    }
	    /* TODO: to get tight extents, use the matrix to transform
	     * the pattern instead of transforming the extents later. */
6
	    if (pattern->matrix.xy != 0. || pattern->matrix.yx != 0.)
		goto UNBOUNDED;
6
	    if (linear->pd1.x == linear->pd2.x) {
6
		x1 = -HUGE_VAL;
6
		x2 = HUGE_VAL;
6
		y1 = MIN (linear->pd1.y, linear->pd2.y);
6
		y2 = MAX (linear->pd1.y, linear->pd2.y);
	    } else if (linear->pd1.y == linear->pd2.y) {
		x1 = MIN (linear->pd1.x, linear->pd2.x);
		x2 = MAX (linear->pd1.x, linear->pd2.x);
		y1 = -HUGE_VAL;
		y2 = HUGE_VAL;
	    } else {
		goto  UNBOUNDED;
	    }
	    /* The current linear renderer just point-samples in the middle
	       of the pixels, similar to the NEAREST filter: */
6
	    round_x = round_y = TRUE;
	}
6
	break;
16902
    case CAIRO_PATTERN_TYPE_MESH:
	{
16902
	    const cairo_mesh_pattern_t *mesh =
		(const cairo_mesh_pattern_t *) pattern;
16902
	    if (! _cairo_mesh_pattern_coord_box (mesh, &x1, &y1, &x2, &y2))
		goto EMPTY;
	}
16902
	break;
    default:
	ASSERT_NOT_REACHED;
    }
29937
    if (_cairo_matrix_is_translation (&pattern->matrix)) {
23317
	x1 -= pattern->matrix.x0; x2 -= pattern->matrix.x0;
23317
	y1 -= pattern->matrix.y0; y2 -= pattern->matrix.y0;
    } else {
	cairo_matrix_t imatrix;
	cairo_status_t status;
6620
	imatrix = pattern->matrix;
6620
	status = cairo_matrix_invert (&imatrix);
	/* cairo_pattern_set_matrix ensures the matrix is invertible */
6620
	assert (status == CAIRO_STATUS_SUCCESS);
6620
	_cairo_matrix_transform_bounding_box (&imatrix,
					      &x1, &y1, &x2, &y2,
					      NULL);
    }
29937
    if (!round_x) {
18648
	x1 -= 0.5;
18648
	x2 += 0.5;
    }
29937
    if (x1 < CAIRO_RECT_INT_MIN)
6
	ix1 = CAIRO_RECT_INT_MIN;
    else 
29931
	ix1 = _cairo_lround (x1);
29937
    if (x2 > CAIRO_RECT_INT_MAX)
6
	ix2 = CAIRO_RECT_INT_MAX;
    else
29931
	ix2 = _cairo_lround (x2);
29937
    extents->x = ix1; extents->width  = ix2 - ix1;
29937
    if (is_vector && extents->width == 0 && x1 != x2)
	extents->width += 1;
29937
    if (!round_y) {
18651
	y1 -= 0.5;
18651
	y2 += 0.5;
    }
29937
    if (y1 < CAIRO_RECT_INT_MIN)
	iy1 = CAIRO_RECT_INT_MIN;
    else
29937
	iy1 = _cairo_lround (y1);
29937
    if (y2 > CAIRO_RECT_INT_MAX)
	iy2 = CAIRO_RECT_INT_MAX;
    else
29937
	iy2 = _cairo_lround (y2);
29937
    extents->y = iy1; extents->height = iy2 - iy1;
29937
    if (is_vector && extents->height == 0 && y1 != y2)
	extents->height += 1;
29937
    return;
1154943
  UNBOUNDED:
    /* unbounded patterns -> 'infinite' extents */
1154943
    _cairo_unbounded_rectangle_init (extents);
1154943
    return;
  EMPTY:
    extents->x = extents->y = 0;
    extents->width = extents->height = 0;
    return;
}
/**
 * _cairo_pattern_get_ink_extents:
 *
 * Return the "target-space" inked extents of @pattern in @extents.
 **/
cairo_int_status_t
_cairo_pattern_get_ink_extents (const cairo_pattern_t         *pattern,
				cairo_rectangle_int_t         *extents)
{
    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE &&
	pattern->extend == CAIRO_EXTEND_NONE)
    {
	const cairo_surface_pattern_t *surface_pattern =
	    (const cairo_surface_pattern_t *) pattern;
	cairo_surface_t *surface = surface_pattern->surface;
	surface = _cairo_surface_get_source (surface, NULL);
	if (_cairo_surface_is_recording (surface)) {
	    cairo_matrix_t imatrix;
	    cairo_box_t box;
	    cairo_status_t status;
	    imatrix = pattern->matrix;
	    status = cairo_matrix_invert (&imatrix);
	    /* cairo_pattern_set_matrix ensures the matrix is invertible */
	    assert (status == CAIRO_STATUS_SUCCESS);
	    status = _cairo_recording_surface_get_ink_bbox ((cairo_recording_surface_t *)surface,
						   &box, &imatrix);
	    if (unlikely (status))
		return status;
	    _cairo_box_round_to_rectangle (&box, extents);
	    return CAIRO_STATUS_SUCCESS;
	}
    }
    _cairo_pattern_get_extents (pattern, extents, TRUE);
    return CAIRO_STATUS_SUCCESS;
}
static uintptr_t
_cairo_solid_pattern_hash (uintptr_t hash,
			   const cairo_solid_pattern_t *solid)
{
    hash = _cairo_hash_bytes (hash, &solid->color, sizeof (solid->color));
    return hash;
}
static uintptr_t
_cairo_gradient_color_stops_hash (uintptr_t hash,
				  const cairo_gradient_pattern_t *gradient)
{
    unsigned int n;
    hash = _cairo_hash_bytes (hash,
			      &gradient->n_stops,
			      sizeof (gradient->n_stops));
    for (n = 0; n < gradient->n_stops; n++) {
	hash = _cairo_hash_bytes (hash,
				  &gradient->stops[n].offset,
				  sizeof (double));
	hash = _cairo_hash_bytes (hash,
				  &gradient->stops[n].color,
				  sizeof (cairo_color_stop_t));
    }
    return hash;
}
uintptr_t
_cairo_linear_pattern_hash (uintptr_t hash,
			    const cairo_linear_pattern_t *linear)
{
    hash = _cairo_hash_bytes (hash, &linear->pd1, sizeof (linear->pd1));
    hash = _cairo_hash_bytes (hash, &linear->pd2, sizeof (linear->pd2));
    return _cairo_gradient_color_stops_hash (hash, &linear->base);
}
uintptr_t
_cairo_radial_pattern_hash (uintptr_t hash,
			    const cairo_radial_pattern_t *radial)
{
    hash = _cairo_hash_bytes (hash, &radial->cd1.center, sizeof (radial->cd1.center));
    hash = _cairo_hash_bytes (hash, &radial->cd1.radius, sizeof (radial->cd1.radius));
    hash = _cairo_hash_bytes (hash, &radial->cd2.center, sizeof (radial->cd2.center));
    hash = _cairo_hash_bytes (hash, &radial->cd2.radius, sizeof (radial->cd2.radius));
    return _cairo_gradient_color_stops_hash (hash, &radial->base);
}
static uintptr_t
_cairo_mesh_pattern_hash (uintptr_t hash, const cairo_mesh_pattern_t *mesh)
{
    const cairo_mesh_patch_t *patch = _cairo_array_index_const (&mesh->patches, 0);
    unsigned int i, n = _cairo_array_num_elements (&mesh->patches);
    for (i = 0; i < n; i++)
       hash = _cairo_hash_bytes (hash, patch + i, sizeof (cairo_mesh_patch_t));
    return hash;
}
static uintptr_t
_cairo_surface_pattern_hash (uintptr_t hash,
			     const cairo_surface_pattern_t *surface)
{
    hash ^= surface->surface->unique_id;
    return hash;
}
static uintptr_t
_cairo_raster_source_pattern_hash (uintptr_t hash,
				   const cairo_raster_source_pattern_t *raster)
{
    hash ^= (uintptr_t)raster->user_data;
    return hash;
}
uintptr_t
_cairo_pattern_hash (const cairo_pattern_t *pattern)
{
    uintptr_t hash = _CAIRO_HASH_INIT_VALUE;
    if (pattern->status)
	return 0;
    hash = _cairo_hash_bytes (hash, &pattern->type, sizeof (pattern->type));
    if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
	hash = _cairo_hash_bytes (hash,
				  &pattern->matrix, sizeof (pattern->matrix));
	hash = _cairo_hash_bytes (hash,
				  &pattern->filter, sizeof (pattern->filter));
	hash = _cairo_hash_bytes (hash,
				  &pattern->extend, sizeof (pattern->extend));
	hash = _cairo_hash_bytes (hash,
				  &pattern->has_component_alpha,
				  sizeof (pattern->has_component_alpha));
    }
    switch (pattern->type) {
    case CAIRO_PATTERN_TYPE_SOLID:
	return _cairo_solid_pattern_hash (hash, (cairo_solid_pattern_t *) pattern);
    case CAIRO_PATTERN_TYPE_LINEAR:
	return _cairo_linear_pattern_hash (hash, (cairo_linear_pattern_t *) pattern);
    case CAIRO_PATTERN_TYPE_RADIAL:
	return _cairo_radial_pattern_hash (hash, (cairo_radial_pattern_t *) pattern);
    case CAIRO_PATTERN_TYPE_MESH:
	return _cairo_mesh_pattern_hash (hash, (cairo_mesh_pattern_t *) pattern);
    case CAIRO_PATTERN_TYPE_SURFACE:
	return _cairo_surface_pattern_hash (hash, (cairo_surface_pattern_t *) pattern);
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
	return _cairo_raster_source_pattern_hash (hash, (cairo_raster_source_pattern_t *) pattern);
    default:
	ASSERT_NOT_REACHED;
	return FALSE;
    }
}
static cairo_bool_t
1
_cairo_solid_pattern_equal (const cairo_solid_pattern_t *a,
			    const cairo_solid_pattern_t *b)
{
1
    return _cairo_color_equal (&a->color, &b->color);
}
static cairo_bool_t
_cairo_gradient_color_stops_equal (const cairo_gradient_pattern_t *a,
				   const cairo_gradient_pattern_t *b)
{
    unsigned int n;
    if (a->n_stops != b->n_stops)
	return FALSE;
    for (n = 0; n < a->n_stops; n++) {
	if (a->stops[n].offset != b->stops[n].offset)
	    return FALSE;
	if (! _cairo_color_stop_equal (&a->stops[n].color, &b->stops[n].color))
	    return FALSE;
    }
    return TRUE;
}
cairo_bool_t
_cairo_linear_pattern_equal (const cairo_linear_pattern_t *a,
			     const cairo_linear_pattern_t *b)
{
    if (a->pd1.x != b->pd1.x)
	return FALSE;
    if (a->pd1.y != b->pd1.y)
	return FALSE;
    if (a->pd2.x != b->pd2.x)
	return FALSE;
    if (a->pd2.y != b->pd2.y)
	return FALSE;
    return _cairo_gradient_color_stops_equal (&a->base, &b->base);
}
cairo_bool_t
_cairo_radial_pattern_equal (const cairo_radial_pattern_t *a,
			     const cairo_radial_pattern_t *b)
{
    if (a->cd1.center.x != b->cd1.center.x)
	return FALSE;
    if (a->cd1.center.y != b->cd1.center.y)
	return FALSE;
    if (a->cd1.radius != b->cd1.radius)
	return FALSE;
    if (a->cd2.center.x != b->cd2.center.x)
	return FALSE;
    if (a->cd2.center.y != b->cd2.center.y)
	return FALSE;
    if (a->cd2.radius != b->cd2.radius)
	return FALSE;
    return _cairo_gradient_color_stops_equal (&a->base, &b->base);
}
static cairo_bool_t
_cairo_mesh_pattern_equal (const cairo_mesh_pattern_t *a,
			   const cairo_mesh_pattern_t *b)
{
    const cairo_mesh_patch_t *patch_a, *patch_b;
    unsigned int i, num_patches_a, num_patches_b;
    num_patches_a = _cairo_array_num_elements (&a->patches);
    num_patches_b = _cairo_array_num_elements (&b->patches);
    if (num_patches_a != num_patches_b)
	return FALSE;
    for (i = 0; i < num_patches_a; i++) {
	patch_a = _cairo_array_index_const (&a->patches, i);
	patch_b = _cairo_array_index_const (&b->patches, i);
	if (memcmp (patch_a, patch_b, sizeof(cairo_mesh_patch_t)) != 0)
	    return FALSE;
    }
    return TRUE;
}
static cairo_bool_t
_cairo_surface_pattern_equal (const cairo_surface_pattern_t *a,
			      const cairo_surface_pattern_t *b)
{
    return a->surface->unique_id == b->surface->unique_id;
}
static cairo_bool_t
_cairo_raster_source_pattern_equal (const cairo_raster_source_pattern_t *a,
				    const cairo_raster_source_pattern_t *b)
{
    return a->user_data == b->user_data;
}
cairo_bool_t
2
_cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b)
{
2
    if (a->status || b->status)
	return FALSE;
2
    if (a == b)
	return TRUE;
2
    if (a->type != b->type)
1
	return FALSE;
1
    if (a->has_component_alpha != b->has_component_alpha)
	return FALSE;
1
    if (a->type != CAIRO_PATTERN_TYPE_SOLID) {
	if (memcmp (&a->matrix, &b->matrix, sizeof (cairo_matrix_t)))
	    return FALSE;
	if (a->filter != b->filter)
	    return FALSE;
	if (a->extend != b->extend)
	    return FALSE;
    }
1
    switch (a->type) {
1
    case CAIRO_PATTERN_TYPE_SOLID:
1
	return _cairo_solid_pattern_equal ((cairo_solid_pattern_t *) a,
					   (cairo_solid_pattern_t *) b);
    case CAIRO_PATTERN_TYPE_LINEAR:
	return _cairo_linear_pattern_equal ((cairo_linear_pattern_t *) a,
					    (cairo_linear_pattern_t *) b);
    case CAIRO_PATTERN_TYPE_RADIAL:
	return _cairo_radial_pattern_equal ((cairo_radial_pattern_t *) a,
					    (cairo_radial_pattern_t *) b);
    case CAIRO_PATTERN_TYPE_MESH:
	return _cairo_mesh_pattern_equal ((cairo_mesh_pattern_t *) a,
					  (cairo_mesh_pattern_t *) b);
    case CAIRO_PATTERN_TYPE_SURFACE:
	return _cairo_surface_pattern_equal ((cairo_surface_pattern_t *) a,
					     (cairo_surface_pattern_t *) b);
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
	return _cairo_raster_source_pattern_equal ((cairo_raster_source_pattern_t *) a,
						   (cairo_raster_source_pattern_t *) b);
    default:
	ASSERT_NOT_REACHED;
	return FALSE;
    }
}
/**
 * cairo_pattern_get_rgba:
 * @pattern: a #cairo_pattern_t
 * @red: return value for red component of color, or %NULL
 * @green: return value for green component of color, or %NULL
 * @blue: return value for blue component of color, or %NULL
 * @alpha: return value for alpha component of color, or %NULL
 *
 * Gets the solid color for a solid color pattern.
 *
 * Note that the color and alpha values are not premultiplied.
 *
 * Return value: %CAIRO_STATUS_SUCCESS, or
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid
 * color pattern.
 *
 * Since: 1.4
 **/
cairo_status_t
63
cairo_pattern_get_rgba (cairo_pattern_t *pattern,
			double *red, double *green,
			double *blue, double *alpha)
{
63
    cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
    double r0, g0, b0, a0;
63
    if (pattern->status)
	return pattern->status;
63
    if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
63
    _cairo_color_get_rgba (&solid->color, &r0, &g0, &b0, &a0);
63
    if (red)
63
	*red = r0;
63
    if (green)
63
	*green = g0;
63
    if (blue)
63
	*blue = b0;
63
    if (alpha)
63
	*alpha = a0;
63
    return CAIRO_STATUS_SUCCESS;
}
/**
 * cairo_pattern_get_surface:
 * @pattern: a #cairo_pattern_t
 * @surface: return value for surface of pattern, or %NULL
 *
 * Gets the surface of a surface pattern.  The reference returned in
 * @surface is owned by the pattern; the caller should call
 * cairo_surface_reference() if the surface is to be retained.
 *
 * Return value: %CAIRO_STATUS_SUCCESS, or
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a surface
 * pattern.
 *
 * Since: 1.4
 **/
cairo_status_t
3
cairo_pattern_get_surface (cairo_pattern_t *pattern,
			   cairo_surface_t **surface)
{
3
    cairo_surface_pattern_t *spat = (cairo_surface_pattern_t*) pattern;
3
    if (pattern->status)
	return pattern->status;
3
    if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
3
    if (surface)
3
	*surface = spat->surface;
3
    return CAIRO_STATUS_SUCCESS;
}
/**
 * cairo_pattern_get_color_stop_rgba:
 * @pattern: a #cairo_pattern_t
 * @index: index of the stop to return data for
 * @offset: return value for the offset of the stop, or %NULL
 * @red: return value for red component of color, or %NULL
 * @green: return value for green component of color, or %NULL
 * @blue: return value for blue component of color, or %NULL
 * @alpha: return value for alpha component of color, or %NULL
 *
 * Gets the color and offset information at the given @index for a
 * gradient pattern.  Values of @index range from 0 to n-1
 * where n is the number returned
 * by cairo_pattern_get_color_stop_count().
 *
 * Note that the color and alpha values are not premultiplied.
 *
 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
 * if @index is not valid for the given pattern.  If the pattern is
 * not a gradient pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
 * returned.
 *
 * Since: 1.4
 **/
cairo_status_t
12
cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
				   int index, double *offset,
				   double *red, double *green,
				   double *blue, double *alpha)
{
12
    cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
12
    if (pattern->status)
	return pattern->status;
12
    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
	pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
12
    if (index < 0 || (unsigned int) index >= gradient->n_stops)
3
	return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
9
    if (offset)
9
	*offset = gradient->stops[index].offset;
9
    if (red)
9
	*red = gradient->stops[index].color.red;
9
    if (green)
9
	*green = gradient->stops[index].color.green;
9
    if (blue)
9
	*blue = gradient->stops[index].color.blue;
9
    if (alpha)
9
	*alpha = gradient->stops[index].color.alpha;
9
    return CAIRO_STATUS_SUCCESS;
}
/**
 * cairo_pattern_get_color_stop_count:
 * @pattern: a #cairo_pattern_t
 * @count: return value for the number of color stops, or %NULL
 *
 * Gets the number of color stops specified in the given gradient
 * pattern.
 *
 * Return value: %CAIRO_STATUS_SUCCESS, or
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
 * pattern.
 *
 * Since: 1.4
 **/
cairo_status_t
3
cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
				    int *count)
{
3
    cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
3
    if (pattern->status)
	return pattern->status;
3
    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
	pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
3
    if (count)
3
	*count = gradient->n_stops;
3
    return CAIRO_STATUS_SUCCESS;
}
/**
 * cairo_pattern_get_linear_points:
 * @pattern: a #cairo_pattern_t
 * @x0: return value for the x coordinate of the first point, or %NULL
 * @y0: return value for the y coordinate of the first point, or %NULL
 * @x1: return value for the x coordinate of the second point, or %NULL
 * @y1: return value for the y coordinate of the second point, or %NULL
 *
 * Gets the gradient endpoints for a linear gradient.
 *
 * Return value: %CAIRO_STATUS_SUCCESS, or
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a linear
 * gradient pattern.
 *
 * Since: 1.4
 **/
cairo_status_t
3
cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
				 double *x0, double *y0,
				 double *x1, double *y1)
{
3
    cairo_linear_pattern_t *linear = (cairo_linear_pattern_t*) pattern;
3
    if (pattern->status)
	return pattern->status;
3
    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR)
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
3
    if (x0)
3
	*x0 = linear->pd1.x;
3
    if (y0)
3
	*y0 = linear->pd1.y;
3
    if (x1)
3
	*x1 = linear->pd2.x;
3
    if (y1)
3
	*y1 = linear->pd2.y;
3
    return CAIRO_STATUS_SUCCESS;
}
/**
 * cairo_pattern_get_radial_circles:
 * @pattern: a #cairo_pattern_t
 * @x0: return value for the x coordinate of the center of the first circle, or %NULL
 * @y0: return value for the y coordinate of the center of the first circle, or %NULL
 * @r0: return value for the radius of the first circle, or %NULL
 * @x1: return value for the x coordinate of the center of the second circle, or %NULL
 * @y1: return value for the y coordinate of the center of the second circle, or %NULL
 * @r1: return value for the radius of the second circle, or %NULL
 *
 * Gets the gradient endpoint circles for a radial gradient, each
 * specified as a center coordinate and a radius.
 *
 * Return value: %CAIRO_STATUS_SUCCESS, or
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial
 * gradient pattern.
 *
 * Since: 1.4
 **/
cairo_status_t
3
cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
				  double *x0, double *y0, double *r0,
				  double *x1, double *y1, double *r1)
{
3
    cairo_radial_pattern_t *radial = (cairo_radial_pattern_t*) pattern;
3
    if (pattern->status)
	return pattern->status;
3
    if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
3
    if (x0)
3
	*x0 = radial->cd1.center.x;
3
    if (y0)
3
	*y0 = radial->cd1.center.y;
3
    if (r0)
3
	*r0 = radial->cd1.radius;
3
    if (x1)
3
	*x1 = radial->cd2.center.x;
3
    if (y1)
3
	*y1 = radial->cd2.center.y;
3
    if (r1)
3
	*r1 = radial->cd2.radius;
3
    return CAIRO_STATUS_SUCCESS;
}
/**
 * cairo_mesh_pattern_get_patch_count:
 * @pattern: a #cairo_pattern_t
 * @count: return value for the number patches, or %NULL
 *
 * Gets the number of patches specified in the given mesh pattern.
 *
 * The number only includes patches which have been finished by
 * calling cairo_mesh_pattern_end_patch(). For example it will be 0
 * during the definition of the first patch.
 *
 * Return value: %CAIRO_STATUS_SUCCESS, or
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a mesh
 * pattern.
 *
 * Since: 1.12
 **/
cairo_status_t
12
cairo_mesh_pattern_get_patch_count (cairo_pattern_t *pattern,
				    unsigned int *count)
{
12
    cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
12
    if (unlikely (pattern->status))
	return pattern->status;
12
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH))
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
12
    if (count) {
12
	*count = _cairo_array_num_elements (&mesh->patches);
12
	if (mesh->current_patch)
3
	    *count -= 1;
    }
12
    return CAIRO_STATUS_SUCCESS;
}
/**
 * cairo_mesh_pattern_get_path:
 * @pattern: a #cairo_pattern_t
 * @patch_num: the patch number to return data for
 *
 * Gets path defining the patch @patch_num for a mesh
 * pattern.
 *
 * @patch_num can range from 0 to n-1 where n is the number returned by
 * cairo_mesh_pattern_get_patch_count().
 *
 * Return value: the path defining the patch, or a path with status
 * %CAIRO_STATUS_INVALID_INDEX if @patch_num or @point_num is not
 * valid for @pattern. If @pattern is not a mesh pattern, a path with
 * status %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is returned.
 *
 * Since: 1.12
 **/
cairo_path_t *
cairo_mesh_pattern_get_path (cairo_pattern_t *pattern,
			     unsigned int patch_num)
{
    cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
    const cairo_mesh_patch_t *patch;
    cairo_path_t *path;
    cairo_path_data_t *data;
    unsigned int patch_count;
    int l, current_point;
    if (unlikely (pattern->status))
	return _cairo_path_create_in_error (pattern->status);
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH))
	return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH));
    patch_count = _cairo_array_num_elements (&mesh->patches);
    if (mesh->current_patch)
	patch_count--;
    if (unlikely (patch_num >= patch_count))
	return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_INDEX));
    patch = _cairo_array_index_const (&mesh->patches, patch_num);
    path = _cairo_calloc (sizeof (cairo_path_t));
    if (path == NULL)
	return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
    path->num_data = 18;
    path->data = _cairo_calloc_ab (path->num_data,
				   sizeof (cairo_path_data_t));
    if (path->data == NULL) {
	free (path);
	return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
    }
    data = path->data;
    data[0].header.type = CAIRO_PATH_MOVE_TO;
    data[0].header.length = 2;
    data[1].point.x = patch->points[0][0].x;
    data[1].point.y = patch->points[0][0].y;
    data += data[0].header.length;
    current_point = 0;
    for (l = 0; l < 4; l++) {
	int i, j, k;
	data[0].header.type = CAIRO_PATH_CURVE_TO;
	data[0].header.length = 4;
	for (k = 1; k < 4; k++) {
	    current_point = (current_point + 1) % 12;
	    i = mesh_path_point_i[current_point];
	    j = mesh_path_point_j[current_point];
	    data[k].point.x = patch->points[i][j].x;
	    data[k].point.y = patch->points[i][j].y;
	}
	data += data[0].header.length;
    }
    path->status = CAIRO_STATUS_SUCCESS;
    return path;
}
/**
 * cairo_mesh_pattern_get_corner_color_rgba:
 * @pattern: a #cairo_pattern_t
 * @patch_num: the patch number to return data for
 * @corner_num: the corner number to return data for
 * @red: return value for red component of color, or %NULL
 * @green: return value for green component of color, or %NULL
 * @blue: return value for blue component of color, or %NULL
 * @alpha: return value for alpha component of color, or %NULL
 *
 * Gets the color information in corner @corner_num of patch
 * @patch_num for a mesh pattern.
 *
 * @patch_num can range from 0 to n-1 where n is the number returned by
 * cairo_mesh_pattern_get_patch_count().
 *
 * Valid values for @corner_num are from 0 to 3 and identify the
 * corners as explained in cairo_pattern_create_mesh().
 *
 * Note that the color and alpha values are not premultiplied.
 *
 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
 * if @patch_num or @corner_num is not valid for @pattern. If
 * @pattern is not a mesh pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH
 * is returned.
 *
 * Since: 1.12
 **/
cairo_status_t
12
cairo_mesh_pattern_get_corner_color_rgba (cairo_pattern_t *pattern,
					  unsigned int patch_num,
					  unsigned int corner_num,
					  double *red, double *green,
					  double *blue, double *alpha)
{
12
    cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
    unsigned int patch_count;
    const cairo_mesh_patch_t *patch;
12
    if (unlikely (pattern->status))
	return pattern->status;
12
    if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH))
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
12
    if (unlikely (corner_num > 3))
	return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
12
    patch_count = _cairo_array_num_elements (&mesh->patches);
12
    if (mesh->current_patch)
	patch_count--;
12
    if (unlikely (patch_num >= patch_count))
	return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
12
    patch = _cairo_array_index_const (&mesh->patches, patch_num);
12
    if (red)
12
	*red = patch->colors[corner_num].red;
12
    if (green)
12
	*green = patch->colors[corner_num].green;
12
    if (blue)
12
	*blue = patch->colors[corner_num].blue;
12
    if (alpha)
12
	*alpha = patch->colors[corner_num].alpha;
12
    return CAIRO_STATUS_SUCCESS;
}
/**
 * cairo_mesh_pattern_get_control_point:
 * @pattern: a #cairo_pattern_t
 * @patch_num: the patch number to return data for
 * @point_num: the control point number to return data for
 * @x: return value for the x coordinate of the control point, or %NULL
 * @y: return value for the y coordinate of the control point, or %NULL
 *
 * Gets the control point @point_num of patch @patch_num for a mesh
 * pattern.
 *
 * @patch_num can range from 0 to n-1 where n is the number returned by
 * cairo_mesh_pattern_get_patch_count().
 *
 * Valid values for @point_num are from 0 to 3 and identify the
 * control points as explained in cairo_pattern_create_mesh().
 *
 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
 * if @patch_num or @point_num is not valid for @pattern. If @pattern
 * is not a mesh pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
 * returned.
 *
 * Since: 1.12
 **/
cairo_status_t
36
cairo_mesh_pattern_get_control_point (cairo_pattern_t *pattern,
				      unsigned int patch_num,
				      unsigned int point_num,
				      double *x, double *y)
{
36
    cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
    const cairo_mesh_patch_t *patch;
    unsigned int patch_count;
    int i, j;
36
    if (pattern->status)
	return pattern->status;
36
    if (pattern->type != CAIRO_PATTERN_TYPE_MESH)
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
36
    if (point_num > 3)
	return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
36
    patch_count = _cairo_array_num_elements (&mesh->patches);
36
    if (mesh->current_patch)
	patch_count--;
36
    if (unlikely (patch_num >= patch_count))
	return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
36
    patch = _cairo_array_index_const (&mesh->patches, patch_num);
36
    i = mesh_control_point_i[point_num];
36
    j = mesh_control_point_j[point_num];
36
    if (x)
36
	*x = patch->points[i][j].x;
36
    if (y)
36
	*y = patch->points[i][j].y;
36
    return CAIRO_STATUS_SUCCESS;
}
void
608
_cairo_pattern_reset_static_data (void)
{
    int i;
3648
    for (i = 0; i < ARRAY_LENGTH (freed_pattern_pool); i++)
3040
	_freed_pool_reset (&freed_pattern_pool[i]);
608
}
static void
_cairo_debug_print_surface_pattern (FILE *file,
				    const cairo_surface_pattern_t *pattern)
{
    const char *s;
    switch (pattern->surface->type) {
    case CAIRO_SURFACE_TYPE_IMAGE: s = "image"; break;
    case CAIRO_SURFACE_TYPE_PDF: s = "pdf"; break;
    case CAIRO_SURFACE_TYPE_PS: s = "ps"; break;
    case CAIRO_SURFACE_TYPE_XLIB: s = "xlib"; break;
    case CAIRO_SURFACE_TYPE_XCB: s = "xcb"; break;
    case CAIRO_SURFACE_TYPE_GLITZ: s = "glitz"; break;
    case CAIRO_SURFACE_TYPE_QUARTZ: s = "quartz"; break;
    case CAIRO_SURFACE_TYPE_WIN32: s = "win32"; break;
    case CAIRO_SURFACE_TYPE_BEOS: s = "beos"; break;
    case CAIRO_SURFACE_TYPE_DIRECTFB: s = "directfb"; break;
    case CAIRO_SURFACE_TYPE_SVG: s = "svg"; break;
    case CAIRO_SURFACE_TYPE_OS2: s = "os2"; break;
    case CAIRO_SURFACE_TYPE_WIN32_PRINTING: s = "win32_printing"; break;
    case CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: s = "quartz_image"; break;
    case CAIRO_SURFACE_TYPE_SCRIPT: s = "script"; break;
    case CAIRO_SURFACE_TYPE_QT: s = "qt"; break;
    case CAIRO_SURFACE_TYPE_RECORDING: s = "recording"; break;
    case CAIRO_SURFACE_TYPE_VG: s = "vg"; break;
    case CAIRO_SURFACE_TYPE_GL: s = "gl"; break;
    case CAIRO_SURFACE_TYPE_DRM: s = "drm"; break;
    case CAIRO_SURFACE_TYPE_TEE: s = "tee"; break;
    case CAIRO_SURFACE_TYPE_XML: s = "xml"; break;
    case CAIRO_SURFACE_TYPE_SKIA: s = "skia"; break; /* Deprecated */
    case CAIRO_SURFACE_TYPE_SUBSURFACE: s = "subsurface"; break;
    case CAIRO_SURFACE_TYPE_COGL: s = "cogl"; break;
    default: s = "invalid"; ASSERT_NOT_REACHED; break;
    }
    fprintf (file, "  surface type: %s\n", s);
}
static void
_cairo_debug_print_raster_source_pattern (FILE *file,
					  const cairo_raster_source_pattern_t *raster)
{
    fprintf (file, "  content: %x, size %dx%d\n", raster->content, raster->extents.width, raster->extents.height);
}
static void
_cairo_debug_print_linear_pattern (FILE *file,
				    const cairo_linear_pattern_t *pattern)
{
}
static void
_cairo_debug_print_radial_pattern (FILE *file,
				   const cairo_radial_pattern_t *pattern)
{
}
static void
_cairo_debug_print_mesh_pattern (FILE *file,
				 const cairo_mesh_pattern_t *pattern)
{
}
void
_cairo_debug_print_pattern (FILE *file, const cairo_pattern_t *pattern)
{
    const char *s;
    switch (pattern->type) {
    case CAIRO_PATTERN_TYPE_SOLID: s = "solid"; break;
    case CAIRO_PATTERN_TYPE_SURFACE: s = "surface"; break;
    case CAIRO_PATTERN_TYPE_LINEAR: s = "linear"; break;
    case CAIRO_PATTERN_TYPE_RADIAL: s = "radial"; break;
    case CAIRO_PATTERN_TYPE_MESH: s = "mesh"; break;
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE: s = "raster"; break;
    default: s = "invalid"; ASSERT_NOT_REACHED; break;
    }
    fprintf (file, "pattern: %s\n", s);
    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
	return;
    switch (pattern->extend) {
    case CAIRO_EXTEND_NONE: s = "none"; break;
    case CAIRO_EXTEND_REPEAT: s = "repeat"; break;
    case CAIRO_EXTEND_REFLECT: s = "reflect"; break;
    case CAIRO_EXTEND_PAD: s = "pad"; break;
    default: s = "invalid"; ASSERT_NOT_REACHED; break;
    }
    fprintf (file, "  extend: %s\n", s);
    switch (pattern->filter) {
    case CAIRO_FILTER_FAST: s = "fast"; break;
    case CAIRO_FILTER_GOOD: s = "good"; break;
    case CAIRO_FILTER_BEST: s = "best"; break;
    case CAIRO_FILTER_NEAREST: s = "nearest"; break;
    case CAIRO_FILTER_BILINEAR: s = "bilinear"; break;
    case CAIRO_FILTER_GAUSSIAN: s = "gaussian"; break;
    default: s = "invalid"; ASSERT_NOT_REACHED; break;
    }
    fprintf (file, "  filter: %s\n", s);
    fprintf (file, "  matrix: [%g %g %g %g %g %g]\n",
	     pattern->matrix.xx, pattern->matrix.yx,
	     pattern->matrix.xy, pattern->matrix.yy,
	     pattern->matrix.x0, pattern->matrix.y0);
    switch (pattern->type) {
    default:
    case CAIRO_PATTERN_TYPE_SOLID:
	break;
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
	_cairo_debug_print_raster_source_pattern (file, (cairo_raster_source_pattern_t *)pattern);
	break;
    case CAIRO_PATTERN_TYPE_SURFACE:
	_cairo_debug_print_surface_pattern (file, (cairo_surface_pattern_t *)pattern);
	break;
    case CAIRO_PATTERN_TYPE_LINEAR:
	_cairo_debug_print_linear_pattern (file, (cairo_linear_pattern_t *)pattern);
	break;
    case CAIRO_PATTERN_TYPE_RADIAL:
	_cairo_debug_print_radial_pattern (file, (cairo_radial_pattern_t *)pattern);
	break;
    case CAIRO_PATTERN_TYPE_MESH:
	_cairo_debug_print_mesh_pattern (file, (cairo_mesh_pattern_t *)pattern);
	break;
    }
}