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 #include "cairo-array-private.h"
34 #include "cairo-error-private.h"
35 #include "cairo-freed-pool-private.h"
36 #include "cairo-image-surface-private.h"
37 #include "cairo-list-inline.h"
38 #include "cairo-path-private.h"
39 #include "cairo-pattern-private.h"
40 #include "cairo-recording-surface-inline.h"
41 #include "cairo-surface-snapshot-inline.h"
45 #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
48 * SECTION:cairo-pattern
49 * @Title: cairo_pattern_t
50 * @Short_Description: Sources for drawing
51 * @See_Also: #cairo_t, #cairo_surface_t
53 * #cairo_pattern_t is the paint with which cairo draws.
54 * The primary use of patterns is as the source for all cairo drawing
55 * operations, although they can also be used as masks, that is, as the
58 * A cairo pattern is created by using one of the many constructors,
60 * <function>cairo_pattern_create_<emphasis>type</emphasis>()</function>
61 * or implicitly through
62 * <function>cairo_set_source_<emphasis>type</emphasis>()</function>
66 static freed_pool_t freed_pattern_pool[5];
68 static const cairo_solid_pattern_t _cairo_pattern_nil = {
70 CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
71 CAIRO_STATUS_NO_MEMORY, /* status */
72 { 0, 0, 0, NULL }, /* user_data */
73 { NULL, NULL }, /* observers */
75 CAIRO_PATTERN_TYPE_SOLID, /* type */
76 CAIRO_FILTER_DEFAULT, /* filter */
77 CAIRO_EXTEND_GRADIENT_DEFAULT, /* extend */
78 FALSE, /* has component alpha */
79 { 1., 0., 0., 1., 0., 0., }, /* matrix */
84 static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = {
86 CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
87 CAIRO_STATUS_NULL_POINTER, /* status */
88 { 0, 0, 0, NULL }, /* user_data */
89 { NULL, NULL }, /* observers */
91 CAIRO_PATTERN_TYPE_SOLID, /* type */
92 CAIRO_FILTER_DEFAULT, /* filter */
93 CAIRO_EXTEND_GRADIENT_DEFAULT, /* extend */
94 FALSE, /* has component alpha */
95 { 1., 0., 0., 1., 0., 0., }, /* matrix */
100 const cairo_solid_pattern_t _cairo_pattern_black = {
102 CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
103 CAIRO_STATUS_SUCCESS, /* status */
104 { 0, 0, 0, NULL }, /* user_data */
105 { NULL, NULL }, /* observers */
107 CAIRO_PATTERN_TYPE_SOLID, /* type */
108 CAIRO_FILTER_NEAREST, /* filter */
109 CAIRO_EXTEND_REPEAT, /* extend */
110 FALSE, /* has component alpha */
111 { 1., 0., 0., 1., 0., 0., }, /* matrix */
114 { 0., 0., 0., 1., 0, 0, 0, 0xffff },/* color (double rgba, short rgba) */
117 const cairo_solid_pattern_t _cairo_pattern_clear = {
119 CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
120 CAIRO_STATUS_SUCCESS, /* status */
121 { 0, 0, 0, NULL }, /* user_data */
122 { NULL, NULL }, /* observers */
124 CAIRO_PATTERN_TYPE_SOLID, /* type */
125 CAIRO_FILTER_NEAREST, /* filter */
126 CAIRO_EXTEND_REPEAT, /* extend */
127 FALSE, /* has component alpha */
128 { 1., 0., 0., 1., 0., 0., }, /* matrix */
131 { 0., 0., 0., 0., 0, 0, 0, 0 },/* color (double rgba, short rgba) */
134 const cairo_solid_pattern_t _cairo_pattern_white = {
136 CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
137 CAIRO_STATUS_SUCCESS, /* status */
138 { 0, 0, 0, NULL }, /* user_data */
139 { NULL, NULL }, /* observers */
141 CAIRO_PATTERN_TYPE_SOLID, /* type */
142 CAIRO_FILTER_NEAREST, /* filter */
143 CAIRO_EXTEND_REPEAT, /* extend */
144 FALSE, /* has component alpha */
145 { 1., 0., 0., 1., 0., 0., }, /* matrix */
148 { 1., 1., 1., 1., 0xffff, 0xffff, 0xffff, 0xffff },/* color (double rgba, short rgba) */
152 _cairo_pattern_notify_observers (cairo_pattern_t *pattern,
155 cairo_pattern_observer_t *pos;
157 cairo_list_foreach_entry (pos, cairo_pattern_observer_t, &pattern->observers, link)
158 pos->notify (pos, pattern, flags);
162 * _cairo_pattern_set_error:
163 * @pattern: a pattern
164 * @status: a status value indicating an error
166 * Atomically sets pattern->status to @status and calls _cairo_error;
167 * Does nothing if status is %CAIRO_STATUS_SUCCESS.
169 * All assignments of an error status to pattern->status should happen
170 * through _cairo_pattern_set_error(). Note that due to the nature of
171 * the atomic operation, it is not safe to call this function on the nil
174 * The purpose of this function is to allow the user to set a
175 * breakpoint in _cairo_error() to generate a stack trace for when the
176 * user causes cairo to detect an error.
178 static cairo_status_t
179 _cairo_pattern_set_error (cairo_pattern_t *pattern,
180 cairo_status_t status)
182 if (status == CAIRO_STATUS_SUCCESS)
185 /* Don't overwrite an existing error. This preserves the first
186 * error, which is the most significant. */
187 _cairo_status_set_error (&pattern->status, status);
189 return _cairo_error (status);
193 _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
197 case CAIRO_PATTERN_TYPE_SOLID:
198 VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t));
200 case CAIRO_PATTERN_TYPE_SURFACE:
201 VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t));
203 case CAIRO_PATTERN_TYPE_LINEAR:
204 VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t));
206 case CAIRO_PATTERN_TYPE_RADIAL:
207 VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t));
209 case CAIRO_PATTERN_TYPE_MESH:
210 VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t));
212 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
217 pattern->type = type;
218 pattern->status = CAIRO_STATUS_SUCCESS;
220 /* Set the reference count to zero for on-stack patterns.
221 * Callers needs to explicitly increment the count for heap allocations. */
222 CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
224 _cairo_user_data_array_init (&pattern->user_data);
226 if (type == CAIRO_PATTERN_TYPE_SURFACE ||
227 type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
228 pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
230 pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT;
232 pattern->filter = CAIRO_FILTER_DEFAULT;
233 pattern->opacity = 1.0;
235 pattern->has_component_alpha = FALSE;
237 cairo_matrix_init_identity (&pattern->matrix);
239 cairo_list_init (&pattern->observers);
241 pattern->x_sigma = 0.0f;
242 pattern->y_sigma = 0.0;
243 pattern->x_radius = 0;
244 pattern->y_radius = 0;
245 pattern->convolution_matrix = NULL;
246 pattern->convolution_changed = FALSE;
248 memset (&pattern->shadow, 0, sizeof (cairo_shadow_t));
251 static cairo_status_t
252 _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
253 const cairo_gradient_pattern_t *other)
255 if (CAIRO_INJECT_FAULT ())
256 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
258 if (other->base.type == CAIRO_PATTERN_TYPE_LINEAR)
260 cairo_linear_pattern_t *dst = (cairo_linear_pattern_t *) pattern;
261 cairo_linear_pattern_t *src = (cairo_linear_pattern_t *) other;
267 cairo_radial_pattern_t *dst = (cairo_radial_pattern_t *) pattern;
268 cairo_radial_pattern_t *src = (cairo_radial_pattern_t *) other;
273 if (other->stops == other->stops_embedded)
274 pattern->stops = pattern->stops_embedded;
275 else if (other->stops)
277 pattern->stops = _cairo_malloc_ab (other->stops_size,
278 sizeof (cairo_gradient_stop_t));
279 if (unlikely (pattern->stops == NULL)) {
280 pattern->stops_size = 0;
281 pattern->n_stops = 0;
282 return _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
285 memcpy (pattern->stops, other->stops,
286 other->n_stops * sizeof (cairo_gradient_stop_t));
289 return CAIRO_STATUS_SUCCESS;
292 static cairo_status_t
293 _cairo_mesh_pattern_init_copy (cairo_mesh_pattern_t *pattern,
294 const cairo_mesh_pattern_t *other)
299 _cairo_array_init (&pattern->patches, sizeof (cairo_mesh_patch_t));
300 data = _cairo_array_index_const (&other->patches, 0);
302 return CAIRO_STATUS_NULL_POINTER;
303 return _cairo_array_append_multiple (&pattern->patches,
305 _cairo_array_num_elements (&other->patches));
309 _cairo_pattern_init_copy (cairo_pattern_t *pattern,
310 const cairo_pattern_t *other)
312 cairo_status_t status;
315 return _cairo_pattern_set_error (pattern, other->status);
317 switch (other->type) {
318 case CAIRO_PATTERN_TYPE_SOLID: {
319 cairo_solid_pattern_t *dst = (cairo_solid_pattern_t *) pattern;
320 cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) other;
322 VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t)));
326 case CAIRO_PATTERN_TYPE_SURFACE: {
327 cairo_surface_pattern_t *dst = (cairo_surface_pattern_t *) pattern;
328 cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) other;
330 VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t)));
333 cairo_surface_reference (dst->surface);
335 case CAIRO_PATTERN_TYPE_LINEAR:
336 case CAIRO_PATTERN_TYPE_RADIAL: {
337 cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern;
338 cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other;
340 if (other->type == CAIRO_PATTERN_TYPE_LINEAR) {
341 VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t)));
343 VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t)));
346 status = _cairo_gradient_pattern_init_copy (dst, src);
347 if (unlikely (status))
351 case CAIRO_PATTERN_TYPE_MESH: {
352 cairo_mesh_pattern_t *dst = (cairo_mesh_pattern_t *) pattern;
353 cairo_mesh_pattern_t *src = (cairo_mesh_pattern_t *) other;
355 VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t)));
357 status = _cairo_mesh_pattern_init_copy (dst, src);
358 if (unlikely (status))
363 case CAIRO_PATTERN_TYPE_RASTER_SOURCE: {
364 status = _cairo_raster_source_pattern_init_copy (pattern, other);
365 if (unlikely (status))
370 /* The reference count and user_data array are unique to the copy. */
371 CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
372 _cairo_user_data_array_init (&pattern->user_data);
374 /* make separate copy of convolution matrix */
375 if (other->convolution_matrix) {
376 int col = 2 * other->x_radius + 1;
377 int row = 2 * other->y_radius + 1;
378 int size = row * col;
380 pattern->convolution_matrix = _cairo_malloc_ab (size, sizeof(double));
381 if (pattern->convolution_matrix == NULL)
382 return CAIRO_STATUS_NO_MEMORY;
384 memcpy (pattern->convolution_matrix, other->convolution_matrix,
385 sizeof (double) * size);
388 return CAIRO_STATUS_SUCCESS;
392 _cairo_pattern_init_static_copy (cairo_pattern_t *pattern,
393 const cairo_pattern_t *other)
397 assert (other->status == CAIRO_STATUS_SUCCESS);
399 switch (other->type) {
402 case CAIRO_PATTERN_TYPE_SOLID:
403 size = sizeof (cairo_solid_pattern_t);
405 case CAIRO_PATTERN_TYPE_SURFACE:
406 size = sizeof (cairo_surface_pattern_t);
408 case CAIRO_PATTERN_TYPE_LINEAR:
409 size = sizeof (cairo_linear_pattern_t);
411 case CAIRO_PATTERN_TYPE_RADIAL:
412 size = sizeof (cairo_radial_pattern_t);
414 case CAIRO_PATTERN_TYPE_MESH:
415 size = sizeof (cairo_mesh_pattern_t);
417 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
418 size = sizeof (cairo_raster_source_pattern_t);
422 memcpy (pattern, other, size);
424 CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
425 _cairo_user_data_array_init (&pattern->user_data);
429 _cairo_pattern_init_snapshot (cairo_pattern_t *pattern,
430 const cairo_pattern_t *other)
432 cairo_status_t status;
434 /* We don't bother doing any fancy copy-on-write implementation
435 * for the pattern's data. It's generally quite tiny. */
436 status = _cairo_pattern_init_copy (pattern, other);
437 if (unlikely (status))
440 /* But we do let the surface snapshot stuff be as fancy as it
441 * would like to be. */
442 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
443 cairo_surface_pattern_t *surface_pattern =
444 (cairo_surface_pattern_t *) pattern;
445 cairo_surface_t *surface = surface_pattern->surface;
447 surface_pattern->surface = _cairo_surface_snapshot (surface);
449 cairo_surface_destroy (surface);
451 status = surface_pattern->surface->status;
452 } else if (pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
453 status = _cairo_raster_source_pattern_snapshot (pattern);
459 _cairo_pattern_fini (cairo_pattern_t *pattern)
461 _cairo_user_data_array_fini (&pattern->user_data);
463 switch (pattern->type) {
464 case CAIRO_PATTERN_TYPE_SOLID:
466 case CAIRO_PATTERN_TYPE_SURFACE: {
467 cairo_surface_pattern_t *surface_pattern =
468 (cairo_surface_pattern_t *) pattern;
470 cairo_surface_destroy (surface_pattern->surface);
472 case CAIRO_PATTERN_TYPE_LINEAR:
473 case CAIRO_PATTERN_TYPE_RADIAL: {
474 cairo_gradient_pattern_t *gradient =
475 (cairo_gradient_pattern_t *) pattern;
477 if (gradient->stops && gradient->stops != gradient->stops_embedded)
478 free (gradient->stops);
480 case CAIRO_PATTERN_TYPE_MESH: {
481 cairo_mesh_pattern_t *mesh =
482 (cairo_mesh_pattern_t *) pattern;
484 _cairo_array_fini (&mesh->patches);
486 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
487 _cairo_raster_source_pattern_finish (pattern);
491 if (pattern->convolution_matrix)
492 free (pattern->convolution_matrix);
495 switch (pattern->type) {
496 case CAIRO_PATTERN_TYPE_SOLID:
497 VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_solid_pattern_t));
499 case CAIRO_PATTERN_TYPE_SURFACE:
500 VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_surface_pattern_t));
502 case CAIRO_PATTERN_TYPE_LINEAR:
503 VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_linear_pattern_t));
505 case CAIRO_PATTERN_TYPE_RADIAL:
506 VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_radial_pattern_t));
508 case CAIRO_PATTERN_TYPE_MESH:
509 VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_mesh_pattern_t));
511 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
518 _cairo_pattern_create_copy (cairo_pattern_t **pattern_out,
519 const cairo_pattern_t *other)
521 cairo_pattern_t *pattern;
522 cairo_status_t status;
525 return other->status;
527 switch (other->type) {
528 case CAIRO_PATTERN_TYPE_SOLID:
529 pattern = malloc (sizeof (cairo_solid_pattern_t));
531 case CAIRO_PATTERN_TYPE_SURFACE:
532 pattern = malloc (sizeof (cairo_surface_pattern_t));
534 case CAIRO_PATTERN_TYPE_LINEAR:
535 pattern = malloc (sizeof (cairo_linear_pattern_t));
537 case CAIRO_PATTERN_TYPE_RADIAL:
538 pattern = malloc (sizeof (cairo_radial_pattern_t));
540 case CAIRO_PATTERN_TYPE_MESH:
541 pattern = malloc (sizeof (cairo_mesh_pattern_t));
543 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
544 pattern = malloc (sizeof (cairo_raster_source_pattern_t));
548 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
550 if (unlikely (pattern == NULL))
551 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
553 status = _cairo_pattern_init_copy (pattern, other);
554 if (unlikely (status)) {
559 CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
560 *pattern_out = pattern;
561 return CAIRO_STATUS_SUCCESS;
565 _cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
566 const cairo_color_t *color)
568 _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
569 pattern->color = *color;
573 _cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern,
574 cairo_surface_t *surface)
576 if (surface->status) {
577 /* Force to solid to simplify the pattern_fini process. */
578 _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
579 _cairo_pattern_set_error (&pattern->base, surface->status);
583 _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SURFACE);
585 pattern->surface = cairo_surface_reference (surface);
589 _cairo_pattern_init_gradient (cairo_gradient_pattern_t *pattern,
590 cairo_pattern_type_t type)
592 _cairo_pattern_init (&pattern->base, type);
594 pattern->n_stops = 0;
595 pattern->stops_size = 0;
596 pattern->stops = NULL;
600 _cairo_pattern_init_linear (cairo_linear_pattern_t *pattern,
601 double x0, double y0, double x1, double y1)
603 _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_LINEAR);
612 _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
613 double cx0, double cy0, double radius0,
614 double cx1, double cy1, double radius1)
616 _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL);
618 pattern->cd1.center.x = cx0;
619 pattern->cd1.center.y = cy0;
620 pattern->cd1.radius = fabs (radius0);
621 pattern->cd2.center.x = cx1;
622 pattern->cd2.center.y = cy1;
623 pattern->cd2.radius = fabs (radius1);
627 _cairo_pattern_create_solid (const cairo_color_t *color)
629 cairo_solid_pattern_t *pattern;
632 _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SOLID]);
633 if (unlikely (pattern == NULL)) {
634 /* None cached, need to create a new pattern. */
635 pattern = malloc (sizeof (cairo_solid_pattern_t));
636 if (unlikely (pattern == NULL)) {
637 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
638 return (cairo_pattern_t *) &_cairo_pattern_nil;
642 _cairo_pattern_init_solid (pattern, color);
643 CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
645 return &pattern->base;
649 _cairo_pattern_create_in_error (cairo_status_t status)
651 cairo_pattern_t *pattern;
653 if (status == CAIRO_STATUS_NO_MEMORY)
654 return (cairo_pattern_t *)&_cairo_pattern_nil.base;
656 CAIRO_MUTEX_INITIALIZE ();
658 pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
659 if (pattern->status == CAIRO_STATUS_SUCCESS)
660 status = _cairo_pattern_set_error (pattern, status);
666 * cairo_pattern_create_rgb:
667 * @red: red component of the color
668 * @green: green component of the color
669 * @blue: blue component of the color
671 * Creates a new #cairo_pattern_t corresponding to an opaque color. The
672 * color components are floating point numbers in the range 0 to 1.
673 * If the values passed in are outside that range, they will be
676 * Return value: the newly created #cairo_pattern_t if successful, or
677 * an error pattern in case of no memory. The caller owns the
678 * returned object and should call cairo_pattern_destroy() when
681 * This function will always return a valid pointer, but if an error
682 * occurred the pattern status will be set to an error. To inspect
683 * the status of a pattern use cairo_pattern_status().
688 cairo_pattern_create_rgb (double red, double green, double blue)
690 return cairo_pattern_create_rgba (red, green, blue, 1.0);
692 slim_hidden_def (cairo_pattern_create_rgb);
695 * cairo_pattern_create_rgba:
696 * @red: red component of the color
697 * @green: green component of the color
698 * @blue: blue component of the color
699 * @alpha: alpha component of the color
701 * Creates a new #cairo_pattern_t corresponding to a translucent color.
702 * The color components are floating point numbers in the range 0 to
703 * 1. If the values passed in are outside that range, they will be
706 * Return value: the newly created #cairo_pattern_t if successful, or
707 * an error pattern in case of no memory. The caller owns the
708 * returned object and should call cairo_pattern_destroy() when
711 * This function will always return a valid pointer, but if an error
712 * occurred the pattern status will be set to an error. To inspect
713 * the status of a pattern use cairo_pattern_status().
718 cairo_pattern_create_rgba (double red, double green, double blue,
723 red = _cairo_restrict_value (red, 0.0, 1.0);
724 green = _cairo_restrict_value (green, 0.0, 1.0);
725 blue = _cairo_restrict_value (blue, 0.0, 1.0);
726 alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
728 _cairo_color_init_rgba (&color, red, green, blue, alpha);
730 CAIRO_MUTEX_INITIALIZE ();
732 return _cairo_pattern_create_solid (&color);
734 slim_hidden_def (cairo_pattern_create_rgba);
737 * cairo_pattern_create_for_surface:
738 * @surface: the surface
740 * Create a new #cairo_pattern_t for the given surface.
742 * Return value: the newly created #cairo_pattern_t if successful, or
743 * an error pattern in case of no memory. The caller owns the
744 * returned object and should call cairo_pattern_destroy() when
747 * This function will always return a valid pointer, but if an error
748 * occurred the pattern status will be set to an error. To inspect
749 * the status of a pattern use cairo_pattern_status().
754 cairo_pattern_create_for_surface (cairo_surface_t *surface)
756 cairo_surface_pattern_t *pattern;
758 if (surface == NULL) {
759 _cairo_error_throw (CAIRO_STATUS_NULL_POINTER);
760 return (cairo_pattern_t*) &_cairo_pattern_nil_null_pointer;
764 return _cairo_pattern_create_in_error (surface->status);
767 _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SURFACE]);
768 if (unlikely (pattern == NULL)) {
769 pattern = malloc (sizeof (cairo_surface_pattern_t));
770 if (unlikely (pattern == NULL)) {
771 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
772 return (cairo_pattern_t *)&_cairo_pattern_nil.base;
776 CAIRO_MUTEX_INITIALIZE ();
778 _cairo_pattern_init_for_surface (pattern, surface);
779 CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
781 return &pattern->base;
783 slim_hidden_def (cairo_pattern_create_for_surface);
786 * cairo_pattern_create_linear:
787 * @x0: x coordinate of the start point
788 * @y0: y coordinate of the start point
789 * @x1: x coordinate of the end point
790 * @y1: y coordinate of the end point
792 * Create a new linear gradient #cairo_pattern_t along the line defined
793 * by (x0, y0) and (x1, y1). Before using the gradient pattern, a
794 * number of color stops should be defined using
795 * cairo_pattern_add_color_stop_rgb() or
796 * cairo_pattern_add_color_stop_rgba().
798 * Note: The coordinates here are in pattern space. For a new pattern,
799 * pattern space is identical to user space, but the relationship
800 * between the spaces can be changed with cairo_pattern_set_matrix().
802 * Return value: the newly created #cairo_pattern_t if successful, or
803 * an error pattern in case of no memory. The caller owns the
804 * returned object and should call cairo_pattern_destroy() when
807 * This function will always return a valid pointer, but if an error
808 * occurred the pattern status will be set to an error. To inspect
809 * the status of a pattern use cairo_pattern_status().
814 cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
816 cairo_linear_pattern_t *pattern;
819 _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_LINEAR]);
820 if (unlikely (pattern == NULL)) {
821 pattern = malloc (sizeof (cairo_linear_pattern_t));
822 if (unlikely (pattern == NULL)) {
823 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
824 return (cairo_pattern_t *) &_cairo_pattern_nil.base;
828 CAIRO_MUTEX_INITIALIZE ();
830 _cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
831 CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
833 return &pattern->base.base;
837 * cairo_pattern_create_radial:
838 * @cx0: x coordinate for the center of the start circle
839 * @cy0: y coordinate for the center of the start circle
840 * @radius0: radius of the start circle
841 * @cx1: x coordinate for the center of the end circle
842 * @cy1: y coordinate for the center of the end circle
843 * @radius1: radius of the end circle
845 * Creates a new radial gradient #cairo_pattern_t between the two
846 * circles defined by (cx0, cy0, radius0) and (cx1, cy1, radius1). Before using the
847 * gradient pattern, a number of color stops should be defined using
848 * cairo_pattern_add_color_stop_rgb() or
849 * cairo_pattern_add_color_stop_rgba().
851 * Note: The coordinates here are in pattern space. For a new pattern,
852 * pattern space is identical to user space, but the relationship
853 * between the spaces can be changed with cairo_pattern_set_matrix().
855 * Return value: the newly created #cairo_pattern_t if successful, or
856 * an error pattern in case of no memory. The caller owns the
857 * returned object and should call cairo_pattern_destroy() when
860 * This function will always return a valid pointer, but if an error
861 * occurred the pattern status will be set to an error. To inspect
862 * the status of a pattern use cairo_pattern_status().
867 cairo_pattern_create_radial (double cx0, double cy0, double radius0,
868 double cx1, double cy1, double radius1)
870 cairo_radial_pattern_t *pattern;
873 _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_RADIAL]);
874 if (unlikely (pattern == NULL)) {
875 pattern = malloc (sizeof (cairo_radial_pattern_t));
876 if (unlikely (pattern == NULL)) {
877 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
878 return (cairo_pattern_t *) &_cairo_pattern_nil.base;
882 CAIRO_MUTEX_INITIALIZE ();
884 _cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
885 CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
887 return &pattern->base.base;
890 /* This order is specified in the diagram in the documentation for
891 * cairo_pattern_create_mesh() */
892 static const int mesh_path_point_i[12] = { 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1 };
893 static const int mesh_path_point_j[12] = { 0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0 };
894 static const int mesh_control_point_i[4] = { 1, 1, 2, 2 };
895 static const int mesh_control_point_j[4] = { 1, 2, 2, 1 };
898 * cairo_pattern_create_mesh:
900 * Create a new mesh pattern.
902 * Mesh patterns are tensor-product patch meshes (type 7 shadings in
903 * PDF). Mesh patterns may also be used to create other types of
904 * shadings that are special cases of tensor-product patch meshes such
905 * as Coons patch meshes (type 6 shading in PDF) and Gouraud-shaded
906 * triangle meshes (type 4 and 5 shadings in PDF).
908 * Mesh patterns consist of one or more tensor-product patches, which
909 * should be defined before using the mesh pattern. Using a mesh
910 * pattern with a partially defined patch as source or mask will put
911 * the context in an error status with a status of
912 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
914 * A tensor-product patch is defined by 4 Bézier curves (side 0, 1, 2,
915 * 3) and by 4 additional control points (P0, P1, P2, P3) that provide
916 * further control over the patch and complete the definition of the
917 * tensor-product patch. The corner C0 is the first point of the
920 * Degenerate sides are permitted so straight lines may be used. A
921 * zero length line on one side may be used to create 3 sided patches.
923 * <informalexample><screen>
936 * </screen></informalexample>
938 * Each patch is constructed by first calling
939 * cairo_mesh_pattern_begin_patch(), then cairo_mesh_pattern_move_to()
940 * to specify the first point in the patch (C0). Then the sides are
941 * specified with calls to cairo_mesh_pattern_curve_to() and
942 * cairo_mesh_pattern_line_to().
944 * The four additional control points (P0, P1, P2, P3) in a patch can
945 * be specified with cairo_mesh_pattern_set_control_point().
947 * At each corner of the patch (C0, C1, C2, C3) a color may be
948 * specified with cairo_mesh_pattern_set_corner_color_rgb() or
949 * cairo_mesh_pattern_set_corner_color_rgba(). Any corner whose color
950 * is not explicitly specified defaults to transparent black.
952 * A Coons patch is a special case of the tensor-product patch where
953 * the control points are implicitly defined by the sides of the
954 * patch. The default value for any control point not specified is the
955 * implicit value for a Coons patch, i.e. if no control points are
956 * specified the patch is a Coons patch.
958 * A triangle is a special case of the tensor-product patch where the
959 * control points are implicitly defined by the sides of the patch,
960 * all the sides are lines and one of them has length 0, i.e. if the
961 * patch is specified using just 3 lines, it is a triangle. If the
962 * corners connected by the 0-length side have the same color, the
963 * patch is a Gouraud-shaded triangle.
965 * Patches may be oriented differently to the above diagram. For
966 * example the first point could be at the top left. The diagram only
967 * shows the relationship between the sides, corners and control
968 * points. Regardless of where the first point is located, when
969 * specifying colors, corner 0 will always be the first point, corner
970 * 1 the point between side 0 and side 1 etc.
972 * Calling cairo_mesh_pattern_end_patch() completes the current
973 * patch. If less than 4 sides have been defined, the first missing
974 * side is defined as a line from the current point to the first point
975 * of the patch (C0) and the other sides are degenerate lines from C0
976 * to C0. The corners between the added sides will all be coincident
977 * with C0 of the patch and their color will be set to be the same as
980 * Additional patches may be added with additional calls to
981 * cairo_mesh_pattern_begin_patch()/cairo_mesh_pattern_end_patch().
983 * <informalexample><programlisting>
984 * cairo_pattern_t *pattern = cairo_pattern_create_mesh ();
986 * /* Add a Coons patch */
987 * cairo_mesh_pattern_begin_patch (pattern);
988 * cairo_mesh_pattern_move_to (pattern, 0, 0);
989 * cairo_mesh_pattern_curve_to (pattern, 30, -30, 60, 30, 100, 0);
990 * cairo_mesh_pattern_curve_to (pattern, 60, 30, 130, 60, 100, 100);
991 * cairo_mesh_pattern_curve_to (pattern, 60, 70, 30, 130, 0, 100);
992 * cairo_mesh_pattern_curve_to (pattern, 30, 70, -30, 30, 0, 0);
993 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 0, 1, 0, 0);
994 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 1, 0, 1, 0);
995 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 2, 0, 0, 1);
996 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 3, 1, 1, 0);
997 * cairo_mesh_pattern_end_patch (pattern);
999 * /* Add a Gouraud-shaded triangle */
1000 * cairo_mesh_pattern_begin_patch (pattern)
1001 * cairo_mesh_pattern_move_to (pattern, 100, 100);
1002 * cairo_mesh_pattern_line_to (pattern, 130, 130);
1003 * cairo_mesh_pattern_line_to (pattern, 130, 70);
1004 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 0, 1, 0, 0);
1005 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 1, 0, 1, 0);
1006 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 2, 0, 0, 1);
1007 * cairo_mesh_pattern_end_patch (pattern)
1008 * </programlisting></informalexample>
1010 * When two patches overlap, the last one that has been added is drawn
1011 * over the first one.
1013 * When a patch folds over itself, points are sorted depending on
1014 * their parameter coordinates inside the patch. The v coordinate
1015 * ranges from 0 to 1 when moving from side 3 to side 1; the u
1016 * coordinate ranges from 0 to 1 when going from side 0 to side
1017 * 2. Points with higher v coordinate hide points with lower v
1018 * coordinate. When two points have the same v coordinate, the one
1019 * with higher u coordinate is above. This means that points nearer to
1020 * side 1 are above points nearer to side 3; when this is not
1021 * sufficient to decide which point is above (for example when both
1022 * points belong to side 1 or side 3) points nearer to side 2 are
1023 * above points nearer to side 0.
1025 * For a complete definition of tensor-product patches, see the PDF
1026 * specification (ISO32000), which describes the parametrization in
1029 * Note: The coordinates are always in pattern space. For a new
1030 * pattern, pattern space is identical to user space, but the
1031 * relationship between the spaces can be changed with
1032 * cairo_pattern_set_matrix().
1034 * Return value: the newly created #cairo_pattern_t if successful, or
1035 * an error pattern in case of no memory. The caller owns the returned
1036 * object and should call cairo_pattern_destroy() when finished with
1039 * This function will always return a valid pointer, but if an error
1040 * occurred the pattern status will be set to an error. To inspect the
1041 * status of a pattern use cairo_pattern_status().
1046 cairo_pattern_create_mesh (void)
1048 cairo_mesh_pattern_t *pattern;
1051 _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_MESH]);
1052 if (unlikely (pattern == NULL)) {
1053 pattern = malloc (sizeof (cairo_mesh_pattern_t));
1054 if (unlikely (pattern == NULL)) {
1055 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1056 return (cairo_pattern_t *) &_cairo_pattern_nil.base;
1060 CAIRO_MUTEX_INITIALIZE ();
1062 _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_MESH);
1063 _cairo_array_init (&pattern->patches, sizeof (cairo_mesh_patch_t));
1064 pattern->current_patch = NULL;
1065 CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
1067 return &pattern->base;
1071 * cairo_pattern_reference:
1072 * @pattern: a #cairo_pattern_t
1074 * Increases the reference count on @pattern by one. This prevents
1075 * @pattern from being destroyed until a matching call to
1076 * cairo_pattern_destroy() is made.
1078 * The number of references to a #cairo_pattern_t can be get using
1079 * cairo_pattern_get_reference_count().
1081 * Return value: the referenced #cairo_pattern_t.
1086 cairo_pattern_reference (cairo_pattern_t *pattern)
1088 if (pattern == NULL ||
1089 CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1092 assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
1094 _cairo_reference_count_inc (&pattern->ref_count);
1098 slim_hidden_def (cairo_pattern_reference);
1101 * cairo_pattern_get_type:
1102 * @pattern: a #cairo_pattern_t
1104 * This function returns the type a pattern.
1105 * See #cairo_pattern_type_t for available types.
1107 * Return value: The type of @pattern.
1111 cairo_pattern_type_t
1112 cairo_pattern_get_type (cairo_pattern_t *pattern)
1114 return pattern->type;
1118 * cairo_pattern_status:
1119 * @pattern: a #cairo_pattern_t
1121 * Checks whether an error has previously occurred for this
1124 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NO_MEMORY,
1125 * %CAIRO_STATUS_INVALID_MATRIX, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH,
1126 * or %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1131 cairo_pattern_status (cairo_pattern_t *pattern)
1133 return pattern->status;
1137 * cairo_pattern_destroy:
1138 * @pattern: a #cairo_pattern_t
1140 * Decreases the reference count on @pattern by one. If the result is
1141 * zero, then @pattern and all associated resources are freed. See
1142 * cairo_pattern_reference().
1147 cairo_pattern_destroy (cairo_pattern_t *pattern)
1149 cairo_pattern_type_t type;
1151 if (pattern == NULL ||
1152 CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1155 assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
1157 if (! _cairo_reference_count_dec_and_test (&pattern->ref_count))
1160 type = pattern->type;
1161 _cairo_pattern_fini (pattern);
1163 /* maintain a small cache of freed patterns */
1164 if (type < ARRAY_LENGTH (freed_pattern_pool))
1165 _freed_pool_put (&freed_pattern_pool[type], pattern);
1169 slim_hidden_def (cairo_pattern_destroy);
1172 * cairo_pattern_get_reference_count:
1173 * @pattern: a #cairo_pattern_t
1175 * Returns the current reference count of @pattern.
1177 * Return value: the current reference count of @pattern. If the
1178 * object is a nil object, 0 will be returned.
1183 cairo_pattern_get_reference_count (cairo_pattern_t *pattern)
1185 if (pattern == NULL ||
1186 CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1189 return CAIRO_REFERENCE_COUNT_GET_VALUE (&pattern->ref_count);
1193 * cairo_pattern_get_user_data:
1194 * @pattern: a #cairo_pattern_t
1195 * @key: the address of the #cairo_user_data_key_t the user data was
1198 * Return user data previously attached to @pattern using the
1199 * specified key. If no user data has been attached with the given
1200 * key this function returns %NULL.
1202 * Return value: the user data previously attached or %NULL.
1207 cairo_pattern_get_user_data (cairo_pattern_t *pattern,
1208 const cairo_user_data_key_t *key)
1210 return _cairo_user_data_array_get_data (&pattern->user_data,
1215 * cairo_pattern_set_user_data:
1216 * @pattern: a #cairo_pattern_t
1217 * @key: the address of a #cairo_user_data_key_t to attach the user data to
1218 * @user_data: the user data to attach to the #cairo_pattern_t
1219 * @destroy: a #cairo_destroy_func_t which will be called when the
1220 * #cairo_t is destroyed or when new user data is attached using the
1223 * Attach user data to @pattern. To remove user data from a surface,
1224 * call this function with the key that was used to set it and %NULL
1227 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
1228 * slot could not be allocated for the user data.
1233 cairo_pattern_set_user_data (cairo_pattern_t *pattern,
1234 const cairo_user_data_key_t *key,
1236 cairo_destroy_func_t destroy)
1238 if (CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1239 return pattern->status;
1241 return _cairo_user_data_array_set_data (&pattern->user_data,
1242 key, user_data, destroy);
1246 * cairo_mesh_pattern_begin_patch:
1247 * @pattern: a #cairo_pattern_t
1249 * Begin a patch in a mesh pattern.
1251 * After calling this function, the patch shape should be defined with
1252 * cairo_mesh_pattern_move_to(), cairo_mesh_pattern_line_to() and
1253 * cairo_mesh_pattern_curve_to().
1255 * After defining the patch, cairo_mesh_pattern_end_patch() must be
1256 * called before using @pattern as a source or mask.
1258 * Note: If @pattern is not a mesh pattern then @pattern will be put
1259 * into an error status with a status of
1260 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern already has a
1261 * current patch, it will be put into an error status with a status of
1262 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1267 cairo_mesh_pattern_begin_patch (cairo_pattern_t *pattern)
1269 cairo_mesh_pattern_t *mesh;
1270 cairo_status_t status;
1271 cairo_mesh_patch_t *current_patch;
1274 if (unlikely (pattern->status))
1277 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1278 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1282 mesh = (cairo_mesh_pattern_t *) pattern;
1283 if (unlikely (mesh->current_patch)) {
1284 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1288 status = _cairo_array_allocate (&mesh->patches, 1, (void **) ¤t_patch);
1289 if (unlikely (status)) {
1290 _cairo_pattern_set_error (pattern, status);
1294 mesh->current_patch = current_patch;
1295 mesh->current_side = -2; /* no current point */
1297 for (i = 0; i < 4; i++)
1298 mesh->has_control_point[i] = FALSE;
1300 for (i = 0; i < 4; i++)
1301 mesh->has_color[i] = FALSE;
1306 _calc_control_point (cairo_mesh_patch_t *patch, int control_point)
1308 /* The Coons patch is a special case of the Tensor Product patch
1309 * where the four control points are:
1316 * where S is the gradient surface.
1318 * When one or more control points has not been specified
1319 * calculated the Coons patch control points are substituted. If
1320 * no control points are specified the gradient will be a Coons
1323 * The equations below are defined in the ISO32000 standard.
1325 cairo_point_double_t *p[3][3];
1326 int cp_i, cp_j, i, j;
1328 cp_i = mesh_control_point_i[control_point];
1329 cp_j = mesh_control_point_j[control_point];
1331 for (i = 0; i < 3; i++)
1332 for (j = 0; j < 3; j++)
1333 p[i][j] = &patch->points[cp_i ^ i][cp_j ^ j];
1335 p[0][0]->x = (- 4 * p[1][1]->x
1336 + 6 * (p[1][0]->x + p[0][1]->x)
1337 - 2 * (p[1][2]->x + p[2][1]->x)
1338 + 3 * (p[2][0]->x + p[0][2]->x)
1339 - 1 * p[2][2]->x) * (1. / 9);
1341 p[0][0]->y = (- 4 * p[1][1]->y
1342 + 6 * (p[1][0]->y + p[0][1]->y)
1343 - 2 * (p[1][2]->y + p[2][1]->y)
1344 + 3 * (p[2][0]->y + p[0][2]->y)
1345 - 1 * p[2][2]->y) * (1. / 9);
1349 * cairo_mesh_pattern_end_patch:
1350 * @pattern: a #cairo_pattern_t
1352 * Indicates the end of the current patch in a mesh pattern.
1354 * If the current patch has less than 4 sides, it is closed with a
1355 * straight line from the current point to the first point of the
1356 * patch as if cairo_mesh_pattern_line_to() was used.
1358 * Note: If @pattern is not a mesh pattern then @pattern will be put
1359 * into an error status with a status of
1360 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
1361 * patch or the current patch has no current point, @pattern will be
1362 * put into an error status with a status of
1363 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1368 cairo_mesh_pattern_end_patch (cairo_pattern_t *pattern)
1370 cairo_mesh_pattern_t *mesh;
1371 cairo_mesh_patch_t *current_patch;
1374 if (unlikely (pattern->status))
1377 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1378 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1382 mesh = (cairo_mesh_pattern_t *) pattern;
1383 current_patch = mesh->current_patch;
1384 if (unlikely (!current_patch)) {
1385 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1389 if (unlikely (mesh->current_side == -2)) {
1390 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1394 while (mesh->current_side < 3) {
1397 cairo_mesh_pattern_line_to (pattern,
1398 current_patch->points[0][0].x,
1399 current_patch->points[0][0].y);
1401 corner_num = mesh->current_side + 1;
1402 if (corner_num < 4 && ! mesh->has_color[corner_num]) {
1403 current_patch->colors[corner_num] = current_patch->colors[0];
1404 mesh->has_color[corner_num] = TRUE;
1408 for (i = 0; i < 4; i++) {
1409 if (! mesh->has_control_point[i])
1410 _calc_control_point (current_patch, i);
1413 for (i = 0; i < 4; i++) {
1414 if (! mesh->has_color[i])
1415 current_patch->colors[i] = *CAIRO_COLOR_TRANSPARENT;
1418 mesh->current_patch = NULL;
1422 * cairo_mesh_pattern_curve_to:
1423 * @pattern: a #cairo_pattern_t
1424 * @x1: the X coordinate of the first control point
1425 * @y1: the Y coordinate of the first control point
1426 * @x2: the X coordinate of the second control point
1427 * @y2: the Y coordinate of the second control point
1428 * @x3: the X coordinate of the end of the curve
1429 * @y3: the Y coordinate of the end of the curve
1431 * Adds a cubic Bézier spline to the current patch from the current
1432 * point to position (@x3, @y3) in pattern-space coordinates, using
1433 * (@x1, @y1) and (@x2, @y2) as the control points.
1435 * If the current patch has no current point before the call to
1436 * cairo_mesh_pattern_curve_to(), this function will behave as if
1437 * preceded by a call to cairo_mesh_pattern_move_to(@pattern, @x1,
1440 * After this call the current point will be (@x3, @y3).
1442 * Note: If @pattern is not a mesh pattern then @pattern will be put
1443 * into an error status with a status of
1444 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
1445 * patch or the current patch already has 4 sides, @pattern will be
1446 * put into an error status with a status of
1447 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1452 cairo_mesh_pattern_curve_to (cairo_pattern_t *pattern,
1453 double x1, double y1,
1454 double x2, double y2,
1455 double x3, double y3)
1457 cairo_mesh_pattern_t *mesh;
1458 int current_point, i, j;
1460 if (unlikely (pattern->status))
1463 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1464 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1468 mesh = (cairo_mesh_pattern_t *) pattern;
1469 if (unlikely (!mesh->current_patch)) {
1470 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1474 if (unlikely (mesh->current_side == 3)) {
1475 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1479 if (mesh->current_side == -2)
1480 cairo_mesh_pattern_move_to (pattern, x1, y1);
1482 assert (mesh->current_side >= -1);
1483 assert (pattern->status == CAIRO_STATUS_SUCCESS);
1485 mesh->current_side++;
1487 current_point = 3 * mesh->current_side;
1490 i = mesh_path_point_i[current_point];
1491 j = mesh_path_point_j[current_point];
1492 mesh->current_patch->points[i][j].x = x1;
1493 mesh->current_patch->points[i][j].y = y1;
1496 i = mesh_path_point_i[current_point];
1497 j = mesh_path_point_j[current_point];
1498 mesh->current_patch->points[i][j].x = x2;
1499 mesh->current_patch->points[i][j].y = y2;
1502 if (current_point < 12) {
1503 i = mesh_path_point_i[current_point];
1504 j = mesh_path_point_j[current_point];
1505 mesh->current_patch->points[i][j].x = x3;
1506 mesh->current_patch->points[i][j].y = y3;
1509 slim_hidden_def (cairo_mesh_pattern_curve_to);
1512 * cairo_mesh_pattern_line_to:
1513 * @pattern: a #cairo_pattern_t
1514 * @x: the X coordinate of the end of the new line
1515 * @y: the Y coordinate of the end of the new line
1517 * Adds a line to the current patch from the current point to position
1518 * (@x, @y) in pattern-space coordinates.
1520 * If there is no current point before the call to
1521 * cairo_mesh_pattern_line_to() this function will behave as
1522 * cairo_mesh_pattern_move_to(@pattern, @x, @y).
1524 * After this call the current point will be (@x, @y).
1526 * Note: If @pattern is not a mesh pattern then @pattern will be put
1527 * into an error status with a status of
1528 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
1529 * patch or the current patch already has 4 sides, @pattern will be
1530 * put into an error status with a status of
1531 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1536 cairo_mesh_pattern_line_to (cairo_pattern_t *pattern,
1539 cairo_mesh_pattern_t *mesh;
1540 cairo_point_double_t last_point;
1541 int last_point_idx, i, j;
1543 if (unlikely (pattern->status))
1546 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1547 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1551 mesh = (cairo_mesh_pattern_t *) pattern;
1552 if (unlikely (!mesh->current_patch)) {
1553 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1557 if (unlikely (mesh->current_side == 3)) {
1558 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1562 if (mesh->current_side == -2) {
1563 cairo_mesh_pattern_move_to (pattern, x, y);
1567 last_point_idx = 3 * (mesh->current_side + 1);
1568 i = mesh_path_point_i[last_point_idx];
1569 j = mesh_path_point_j[last_point_idx];
1571 last_point = mesh->current_patch->points[i][j];
1573 cairo_mesh_pattern_curve_to (pattern,
1574 (2 * last_point.x + x) * (1. / 3),
1575 (2 * last_point.y + y) * (1. / 3),
1576 (last_point.x + 2 * x) * (1. / 3),
1577 (last_point.y + 2 * y) * (1. / 3),
1580 slim_hidden_def (cairo_mesh_pattern_line_to);
1583 * cairo_mesh_pattern_move_to:
1584 * @pattern: a #cairo_pattern_t
1585 * @x: the X coordinate of the new position
1586 * @y: the Y coordinate of the new position
1588 * Define the first point of the current patch in a mesh pattern.
1590 * After this call the current point will be (@x, @y).
1592 * Note: If @pattern is not a mesh pattern then @pattern will be put
1593 * into an error status with a status of
1594 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
1595 * patch or the current patch already has at least one side, @pattern
1596 * will be put into an error status with a status of
1597 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1602 cairo_mesh_pattern_move_to (cairo_pattern_t *pattern,
1605 cairo_mesh_pattern_t *mesh;
1607 if (unlikely (pattern->status))
1610 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1611 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1615 mesh = (cairo_mesh_pattern_t *) pattern;
1616 if (unlikely (!mesh->current_patch)) {
1617 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1621 if (unlikely (mesh->current_side >= 0)) {
1622 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1626 mesh->current_side = -1;
1627 mesh->current_patch->points[0][0].x = x;
1628 mesh->current_patch->points[0][0].y = y;
1630 slim_hidden_def (cairo_mesh_pattern_move_to);
1633 * cairo_mesh_pattern_set_control_point:
1634 * @pattern: a #cairo_pattern_t
1635 * @point_num: the control point to set the position for
1636 * @x: the X coordinate of the control point
1637 * @y: the Y coordinate of the control point
1639 * Set an internal control point of the current patch.
1641 * Valid values for @point_num are from 0 to 3 and identify the
1642 * control points as explained in cairo_pattern_create_mesh().
1644 * Note: If @pattern is not a mesh pattern then @pattern will be put
1645 * into an error status with a status of
1646 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @point_num is not valid,
1647 * @pattern will be put into an error status with a status of
1648 * %CAIRO_STATUS_INVALID_INDEX. If @pattern has no current patch,
1649 * @pattern will be put into an error status with a status of
1650 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1655 cairo_mesh_pattern_set_control_point (cairo_pattern_t *pattern,
1656 unsigned int point_num,
1660 cairo_mesh_pattern_t *mesh;
1663 if (unlikely (pattern->status))
1666 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1667 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1671 if (unlikely (point_num > 3)) {
1672 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_INDEX);
1676 mesh = (cairo_mesh_pattern_t *) pattern;
1677 if (unlikely (!mesh->current_patch)) {
1678 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1682 i = mesh_control_point_i[point_num];
1683 j = mesh_control_point_j[point_num];
1685 mesh->current_patch->points[i][j].x = x;
1686 mesh->current_patch->points[i][j].y = y;
1687 mesh->has_control_point[point_num] = TRUE;
1690 /* make room for at least one more color stop */
1691 static cairo_status_t
1692 _cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
1694 cairo_gradient_stop_t *new_stops;
1695 int old_size = pattern->stops_size;
1696 int embedded_size = ARRAY_LENGTH (pattern->stops_embedded);
1697 int new_size = 2 * MAX (old_size, 4);
1699 /* we have a local buffer at pattern->stops_embedded. try to fulfill the request
1701 if (old_size < embedded_size) {
1702 pattern->stops = pattern->stops_embedded;
1703 pattern->stops_size = embedded_size;
1704 return CAIRO_STATUS_SUCCESS;
1707 if (CAIRO_INJECT_FAULT ())
1708 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1710 assert (pattern->n_stops <= pattern->stops_size);
1712 if (pattern->stops == pattern->stops_embedded) {
1713 new_stops = _cairo_malloc_ab (new_size, sizeof (cairo_gradient_stop_t));
1715 memcpy (new_stops, pattern->stops, old_size * sizeof (cairo_gradient_stop_t));
1717 new_stops = _cairo_realloc_ab (pattern->stops,
1719 sizeof (cairo_gradient_stop_t));
1722 if (unlikely (new_stops == NULL))
1723 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1725 pattern->stops = new_stops;
1726 pattern->stops_size = new_size;
1728 return CAIRO_STATUS_SUCCESS;
1732 _cairo_mesh_pattern_set_corner_color (cairo_mesh_pattern_t *mesh,
1733 unsigned int corner_num,
1734 double red, double green, double blue,
1737 cairo_color_t *color;
1739 assert (mesh->current_patch);
1740 assert (corner_num <= 3);
1742 color = &mesh->current_patch->colors[corner_num];
1744 color->green = green;
1746 color->alpha = alpha;
1748 color->red_short = _cairo_color_double_to_short (red);
1749 color->green_short = _cairo_color_double_to_short (green);
1750 color->blue_short = _cairo_color_double_to_short (blue);
1751 color->alpha_short = _cairo_color_double_to_short (alpha);
1753 mesh->has_color[corner_num] = TRUE;
1757 * cairo_mesh_pattern_set_corner_color_rgb:
1758 * @pattern: a #cairo_pattern_t
1759 * @corner_num: the corner to set the color for
1760 * @red: red component of color
1761 * @green: green component of color
1762 * @blue: blue component of color
1764 * Sets the color of a corner of the current patch in a mesh pattern.
1766 * The color is specified in the same way as in cairo_set_source_rgb().
1768 * Valid values for @corner_num are from 0 to 3 and identify the
1769 * corners as explained in cairo_pattern_create_mesh().
1771 * Note: If @pattern is not a mesh pattern then @pattern will be put
1772 * into an error status with a status of
1773 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @corner_num is not valid,
1774 * @pattern will be put into an error status with a status of
1775 * %CAIRO_STATUS_INVALID_INDEX. If @pattern has no current patch,
1776 * @pattern will be put into an error status with a status of
1777 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1782 cairo_mesh_pattern_set_corner_color_rgb (cairo_pattern_t *pattern,
1783 unsigned int corner_num,
1784 double red, double green, double blue)
1786 cairo_mesh_pattern_set_corner_color_rgba (pattern, corner_num, red, green, blue, 1.0);
1790 * cairo_mesh_pattern_set_corner_color_rgba:
1791 * @pattern: a #cairo_pattern_t
1792 * @corner_num: the corner to set the color for
1793 * @red: red component of color
1794 * @green: green component of color
1795 * @blue: blue component of color
1796 * @alpha: alpha component of color
1798 * Sets the color of a corner of the current patch in a mesh pattern.
1800 * The color is specified in the same way as in cairo_set_source_rgba().
1802 * Valid values for @corner_num are from 0 to 3 and identify the
1803 * corners as explained in cairo_pattern_create_mesh().
1805 * Note: If @pattern is not a mesh pattern then @pattern will be put
1806 * into an error status with a status of
1807 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @corner_num is not valid,
1808 * @pattern will be put into an error status with a status of
1809 * %CAIRO_STATUS_INVALID_INDEX. If @pattern has no current patch,
1810 * @pattern will be put into an error status with a status of
1811 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1816 cairo_mesh_pattern_set_corner_color_rgba (cairo_pattern_t *pattern,
1817 unsigned int corner_num,
1818 double red, double green, double blue,
1821 cairo_mesh_pattern_t *mesh;
1823 if (unlikely (pattern->status))
1826 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1827 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1831 if (unlikely (corner_num > 3)) {
1832 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_INDEX);
1836 mesh = (cairo_mesh_pattern_t *) pattern;
1837 if (unlikely (!mesh->current_patch)) {
1838 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1842 red = _cairo_restrict_value (red, 0.0, 1.0);
1843 green = _cairo_restrict_value (green, 0.0, 1.0);
1844 blue = _cairo_restrict_value (blue, 0.0, 1.0);
1845 alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
1847 _cairo_mesh_pattern_set_corner_color (mesh, corner_num, red, green, blue, alpha);
1849 slim_hidden_def (cairo_mesh_pattern_set_corner_color_rgba);
1852 _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
1859 cairo_gradient_stop_t *stops;
1862 if (pattern->n_stops >= pattern->stops_size) {
1863 cairo_status_t status = _cairo_pattern_gradient_grow (pattern);
1864 if (unlikely (status)) {
1865 status = _cairo_pattern_set_error (&pattern->base, status);
1870 stops = pattern->stops;
1872 for (i = 0; i < pattern->n_stops; i++)
1874 if (offset < stops[i].offset)
1876 memmove (&stops[i + 1], &stops[i],
1877 sizeof (cairo_gradient_stop_t) * (pattern->n_stops - i));
1883 stops[i].offset = offset;
1885 stops[i].color.red = red;
1886 stops[i].color.green = green;
1887 stops[i].color.blue = blue;
1888 stops[i].color.alpha = alpha;
1890 stops[i].color.red_short = _cairo_color_double_to_short (red);
1891 stops[i].color.green_short = _cairo_color_double_to_short (green);
1892 stops[i].color.blue_short = _cairo_color_double_to_short (blue);
1893 stops[i].color.alpha_short = _cairo_color_double_to_short (alpha);
1899 * cairo_pattern_add_color_stop_rgb:
1900 * @pattern: a #cairo_pattern_t
1901 * @offset: an offset in the range [0.0 .. 1.0]
1902 * @red: red component of color
1903 * @green: green component of color
1904 * @blue: blue component of color
1906 * Adds an opaque color stop to a gradient pattern. The offset
1907 * specifies the location along the gradient's control vector. For
1908 * example, a linear gradient's control vector is from (x0,y0) to
1909 * (x1,y1) while a radial gradient's control vector is from any point
1910 * on the start circle to the corresponding point on the end circle.
1912 * The color is specified in the same way as in cairo_set_source_rgb().
1914 * If two (or more) stops are specified with identical offset values,
1915 * they will be sorted according to the order in which the stops are
1916 * added, (stops added earlier will compare less than stops added
1917 * later). This can be useful for reliably making sharp color
1918 * transitions instead of the typical blend.
1921 * Note: If the pattern is not a gradient pattern, (eg. a linear or
1922 * radial pattern), then the pattern will be put into an error status
1923 * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
1928 cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
1934 cairo_pattern_add_color_stop_rgba (pattern, offset, red, green, blue, 1.0);
1938 * cairo_pattern_add_color_stop_rgba:
1939 * @pattern: a #cairo_pattern_t
1940 * @offset: an offset in the range [0.0 .. 1.0]
1941 * @red: red component of color
1942 * @green: green component of color
1943 * @blue: blue component of color
1944 * @alpha: alpha component of color
1946 * Adds a translucent color stop to a gradient pattern. The offset
1947 * specifies the location along the gradient's control vector. For
1948 * example, a linear gradient's control vector is from (x0,y0) to
1949 * (x1,y1) while a radial gradient's control vector is from any point
1950 * on the start circle to the corresponding point on the end circle.
1952 * The color is specified in the same way as in cairo_set_source_rgba().
1954 * If two (or more) stops are specified with identical offset values,
1955 * they will be sorted according to the order in which the stops are
1956 * added, (stops added earlier will compare less than stops added
1957 * later). This can be useful for reliably making sharp color
1958 * transitions instead of the typical blend.
1960 * Note: If the pattern is not a gradient pattern, (eg. a linear or
1961 * radial pattern), then the pattern will be put into an error status
1962 * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
1967 cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
1974 if (pattern->status)
1977 if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
1978 pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
1980 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1984 offset = _cairo_restrict_value (offset, 0.0, 1.0);
1985 red = _cairo_restrict_value (red, 0.0, 1.0);
1986 green = _cairo_restrict_value (green, 0.0, 1.0);
1987 blue = _cairo_restrict_value (blue, 0.0, 1.0);
1988 alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
1990 _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
1991 offset, red, green, blue, alpha);
1993 slim_hidden_def (cairo_pattern_add_color_stop_rgba);
1996 * cairo_pattern_set_matrix:
1997 * @pattern: a #cairo_pattern_t
1998 * @matrix: a #cairo_matrix_t
2000 * Sets the pattern's transformation matrix to @matrix. This matrix is
2001 * a transformation from user space to pattern space.
2003 * When a pattern is first created it always has the identity matrix
2004 * for its transformation matrix, which means that pattern space is
2005 * initially identical to user space.
2007 * Important: Please note that the direction of this transformation
2008 * matrix is from user space to pattern space. This means that if you
2009 * imagine the flow from a pattern to user space (and on to device
2010 * space), then coordinates in that flow will be transformed by the
2011 * inverse of the pattern matrix.
2013 * For example, if you want to make a pattern appear twice as large as
2014 * it does by default the correct code to use is:
2016 * <informalexample><programlisting>
2017 * cairo_matrix_init_scale (&matrix, 0.5, 0.5);
2018 * cairo_pattern_set_matrix (pattern, &matrix);
2019 * </programlisting></informalexample>
2021 * Meanwhile, using values of 2.0 rather than 0.5 in the code above
2022 * would cause the pattern to appear at half of its default size.
2024 * Also, please note the discussion of the user-space locking
2025 * semantics of cairo_set_source().
2030 cairo_pattern_set_matrix (cairo_pattern_t *pattern,
2031 const cairo_matrix_t *matrix)
2033 cairo_matrix_t inverse;
2034 cairo_status_t status;
2036 if (pattern->status)
2039 if (memcmp (&pattern->matrix, matrix, sizeof (cairo_matrix_t)) == 0)
2042 pattern->matrix = *matrix;
2043 _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_MATRIX);
2046 status = cairo_matrix_invert (&inverse);
2047 if (unlikely (status))
2048 status = _cairo_pattern_set_error (pattern, status);
2050 slim_hidden_def (cairo_pattern_set_matrix);
2053 * cairo_pattern_get_matrix:
2054 * @pattern: a #cairo_pattern_t
2055 * @matrix: return value for the matrix
2057 * Stores the pattern's transformation matrix into @matrix.
2062 cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
2064 *matrix = pattern->matrix;
2068 * cairo_pattern_set_filter:
2069 * @pattern: a #cairo_pattern_t
2070 * @filter: a #cairo_filter_t describing the filter to use for resizing
2073 * Sets the filter to be used for resizing when using this pattern.
2074 * See #cairo_filter_t for details on each filter.
2076 * * Note that you might want to control filtering even when you do not
2077 * have an explicit #cairo_pattern_t object, (for example when using
2078 * cairo_set_source_surface()). In these cases, it is convenient to
2079 * use cairo_get_source() to get access to the pattern that cairo
2080 * creates implicitly. For example:
2082 * <informalexample><programlisting>
2083 * cairo_set_source_surface (cr, image, x, y);
2084 * cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
2085 * </programlisting></informalexample>
2090 cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
2092 if (pattern->status)
2095 pattern->filter = filter;
2096 _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_FILTER);
2100 * cairo_pattern_get_filter:
2101 * @pattern: a #cairo_pattern_t
2103 * Gets the current filter for a pattern. See #cairo_filter_t
2104 * for details on each filter.
2106 * Return value: the current filter used for resizing the pattern.
2111 cairo_pattern_get_filter (cairo_pattern_t *pattern)
2113 return pattern->filter;
2117 * cairo_pattern_set_extend:
2118 * @pattern: a #cairo_pattern_t
2119 * @extend: a #cairo_extend_t describing how the area outside of the
2120 * pattern will be drawn
2122 * Sets the mode to be used for drawing outside the area of a pattern.
2123 * See #cairo_extend_t for details on the semantics of each extend
2126 * The default extend mode is %CAIRO_EXTEND_NONE for surface patterns
2127 * and %CAIRO_EXTEND_PAD for gradient patterns.
2132 cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
2134 if (pattern->status)
2137 pattern->extend = extend;
2138 _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_EXTEND);
2142 * cairo_pattern_get_extend:
2143 * @pattern: a #cairo_pattern_t
2145 * Gets the current extend mode for a pattern. See #cairo_extend_t
2146 * for details on the semantics of each extend strategy.
2148 * Return value: the current extend strategy used for drawing the
2154 cairo_pattern_get_extend (cairo_pattern_t *pattern)
2156 return pattern->extend;
2158 slim_hidden_def (cairo_pattern_get_extend);
2161 _cairo_pattern_transform (cairo_pattern_t *pattern,
2162 const cairo_matrix_t *ctm_inverse)
2164 if (pattern->status)
2167 cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
2171 _linear_pattern_is_degenerate (const cairo_linear_pattern_t *linear)
2173 return fabs (linear->pd1.x - linear->pd2.x) < DBL_EPSILON &&
2174 fabs (linear->pd1.y - linear->pd2.y) < DBL_EPSILON;
2178 _radial_pattern_is_degenerate (const cairo_radial_pattern_t *radial)
2180 /* A radial pattern is considered degenerate if it can be
2181 * represented as a solid or clear pattern. This corresponds to
2182 * one of the two cases:
2184 * 1) The radii are both very small:
2185 * |dr| < DBL_EPSILON && min (r0, r1) < DBL_EPSILON
2187 * 2) The two circles have about the same radius and are very
2188 * close to each other (approximately a cylinder gradient that
2189 * doesn't move with the parameter):
2190 * |dr| < DBL_EPSILON && max (|dx|, |dy|) < 2 * DBL_EPSILON
2192 * These checks are consistent with the assumptions used in
2193 * _cairo_radial_pattern_box_to_parameter ().
2196 return fabs (radial->cd1.radius - radial->cd2.radius) < DBL_EPSILON &&
2197 (MIN (radial->cd1.radius, radial->cd2.radius) < DBL_EPSILON ||
2198 MAX (fabs (radial->cd1.center.x - radial->cd2.center.x),
2199 fabs (radial->cd1.center.y - radial->cd2.center.y)) < 2 * DBL_EPSILON);
2203 _cairo_linear_pattern_box_to_parameter (const cairo_linear_pattern_t *linear,
2204 double x0, double y0,
2205 double x1, double y1,
2208 double t0, tdx, tdy;
2209 double p1x, p1y, pdx, pdy, invsqnorm;
2211 assert (! _linear_pattern_is_degenerate (linear));
2214 * Linear gradients are othrogonal to the line passing through
2215 * their extremes. Because of convexity, the parameter range can
2216 * be computed as the convex hull (one the real line) of the
2217 * parameter values of the 4 corners of the box.
2219 * The parameter value t for a point (x,y) can be computed as:
2221 * t = (p2 - p1) . (x,y) / |p2 - p1|^2
2223 * t0 is the t value for the top left corner
2224 * tdx is the difference between left and right corners
2225 * tdy is the difference between top and bottom corners
2228 p1x = linear->pd1.x;
2229 p1y = linear->pd1.y;
2230 pdx = linear->pd2.x - p1x;
2231 pdy = linear->pd2.y - p1y;
2232 invsqnorm = 1.0 / (pdx * pdx + pdy * pdy);
2236 t0 = (x0 - p1x) * pdx + (y0 - p1y) * pdy;
2237 tdx = (x1 - x0) * pdx;
2238 tdy = (y1 - y0) * pdy;
2241 * Because of the linearity of the t value, tdx can simply be
2242 * added the t0 to move along the top edge. After this, range[0]
2243 * and range[1] represent the parameter range for the top edge, so
2244 * extending it to include the whole box simply requires adding
2245 * tdy to the correct extreme.
2248 range[0] = range[1] = t0;
2261 _extend_range (double range[2], double value, cairo_bool_t valid)
2264 range[0] = range[1] = value;
2265 else if (value < range[0])
2267 else if (value > range[1])
2274 * _cairo_radial_pattern_focus_is_inside:
2276 * Returns %TRUE if and only if the focus point exists and is
2277 * contained in one of the two extreme circles. This condition is
2278 * equivalent to one of the two extreme circles being completely
2279 * contained in the other one.
2281 * Note: if the focus is on the border of one of the two circles (in
2282 * which case the circles are tangent in the focus point), it is not
2283 * considered as contained in the circle, hence this function returns
2288 _cairo_radial_pattern_focus_is_inside (const cairo_radial_pattern_t *radial)
2290 double cx, cy, cr, dx, dy, dr;
2292 cx = radial->cd1.center.x;
2293 cy = radial->cd1.center.y;
2294 cr = radial->cd1.radius;
2295 dx = radial->cd2.center.x - cx;
2296 dy = radial->cd2.center.y - cy;
2297 dr = radial->cd2.radius - cr;
2299 return dx*dx + dy*dy < dr*dr;
2303 _cairo_radial_pattern_box_to_parameter (const cairo_radial_pattern_t *radial,
2304 double x0, double y0,
2305 double x1, double y1,
2309 double cx, cy, cr, dx, dy, dr;
2310 double a, x_focus, y_focus;
2311 double mindr, minx, miny, maxx, maxy;
2314 assert (! _radial_pattern_is_degenerate (radial));
2318 tolerance = MAX (tolerance, DBL_EPSILON);
2320 range[0] = range[1] = 0;
2323 x_focus = y_focus = 0; /* silence gcc */
2325 cx = radial->cd1.center.x;
2326 cy = radial->cd1.center.y;
2327 cr = radial->cd1.radius;
2328 dx = radial->cd2.center.x - cx;
2329 dy = radial->cd2.center.y - cy;
2330 dr = radial->cd2.radius - cr;
2332 /* translate by -(cx, cy) to simplify computations */
2338 /* enlarge boundaries slightly to avoid rounding problems in the
2339 * parameter range computation */
2345 /* enlarge boundaries even more to avoid rounding problems when
2346 * testing if a point belongs to the box */
2347 minx = x0 - DBL_EPSILON;
2348 miny = y0 - DBL_EPSILON;
2349 maxx = x1 + DBL_EPSILON;
2350 maxy = y1 + DBL_EPSILON;
2352 /* we dont' allow negative radiuses, so we will be checking that
2353 * t*dr >= mindr to consider t valid */
2354 mindr = -(cr + DBL_EPSILON);
2357 * After the previous transformations, the start circle is
2358 * centered in the origin and has radius cr. A 1-unit change in
2359 * the t parameter corresponds to dx,dy,dr changes in the x,y,r of
2360 * the circle (center coordinates, radius).
2362 * To compute the minimum range needed to correctly draw the
2363 * pattern, we start with an empty range and extend it to include
2364 * the circles touching the bounding box or within it.
2368 * Focus, the point where the circle has radius == 0.
2370 * r = cr + t * dr = 0
2373 * If the radius is constant (dr == 0) there is no focus (the
2374 * gradient represents a cylinder instead of a cone).
2376 if (fabs (dr) >= DBL_EPSILON) {
2380 x_focus = t_focus * dx;
2381 y_focus = t_focus * dy;
2382 if (minx <= x_focus && x_focus <= maxx &&
2383 miny <= y_focus && y_focus <= maxy)
2385 valid = _extend_range (range, t_focus, valid);
2390 * Circles externally tangent to box edges.
2392 * All circles have center in (dx, dy) * t
2394 * If the circle is tangent to the line defined by the edge of the
2395 * box, then at least one of the following holds true:
2397 * (dx*t) + (cr + dr*t) == x0 (left edge)
2398 * (dx*t) - (cr + dr*t) == x1 (right edge)
2399 * (dy*t) + (cr + dr*t) == y0 (top edge)
2400 * (dy*t) - (cr + dr*t) == y1 (bottom edge)
2402 * The solution is only valid if the tangent point is actually on
2403 * the edge, i.e. if its y coordinate is in [y0,y1] for left/right
2404 * edges and if its x coordinate is in [x0,x1] for top/bottom
2407 * For the first equation:
2409 * (dx + dr) * t = x0 - cr
2410 * t = (x0 - cr) / (dx + dr)
2413 * in the code this becomes:
2415 * t_edge = (num) / (den)
2416 * v = (delta) * t_edge
2418 * If the denominator in t is 0, the pattern is tangent to a line
2419 * parallel to the edge under examination. The corner-case where
2420 * the boundary line is the same as the edge is handled by the
2421 * focus point case and/or by the a==0 case.
2423 #define T_EDGE(num,den,delta,lower,upper) \
2424 if (fabs (den) >= DBL_EPSILON) { \
2427 t_edge = (num) / (den); \
2428 v = t_edge * (delta); \
2429 if (t_edge * dr >= mindr && (lower) <= v && v <= (upper)) \
2430 valid = _extend_range (range, t_edge, valid); \
2433 /* circles tangent (externally) to left/right/top/bottom edge */
2434 T_EDGE (x0 - cr, dx + dr, dy, miny, maxy);
2435 T_EDGE (x1 + cr, dx - dr, dy, miny, maxy);
2436 T_EDGE (y0 - cr, dy + dr, dx, minx, maxx);
2437 T_EDGE (y1 + cr, dy - dr, dx, minx, maxx);
2442 * Circles passing through a corner.
2444 * A circle passing through the point (x,y) satisfies:
2446 * (x-t*dx)^2 + (y-t*dy)^2 == (cr + t*dr)^2
2449 * a = dx^2 + dy^2 - dr^2
2450 * b = x*dx + y*dy + cr*dr
2451 * c = x^2 + y^2 - cr^2
2453 * a*t^2 - 2*b*t + c == 0
2455 a = dx * dx + dy * dy - dr * dr;
2456 if (fabs (a) < DBL_EPSILON * DBL_EPSILON) {
2459 /* Ensure that gradients with both a and dr small are
2460 * considered degenerate.
2461 * The floating point version of the degeneracy test implemented
2462 * in _radial_pattern_is_degenerate() is:
2464 * 1) The circles are practically the same size:
2465 * |dr| < DBL_EPSILON
2467 * 2a) The circles are both very small:
2468 * min (r0, r1) < DBL_EPSILON
2470 * 2b) The circles are very close to each other:
2471 * max (|dx|, |dy|) < 2 * DBL_EPSILON
2473 * Assuming that the gradient is not degenerate, we want to
2474 * show that |a| < DBL_EPSILON^2 implies |dr| >= DBL_EPSILON.
2476 * If the gradient is not degenerate yet it has |dr| <
2477 * DBL_EPSILON, (2b) is false, thus:
2479 * max (|dx|, |dy|) >= 2*DBL_EPSILON
2481 * 4*DBL_EPSILON^2 <= max (|dx|, |dy|)^2 <= dx^2 + dy^2
2483 * From the definition of a, we get:
2484 * a = dx^2 + dy^2 - dr^2 < DBL_EPSILON^2
2485 * dx^2 + dy^2 - DBL_EPSILON^2 < dr^2
2486 * 3*DBL_EPSILON^2 < dr^2
2488 * which is inconsistent with the hypotheses, thus |dr| <
2489 * DBL_EPSILON is false or the gradient is degenerate.
2491 assert (fabs (dr) >= DBL_EPSILON);
2494 * If a == 0, all the circles are tangent to a line in the
2495 * focus point. If this line is within the box extents, we
2496 * should add the circle with infinite radius, but this would
2497 * make the range unbounded, so we add the smallest circle whose
2498 * distance to the desired (degenerate) circle within the
2499 * bounding box does not exceed tolerance.
2501 * The equation of the line is b==0, i.e.:
2502 * x*dx + y*dy + cr*dr == 0
2504 * We compute the intersection of the line with the box and
2505 * keep the intersection with maximum square distance (maxd2)
2506 * from the focus point.
2508 * In the code the intersection is represented in another
2509 * coordinate system, whose origin is the focus point and
2510 * which has a u,v axes, which are respectively orthogonal and
2511 * parallel to the edge being intersected.
2513 * The intersection is valid only if it belongs to the box,
2514 * otherwise it is ignored.
2519 * x*dx + y0*dy + cr*dr == 0
2520 * x = -(y0*dy + cr*dr) / dx
2522 * which in (u,v) is:
2524 * v = -(y0*dy + cr*dr) / dx - x_focus
2527 * u = (edge) - (u_origin)
2528 * v = -((edge) * (delta) + cr*dr) / (den) - v_focus
2530 #define T_EDGE(edge,delta,den,lower,upper,u_origin,v_origin) \
2531 if (fabs (den) >= DBL_EPSILON) { \
2534 v = -((edge) * (delta) + cr * dr) / (den); \
2535 if ((lower) <= v && v <= (upper)) { \
2538 u = (edge) - (u_origin); \
2548 /* degenerate circles (lines) passing through each edge */
2549 T_EDGE (y0, dy, dx, minx, maxx, y_focus, x_focus);
2550 T_EDGE (y1, dy, dx, minx, maxx, y_focus, x_focus);
2551 T_EDGE (x0, dx, dy, miny, maxy, x_focus, y_focus);
2552 T_EDGE (x1, dx, dy, miny, maxy, x_focus, y_focus);
2557 * The limit circle can be transformed rigidly to the y=0 line
2558 * and the circles tangent to it in (0,0) are:
2560 * x^2 + (y-r)^2 = r^2 <=> x^2 + y^2 - 2*y*r = 0
2562 * y is the distance from the line, in our case tolerance;
2563 * x is the distance along the line, i.e. sqrt(maxd2),
2566 * r = cr + dr * t = (maxd2 + tolerance^2) / (2*tolerance)
2567 * t = (r - cr) / dr =
2568 * (maxd2 + tolerance^2 - 2*tolerance*cr) / (2*tolerance*dr)
2571 double t_limit = maxd2 + tolerance*tolerance - 2*tolerance*cr;
2572 t_limit /= 2 * tolerance * dr;
2573 valid = _extend_range (range, t_limit, valid);
2577 * Nondegenerate, nonlimit circles passing through the corners.
2579 * a == 0 && a*t^2 - 2*b*t + c == 0
2583 * The b == 0 case has just been handled, so we only have to
2584 * compute this if b != 0.
2586 #define T_CORNER(x,y) \
2587 b = (x) * dx + (y) * dy + cr * dr; \
2588 if (fabs (b) >= DBL_EPSILON) { \
2590 double x2 = (x) * (x); \
2591 double y2 = (y) * (y); \
2592 double cr2 = (cr) * (cr); \
2593 double c = x2 + y2 - cr2; \
2595 t_corner = 0.5 * c / b; \
2596 if (t_corner * dr >= mindr) \
2597 valid = _extend_range (range, t_corner, valid); \
2600 /* circles touching each corner */
2608 double inva, b, c, d;
2613 * Nondegenerate, nonlimit circles passing through the corners.
2615 * a != 0 && a*t^2 - 2*b*t + c == 0
2617 * t = (b +- sqrt (b*b - a*c)) / a
2619 * If the argument of sqrt() is negative, then no circle
2620 * passes through the corner.
2622 #define T_CORNER(x,y) \
2623 b = (x) * dx + (y) * dy + cr * dr; \
2624 c = (x) * (x) + (y) * (y) - cr * cr; \
2625 d = b * b - a * c; \
2630 t_corner = (b + d) * inva; \
2631 if (t_corner * dr >= mindr) \
2632 valid = _extend_range (range, t_corner, valid); \
2633 t_corner = (b - d) * inva; \
2634 if (t_corner * dr >= mindr) \
2635 valid = _extend_range (range, t_corner, valid); \
2638 /* circles touching each corner */
2649 * _cairo_gradient_pattern_box_to_parameter:
2651 * Compute a interpolation range sufficient to draw (within the given
2652 * tolerance) the gradient in the given box getting the same result as
2653 * using the (-inf, +inf) range.
2655 * Assumes that the pattern is not degenerate. This can be guaranteed
2656 * by simplifying it to a solid clear if _cairo_pattern_is_clear or to
2657 * a solid color if _cairo_gradient_pattern_is_solid.
2659 * The range isn't guaranteed to be minimal, but it tries to.
2662 _cairo_gradient_pattern_box_to_parameter (const cairo_gradient_pattern_t *gradient,
2663 double x0, double y0,
2664 double x1, double y1,
2666 double out_range[2])
2668 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
2669 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
2671 if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
2672 _cairo_linear_pattern_box_to_parameter ((cairo_linear_pattern_t *) gradient,
2673 x0, y0, x1, y1, out_range);
2675 _cairo_radial_pattern_box_to_parameter ((cairo_radial_pattern_t *) gradient,
2676 x0, y0, x1, y1, tolerance, out_range);
2681 * _cairo_gradient_pattern_interpolate:
2683 * Interpolate between the start and end objects of linear or radial
2684 * gradients. The interpolated object is stored in out_circle, with
2685 * the radius being zero in the linear gradient case.
2688 _cairo_gradient_pattern_interpolate (const cairo_gradient_pattern_t *gradient,
2690 cairo_circle_double_t *out_circle)
2692 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
2693 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
2695 #define lerp(a,b) (a)*(1-t) + (b)*t
2697 if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
2698 cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
2699 out_circle->center.x = lerp (linear->pd1.x, linear->pd2.x);
2700 out_circle->center.y = lerp (linear->pd1.y, linear->pd2.y);
2701 out_circle->radius = 0;
2703 cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
2704 out_circle->center.x = lerp (radial->cd1.center.x, radial->cd2.center.x);
2705 out_circle->center.y = lerp (radial->cd1.center.y, radial->cd2.center.y);
2706 out_circle->radius = lerp (radial->cd1.radius , radial->cd2.radius);
2714 * _cairo_gradient_pattern_fit_to_range:
2716 * Scale the extremes of a gradient to guarantee that the coordinates
2717 * and their deltas are within the range (-max_value, max_value). The
2718 * new extremes are stored in out_circle.
2720 * The pattern matrix is scaled to guarantee that the aspect of the
2721 * gradient is the same and the result is stored in out_matrix.
2725 _cairo_gradient_pattern_fit_to_range (const cairo_gradient_pattern_t *gradient,
2727 cairo_matrix_t *out_matrix,
2728 cairo_circle_double_t out_circle[2])
2732 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
2733 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
2735 if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
2736 cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
2738 out_circle[0].center = linear->pd1;
2739 out_circle[0].radius = 0;
2740 out_circle[1].center = linear->pd2;
2741 out_circle[1].radius = 0;
2743 dim = fabs (linear->pd1.x);
2744 dim = MAX (dim, fabs (linear->pd1.y));
2745 dim = MAX (dim, fabs (linear->pd2.x));
2746 dim = MAX (dim, fabs (linear->pd2.y));
2747 dim = MAX (dim, fabs (linear->pd1.x - linear->pd2.x));
2748 dim = MAX (dim, fabs (linear->pd1.y - linear->pd2.y));
2750 cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
2752 out_circle[0] = radial->cd1;
2753 out_circle[1] = radial->cd2;
2755 dim = fabs (radial->cd1.center.x);
2756 dim = MAX (dim, fabs (radial->cd1.center.y));
2757 dim = MAX (dim, fabs (radial->cd1.radius));
2758 dim = MAX (dim, fabs (radial->cd2.center.x));
2759 dim = MAX (dim, fabs (radial->cd2.center.y));
2760 dim = MAX (dim, fabs (radial->cd2.radius));
2761 dim = MAX (dim, fabs (radial->cd1.center.x - radial->cd2.center.x));
2762 dim = MAX (dim, fabs (radial->cd1.center.y - radial->cd2.center.y));
2763 dim = MAX (dim, fabs (radial->cd1.radius - radial->cd2.radius));
2766 if (unlikely (dim > max_value)) {
2767 cairo_matrix_t scale;
2769 dim = max_value / dim;
2771 out_circle[0].center.x *= dim;
2772 out_circle[0].center.y *= dim;
2773 out_circle[0].radius *= dim;
2774 out_circle[1].center.x *= dim;
2775 out_circle[1].center.y *= dim;
2776 out_circle[1].radius *= dim;
2778 cairo_matrix_init_scale (&scale, dim, dim);
2779 cairo_matrix_multiply (out_matrix, &gradient->base.matrix, &scale);
2781 *out_matrix = gradient->base.matrix;
2786 _gradient_is_clear (const cairo_gradient_pattern_t *gradient,
2787 const cairo_rectangle_int_t *extents)
2791 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
2792 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
2794 if (gradient->n_stops == 0 ||
2795 (gradient->base.extend == CAIRO_EXTEND_NONE &&
2796 gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
2799 if (gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL) {
2800 /* degenerate radial gradients are clear */
2801 if (_radial_pattern_is_degenerate ((cairo_radial_pattern_t *) gradient))
2803 } else if (gradient->base.extend == CAIRO_EXTEND_NONE) {
2804 /* EXTEND_NONE degenerate linear gradients are clear */
2805 if (_linear_pattern_is_degenerate ((cairo_linear_pattern_t *) gradient))
2809 /* Check if the extents intersect the drawn part of the pattern. */
2810 if (extents != NULL &&
2811 (gradient->base.extend == CAIRO_EXTEND_NONE ||
2812 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL))
2816 _cairo_gradient_pattern_box_to_parameter (gradient,
2819 extents->x + extents->width,
2820 extents->y + extents->height,
2824 if (gradient->base.extend == CAIRO_EXTEND_NONE &&
2825 (t[0] >= gradient->stops[gradient->n_stops - 1].offset ||
2826 t[1] <= gradient->stops[0].offset))
2835 for (i = 0; i < gradient->n_stops; i++)
2836 if (! CAIRO_COLOR_IS_CLEAR (&gradient->stops[i].color))
2843 _gradient_color_average (const cairo_gradient_pattern_t *gradient,
2844 cairo_color_t *color)
2846 double delta0, delta1;
2848 unsigned int i, start = 1, end;
2850 assert (gradient->n_stops > 0);
2851 assert (gradient->base.extend != CAIRO_EXTEND_NONE);
2853 if (gradient->n_stops == 1) {
2854 _cairo_color_init_rgba (color,
2855 gradient->stops[0].color.red,
2856 gradient->stops[0].color.green,
2857 gradient->stops[0].color.blue,
2858 gradient->stops[0].color.alpha);
2862 end = gradient->n_stops - 1;
2864 switch (gradient->base.extend) {
2865 case CAIRO_EXTEND_REPEAT:
2867 * Sa, Sb and Sy, Sz are the first two and last two stops respectively.
2868 * The weight of the first and last stop can be computed as the area of
2869 * the following triangles (taken with height 1, since the whole [0-1]
2870 * will have total weight 1 this way): b*h/2
2876 * ~~~~~+---+---+---+~~~~~~~+-------+---+---+~~~~~
2877 * -1+Sz 0 Sa Sb Sy Sz 1 1+Sa
2879 * For the first stop: (Sb-(-1+Sz)/2 = (1+Sb-Sz)/2
2880 * For the last stop: ((1+Sa)-Sy)/2 = (1+Sa-Sy)/2
2881 * Halving the result is done after summing up all the areas.
2883 delta0 = 1.0 + gradient->stops[1].offset - gradient->stops[end].offset;
2884 delta1 = 1.0 + gradient->stops[0].offset - gradient->stops[end-1].offset;
2887 case CAIRO_EXTEND_REFLECT:
2889 * Sa, Sb and Sy, Sz are the first two and last two stops respectively.
2890 * The weight of the first and last stop can be computed as the area of
2891 * the following trapezoids (taken with height 1, since the whole [0-1]
2892 * will have total weight 1 this way): (b+B)*h/2
2898 * +-------+---+~~~~~~~+-------+---+
2901 * For the first stop: (Sa+Sb)/2
2902 * For the last stop: ((1-Sz) + (1-Sy))/2 = (2-Sy-Sz)/2
2903 * Halving the result is done after summing up all the areas.
2905 delta0 = gradient->stops[0].offset + gradient->stops[1].offset;
2906 delta1 = 2.0 - gradient->stops[end-1].offset - gradient->stops[end].offset;
2909 case CAIRO_EXTEND_PAD:
2910 /* PAD is computed as the average of the first and last stop:
2911 * - take both of them with weight 1 (they will be halved
2912 * after the whole sum has been computed).
2913 * - avoid summing any of the inner stops.
2915 delta0 = delta1 = 1.0;
2919 case CAIRO_EXTEND_NONE:
2922 _cairo_color_init_rgba (color, 0, 0, 0, 0);
2926 r = delta0 * gradient->stops[0].color.red;
2927 g = delta0 * gradient->stops[0].color.green;
2928 b = delta0 * gradient->stops[0].color.blue;
2929 a = delta0 * gradient->stops[0].color.alpha;
2931 for (i = start; i < end; ++i) {
2932 /* Inner stops weight is the same as the area of the triangle they influence
2933 * (which goes from the stop before to the stop after), again with height 1
2934 * since the whole must sum up to 1: b*h/2
2935 * Halving is done after the whole sum has been computed.
2937 double delta = gradient->stops[i+1].offset - gradient->stops[i-1].offset;
2938 r += delta * gradient->stops[i].color.red;
2939 g += delta * gradient->stops[i].color.green;
2940 b += delta * gradient->stops[i].color.blue;
2941 a += delta * gradient->stops[i].color.alpha;
2944 r += delta1 * gradient->stops[end].color.red;
2945 g += delta1 * gradient->stops[end].color.green;
2946 b += delta1 * gradient->stops[end].color.blue;
2947 a += delta1 * gradient->stops[end].color.alpha;
2949 _cairo_color_init_rgba (color, r * .5, g * .5, b * .5, a * .5);
2953 * _cairo_pattern_alpha_range:
2955 * Convenience function to determine the minimum and maximum alpha in
2956 * the drawn part of a pattern (i.e. ignoring clear parts caused by
2957 * extend modes and/or pattern shape).
2959 * If not NULL, out_min and out_max will be set respectively to the
2960 * minimum and maximum alpha value of the pattern.
2963 _cairo_pattern_alpha_range (const cairo_pattern_t *pattern,
2967 double alpha_min, alpha_max;
2969 switch (pattern->type) {
2970 case CAIRO_PATTERN_TYPE_SOLID: {
2971 const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
2972 alpha_min = alpha_max = solid->color.alpha;
2976 case CAIRO_PATTERN_TYPE_LINEAR:
2977 case CAIRO_PATTERN_TYPE_RADIAL: {
2978 const cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
2981 assert (gradient->n_stops >= 1);
2983 alpha_min = alpha_max = gradient->stops[0].color.alpha;
2984 for (i = 1; i < gradient->n_stops; i++) {
2985 if (alpha_min > gradient->stops[i].color.alpha)
2986 alpha_min = gradient->stops[i].color.alpha;
2987 else if (alpha_max < gradient->stops[i].color.alpha)
2988 alpha_max = gradient->stops[i].color.alpha;
2994 case CAIRO_PATTERN_TYPE_MESH: {
2995 const cairo_mesh_pattern_t *mesh = (const cairo_mesh_pattern_t *) pattern;
2996 const cairo_mesh_patch_t *patch = _cairo_array_index_const (&mesh->patches, 0);
2997 unsigned int i, j, n = _cairo_array_num_elements (&mesh->patches);
3001 alpha_min = alpha_max = patch[0].colors[0].alpha;
3002 for (i = 0; i < n; i++) {
3003 for (j = 0; j < 4; j++) {
3004 if (patch[i].colors[j].alpha < alpha_min)
3005 alpha_min = patch[i].colors[j].alpha;
3006 else if (patch[i].colors[j].alpha > alpha_max)
3007 alpha_max = patch[i].colors[j].alpha;
3018 case CAIRO_PATTERN_TYPE_SURFACE:
3019 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3026 *out_min = alpha_min;
3028 *out_max = alpha_max;
3032 * _cairo_mesh_pattern_coord_box:
3034 * Convenience function to determine the range of the coordinates of
3035 * the points used to define the patches of the mesh.
3037 * This is guaranteed to contain the pattern extents, but might not be
3038 * tight, just like a Bezier curve is always inside the convex hull of
3039 * the control points.
3041 * This function cannot be used while the mesh is being constructed.
3043 * The function returns TRUE and sets the output parametes to define
3044 * the coodrinate range if the mesh pattern contains at least one
3045 * patch, otherwise it returns FALSE.
3048 _cairo_mesh_pattern_coord_box (const cairo_mesh_pattern_t *mesh,
3054 const cairo_mesh_patch_t *patch;
3055 unsigned int num_patches, i, j, k;
3056 double x0, y0, x1, y1;
3058 assert (mesh->current_patch == NULL);
3060 num_patches = _cairo_array_num_elements (&mesh->patches);
3062 if (num_patches == 0)
3065 patch = _cairo_array_index_const (&mesh->patches, 0);
3066 x0 = x1 = patch->points[0][0].x;
3067 y0 = y1 = patch->points[0][0].y;
3069 for (i = 0; i < num_patches; i++) {
3070 for (j = 0; j < 4; j++) {
3071 for (k = 0; k < 4; k++) {
3072 x0 = MIN (x0, patch[i].points[j][k].x);
3073 y0 = MIN (y0, patch[i].points[j][k].y);
3074 x1 = MAX (x1, patch[i].points[j][k].x);
3075 y1 = MAX (y1, patch[i].points[j][k].y);
3089 * _cairo_gradient_pattern_is_solid:
3091 * Convenience function to determine whether a gradient pattern is
3092 * a solid color within the given extents. In this case the color
3093 * argument is initialized to the color the pattern represents.
3094 * This functions doesn't handle completely transparent gradients,
3095 * thus it should be called only after _cairo_pattern_is_clear has
3098 * Return value: %TRUE if the pattern is a solid color.
3101 _cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient,
3102 const cairo_rectangle_int_t *extents,
3103 cairo_color_t *color)
3107 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
3108 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
3111 if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
3112 cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
3113 if (_linear_pattern_is_degenerate (linear)) {
3114 _gradient_color_average (gradient, color);
3118 if (gradient->base.extend == CAIRO_EXTEND_NONE) {
3121 /* We already know that the pattern is not clear, thus if some
3122 * part of it is clear, the whole is not solid.
3125 if (extents == NULL)
3128 _cairo_linear_pattern_box_to_parameter (linear,
3131 extents->x + extents->width,
3132 extents->y + extents->height,
3135 if (t[0] < 0.0 || t[1] > 1.0)
3141 for (i = 1; i < gradient->n_stops; i++)
3142 if (! _cairo_color_stop_equal (&gradient->stops[0].color,
3143 &gradient->stops[i].color))
3146 _cairo_color_init_rgba (color,
3147 gradient->stops[0].color.red,
3148 gradient->stops[0].color.green,
3149 gradient->stops[0].color.blue,
3150 gradient->stops[0].color.alpha);
3156 _mesh_is_clear (const cairo_mesh_pattern_t *mesh)
3158 double x1, y1, x2, y2;
3159 cairo_bool_t is_valid;
3161 is_valid = _cairo_mesh_pattern_coord_box (mesh, &x1, &y1, &x2, &y2);
3165 if (x2 - x1 < DBL_EPSILON || y2 - y1 < DBL_EPSILON)
3172 * _cairo_pattern_is_opaque_solid:
3174 * Convenience function to determine whether a pattern is an opaque
3175 * (alpha==1.0) solid color pattern. This is done by testing whether
3176 * the pattern's alpha value when converted to a byte is 255, so if a
3177 * backend actually supported deep alpha channels this function might
3178 * not do the right thing.
3180 * Return value: %TRUE if the pattern is an opaque, solid color.
3183 _cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern)
3185 cairo_solid_pattern_t *solid;
3187 if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
3190 solid = (cairo_solid_pattern_t *) pattern;
3192 return CAIRO_COLOR_IS_OPAQUE (&solid->color);
3196 _surface_is_opaque (const cairo_surface_pattern_t *pattern,
3197 const cairo_rectangle_int_t *sample)
3199 cairo_rectangle_int_t extents;
3201 if (pattern->surface->content & CAIRO_CONTENT_ALPHA)
3204 if (pattern->base.extend != CAIRO_EXTEND_NONE)
3207 if (! _cairo_surface_get_extents (pattern->surface, &extents))
3213 return _cairo_rectangle_contains_rectangle (&extents, sample);
3217 _raster_source_is_opaque (const cairo_raster_source_pattern_t *pattern,
3218 const cairo_rectangle_int_t *sample)
3220 if (pattern->content & CAIRO_CONTENT_ALPHA)
3223 if (pattern->base.extend != CAIRO_EXTEND_NONE)
3229 return _cairo_rectangle_contains_rectangle (&pattern->extents, sample);
3233 _surface_is_clear (const cairo_surface_pattern_t *pattern)
3235 cairo_rectangle_int_t extents;
3237 if (_cairo_surface_get_extents (pattern->surface, &extents) &&
3238 (extents.width == 0 || extents.height == 0))
3241 return pattern->surface->is_clear &&
3242 pattern->surface->content & CAIRO_CONTENT_ALPHA;
3246 _raster_source_is_clear (const cairo_raster_source_pattern_t *pattern)
3248 return pattern->extents.width == 0 || pattern->extents.height == 0;
3252 _gradient_is_opaque (const cairo_gradient_pattern_t *gradient,
3253 const cairo_rectangle_int_t *sample)
3257 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
3258 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
3260 if (gradient->n_stops == 0 ||
3261 (gradient->base.extend == CAIRO_EXTEND_NONE &&
3262 gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
3265 if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
3266 if (gradient->base.extend == CAIRO_EXTEND_NONE) {
3268 cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
3270 /* EXTEND_NONE degenerate radial gradients are clear */
3271 if (_linear_pattern_is_degenerate (linear))
3277 _cairo_linear_pattern_box_to_parameter (linear,
3280 sample->x + sample->width,
3281 sample->y + sample->height,
3284 if (t[0] < 0.0 || t[1] > 1.0)
3288 return FALSE; /* TODO: check actual intersection */
3290 for (i = 0; i < gradient->n_stops; i++)
3291 if (! CAIRO_COLOR_IS_OPAQUE (&gradient->stops[i].color))
3298 * _cairo_pattern_is_opaque:
3300 * Convenience function to determine whether a pattern is an opaque
3301 * pattern (of any type). The same caveats that apply to
3302 * _cairo_pattern_is_opaque_solid apply here as well.
3304 * Return value: %TRUE if the pattern is a opaque.
3307 _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern,
3308 const cairo_rectangle_int_t *sample)
3310 const cairo_pattern_union_t *pattern;
3312 if (abstract_pattern->has_component_alpha)
3315 pattern = (cairo_pattern_union_t *) abstract_pattern;
3316 switch (pattern->base.type) {
3317 case CAIRO_PATTERN_TYPE_SOLID:
3318 return _cairo_pattern_is_opaque_solid (abstract_pattern);
3319 case CAIRO_PATTERN_TYPE_SURFACE:
3320 return _surface_is_opaque (&pattern->surface, sample);
3321 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3322 return _raster_source_is_opaque (&pattern->raster_source, sample);
3323 case CAIRO_PATTERN_TYPE_LINEAR:
3324 case CAIRO_PATTERN_TYPE_RADIAL:
3325 return _gradient_is_opaque (&pattern->gradient.base, sample);
3326 case CAIRO_PATTERN_TYPE_MESH:
3335 _cairo_pattern_is_clear (const cairo_pattern_t *abstract_pattern)
3337 const cairo_pattern_union_t *pattern;
3339 if (abstract_pattern->has_component_alpha)
3342 pattern = (cairo_pattern_union_t *) abstract_pattern;
3343 switch (abstract_pattern->type) {
3344 case CAIRO_PATTERN_TYPE_SOLID:
3345 return CAIRO_COLOR_IS_CLEAR (&pattern->solid.color);
3346 case CAIRO_PATTERN_TYPE_SURFACE:
3347 return _surface_is_clear (&pattern->surface);
3348 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3349 return _raster_source_is_clear (&pattern->raster_source);
3350 case CAIRO_PATTERN_TYPE_LINEAR:
3351 case CAIRO_PATTERN_TYPE_RADIAL:
3352 return _gradient_is_clear (&pattern->gradient.base, NULL);
3353 case CAIRO_PATTERN_TYPE_MESH:
3354 return _mesh_is_clear (&pattern->mesh);
3362 * _cairo_pattern_analyze_filter:
3363 * @pattern: surface pattern
3364 * @pad_out: location to store necessary padding in the source image, or %NULL
3365 * Returns: the optimized #cairo_filter_t to use with @pattern.
3367 * Analyze the filter to determine how much extra needs to be sampled
3368 * from the source image to account for the filter radius and whether
3369 * we can optimize the filter to a simpler value.
3371 * XXX: We don't actually have any way of querying the backend for
3372 * the filter radius, so we just guess base on what we know that
3373 * backends do currently (see bug #10508)
3376 _cairo_pattern_analyze_filter (const cairo_pattern_t *pattern,
3380 cairo_filter_t optimized_filter;
3382 switch (pattern->filter) {
3383 case CAIRO_FILTER_GOOD:
3384 case CAIRO_FILTER_BEST:
3385 case CAIRO_FILTER_BILINEAR:
3386 /* If source pixels map 1:1 onto destination pixels, we do
3387 * not need to filter (and do not want to filter, since it
3388 * will cause blurriness)
3390 if (_cairo_matrix_is_pixel_exact (&pattern->matrix)) {
3392 optimized_filter = CAIRO_FILTER_NEAREST;
3394 /* 0.5 is enough for a bilinear filter. It's possible we
3395 * should defensively use more for CAIRO_FILTER_BEST, but
3396 * without a single example, it's hard to know how much
3397 * more would be defensive...
3400 optimized_filter = pattern->filter;
3404 case CAIRO_FILTER_FAST:
3405 case CAIRO_FILTER_NEAREST:
3406 case CAIRO_FILTER_GAUSSIAN:
3409 optimized_filter = pattern->filter;
3416 return optimized_filter;
3420 _cairo_pattern_sampled_area (const cairo_pattern_t *pattern,
3421 const cairo_rectangle_int_t *extents,
3422 cairo_rectangle_int_t *sample)
3424 cairo_filter_t filter;
3425 double x1, x2, y1, y2;
3428 filter = _cairo_pattern_analyze_filter (pattern, &pad);
3429 if (pad == 0.0 && _cairo_matrix_is_identity (&pattern->matrix)) {
3436 x2 = extents->x + (int) extents->width;
3437 y2 = extents->y + (int) extents->height;
3439 _cairo_matrix_transform_bounding_box (&pattern->matrix,
3442 if (x1 > CAIRO_RECT_INT_MIN)
3443 sample->x = floor (x1 - pad);
3445 sample->x = CAIRO_RECT_INT_MIN;
3447 if (y1 > CAIRO_RECT_INT_MIN)
3448 sample->y = floor (y1 - pad);
3450 sample->y = CAIRO_RECT_INT_MIN;
3452 if (x2 < CAIRO_RECT_INT_MAX)
3453 sample->width = ceil (x2 + pad);
3455 sample->width = CAIRO_RECT_INT_MAX;
3457 if (y2 < CAIRO_RECT_INT_MAX)
3458 sample->height = ceil (y2 + pad);
3460 sample->height = CAIRO_RECT_INT_MAX;
3462 sample->width -= sample->x;
3463 sample->height -= sample->y;
3469 * _cairo_pattern_get_extents:
3471 * Return the "target-space" extents of @pattern in @extents.
3473 * For unbounded patterns, the @extents will be initialized with
3474 * "infinite" extents, (minimum and maximum fixed-point values).
3476 * XXX: Currently, bounded gradient patterns will also return
3477 * "infinite" extents, though it would be possible to optimize these
3478 * with a little more work.
3481 _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
3482 cairo_rectangle_int_t *extents)
3484 double x1, y1, x2, y2;
3485 cairo_status_t status;
3487 switch (pattern->type) {
3488 case CAIRO_PATTERN_TYPE_SOLID:
3491 case CAIRO_PATTERN_TYPE_SURFACE:
3493 cairo_rectangle_int_t surface_extents;
3494 const cairo_surface_pattern_t *surface_pattern =
3495 (const cairo_surface_pattern_t *) pattern;
3496 cairo_surface_t *surface = surface_pattern->surface;
3499 if (! _cairo_surface_get_extents (surface, &surface_extents))
3502 if (surface_extents.width == 0 || surface_extents.height == 0)
3505 if (pattern->extend != CAIRO_EXTEND_NONE)
3508 /* The filter can effectively enlarge the extents of the
3509 * pattern, so extend as necessary.
3511 _cairo_pattern_analyze_filter (&surface_pattern->base, &pad);
3512 x1 = surface_extents.x - pad;
3513 y1 = surface_extents.y - pad;
3514 x2 = surface_extents.x + (int) surface_extents.width + pad;
3515 y2 = surface_extents.y + (int) surface_extents.height + pad;
3519 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3521 const cairo_raster_source_pattern_t *raster =
3522 (const cairo_raster_source_pattern_t *) pattern;
3525 if (raster->extents.width == 0 || raster->extents.height == 0)
3528 if (pattern->extend != CAIRO_EXTEND_NONE)
3531 /* The filter can effectively enlarge the extents of the
3532 * pattern, so extend as necessary.
3534 _cairo_pattern_analyze_filter (pattern, &pad);
3535 x1 = raster->extents.x - pad;
3536 y1 = raster->extents.y - pad;
3537 x2 = raster->extents.x + (int) raster->extents.width + pad;
3538 y2 = raster->extents.y + (int) raster->extents.height + pad;
3542 case CAIRO_PATTERN_TYPE_RADIAL:
3544 const cairo_radial_pattern_t *radial =
3545 (const cairo_radial_pattern_t *) pattern;
3550 if (_radial_pattern_is_degenerate (radial)) {
3551 /* cairo-gstate should have optimised degenerate
3552 * patterns to solid clear patterns, so we can ignore
3557 /* TODO: in some cases (focus outside/on the circle) it is
3559 if (pattern->extend != CAIRO_EXTEND_NONE)
3562 cx1 = radial->cd1.center.x;
3563 cy1 = radial->cd1.center.y;
3564 r1 = radial->cd1.radius;
3566 cx2 = radial->cd2.center.x;
3567 cy2 = radial->cd2.center.y;
3568 r2 = radial->cd2.radius;
3570 x1 = MIN (cx1 - r1, cx2 - r2);
3571 y1 = MIN (cy1 - r1, cy2 - r2);
3572 x2 = MAX (cx1 + r1, cx2 + r2);
3573 y2 = MAX (cy1 + r1, cy2 + r2);
3577 case CAIRO_PATTERN_TYPE_LINEAR:
3579 const cairo_linear_pattern_t *linear =
3580 (const cairo_linear_pattern_t *) pattern;
3582 if (pattern->extend != CAIRO_EXTEND_NONE)
3585 if (_linear_pattern_is_degenerate (linear)) {
3586 /* cairo-gstate should have optimised degenerate
3587 * patterns to solid ones, so we can again ignore
3592 /* TODO: to get tight extents, use the matrix to transform
3593 * the pattern instead of transforming the extents later. */
3594 if (pattern->matrix.xy != 0. || pattern->matrix.yx != 0.)
3597 if (linear->pd1.x == linear->pd2.x) {
3600 y1 = MIN (linear->pd1.y, linear->pd2.y);
3601 y2 = MAX (linear->pd1.y, linear->pd2.y);
3602 } else if (linear->pd1.y == linear->pd2.y) {
3603 x1 = MIN (linear->pd1.x, linear->pd2.x);
3604 x2 = MAX (linear->pd1.x, linear->pd2.x);
3613 case CAIRO_PATTERN_TYPE_MESH:
3615 const cairo_mesh_pattern_t *mesh =
3616 (const cairo_mesh_pattern_t *) pattern;
3618 cairo_bool_t is_valid;
3620 is_valid = _cairo_mesh_pattern_coord_box (mesh, &x1, &y1, &x2, &y2);
3625 cairo_matrix_transform_distance (&pattern->matrix, &padx, &pady);
3640 if (_cairo_matrix_is_translation (&pattern->matrix)) {
3641 x1 -= pattern->matrix.x0; x2 -= pattern->matrix.x0;
3642 y1 -= pattern->matrix.y0; y2 -= pattern->matrix.y0;
3644 cairo_matrix_t imatrix;
3646 imatrix = pattern->matrix;
3647 status = cairo_matrix_invert (&imatrix);
3648 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3649 assert (status == CAIRO_STATUS_SUCCESS);
3651 _cairo_matrix_transform_bounding_box (&imatrix,
3657 if (x1 < CAIRO_RECT_INT_MIN)
3658 x1 = CAIRO_RECT_INT_MIN;
3660 if (y1 < CAIRO_RECT_INT_MIN)
3661 y1 = CAIRO_RECT_INT_MIN;
3664 if (x2 > CAIRO_RECT_INT_MAX)
3665 x2 = CAIRO_RECT_INT_MAX;
3667 if (y2 > CAIRO_RECT_INT_MAX)
3668 y2 = CAIRO_RECT_INT_MAX;
3670 extents->x = x1; extents->width = x2 - x1;
3671 extents->y = y1; extents->height = y2 - y1;
3675 /* unbounded patterns -> 'infinite' extents */
3676 _cairo_unbounded_rectangle_init (extents);
3680 extents->x = extents->y = 0;
3681 extents->width = extents->height = 0;
3686 _cairo_pattern_get_exact_extents (const cairo_pattern_t *pattern,
3687 cairo_rectangle_t *extents)
3689 double x1, y1, x2, y2;
3690 cairo_status_t status;
3691 cairo_rectangle_int_t int_rect;;
3693 switch (pattern->type) {
3694 case CAIRO_PATTERN_TYPE_SOLID:
3697 case CAIRO_PATTERN_TYPE_SURFACE:
3699 cairo_rectangle_int_t surface_extents;
3700 const cairo_surface_pattern_t *surface_pattern =
3701 (const cairo_surface_pattern_t *) pattern;
3702 cairo_surface_t *surface = surface_pattern->surface;
3704 if (! _cairo_surface_get_extents (surface, &surface_extents))
3707 if (surface_extents.width == 0 || surface_extents.height == 0)
3710 if (pattern->extend != CAIRO_EXTEND_NONE)
3713 x1 = surface_extents.x;
3714 y1 = surface_extents.y;
3715 x2 = surface_extents.x + surface_extents.width;
3716 y2 = surface_extents.y + surface_extents.height;
3720 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3722 const cairo_raster_source_pattern_t *raster =
3723 (const cairo_raster_source_pattern_t *) pattern;
3725 if (raster->extents.width == 0 || raster->extents.height == 0)
3728 if (pattern->extend != CAIRO_EXTEND_NONE)
3731 x1 = raster->extents.x;
3732 y1 = raster->extents.y;
3733 x2 = raster->extents.x + raster->extents.width;
3734 y2 = raster->extents.y + raster->extents.height;
3738 case CAIRO_PATTERN_TYPE_RADIAL:
3740 const cairo_radial_pattern_t *radial =
3741 (const cairo_radial_pattern_t *) pattern;
3746 if (_radial_pattern_is_degenerate (radial)) {
3747 /* cairo-gstate should have optimised degenerate
3748 * patterns to solid clear patterns, so we can ignore
3753 /* TODO: in some cases (focus outside/on the circle) it is
3755 if (pattern->extend != CAIRO_EXTEND_NONE)
3758 cx1 = radial->cd1.center.x;
3759 cy1 = radial->cd1.center.y;
3760 r1 = radial->cd1.radius;
3762 cx2 = radial->cd2.center.x;
3763 cy2 = radial->cd2.center.y;
3764 r2 = radial->cd2.radius;
3766 x1 = MIN (cx1 - r1, cx2 - r2);
3767 y1 = MIN (cy1 - r1, cy2 - r2);
3768 x2 = MAX (cx1 + r1, cx2 + r2);
3769 y2 = MAX (cy1 + r1, cy2 + r2);
3773 case CAIRO_PATTERN_TYPE_LINEAR:
3775 const cairo_linear_pattern_t *linear =
3776 (const cairo_linear_pattern_t *) pattern;
3778 if (pattern->extend != CAIRO_EXTEND_NONE)
3781 if (_linear_pattern_is_degenerate (linear)) {
3782 /* cairo-gstate should have optimised degenerate
3783 * patterns to solid ones, so we can again ignore
3788 /* TODO: to get tight extents, use the matrix to transform
3789 * the pattern instead of transforming the extents later. */
3790 if (pattern->matrix.xy != 0. || pattern->matrix.yx != 0.)
3793 if (linear->pd1.x == linear->pd2.x) {
3796 y1 = MIN (linear->pd1.y, linear->pd2.y);
3797 y2 = MAX (linear->pd1.y, linear->pd2.y);
3798 } else if (linear->pd1.y == linear->pd2.y) {
3799 x1 = MIN (linear->pd1.x, linear->pd2.x);
3800 x2 = MAX (linear->pd1.x, linear->pd2.x);
3809 case CAIRO_PATTERN_TYPE_MESH:
3811 const cairo_mesh_pattern_t *mesh =
3812 (const cairo_mesh_pattern_t *) pattern;
3814 cairo_bool_t is_valid;
3816 is_valid = _cairo_mesh_pattern_coord_box (mesh, &x1, &y1, &x2, &y2);
3821 cairo_matrix_transform_distance (&pattern->matrix, &padx, &pady);
3836 if (_cairo_matrix_is_translation (&pattern->matrix)) {
3837 x1 -= pattern->matrix.x0; x2 -= pattern->matrix.x0;
3838 y1 -= pattern->matrix.y0; y2 -= pattern->matrix.y0;
3840 cairo_matrix_t imatrix;
3842 imatrix = pattern->matrix;
3843 status = cairo_matrix_invert (&imatrix);
3844 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3845 assert (status == CAIRO_STATUS_SUCCESS);
3847 _cairo_matrix_transform_bounding_box (&imatrix,
3852 if (x1 < CAIRO_RECT_INT_MIN)
3853 x1 = CAIRO_RECT_INT_MIN;
3854 if (y1 < CAIRO_RECT_INT_MIN)
3855 y1 = CAIRO_RECT_INT_MIN;
3857 if (x2 > CAIRO_RECT_INT_MAX)
3858 x2 = CAIRO_RECT_INT_MAX;
3859 if (y2 > CAIRO_RECT_INT_MAX)
3860 y2 = CAIRO_RECT_INT_MAX;
3862 extents->x = x1; extents->width = x2 - x1;
3863 extents->y = y1; extents->height = y2 - y1;
3867 /* unbounded patterns -> 'infinite' extents */
3868 _cairo_unbounded_rectangle_init (&int_rect);
3869 extents->x = int_rect.x;
3870 extents->y = int_rect.y;
3871 extents->width = int_rect.width;
3872 extents->height = int_rect.height;
3876 extents->x = extents->y = 0;
3877 extents->width = extents->height = 0;
3882 * _cairo_pattern_get_ink_extents:
3884 * Return the "target-space" inked extents of @pattern in @extents.
3887 _cairo_pattern_get_ink_extents (const cairo_pattern_t *pattern,
3888 cairo_rectangle_int_t *extents)
3890 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE &&
3891 pattern->extend == CAIRO_EXTEND_NONE)
3893 const cairo_surface_pattern_t *surface_pattern =
3894 (const cairo_surface_pattern_t *) pattern;
3895 cairo_surface_t *surface = surface_pattern->surface;
3897 surface = _cairo_surface_get_source (surface, NULL);
3898 if (_cairo_surface_is_recording (surface)) {
3899 cairo_matrix_t imatrix;
3901 cairo_status_t status;
3903 imatrix = pattern->matrix;
3904 status = cairo_matrix_invert (&imatrix);
3905 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3906 assert (status == CAIRO_STATUS_SUCCESS);
3908 status = _cairo_recording_surface_get_ink_bbox ((cairo_recording_surface_t *)surface,
3910 if (unlikely (status))
3913 _cairo_box_round_to_rectangle (&box, extents);
3914 return CAIRO_STATUS_SUCCESS;
3918 _cairo_pattern_get_extents (pattern, extents);
3919 return CAIRO_STATUS_SUCCESS;
3922 static unsigned long
3923 _cairo_solid_pattern_hash (unsigned long hash,
3924 const cairo_solid_pattern_t *solid)
3926 hash = _cairo_hash_bytes (hash, &solid->color, sizeof (solid->color));
3931 static unsigned long
3932 _cairo_gradient_color_stops_hash (unsigned long hash,
3933 const cairo_gradient_pattern_t *gradient)
3937 hash = _cairo_hash_bytes (hash,
3939 sizeof (gradient->n_stops));
3941 for (n = 0; n < gradient->n_stops; n++) {
3942 hash = _cairo_hash_bytes (hash,
3943 &gradient->stops[n].offset,
3945 hash = _cairo_hash_bytes (hash,
3946 &gradient->stops[n].color,
3947 sizeof (cairo_color_stop_t));
3954 _cairo_linear_pattern_hash (unsigned long hash,
3955 const cairo_linear_pattern_t *linear)
3957 hash = _cairo_hash_bytes (hash, &linear->pd1, sizeof (linear->pd1));
3958 hash = _cairo_hash_bytes (hash, &linear->pd2, sizeof (linear->pd2));
3960 return _cairo_gradient_color_stops_hash (hash, &linear->base);
3964 _cairo_radial_pattern_hash (unsigned long hash,
3965 const cairo_radial_pattern_t *radial)
3967 hash = _cairo_hash_bytes (hash, &radial->cd1.center, sizeof (radial->cd1.center));
3968 hash = _cairo_hash_bytes (hash, &radial->cd1.radius, sizeof (radial->cd1.radius));
3969 hash = _cairo_hash_bytes (hash, &radial->cd2.center, sizeof (radial->cd2.center));
3970 hash = _cairo_hash_bytes (hash, &radial->cd2.radius, sizeof (radial->cd2.radius));
3972 return _cairo_gradient_color_stops_hash (hash, &radial->base);
3975 static unsigned long
3976 _cairo_mesh_pattern_hash (unsigned long hash, const cairo_mesh_pattern_t *mesh)
3978 const cairo_mesh_patch_t *patch = _cairo_array_index_const (&mesh->patches, 0);
3979 unsigned int i, n = _cairo_array_num_elements (&mesh->patches);
3981 for (i = 0; i < n; i++)
3982 hash = _cairo_hash_bytes (hash, patch + i, sizeof (cairo_mesh_patch_t));
3987 static unsigned long
3988 _cairo_surface_pattern_hash (unsigned long hash,
3989 const cairo_surface_pattern_t *surface)
3991 hash ^= surface->surface->unique_id;
3996 static unsigned long
3997 _cairo_raster_source_pattern_hash (unsigned long hash,
3998 const cairo_raster_source_pattern_t *raster)
4000 hash ^= (uintptr_t)raster->user_data;
4006 _cairo_pattern_hash (const cairo_pattern_t *pattern)
4008 unsigned long hash = _CAIRO_HASH_INIT_VALUE;
4010 if (pattern->status)
4013 hash = _cairo_hash_bytes (hash, &pattern->type, sizeof (pattern->type));
4014 if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
4015 hash = _cairo_hash_bytes (hash,
4016 &pattern->matrix, sizeof (pattern->matrix));
4017 hash = _cairo_hash_bytes (hash,
4018 &pattern->filter, sizeof (pattern->filter));
4019 hash = _cairo_hash_bytes (hash,
4020 &pattern->extend, sizeof (pattern->extend));
4021 hash = _cairo_hash_bytes (hash,
4022 &pattern->has_component_alpha,
4023 sizeof (pattern->has_component_alpha));
4026 switch (pattern->type) {
4027 case CAIRO_PATTERN_TYPE_SOLID:
4028 return _cairo_solid_pattern_hash (hash, (cairo_solid_pattern_t *) pattern);
4029 case CAIRO_PATTERN_TYPE_LINEAR:
4030 return _cairo_linear_pattern_hash (hash, (cairo_linear_pattern_t *) pattern);
4031 case CAIRO_PATTERN_TYPE_RADIAL:
4032 return _cairo_radial_pattern_hash (hash, (cairo_radial_pattern_t *) pattern);
4033 case CAIRO_PATTERN_TYPE_MESH:
4034 return _cairo_mesh_pattern_hash (hash, (cairo_mesh_pattern_t *) pattern);
4035 case CAIRO_PATTERN_TYPE_SURFACE:
4036 return _cairo_surface_pattern_hash (hash, (cairo_surface_pattern_t *) pattern);
4037 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4038 return _cairo_raster_source_pattern_hash (hash, (cairo_raster_source_pattern_t *) pattern);
4046 _cairo_solid_pattern_equal (const cairo_solid_pattern_t *a,
4047 const cairo_solid_pattern_t *b)
4049 return _cairo_color_equal (&a->color, &b->color);
4053 _cairo_gradient_color_stops_equal (const cairo_gradient_pattern_t *a,
4054 const cairo_gradient_pattern_t *b)
4058 if (a->n_stops != b->n_stops)
4061 for (n = 0; n < a->n_stops; n++) {
4062 if (a->stops[n].offset != b->stops[n].offset)
4064 if (! _cairo_color_stop_equal (&a->stops[n].color, &b->stops[n].color))
4072 _cairo_linear_pattern_equal (const cairo_linear_pattern_t *a,
4073 const cairo_linear_pattern_t *b)
4075 if (a->pd1.x != b->pd1.x)
4078 if (a->pd1.y != b->pd1.y)
4081 if (a->pd2.x != b->pd2.x)
4084 if (a->pd2.y != b->pd2.y)
4087 return _cairo_gradient_color_stops_equal (&a->base, &b->base);
4091 _cairo_radial_pattern_equal (const cairo_radial_pattern_t *a,
4092 const cairo_radial_pattern_t *b)
4094 if (a->cd1.center.x != b->cd1.center.x)
4097 if (a->cd1.center.y != b->cd1.center.y)
4100 if (a->cd1.radius != b->cd1.radius)
4103 if (a->cd2.center.x != b->cd2.center.x)
4106 if (a->cd2.center.y != b->cd2.center.y)
4109 if (a->cd2.radius != b->cd2.radius)
4112 return _cairo_gradient_color_stops_equal (&a->base, &b->base);
4116 _cairo_mesh_pattern_equal (const cairo_mesh_pattern_t *a,
4117 const cairo_mesh_pattern_t *b)
4119 const cairo_mesh_patch_t *patch_a, *patch_b;
4120 unsigned int i, num_patches_a, num_patches_b;
4122 num_patches_a = _cairo_array_num_elements (&a->patches);
4123 num_patches_b = _cairo_array_num_elements (&b->patches);
4125 if (num_patches_a != num_patches_b)
4128 for (i = 0; i < num_patches_a; i++) {
4129 patch_a = _cairo_array_index_const (&a->patches, i);
4130 patch_b = _cairo_array_index_const (&b->patches, i);
4131 if (patch_a == NULL || patch_b == NULL)
4134 if (memcmp (patch_a, patch_b, sizeof(cairo_mesh_patch_t)) != 0)
4142 _cairo_surface_pattern_equal (const cairo_surface_pattern_t *a,
4143 const cairo_surface_pattern_t *b)
4145 return a->surface->unique_id == b->surface->unique_id;
4149 _cairo_raster_source_pattern_equal (const cairo_raster_source_pattern_t *a,
4150 const cairo_raster_source_pattern_t *b)
4152 return a->user_data == b->user_data;
4156 _cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b)
4158 if (a->status || b->status)
4164 if (a->type != b->type)
4167 if (a->has_component_alpha != b->has_component_alpha)
4170 if (a->type != CAIRO_PATTERN_TYPE_SOLID) {
4171 if (memcmp (&a->matrix, &b->matrix, sizeof (cairo_matrix_t)))
4174 if (a->filter != b->filter)
4177 if (a->extend != b->extend)
4182 case CAIRO_PATTERN_TYPE_SOLID:
4183 return _cairo_solid_pattern_equal ((cairo_solid_pattern_t *) a,
4184 (cairo_solid_pattern_t *) b);
4185 case CAIRO_PATTERN_TYPE_LINEAR:
4186 return _cairo_linear_pattern_equal ((cairo_linear_pattern_t *) a,
4187 (cairo_linear_pattern_t *) b);
4188 case CAIRO_PATTERN_TYPE_RADIAL:
4189 return _cairo_radial_pattern_equal ((cairo_radial_pattern_t *) a,
4190 (cairo_radial_pattern_t *) b);
4191 case CAIRO_PATTERN_TYPE_MESH:
4192 return _cairo_mesh_pattern_equal ((cairo_mesh_pattern_t *) a,
4193 (cairo_mesh_pattern_t *) b);
4194 case CAIRO_PATTERN_TYPE_SURFACE:
4195 return _cairo_surface_pattern_equal ((cairo_surface_pattern_t *) a,
4196 (cairo_surface_pattern_t *) b);
4197 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4198 return _cairo_raster_source_pattern_equal ((cairo_raster_source_pattern_t *) a,
4199 (cairo_raster_source_pattern_t *) b);
4207 * cairo_pattern_get_rgba:
4208 * @pattern: a #cairo_pattern_t
4209 * @red: return value for red component of color, or %NULL
4210 * @green: return value for green component of color, or %NULL
4211 * @blue: return value for blue component of color, or %NULL
4212 * @alpha: return value for alpha component of color, or %NULL
4214 * Gets the solid color for a solid color pattern.
4216 * Return value: %CAIRO_STATUS_SUCCESS, or
4217 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid
4223 cairo_pattern_get_rgba (cairo_pattern_t *pattern,
4224 double *red, double *green,
4225 double *blue, double *alpha)
4227 cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
4228 double r0, g0, b0, a0;
4230 if (pattern->status)
4231 return pattern->status;
4233 if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
4234 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4236 _cairo_color_get_rgba (&solid->color, &r0, &g0, &b0, &a0);
4247 return CAIRO_STATUS_SUCCESS;
4251 * cairo_pattern_get_surface:
4252 * @pattern: a #cairo_pattern_t
4253 * @surface: return value for surface of pattern, or %NULL
4255 * Gets the surface of a surface pattern. The reference returned in
4256 * @surface is owned by the pattern; the caller should call
4257 * cairo_surface_reference() if the surface is to be retained.
4259 * Return value: %CAIRO_STATUS_SUCCESS, or
4260 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a surface
4266 cairo_pattern_get_surface (cairo_pattern_t *pattern,
4267 cairo_surface_t **surface)
4269 cairo_surface_pattern_t *spat = (cairo_surface_pattern_t*) pattern;
4271 if (pattern->status)
4272 return pattern->status;
4274 if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
4275 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4278 *surface = spat->surface;
4280 return CAIRO_STATUS_SUCCESS;
4284 * cairo_pattern_get_color_stop_rgba:
4285 * @pattern: a #cairo_pattern_t
4286 * @index: index of the stop to return data for
4287 * @offset: return value for the offset of the stop, or %NULL
4288 * @red: return value for red component of color, or %NULL
4289 * @green: return value for green component of color, or %NULL
4290 * @blue: return value for blue component of color, or %NULL
4291 * @alpha: return value for alpha component of color, or %NULL
4293 * Gets the color and offset information at the given @index for a
4294 * gradient pattern. Values of @index are 0 to 1 less than the number
4295 * returned by cairo_pattern_get_color_stop_count().
4297 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
4298 * if @index is not valid for the given pattern. If the pattern is
4299 * not a gradient pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
4305 cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
4306 int index, double *offset,
4307 double *red, double *green,
4308 double *blue, double *alpha)
4310 cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
4312 if (pattern->status)
4313 return pattern->status;
4315 if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
4316 pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
4317 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4319 if (index < 0 || (unsigned int) index >= gradient->n_stops)
4320 return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4323 *offset = gradient->stops[index].offset;
4325 *red = gradient->stops[index].color.red;
4327 *green = gradient->stops[index].color.green;
4329 *blue = gradient->stops[index].color.blue;
4331 *alpha = gradient->stops[index].color.alpha;
4333 return CAIRO_STATUS_SUCCESS;
4337 * cairo_pattern_get_color_stop_count:
4338 * @pattern: a #cairo_pattern_t
4339 * @count: return value for the number of color stops, or %NULL
4341 * Gets the number of color stops specified in the given gradient
4344 * Return value: %CAIRO_STATUS_SUCCESS, or
4345 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
4351 cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
4354 cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
4356 if (pattern->status)
4357 return pattern->status;
4359 if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
4360 pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
4361 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4364 *count = gradient->n_stops;
4366 return CAIRO_STATUS_SUCCESS;
4370 * cairo_pattern_get_linear_points:
4371 * @pattern: a #cairo_pattern_t
4372 * @x0: return value for the x coordinate of the first point, or %NULL
4373 * @y0: return value for the y coordinate of the first point, or %NULL
4374 * @x1: return value for the x coordinate of the second point, or %NULL
4375 * @y1: return value for the y coordinate of the second point, or %NULL
4377 * Gets the gradient endpoints for a linear gradient.
4379 * Return value: %CAIRO_STATUS_SUCCESS, or
4380 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a linear
4386 cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
4387 double *x0, double *y0,
4388 double *x1, double *y1)
4390 cairo_linear_pattern_t *linear = (cairo_linear_pattern_t*) pattern;
4392 if (pattern->status)
4393 return pattern->status;
4395 if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR)
4396 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4399 *x0 = linear->pd1.x;
4401 *y0 = linear->pd1.y;
4403 *x1 = linear->pd2.x;
4405 *y1 = linear->pd2.y;
4407 return CAIRO_STATUS_SUCCESS;
4411 * cairo_pattern_get_radial_circles:
4412 * @pattern: a #cairo_pattern_t
4413 * @x0: return value for the x coordinate of the center of the first circle, or %NULL
4414 * @y0: return value for the y coordinate of the center of the first circle, or %NULL
4415 * @r0: return value for the radius of the first circle, or %NULL
4416 * @x1: return value for the x coordinate of the center of the second circle, or %NULL
4417 * @y1: return value for the y coordinate of the center of the second circle, or %NULL
4418 * @r1: return value for the radius of the second circle, or %NULL
4420 * Gets the gradient endpoint circles for a radial gradient, each
4421 * specified as a center coordinate and a radius.
4423 * Return value: %CAIRO_STATUS_SUCCESS, or
4424 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial
4430 cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
4431 double *x0, double *y0, double *r0,
4432 double *x1, double *y1, double *r1)
4434 cairo_radial_pattern_t *radial = (cairo_radial_pattern_t*) pattern;
4436 if (pattern->status)
4437 return pattern->status;
4439 if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
4440 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4443 *x0 = radial->cd1.center.x;
4445 *y0 = radial->cd1.center.y;
4447 *r0 = radial->cd1.radius;
4449 *x1 = radial->cd2.center.x;
4451 *y1 = radial->cd2.center.y;
4453 *r1 = radial->cd2.radius;
4455 return CAIRO_STATUS_SUCCESS;
4459 * cairo_mesh_pattern_get_patch_count:
4460 * @pattern: a #cairo_pattern_t
4461 * @count: return value for the number patches, or %NULL
4463 * Gets the number of patches specified in the given mesh pattern.
4465 * The number only includes patches which have been finished by
4466 * calling cairo_mesh_pattern_end_patch(). For example it will be 0
4467 * during the definition of the first patch.
4469 * Return value: %CAIRO_STATUS_SUCCESS, or
4470 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a mesh
4476 cairo_mesh_pattern_get_patch_count (cairo_pattern_t *pattern,
4477 unsigned int *count)
4479 cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
4481 if (unlikely (pattern->status))
4482 return pattern->status;
4484 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH))
4485 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4488 *count = _cairo_array_num_elements (&mesh->patches);
4489 if (mesh->current_patch)
4493 return CAIRO_STATUS_SUCCESS;
4495 slim_hidden_def (cairo_mesh_pattern_get_patch_count);
4498 * cairo_mesh_pattern_get_path:
4499 * @pattern: a #cairo_pattern_t
4500 * @patch_num: the patch number to return data for
4502 * Gets path defining the patch @patch_num for a mesh
4505 * @patch_num can range 0 to 1 less than the number returned by
4506 * cairo_mesh_pattern_get_patch_count().
4508 * Return value: the path defining the patch, or a path with status
4509 * %CAIRO_STATUS_INVALID_INDEX if @patch_num or @point_num is not
4510 * valid for @pattern. If @pattern is not a mesh pattern, a path with
4511 * status %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is returned.
4516 cairo_mesh_pattern_get_path (cairo_pattern_t *pattern,
4517 unsigned int patch_num)
4519 cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
4520 const cairo_mesh_patch_t *patch;
4522 cairo_path_data_t *data;
4523 unsigned int patch_count;
4524 int l, current_point;
4526 if (unlikely (pattern->status))
4527 return _cairo_path_create_in_error (pattern->status);
4529 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH))
4530 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH));
4532 patch_count = _cairo_array_num_elements (&mesh->patches);
4533 if (mesh->current_patch)
4536 if (unlikely (patch_num >= patch_count))
4537 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_INDEX));
4539 patch = _cairo_array_index_const (&mesh->patches, patch_num);
4542 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_INDEX));
4544 path = malloc (sizeof (cairo_path_t));
4546 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
4548 path->num_data = 18;
4549 path->data = _cairo_malloc_ab (path->num_data,
4550 sizeof (cairo_path_data_t));
4551 if (path->data == NULL) {
4553 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
4557 data[0].header.type = CAIRO_PATH_MOVE_TO;
4558 data[0].header.length = 2;
4559 data[1].point.x = patch->points[0][0].x;
4560 data[1].point.y = patch->points[0][0].y;
4561 data += data[0].header.length;
4565 for (l = 0; l < 4; l++) {
4568 data[0].header.type = CAIRO_PATH_CURVE_TO;
4569 data[0].header.length = 4;
4571 for (k = 1; k < 4; k++) {
4572 current_point = (current_point + 1) % 12;
4573 i = mesh_path_point_i[current_point];
4574 j = mesh_path_point_j[current_point];
4575 data[k].point.x = patch->points[i][j].x;
4576 data[k].point.y = patch->points[i][j].y;
4579 data += data[0].header.length;
4582 path->status = CAIRO_STATUS_SUCCESS;
4586 slim_hidden_def (cairo_mesh_pattern_get_path);
4589 * cairo_mesh_pattern_get_corner_color_rgba:
4590 * @pattern: a #cairo_pattern_t
4591 * @patch_num: the patch number to return data for
4592 * @corner_num: the corner number to return data for
4593 * @red: return value for red component of color, or %NULL
4594 * @green: return value for green component of color, or %NULL
4595 * @blue: return value for blue component of color, or %NULL
4596 * @alpha: return value for alpha component of color, or %NULL
4598 * Gets the color information in corner @corner_num of patch
4599 * @patch_num for a mesh pattern.
4601 * @patch_num can range 0 to 1 less than the number returned by
4602 * cairo_mesh_pattern_get_patch_count().
4604 * Valid values for @corner_num are from 0 to 3 and identify the
4605 * corners as explained in cairo_pattern_create_mesh().
4607 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
4608 * if @patch_num or @corner_num is not valid for @pattern. If
4609 * @pattern is not a mesh pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH
4615 cairo_mesh_pattern_get_corner_color_rgba (cairo_pattern_t *pattern,
4616 unsigned int patch_num,
4617 unsigned int corner_num,
4618 double *red, double *green,
4619 double *blue, double *alpha)
4621 cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
4622 unsigned int patch_count;
4623 const cairo_mesh_patch_t *patch;
4625 if (unlikely (pattern->status))
4626 return pattern->status;
4628 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH))
4629 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4631 if (unlikely (corner_num > 3))
4632 return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4634 patch_count = _cairo_array_num_elements (&mesh->patches);
4635 if (mesh->current_patch)
4638 if (unlikely (patch_num >= patch_count))
4639 return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4641 patch = _cairo_array_index_const (&mesh->patches, patch_num);
4643 return _cairo_error(CAIRO_STATUS_NULL_POINTER);
4646 *red = patch->colors[corner_num].red;
4648 *green = patch->colors[corner_num].green;
4650 *blue = patch->colors[corner_num].blue;
4652 *alpha = patch->colors[corner_num].alpha;
4654 return CAIRO_STATUS_SUCCESS;
4656 slim_hidden_def (cairo_mesh_pattern_get_corner_color_rgba);
4659 * cairo_mesh_pattern_get_control_point:
4660 * @pattern: a #cairo_pattern_t
4661 * @patch_num: the patch number to return data for
4662 * @point_num: the control point number to return data for
4663 * @x: return value for the x coordinate of the control point, or %NULL
4664 * @y: return value for the y coordinate of the control point, or %NULL
4666 * Gets the control point @point_num of patch @patch_num for a mesh
4669 * @patch_num can range 0 to 1 less than the number returned by
4670 * cairo_mesh_pattern_get_patch_count().
4672 * Valid values for @point_num are from 0 to 3 and identify the
4673 * control points as explained in cairo_pattern_create_mesh().
4675 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
4676 * if @patch_num or @point_num is not valid for @pattern. If @pattern
4677 * is not a mesh pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
4683 cairo_mesh_pattern_get_control_point (cairo_pattern_t *pattern,
4684 unsigned int patch_num,
4685 unsigned int point_num,
4686 double *x, double *y)
4688 cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
4689 const cairo_mesh_patch_t *patch;
4690 unsigned int patch_count;
4693 if (pattern->status)
4694 return pattern->status;
4696 if (pattern->type != CAIRO_PATTERN_TYPE_MESH)
4697 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4700 return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4702 patch_count = _cairo_array_num_elements (&mesh->patches);
4703 if (mesh->current_patch)
4706 if (unlikely (patch_num >= patch_count))
4707 return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4709 patch = _cairo_array_index_const (&mesh->patches, patch_num);
4711 return _cairo_error (CAIRO_STATUS_NULL_POINTER);
4713 i = mesh_control_point_i[point_num];
4714 j = mesh_control_point_j[point_num];
4717 *x = patch->points[i][j].x;
4719 *y = patch->points[i][j].y;
4721 return CAIRO_STATUS_SUCCESS;
4723 slim_hidden_def (cairo_mesh_pattern_get_control_point);
4726 cairo_pattern_set_sigma (cairo_pattern_t *pattern,
4727 const double x_sigma,
4728 const double y_sigma)
4733 if (pattern->status)
4734 return pattern->status;
4736 if (pattern->filter != CAIRO_FILTER_GAUSSIAN)
4737 return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
4739 if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
4740 return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
4748 if (pattern->x_sigma == x &&
4749 pattern->y_sigma == y)
4750 return CAIRO_STATUS_SUCCESS;
4752 if (x > CAIRO_MAX_BLUR >> 1)
4753 x = CAIRO_MAX_BLUR >> 1;
4754 if (y > CAIRO_MAX_BLUR >> 1)
4755 y = CAIRO_MAX_BLUR >> 1;
4757 pattern->x_sigma = x;
4758 pattern->y_sigma = y;
4759 pattern->convolution_changed = TRUE;
4761 return CAIRO_STATUS_SUCCESS;
4765 cairo_pattern_get_sigma (cairo_pattern_t *pattern,
4769 if (pattern->status)
4770 return pattern->status;
4772 if (pattern->filter != CAIRO_FILTER_GAUSSIAN)
4773 return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
4775 if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
4776 return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
4778 *x_sigma = pattern->x_sigma;
4779 *y_sigma = pattern->y_sigma;
4780 return CAIRO_STATUS_SUCCESS;
4784 _cairo_pattern_create_gaussian_matrix (cairo_pattern_t *pattern,
4787 double x_sigma, y_sigma;
4788 unsigned int x_factor, y_factor;
4790 double x_sigma_sq, y_sigma_sq;
4797 cairo_rectangle_int_t extents;
4798 int width = CAIRO_MIN_SHRINK_SIZE;
4799 int height = CAIRO_MIN_SHRINK_SIZE;
4800 double min_line_width = (line_width >= 1.0) ? CAIRO_MIN_LINE_WIDTH : line_width;
4801 double max_sigma = CAIRO_MAX_SIGMA;
4802 double test_line_width = line_width;
4804 if (pattern->status)
4805 return pattern->status;
4807 if (pattern->filter != CAIRO_FILTER_GAUSSIAN)
4808 return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
4810 if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
4811 return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
4813 if (! pattern->convolution_changed)
4814 return CAIRO_STATUS_SUCCESS;
4816 if (_cairo_surface_get_extents (((cairo_surface_pattern_t *)pattern)->surface, &extents)) {
4817 width = extents.width;
4818 height = extents.height;
4823 x_sigma = pattern->x_sigma;
4824 y_sigma = pattern->y_sigma;
4827 if (x_sigma == 0.0 && y_sigma == 0.0) {
4828 if (pattern->convolution_matrix)
4829 free (pattern->convolution_matrix);
4830 pattern->convolution_matrix = NULL;
4832 return CAIRO_STATUS_SUCCESS;
4836 pattern->x_radius = 0;
4838 while (x_sigma >= max_sigma && test_line_width >= min_line_width) {
4839 if (width <= CAIRO_MIN_SHRINK_SIZE)
4845 test_line_width *= 0.5;
4847 if (x_sigma > max_sigma)
4848 x_sigma = max_sigma;
4849 /* XXX: skia uses 3, we follow css spec which is 2 */
4850 pattern->x_radius = ceil (x_sigma * 2);
4852 pattern->shrink_factor_x = x_factor;
4853 test_line_width = line_width;
4856 pattern->y_radius = 0;
4858 while (y_sigma >= max_sigma && test_line_width >= min_line_width) {
4859 if (height <= CAIRO_MIN_SHRINK_SIZE)
4865 test_line_width *= 0.5;
4867 if (y_sigma > max_sigma)
4868 y_sigma = max_sigma;
4869 pattern->y_radius = ceil (y_sigma * 2);
4871 pattern->shrink_factor_y = y_factor;
4873 if (pattern->convolution_matrix)
4874 free (pattern->convolution_matrix);
4876 pattern->convolution_matrix = NULL;
4879 * f(x, y) = exp (-((x-x0)^2/(2*x_sigma^2)+(y-y0)^2/(2*y_sigma*2)))
4881 row = pattern->y_radius;
4882 col = pattern->x_radius;
4883 n = (2 * row + 1) * (2 * col + 1);
4885 x_sigma_sq = 2 * x_sigma * x_sigma;
4886 y_sigma_sq = 2 * y_sigma * y_sigma;
4888 buffer = _cairo_malloc_ab (n, sizeof (double));
4890 return CAIRO_STATUS_NO_MEMORY;
4893 for (y = -row; y <= row; y++) {
4894 for (x = - col; x <= col; x++) {
4900 u1 = u / x_sigma_sq;
4905 v1 = v / y_sigma_sq;
4906 buffer[i] = exp (-(u1 + v1));
4914 for (i = 0; i < n; i++)
4917 pattern->convolution_matrix = buffer;
4918 pattern->convolution_changed = FALSE;
4919 return CAIRO_STATUS_SUCCESS;
4923 _cairo_pattern_reset_static_data (void)
4927 for (i = 0; i < ARRAY_LENGTH (freed_pattern_pool); i++)
4928 _freed_pool_reset (&freed_pattern_pool[i]);
4932 _cairo_debug_print_surface_pattern (FILE *file,
4933 const cairo_surface_pattern_t *pattern)
4935 printf (" surface type: %d\n", pattern->surface->type);
4939 _cairo_debug_print_raster_source_pattern (FILE *file,
4940 const cairo_raster_source_pattern_t *raster)
4942 printf (" content: %x, size %dx%d\n", raster->content, raster->extents.width, raster->extents.height);
4946 _cairo_debug_print_linear_pattern (FILE *file,
4947 const cairo_linear_pattern_t *pattern)
4952 _cairo_debug_print_radial_pattern (FILE *file,
4953 const cairo_radial_pattern_t *pattern)
4958 _cairo_debug_print_mesh_pattern (FILE *file,
4959 const cairo_mesh_pattern_t *pattern)
4964 _cairo_debug_print_pattern (FILE *file, const cairo_pattern_t *pattern)
4967 switch (pattern->type) {
4968 case CAIRO_PATTERN_TYPE_SOLID: s = "solid"; break;
4969 case CAIRO_PATTERN_TYPE_SURFACE: s = "surface"; break;
4970 case CAIRO_PATTERN_TYPE_LINEAR: s = "linear"; break;
4971 case CAIRO_PATTERN_TYPE_RADIAL: s = "radial"; break;
4972 case CAIRO_PATTERN_TYPE_MESH: s = "mesh"; break;
4973 case CAIRO_PATTERN_TYPE_RASTER_SOURCE: s = "raster"; break;
4974 default: s = "invalid"; ASSERT_NOT_REACHED; break;
4977 fprintf (file, "pattern: %s\n", s);
4978 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
4981 switch (pattern->extend) {
4982 case CAIRO_EXTEND_NONE: s = "none"; break;
4983 case CAIRO_EXTEND_REPEAT: s = "repeat"; break;
4984 case CAIRO_EXTEND_REFLECT: s = "reflect"; break;
4985 case CAIRO_EXTEND_PAD: s = "pad"; break;
4986 default: s = "invalid"; ASSERT_NOT_REACHED; break;
4988 fprintf (file, " extend: %s\n", s);
4990 switch (pattern->filter) {
4991 case CAIRO_FILTER_FAST: s = "fast"; break;
4992 case CAIRO_FILTER_GOOD: s = "good"; break;
4993 case CAIRO_FILTER_BEST: s = "best"; break;
4994 case CAIRO_FILTER_NEAREST: s = "nearest"; break;
4995 case CAIRO_FILTER_BILINEAR: s = "bilinear"; break;
4996 case CAIRO_FILTER_GAUSSIAN: s = "guassian"; break;
4997 default: s = "invalid"; ASSERT_NOT_REACHED; break;
4999 fprintf (file, " filter: %s\n", s);
5000 fprintf (file, " matrix: [%g %g %g %g %g %g]\n",
5001 pattern->matrix.xx, pattern->matrix.yx,
5002 pattern->matrix.xy, pattern->matrix.yy,
5003 pattern->matrix.x0, pattern->matrix.y0);
5004 switch (pattern->type) {
5006 case CAIRO_PATTERN_TYPE_SOLID:
5008 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
5009 _cairo_debug_print_raster_source_pattern (file, (cairo_raster_source_pattern_t *)pattern);
5011 case CAIRO_PATTERN_TYPE_SURFACE:
5012 _cairo_debug_print_surface_pattern (file, (cairo_surface_pattern_t *)pattern);
5014 case CAIRO_PATTERN_TYPE_LINEAR:
5015 _cairo_debug_print_linear_pattern (file, (cairo_linear_pattern_t *)pattern);
5017 case CAIRO_PATTERN_TYPE_RADIAL:
5018 _cairo_debug_print_radial_pattern (file, (cairo_radial_pattern_t *)pattern);
5020 case CAIRO_PATTERN_TYPE_MESH:
5021 _cairo_debug_print_mesh_pattern (file, (cairo_mesh_pattern_t *)pattern);
5026 static unsigned long
5027 _cairo_solid_pattern_alpha_hash (unsigned long hash,
5028 const cairo_solid_pattern_t *solid)
5030 return _cairo_hash_bytes (hash, &solid->color.alpha, sizeof (double));
5034 _cairo_pattern_hash_with_hash (unsigned long hash,
5035 const cairo_pattern_t *pattern,
5036 const cairo_bool_t use_color)
5038 if (pattern->status)
5041 hash = _cairo_hash_bytes (hash, &pattern->type, sizeof (pattern->type));
5042 if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
5043 hash = _cairo_hash_bytes (hash, &pattern->matrix, sizeof (double) * 4);
5044 hash = _cairo_hash_bytes (hash,
5045 &pattern->filter, sizeof (pattern->filter));
5046 hash = _cairo_hash_bytes (hash,
5047 &pattern->extend, sizeof (pattern->extend));
5048 hash = _cairo_hash_bytes (hash,
5049 &pattern->has_component_alpha,
5050 sizeof (pattern->has_component_alpha));
5053 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
5054 hash = _cairo_hash_bytes (hash, &pattern->x_sigma, sizeof (double) * 2);
5056 switch (pattern->type) {
5057 case CAIRO_PATTERN_TYPE_SOLID:
5059 return _cairo_solid_pattern_hash (hash, (cairo_solid_pattern_t *) pattern);
5061 return _cairo_solid_pattern_alpha_hash (hash, (cairo_solid_pattern_t *) pattern);
5062 case CAIRO_PATTERN_TYPE_LINEAR:
5063 return _cairo_linear_pattern_hash (hash, (cairo_linear_pattern_t *) pattern);
5064 case CAIRO_PATTERN_TYPE_RADIAL:
5065 return _cairo_radial_pattern_hash (hash, (cairo_radial_pattern_t *) pattern);
5066 case CAIRO_PATTERN_TYPE_MESH:
5067 return _cairo_mesh_pattern_hash (hash, (cairo_mesh_pattern_t *) pattern);
5068 case CAIRO_PATTERN_TYPE_SURFACE:
5069 return _cairo_surface_pattern_hash (hash, (cairo_surface_pattern_t *) pattern);
5070 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
5071 return _cairo_raster_source_pattern_hash (hash, (cairo_raster_source_pattern_t *) pattern);