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
;
1250 int clone_offset_x
, clone_offset_y
;
1251 cairo_matrix_t matrix
= pattern
->base
.matrix
;
1253 if (pattern
->n_stops
> ARRAY_LENGTH(pixman_stops_static
)) {
1254 pixman_stops
= _cairo_malloc_ab (pattern
->n_stops
, sizeof(pixman_gradient_stop_t
));
1255 if (pixman_stops
== NULL
)
1256 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1259 for (i
= 0; i
< pattern
->n_stops
; i
++) {
1260 pixman_stops
[i
].x
= _cairo_fixed_16_16_from_double (pattern
->stops
[i
].offset
);
1261 pixman_stops
[i
].color
.red
= pattern
->stops
[i
].color
.red_short
;
1262 pixman_stops
[i
].color
.green
= pattern
->stops
[i
].color
.green_short
;
1263 pixman_stops
[i
].color
.blue
= pattern
->stops
[i
].color
.blue_short
;
1264 pixman_stops
[i
].color
.alpha
= pattern
->stops
[i
].color
.alpha_short
;
1267 if (pattern
->base
.type
== CAIRO_PATTERN_TYPE_LINEAR
)
1269 cairo_linear_pattern_t
*linear
= (cairo_linear_pattern_t
*) pattern
;
1270 pixman_point_fixed_t p1
, p2
;
1271 cairo_fixed_t xdim
, ydim
;
1273 xdim
= linear
->p2
.x
- linear
->p1
.x
;
1274 ydim
= linear
->p2
.y
- linear
->p1
.y
;
1277 * Transform the matrix to avoid overflow when converting between
1278 * cairo_fixed_t and pixman_fixed_t (without incurring performance
1279 * loss when the transformation is unnecessary).
1281 * XXX: Consider converting out-of-range co-ordinates and transforms.
1282 * Having a function to compute the required transformation to
1283 * "normalize" a given bounding box would be generally useful -
1284 * cf linear patterns, gradient patterns, surface patterns...
1286 #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
1287 if (_cairo_fixed_integer_ceil (xdim
) > PIXMAN_MAX_INT
||
1288 _cairo_fixed_integer_ceil (ydim
) > PIXMAN_MAX_INT
)
1293 sf
= PIXMAN_MAX_INT
/ _cairo_fixed_to_double (xdim
);
1295 sf
= PIXMAN_MAX_INT
/ _cairo_fixed_to_double (ydim
);
1297 p1
.x
= _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear
->p1
.x
) * sf
);
1298 p1
.y
= _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear
->p1
.y
) * sf
);
1299 p2
.x
= _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear
->p2
.x
) * sf
);
1300 p2
.y
= _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear
->p2
.y
) * sf
);
1302 cairo_matrix_scale (&matrix
, sf
, sf
);
1306 p1
.x
= _cairo_fixed_to_16_16 (linear
->p1
.x
);
1307 p1
.y
= _cairo_fixed_to_16_16 (linear
->p1
.y
);
1308 p2
.x
= _cairo_fixed_to_16_16 (linear
->p2
.x
);
1309 p2
.y
= _cairo_fixed_to_16_16 (linear
->p2
.y
);
1312 pixman_image
= pixman_image_create_linear_gradient (&p1
, &p2
,
1318 cairo_radial_pattern_t
*radial
= (cairo_radial_pattern_t
*) pattern
;
1319 pixman_point_fixed_t c1
, c2
;
1320 pixman_fixed_t r1
, r2
;
1322 c1
.x
= _cairo_fixed_to_16_16 (radial
->c1
.x
);
1323 c1
.y
= _cairo_fixed_to_16_16 (radial
->c1
.y
);
1324 r1
= _cairo_fixed_to_16_16 (radial
->r1
);
1326 c2
.x
= _cairo_fixed_to_16_16 (radial
->c2
.x
);
1327 c2
.y
= _cairo_fixed_to_16_16 (radial
->c2
.y
);
1328 r2
= _cairo_fixed_to_16_16 (radial
->r2
);
1330 pixman_image
= pixman_image_create_radial_gradient (&c1
, &c2
,
1336 if (pixman_stops
!= pixman_stops_static
)
1337 free (pixman_stops
);
1339 if (pixman_image
== NULL
)
1340 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1342 if (_cairo_surface_is_image (dst
))
1344 image
= (cairo_image_surface_t
*)
1345 _cairo_image_surface_create_for_pixman_image (pixman_image
,
1347 if (image
->base
.status
)
1349 pixman_image_unref (pixman_image
);
1350 return image
->base
.status
;
1353 attr
->x_offset
= attr
->y_offset
= 0;
1354 attr
->matrix
= matrix
;
1355 attr
->extend
= pattern
->base
.extend
;
1356 attr
->filter
= CAIRO_FILTER_NEAREST
;
1357 attr
->acquired
= FALSE
;
1359 *out
= &image
->base
;
1361 return CAIRO_STATUS_SUCCESS
;
1364 if (pattern
->base
.type
== CAIRO_PATTERN_TYPE_LINEAR
) {
1365 cairo_bool_t is_horizontal
;
1366 cairo_bool_t is_vertical
;
1368 _cairo_linear_pattern_classify ((cairo_linear_pattern_t
*)pattern
,
1369 x
, y
, width
, height
,
1370 &is_horizontal
, &is_vertical
);
1371 if (is_horizontal
) {
1375 /* width-1 repeating patterns are quite slow with scan-line based
1376 * compositing code, so we use a wider strip and spend some extra
1377 * expense in computing the gradient. It's possible that for narrow
1378 * gradients we'd be better off using a 2 or 4 pixel strip; the
1379 * wider the gradient, the more it's worth spending extra time
1380 * computing a sample.
1382 if (is_vertical
&& width
> 8) {
1388 if (! pixman_image_set_filter (pixman_image
, PIXMAN_FILTER_BILINEAR
,
1391 pixman_image_unref (pixman_image
);
1392 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1395 image
= (cairo_image_surface_t
*)
1396 cairo_image_surface_create (CAIRO_FORMAT_ARGB32
, width
, height
);
1397 if (image
->base
.status
) {
1398 pixman_image_unref (pixman_image
);
1399 return image
->base
.status
;
1402 _cairo_matrix_to_pixman_matrix (&matrix
, &pixman_transform
);
1403 if (!pixman_image_set_transform (pixman_image
, &pixman_transform
)) {
1404 cairo_surface_destroy (&image
->base
);
1405 pixman_image_unref (pixman_image
);
1406 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1409 switch (pattern
->base
.extend
) {
1410 case CAIRO_EXTEND_NONE
:
1411 pixman_image_set_repeat (pixman_image
, PIXMAN_REPEAT_NONE
);
1413 case CAIRO_EXTEND_REPEAT
:
1414 pixman_image_set_repeat (pixman_image
, PIXMAN_REPEAT_NORMAL
);
1416 case CAIRO_EXTEND_REFLECT
:
1417 pixman_image_set_repeat (pixman_image
, PIXMAN_REPEAT_REFLECT
);
1419 case CAIRO_EXTEND_PAD
:
1420 pixman_image_set_repeat (pixman_image
, PIXMAN_REPEAT_PAD
);
1424 pixman_image_composite (PIXMAN_OP_SRC
,
1427 image
->pixman_image
,
1433 pixman_image_unref (pixman_image
);
1435 status
= _cairo_surface_clone_similar (dst
, &image
->base
,
1436 0, 0, width
, height
,
1441 cairo_surface_destroy (&image
->base
);
1443 attr
->x_offset
= -x
;
1444 attr
->y_offset
= -y
;
1445 cairo_matrix_init_identity (&attr
->matrix
);
1446 attr
->extend
= repeat
? CAIRO_EXTEND_REPEAT
: CAIRO_EXTEND_NONE
;
1447 attr
->filter
= CAIRO_FILTER_NEAREST
;
1448 attr
->acquired
= FALSE
;
1453 /* We maintain a small cache here, because we don't want to constantly
1454 * recreate surfaces for simple solid colors. */
1455 #define MAX_SURFACE_CACHE_SIZE 16
1457 struct _cairo_pattern_solid_surface_cache
{
1458 cairo_content_t content
;
1459 cairo_color_t color
;
1460 cairo_surface_t
*surface
;
1461 } cache
[MAX_SURFACE_CACHE_SIZE
];
1463 } solid_surface_cache
;
1466 _cairo_pattern_solid_surface_matches (
1467 const struct _cairo_pattern_solid_surface_cache
*cache
,
1468 const cairo_solid_pattern_t
*pattern
,
1469 cairo_surface_t
*dst
)
1471 if (cache
->content
!= pattern
->content
)
1474 if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache
->surface
->ref_count
) != 1)
1477 if (! _cairo_surface_is_similar (cache
->surface
, dst
, pattern
->content
))
1484 _cairo_pattern_solid_surface_matches_color (
1485 const struct _cairo_pattern_solid_surface_cache
*cache
,
1486 const cairo_solid_pattern_t
*pattern
,
1487 cairo_surface_t
*dst
)
1489 if (! _cairo_color_equal (&cache
->color
, &pattern
->color
))
1492 return _cairo_pattern_solid_surface_matches (cache
, pattern
, dst
);
1495 static cairo_int_status_t
1496 _cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t
*pattern
,
1497 cairo_surface_t
*dst
,
1501 unsigned int height
,
1502 cairo_surface_t
**out
,
1503 cairo_surface_attributes_t
*attribs
)
1507 cairo_surface_t
*surface
, *to_destroy
= NULL
;
1508 cairo_status_t status
;
1510 CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock
);
1512 /* Check cache first */
1513 if (i
< solid_surface_cache
.size
&&
1514 _cairo_pattern_solid_surface_matches_color (&solid_surface_cache
.cache
[i
],
1518 status
= _cairo_surface_reset (solid_surface_cache
.cache
[i
].surface
);
1525 for (i
= 0 ; i
< solid_surface_cache
.size
; i
++) {
1526 if (_cairo_pattern_solid_surface_matches_color (&solid_surface_cache
.cache
[i
],
1530 status
= _cairo_surface_reset (solid_surface_cache
.cache
[i
].surface
);
1538 /* Choose a surface to repaint/evict */
1540 if (solid_surface_cache
.size
== MAX_SURFACE_CACHE_SIZE
) {
1541 i
= rand () % MAX_SURFACE_CACHE_SIZE
;
1542 surface
= solid_surface_cache
.cache
[i
].surface
;
1544 if (_cairo_pattern_solid_surface_matches (&solid_surface_cache
.cache
[i
],
1548 /* Reuse the surface instead of evicting */
1550 status
= _cairo_surface_reset (surface
);
1554 status
= _cairo_surface_repaint_solid_pattern_surface (dst
, surface
, pattern
);
1558 cairo_surface_reference (surface
);
1567 if (surface
== NULL
) {
1568 /* Not cached, need to create new */
1569 surface
= _cairo_surface_create_solid_pattern_surface (dst
, pattern
);
1570 if (surface
->status
) {
1571 status
= surface
->status
;
1575 if (! _cairo_surface_is_similar (surface
, dst
, pattern
->content
)) {
1576 /* in the rare event of a substitute surface being returned (e.g.
1577 * malloc failure) don't cache the fallback surface */
1583 if (i
== solid_surface_cache
.size
)
1584 solid_surface_cache
.size
++;
1586 to_destroy
= solid_surface_cache
.cache
[i
].surface
;
1587 solid_surface_cache
.cache
[i
].surface
= surface
;
1588 solid_surface_cache
.cache
[i
].color
= pattern
->color
;
1589 solid_surface_cache
.cache
[i
].content
= pattern
->content
;
1592 *out
= cairo_surface_reference (solid_surface_cache
.cache
[i
].surface
);
1595 attribs
->x_offset
= attribs
->y_offset
= 0;
1596 cairo_matrix_init_identity (&attribs
->matrix
);
1597 attribs
->extend
= CAIRO_EXTEND_REPEAT
;
1598 attribs
->filter
= CAIRO_FILTER_NEAREST
;
1599 attribs
->acquired
= FALSE
;
1601 status
= CAIRO_STATUS_SUCCESS
;
1604 CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock
);
1607 cairo_surface_destroy (to_destroy
);
1613 _cairo_pattern_reset_solid_surface_cache (void)
1615 CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock
);
1617 /* remove surfaces starting from the end so that solid_surface_cache.cache
1618 * is always in a consistent state when we release the mutex. */
1619 while (solid_surface_cache
.size
) {
1620 cairo_surface_t
*surface
;
1622 solid_surface_cache
.size
--;
1623 surface
= solid_surface_cache
.cache
[solid_surface_cache
.size
].surface
;
1624 solid_surface_cache
.cache
[solid_surface_cache
.size
].surface
= NULL
;
1626 /* release the lock to avoid the possibility of a recursive
1627 * deadlock when the scaled font destroy closure gets called */
1628 CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock
);
1629 cairo_surface_destroy (surface
);
1630 CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock
);
1633 CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock
);
1637 * _cairo_pattern_is_opaque_solid
1639 * Convenience function to determine whether a pattern is an opaque
1640 * (alpha==1.0) solid color pattern. This is done by testing whether
1641 * the pattern's alpha value when converted to a byte is 255, so if a
1642 * backend actually supported deep alpha channels this function might
1643 * not do the right thing.
1645 * Return value: %TRUE if the pattern is an opaque, solid color.
1648 _cairo_pattern_is_opaque_solid (const cairo_pattern_t
*pattern
)
1650 cairo_solid_pattern_t
*solid
;
1652 if (pattern
->type
!= CAIRO_PATTERN_TYPE_SOLID
)
1655 solid
= (cairo_solid_pattern_t
*) pattern
;
1657 return CAIRO_COLOR_IS_OPAQUE (&solid
->color
);
1661 _gradient_is_opaque (const cairo_gradient_pattern_t
*gradient
)
1665 for (i
= 0; i
< gradient
->n_stops
; i
++)
1666 if (! CAIRO_COLOR_IS_OPAQUE (&gradient
->stops
[i
].color
))
1673 * _cairo_pattern_is_opaque
1675 * Convenience function to determine whether a pattern is an opaque
1676 * pattern (of any type). The same caveats that apply to
1677 * _cairo_pattern_is_opaque_solid apply here as well.
1679 * Return value: %TRUE if the pattern is a opaque.
1682 _cairo_pattern_is_opaque (const cairo_pattern_t
*abstract_pattern
)
1684 const cairo_pattern_union_t
*pattern
;
1686 pattern
= (cairo_pattern_union_t
*) abstract_pattern
;
1687 switch (pattern
->base
.type
) {
1688 case CAIRO_PATTERN_TYPE_SOLID
:
1689 return _cairo_pattern_is_opaque_solid (abstract_pattern
);
1690 case CAIRO_PATTERN_TYPE_SURFACE
:
1691 return cairo_surface_get_content (pattern
->surface
.surface
) == CAIRO_CONTENT_COLOR
;
1692 case CAIRO_PATTERN_TYPE_LINEAR
:
1693 case CAIRO_PATTERN_TYPE_RADIAL
:
1694 return _gradient_is_opaque (&pattern
->gradient
.base
);
1702 * _cairo_pattern_analyze_filter:
1703 * @pattern: surface pattern
1704 * @pad_out: location to store necessary padding in the source image, or %NULL
1705 * Returns: the optimized #cairo_filter_t to use with @pattern.
1707 * Analyze the filter to determine how much extra needs to be sampled
1708 * from the source image to account for the filter radius and whether
1709 * we can optimize the filter to a simpler value.
1711 * XXX: We don't actually have any way of querying the backend for
1712 * the filter radius, so we just guess base on what we know that
1713 * backends do currently (see bug #10508)
1715 static cairo_filter_t
1716 _cairo_pattern_analyze_filter (cairo_surface_pattern_t
*pattern
,
1720 cairo_filter_t optimized_filter
;
1722 switch (pattern
->base
.filter
) {
1723 case CAIRO_FILTER_GOOD
:
1724 case CAIRO_FILTER_BEST
:
1725 case CAIRO_FILTER_BILINEAR
:
1726 /* If source pixels map 1:1 onto destination pixels, we do
1727 * not need to filter (and do not want to filter, since it
1728 * will cause blurriness)
1730 if (_cairo_matrix_is_pixel_exact (&pattern
->base
.matrix
)) {
1732 optimized_filter
= CAIRO_FILTER_NEAREST
;
1734 /* 0.5 is enough for a bilinear filter. It's possible we
1735 * should defensively use more for CAIRO_FILTER_BEST, but
1736 * without a single example, it's hard to know how much
1737 * more would be defensive...
1740 optimized_filter
= pattern
->base
.filter
;
1744 case CAIRO_FILTER_FAST
:
1745 case CAIRO_FILTER_NEAREST
:
1746 case CAIRO_FILTER_GAUSSIAN
:
1749 optimized_filter
= pattern
->base
.filter
;
1756 return optimized_filter
;
1761 _pixman_nearest_sample (double d
)
1763 return ceil (d
- .5);
1766 static cairo_int_status_t
1767 _cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t
*pattern
,
1768 cairo_surface_t
*dst
,
1772 unsigned int height
,
1773 cairo_surface_t
**out
,
1774 cairo_surface_attributes_t
*attr
)
1776 cairo_int_status_t status
;
1780 attr
->acquired
= FALSE
;
1782 attr
->extend
= pattern
->base
.extend
;
1783 attr
->filter
= _cairo_pattern_analyze_filter (pattern
, &pad
);
1785 if (_cairo_matrix_is_integer_translation (&pattern
->base
.matrix
,
1788 cairo_matrix_init_identity (&attr
->matrix
);
1789 attr
->x_offset
= tx
;
1790 attr
->y_offset
= ty
;
1792 else if (attr
->filter
== CAIRO_FILTER_NEAREST
)
1795 * For NEAREST, we can remove the fractional translation component
1796 * from the transformation - this ensures that the pattern will always
1797 * hit fast-paths in the backends for simple transformations that
1798 * become (almost) identity, without loss of quality.
1800 attr
->matrix
= pattern
->base
.matrix
;
1801 attr
->matrix
.x0
= 0;
1802 attr
->matrix
.y0
= 0;
1803 if (_cairo_matrix_is_pixel_exact (&attr
->matrix
)) {
1804 /* The rounding here is rather peculiar as it needs to match the
1805 * rounding performed on the sample coordinate used by pixman.
1807 attr
->matrix
.x0
= _pixman_nearest_sample (pattern
->base
.matrix
.x0
);
1808 attr
->matrix
.y0
= _pixman_nearest_sample (pattern
->base
.matrix
.y0
);
1810 attr
->matrix
.x0
= pattern
->base
.matrix
.x0
;
1811 attr
->matrix
.y0
= pattern
->base
.matrix
.y0
;
1814 attr
->x_offset
= attr
->y_offset
= 0;
1819 attr
->matrix
= pattern
->base
.matrix
;
1820 attr
->x_offset
= attr
->y_offset
= 0;
1827 * The way we currently support CAIRO_EXTEND_REFLECT is to create
1828 * an image twice bigger on each side, and create a pattern of four
1829 * images such that the new image, when repeated, has the same effect
1830 * of reflecting the original pattern.
1832 * This is because the reflect support in pixman is broken and we
1833 * pass repeat instead of reflect to pixman. See
1834 * _cairo_image_surface_set_attributes() for that.
1836 if (attr
->extend
== CAIRO_EXTEND_REFLECT
) {
1840 cairo_rectangle_int_t extents
;
1841 status
= _cairo_surface_get_extents (pattern
->surface
, &extents
);
1845 attr
->extend
= CAIRO_EXTEND_REPEAT
;
1847 /* TODO: Instead of rendering pattern->surface four times to
1848 * out, we should first copy pattern->surface to surface similar
1849 * to dst and then copy that four times to out. This may cause
1850 * an extra copy in the case of image destination, but for X servers,
1851 * this will send pattern->surface just once over the wire instead
1856 w
= 2 * extents
.width
;
1857 h
= 2 * extents
.height
;
1859 *out
= cairo_surface_create_similar (dst
, dst
->content
, w
, h
);
1860 status
= cairo_surface_status (*out
);
1862 cairo_surface_destroy (*out
);
1867 (*out
)->device_transform
= pattern
->surface
->device_transform
;
1868 (*out
)->device_transform_inverse
= pattern
->surface
->device_transform_inverse
;
1870 cr
= cairo_create (*out
);
1872 cairo_set_source_surface (cr
, pattern
->surface
, -x
, -y
);
1875 cairo_scale (cr
, -1, +1);
1876 cairo_set_source_surface (cr
, pattern
->surface
, x
-w
, -y
);
1879 cairo_scale (cr
, +1, -1);
1880 cairo_set_source_surface (cr
, pattern
->surface
, x
-w
, y
-h
);
1883 cairo_scale (cr
, -1, +1);
1884 cairo_set_source_surface (cr
, pattern
->surface
, -x
, y
-h
);
1887 status
= cairo_status (cr
);
1891 cairo_surface_destroy (*out
);
1898 if (_cairo_surface_is_image (dst
)) {
1899 cairo_image_surface_t
*image
;
1901 status
= _cairo_surface_acquire_source_image (pattern
->surface
,
1907 *out
= &image
->base
;
1908 attr
->acquired
= TRUE
;
1910 cairo_rectangle_int_t extents
;
1911 cairo_bool_t is_empty
;
1913 status
= _cairo_surface_get_extents (pattern
->surface
, &extents
);
1917 /* If we're repeating, we just play it safe and clone the
1918 * entire surface - i.e. we use the existing extents.
1920 if (attr
->extend
!= CAIRO_EXTEND_REPEAT
) {
1921 cairo_rectangle_int_t sampled_area
;
1923 /* Otherwise, we first transform the rectangle to the
1924 * coordinate space of the source surface so that we can
1925 * clone only that portion of the surface that will be
1928 if (_cairo_matrix_is_identity (&attr
->matrix
)) {
1931 sampled_area
.width
= width
;
1932 sampled_area
.height
= height
;
1936 double x2
= x
+ (int) width
;
1937 double y2
= y
+ (int) height
;
1939 _cairo_matrix_transform_bounding_box (&attr
->matrix
,
1943 sampled_area
.x
= floor (x1
- pad
);
1944 sampled_area
.y
= floor (y1
- pad
);
1945 sampled_area
.width
= ceil (x2
+ pad
) - sampled_area
.x
;
1946 sampled_area
.height
= ceil (y2
+ pad
) - sampled_area
.y
;
1950 sampled_area
.x
+= tx
;
1951 sampled_area
.y
+= ty
;
1953 /* Never acquire a larger area than the source itself */
1954 is_empty
= _cairo_rectangle_intersect (&extents
, &sampled_area
);
1957 /* XXX can we use is_empty? */
1959 status
= _cairo_surface_clone_similar (dst
, pattern
->surface
,
1960 extents
.x
, extents
.y
,
1961 extents
.width
, extents
.height
,
1963 if (status
== CAIRO_STATUS_SUCCESS
&& (x
!= 0 || y
!= 0)) {
1964 if (_cairo_matrix_is_identity (&attr
->matrix
)) {
1965 attr
->x_offset
-= x
;
1966 attr
->y_offset
-= y
;
1970 x
-= attr
->x_offset
;
1971 y
-= attr
->y_offset
;
1975 cairo_matrix_init_translate (&m
, -x
, -y
);
1976 cairo_matrix_multiply (&attr
->matrix
, &attr
->matrix
, &m
);
1985 * _cairo_pattern_acquire_surface:
1986 * @pattern: a #cairo_pattern_t
1987 * @dst: destination surface
1988 * @x: X coordinate in source corresponding to left side of destination area
1989 * @y: Y coordinate in source corresponding to top side of destination area
1990 * @width: width of destination area
1991 * @height: height of destination area
1992 * @surface_out: location to store a pointer to a surface
1993 * @attributes: surface attributes that destination backend should apply to
1994 * the returned surface
1996 * A convenience function to obtain a surface to use as the source for
1999 * Note that this function is only suitable for use when the destination
2000 * surface is pixel based and 1 device unit maps to one pixel.
2002 * Return value: %CAIRO_STATUS_SUCCESS if a surface was stored in @surface_out.
2005 _cairo_pattern_acquire_surface (cairo_pattern_t
*pattern
,
2006 cairo_surface_t
*dst
,
2010 unsigned int height
,
2011 cairo_surface_t
**surface_out
,
2012 cairo_surface_attributes_t
*attributes
)
2014 cairo_status_t status
;
2016 if (pattern
->status
) {
2017 *surface_out
= NULL
;
2018 attributes
->acquired
= FALSE
;
2019 return pattern
->status
;
2022 switch (pattern
->type
) {
2023 case CAIRO_PATTERN_TYPE_SOLID
: {
2024 cairo_solid_pattern_t
*src
= (cairo_solid_pattern_t
*) pattern
;
2026 status
= _cairo_pattern_acquire_surface_for_solid (src
, dst
,
2027 x
, y
, width
, height
,
2031 case CAIRO_PATTERN_TYPE_LINEAR
:
2032 case CAIRO_PATTERN_TYPE_RADIAL
: {
2033 cairo_gradient_pattern_t
*src
= (cairo_gradient_pattern_t
*) pattern
;
2035 /* fast path for gradients with less than 2 color stops */
2036 if (src
->n_stops
< 2)
2038 cairo_solid_pattern_t solid
;
2042 cairo_color_t color
;
2044 _cairo_color_init_rgba (&color
,
2045 src
->stops
->color
.red
,
2046 src
->stops
->color
.green
,
2047 src
->stops
->color
.blue
,
2048 src
->stops
->color
.alpha
);
2050 _cairo_pattern_init_solid (&solid
, &color
, CAIRO_CONTENT_COLOR_ALPHA
);
2054 _cairo_pattern_init_solid (&solid
, CAIRO_COLOR_TRANSPARENT
, CAIRO_CONTENT_ALPHA
);
2057 status
= _cairo_pattern_acquire_surface_for_solid (&solid
, dst
,
2065 status
= _cairo_pattern_acquire_surface_for_gradient (src
, dst
,
2072 case CAIRO_PATTERN_TYPE_SURFACE
: {
2073 cairo_surface_pattern_t
*src
= (cairo_surface_pattern_t
*) pattern
;
2075 status
= _cairo_pattern_acquire_surface_for_surface (src
, dst
,
2076 x
, y
, width
, height
,
2082 status
= _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
2089 * _cairo_pattern_release_surface:
2090 * @pattern: a #cairo_pattern_t
2091 * @surface: a surface obtained by _cairo_pattern_acquire_surface
2092 * @attributes: attributes obtained by _cairo_pattern_acquire_surface
2094 * Releases resources obtained by _cairo_pattern_acquire_surface.
2097 _cairo_pattern_release_surface (cairo_pattern_t
*pattern
,
2098 cairo_surface_t
*surface
,
2099 cairo_surface_attributes_t
*attributes
)
2101 if (attributes
->acquired
)
2103 cairo_surface_pattern_t
*surface_pattern
;
2105 assert (pattern
->type
== CAIRO_PATTERN_TYPE_SURFACE
);
2106 surface_pattern
= (cairo_surface_pattern_t
*) pattern
;
2108 _cairo_surface_release_source_image (surface_pattern
->surface
,
2109 (cairo_image_surface_t
*) surface
,
2114 cairo_surface_destroy (surface
);
2119 _cairo_pattern_acquire_surfaces (cairo_pattern_t
*src
,
2120 cairo_pattern_t
*mask
,
2121 cairo_surface_t
*dst
,
2127 unsigned int height
,
2128 cairo_surface_t
**src_out
,
2129 cairo_surface_t
**mask_out
,
2130 cairo_surface_attributes_t
*src_attributes
,
2131 cairo_surface_attributes_t
*mask_attributes
)
2133 cairo_int_status_t status
;
2134 cairo_pattern_union_t src_tmp
, mask_tmp
;
2138 if (mask
&& mask
->status
)
2139 return mask
->status
;
2141 /* If src and mask are both solid, then the mask alpha can be
2142 * combined into src and mask can be ignored. */
2144 /* XXX: This optimization assumes that there is no color
2145 * information in mask, so this will need to change when we
2146 * support RENDER-style 4-channel masks. */
2147 if (src
->type
== CAIRO_PATTERN_TYPE_SOLID
&&
2148 mask
&& mask
->type
== CAIRO_PATTERN_TYPE_SOLID
)
2150 cairo_color_t combined
;
2151 cairo_solid_pattern_t
*src_solid
= (cairo_solid_pattern_t
*) src
;
2152 cairo_solid_pattern_t
*mask_solid
= (cairo_solid_pattern_t
*) mask
;
2154 combined
= src_solid
->color
;
2155 _cairo_color_multiply_alpha (&combined
, mask_solid
->color
.alpha
);
2157 _cairo_pattern_init_solid (&src_tmp
.solid
, &combined
, CAIRO_CONTENT_COLOR_ALPHA
);
2163 status
= _cairo_pattern_init_copy (&src_tmp
.base
, src
);
2168 status
= _cairo_pattern_acquire_surface (&src_tmp
.base
, dst
,
2171 src_out
, src_attributes
);
2173 _cairo_pattern_fini (&src_tmp
.base
);
2179 _cairo_pattern_fini (&src_tmp
.base
);
2181 return CAIRO_STATUS_SUCCESS
;
2184 status
= _cairo_pattern_init_copy (&mask_tmp
.base
, mask
);
2186 goto CLEANUP_SOURCE
;
2188 status
= _cairo_pattern_acquire_surface (&mask_tmp
.base
, dst
,
2191 mask_out
, mask_attributes
);
2193 _cairo_pattern_fini (&mask_tmp
.base
);
2197 _cairo_pattern_release_surface (&src_tmp
.base
,
2198 *src_out
, src_attributes
);
2200 _cairo_pattern_fini (&src_tmp
.base
);
2206 * _cairo_pattern_get_extents:
2208 * Return the "target-space" extents of @pattern in @extents.
2210 * For unbounded patterns, the @extents will be initialized with
2211 * "infinite" extents, (minimum and maximum fixed-point values).
2213 * XXX: Currently, bounded gradient patterns will also return
2214 * "infinite" extents, though it would be possible to optimize these
2215 * with a little more work.
2218 _cairo_pattern_get_extents (cairo_pattern_t
*pattern
,
2219 cairo_rectangle_int_t
*extents
)
2221 if (pattern
->extend
== CAIRO_EXTEND_NONE
&&
2222 pattern
->type
== CAIRO_PATTERN_TYPE_SURFACE
)
2224 cairo_status_t status
;
2225 cairo_rectangle_int_t surface_extents
;
2226 cairo_surface_pattern_t
*surface_pattern
=
2227 (cairo_surface_pattern_t
*) pattern
;
2228 cairo_surface_t
*surface
= surface_pattern
->surface
;
2229 cairo_matrix_t imatrix
;
2230 double x1
, y1
, x2
, y2
;
2233 status
= _cairo_surface_get_extents (surface
, &surface_extents
);
2237 /* The filter can effectively enlarge the extents of the
2238 * pattern, so extend as necessary.
2240 _cairo_pattern_analyze_filter (surface_pattern
, &pad
);
2241 x1
= surface_extents
.x
- pad
;
2242 y1
= surface_extents
.y
- pad
;
2243 x2
= surface_extents
.x
+ (int) surface_extents
.width
+ pad
;
2244 y2
= surface_extents
.y
+ (int) surface_extents
.height
+ pad
;
2246 imatrix
= pattern
->matrix
;
2247 status
= cairo_matrix_invert (&imatrix
);
2248 /* cairo_pattern_set_matrix ensures the matrix is invertible */
2249 assert (status
== CAIRO_STATUS_SUCCESS
);
2251 _cairo_matrix_transform_bounding_box (&imatrix
,
2256 if (x1
< CAIRO_RECT_INT_MIN
)
2257 x1
= CAIRO_RECT_INT_MIN
;
2259 if (y1
< CAIRO_RECT_INT_MIN
)
2260 y1
= CAIRO_RECT_INT_MIN
;
2263 if (x2
> CAIRO_RECT_INT_MAX
)
2264 x2
= CAIRO_RECT_INT_MAX
;
2266 if (y2
> CAIRO_RECT_INT_MAX
)
2267 y2
= CAIRO_RECT_INT_MAX
;
2269 extents
->x
= x1
; extents
->width
= x2
- x1
;
2270 extents
->y
= y1
; extents
->height
= y2
- y1
;
2272 return CAIRO_STATUS_SUCCESS
;
2275 /* XXX: We could optimize gradients with pattern->extend of NONE
2276 * here in some cases, (eg. radial gradients and 1 axis of
2277 * horizontal/vertical linear gradients).
2280 /* unbounded patterns -> 'infinite' extents */
2281 extents
->x
= CAIRO_RECT_INT_MIN
;
2282 extents
->y
= CAIRO_RECT_INT_MIN
;
2283 extents
->width
= CAIRO_RECT_INT_MAX
- CAIRO_RECT_INT_MIN
;
2284 extents
->height
= CAIRO_RECT_INT_MAX
- CAIRO_RECT_INT_MIN
;
2286 return CAIRO_STATUS_SUCCESS
;
2290 * cairo_pattern_get_rgba
2291 * @pattern: a #cairo_pattern_t
2292 * @red: return value for red component of color, or %NULL
2293 * @green: return value for green component of color, or %NULL
2294 * @blue: return value for blue component of color, or %NULL
2295 * @alpha: return value for alpha component of color, or %NULL
2297 * Gets the solid color for a solid color pattern.
2299 * Return value: %CAIRO_STATUS_SUCCESS, or
2300 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid
2306 cairo_pattern_get_rgba (cairo_pattern_t
*pattern
,
2307 double *red
, double *green
,
2308 double *blue
, double *alpha
)
2310 cairo_solid_pattern_t
*solid
= (cairo_solid_pattern_t
*) pattern
;
2311 double r0
, g0
, b0
, a0
;
2313 if (pattern
->type
!= CAIRO_PATTERN_TYPE_SOLID
)
2314 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
2316 _cairo_color_get_rgba (&solid
->color
, &r0
, &g0
, &b0
, &a0
);
2327 return CAIRO_STATUS_SUCCESS
;
2331 * cairo_pattern_get_surface
2332 * @pattern: a #cairo_pattern_t
2333 * @surface: return value for surface of pattern, or %NULL
2335 * Gets the surface of a surface pattern. The reference returned in
2336 * @surface is owned by the pattern; the caller should call
2337 * cairo_surface_reference() if the surface is to be retained.
2339 * Return value: %CAIRO_STATUS_SUCCESS, or
2340 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a surface
2346 cairo_pattern_get_surface (cairo_pattern_t
*pattern
,
2347 cairo_surface_t
**surface
)
2349 cairo_surface_pattern_t
*spat
= (cairo_surface_pattern_t
*) pattern
;
2351 if (pattern
->type
!= CAIRO_PATTERN_TYPE_SURFACE
)
2352 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
2355 *surface
= spat
->surface
;
2357 return CAIRO_STATUS_SUCCESS
;
2361 * cairo_pattern_get_color_stop_rgba
2362 * @pattern: a #cairo_pattern_t
2363 * @index: index of the stop to return data for
2364 * @offset: return value for the offset of the stop, or %NULL
2365 * @red: return value for red component of color, or %NULL
2366 * @green: return value for green component of color, or %NULL
2367 * @blue: return value for blue component of color, or %NULL
2368 * @alpha: return value for alpha component of color, or %NULL
2370 * Gets the color and offset information at the given @index for a
2371 * gradient pattern. Values of @index are 0 to 1 less than the number
2372 * returned by cairo_pattern_get_color_stop_count().
2374 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
2375 * if @index is not valid for the given pattern. If the pattern is
2376 * not a gradient pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
2382 cairo_pattern_get_color_stop_rgba (cairo_pattern_t
*pattern
,
2383 int index
, double *offset
,
2384 double *red
, double *green
,
2385 double *blue
, double *alpha
)
2387 cairo_gradient_pattern_t
*gradient
= (cairo_gradient_pattern_t
*) pattern
;
2389 if (pattern
->type
!= CAIRO_PATTERN_TYPE_LINEAR
&&
2390 pattern
->type
!= CAIRO_PATTERN_TYPE_RADIAL
)
2391 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
2393 if (index
< 0 || (unsigned int) index
>= gradient
->n_stops
)
2394 return _cairo_error (CAIRO_STATUS_INVALID_INDEX
);
2397 *offset
= gradient
->stops
[index
].offset
;
2399 *red
= gradient
->stops
[index
].color
.red
;
2401 *green
= gradient
->stops
[index
].color
.green
;
2403 *blue
= gradient
->stops
[index
].color
.blue
;
2405 *alpha
= gradient
->stops
[index
].color
.alpha
;
2407 return CAIRO_STATUS_SUCCESS
;
2411 * cairo_pattern_get_color_stop_count
2412 * @pattern: a #cairo_pattern_t
2413 * @count: return value for the number of color stops, or %NULL
2415 * Gets the number of color stops specified in the given gradient
2418 * Return value: %CAIRO_STATUS_SUCCESS, or
2419 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
2425 cairo_pattern_get_color_stop_count (cairo_pattern_t
*pattern
,
2428 cairo_gradient_pattern_t
*gradient
= (cairo_gradient_pattern_t
*) pattern
;
2430 if (pattern
->type
!= CAIRO_PATTERN_TYPE_LINEAR
&&
2431 pattern
->type
!= CAIRO_PATTERN_TYPE_RADIAL
)
2432 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
2435 *count
= gradient
->n_stops
;
2437 return CAIRO_STATUS_SUCCESS
;
2441 * cairo_pattern_get_linear_points
2442 * @pattern: a #cairo_pattern_t
2443 * @x0: return value for the x coordinate of the first point, or %NULL
2444 * @y0: return value for the y coordinate of the first point, or %NULL
2445 * @x1: return value for the x coordinate of the second point, or %NULL
2446 * @y1: return value for the y coordinate of the second point, or %NULL
2448 * Gets the gradient endpoints for a linear gradient.
2450 * Return value: %CAIRO_STATUS_SUCCESS, or
2451 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a linear
2457 cairo_pattern_get_linear_points (cairo_pattern_t
*pattern
,
2458 double *x0
, double *y0
,
2459 double *x1
, double *y1
)
2461 cairo_linear_pattern_t
*linear
= (cairo_linear_pattern_t
*) pattern
;
2463 if (pattern
->type
!= CAIRO_PATTERN_TYPE_LINEAR
)
2464 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
2467 *x0
= _cairo_fixed_to_double (linear
->p1
.x
);
2469 *y0
= _cairo_fixed_to_double (linear
->p1
.y
);
2471 *x1
= _cairo_fixed_to_double (linear
->p2
.x
);
2473 *y1
= _cairo_fixed_to_double (linear
->p2
.y
);
2475 return CAIRO_STATUS_SUCCESS
;
2479 * cairo_pattern_get_radial_circles
2480 * @pattern: a #cairo_pattern_t
2481 * @x0: return value for the x coordinate of the center of the first circle, or %NULL
2482 * @y0: return value for the y coordinate of the center of the first circle, or %NULL
2483 * @r0: return value for the radius of the first circle, or %NULL
2484 * @x1: return value for the x coordinate of the center of the second circle, or %NULL
2485 * @y1: return value for the y coordinate of the center of the second circle, or %NULL
2486 * @r1: return value for the radius of the second circle, or %NULL
2488 * Gets the gradient endpoint circles for a radial gradient, each
2489 * specified as a center coordinate and a radius.
2491 * Return value: %CAIRO_STATUS_SUCCESS, or
2492 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial
2498 cairo_pattern_get_radial_circles (cairo_pattern_t
*pattern
,
2499 double *x0
, double *y0
, double *r0
,
2500 double *x1
, double *y1
, double *r1
)
2502 cairo_radial_pattern_t
*radial
= (cairo_radial_pattern_t
*) pattern
;
2504 if (pattern
->type
!= CAIRO_PATTERN_TYPE_RADIAL
)
2505 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
2508 *x0
= _cairo_fixed_to_double (radial
->c1
.x
);
2510 *y0
= _cairo_fixed_to_double (radial
->c1
.y
);
2512 *r0
= _cairo_fixed_to_double (radial
->r1
);
2514 *x1
= _cairo_fixed_to_double (radial
->c2
.x
);
2516 *y1
= _cairo_fixed_to_double (radial
->c2
.y
);
2518 *r1
= _cairo_fixed_to_double (radial
->r2
);
2520 return CAIRO_STATUS_SUCCESS
;
2524 _cairo_pattern_reset_static_data (void)
2526 _cairo_pattern_reset_solid_pattern_cache ();
2527 _cairo_pattern_reset_solid_surface_cache ();