added MouseWheel event support for Silverlight 3.0
[moon.git] / cairo / src / cairo-pattern.c
blob81fa62ad5a6e8c3c9faeb8a2eb2a12c0d95179e8
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>
31 #include "cairoint.h"
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 */
63 /**
64 * _cairo_pattern_set_error:
65 * @pattern: a pattern
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
74 * objects.
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.
79 **/
80 static cairo_status_t
81 _cairo_pattern_set_error (cairo_pattern_t *pattern,
82 cairo_status_t status)
84 if (status == CAIRO_STATUS_SUCCESS)
85 return status;
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);
94 static void
95 _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
97 pattern->type = 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;
108 else
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;
125 *dst = *src;
127 else
129 cairo_radial_pattern_t *dst = (cairo_radial_pattern_t *) pattern;
130 cairo_radial_pattern_t *src = (cairo_radial_pattern_t *) other;
132 *dst = *src;
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;
154 cairo_status_t
155 _cairo_pattern_init_copy (cairo_pattern_t *pattern,
156 const cairo_pattern_t *other)
158 if (other->status)
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;
166 *dst = *src;
167 } break;
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;
172 *dst = *src;
173 cairo_surface_reference (dst->surface);
174 } break;
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);
182 if (status)
183 return status;
185 } break;
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;
195 cairo_status_t
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);
204 if (status)
205 return status;
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;
225 void
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:
232 break;
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);
238 } break;
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);
246 } break;
250 cairo_status_t
251 _cairo_pattern_create_copy (cairo_pattern_t **pattern,
252 const cairo_pattern_t *other)
254 cairo_status_t status;
256 if (other->status)
257 return other->status;
259 switch (other->type) {
260 case CAIRO_PATTERN_TYPE_SOLID:
261 *pattern = malloc (sizeof (cairo_solid_pattern_t));
262 break;
263 case CAIRO_PATTERN_TYPE_SURFACE:
264 *pattern = malloc (sizeof (cairo_surface_pattern_t));
265 break;
266 case CAIRO_PATTERN_TYPE_LINEAR:
267 *pattern = malloc (sizeof (cairo_linear_pattern_t));
268 break;
269 case CAIRO_PATTERN_TYPE_RADIAL:
270 *pattern = malloc (sizeof (cairo_radial_pattern_t));
271 break;
273 if (*pattern == NULL)
274 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
276 status = _cairo_pattern_init_copy (*pattern, other);
277 if (status) {
278 free (*pattern);
279 return status;
282 CAIRO_REFERENCE_COUNT_INIT (&(*pattern)->ref_count, 1);
284 return CAIRO_STATUS_SUCCESS;
288 void
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;
301 void
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);
309 return;
312 _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SURFACE);
314 pattern->surface = cairo_surface_reference (surface);
317 static void
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;
328 void
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);
340 void
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
358 static struct {
359 cairo_solid_pattern_t *patterns[MAX_PATTERN_CACHE_SIZE];
360 int size;
361 } solid_pattern_cache;
363 cairo_pattern_t *
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;
388 } else {
389 _cairo_pattern_init_solid (pattern, color, content);
390 CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
393 return &pattern->base;
396 static void
397 _cairo_pattern_reset_solid_pattern_cache (void)
399 int i;
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);
427 return pattern;
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
439 * clamped.
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
444 * finished with it.
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().
450 cairo_pattern_t *
451 cairo_pattern_create_rgb (double red, double green, double blue)
453 cairo_color_t color;
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
477 * clamped.
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
482 * finished with it.
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().
488 cairo_pattern_t *
489 cairo_pattern_create_rgba (double red, double green, double blue,
490 double alpha)
492 cairo_color_t color;
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
516 * finished with it.
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().
522 cairo_pattern_t *
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;
532 if (surface->status)
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
570 * finished with it.
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().
576 cairo_pattern_t *
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
617 * finished with it.
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().
623 cairo_pattern_t *
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.
656 cairo_pattern_t *
657 cairo_pattern_reference (cairo_pattern_t *pattern)
659 if (pattern == NULL ||
660 CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
661 return pattern;
663 assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
665 _cairo_reference_count_inc (&pattern->ref_count);
667 return pattern;
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.
680 * Since: 1.2
682 cairo_pattern_type_t
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
694 * pattern.
696 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NO_MEMORY, or
697 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
699 cairo_status_t
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().
714 void
715 cairo_pattern_destroy (cairo_pattern_t *pattern)
717 if (pattern == NULL ||
718 CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
719 return;
721 assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
723 if (! _cairo_reference_count_dec_and_test (&pattern->ref_count))
724 return;
726 _cairo_pattern_fini (pattern);
728 /* maintain a small cache of freed patterns */
729 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
730 int i;
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);
743 } else {
744 free (pattern);
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.
758 * Since: 1.4
760 unsigned int
761 cairo_pattern_get_reference_count (cairo_pattern_t *pattern)
763 if (pattern == NULL ||
764 CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
765 return 0;
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
774 * attached to
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.
782 * Since: 1.4
784 void *
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,
789 key);
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
799 * same key.
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
803 * for @data.
805 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
806 * slot could not be allocated for the user data.
808 * Since: 1.4
810 cairo_status_t
811 cairo_pattern_set_user_data (cairo_pattern_t *pattern,
812 const cairo_user_data_key_t *key,
813 void *user_data,
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
833 * from there. */
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));
844 if (new_stops)
845 memcpy (new_stops, pattern->stops, old_size * sizeof (cairo_gradient_stop_t));
846 } else {
847 new_stops = _cairo_realloc_ab (pattern->stops,
848 new_size,
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;
861 static void
862 _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
863 double offset,
864 double red,
865 double green,
866 double blue,
867 double alpha)
869 cairo_gradient_stop_t *stops;
870 unsigned int i;
872 if (pattern->n_stops >= pattern->stops_size) {
873 cairo_status_t status = _cairo_pattern_gradient_grow (pattern);
874 if (status) {
875 status = _cairo_pattern_set_error (&pattern->base, status);
876 return;
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));
889 break;
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);
905 pattern->n_stops++;
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.
935 void
936 cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
937 double offset,
938 double red,
939 double green,
940 double blue)
942 if (pattern->status)
943 return;
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);
949 return;
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.
988 void
989 cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
990 double offset,
991 double red,
992 double green,
993 double blue,
994 double alpha)
996 if (pattern->status)
997 return;
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);
1003 return;
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 (&amp;matrix, 0.5, 0.5);
1039 * cairo_pattern_set_matrix (pattern, &amp;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().
1048 void
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)
1056 return;
1058 pattern->matrix = *matrix;
1060 inverse = *matrix;
1061 status = cairo_matrix_invert (&inverse);
1062 if (status)
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.
1074 void
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
1084 * the pattern
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>
1100 void
1101 cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
1103 if (pattern->status)
1104 return;
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.
1118 cairo_filter_t
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
1132 * strategy.
1134 * The default extend mode is %CAIRO_EXTEND_NONE for surface patterns
1135 * and %CAIRO_EXTEND_PAD for gradient patterns.
1137 void
1138 cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
1140 if (pattern->status)
1141 return;
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
1154 * pattern.
1156 cairo_extend_t
1157 cairo_pattern_get_extend (cairo_pattern_t *pattern)
1159 return pattern->extend;
1161 slim_hidden_def (cairo_pattern_get_extend);
1163 void
1164 _cairo_pattern_transform (cairo_pattern_t *pattern,
1165 const cairo_matrix_t *ctm_inverse)
1167 if (pattern->status)
1168 return;
1170 cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
1173 static void
1174 _cairo_linear_pattern_classify (cairo_linear_pattern_t *pattern,
1175 double offset_x,
1176 double offset_y,
1177 int width,
1178 int height,
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];
1186 int i;
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
1191 * fourth.
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,
1234 int x,
1235 int y,
1236 unsigned int width,
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;
1249 unsigned int i;
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)
1290 double sf;
1292 if (xdim > ydim)
1293 sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (xdim);
1294 else
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);
1304 else
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,
1313 pixman_stops,
1314 pattern->n_stops);
1316 else
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,
1331 r1, r2,
1332 pixman_stops,
1333 pattern->n_stops);
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,
1346 PIXMAN_a8r8g8b8);
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) {
1372 height = 1;
1373 repeat = TRUE;
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) {
1383 width = 8;
1384 repeat = TRUE;
1388 if (! pixman_image_set_filter (pixman_image, PIXMAN_FILTER_BILINEAR,
1389 NULL, 0))
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);
1412 break;
1413 case CAIRO_EXTEND_REPEAT:
1414 pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NORMAL);
1415 break;
1416 case CAIRO_EXTEND_REFLECT:
1417 pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_REFLECT);
1418 break;
1419 case CAIRO_EXTEND_PAD:
1420 pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_PAD);
1421 break;
1424 pixman_image_composite (PIXMAN_OP_SRC,
1425 pixman_image,
1426 NULL,
1427 image->pixman_image,
1428 x, y,
1429 0, 0,
1430 0, 0,
1431 width, height);
1433 pixman_image_unref (pixman_image);
1435 status = _cairo_surface_clone_similar (dst, &image->base,
1436 0, 0, width, height,
1437 &clone_offset_x,
1438 &clone_offset_y,
1439 out);
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;
1450 return status;
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
1456 static struct {
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];
1462 int size;
1463 } solid_surface_cache;
1465 static cairo_bool_t
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)
1472 return FALSE;
1474 if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache->surface->ref_count) != 1)
1475 return FALSE;
1477 if (! _cairo_surface_is_similar (cache->surface, dst, pattern->content))
1478 return FALSE;
1480 return TRUE;
1483 static cairo_bool_t
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))
1490 return FALSE;
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,
1498 int x,
1499 int y,
1500 unsigned int width,
1501 unsigned int height,
1502 cairo_surface_t **out,
1503 cairo_surface_attributes_t *attribs)
1505 static int i;
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],
1515 pattern,
1516 dst))
1518 status = _cairo_surface_reset (solid_surface_cache.cache[i].surface);
1519 if (status)
1520 goto UNLOCK;
1522 goto DONE;
1525 for (i = 0 ; i < solid_surface_cache.size; i++) {
1526 if (_cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i],
1527 pattern,
1528 dst))
1530 status = _cairo_surface_reset (solid_surface_cache.cache[i].surface);
1531 if (status)
1532 goto UNLOCK;
1534 goto DONE;
1538 /* Choose a surface to repaint/evict */
1539 surface = NULL;
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],
1545 pattern,
1546 dst))
1548 /* Reuse the surface instead of evicting */
1550 status = _cairo_surface_reset (surface);
1551 if (status)
1552 goto EVICT;
1554 status = _cairo_surface_repaint_solid_pattern_surface (dst, surface, pattern);
1555 if (status)
1556 goto EVICT;
1558 cairo_surface_reference (surface);
1560 else
1562 EVICT:
1563 surface = NULL;
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;
1572 goto UNLOCK;
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 */
1578 *out = surface;
1579 goto NOCACHE;
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;
1591 DONE:
1592 *out = cairo_surface_reference (solid_surface_cache.cache[i].surface);
1594 NOCACHE:
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;
1603 UNLOCK:
1604 CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
1606 if (to_destroy)
1607 cairo_surface_destroy (to_destroy);
1609 return status;
1612 static void
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.
1647 cairo_bool_t
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)
1653 return FALSE;
1655 solid = (cairo_solid_pattern_t *) pattern;
1657 return CAIRO_COLOR_IS_OPAQUE (&solid->color);
1660 static cairo_bool_t
1661 _gradient_is_opaque (const cairo_gradient_pattern_t *gradient)
1663 unsigned int i;
1665 for (i = 0; i < gradient->n_stops; i++)
1666 if (! CAIRO_COLOR_IS_OPAQUE (&gradient->stops[i].color))
1667 return FALSE;
1669 return TRUE;
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.
1681 cairo_bool_t
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);
1697 ASSERT_NOT_REACHED;
1698 return FALSE;
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,
1717 double *pad_out)
1719 double pad;
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)) {
1731 pad = 0.;
1732 optimized_filter = CAIRO_FILTER_NEAREST;
1733 } else {
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...
1739 pad = 0.5;
1740 optimized_filter = pattern->base.filter;
1742 break;
1744 case CAIRO_FILTER_FAST:
1745 case CAIRO_FILTER_NEAREST:
1746 case CAIRO_FILTER_GAUSSIAN:
1747 default:
1748 pad = 0.;
1749 optimized_filter = pattern->base.filter;
1750 break;
1753 if (pad_out)
1754 *pad_out = pad;
1756 return optimized_filter;
1760 static double
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,
1769 int x,
1770 int y,
1771 unsigned int width,
1772 unsigned int height,
1773 cairo_surface_t **out,
1774 cairo_surface_attributes_t *attr)
1776 cairo_int_status_t status;
1777 int tx, ty;
1778 double pad;
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,
1786 &tx, &ty))
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);
1809 } else {
1810 attr->matrix.x0 = pattern->base.matrix.x0;
1811 attr->matrix.y0 = pattern->base.matrix.y0;
1814 attr->x_offset = attr->y_offset = 0;
1815 tx = ty = 0;
1817 else
1819 attr->matrix = pattern->base.matrix;
1820 attr->x_offset = attr->y_offset = 0;
1821 tx = 0;
1822 ty = 0;
1825 /* XXX: Hack:
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) {
1837 cairo_t *cr;
1838 int w,h;
1840 cairo_rectangle_int_t extents;
1841 status = _cairo_surface_get_extents (pattern->surface, &extents);
1842 if (status)
1843 return status;
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
1852 * of current four.
1854 x = extents.x;
1855 y = extents.y;
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);
1861 if (status) {
1862 cairo_surface_destroy (*out);
1863 *out = NULL;
1864 return status;
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);
1873 cairo_paint (cr);
1875 cairo_scale (cr, -1, +1);
1876 cairo_set_source_surface (cr, pattern->surface, x-w, -y);
1877 cairo_paint (cr);
1879 cairo_scale (cr, +1, -1);
1880 cairo_set_source_surface (cr, pattern->surface, x-w, y-h);
1881 cairo_paint (cr);
1883 cairo_scale (cr, -1, +1);
1884 cairo_set_source_surface (cr, pattern->surface, -x, y-h);
1885 cairo_paint (cr);
1887 status = cairo_status (cr);
1888 cairo_destroy (cr);
1890 if (status) {
1891 cairo_surface_destroy (*out);
1892 *out = NULL;
1895 return status;
1898 if (_cairo_surface_is_image (dst)) {
1899 cairo_image_surface_t *image;
1901 status = _cairo_surface_acquire_source_image (pattern->surface,
1902 &image,
1903 &attr->extra);
1904 if (status)
1905 return status;
1907 *out = &image->base;
1908 attr->acquired = TRUE;
1909 } else {
1910 cairo_rectangle_int_t extents;
1911 cairo_bool_t is_empty;
1913 status = _cairo_surface_get_extents (pattern->surface, &extents);
1914 if (status)
1915 return status;
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
1926 * read.
1928 if (_cairo_matrix_is_identity (&attr->matrix)) {
1929 sampled_area.x = x;
1930 sampled_area.y = y;
1931 sampled_area.width = width;
1932 sampled_area.height = height;
1933 } else {
1934 double x1 = x;
1935 double y1 = y;
1936 double x2 = x + (int) width;
1937 double y2 = y + (int) height;
1939 _cairo_matrix_transform_bounding_box (&attr->matrix,
1940 &x1, &y1, &x2, &y2,
1941 NULL);
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,
1962 &x, &y, out);
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;
1967 } else {
1968 cairo_matrix_t m;
1970 x -= attr->x_offset;
1971 y -= attr->y_offset;
1972 attr->x_offset = 0;
1973 attr->y_offset = 0;
1975 cairo_matrix_init_translate (&m, -x, -y);
1976 cairo_matrix_multiply (&attr->matrix, &attr->matrix, &m);
1981 return status;
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
1997 * drawing on @dst.
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.
2004 cairo_int_status_t
2005 _cairo_pattern_acquire_surface (cairo_pattern_t *pattern,
2006 cairo_surface_t *dst,
2007 int x,
2008 int y,
2009 unsigned int width,
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,
2028 surface_out,
2029 attributes);
2030 } break;
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;
2040 if (src->n_stops)
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);
2052 else
2054 _cairo_pattern_init_solid (&solid, CAIRO_COLOR_TRANSPARENT, CAIRO_CONTENT_ALPHA);
2057 status = _cairo_pattern_acquire_surface_for_solid (&solid, dst,
2058 x, y,
2059 width, height,
2060 surface_out,
2061 attributes);
2063 else
2065 status = _cairo_pattern_acquire_surface_for_gradient (src, dst,
2066 x, y,
2067 width, height,
2068 surface_out,
2069 attributes);
2071 } break;
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,
2077 surface_out,
2078 attributes);
2079 } break;
2080 default:
2081 ASSERT_NOT_REACHED;
2082 status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
2085 return status;
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.
2096 void
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,
2110 attributes->extra);
2112 else
2114 cairo_surface_destroy (surface);
2118 cairo_int_status_t
2119 _cairo_pattern_acquire_surfaces (cairo_pattern_t *src,
2120 cairo_pattern_t *mask,
2121 cairo_surface_t *dst,
2122 int src_x,
2123 int src_y,
2124 int mask_x,
2125 int mask_y,
2126 unsigned int width,
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;
2136 if (src->status)
2137 return src->status;
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);
2159 mask = NULL;
2161 else
2163 status = _cairo_pattern_init_copy (&src_tmp.base, src);
2164 if (status)
2165 return status;
2168 status = _cairo_pattern_acquire_surface (&src_tmp.base, dst,
2169 src_x, src_y,
2170 width, height,
2171 src_out, src_attributes);
2172 if (status) {
2173 _cairo_pattern_fini (&src_tmp.base);
2174 return status;
2177 if (mask == NULL)
2179 _cairo_pattern_fini (&src_tmp.base);
2180 *mask_out = NULL;
2181 return CAIRO_STATUS_SUCCESS;
2184 status = _cairo_pattern_init_copy (&mask_tmp.base, mask);
2185 if (status)
2186 goto CLEANUP_SOURCE;
2188 status = _cairo_pattern_acquire_surface (&mask_tmp.base, dst,
2189 mask_x, mask_y,
2190 width, height,
2191 mask_out, mask_attributes);
2193 _cairo_pattern_fini (&mask_tmp.base);
2195 CLEANUP_SOURCE:
2196 if (status)
2197 _cairo_pattern_release_surface (&src_tmp.base,
2198 *src_out, src_attributes);
2200 _cairo_pattern_fini (&src_tmp.base);
2202 return status;
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.
2217 cairo_status_t
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;
2231 double pad;
2233 status = _cairo_surface_get_extents (surface, &surface_extents);
2234 if (status)
2235 return status;
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,
2252 &x1, &y1, &x2, &y2,
2253 NULL);
2255 x1 = floor (x1);
2256 if (x1 < CAIRO_RECT_INT_MIN)
2257 x1 = CAIRO_RECT_INT_MIN;
2258 y1 = floor (y1);
2259 if (y1 < CAIRO_RECT_INT_MIN)
2260 y1 = CAIRO_RECT_INT_MIN;
2262 x2 = ceil (x2);
2263 if (x2 > CAIRO_RECT_INT_MAX)
2264 x2 = CAIRO_RECT_INT_MAX;
2265 y2 = ceil (y2);
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
2301 * color pattern.
2303 * Since: 1.4
2305 cairo_status_t
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);
2318 if (red)
2319 *red = r0;
2320 if (green)
2321 *green = g0;
2322 if (blue)
2323 *blue = b0;
2324 if (alpha)
2325 *alpha = 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
2341 * pattern.
2343 * Since: 1.4
2345 cairo_status_t
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);
2354 if (surface)
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
2377 * returned.
2379 * Since: 1.4
2381 cairo_status_t
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);
2396 if (offset)
2397 *offset = gradient->stops[index].offset;
2398 if (red)
2399 *red = gradient->stops[index].color.red;
2400 if (green)
2401 *green = gradient->stops[index].color.green;
2402 if (blue)
2403 *blue = gradient->stops[index].color.blue;
2404 if (alpha)
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
2416 * pattern.
2418 * Return value: %CAIRO_STATUS_SUCCESS, or
2419 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
2420 * pattern.
2422 * Since: 1.4
2424 cairo_status_t
2425 cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
2426 int *count)
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);
2434 if (count)
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
2452 * gradient pattern.
2454 * Since: 1.4
2456 cairo_status_t
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);
2466 if (x0)
2467 *x0 = _cairo_fixed_to_double (linear->p1.x);
2468 if (y0)
2469 *y0 = _cairo_fixed_to_double (linear->p1.y);
2470 if (x1)
2471 *x1 = _cairo_fixed_to_double (linear->p2.x);
2472 if (y1)
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
2493 * gradient pattern.
2495 * Since: 1.4
2497 cairo_status_t
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);
2507 if (x0)
2508 *x0 = _cairo_fixed_to_double (radial->c1.x);
2509 if (y0)
2510 *y0 = _cairo_fixed_to_double (radial->c1.y);
2511 if (r0)
2512 *r0 = _cairo_fixed_to_double (radial->r1);
2513 if (x1)
2514 *x1 = _cairo_fixed_to_double (radial->c2.x);
2515 if (y1)
2516 *y1 = _cairo_fixed_to_double (radial->c2.y);
2517 if (r1)
2518 *r1 = _cairo_fixed_to_double (radial->r2);
2520 return CAIRO_STATUS_SUCCESS;
2523 void
2524 _cairo_pattern_reset_static_data (void)
2526 _cairo_pattern_reset_solid_pattern_cache ();
2527 _cairo_pattern_reset_solid_surface_cache ();