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
4
* Copyright Ā© 2004 David Reveman
5
* Copyright Ā© 2005 Red Hat, Inc.
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.
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.
26
* Authors: David Reveman <davidr@novell.com>
27
* Keith Packard <keithp@keithp.com>
28
* Carl Worth <cworth@cworth.org>
33
const cairo_solid_pattern_t _cairo_pattern_nil = {
34
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
35
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
36
CAIRO_STATUS_NO_MEMORY, /* status */
37
{ 0, 0, 0, NULL }, /* user_data */
38
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
39
CAIRO_FILTER_DEFAULT, /* filter */
40
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
43
static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = {
44
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
45
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
46
CAIRO_STATUS_NULL_POINTER, /* status */
47
{ 0, 0, 0, NULL }, /* user_data */
48
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
49
CAIRO_FILTER_DEFAULT, /* filter */
50
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
53
const cairo_solid_pattern_t _cairo_pattern_none = {
54
{ CAIRO_PATTERN_TYPE_SOLID, /* type */
55
CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
56
CAIRO_STATUS_SUCCESS, /* status */
57
{ 0, 0, 0, NULL }, /* user_data */
58
{ 1., 0., 0., 1., 0., 0., }, /* matrix */
59
CAIRO_FILTER_DEFAULT, /* filter */
60
CAIRO_EXTEND_GRADIENT_DEFAULT }, /* extend */
64
* _cairo_pattern_set_error:
66
* @status: a status value indicating an error
68
* Atomically sets pattern->status to @status and calls _cairo_error;
69
* Does nothing if status is %CAIRO_STATUS_SUCCESS.
71
* All assignments of an error status to pattern->status should happen
72
* through _cairo_pattern_set_error(). Note that due to the nature of
73
* the atomic operation, it is not safe to call this function on the nil
76
* The purpose of this function is to allow the user to set a
77
* breakpoint in _cairo_error() to generate a stack trace for when the
78
* user causes cairo to detect an error.
81
_cairo_pattern_set_error (cairo_pattern_t *pattern,
82
cairo_status_t status)
84
if (status == CAIRO_STATUS_SUCCESS)
87
/* Don't overwrite an existing error. This preserves the first
88
* error, which is the most significant. */
89
_cairo_status_set_error (&pattern->status, status);
91
return _cairo_error (status);
95
_cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
98
pattern->status = CAIRO_STATUS_SUCCESS;
100
/* Set the reference count to zero for on-stack patterns.
101
* Callers needs to explicitly increment the count for heap allocations. */
102
CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
104
_cairo_user_data_array_init (&pattern->user_data);
106
if (type == CAIRO_PATTERN_TYPE_SURFACE)
107
pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
109
pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT;
111
pattern->filter = CAIRO_FILTER_DEFAULT;
113
cairo_matrix_init_identity (&pattern->matrix);
116
static cairo_status_t
117
_cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
118
const cairo_gradient_pattern_t *other)
120
if (other->base.type == CAIRO_PATTERN_TYPE_LINEAR)
122
cairo_linear_pattern_t *dst = (cairo_linear_pattern_t *) pattern;
123
cairo_linear_pattern_t *src = (cairo_linear_pattern_t *) other;
129
cairo_radial_pattern_t *dst = (cairo_radial_pattern_t *) pattern;
130
cairo_radial_pattern_t *src = (cairo_radial_pattern_t *) other;
135
if (other->stops == other->stops_embedded)
136
pattern->stops = pattern->stops_embedded;
137
else if (other->stops)
139
pattern->stops = _cairo_malloc_ab (other->stops_size,
140
sizeof (cairo_gradient_stop_t));
141
if (pattern->stops == NULL) {
142
pattern->stops_size = 0;
143
pattern->n_stops = 0;
144
return _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
147
memcpy (pattern->stops, other->stops,
148
other->n_stops * sizeof (cairo_gradient_stop_t));
151
return CAIRO_STATUS_SUCCESS;
155
_cairo_pattern_init_copy (cairo_pattern_t *pattern,
156
const cairo_pattern_t *other)
159
return _cairo_pattern_set_error (pattern, other->status);
161
switch (other->type) {
162
case CAIRO_PATTERN_TYPE_SOLID: {
163
cairo_solid_pattern_t *dst = (cairo_solid_pattern_t *) pattern;
164
cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) other;
168
case CAIRO_PATTERN_TYPE_SURFACE: {
169
cairo_surface_pattern_t *dst = (cairo_surface_pattern_t *) pattern;
170
cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) other;
173
cairo_surface_reference (dst->surface);
175
case CAIRO_PATTERN_TYPE_LINEAR:
176
case CAIRO_PATTERN_TYPE_RADIAL: {
177
cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern;
178
cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other;
179
cairo_status_t status;
181
status = _cairo_gradient_pattern_init_copy (dst, src);
188
/* The reference count and user_data array are unique to the copy. */
189
CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
190
_cairo_user_data_array_init (&pattern->user_data);
192
return CAIRO_STATUS_SUCCESS;
196
_cairo_pattern_init_snapshot (cairo_pattern_t *pattern,
197
const cairo_pattern_t *other)
199
cairo_status_t status;
201
/* We don't bother doing any fancy copy-on-write implementation
202
* for the pattern's data. It's generally quite tiny. */
203
status = _cairo_pattern_init_copy (pattern, other);
207
/* But we do let the surface snapshot stuff be as fancy as it
208
* would like to be. */
209
if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
210
cairo_surface_pattern_t *surface_pattern =
211
(cairo_surface_pattern_t *) pattern;
212
cairo_surface_t *surface = surface_pattern->surface;
214
surface_pattern->surface = _cairo_surface_snapshot (surface);
216
cairo_surface_destroy (surface);
218
if (surface_pattern->surface->status)
219
return surface_pattern->surface->status;
222
return CAIRO_STATUS_SUCCESS;
226
_cairo_pattern_fini (cairo_pattern_t *pattern)
228
_cairo_user_data_array_fini (&pattern->user_data);
230
switch (pattern->type) {
231
case CAIRO_PATTERN_TYPE_SOLID:
233
case CAIRO_PATTERN_TYPE_SURFACE: {
234
cairo_surface_pattern_t *surface_pattern =
235
(cairo_surface_pattern_t *) pattern;
237
cairo_surface_destroy (surface_pattern->surface);
239
case CAIRO_PATTERN_TYPE_LINEAR:
240
case CAIRO_PATTERN_TYPE_RADIAL: {
241
cairo_gradient_pattern_t *gradient =
242
(cairo_gradient_pattern_t *) pattern;
244
if (gradient->stops && gradient->stops != gradient->stops_embedded)
245
free (gradient->stops);
251
_cairo_pattern_create_copy (cairo_pattern_t **pattern,
252
const cairo_pattern_t *other)
254
cairo_status_t status;
257
return other->status;
259
switch (other->type) {
260
case CAIRO_PATTERN_TYPE_SOLID:
261
*pattern = malloc (sizeof (cairo_solid_pattern_t));
263
case CAIRO_PATTERN_TYPE_SURFACE:
264
*pattern = malloc (sizeof (cairo_surface_pattern_t));
266
case CAIRO_PATTERN_TYPE_LINEAR:
267
*pattern = malloc (sizeof (cairo_linear_pattern_t));
269
case CAIRO_PATTERN_TYPE_RADIAL:
270
*pattern = malloc (sizeof (cairo_radial_pattern_t));
273
if (*pattern == NULL)
274
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
276
status = _cairo_pattern_init_copy (*pattern, other);
282
CAIRO_REFERENCE_COUNT_INIT (&(*pattern)->ref_count, 1);
284
return CAIRO_STATUS_SUCCESS;
289
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
290
const cairo_color_t *color,
291
cairo_content_t content)
293
if (content == CAIRO_CONTENT_COLOR_ALPHA && CAIRO_COLOR_IS_OPAQUE (color))
294
content = CAIRO_CONTENT_COLOR;
296
_cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
297
pattern->color = *color;
298
pattern->content = content;
302
_cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern,
303
cairo_surface_t *surface)
305
if (surface->status) {
306
/* Force to solid to simplify the pattern_fini process. */
307
_cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
308
_cairo_pattern_set_error (&pattern->base, surface->status);
312
_cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SURFACE);
314
pattern->surface = cairo_surface_reference (surface);
318
_cairo_pattern_init_gradient (cairo_gradient_pattern_t *pattern,
319
cairo_pattern_type_t type)
321
_cairo_pattern_init (&pattern->base, type);
323
pattern->n_stops = 0;
324
pattern->stops_size = 0;
325
pattern->stops = NULL;
329
_cairo_pattern_init_linear (cairo_linear_pattern_t *pattern,
330
double x0, double y0, double x1, double y1)
332
_cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_LINEAR);
334
pattern->p1.x = _cairo_fixed_from_double (x0);
335
pattern->p1.y = _cairo_fixed_from_double (y0);
336
pattern->p2.x = _cairo_fixed_from_double (x1);
337
pattern->p2.y = _cairo_fixed_from_double (y1);
341
_cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
342
double cx0, double cy0, double radius0,
343
double cx1, double cy1, double radius1)
345
_cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL);
347
pattern->c1.x = _cairo_fixed_from_double (cx0);
348
pattern->c1.y = _cairo_fixed_from_double (cy0);
349
pattern->r1 = _cairo_fixed_from_double (fabs (radius0));
350
pattern->c2.x = _cairo_fixed_from_double (cx1);
351
pattern->c2.y = _cairo_fixed_from_double (cy1);
352
pattern->r2 = _cairo_fixed_from_double (fabs (radius1));
355
/* We use a small freed pattern cache here, because we don't want to
356
* constantly reallocate simple colors. */
357
#define MAX_PATTERN_CACHE_SIZE 4
359
cairo_solid_pattern_t *patterns[MAX_PATTERN_CACHE_SIZE];
361
} solid_pattern_cache;
364
_cairo_pattern_create_solid (const cairo_color_t *color,
365
cairo_content_t content)
367
cairo_solid_pattern_t *pattern = NULL;
369
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
371
if (solid_pattern_cache.size) {
372
int i = --solid_pattern_cache.size %
373
ARRAY_LENGTH (solid_pattern_cache.patterns);
374
pattern = solid_pattern_cache.patterns[i];
375
solid_pattern_cache.patterns[i] = NULL;
378
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock);
380
if (pattern == NULL) {
381
/* None cached, need to create a new pattern. */
382
pattern = malloc (sizeof (cairo_solid_pattern_t));
385
if (pattern == NULL) {
386
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
387
pattern = (cairo_solid_pattern_t *) &_cairo_pattern_nil;
389
_cairo_pattern_init_solid (pattern, color, content);
390
CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
393
return &pattern->base;
397
_cairo_pattern_reset_solid_pattern_cache (void)
401
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
403
for (i = 0; i < MIN (ARRAY_LENGTH (solid_pattern_cache.patterns), solid_pattern_cache.size); i++) {
404
if (solid_pattern_cache.patterns[i])
405
free (solid_pattern_cache.patterns[i]);
406
solid_pattern_cache.patterns[i] = NULL;
408
solid_pattern_cache.size = 0;
410
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock);
413
static const cairo_pattern_t *
414
_cairo_pattern_create_in_error (cairo_status_t status)
416
cairo_pattern_t *pattern;
418
if (status == CAIRO_STATUS_NO_MEMORY)
419
return (cairo_pattern_t *)&_cairo_pattern_nil.base;
421
CAIRO_MUTEX_INITIALIZE ();
423
pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK, CAIRO_CONTENT_COLOR);
424
if (pattern->status == CAIRO_STATUS_SUCCESS)
425
status = _cairo_pattern_set_error (pattern, status);
431
* cairo_pattern_create_rgb:
432
* @red: red component of the color
433
* @green: green component of the color
434
* @blue: blue component of the color
436
* Creates a new #cairo_pattern_t corresponding to an opaque color. The
437
* color components are floating point numbers in the range 0 to 1.
438
* If the values passed in are outside that range, they will be
441
* Return value: the newly created #cairo_pattern_t if successful, or
442
* an error pattern in case of no memory. The caller owns the
443
* returned object and should call cairo_pattern_destroy() when
446
* This function will always return a valid pointer, but if an error
447
* occurred the pattern status will be set to an error. To inspect
448
* the status of a pattern use cairo_pattern_status().
451
cairo_pattern_create_rgb (double red, double green, double blue)
455
_cairo_restrict_value (&red, 0.0, 1.0);
456
_cairo_restrict_value (&green, 0.0, 1.0);
457
_cairo_restrict_value (&blue, 0.0, 1.0);
459
_cairo_color_init_rgb (&color, red, green, blue);
461
CAIRO_MUTEX_INITIALIZE ();
463
return _cairo_pattern_create_solid (&color, CAIRO_CONTENT_COLOR);
465
slim_hidden_def (cairo_pattern_create_rgb);
468
* cairo_pattern_create_rgba:
469
* @red: red component of the color
470
* @green: green component of the color
471
* @blue: blue component of the color
472
* @alpha: alpha component of the color
474
* Creates a new #cairo_pattern_t corresponding to a translucent color.
475
* The color components are floating point numbers in the range 0 to
476
* 1. If the values passed in are outside that range, they will be
479
* Return value: the newly created #cairo_pattern_t if successful, or
480
* an error pattern in case of no memory. The caller owns the
481
* returned object and should call cairo_pattern_destroy() when
484
* This function will always return a valid pointer, but if an error
485
* occurred the pattern status will be set to an error. To inspect
486
* the status of a pattern use cairo_pattern_status().
489
cairo_pattern_create_rgba (double red, double green, double blue,
494
_cairo_restrict_value (&red, 0.0, 1.0);
495
_cairo_restrict_value (&green, 0.0, 1.0);
496
_cairo_restrict_value (&blue, 0.0, 1.0);
497
_cairo_restrict_value (&alpha, 0.0, 1.0);
499
_cairo_color_init_rgba (&color, red, green, blue, alpha);
501
CAIRO_MUTEX_INITIALIZE ();
503
return _cairo_pattern_create_solid (&color, CAIRO_CONTENT_COLOR_ALPHA);
505
slim_hidden_def (cairo_pattern_create_rgba);
508
* cairo_pattern_create_for_surface:
509
* @surface: the surface
511
* Create a new #cairo_pattern_t for the given surface.
513
* Return value: the newly created #cairo_pattern_t if successful, or
514
* an error pattern in case of no memory. The caller owns the
515
* returned object and should call cairo_pattern_destroy() when
518
* This function will always return a valid pointer, but if an error
519
* occurred the pattern status will be set to an error. To inspect
520
* the status of a pattern use cairo_pattern_status().
523
cairo_pattern_create_for_surface (cairo_surface_t *surface)
525
cairo_surface_pattern_t *pattern;
527
if (surface == NULL) {
528
_cairo_error_throw (CAIRO_STATUS_NULL_POINTER);
529
return (cairo_pattern_t*) &_cairo_pattern_nil_null_pointer;
533
return (cairo_pattern_t*) _cairo_pattern_create_in_error (surface->status);
535
pattern = malloc (sizeof (cairo_surface_pattern_t));
536
if (pattern == NULL) {
537
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
538
return (cairo_pattern_t *)&_cairo_pattern_nil.base;
541
CAIRO_MUTEX_INITIALIZE ();
543
_cairo_pattern_init_for_surface (pattern, surface);
544
CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
546
return &pattern->base;
548
slim_hidden_def (cairo_pattern_create_for_surface);
551
* cairo_pattern_create_linear:
552
* @x0: x coordinate of the start point
553
* @y0: y coordinate of the start point
554
* @x1: x coordinate of the end point
555
* @y1: y coordinate of the end point
557
* Create a new linear gradient #cairo_pattern_t along the line defined
558
* by (x0, y0) and (x1, y1). Before using the gradient pattern, a
559
* number of color stops should be defined using
560
* cairo_pattern_add_color_stop_rgb() or
561
* cairo_pattern_add_color_stop_rgba().
563
* Note: The coordinates here are in pattern space. For a new pattern,
564
* pattern space is identical to user space, but the relationship
565
* between the spaces can be changed with cairo_pattern_set_matrix().
567
* Return value: the newly created #cairo_pattern_t if successful, or
568
* an error pattern in case of no memory. The caller owns the
569
* returned object and should call cairo_pattern_destroy() when
572
* This function will always return a valid pointer, but if an error
573
* occurred the pattern status will be set to an error. To inspect
574
* the status of a pattern use cairo_pattern_status().
577
cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
579
cairo_linear_pattern_t *pattern;
581
pattern = malloc (sizeof (cairo_linear_pattern_t));
582
if (pattern == NULL) {
583
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
584
return (cairo_pattern_t *) &_cairo_pattern_nil.base;
587
CAIRO_MUTEX_INITIALIZE ();
589
_cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
590
CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
592
return &pattern->base.base;
596
* cairo_pattern_create_radial:
597
* @cx0: x coordinate for the center of the start circle
598
* @cy0: y coordinate for the center of the start circle
599
* @radius0: radius of the start circle
600
* @cx1: x coordinate for the center of the end circle
601
* @cy1: y coordinate for the center of the end circle
602
* @radius1: radius of the end circle
604
* Creates a new radial gradient #cairo_pattern_t between the two
605
* circles defined by (cx0, cy0, radius0) and (cx1, cy1, radius1). Before using the
606
* gradient pattern, a number of color stops should be defined using
607
* cairo_pattern_add_color_stop_rgb() or
608
* cairo_pattern_add_color_stop_rgba().
610
* Note: The coordinates here are in pattern space. For a new pattern,
611
* pattern space is identical to user space, but the relationship
612
* between the spaces can be changed with cairo_pattern_set_matrix().
614
* Return value: the newly created #cairo_pattern_t if successful, or
615
* an error pattern in case of no memory. The caller owns the
616
* returned object and should call cairo_pattern_destroy() when
619
* This function will always return a valid pointer, but if an error
620
* occurred the pattern status will be set to an error. To inspect
621
* the status of a pattern use cairo_pattern_status().
624
cairo_pattern_create_radial (double cx0, double cy0, double radius0,
625
double cx1, double cy1, double radius1)
627
cairo_radial_pattern_t *pattern;
629
pattern = malloc (sizeof (cairo_radial_pattern_t));
630
if (pattern == NULL) {
631
_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
632
return (cairo_pattern_t *) &_cairo_pattern_nil.base;
635
CAIRO_MUTEX_INITIALIZE ();
637
_cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
638
CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
640
return &pattern->base.base;
644
* cairo_pattern_reference:
645
* @pattern: a #cairo_pattern_t
647
* Increases the reference count on @pattern by one. This prevents
648
* @pattern from being destroyed until a matching call to
649
* cairo_pattern_destroy() is made.
651
* The number of references to a #cairo_pattern_t can be get using
652
* cairo_pattern_get_reference_count().
654
* Return value: the referenced #cairo_pattern_t.
657
cairo_pattern_reference (cairo_pattern_t *pattern)
659
if (pattern == NULL ||
660
CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
663
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
665
_cairo_reference_count_inc (&pattern->ref_count);
669
slim_hidden_def (cairo_pattern_reference);
672
* cairo_pattern_get_type:
673
* @pattern: a #cairo_pattern_t
675
* This function returns the type a pattern.
676
* See #cairo_pattern_type_t for available types.
678
* Return value: The type of @pattern.
683
cairo_pattern_get_type (cairo_pattern_t *pattern)
685
return pattern->type;
687
slim_hidden_def (cairo_pattern_get_type);
690
* cairo_pattern_status:
691
* @pattern: a #cairo_pattern_t
693
* Checks whether an error has previously occurred for this
696
* Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NO_MEMORY, or
697
* %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
700
cairo_pattern_status (cairo_pattern_t *pattern)
702
return pattern->status;
704
slim_hidden_def (cairo_pattern_status);
707
* cairo_pattern_destroy:
708
* @pattern: a #cairo_pattern_t
710
* Decreases the reference count on @pattern by one. If the result is
711
* zero, then @pattern and all associated resources are freed. See
712
* cairo_pattern_reference().
715
cairo_pattern_destroy (cairo_pattern_t *pattern)
717
if (pattern == NULL ||
718
CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
721
assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
723
if (! _cairo_reference_count_dec_and_test (&pattern->ref_count))
726
_cairo_pattern_fini (pattern);
728
/* maintain a small cache of freed patterns */
729
if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
732
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
734
i = solid_pattern_cache.size++ %
735
ARRAY_LENGTH (solid_pattern_cache.patterns);
736
/* swap an old pattern for this 'cache-hot' pattern */
737
if (solid_pattern_cache.patterns[i])
738
free (solid_pattern_cache.patterns[i]);
740
solid_pattern_cache.patterns[i] = (cairo_solid_pattern_t *) pattern;
742
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock);
747
slim_hidden_def (cairo_pattern_destroy);
750
* cairo_pattern_get_reference_count:
751
* @pattern: a #cairo_pattern_t
753
* Returns the current reference count of @pattern.
755
* Return value: the current reference count of @pattern. If the
756
* object is a nil object, 0 will be returned.
761
cairo_pattern_get_reference_count (cairo_pattern_t *pattern)
763
if (pattern == NULL ||
764
CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
767
return CAIRO_REFERENCE_COUNT_GET_VALUE (&pattern->ref_count);
771
* cairo_pattern_get_user_data:
772
* @pattern: a #cairo_pattern_t
773
* @key: the address of the #cairo_user_data_key_t the user data was
776
* Return user data previously attached to @pattern using the
777
* specified key. If no user data has been attached with the given
778
* key this function returns %NULL.
780
* Return value: the user data previously attached or %NULL.
785
cairo_pattern_get_user_data (cairo_pattern_t *pattern,
786
const cairo_user_data_key_t *key)
788
return _cairo_user_data_array_get_data (&pattern->user_data,
793
* cairo_pattern_set_user_data:
794
* @pattern: a #cairo_pattern_t
795
* @key: the address of a #cairo_user_data_key_t to attach the user data to
796
* @user_data: the user data to attach to the #cairo_pattern_t
797
* @destroy: a #cairo_destroy_func_t which will be called when the
798
* #cairo_t is destroyed or when new user data is attached using the
801
* Attach user data to @pattern. To remove user data from a surface,
802
* call this function with the key that was used to set it and %NULL
805
* Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
806
* slot could not be allocated for the user data.
811
cairo_pattern_set_user_data (cairo_pattern_t *pattern,
812
const cairo_user_data_key_t *key,
814
cairo_destroy_func_t destroy)
816
if (CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
817
return pattern->status;
819
return _cairo_user_data_array_set_data (&pattern->user_data,
820
key, user_data, destroy);
823
/* make room for at least one more color stop */
824
static cairo_status_t
825
_cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
827
cairo_gradient_stop_t *new_stops;
828
int old_size = pattern->stops_size;
829
int embedded_size = ARRAY_LENGTH (pattern->stops_embedded);
830
int new_size = 2 * MAX (old_size, 4);
832
/* we have a local buffer at pattern->stops_embedded. try to fulfill the request
834
if (old_size < embedded_size) {
835
pattern->stops = pattern->stops_embedded;
836
pattern->stops_size = embedded_size;
837
return CAIRO_STATUS_SUCCESS;
840
assert (pattern->n_stops <= pattern->stops_size);
842
if (pattern->stops == pattern->stops_embedded) {
843
new_stops = _cairo_malloc_ab (new_size, sizeof (cairo_gradient_stop_t));
845
memcpy (new_stops, pattern->stops, old_size * sizeof (cairo_gradient_stop_t));
847
new_stops = _cairo_realloc_ab (pattern->stops,
849
sizeof (cairo_gradient_stop_t));
852
if (new_stops == NULL)
853
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
855
pattern->stops = new_stops;
856
pattern->stops_size = new_size;
858
return CAIRO_STATUS_SUCCESS;
862
_cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
869
cairo_gradient_stop_t *stops;
872
if (pattern->n_stops >= pattern->stops_size) {
873
cairo_status_t status = _cairo_pattern_gradient_grow (pattern);
875
status = _cairo_pattern_set_error (&pattern->base, status);
880
stops = pattern->stops;
882
for (i = 0; i < pattern->n_stops; i++)
884
if (offset < stops[i].offset)
886
memmove (&stops[i + 1], &stops[i],
887
sizeof (cairo_gradient_stop_t) * (pattern->n_stops - i));
893
stops[i].offset = offset;
895
stops[i].color.red = red;
896
stops[i].color.green = green;
897
stops[i].color.blue = blue;
898
stops[i].color.alpha = alpha;
900
stops[i].color.red_short = _cairo_color_double_to_short (red);
901
stops[i].color.green_short = _cairo_color_double_to_short (green);
902
stops[i].color.blue_short = _cairo_color_double_to_short (blue);
903
stops[i].color.alpha_short = _cairo_color_double_to_short (alpha);
909
* cairo_pattern_add_color_stop_rgb:
910
* @pattern: a #cairo_pattern_t
911
* @offset: an offset in the range [0.0 .. 1.0]
912
* @red: red component of color
913
* @green: green component of color
914
* @blue: blue component of color
916
* Adds an opaque color stop to a gradient pattern. The offset
917
* specifies the location along the gradient's control vector. For
918
* example, a linear gradient's control vector is from (x0,y0) to
919
* (x1,y1) while a radial gradient's control vector is from any point
920
* on the start circle to the corresponding point on the end circle.
922
* The color is specified in the same way as in cairo_set_source_rgb().
924
* If two (or more) stops are specified with identical offset values,
925
* they will be sorted according to the order in which the stops are
926
* added, (stops added earlier will compare less than stops added
927
* later). This can be useful for reliably making sharp color
928
* transitions instead of the typical blend.
931
* Note: If the pattern is not a gradient pattern, (eg. a linear or
932
* radial pattern), then the pattern will be put into an error status
933
* with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
936
cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
945
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
946
pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
948
_cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
952
_cairo_restrict_value (&offset, 0.0, 1.0);
953
_cairo_restrict_value (&red, 0.0, 1.0);
954
_cairo_restrict_value (&green, 0.0, 1.0);
955
_cairo_restrict_value (&blue, 0.0, 1.0);
957
_cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
958
offset, red, green, blue, 1.0);
962
* cairo_pattern_add_color_stop_rgba:
963
* @pattern: a #cairo_pattern_t
964
* @offset: an offset in the range [0.0 .. 1.0]
965
* @red: red component of color
966
* @green: green component of color
967
* @blue: blue component of color
968
* @alpha: alpha component of color
970
* Adds a translucent color stop to a gradient pattern. The offset
971
* specifies the location along the gradient's control vector. For
972
* example, a linear gradient's control vector is from (x0,y0) to
973
* (x1,y1) while a radial gradient's control vector is from any point
974
* on the start circle to the corresponding point on the end circle.
976
* The color is specified in the same way as in cairo_set_source_rgba().
978
* If two (or more) stops are specified with identical offset values,
979
* they will be sorted according to the order in which the stops are
980
* added, (stops added earlier will compare less than stops added
981
* later). This can be useful for reliably making sharp color
982
* transitions instead of the typical blend.
984
* Note: If the pattern is not a gradient pattern, (eg. a linear or
985
* radial pattern), then the pattern will be put into an error status
986
* with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
989
cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
999
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
1000
pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
1002
_cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1006
_cairo_restrict_value (&offset, 0.0, 1.0);
1007
_cairo_restrict_value (&red, 0.0, 1.0);
1008
_cairo_restrict_value (&green, 0.0, 1.0);
1009
_cairo_restrict_value (&blue, 0.0, 1.0);
1010
_cairo_restrict_value (&alpha, 0.0, 1.0);
1012
_cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
1013
offset, red, green, blue, alpha);
1017
* cairo_pattern_set_matrix:
1018
* @pattern: a #cairo_pattern_t
1019
* @matrix: a #cairo_matrix_t
1021
* Sets the pattern's transformation matrix to @matrix. This matrix is
1022
* a transformation from user space to pattern space.
1024
* When a pattern is first created it always has the identity matrix
1025
* for its transformation matrix, which means that pattern space is
1026
* initially identical to user space.
1028
* Important: Please note that the direction of this transformation
1029
* matrix is from user space to pattern space. This means that if you
1030
* imagine the flow from a pattern to user space (and on to device
1031
* space), then coordinates in that flow will be transformed by the
1032
* inverse of the pattern matrix.
1034
* For example, if you want to make a pattern appear twice as large as
1035
* it does by default the correct code to use is:
1037
* <informalexample><programlisting>
1038
* cairo_matrix_init_scale (&matrix, 0.5, 0.5);
1039
* cairo_pattern_set_matrix (pattern, &matrix);
1040
* </programlisting></informalexample>
1042
* Meanwhile, using values of 2.0 rather than 0.5 in the code above
1043
* would cause the pattern to appear at half of its default size.
1045
* Also, please note the discussion of the user-space locking
1046
* semantics of cairo_set_source().
1049
cairo_pattern_set_matrix (cairo_pattern_t *pattern,
1050
const cairo_matrix_t *matrix)
1052
cairo_matrix_t inverse;
1053
cairo_status_t status;
1055
if (pattern->status)
1058
pattern->matrix = *matrix;
1061
status = cairo_matrix_invert (&inverse);
1063
status = _cairo_pattern_set_error (pattern, status);
1065
slim_hidden_def (cairo_pattern_set_matrix);
1068
* cairo_pattern_get_matrix:
1069
* @pattern: a #cairo_pattern_t
1070
* @matrix: return value for the matrix
1072
* Stores the pattern's transformation matrix into @matrix.
1075
cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
1077
*matrix = pattern->matrix;
1081
* cairo_pattern_set_filter:
1082
* @pattern: a #cairo_pattern_t
1083
* @filter: a #cairo_filter_t describing the filter to use for resizing
1086
* Sets the filter to be used for resizing when using this pattern.
1087
* See #cairo_filter_t for details on each filter.
1089
* * Note that you might want to control filtering even when you do not
1090
* have an explicit #cairo_pattern_t object, (for example when using
1091
* cairo_set_source_surface()). In these cases, it is convenient to
1092
* use cairo_get_source() to get access to the pattern that cairo
1093
* creates implicitly. For example:
1095
* <informalexample><programlisting>
1096
* cairo_set_source_surface (cr, image, x, y);
1097
* cairo_pattern_set_filter (cairo_get_source (cr), %CAIRO_FILTER_NEAREST);
1098
* </programlisting></informalexample>
1101
cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
1103
if (pattern->status)
1106
pattern->filter = filter;
1110
* cairo_pattern_get_filter:
1111
* @pattern: a #cairo_pattern_t
1113
* Gets the current filter for a pattern. See #cairo_filter_t
1114
* for details on each filter.
1116
* Return value: the current filter used for resizing the pattern.
1119
cairo_pattern_get_filter (cairo_pattern_t *pattern)
1121
return pattern->filter;
1125
* cairo_pattern_set_extend:
1126
* @pattern: a #cairo_pattern_t
1127
* @extend: a #cairo_extend_t describing how the area outside of the
1128
* pattern will be drawn
1130
* Sets the mode to be used for drawing outside the area of a pattern.
1131
* See #cairo_extend_t for details on the semantics of each extend
1134
* The default extend mode is %CAIRO_EXTEND_NONE for surface patterns
1135
* and %CAIRO_EXTEND_PAD for gradient patterns.
1138
cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
1140
if (pattern->status)
1143
pattern->extend = extend;
1147
* cairo_pattern_get_extend:
1148
* @pattern: a #cairo_pattern_t
1150
* Gets the current extend mode for a pattern. See #cairo_extend_t
1151
* for details on the semantics of each extend strategy.
1153
* Return value: the current extend strategy used for drawing the
1157
cairo_pattern_get_extend (cairo_pattern_t *pattern)
1159
return pattern->extend;
1161
slim_hidden_def (cairo_pattern_get_extend);
1164
_cairo_pattern_transform (cairo_pattern_t *pattern,
1165
const cairo_matrix_t *ctm_inverse)
1167
if (pattern->status)
1170
cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
1174
_cairo_linear_pattern_classify (cairo_linear_pattern_t *pattern,
1179
cairo_bool_t *is_horizontal,
1180
cairo_bool_t *is_vertical)
1182
cairo_point_double_t point0, point1;
1183
double a, b, c, d, tx, ty;
1184
double scale, start, dx, dy;
1185
cairo_fixed_t factors[3];
1188
/* To classify a pattern as horizontal or vertical, we first
1189
* compute the (fixed point) factors at the corners of the
1190
* pattern. We actually only need 3/4 corners, so we skip the
1193
point0.x = _cairo_fixed_to_double (pattern->p1.x);
1194
point0.y = _cairo_fixed_to_double (pattern->p1.y);
1195
point1.x = _cairo_fixed_to_double (pattern->p2.x);
1196
point1.y = _cairo_fixed_to_double (pattern->p2.y);
1198
_cairo_matrix_get_affine (&pattern->base.base.matrix,
1199
&a, &b, &c, &d, &tx, &ty);
1201
dx = point1.x - point0.x;
1202
dy = point1.y - point0.y;
1203
scale = dx * dx + dy * dy;
1204
scale = (scale) ? 1.0 / scale : 1.0;
1206
start = dx * point0.x + dy * point0.y;
1208
for (i = 0; i < 3; i++) {
1209
double qx_device = (i % 2) * (width - 1) + offset_x;
1210
double qy_device = (i / 2) * (height - 1) + offset_y;
1212
/* transform fragment into pattern space */
1213
double qx = a * qx_device + c * qy_device + tx;
1214
double qy = b * qx_device + d * qy_device + ty;
1216
factors[i] = _cairo_fixed_from_double (((dx * qx + dy * qy) - start) * scale);
1219
/* We consider a pattern to be vertical if the fixed point factor
1220
* at the two upper corners is the same. We could accept a small
1221
* change, but determining what change is acceptable would require
1222
* sorting the stops in the pattern and looking at the differences.
1224
* Horizontal works the same way with the two left corners.
1227
*is_vertical = factors[1] == factors[0];
1228
*is_horizontal = factors[2] == factors[0];
1231
static cairo_int_status_t
1232
_cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
1233
cairo_surface_t *dst,
1237
unsigned int height,
1238
cairo_surface_t **out,
1239
cairo_surface_attributes_t *attr)
1241
cairo_image_surface_t *image;
1242
pixman_image_t *pixman_image;
1243
pixman_transform_t pixman_transform;
1244
cairo_status_t status;
1245
cairo_bool_t repeat = FALSE;
1247
pixman_gradient_stop_t pixman_stops_static[2];
1248
pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
1251
if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
1252
pixman_stops = _cairo_malloc_ab (pattern->n_stops, sizeof(pixman_gradient_stop_t));
1253
if (pixman_stops == NULL)
1254
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1257
for (i = 0; i < pattern->n_stops; i++) {
1258
pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
1259
pixman_stops[i].color.red = pattern->stops[i].color.red_short;
1260
pixman_stops[i].color.green = pattern->stops[i].color.green_short;
1261
pixman_stops[i].color.blue = pattern->stops[i].color.blue_short;
1262
pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
1265
if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR)
1267
cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern;
1268
pixman_point_fixed_t p1, p2;
1270
p1.x = _cairo_fixed_to_16_16 (linear->p1.x);
1271
p1.y = _cairo_fixed_to_16_16 (linear->p1.y);
1272
p2.x = _cairo_fixed_to_16_16 (linear->p2.x);
1273
p2.y = _cairo_fixed_to_16_16 (linear->p2.y);
1275
pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
1281
cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
1282
pixman_point_fixed_t c1, c2;
1283
pixman_fixed_t r1, r2;
1285
c1.x = _cairo_fixed_to_16_16 (radial->c1.x);
1286
c1.y = _cairo_fixed_to_16_16 (radial->c1.y);
1287
r1 = _cairo_fixed_to_16_16 (radial->r1);
1289
c2.x = _cairo_fixed_to_16_16 (radial->c2.x);
1290
c2.y = _cairo_fixed_to_16_16 (radial->c2.y);
1291
r2 = _cairo_fixed_to_16_16 (radial->r2);
1293
pixman_image = pixman_image_create_radial_gradient (&c1, &c2,
1299
if (pixman_stops != pixman_stops_static)
1300
free (pixman_stops);
1302
if (pixman_image == NULL)
1303
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1305
if (_cairo_surface_is_image (dst))
1307
image = (cairo_image_surface_t *)
1308
_cairo_image_surface_create_for_pixman_image (pixman_image,
1310
if (image->base.status)
1312
pixman_image_unref (pixman_image);
1313
return image->base.status;
1316
attr->x_offset = attr->y_offset = 0;
1317
attr->matrix = pattern->base.matrix;
1318
attr->extend = pattern->base.extend;
1319
attr->filter = CAIRO_FILTER_NEAREST;
1320
attr->acquired = FALSE;
1322
*out = &image->base;
1324
return CAIRO_STATUS_SUCCESS;
1327
if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
1328
cairo_bool_t is_horizontal;
1329
cairo_bool_t is_vertical;
1331
_cairo_linear_pattern_classify ((cairo_linear_pattern_t *)pattern,
1332
x, y, width, height,
1333
&is_horizontal, &is_vertical);
1334
if (is_horizontal) {
1338
/* width-1 repeating patterns are quite slow with scan-line based
1339
* compositing code, so we use a wider strip and spend some extra
1340
* expense in computing the gradient. It's possible that for narrow
1341
* gradients we'd be better off using a 2 or 4 pixel strip; the
1342
* wider the gradient, the more it's worth spending extra time
1343
* computing a sample.
1345
if (is_vertical && width > 8) {
1351
if (! pixman_image_set_filter (pixman_image, PIXMAN_FILTER_BILINEAR,
1354
pixman_image_unref (pixman_image);
1355
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1358
image = (cairo_image_surface_t *)
1359
cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
1360
if (image->base.status) {
1361
pixman_image_unref (pixman_image);
1362
return image->base.status;
1365
_cairo_matrix_to_pixman_matrix (&pattern->base.matrix, &pixman_transform);
1366
if (!pixman_image_set_transform (pixman_image, &pixman_transform)) {
1367
cairo_surface_destroy (&image->base);
1368
pixman_image_unref (pixman_image);
1369
return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1372
switch (pattern->base.extend) {
1373
case CAIRO_EXTEND_NONE:
1374
pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NONE);
1376
case CAIRO_EXTEND_REPEAT:
1377
pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NORMAL);
1379
case CAIRO_EXTEND_REFLECT:
1380
pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_REFLECT);
1382
case CAIRO_EXTEND_PAD:
1383
pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_PAD);
1387
pixman_image_composite (PIXMAN_OP_SRC,
1390
image->pixman_image,
1396
pixman_image_unref (pixman_image);
1398
status = _cairo_surface_clone_similar (dst, &image->base,
1399
0, 0, width, height, out);
1401
cairo_surface_destroy (&image->base);
1403
attr->x_offset = -x;
1404
attr->y_offset = -y;
1405
cairo_matrix_init_identity (&attr->matrix);
1406
attr->extend = repeat ? CAIRO_EXTEND_REPEAT : CAIRO_EXTEND_NONE;
1407
attr->filter = CAIRO_FILTER_NEAREST;
1408
attr->acquired = FALSE;
1413
/* We maintain a small cache here, because we don't want to constantly
1414
* recreate surfaces for simple solid colors. */
1415
#define MAX_SURFACE_CACHE_SIZE 16
1417
struct _cairo_pattern_solid_surface_cache{
1418
cairo_content_t content;
1419
cairo_color_t color;
1420
cairo_surface_t *surface;
1421
} cache[MAX_SURFACE_CACHE_SIZE];
1423
} solid_surface_cache;
1426
_cairo_pattern_solid_surface_matches (
1427
const struct _cairo_pattern_solid_surface_cache *cache,
1428
const cairo_solid_pattern_t *pattern,
1429
cairo_surface_t *dst)
1431
if (cache->content != pattern->content)
1434
if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache->surface->ref_count) != 1)
1437
if (! _cairo_surface_is_similar (cache->surface, dst, pattern->content))
1444
_cairo_pattern_solid_surface_matches_color (
1445
const struct _cairo_pattern_solid_surface_cache *cache,
1446
const cairo_solid_pattern_t *pattern,
1447
cairo_surface_t *dst)
1449
if (! _cairo_color_equal (&cache->color, &pattern->color))
1452
return _cairo_pattern_solid_surface_matches (cache, pattern, dst);
1455
static cairo_int_status_t
1456
_cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t *pattern,
1457
cairo_surface_t *dst,
1461
unsigned int height,
1462
cairo_surface_t **out,
1463
cairo_surface_attributes_t *attribs)
1467
cairo_surface_t *surface, *to_destroy = NULL;
1468
cairo_status_t status;
1470
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
1472
/* Check cache first */
1473
if (i < solid_surface_cache.size &&
1474
_cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i],
1478
status = _cairo_surface_reset (solid_surface_cache.cache[i].surface);
1485
for (i = 0 ; i < solid_surface_cache.size; i++) {
1486
if (_cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i],
1490
status = _cairo_surface_reset (solid_surface_cache.cache[i].surface);
1498
/* Choose a surface to repaint/evict */
1500
if (solid_surface_cache.size == MAX_SURFACE_CACHE_SIZE) {
1501
i = rand () % MAX_SURFACE_CACHE_SIZE;
1502
surface = solid_surface_cache.cache[i].surface;
1504
if (_cairo_pattern_solid_surface_matches (&solid_surface_cache.cache[i],
1508
/* Reuse the surface instead of evicting */
1510
status = _cairo_surface_reset (surface);
1514
status = _cairo_surface_repaint_solid_pattern_surface (dst, surface, pattern);
1518
cairo_surface_reference (surface);
1527
if (surface == NULL) {
1528
/* Not cached, need to create new */
1529
surface = _cairo_surface_create_solid_pattern_surface (dst, pattern);
1530
if (surface->status) {
1531
status = surface->status;
1535
if (! _cairo_surface_is_similar (surface, dst, pattern->content)) {
1536
/* in the rare event of a substitute surface being returned (e.g.
1537
* malloc failure) don't cache the fallback surface */
1543
if (i == solid_surface_cache.size)
1544
solid_surface_cache.size++;
1546
to_destroy = solid_surface_cache.cache[i].surface;
1547
solid_surface_cache.cache[i].surface = surface;
1548
solid_surface_cache.cache[i].color = pattern->color;
1549
solid_surface_cache.cache[i].content = pattern->content;
1552
*out = cairo_surface_reference (solid_surface_cache.cache[i].surface);
1555
attribs->x_offset = attribs->y_offset = 0;
1556
cairo_matrix_init_identity (&attribs->matrix);
1557
attribs->extend = CAIRO_EXTEND_REPEAT;
1558
attribs->filter = CAIRO_FILTER_NEAREST;
1559
attribs->acquired = FALSE;
1561
status = CAIRO_STATUS_SUCCESS;
1564
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
1567
cairo_surface_destroy (to_destroy);
1573
_cairo_pattern_reset_solid_surface_cache (void)
1575
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
1577
/* remove surfaces starting from the end so that solid_surface_cache.cache
1578
* is always in a consistent state when we release the mutex. */
1579
while (solid_surface_cache.size) {
1580
cairo_surface_t *surface;
1582
solid_surface_cache.size--;
1583
surface = solid_surface_cache.cache[solid_surface_cache.size].surface;
1584
solid_surface_cache.cache[solid_surface_cache.size].surface = NULL;
1586
/* release the lock to avoid the possibility of a recursive
1587
* deadlock when the scaled font destroy closure gets called */
1588
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
1589
cairo_surface_destroy (surface);
1590
CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
1593
CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
1597
* _cairo_pattern_is_opaque_solid
1599
* Convenience function to determine whether a pattern is an opaque
1600
* (alpha==1.0) solid color pattern. This is done by testing whether
1601
* the pattern's alpha value when converted to a byte is 255, so if a
1602
* backend actually supported deep alpha channels this function might
1603
* not do the right thing.
1605
* Return value: %TRUE if the pattern is an opaque, solid color.
1608
_cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern)
1610
cairo_solid_pattern_t *solid;
1612
if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
1615
solid = (cairo_solid_pattern_t *) pattern;
1617
return CAIRO_COLOR_IS_OPAQUE (&solid->color);
1621
_gradient_is_opaque (const cairo_gradient_pattern_t *gradient)
1625
for (i = 0; i < gradient->n_stops; i++)
1626
if (! CAIRO_COLOR_IS_OPAQUE (&gradient->stops[i].color))
1633
* _cairo_pattern_is_opaque
1635
* Convenience function to determine whether a pattern is an opaque
1636
* pattern (of any type). The same caveats that apply to
1637
* _cairo_pattern_is_opaque_solid apply here as well.
1639
* Return value: %TRUE if the pattern is a opaque.
1642
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern)
1644
const cairo_pattern_union_t *pattern;
1646
pattern = (cairo_pattern_union_t *) abstract_pattern;
1647
switch (pattern->base.type) {
1648
case CAIRO_PATTERN_TYPE_SOLID:
1649
return _cairo_pattern_is_opaque_solid (abstract_pattern);
1650
case CAIRO_PATTERN_TYPE_SURFACE:
1651
return cairo_surface_get_content (pattern->surface.surface) == CAIRO_CONTENT_COLOR;
1652
case CAIRO_PATTERN_TYPE_LINEAR:
1653
case CAIRO_PATTERN_TYPE_RADIAL:
1654
return _gradient_is_opaque (&pattern->gradient.base);
1661
static cairo_int_status_t
1662
_cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t *pattern,
1663
cairo_surface_t *dst,
1667
unsigned int height,
1668
cairo_surface_t **out,
1669
cairo_surface_attributes_t *attr)
1671
cairo_int_status_t status;
1674
attr->acquired = FALSE;
1676
attr->extend = pattern->base.extend;
1677
attr->filter = pattern->base.filter;
1678
if (_cairo_matrix_is_integer_translation (&pattern->base.matrix,
1681
cairo_matrix_init_identity (&attr->matrix);
1682
attr->x_offset = tx;
1683
attr->y_offset = ty;
1684
attr->filter = CAIRO_FILTER_NEAREST;
1688
attr->matrix = pattern->base.matrix;
1689
attr->x_offset = attr->y_offset = 0;
1696
* The way we currently support CAIRO_EXTEND_REFLECT is to create
1697
* an image twice bigger on each side, and create a pattern of four
1698
* images such that the new image, when repeated, has the same effect
1699
* of reflecting the original pattern.
1701
* This is because the reflect support in pixman is broken and we
1702
* pass repeat instead of reflect to pixman. See
1703
* _cairo_image_surface_set_attributes() for that.
1705
if (attr->extend == CAIRO_EXTEND_REFLECT) {
1709
cairo_rectangle_int_t extents;
1710
status = _cairo_surface_get_extents (pattern->surface, &extents);
1714
attr->extend = CAIRO_EXTEND_REPEAT;
1716
/* TODO: Instead of rendering pattern->surface four times to
1717
* out, we should first copy pattern->surface to surface similar
1718
* to dst and then copy that four times to out. This may cause
1719
* an extra copy in the case of image destination, but for X servers,
1720
* this will send pattern->surface just once over the wire instead
1725
w = 2 * extents.width;
1726
h = 2 * extents.height;
1728
*out = cairo_surface_create_similar (dst, dst->content, w, h);
1729
status = cairo_surface_status (*out);
1731
cairo_surface_destroy (*out);
1736
(*out)->device_transform = pattern->surface->device_transform;
1737
(*out)->device_transform_inverse = pattern->surface->device_transform_inverse;
1739
cr = cairo_create (*out);
1741
cairo_set_source_surface (cr, pattern->surface, -x, -y);
1744
cairo_scale (cr, -1, +1);
1745
cairo_set_source_surface (cr, pattern->surface, x-w, -y);
1748
cairo_scale (cr, +1, -1);
1749
cairo_set_source_surface (cr, pattern->surface, x-w, y-h);
1752
cairo_scale (cr, -1, +1);
1753
cairo_set_source_surface (cr, pattern->surface, -x, y-h);
1756
status = cairo_status (cr);
1760
cairo_surface_destroy (*out);
1767
if (_cairo_surface_is_image (dst))
1769
cairo_image_surface_t *image;
1771
status = _cairo_surface_acquire_source_image (pattern->surface,
1777
*out = &image->base;
1778
attr->acquired = TRUE;
1782
cairo_rectangle_int_t extents;
1783
status = _cairo_surface_get_extents (pattern->surface, &extents);
1787
/* If we're repeating, we just play it safe and clone the entire surface. */
1788
/* If requested width and height are -1, clone the entire surface.
1789
* This is relied on in the svg backend. */
1790
if (attr->extend == CAIRO_EXTEND_REPEAT ||
1791
(width == (unsigned int) -1 && height == (unsigned int) -1)) {
1794
width = extents.width;
1795
height = extents.height;
1797
/* Otherwise, we first transform the rectangle to the
1798
* coordinate space of the source surface so that we can
1799
* clone only that portion of the surface that will be
1801
if (! _cairo_matrix_is_identity (&attr->matrix)) {
1804
double x2 = x + width;
1805
double y2 = y + height;
1806
cairo_bool_t is_tight;
1808
_cairo_matrix_transform_bounding_box (&attr->matrix,
1812
/* The transform_bounding_box call may have resulted
1813
* in a region larger than the surface, but we never
1814
* want to clone more than the surface itself, (we
1815
* know we're not repeating at this point due to the
1818
* XXX: The one padding here is to account for filter
1819
* radius. It's a workaround right now, until we get a
1820
* proper fix. (see bug #10508)
1822
x = MAX (0, floor (x1) - 1);
1823
y = MAX (0, floor (y1) - 1);
1824
width = MAX (MIN (extents.width, ceil (x2) + 1) - x, 0);
1825
height = MAX (MIN (extents.height, ceil (y2) + 1) - y, 0);
1831
status = _cairo_surface_clone_similar (dst, pattern->surface,
1832
x, y, width, height, out);
1839
* _cairo_pattern_acquire_surface:
1840
* @pattern: a #cairo_pattern_t
1841
* @dst: destination surface
1842
* @x: X coordinate in source corresponding to left side of destination area
1843
* @y: Y coordinate in source corresponding to top side of destination area
1844
* @width: width of destination area
1845
* @height: height of destination area
1846
* @surface_out: location to store a pointer to a surface
1847
* @attributes: surface attributes that destination backend should apply to
1848
* the returned surface
1850
* A convenience function to obtain a surface to use as the source for
1853
* Return value: %CAIRO_STATUS_SUCCESS if a surface was stored in @surface_out.
1856
_cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
1857
cairo_surface_t *dst,
1861
unsigned int height,
1862
cairo_surface_t **surface_out,
1863
cairo_surface_attributes_t *attributes)
1865
cairo_status_t status;
1867
if (pattern->status) {
1868
*surface_out = NULL;
1869
attributes->acquired = FALSE;
1870
return pattern->status;
1873
switch (pattern->type) {
1874
case CAIRO_PATTERN_TYPE_SOLID: {
1875
cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) pattern;
1877
status = _cairo_pattern_acquire_surface_for_solid (src, dst,
1878
x, y, width, height,
1882
case CAIRO_PATTERN_TYPE_LINEAR:
1883
case CAIRO_PATTERN_TYPE_RADIAL: {
1884
cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) pattern;
1886
/* fast path for gradients with less than 2 color stops */
1887
if (src->n_stops < 2)
1889
cairo_solid_pattern_t solid;
1893
cairo_color_t color;
1895
_cairo_color_init_rgba (&color,
1896
src->stops->color.red,
1897
src->stops->color.green,
1898
src->stops->color.blue,
1899
src->stops->color.alpha);
1901
_cairo_pattern_init_solid (&solid, &color, CAIRO_CONTENT_COLOR_ALPHA);
1905
_cairo_pattern_init_solid (&solid, CAIRO_COLOR_TRANSPARENT, CAIRO_CONTENT_ALPHA);
1908
status = _cairo_pattern_acquire_surface_for_solid (&solid, dst,
1916
status = _cairo_pattern_acquire_surface_for_gradient (src, dst,
1923
case CAIRO_PATTERN_TYPE_SURFACE: {
1924
cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) pattern;
1926
status = _cairo_pattern_acquire_surface_for_surface (src, dst,
1927
x, y, width, height,
1933
status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1940
* _cairo_pattern_release_surface:
1941
* @pattern: a #cairo_pattern_t
1942
* @surface: a surface obtained by _cairo_pattern_acquire_surface
1943
* @attributes: attributes obtained by _cairo_pattern_acquire_surface
1945
* Releases resources obtained by _cairo_pattern_acquire_surface.
1948
_cairo_pattern_release_surface (cairo_pattern_t *pattern,
1949
cairo_surface_t *surface,
1950
cairo_surface_attributes_t *attributes)
1952
if (attributes->acquired)
1954
cairo_surface_pattern_t *surface_pattern;
1956
assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
1957
surface_pattern = (cairo_surface_pattern_t *) pattern;
1959
_cairo_surface_release_source_image (surface_pattern->surface,
1960
(cairo_image_surface_t *) surface,
1965
cairo_surface_destroy (surface);
1970
_cairo_pattern_acquire_surfaces (cairo_pattern_t *src,
1971
cairo_pattern_t *mask,
1972
cairo_surface_t *dst,
1978
unsigned int height,
1979
cairo_surface_t **src_out,
1980
cairo_surface_t **mask_out,
1981
cairo_surface_attributes_t *src_attributes,
1982
cairo_surface_attributes_t *mask_attributes)
1984
cairo_int_status_t status;
1985
cairo_pattern_union_t src_tmp, mask_tmp;
1989
if (mask && mask->status)
1990
return mask->status;
1992
/* If src and mask are both solid, then the mask alpha can be
1993
* combined into src and mask can be ignored. */
1995
/* XXX: This optimization assumes that there is no color
1996
* information in mask, so this will need to change when we
1997
* support RENDER-style 4-channel masks. */
1998
if (src->type == CAIRO_PATTERN_TYPE_SOLID &&
1999
mask && mask->type == CAIRO_PATTERN_TYPE_SOLID)
2001
cairo_color_t combined;
2002
cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src;
2003
cairo_solid_pattern_t *mask_solid = (cairo_solid_pattern_t *) mask;
2005
combined = src_solid->color;
2006
_cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
2008
_cairo_pattern_init_solid (&src_tmp.solid, &combined, CAIRO_CONTENT_COLOR_ALPHA);
2014
status = _cairo_pattern_init_copy (&src_tmp.base, src);
2019
status = _cairo_pattern_acquire_surface (&src_tmp.base, dst,
2022
src_out, src_attributes);
2024
_cairo_pattern_fini (&src_tmp.base);
2030
_cairo_pattern_fini (&src_tmp.base);
2032
return CAIRO_STATUS_SUCCESS;
2035
status = _cairo_pattern_init_copy (&mask_tmp.base, mask);
2037
goto CLEANUP_SOURCE;
2039
status = _cairo_pattern_acquire_surface (&mask_tmp.base, dst,
2042
mask_out, mask_attributes);
2044
_cairo_pattern_fini (&mask_tmp.base);
2048
_cairo_pattern_release_surface (&src_tmp.base,
2049
*src_out, src_attributes);
2051
_cairo_pattern_fini (&src_tmp.base);
2057
* _cairo_pattern_get_extents:
2059
* Return the "target-space" extents of @pattern in @extents.
2061
* For unbounded patterns, the @extents will be initialized with
2062
* "infinite" extents, (minimum and maximum fixed-point values).
2064
* XXX: Currently, bounded gradient patterns will also return
2065
* "infinite" extents, though it would be possible to optimize these
2066
* with a little more work.
2069
_cairo_pattern_get_extents (cairo_pattern_t *pattern,
2070
cairo_rectangle_int_t *extents)
2072
if (pattern->extend == CAIRO_EXTEND_NONE &&
2073
pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
2075
cairo_status_t status;
2076
cairo_rectangle_int_t surface_extents;
2077
cairo_surface_pattern_t *surface_pattern =
2078
(cairo_surface_pattern_t *) pattern;
2079
cairo_surface_t *surface = surface_pattern->surface;
2080
cairo_matrix_t imatrix;
2081
double x1, y1, x2, y2;
2083
status = _cairo_surface_get_extents (surface, &surface_extents);
2087
x1 = surface_extents.x;
2088
y1 = surface_extents.y;
2089
x2 = x1 + surface_extents.width;
2090
y2 = y1 + surface_extents.height;
2092
imatrix = pattern->matrix;
2093
status = cairo_matrix_invert (&imatrix);
2094
/* cairo_pattern_set_matrix ensures the matrix is invertible */
2095
assert (status == CAIRO_STATUS_SUCCESS);
2097
_cairo_matrix_transform_bounding_box (&imatrix,
2109
if (x2 > CAIRO_RECT_INT_MAX)
2110
x2 = CAIRO_RECT_INT_MAX;
2112
if (y2 > CAIRO_RECT_INT_MAX)
2113
y2 = CAIRO_RECT_INT_MAX;
2115
extents->x = x1; extents->width = x2 - x1;
2116
extents->y = y1; extents->height = y2 - y1;
2118
return CAIRO_STATUS_SUCCESS;
2121
/* XXX: We could optimize gradients with pattern->extend of NONE
2122
* here in some cases, (eg. radial gradients and 1 axis of
2123
* horizontal/vertical linear gradients).
2126
/* unbounded patterns -> 'infinite' extents */
2127
extents->x = CAIRO_RECT_INT_MIN;
2128
extents->y = CAIRO_RECT_INT_MIN;
2129
extents->width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
2130
extents->height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
2132
return CAIRO_STATUS_SUCCESS;
2136
* cairo_pattern_get_rgba
2137
* @pattern: a #cairo_pattern_t
2138
* @red: return value for red component of color, or %NULL
2139
* @green: return value for green component of color, or %NULL
2140
* @blue: return value for blue component of color, or %NULL
2141
* @alpha: return value for alpha component of color, or %NULL
2143
* Gets the solid color for a solid color pattern.
2145
* Return value: %CAIRO_STATUS_SUCCESS, or
2146
* %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid
2152
cairo_pattern_get_rgba (cairo_pattern_t *pattern,
2153
double *red, double *green,
2154
double *blue, double *alpha)
2156
cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
2157
double r0, g0, b0, a0;
2159
if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
2160
return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
2162
_cairo_color_get_rgba (&solid->color, &r0, &g0, &b0, &a0);
2173
return CAIRO_STATUS_SUCCESS;
2177
* cairo_pattern_get_surface
2178
* @pattern: a #cairo_pattern_t
2179
* @surface: return value for surface of pattern, or %NULL
2181
* Gets the surface of a surface pattern. The reference returned in
2182
* @surface is owned by the pattern; the caller should call
2183
* cairo_surface_reference() if the surface is to be retained.
2185
* Return value: %CAIRO_STATUS_SUCCESS, or
2186
* %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a surface
2192
cairo_pattern_get_surface (cairo_pattern_t *pattern,
2193
cairo_surface_t **surface)
2195
cairo_surface_pattern_t *spat = (cairo_surface_pattern_t*) pattern;
2197
if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
2198
return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
2201
*surface = spat->surface;
2203
return CAIRO_STATUS_SUCCESS;
2207
* cairo_pattern_get_color_stop_rgba
2208
* @pattern: a #cairo_pattern_t
2209
* @index: index of the stop to return data for
2210
* @offset: return value for the offset of the stop, or %NULL
2211
* @red: return value for red component of color, or %NULL
2212
* @green: return value for green component of color, or %NULL
2213
* @blue: return value for blue component of color, or %NULL
2214
* @alpha: return value for alpha component of color, or %NULL
2216
* Gets the color and offset information at the given @index for a
2217
* gradient pattern. Values of @index are 0 to 1 less than the number
2218
* returned by cairo_pattern_get_color_stop_count().
2220
* Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
2221
* if @index is not valid for the given pattern. If the pattern is
2222
* not a gradient pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
2228
cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
2229
int index, double *offset,
2230
double *red, double *green,
2231
double *blue, double *alpha)
2233
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
2235
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
2236
pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
2237
return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
2239
if (index < 0 || (unsigned int) index >= gradient->n_stops)
2240
return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
2243
*offset = gradient->stops[index].offset;
2245
*red = gradient->stops[index].color.red;
2247
*green = gradient->stops[index].color.green;
2249
*blue = gradient->stops[index].color.blue;
2251
*alpha = gradient->stops[index].color.alpha;
2253
return CAIRO_STATUS_SUCCESS;
2257
* cairo_pattern_get_color_stop_count
2258
* @pattern: a #cairo_pattern_t
2259
* @count: return value for the number of color stops, or %NULL
2261
* Gets the number of color stops specified in the given gradient
2264
* Return value: %CAIRO_STATUS_SUCCESS, or
2265
* %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
2271
cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
2274
cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
2276
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
2277
pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
2278
return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
2281
*count = gradient->n_stops;
2283
return CAIRO_STATUS_SUCCESS;
2287
* cairo_pattern_get_linear_points
2288
* @pattern: a #cairo_pattern_t
2289
* @x0: return value for the x coordinate of the first point, or %NULL
2290
* @y0: return value for the y coordinate of the first point, or %NULL
2291
* @x1: return value for the x coordinate of the second point, or %NULL
2292
* @y1: return value for the y coordinate of the second point, or %NULL
2294
* Gets the gradient endpoints for a linear gradient.
2296
* Return value: %CAIRO_STATUS_SUCCESS, or
2297
* %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a linear
2303
cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
2304
double *x0, double *y0,
2305
double *x1, double *y1)
2307
cairo_linear_pattern_t *linear = (cairo_linear_pattern_t*) pattern;
2309
if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR)
2310
return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
2313
*x0 = _cairo_fixed_to_double (linear->p1.x);
2315
*y0 = _cairo_fixed_to_double (linear->p1.y);
2317
*x1 = _cairo_fixed_to_double (linear->p2.x);
2319
*y1 = _cairo_fixed_to_double (linear->p2.y);
2321
return CAIRO_STATUS_SUCCESS;
2325
* cairo_pattern_get_radial_circles
2326
* @pattern: a #cairo_pattern_t
2327
* @x0: return value for the x coordinate of the center of the first circle, or %NULL
2328
* @y0: return value for the y coordinate of the center of the first circle, or %NULL
2329
* @r0: return value for the radius of the first circle, or %NULL
2330
* @x1: return value for the x coordinate of the center of the second circle, or %NULL
2331
* @y1: return value for the y coordinate of the center of the second circle, or %NULL
2332
* @r1: return value for the radius of the second circle, or %NULL
2334
* Gets the gradient endpoint circles for a radial gradient, each
2335
* specified as a center coordinate and a radius.
2337
* Return value: %CAIRO_STATUS_SUCCESS, or
2338
* %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial
2344
cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
2345
double *x0, double *y0, double *r0,
2346
double *x1, double *y1, double *r1)
2348
cairo_radial_pattern_t *radial = (cairo_radial_pattern_t*) pattern;
2350
if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
2351
return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
2354
*x0 = _cairo_fixed_to_double (radial->c1.x);
2356
*y0 = _cairo_fixed_to_double (radial->c1.y);
2358
*r0 = _cairo_fixed_to_double (radial->r1);
2360
*x1 = _cairo_fixed_to_double (radial->c2.x);
2362
*y1 = _cairo_fixed_to_double (radial->c2.y);
2364
*r1 = _cairo_fixed_to_double (radial->r2);
2366
return CAIRO_STATUS_SUCCESS;
2370
_cairo_pattern_reset_static_data (void)
2372
_cairo_pattern_reset_solid_pattern_cache ();
2373
_cairo_pattern_reset_solid_surface_cache ();