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);
242 static cairo_status_t
243 _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
244 const cairo_gradient_pattern_t *other)
246 if (CAIRO_INJECT_FAULT ())
247 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
249 if (other->base.type == CAIRO_PATTERN_TYPE_LINEAR)
251 cairo_linear_pattern_t *dst = (cairo_linear_pattern_t *) pattern;
252 cairo_linear_pattern_t *src = (cairo_linear_pattern_t *) other;
258 cairo_radial_pattern_t *dst = (cairo_radial_pattern_t *) pattern;
259 cairo_radial_pattern_t *src = (cairo_radial_pattern_t *) other;
264 if (other->stops == other->stops_embedded)
265 pattern->stops = pattern->stops_embedded;
266 else if (other->stops)
268 pattern->stops = _cairo_malloc_ab (other->stops_size,
269 sizeof (cairo_gradient_stop_t));
270 if (unlikely (pattern->stops == NULL)) {
271 pattern->stops_size = 0;
272 pattern->n_stops = 0;
273 return _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
276 memcpy (pattern->stops, other->stops,
277 other->n_stops * sizeof (cairo_gradient_stop_t));
280 return CAIRO_STATUS_SUCCESS;
283 static cairo_status_t
284 _cairo_mesh_pattern_init_copy (cairo_mesh_pattern_t *pattern,
285 const cairo_mesh_pattern_t *other)
289 _cairo_array_init (&pattern->patches, sizeof (cairo_mesh_patch_t));
290 return _cairo_array_append_multiple (&pattern->patches,
291 _cairo_array_index_const (&other->patches, 0),
292 _cairo_array_num_elements (&other->patches));
296 _cairo_pattern_init_copy (cairo_pattern_t *pattern,
297 const cairo_pattern_t *other)
299 cairo_status_t status;
302 return _cairo_pattern_set_error (pattern, other->status);
304 switch (other->type) {
305 case CAIRO_PATTERN_TYPE_SOLID: {
306 cairo_solid_pattern_t *dst = (cairo_solid_pattern_t *) pattern;
307 cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) other;
309 VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t)));
313 case CAIRO_PATTERN_TYPE_SURFACE: {
314 cairo_surface_pattern_t *dst = (cairo_surface_pattern_t *) pattern;
315 cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) other;
317 VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t)));
320 cairo_surface_reference (dst->surface);
322 case CAIRO_PATTERN_TYPE_LINEAR:
323 case CAIRO_PATTERN_TYPE_RADIAL: {
324 cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern;
325 cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other;
327 if (other->type == CAIRO_PATTERN_TYPE_LINEAR) {
328 VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t)));
330 VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t)));
333 status = _cairo_gradient_pattern_init_copy (dst, src);
334 if (unlikely (status))
338 case CAIRO_PATTERN_TYPE_MESH: {
339 cairo_mesh_pattern_t *dst = (cairo_mesh_pattern_t *) pattern;
340 cairo_mesh_pattern_t *src = (cairo_mesh_pattern_t *) other;
342 VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t)));
344 status = _cairo_mesh_pattern_init_copy (dst, src);
345 if (unlikely (status))
350 case CAIRO_PATTERN_TYPE_RASTER_SOURCE: {
351 status = _cairo_raster_source_pattern_init_copy (pattern, other);
352 if (unlikely (status))
357 /* The reference count and user_data array are unique to the copy. */
358 CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
359 _cairo_user_data_array_init (&pattern->user_data);
361 return CAIRO_STATUS_SUCCESS;
365 _cairo_pattern_init_static_copy (cairo_pattern_t *pattern,
366 const cairo_pattern_t *other)
370 assert (other->status == CAIRO_STATUS_SUCCESS);
372 switch (other->type) {
375 case CAIRO_PATTERN_TYPE_SOLID:
376 size = sizeof (cairo_solid_pattern_t);
378 case CAIRO_PATTERN_TYPE_SURFACE:
379 size = sizeof (cairo_surface_pattern_t);
381 case CAIRO_PATTERN_TYPE_LINEAR:
382 size = sizeof (cairo_linear_pattern_t);
384 case CAIRO_PATTERN_TYPE_RADIAL:
385 size = sizeof (cairo_radial_pattern_t);
387 case CAIRO_PATTERN_TYPE_MESH:
388 size = sizeof (cairo_mesh_pattern_t);
390 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
391 size = sizeof (cairo_raster_source_pattern_t);
395 memcpy (pattern, other, size);
397 CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
398 _cairo_user_data_array_init (&pattern->user_data);
402 _cairo_pattern_init_snapshot (cairo_pattern_t *pattern,
403 const cairo_pattern_t *other)
405 cairo_status_t status;
407 /* We don't bother doing any fancy copy-on-write implementation
408 * for the pattern's data. It's generally quite tiny. */
409 status = _cairo_pattern_init_copy (pattern, other);
410 if (unlikely (status))
413 /* But we do let the surface snapshot stuff be as fancy as it
414 * would like to be. */
415 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
416 cairo_surface_pattern_t *surface_pattern =
417 (cairo_surface_pattern_t *) pattern;
418 cairo_surface_t *surface = surface_pattern->surface;
420 surface_pattern->surface = _cairo_surface_snapshot (surface);
422 cairo_surface_destroy (surface);
424 status = surface_pattern->surface->status;
425 } else if (pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
426 status = _cairo_raster_source_pattern_snapshot (pattern);
432 _cairo_pattern_fini (cairo_pattern_t *pattern)
434 _cairo_user_data_array_fini (&pattern->user_data);
436 switch (pattern->type) {
437 case CAIRO_PATTERN_TYPE_SOLID:
439 case CAIRO_PATTERN_TYPE_SURFACE: {
440 cairo_surface_pattern_t *surface_pattern =
441 (cairo_surface_pattern_t *) pattern;
443 cairo_surface_destroy (surface_pattern->surface);
445 case CAIRO_PATTERN_TYPE_LINEAR:
446 case CAIRO_PATTERN_TYPE_RADIAL: {
447 cairo_gradient_pattern_t *gradient =
448 (cairo_gradient_pattern_t *) pattern;
450 if (gradient->stops && gradient->stops != gradient->stops_embedded)
451 free (gradient->stops);
453 case CAIRO_PATTERN_TYPE_MESH: {
454 cairo_mesh_pattern_t *mesh =
455 (cairo_mesh_pattern_t *) pattern;
457 _cairo_array_fini (&mesh->patches);
459 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
460 _cairo_raster_source_pattern_finish (pattern);
465 switch (pattern->type) {
466 case CAIRO_PATTERN_TYPE_SOLID:
467 VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_solid_pattern_t));
469 case CAIRO_PATTERN_TYPE_SURFACE:
470 VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_surface_pattern_t));
472 case CAIRO_PATTERN_TYPE_LINEAR:
473 VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_linear_pattern_t));
475 case CAIRO_PATTERN_TYPE_RADIAL:
476 VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_radial_pattern_t));
478 case CAIRO_PATTERN_TYPE_MESH:
479 VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_mesh_pattern_t));
481 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
488 _cairo_pattern_create_copy (cairo_pattern_t **pattern_out,
489 const cairo_pattern_t *other)
491 cairo_pattern_t *pattern;
492 cairo_status_t status;
495 return other->status;
497 switch (other->type) {
498 case CAIRO_PATTERN_TYPE_SOLID:
499 pattern = malloc (sizeof (cairo_solid_pattern_t));
501 case CAIRO_PATTERN_TYPE_SURFACE:
502 pattern = malloc (sizeof (cairo_surface_pattern_t));
504 case CAIRO_PATTERN_TYPE_LINEAR:
505 pattern = malloc (sizeof (cairo_linear_pattern_t));
507 case CAIRO_PATTERN_TYPE_RADIAL:
508 pattern = malloc (sizeof (cairo_radial_pattern_t));
510 case CAIRO_PATTERN_TYPE_MESH:
511 pattern = malloc (sizeof (cairo_mesh_pattern_t));
513 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
514 pattern = malloc (sizeof (cairo_raster_source_pattern_t));
518 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
520 if (unlikely (pattern == NULL))
521 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
523 status = _cairo_pattern_init_copy (pattern, other);
524 if (unlikely (status)) {
529 CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
530 *pattern_out = pattern;
531 return CAIRO_STATUS_SUCCESS;
535 _cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
536 const cairo_color_t *color)
538 _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
539 pattern->color = *color;
543 _cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern,
544 cairo_surface_t *surface)
546 if (surface->status) {
547 /* Force to solid to simplify the pattern_fini process. */
548 _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
549 _cairo_pattern_set_error (&pattern->base, surface->status);
553 _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SURFACE);
555 pattern->surface = cairo_surface_reference (surface);
559 _cairo_pattern_init_gradient (cairo_gradient_pattern_t *pattern,
560 cairo_pattern_type_t type)
562 _cairo_pattern_init (&pattern->base, type);
564 pattern->n_stops = 0;
565 pattern->stops_size = 0;
566 pattern->stops = NULL;
570 _cairo_pattern_init_linear (cairo_linear_pattern_t *pattern,
571 double x0, double y0, double x1, double y1)
573 _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_LINEAR);
582 _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
583 double cx0, double cy0, double radius0,
584 double cx1, double cy1, double radius1)
586 _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL);
588 pattern->cd1.center.x = cx0;
589 pattern->cd1.center.y = cy0;
590 pattern->cd1.radius = fabs (radius0);
591 pattern->cd2.center.x = cx1;
592 pattern->cd2.center.y = cy1;
593 pattern->cd2.radius = fabs (radius1);
597 _cairo_pattern_create_solid (const cairo_color_t *color)
599 cairo_solid_pattern_t *pattern;
602 _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SOLID]);
603 if (unlikely (pattern == NULL)) {
604 /* None cached, need to create a new pattern. */
605 pattern = malloc (sizeof (cairo_solid_pattern_t));
606 if (unlikely (pattern == NULL)) {
607 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
608 return (cairo_pattern_t *) &_cairo_pattern_nil;
612 _cairo_pattern_init_solid (pattern, color);
613 CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
615 return &pattern->base;
619 _cairo_pattern_create_in_error (cairo_status_t status)
621 cairo_pattern_t *pattern;
623 if (status == CAIRO_STATUS_NO_MEMORY)
624 return (cairo_pattern_t *)&_cairo_pattern_nil.base;
626 CAIRO_MUTEX_INITIALIZE ();
628 pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
629 if (pattern->status == CAIRO_STATUS_SUCCESS)
630 status = _cairo_pattern_set_error (pattern, status);
636 * cairo_pattern_create_rgb:
637 * @red: red component of the color
638 * @green: green component of the color
639 * @blue: blue component of the color
641 * Creates a new #cairo_pattern_t corresponding to an opaque color. The
642 * color components are floating point numbers in the range 0 to 1.
643 * If the values passed in are outside that range, they will be
646 * Return value: the newly created #cairo_pattern_t if successful, or
647 * an error pattern in case of no memory. The caller owns the
648 * returned object and should call cairo_pattern_destroy() when
651 * This function will always return a valid pointer, but if an error
652 * occurred the pattern status will be set to an error. To inspect
653 * the status of a pattern use cairo_pattern_status().
658 cairo_pattern_create_rgb (double red, double green, double blue)
660 return cairo_pattern_create_rgba (red, green, blue, 1.0);
662 slim_hidden_def (cairo_pattern_create_rgb);
665 * cairo_pattern_create_rgba:
666 * @red: red component of the color
667 * @green: green component of the color
668 * @blue: blue component of the color
669 * @alpha: alpha component of the color
671 * Creates a new #cairo_pattern_t corresponding to a translucent color.
672 * The color components are floating point numbers in the range 0 to
673 * 1. 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_rgba (double red, double green, double blue,
693 red = _cairo_restrict_value (red, 0.0, 1.0);
694 green = _cairo_restrict_value (green, 0.0, 1.0);
695 blue = _cairo_restrict_value (blue, 0.0, 1.0);
696 alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
698 _cairo_color_init_rgba (&color, red, green, blue, alpha);
700 CAIRO_MUTEX_INITIALIZE ();
702 return _cairo_pattern_create_solid (&color);
704 slim_hidden_def (cairo_pattern_create_rgba);
707 * cairo_pattern_create_for_surface:
708 * @surface: the surface
710 * Create a new #cairo_pattern_t for the given surface.
712 * Return value: the newly created #cairo_pattern_t if successful, or
713 * an error pattern in case of no memory. The caller owns the
714 * returned object and should call cairo_pattern_destroy() when
717 * This function will always return a valid pointer, but if an error
718 * occurred the pattern status will be set to an error. To inspect
719 * the status of a pattern use cairo_pattern_status().
724 cairo_pattern_create_for_surface (cairo_surface_t *surface)
726 cairo_surface_pattern_t *pattern;
728 if (surface == NULL) {
729 _cairo_error_throw (CAIRO_STATUS_NULL_POINTER);
730 return (cairo_pattern_t*) &_cairo_pattern_nil_null_pointer;
734 return _cairo_pattern_create_in_error (surface->status);
737 _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SURFACE]);
738 if (unlikely (pattern == NULL)) {
739 pattern = malloc (sizeof (cairo_surface_pattern_t));
740 if (unlikely (pattern == NULL)) {
741 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
742 return (cairo_pattern_t *)&_cairo_pattern_nil.base;
746 CAIRO_MUTEX_INITIALIZE ();
748 _cairo_pattern_init_for_surface (pattern, surface);
749 CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
751 return &pattern->base;
753 slim_hidden_def (cairo_pattern_create_for_surface);
756 * cairo_pattern_create_linear:
757 * @x0: x coordinate of the start point
758 * @y0: y coordinate of the start point
759 * @x1: x coordinate of the end point
760 * @y1: y coordinate of the end point
762 * Create a new linear gradient #cairo_pattern_t along the line defined
763 * by (x0, y0) and (x1, y1). Before using the gradient pattern, a
764 * number of color stops should be defined using
765 * cairo_pattern_add_color_stop_rgb() or
766 * cairo_pattern_add_color_stop_rgba().
768 * Note: The coordinates here are in pattern space. For a new pattern,
769 * pattern space is identical to user space, but the relationship
770 * between the spaces can be changed with cairo_pattern_set_matrix().
772 * Return value: the newly created #cairo_pattern_t if successful, or
773 * an error pattern in case of no memory. The caller owns the
774 * returned object and should call cairo_pattern_destroy() when
777 * This function will always return a valid pointer, but if an error
778 * occurred the pattern status will be set to an error. To inspect
779 * the status of a pattern use cairo_pattern_status().
784 cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
786 cairo_linear_pattern_t *pattern;
789 _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_LINEAR]);
790 if (unlikely (pattern == NULL)) {
791 pattern = malloc (sizeof (cairo_linear_pattern_t));
792 if (unlikely (pattern == NULL)) {
793 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
794 return (cairo_pattern_t *) &_cairo_pattern_nil.base;
798 CAIRO_MUTEX_INITIALIZE ();
800 _cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
801 CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
803 return &pattern->base.base;
807 * cairo_pattern_create_radial:
808 * @cx0: x coordinate for the center of the start circle
809 * @cy0: y coordinate for the center of the start circle
810 * @radius0: radius of the start circle
811 * @cx1: x coordinate for the center of the end circle
812 * @cy1: y coordinate for the center of the end circle
813 * @radius1: radius of the end circle
815 * Creates a new radial gradient #cairo_pattern_t between the two
816 * circles defined by (cx0, cy0, radius0) and (cx1, cy1, radius1). Before using the
817 * gradient pattern, a number of color stops should be defined using
818 * cairo_pattern_add_color_stop_rgb() or
819 * cairo_pattern_add_color_stop_rgba().
821 * Note: The coordinates here are in pattern space. For a new pattern,
822 * pattern space is identical to user space, but the relationship
823 * between the spaces can be changed with cairo_pattern_set_matrix().
825 * Return value: the newly created #cairo_pattern_t if successful, or
826 * an error pattern in case of no memory. The caller owns the
827 * returned object and should call cairo_pattern_destroy() when
830 * This function will always return a valid pointer, but if an error
831 * occurred the pattern status will be set to an error. To inspect
832 * the status of a pattern use cairo_pattern_status().
837 cairo_pattern_create_radial (double cx0, double cy0, double radius0,
838 double cx1, double cy1, double radius1)
840 cairo_radial_pattern_t *pattern;
843 _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_RADIAL]);
844 if (unlikely (pattern == NULL)) {
845 pattern = malloc (sizeof (cairo_radial_pattern_t));
846 if (unlikely (pattern == NULL)) {
847 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
848 return (cairo_pattern_t *) &_cairo_pattern_nil.base;
852 CAIRO_MUTEX_INITIALIZE ();
854 _cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
855 CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
857 return &pattern->base.base;
860 /* This order is specified in the diagram in the documentation for
861 * cairo_pattern_create_mesh() */
862 static const int mesh_path_point_i[12] = { 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1 };
863 static const int mesh_path_point_j[12] = { 0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0 };
864 static const int mesh_control_point_i[4] = { 1, 1, 2, 2 };
865 static const int mesh_control_point_j[4] = { 1, 2, 2, 1 };
868 * cairo_pattern_create_mesh:
870 * Create a new mesh pattern.
872 * Mesh patterns are tensor-product patch meshes (type 7 shadings in
873 * PDF). Mesh patterns may also be used to create other types of
874 * shadings that are special cases of tensor-product patch meshes such
875 * as Coons patch meshes (type 6 shading in PDF) and Gouraud-shaded
876 * triangle meshes (type 4 and 5 shadings in PDF).
878 * Mesh patterns consist of one or more tensor-product patches, which
879 * should be defined before using the mesh pattern. Using a mesh
880 * pattern with a partially defined patch as source or mask will put
881 * the context in an error status with a status of
882 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
884 * A tensor-product patch is defined by 4 Bézier curves (side 0, 1, 2,
885 * 3) and by 4 additional control points (P0, P1, P2, P3) that provide
886 * further control over the patch and complete the definition of the
887 * tensor-product patch. The corner C0 is the first point of the
890 * Degenerate sides are permitted so straight lines may be used. A
891 * zero length line on one side may be used to create 3 sided patches.
893 * <informalexample><screen>
906 * </screen></informalexample>
908 * Each patch is constructed by first calling
909 * cairo_mesh_pattern_begin_patch(), then cairo_mesh_pattern_move_to()
910 * to specify the first point in the patch (C0). Then the sides are
911 * specified with calls to cairo_mesh_pattern_curve_to() and
912 * cairo_mesh_pattern_line_to().
914 * The four additional control points (P0, P1, P2, P3) in a patch can
915 * be specified with cairo_mesh_pattern_set_control_point().
917 * At each corner of the patch (C0, C1, C2, C3) a color may be
918 * specified with cairo_mesh_pattern_set_corner_color_rgb() or
919 * cairo_mesh_pattern_set_corner_color_rgba(). Any corner whose color
920 * is not explicitly specified defaults to transparent black.
922 * A Coons patch is a special case of the tensor-product patch where
923 * the control points are implicitly defined by the sides of the
924 * patch. The default value for any control point not specified is the
925 * implicit value for a Coons patch, i.e. if no control points are
926 * specified the patch is a Coons patch.
928 * A triangle is a special case of the tensor-product patch where the
929 * control points are implicitly defined by the sides of the patch,
930 * all the sides are lines and one of them has length 0, i.e. if the
931 * patch is specified using just 3 lines, it is a triangle. If the
932 * corners connected by the 0-length side have the same color, the
933 * patch is a Gouraud-shaded triangle.
935 * Patches may be oriented differently to the above diagram. For
936 * example the first point could be at the top left. The diagram only
937 * shows the relationship between the sides, corners and control
938 * points. Regardless of where the first point is located, when
939 * specifying colors, corner 0 will always be the first point, corner
940 * 1 the point between side 0 and side 1 etc.
942 * Calling cairo_mesh_pattern_end_patch() completes the current
943 * patch. If less than 4 sides have been defined, the first missing
944 * side is defined as a line from the current point to the first point
945 * of the patch (C0) and the other sides are degenerate lines from C0
946 * to C0. The corners between the added sides will all be coincident
947 * with C0 of the patch and their color will be set to be the same as
950 * Additional patches may be added with additional calls to
951 * cairo_mesh_pattern_begin_patch()/cairo_mesh_pattern_end_patch().
953 * <informalexample><programlisting>
954 * cairo_pattern_t *pattern = cairo_pattern_create_mesh ();
956 * /* Add a Coons patch */
957 * cairo_mesh_pattern_begin_patch (pattern);
958 * cairo_mesh_pattern_move_to (pattern, 0, 0);
959 * cairo_mesh_pattern_curve_to (pattern, 30, -30, 60, 30, 100, 0);
960 * cairo_mesh_pattern_curve_to (pattern, 60, 30, 130, 60, 100, 100);
961 * cairo_mesh_pattern_curve_to (pattern, 60, 70, 30, 130, 0, 100);
962 * cairo_mesh_pattern_curve_to (pattern, 30, 70, -30, 30, 0, 0);
963 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 0, 1, 0, 0);
964 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 1, 0, 1, 0);
965 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 2, 0, 0, 1);
966 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 3, 1, 1, 0);
967 * cairo_mesh_pattern_end_patch (pattern);
969 * /* Add a Gouraud-shaded triangle */
970 * cairo_mesh_pattern_begin_patch (pattern)
971 * cairo_mesh_pattern_move_to (pattern, 100, 100);
972 * cairo_mesh_pattern_line_to (pattern, 130, 130);
973 * cairo_mesh_pattern_line_to (pattern, 130, 70);
974 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 0, 1, 0, 0);
975 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 1, 0, 1, 0);
976 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 2, 0, 0, 1);
977 * cairo_mesh_pattern_end_patch (pattern)
978 * </programlisting></informalexample>
980 * When two patches overlap, the last one that has been added is drawn
981 * over the first one.
983 * When a patch folds over itself, points are sorted depending on
984 * their parameter coordinates inside the patch. The v coordinate
985 * ranges from 0 to 1 when moving from side 3 to side 1; the u
986 * coordinate ranges from 0 to 1 when going from side 0 to side
987 * 2. Points with higher v coordinate hide points with lower v
988 * coordinate. When two points have the same v coordinate, the one
989 * with higher u coordinate is above. This means that points nearer to
990 * side 1 are above points nearer to side 3; when this is not
991 * sufficient to decide which point is above (for example when both
992 * points belong to side 1 or side 3) points nearer to side 2 are
993 * above points nearer to side 0.
995 * For a complete definition of tensor-product patches, see the PDF
996 * specification (ISO32000), which describes the parametrization in
999 * Note: The coordinates are always in pattern space. For a new
1000 * pattern, pattern space is identical to user space, but the
1001 * relationship between the spaces can be changed with
1002 * cairo_pattern_set_matrix().
1004 * Return value: the newly created #cairo_pattern_t if successful, or
1005 * an error pattern in case of no memory. The caller owns the returned
1006 * object and should call cairo_pattern_destroy() when finished with
1009 * This function will always return a valid pointer, but if an error
1010 * occurred the pattern status will be set to an error. To inspect the
1011 * status of a pattern use cairo_pattern_status().
1016 cairo_pattern_create_mesh (void)
1018 cairo_mesh_pattern_t *pattern;
1021 _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_MESH]);
1022 if (unlikely (pattern == NULL)) {
1023 pattern = malloc (sizeof (cairo_mesh_pattern_t));
1024 if (unlikely (pattern == NULL)) {
1025 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1026 return (cairo_pattern_t *) &_cairo_pattern_nil.base;
1030 CAIRO_MUTEX_INITIALIZE ();
1032 _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_MESH);
1033 _cairo_array_init (&pattern->patches, sizeof (cairo_mesh_patch_t));
1034 pattern->current_patch = NULL;
1035 CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
1037 return &pattern->base;
1041 * cairo_pattern_reference:
1042 * @pattern: a #cairo_pattern_t
1044 * Increases the reference count on @pattern by one. This prevents
1045 * @pattern from being destroyed until a matching call to
1046 * cairo_pattern_destroy() is made.
1048 * The number of references to a #cairo_pattern_t can be get using
1049 * cairo_pattern_get_reference_count().
1051 * Return value: the referenced #cairo_pattern_t.
1056 cairo_pattern_reference (cairo_pattern_t *pattern)
1058 if (pattern == NULL ||
1059 CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1062 assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
1064 _cairo_reference_count_inc (&pattern->ref_count);
1068 slim_hidden_def (cairo_pattern_reference);
1071 * cairo_pattern_get_type:
1072 * @pattern: a #cairo_pattern_t
1074 * This function returns the type a pattern.
1075 * See #cairo_pattern_type_t for available types.
1077 * Return value: The type of @pattern.
1081 cairo_pattern_type_t
1082 cairo_pattern_get_type (cairo_pattern_t *pattern)
1084 return pattern->type;
1088 * cairo_pattern_status:
1089 * @pattern: a #cairo_pattern_t
1091 * Checks whether an error has previously occurred for this
1094 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NO_MEMORY,
1095 * %CAIRO_STATUS_INVALID_MATRIX, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH,
1096 * or %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1101 cairo_pattern_status (cairo_pattern_t *pattern)
1103 return pattern->status;
1107 * cairo_pattern_destroy:
1108 * @pattern: a #cairo_pattern_t
1110 * Decreases the reference count on @pattern by one. If the result is
1111 * zero, then @pattern and all associated resources are freed. See
1112 * cairo_pattern_reference().
1117 cairo_pattern_destroy (cairo_pattern_t *pattern)
1119 cairo_pattern_type_t type;
1121 if (pattern == NULL ||
1122 CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1125 assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
1127 if (! _cairo_reference_count_dec_and_test (&pattern->ref_count))
1130 type = pattern->type;
1131 _cairo_pattern_fini (pattern);
1133 /* maintain a small cache of freed patterns */
1134 if (type < ARRAY_LENGTH (freed_pattern_pool))
1135 _freed_pool_put (&freed_pattern_pool[type], pattern);
1139 slim_hidden_def (cairo_pattern_destroy);
1142 * cairo_pattern_get_reference_count:
1143 * @pattern: a #cairo_pattern_t
1145 * Returns the current reference count of @pattern.
1147 * Return value: the current reference count of @pattern. If the
1148 * object is a nil object, 0 will be returned.
1153 cairo_pattern_get_reference_count (cairo_pattern_t *pattern)
1155 if (pattern == NULL ||
1156 CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1159 return CAIRO_REFERENCE_COUNT_GET_VALUE (&pattern->ref_count);
1163 * cairo_pattern_get_user_data:
1164 * @pattern: a #cairo_pattern_t
1165 * @key: the address of the #cairo_user_data_key_t the user data was
1168 * Return user data previously attached to @pattern using the
1169 * specified key. If no user data has been attached with the given
1170 * key this function returns %NULL.
1172 * Return value: the user data previously attached or %NULL.
1177 cairo_pattern_get_user_data (cairo_pattern_t *pattern,
1178 const cairo_user_data_key_t *key)
1180 return _cairo_user_data_array_get_data (&pattern->user_data,
1185 * cairo_pattern_set_user_data:
1186 * @pattern: a #cairo_pattern_t
1187 * @key: the address of a #cairo_user_data_key_t to attach the user data to
1188 * @user_data: the user data to attach to the #cairo_pattern_t
1189 * @destroy: a #cairo_destroy_func_t which will be called when the
1190 * #cairo_t is destroyed or when new user data is attached using the
1193 * Attach user data to @pattern. To remove user data from a surface,
1194 * call this function with the key that was used to set it and %NULL
1197 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
1198 * slot could not be allocated for the user data.
1203 cairo_pattern_set_user_data (cairo_pattern_t *pattern,
1204 const cairo_user_data_key_t *key,
1206 cairo_destroy_func_t destroy)
1208 if (CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1209 return pattern->status;
1211 return _cairo_user_data_array_set_data (&pattern->user_data,
1212 key, user_data, destroy);
1216 * cairo_mesh_pattern_begin_patch:
1217 * @pattern: a #cairo_pattern_t
1219 * Begin a patch in a mesh pattern.
1221 * After calling this function, the patch shape should be defined with
1222 * cairo_mesh_pattern_move_to(), cairo_mesh_pattern_line_to() and
1223 * cairo_mesh_pattern_curve_to().
1225 * After defining the patch, cairo_mesh_pattern_end_patch() must be
1226 * called before using @pattern as a source or mask.
1228 * Note: If @pattern is not a mesh pattern then @pattern will be put
1229 * into an error status with a status of
1230 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern already has a
1231 * current patch, it will be put into an error status with a status of
1232 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1237 cairo_mesh_pattern_begin_patch (cairo_pattern_t *pattern)
1239 cairo_mesh_pattern_t *mesh;
1240 cairo_status_t status;
1241 cairo_mesh_patch_t *current_patch;
1244 if (unlikely (pattern->status))
1247 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1248 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1252 mesh = (cairo_mesh_pattern_t *) pattern;
1253 if (unlikely (mesh->current_patch)) {
1254 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1258 status = _cairo_array_allocate (&mesh->patches, 1, (void **) ¤t_patch);
1259 if (unlikely (status)) {
1260 _cairo_pattern_set_error (pattern, status);
1264 mesh->current_patch = current_patch;
1265 mesh->current_side = -2; /* no current point */
1267 for (i = 0; i < 4; i++)
1268 mesh->has_control_point[i] = FALSE;
1270 for (i = 0; i < 4; i++)
1271 mesh->has_color[i] = FALSE;
1276 _calc_control_point (cairo_mesh_patch_t *patch, int control_point)
1278 /* The Coons patch is a special case of the Tensor Product patch
1279 * where the four control points are:
1286 * where S is the gradient surface.
1288 * When one or more control points has not been specified
1289 * calculated the Coons patch control points are substituted. If
1290 * no control points are specified the gradient will be a Coons
1293 * The equations below are defined in the ISO32000 standard.
1295 cairo_point_double_t *p[3][3];
1296 int cp_i, cp_j, i, j;
1298 cp_i = mesh_control_point_i[control_point];
1299 cp_j = mesh_control_point_j[control_point];
1301 for (i = 0; i < 3; i++)
1302 for (j = 0; j < 3; j++)
1303 p[i][j] = &patch->points[cp_i ^ i][cp_j ^ j];
1305 p[0][0]->x = (- 4 * p[1][1]->x
1306 + 6 * (p[1][0]->x + p[0][1]->x)
1307 - 2 * (p[1][2]->x + p[2][1]->x)
1308 + 3 * (p[2][0]->x + p[0][2]->x)
1309 - 1 * p[2][2]->x) * (1. / 9);
1311 p[0][0]->y = (- 4 * p[1][1]->y
1312 + 6 * (p[1][0]->y + p[0][1]->y)
1313 - 2 * (p[1][2]->y + p[2][1]->y)
1314 + 3 * (p[2][0]->y + p[0][2]->y)
1315 - 1 * p[2][2]->y) * (1. / 9);
1319 * cairo_mesh_pattern_end_patch:
1320 * @pattern: a #cairo_pattern_t
1322 * Indicates the end of the current patch in a mesh pattern.
1324 * If the current patch has less than 4 sides, it is closed with a
1325 * straight line from the current point to the first point of the
1326 * patch as if cairo_mesh_pattern_line_to() was used.
1328 * Note: If @pattern is not a mesh pattern then @pattern will be put
1329 * into an error status with a status of
1330 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
1331 * patch or the current patch has no current point, @pattern will be
1332 * put into an error status with a status of
1333 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1338 cairo_mesh_pattern_end_patch (cairo_pattern_t *pattern)
1340 cairo_mesh_pattern_t *mesh;
1341 cairo_mesh_patch_t *current_patch;
1344 if (unlikely (pattern->status))
1347 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1348 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1352 mesh = (cairo_mesh_pattern_t *) pattern;
1353 current_patch = mesh->current_patch;
1354 if (unlikely (!current_patch)) {
1355 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1359 if (unlikely (mesh->current_side == -2)) {
1360 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1364 while (mesh->current_side < 3) {
1367 cairo_mesh_pattern_line_to (pattern,
1368 current_patch->points[0][0].x,
1369 current_patch->points[0][0].y);
1371 corner_num = mesh->current_side + 1;
1372 if (corner_num < 4 && ! mesh->has_color[corner_num]) {
1373 current_patch->colors[corner_num] = current_patch->colors[0];
1374 mesh->has_color[corner_num] = TRUE;
1378 for (i = 0; i < 4; i++) {
1379 if (! mesh->has_control_point[i])
1380 _calc_control_point (current_patch, i);
1383 for (i = 0; i < 4; i++) {
1384 if (! mesh->has_color[i])
1385 current_patch->colors[i] = *CAIRO_COLOR_TRANSPARENT;
1388 mesh->current_patch = NULL;
1392 * cairo_mesh_pattern_curve_to:
1393 * @pattern: a #cairo_pattern_t
1394 * @x1: the X coordinate of the first control point
1395 * @y1: the Y coordinate of the first control point
1396 * @x2: the X coordinate of the second control point
1397 * @y2: the Y coordinate of the second control point
1398 * @x3: the X coordinate of the end of the curve
1399 * @y3: the Y coordinate of the end of the curve
1401 * Adds a cubic Bézier spline to the current patch from the current
1402 * point to position (@x3, @y3) in pattern-space coordinates, using
1403 * (@x1, @y1) and (@x2, @y2) as the control points.
1405 * If the current patch has no current point before the call to
1406 * cairo_mesh_pattern_curve_to(), this function will behave as if
1407 * preceded by a call to cairo_mesh_pattern_move_to(@pattern, @x1,
1410 * After this call the current point will be (@x3, @y3).
1412 * Note: If @pattern is not a mesh pattern then @pattern will be put
1413 * into an error status with a status of
1414 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
1415 * patch or the current patch already has 4 sides, @pattern will be
1416 * put into an error status with a status of
1417 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1422 cairo_mesh_pattern_curve_to (cairo_pattern_t *pattern,
1423 double x1, double y1,
1424 double x2, double y2,
1425 double x3, double y3)
1427 cairo_mesh_pattern_t *mesh;
1428 int current_point, i, j;
1430 if (unlikely (pattern->status))
1433 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1434 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1438 mesh = (cairo_mesh_pattern_t *) pattern;
1439 if (unlikely (!mesh->current_patch)) {
1440 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1444 if (unlikely (mesh->current_side == 3)) {
1445 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1449 if (mesh->current_side == -2)
1450 cairo_mesh_pattern_move_to (pattern, x1, y1);
1452 assert (mesh->current_side >= -1);
1453 assert (pattern->status == CAIRO_STATUS_SUCCESS);
1455 mesh->current_side++;
1457 current_point = 3 * mesh->current_side;
1460 i = mesh_path_point_i[current_point];
1461 j = mesh_path_point_j[current_point];
1462 mesh->current_patch->points[i][j].x = x1;
1463 mesh->current_patch->points[i][j].y = y1;
1466 i = mesh_path_point_i[current_point];
1467 j = mesh_path_point_j[current_point];
1468 mesh->current_patch->points[i][j].x = x2;
1469 mesh->current_patch->points[i][j].y = y2;
1472 if (current_point < 12) {
1473 i = mesh_path_point_i[current_point];
1474 j = mesh_path_point_j[current_point];
1475 mesh->current_patch->points[i][j].x = x3;
1476 mesh->current_patch->points[i][j].y = y3;
1479 slim_hidden_def (cairo_mesh_pattern_curve_to);
1482 * cairo_mesh_pattern_line_to:
1483 * @pattern: a #cairo_pattern_t
1484 * @x: the X coordinate of the end of the new line
1485 * @y: the Y coordinate of the end of the new line
1487 * Adds a line to the current patch from the current point to position
1488 * (@x, @y) in pattern-space coordinates.
1490 * If there is no current point before the call to
1491 * cairo_mesh_pattern_line_to() this function will behave as
1492 * cairo_mesh_pattern_move_to(@pattern, @x, @y).
1494 * After this call the current point will be (@x, @y).
1496 * Note: If @pattern is not a mesh pattern then @pattern will be put
1497 * into an error status with a status of
1498 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
1499 * patch or the current patch already has 4 sides, @pattern will be
1500 * put into an error status with a status of
1501 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1506 cairo_mesh_pattern_line_to (cairo_pattern_t *pattern,
1509 cairo_mesh_pattern_t *mesh;
1510 cairo_point_double_t last_point;
1511 int last_point_idx, i, j;
1513 if (unlikely (pattern->status))
1516 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1517 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1521 mesh = (cairo_mesh_pattern_t *) pattern;
1522 if (unlikely (!mesh->current_patch)) {
1523 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1527 if (unlikely (mesh->current_side == 3)) {
1528 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1532 if (mesh->current_side == -2) {
1533 cairo_mesh_pattern_move_to (pattern, x, y);
1537 last_point_idx = 3 * (mesh->current_side + 1);
1538 i = mesh_path_point_i[last_point_idx];
1539 j = mesh_path_point_j[last_point_idx];
1541 last_point = mesh->current_patch->points[i][j];
1543 cairo_mesh_pattern_curve_to (pattern,
1544 (2 * last_point.x + x) * (1. / 3),
1545 (2 * last_point.y + y) * (1. / 3),
1546 (last_point.x + 2 * x) * (1. / 3),
1547 (last_point.y + 2 * y) * (1. / 3),
1550 slim_hidden_def (cairo_mesh_pattern_line_to);
1553 * cairo_mesh_pattern_move_to:
1554 * @pattern: a #cairo_pattern_t
1555 * @x: the X coordinate of the new position
1556 * @y: the Y coordinate of the new position
1558 * Define the first point of the current patch in a mesh pattern.
1560 * After this call the current point will be (@x, @y).
1562 * Note: If @pattern is not a mesh pattern then @pattern will be put
1563 * into an error status with a status of
1564 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
1565 * patch or the current patch already has at least one side, @pattern
1566 * will be put into an error status with a status of
1567 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1572 cairo_mesh_pattern_move_to (cairo_pattern_t *pattern,
1575 cairo_mesh_pattern_t *mesh;
1577 if (unlikely (pattern->status))
1580 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1581 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1585 mesh = (cairo_mesh_pattern_t *) pattern;
1586 if (unlikely (!mesh->current_patch)) {
1587 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1591 if (unlikely (mesh->current_side >= 0)) {
1592 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1596 mesh->current_side = -1;
1597 mesh->current_patch->points[0][0].x = x;
1598 mesh->current_patch->points[0][0].y = y;
1600 slim_hidden_def (cairo_mesh_pattern_move_to);
1603 * cairo_mesh_pattern_set_control_point:
1604 * @pattern: a #cairo_pattern_t
1605 * @point_num: the control point to set the position for
1606 * @x: the X coordinate of the control point
1607 * @y: the Y coordinate of the control point
1609 * Set an internal control point of the current patch.
1611 * Valid values for @point_num are from 0 to 3 and identify the
1612 * control points as explained in cairo_pattern_create_mesh().
1614 * Note: If @pattern is not a mesh pattern then @pattern will be put
1615 * into an error status with a status of
1616 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @point_num is not valid,
1617 * @pattern will be put into an error status with a status of
1618 * %CAIRO_STATUS_INVALID_INDEX. If @pattern has no current patch,
1619 * @pattern will be put into an error status with a status of
1620 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1625 cairo_mesh_pattern_set_control_point (cairo_pattern_t *pattern,
1626 unsigned int point_num,
1630 cairo_mesh_pattern_t *mesh;
1633 if (unlikely (pattern->status))
1636 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1637 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1641 if (unlikely (point_num > 3)) {
1642 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_INDEX);
1646 mesh = (cairo_mesh_pattern_t *) pattern;
1647 if (unlikely (!mesh->current_patch)) {
1648 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1652 i = mesh_control_point_i[point_num];
1653 j = mesh_control_point_j[point_num];
1655 mesh->current_patch->points[i][j].x = x;
1656 mesh->current_patch->points[i][j].y = y;
1657 mesh->has_control_point[point_num] = TRUE;
1660 /* make room for at least one more color stop */
1661 static cairo_status_t
1662 _cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
1664 cairo_gradient_stop_t *new_stops;
1665 int old_size = pattern->stops_size;
1666 int embedded_size = ARRAY_LENGTH (pattern->stops_embedded);
1667 int new_size = 2 * MAX (old_size, 4);
1669 /* we have a local buffer at pattern->stops_embedded. try to fulfill the request
1671 if (old_size < embedded_size) {
1672 pattern->stops = pattern->stops_embedded;
1673 pattern->stops_size = embedded_size;
1674 return CAIRO_STATUS_SUCCESS;
1677 if (CAIRO_INJECT_FAULT ())
1678 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1680 assert (pattern->n_stops <= pattern->stops_size);
1682 if (pattern->stops == pattern->stops_embedded) {
1683 new_stops = _cairo_malloc_ab (new_size, sizeof (cairo_gradient_stop_t));
1685 memcpy (new_stops, pattern->stops, old_size * sizeof (cairo_gradient_stop_t));
1687 new_stops = _cairo_realloc_ab (pattern->stops,
1689 sizeof (cairo_gradient_stop_t));
1692 if (unlikely (new_stops == NULL))
1693 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1695 pattern->stops = new_stops;
1696 pattern->stops_size = new_size;
1698 return CAIRO_STATUS_SUCCESS;
1702 _cairo_mesh_pattern_set_corner_color (cairo_mesh_pattern_t *mesh,
1703 unsigned int corner_num,
1704 double red, double green, double blue,
1707 cairo_color_t *color;
1709 assert (mesh->current_patch);
1710 assert (corner_num <= 3);
1712 color = &mesh->current_patch->colors[corner_num];
1714 color->green = green;
1716 color->alpha = alpha;
1718 color->red_short = _cairo_color_double_to_short (red);
1719 color->green_short = _cairo_color_double_to_short (green);
1720 color->blue_short = _cairo_color_double_to_short (blue);
1721 color->alpha_short = _cairo_color_double_to_short (alpha);
1723 mesh->has_color[corner_num] = TRUE;
1727 * cairo_mesh_pattern_set_corner_color_rgb:
1728 * @pattern: a #cairo_pattern_t
1729 * @corner_num: the corner to set the color for
1730 * @red: red component of color
1731 * @green: green component of color
1732 * @blue: blue component of color
1734 * Sets the color of a corner of the current patch in a mesh pattern.
1736 * The color is specified in the same way as in cairo_set_source_rgb().
1738 * Valid values for @corner_num are from 0 to 3 and identify the
1739 * corners as explained in cairo_pattern_create_mesh().
1741 * Note: If @pattern is not a mesh pattern then @pattern will be put
1742 * into an error status with a status of
1743 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @corner_num is not valid,
1744 * @pattern will be put into an error status with a status of
1745 * %CAIRO_STATUS_INVALID_INDEX. If @pattern has no current patch,
1746 * @pattern will be put into an error status with a status of
1747 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1752 cairo_mesh_pattern_set_corner_color_rgb (cairo_pattern_t *pattern,
1753 unsigned int corner_num,
1754 double red, double green, double blue)
1756 cairo_mesh_pattern_set_corner_color_rgba (pattern, corner_num, red, green, blue, 1.0);
1760 * cairo_mesh_pattern_set_corner_color_rgba:
1761 * @pattern: a #cairo_pattern_t
1762 * @corner_num: the corner to set the color for
1763 * @red: red component of color
1764 * @green: green component of color
1765 * @blue: blue component of color
1766 * @alpha: alpha component of color
1768 * Sets the color of a corner of the current patch in a mesh pattern.
1770 * The color is specified in the same way as in cairo_set_source_rgba().
1772 * Valid values for @corner_num are from 0 to 3 and identify the
1773 * corners as explained in cairo_pattern_create_mesh().
1775 * Note: If @pattern is not a mesh pattern then @pattern will be put
1776 * into an error status with a status of
1777 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @corner_num is not valid,
1778 * @pattern will be put into an error status with a status of
1779 * %CAIRO_STATUS_INVALID_INDEX. If @pattern has no current patch,
1780 * @pattern will be put into an error status with a status of
1781 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1786 cairo_mesh_pattern_set_corner_color_rgba (cairo_pattern_t *pattern,
1787 unsigned int corner_num,
1788 double red, double green, double blue,
1791 cairo_mesh_pattern_t *mesh;
1793 if (unlikely (pattern->status))
1796 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1797 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1801 if (unlikely (corner_num > 3)) {
1802 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_INDEX);
1806 mesh = (cairo_mesh_pattern_t *) pattern;
1807 if (unlikely (!mesh->current_patch)) {
1808 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1812 red = _cairo_restrict_value (red, 0.0, 1.0);
1813 green = _cairo_restrict_value (green, 0.0, 1.0);
1814 blue = _cairo_restrict_value (blue, 0.0, 1.0);
1815 alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
1817 _cairo_mesh_pattern_set_corner_color (mesh, corner_num, red, green, blue, alpha);
1819 slim_hidden_def (cairo_mesh_pattern_set_corner_color_rgba);
1822 _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
1829 cairo_gradient_stop_t *stops;
1832 if (pattern->n_stops >= pattern->stops_size) {
1833 cairo_status_t status = _cairo_pattern_gradient_grow (pattern);
1834 if (unlikely (status)) {
1835 status = _cairo_pattern_set_error (&pattern->base, status);
1840 stops = pattern->stops;
1842 for (i = 0; i < pattern->n_stops; i++)
1844 if (offset < stops[i].offset)
1846 memmove (&stops[i + 1], &stops[i],
1847 sizeof (cairo_gradient_stop_t) * (pattern->n_stops - i));
1853 stops[i].offset = offset;
1855 stops[i].color.red = red;
1856 stops[i].color.green = green;
1857 stops[i].color.blue = blue;
1858 stops[i].color.alpha = alpha;
1860 stops[i].color.red_short = _cairo_color_double_to_short (red);
1861 stops[i].color.green_short = _cairo_color_double_to_short (green);
1862 stops[i].color.blue_short = _cairo_color_double_to_short (blue);
1863 stops[i].color.alpha_short = _cairo_color_double_to_short (alpha);
1869 * cairo_pattern_add_color_stop_rgb:
1870 * @pattern: a #cairo_pattern_t
1871 * @offset: an offset in the range [0.0 .. 1.0]
1872 * @red: red component of color
1873 * @green: green component of color
1874 * @blue: blue component of color
1876 * Adds an opaque color stop to a gradient pattern. The offset
1877 * specifies the location along the gradient's control vector. For
1878 * example, a linear gradient's control vector is from (x0,y0) to
1879 * (x1,y1) while a radial gradient's control vector is from any point
1880 * on the start circle to the corresponding point on the end circle.
1882 * The color is specified in the same way as in cairo_set_source_rgb().
1884 * If two (or more) stops are specified with identical offset values,
1885 * they will be sorted according to the order in which the stops are
1886 * added, (stops added earlier will compare less than stops added
1887 * later). This can be useful for reliably making sharp color
1888 * transitions instead of the typical blend.
1891 * Note: If the pattern is not a gradient pattern, (eg. a linear or
1892 * radial pattern), then the pattern will be put into an error status
1893 * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
1898 cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
1904 cairo_pattern_add_color_stop_rgba (pattern, offset, red, green, blue, 1.0);
1908 * cairo_pattern_add_color_stop_rgba:
1909 * @pattern: a #cairo_pattern_t
1910 * @offset: an offset in the range [0.0 .. 1.0]
1911 * @red: red component of color
1912 * @green: green component of color
1913 * @blue: blue component of color
1914 * @alpha: alpha component of color
1916 * Adds a translucent color stop to a gradient pattern. The offset
1917 * specifies the location along the gradient's control vector. For
1918 * example, a linear gradient's control vector is from (x0,y0) to
1919 * (x1,y1) while a radial gradient's control vector is from any point
1920 * on the start circle to the corresponding point on the end circle.
1922 * The color is specified in the same way as in cairo_set_source_rgba().
1924 * If two (or more) stops are specified with identical offset values,
1925 * they will be sorted according to the order in which the stops are
1926 * added, (stops added earlier will compare less than stops added
1927 * later). This can be useful for reliably making sharp color
1928 * transitions instead of the typical blend.
1930 * Note: If the pattern is not a gradient pattern, (eg. a linear or
1931 * radial pattern), then the pattern will be put into an error status
1932 * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
1937 cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
1944 if (pattern->status)
1947 if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
1948 pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
1950 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1954 offset = _cairo_restrict_value (offset, 0.0, 1.0);
1955 red = _cairo_restrict_value (red, 0.0, 1.0);
1956 green = _cairo_restrict_value (green, 0.0, 1.0);
1957 blue = _cairo_restrict_value (blue, 0.0, 1.0);
1958 alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
1960 _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
1961 offset, red, green, blue, alpha);
1963 slim_hidden_def (cairo_pattern_add_color_stop_rgba);
1966 * cairo_pattern_set_matrix:
1967 * @pattern: a #cairo_pattern_t
1968 * @matrix: a #cairo_matrix_t
1970 * Sets the pattern's transformation matrix to @matrix. This matrix is
1971 * a transformation from user space to pattern space.
1973 * When a pattern is first created it always has the identity matrix
1974 * for its transformation matrix, which means that pattern space is
1975 * initially identical to user space.
1977 * Important: Please note that the direction of this transformation
1978 * matrix is from user space to pattern space. This means that if you
1979 * imagine the flow from a pattern to user space (and on to device
1980 * space), then coordinates in that flow will be transformed by the
1981 * inverse of the pattern matrix.
1983 * For example, if you want to make a pattern appear twice as large as
1984 * it does by default the correct code to use is:
1986 * <informalexample><programlisting>
1987 * cairo_matrix_init_scale (&matrix, 0.5, 0.5);
1988 * cairo_pattern_set_matrix (pattern, &matrix);
1989 * </programlisting></informalexample>
1991 * Meanwhile, using values of 2.0 rather than 0.5 in the code above
1992 * would cause the pattern to appear at half of its default size.
1994 * Also, please note the discussion of the user-space locking
1995 * semantics of cairo_set_source().
2000 cairo_pattern_set_matrix (cairo_pattern_t *pattern,
2001 const cairo_matrix_t *matrix)
2003 cairo_matrix_t inverse;
2004 cairo_status_t status;
2006 if (pattern->status)
2009 if (memcmp (&pattern->matrix, matrix, sizeof (cairo_matrix_t)) == 0)
2012 pattern->matrix = *matrix;
2013 _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_MATRIX);
2016 status = cairo_matrix_invert (&inverse);
2017 if (unlikely (status))
2018 status = _cairo_pattern_set_error (pattern, status);
2020 slim_hidden_def (cairo_pattern_set_matrix);
2023 * cairo_pattern_get_matrix:
2024 * @pattern: a #cairo_pattern_t
2025 * @matrix: return value for the matrix
2027 * Stores the pattern's transformation matrix into @matrix.
2032 cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
2034 *matrix = pattern->matrix;
2038 * cairo_pattern_set_filter:
2039 * @pattern: a #cairo_pattern_t
2040 * @filter: a #cairo_filter_t describing the filter to use for resizing
2043 * Sets the filter to be used for resizing when using this pattern.
2044 * See #cairo_filter_t for details on each filter.
2046 * * Note that you might want to control filtering even when you do not
2047 * have an explicit #cairo_pattern_t object, (for example when using
2048 * cairo_set_source_surface()). In these cases, it is convenient to
2049 * use cairo_get_source() to get access to the pattern that cairo
2050 * creates implicitly. For example:
2052 * <informalexample><programlisting>
2053 * cairo_set_source_surface (cr, image, x, y);
2054 * cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
2055 * </programlisting></informalexample>
2060 cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
2062 if (pattern->status)
2065 pattern->filter = filter;
2066 _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_FILTER);
2070 * cairo_pattern_get_filter:
2071 * @pattern: a #cairo_pattern_t
2073 * Gets the current filter for a pattern. See #cairo_filter_t
2074 * for details on each filter.
2076 * Return value: the current filter used for resizing the pattern.
2081 cairo_pattern_get_filter (cairo_pattern_t *pattern)
2083 return pattern->filter;
2087 * cairo_pattern_set_extend:
2088 * @pattern: a #cairo_pattern_t
2089 * @extend: a #cairo_extend_t describing how the area outside of the
2090 * pattern will be drawn
2092 * Sets the mode to be used for drawing outside the area of a pattern.
2093 * See #cairo_extend_t for details on the semantics of each extend
2096 * The default extend mode is %CAIRO_EXTEND_NONE for surface patterns
2097 * and %CAIRO_EXTEND_PAD for gradient patterns.
2102 cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
2104 if (pattern->status)
2107 pattern->extend = extend;
2108 _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_EXTEND);
2112 * cairo_pattern_get_extend:
2113 * @pattern: a #cairo_pattern_t
2115 * Gets the current extend mode for a pattern. See #cairo_extend_t
2116 * for details on the semantics of each extend strategy.
2118 * Return value: the current extend strategy used for drawing the
2124 cairo_pattern_get_extend (cairo_pattern_t *pattern)
2126 return pattern->extend;
2128 slim_hidden_def (cairo_pattern_get_extend);
2131 _cairo_pattern_transform (cairo_pattern_t *pattern,
2132 const cairo_matrix_t *ctm_inverse)
2134 if (pattern->status)
2137 cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
2141 _linear_pattern_is_degenerate (const cairo_linear_pattern_t *linear)
2143 return fabs (linear->pd1.x - linear->pd2.x) < DBL_EPSILON &&
2144 fabs (linear->pd1.y - linear->pd2.y) < DBL_EPSILON;
2148 _radial_pattern_is_degenerate (const cairo_radial_pattern_t *radial)
2150 /* A radial pattern is considered degenerate if it can be
2151 * represented as a solid or clear pattern. This corresponds to
2152 * one of the two cases:
2154 * 1) The radii are both very small:
2155 * |dr| < DBL_EPSILON && min (r0, r1) < DBL_EPSILON
2157 * 2) The two circles have about the same radius and are very
2158 * close to each other (approximately a cylinder gradient that
2159 * doesn't move with the parameter):
2160 * |dr| < DBL_EPSILON && max (|dx|, |dy|) < 2 * DBL_EPSILON
2162 * These checks are consistent with the assumptions used in
2163 * _cairo_radial_pattern_box_to_parameter ().
2166 return fabs (radial->cd1.radius - radial->cd2.radius) < DBL_EPSILON &&
2167 (MIN (radial->cd1.radius, radial->cd2.radius) < DBL_EPSILON ||
2168 MAX (fabs (radial->cd1.center.x - radial->cd2.center.x),
2169 fabs (radial->cd1.center.y - radial->cd2.center.y)) < 2 * DBL_EPSILON);
2173 _cairo_linear_pattern_box_to_parameter (const cairo_linear_pattern_t *linear,
2174 double x0, double y0,
2175 double x1, double y1,
2178 double t0, tdx, tdy;
2179 double p1x, p1y, pdx, pdy, invsqnorm;
2181 assert (! _linear_pattern_is_degenerate (linear));
2184 * Linear gradients are othrogonal to the line passing through
2185 * their extremes. Because of convexity, the parameter range can
2186 * be computed as the convex hull (one the real line) of the
2187 * parameter values of the 4 corners of the box.
2189 * The parameter value t for a point (x,y) can be computed as:
2191 * t = (p2 - p1) . (x,y) / |p2 - p1|^2
2193 * t0 is the t value for the top left corner
2194 * tdx is the difference between left and right corners
2195 * tdy is the difference between top and bottom corners
2198 p1x = linear->pd1.x;
2199 p1y = linear->pd1.y;
2200 pdx = linear->pd2.x - p1x;
2201 pdy = linear->pd2.y - p1y;
2202 invsqnorm = 1.0 / (pdx * pdx + pdy * pdy);
2206 t0 = (x0 - p1x) * pdx + (y0 - p1y) * pdy;
2207 tdx = (x1 - x0) * pdx;
2208 tdy = (y1 - y0) * pdy;
2211 * Because of the linearity of the t value, tdx can simply be
2212 * added the t0 to move along the top edge. After this, range[0]
2213 * and range[1] represent the parameter range for the top edge, so
2214 * extending it to include the whole box simply requires adding
2215 * tdy to the correct extreme.
2218 range[0] = range[1] = t0;
2231 _extend_range (double range[2], double value, cairo_bool_t valid)
2234 range[0] = range[1] = value;
2235 else if (value < range[0])
2237 else if (value > range[1])
2244 * _cairo_radial_pattern_focus_is_inside:
2246 * Returns %TRUE if and only if the focus point exists and is
2247 * contained in one of the two extreme circles. This condition is
2248 * equivalent to one of the two extreme circles being completely
2249 * contained in the other one.
2251 * Note: if the focus is on the border of one of the two circles (in
2252 * which case the circles are tangent in the focus point), it is not
2253 * considered as contained in the circle, hence this function returns
2258 _cairo_radial_pattern_focus_is_inside (const cairo_radial_pattern_t *radial)
2260 double cx, cy, cr, dx, dy, dr;
2262 cx = radial->cd1.center.x;
2263 cy = radial->cd1.center.y;
2264 cr = radial->cd1.radius;
2265 dx = radial->cd2.center.x - cx;
2266 dy = radial->cd2.center.y - cy;
2267 dr = radial->cd2.radius - cr;
2269 return dx*dx + dy*dy < dr*dr;
2273 _cairo_radial_pattern_box_to_parameter (const cairo_radial_pattern_t *radial,
2274 double x0, double y0,
2275 double x1, double y1,
2279 double cx, cy, cr, dx, dy, dr;
2280 double a, x_focus, y_focus;
2281 double mindr, minx, miny, maxx, maxy;
2284 assert (! _radial_pattern_is_degenerate (radial));
2288 tolerance = MAX (tolerance, DBL_EPSILON);
2290 range[0] = range[1] = 0;
2293 x_focus = y_focus = 0; /* silence gcc */
2295 cx = radial->cd1.center.x;
2296 cy = radial->cd1.center.y;
2297 cr = radial->cd1.radius;
2298 dx = radial->cd2.center.x - cx;
2299 dy = radial->cd2.center.y - cy;
2300 dr = radial->cd2.radius - cr;
2302 /* translate by -(cx, cy) to simplify computations */
2308 /* enlarge boundaries slightly to avoid rounding problems in the
2309 * parameter range computation */
2315 /* enlarge boundaries even more to avoid rounding problems when
2316 * testing if a point belongs to the box */
2317 minx = x0 - DBL_EPSILON;
2318 miny = y0 - DBL_EPSILON;
2319 maxx = x1 + DBL_EPSILON;
2320 maxy = y1 + DBL_EPSILON;
2322 /* we dont' allow negative radiuses, so we will be checking that
2323 * t*dr >= mindr to consider t valid */
2324 mindr = -(cr + DBL_EPSILON);
2327 * After the previous transformations, the start circle is
2328 * centered in the origin and has radius cr. A 1-unit change in
2329 * the t parameter corresponds to dx,dy,dr changes in the x,y,r of
2330 * the circle (center coordinates, radius).
2332 * To compute the minimum range needed to correctly draw the
2333 * pattern, we start with an empty range and extend it to include
2334 * the circles touching the bounding box or within it.
2338 * Focus, the point where the circle has radius == 0.
2340 * r = cr + t * dr = 0
2343 * If the radius is constant (dr == 0) there is no focus (the
2344 * gradient represents a cylinder instead of a cone).
2346 if (fabs (dr) >= DBL_EPSILON) {
2350 x_focus = t_focus * dx;
2351 y_focus = t_focus * dy;
2352 if (minx <= x_focus && x_focus <= maxx &&
2353 miny <= y_focus && y_focus <= maxy)
2355 valid = _extend_range (range, t_focus, valid);
2360 * Circles externally tangent to box edges.
2362 * All circles have center in (dx, dy) * t
2364 * If the circle is tangent to the line defined by the edge of the
2365 * box, then at least one of the following holds true:
2367 * (dx*t) + (cr + dr*t) == x0 (left edge)
2368 * (dx*t) - (cr + dr*t) == x1 (right edge)
2369 * (dy*t) + (cr + dr*t) == y0 (top edge)
2370 * (dy*t) - (cr + dr*t) == y1 (bottom edge)
2372 * The solution is only valid if the tangent point is actually on
2373 * the edge, i.e. if its y coordinate is in [y0,y1] for left/right
2374 * edges and if its x coordinate is in [x0,x1] for top/bottom
2377 * For the first equation:
2379 * (dx + dr) * t = x0 - cr
2380 * t = (x0 - cr) / (dx + dr)
2383 * in the code this becomes:
2385 * t_edge = (num) / (den)
2386 * v = (delta) * t_edge
2388 * If the denominator in t is 0, the pattern is tangent to a line
2389 * parallel to the edge under examination. The corner-case where
2390 * the boundary line is the same as the edge is handled by the
2391 * focus point case and/or by the a==0 case.
2393 #define T_EDGE(num,den,delta,lower,upper) \
2394 if (fabs (den) >= DBL_EPSILON) { \
2397 t_edge = (num) / (den); \
2398 v = t_edge * (delta); \
2399 if (t_edge * dr >= mindr && (lower) <= v && v <= (upper)) \
2400 valid = _extend_range (range, t_edge, valid); \
2403 /* circles tangent (externally) to left/right/top/bottom edge */
2404 T_EDGE (x0 - cr, dx + dr, dy, miny, maxy);
2405 T_EDGE (x1 + cr, dx - dr, dy, miny, maxy);
2406 T_EDGE (y0 - cr, dy + dr, dx, minx, maxx);
2407 T_EDGE (y1 + cr, dy - dr, dx, minx, maxx);
2412 * Circles passing through a corner.
2414 * A circle passing through the point (x,y) satisfies:
2416 * (x-t*dx)^2 + (y-t*dy)^2 == (cr + t*dr)^2
2419 * a = dx^2 + dy^2 - dr^2
2420 * b = x*dx + y*dy + cr*dr
2421 * c = x^2 + y^2 - cr^2
2423 * a*t^2 - 2*b*t + c == 0
2425 a = dx * dx + dy * dy - dr * dr;
2426 if (fabs (a) < DBL_EPSILON * DBL_EPSILON) {
2429 /* Ensure that gradients with both a and dr small are
2430 * considered degenerate.
2431 * The floating point version of the degeneracy test implemented
2432 * in _radial_pattern_is_degenerate() is:
2434 * 1) The circles are practically the same size:
2435 * |dr| < DBL_EPSILON
2437 * 2a) The circles are both very small:
2438 * min (r0, r1) < DBL_EPSILON
2440 * 2b) The circles are very close to each other:
2441 * max (|dx|, |dy|) < 2 * DBL_EPSILON
2443 * Assuming that the gradient is not degenerate, we want to
2444 * show that |a| < DBL_EPSILON^2 implies |dr| >= DBL_EPSILON.
2446 * If the gradient is not degenerate yet it has |dr| <
2447 * DBL_EPSILON, (2b) is false, thus:
2449 * max (|dx|, |dy|) >= 2*DBL_EPSILON
2451 * 4*DBL_EPSILON^2 <= max (|dx|, |dy|)^2 <= dx^2 + dy^2
2453 * From the definition of a, we get:
2454 * a = dx^2 + dy^2 - dr^2 < DBL_EPSILON^2
2455 * dx^2 + dy^2 - DBL_EPSILON^2 < dr^2
2456 * 3*DBL_EPSILON^2 < dr^2
2458 * which is inconsistent with the hypotheses, thus |dr| <
2459 * DBL_EPSILON is false or the gradient is degenerate.
2461 assert (fabs (dr) >= DBL_EPSILON);
2464 * If a == 0, all the circles are tangent to a line in the
2465 * focus point. If this line is within the box extents, we
2466 * should add the circle with infinite radius, but this would
2467 * make the range unbounded, so we add the smallest circle whose
2468 * distance to the desired (degenerate) circle within the
2469 * bounding box does not exceed tolerance.
2471 * The equation of the line is b==0, i.e.:
2472 * x*dx + y*dy + cr*dr == 0
2474 * We compute the intersection of the line with the box and
2475 * keep the intersection with maximum square distance (maxd2)
2476 * from the focus point.
2478 * In the code the intersection is represented in another
2479 * coordinate system, whose origin is the focus point and
2480 * which has a u,v axes, which are respectively orthogonal and
2481 * parallel to the edge being intersected.
2483 * The intersection is valid only if it belongs to the box,
2484 * otherwise it is ignored.
2489 * x*dx + y0*dy + cr*dr == 0
2490 * x = -(y0*dy + cr*dr) / dx
2492 * which in (u,v) is:
2494 * v = -(y0*dy + cr*dr) / dx - x_focus
2497 * u = (edge) - (u_origin)
2498 * v = -((edge) * (delta) + cr*dr) / (den) - v_focus
2500 #define T_EDGE(edge,delta,den,lower,upper,u_origin,v_origin) \
2501 if (fabs (den) >= DBL_EPSILON) { \
2504 v = -((edge) * (delta) + cr * dr) / (den); \
2505 if ((lower) <= v && v <= (upper)) { \
2508 u = (edge) - (u_origin); \
2518 /* degenerate circles (lines) passing through each edge */
2519 T_EDGE (y0, dy, dx, minx, maxx, y_focus, x_focus);
2520 T_EDGE (y1, dy, dx, minx, maxx, y_focus, x_focus);
2521 T_EDGE (x0, dx, dy, miny, maxy, x_focus, y_focus);
2522 T_EDGE (x1, dx, dy, miny, maxy, x_focus, y_focus);
2527 * The limit circle can be transformed rigidly to the y=0 line
2528 * and the circles tangent to it in (0,0) are:
2530 * x^2 + (y-r)^2 = r^2 <=> x^2 + y^2 - 2*y*r = 0
2532 * y is the distance from the line, in our case tolerance;
2533 * x is the distance along the line, i.e. sqrt(maxd2),
2536 * r = cr + dr * t = (maxd2 + tolerance^2) / (2*tolerance)
2537 * t = (r - cr) / dr =
2538 * (maxd2 + tolerance^2 - 2*tolerance*cr) / (2*tolerance*dr)
2541 double t_limit = maxd2 + tolerance*tolerance - 2*tolerance*cr;
2542 t_limit /= 2 * tolerance * dr;
2543 valid = _extend_range (range, t_limit, valid);
2547 * Nondegenerate, nonlimit circles passing through the corners.
2549 * a == 0 && a*t^2 - 2*b*t + c == 0
2553 * The b == 0 case has just been handled, so we only have to
2554 * compute this if b != 0.
2556 #define T_CORNER(x,y) \
2557 b = (x) * dx + (y) * dy + cr * dr; \
2558 if (fabs (b) >= DBL_EPSILON) { \
2560 double x2 = (x) * (x); \
2561 double y2 = (y) * (y); \
2562 double cr2 = (cr) * (cr); \
2563 double c = x2 + y2 - cr2; \
2565 t_corner = 0.5 * c / b; \
2566 if (t_corner * dr >= mindr) \
2567 valid = _extend_range (range, t_corner, valid); \
2570 /* circles touching each corner */
2578 double inva, b, c, d;
2583 * Nondegenerate, nonlimit circles passing through the corners.
2585 * a != 0 && a*t^2 - 2*b*t + c == 0
2587 * t = (b +- sqrt (b*b - a*c)) / a
2589 * If the argument of sqrt() is negative, then no circle
2590 * passes through the corner.
2592 #define T_CORNER(x,y) \
2593 b = (x) * dx + (y) * dy + cr * dr; \
2594 c = (x) * (x) + (y) * (y) - cr * cr; \
2595 d = b * b - a * c; \
2600 t_corner = (b + d) * inva; \
2601 if (t_corner * dr >= mindr) \
2602 valid = _extend_range (range, t_corner, valid); \
2603 t_corner = (b - d) * inva; \
2604 if (t_corner * dr >= mindr) \
2605 valid = _extend_range (range, t_corner, valid); \
2608 /* circles touching each corner */
2619 * _cairo_gradient_pattern_box_to_parameter:
2621 * Compute a interpolation range sufficient to draw (within the given
2622 * tolerance) the gradient in the given box getting the same result as
2623 * using the (-inf, +inf) range.
2625 * Assumes that the pattern is not degenerate. This can be guaranteed
2626 * by simplifying it to a solid clear if _cairo_pattern_is_clear or to
2627 * a solid color if _cairo_gradient_pattern_is_solid.
2629 * The range isn't guaranteed to be minimal, but it tries to.
2632 _cairo_gradient_pattern_box_to_parameter (const cairo_gradient_pattern_t *gradient,
2633 double x0, double y0,
2634 double x1, double y1,
2636 double out_range[2])
2638 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
2639 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
2641 if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
2642 _cairo_linear_pattern_box_to_parameter ((cairo_linear_pattern_t *) gradient,
2643 x0, y0, x1, y1, out_range);
2645 _cairo_radial_pattern_box_to_parameter ((cairo_radial_pattern_t *) gradient,
2646 x0, y0, x1, y1, tolerance, out_range);
2651 * _cairo_gradient_pattern_interpolate:
2653 * Interpolate between the start and end objects of linear or radial
2654 * gradients. The interpolated object is stored in out_circle, with
2655 * the radius being zero in the linear gradient case.
2658 _cairo_gradient_pattern_interpolate (const cairo_gradient_pattern_t *gradient,
2660 cairo_circle_double_t *out_circle)
2662 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
2663 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
2665 #define lerp(a,b) (a)*(1-t) + (b)*t
2667 if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
2668 cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
2669 out_circle->center.x = lerp (linear->pd1.x, linear->pd2.x);
2670 out_circle->center.y = lerp (linear->pd1.y, linear->pd2.y);
2671 out_circle->radius = 0;
2673 cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
2674 out_circle->center.x = lerp (radial->cd1.center.x, radial->cd2.center.x);
2675 out_circle->center.y = lerp (radial->cd1.center.y, radial->cd2.center.y);
2676 out_circle->radius = lerp (radial->cd1.radius , radial->cd2.radius);
2684 * _cairo_gradient_pattern_fit_to_range:
2686 * Scale the extremes of a gradient to guarantee that the coordinates
2687 * and their deltas are within the range (-max_value, max_value). The
2688 * new extremes are stored in out_circle.
2690 * The pattern matrix is scaled to guarantee that the aspect of the
2691 * gradient is the same and the result is stored in out_matrix.
2695 _cairo_gradient_pattern_fit_to_range (const cairo_gradient_pattern_t *gradient,
2697 cairo_matrix_t *out_matrix,
2698 cairo_circle_double_t out_circle[2])
2702 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
2703 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
2705 if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
2706 cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
2708 out_circle[0].center = linear->pd1;
2709 out_circle[0].radius = 0;
2710 out_circle[1].center = linear->pd2;
2711 out_circle[1].radius = 0;
2713 dim = fabs (linear->pd1.x);
2714 dim = MAX (dim, fabs (linear->pd1.y));
2715 dim = MAX (dim, fabs (linear->pd2.x));
2716 dim = MAX (dim, fabs (linear->pd2.y));
2717 dim = MAX (dim, fabs (linear->pd1.x - linear->pd2.x));
2718 dim = MAX (dim, fabs (linear->pd1.y - linear->pd2.y));
2720 cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
2722 out_circle[0] = radial->cd1;
2723 out_circle[1] = radial->cd2;
2725 dim = fabs (radial->cd1.center.x);
2726 dim = MAX (dim, fabs (radial->cd1.center.y));
2727 dim = MAX (dim, fabs (radial->cd1.radius));
2728 dim = MAX (dim, fabs (radial->cd2.center.x));
2729 dim = MAX (dim, fabs (radial->cd2.center.y));
2730 dim = MAX (dim, fabs (radial->cd2.radius));
2731 dim = MAX (dim, fabs (radial->cd1.center.x - radial->cd2.center.x));
2732 dim = MAX (dim, fabs (radial->cd1.center.y - radial->cd2.center.y));
2733 dim = MAX (dim, fabs (radial->cd1.radius - radial->cd2.radius));
2736 if (unlikely (dim > max_value)) {
2737 cairo_matrix_t scale;
2739 dim = max_value / dim;
2741 out_circle[0].center.x *= dim;
2742 out_circle[0].center.y *= dim;
2743 out_circle[0].radius *= dim;
2744 out_circle[1].center.x *= dim;
2745 out_circle[1].center.y *= dim;
2746 out_circle[1].radius *= dim;
2748 cairo_matrix_init_scale (&scale, dim, dim);
2749 cairo_matrix_multiply (out_matrix, &gradient->base.matrix, &scale);
2751 *out_matrix = gradient->base.matrix;
2756 _gradient_is_clear (const cairo_gradient_pattern_t *gradient,
2757 const cairo_rectangle_int_t *extents)
2761 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
2762 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
2764 if (gradient->n_stops == 0 ||
2765 (gradient->base.extend == CAIRO_EXTEND_NONE &&
2766 gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
2769 if (gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL) {
2770 /* degenerate radial gradients are clear */
2771 if (_radial_pattern_is_degenerate ((cairo_radial_pattern_t *) gradient))
2773 } else if (gradient->base.extend == CAIRO_EXTEND_NONE) {
2774 /* EXTEND_NONE degenerate linear gradients are clear */
2775 if (_linear_pattern_is_degenerate ((cairo_linear_pattern_t *) gradient))
2779 /* Check if the extents intersect the drawn part of the pattern. */
2780 if (extents != NULL &&
2781 (gradient->base.extend == CAIRO_EXTEND_NONE ||
2782 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL))
2786 _cairo_gradient_pattern_box_to_parameter (gradient,
2789 extents->x + extents->width,
2790 extents->y + extents->height,
2794 if (gradient->base.extend == CAIRO_EXTEND_NONE &&
2795 (t[0] >= gradient->stops[gradient->n_stops - 1].offset ||
2796 t[1] <= gradient->stops[0].offset))
2805 for (i = 0; i < gradient->n_stops; i++)
2806 if (! CAIRO_COLOR_IS_CLEAR (&gradient->stops[i].color))
2813 _gradient_color_average (const cairo_gradient_pattern_t *gradient,
2814 cairo_color_t *color)
2816 double delta0, delta1;
2818 unsigned int i, start = 1, end;
2820 assert (gradient->n_stops > 0);
2821 assert (gradient->base.extend != CAIRO_EXTEND_NONE);
2823 if (gradient->n_stops == 1) {
2824 _cairo_color_init_rgba (color,
2825 gradient->stops[0].color.red,
2826 gradient->stops[0].color.green,
2827 gradient->stops[0].color.blue,
2828 gradient->stops[0].color.alpha);
2832 end = gradient->n_stops - 1;
2834 switch (gradient->base.extend) {
2835 case CAIRO_EXTEND_REPEAT:
2837 * Sa, Sb and Sy, Sz are the first two and last two stops respectively.
2838 * The weight of the first and last stop can be computed as the area of
2839 * the following triangles (taken with height 1, since the whole [0-1]
2840 * will have total weight 1 this way): b*h/2
2846 * ~~~~~+---+---+---+~~~~~~~+-------+---+---+~~~~~
2847 * -1+Sz 0 Sa Sb Sy Sz 1 1+Sa
2849 * For the first stop: (Sb-(-1+Sz)/2 = (1+Sb-Sz)/2
2850 * For the last stop: ((1+Sa)-Sy)/2 = (1+Sa-Sy)/2
2851 * Halving the result is done after summing up all the areas.
2853 delta0 = 1.0 + gradient->stops[1].offset - gradient->stops[end].offset;
2854 delta1 = 1.0 + gradient->stops[0].offset - gradient->stops[end-1].offset;
2857 case CAIRO_EXTEND_REFLECT:
2859 * Sa, Sb and Sy, Sz are the first two and last two stops respectively.
2860 * The weight of the first and last stop can be computed as the area of
2861 * the following trapezoids (taken with height 1, since the whole [0-1]
2862 * will have total weight 1 this way): (b+B)*h/2
2868 * +-------+---+~~~~~~~+-------+---+
2871 * For the first stop: (Sa+Sb)/2
2872 * For the last stop: ((1-Sz) + (1-Sy))/2 = (2-Sy-Sz)/2
2873 * Halving the result is done after summing up all the areas.
2875 delta0 = gradient->stops[0].offset + gradient->stops[1].offset;
2876 delta1 = 2.0 - gradient->stops[end-1].offset - gradient->stops[end].offset;
2879 case CAIRO_EXTEND_PAD:
2880 /* PAD is computed as the average of the first and last stop:
2881 * - take both of them with weight 1 (they will be halved
2882 * after the whole sum has been computed).
2883 * - avoid summing any of the inner stops.
2885 delta0 = delta1 = 1.0;
2889 case CAIRO_EXTEND_NONE:
2892 _cairo_color_init_rgba (color, 0, 0, 0, 0);
2896 r = delta0 * gradient->stops[0].color.red;
2897 g = delta0 * gradient->stops[0].color.green;
2898 b = delta0 * gradient->stops[0].color.blue;
2899 a = delta0 * gradient->stops[0].color.alpha;
2901 for (i = start; i < end; ++i) {
2902 /* Inner stops weight is the same as the area of the triangle they influence
2903 * (which goes from the stop before to the stop after), again with height 1
2904 * since the whole must sum up to 1: b*h/2
2905 * Halving is done after the whole sum has been computed.
2907 double delta = gradient->stops[i+1].offset - gradient->stops[i-1].offset;
2908 r += delta * gradient->stops[i].color.red;
2909 g += delta * gradient->stops[i].color.green;
2910 b += delta * gradient->stops[i].color.blue;
2911 a += delta * gradient->stops[i].color.alpha;
2914 r += delta1 * gradient->stops[end].color.red;
2915 g += delta1 * gradient->stops[end].color.green;
2916 b += delta1 * gradient->stops[end].color.blue;
2917 a += delta1 * gradient->stops[end].color.alpha;
2919 _cairo_color_init_rgba (color, r * .5, g * .5, b * .5, a * .5);
2923 * _cairo_pattern_alpha_range:
2925 * Convenience function to determine the minimum and maximum alpha in
2926 * the drawn part of a pattern (i.e. ignoring clear parts caused by
2927 * extend modes and/or pattern shape).
2929 * If not NULL, out_min and out_max will be set respectively to the
2930 * minimum and maximum alpha value of the pattern.
2933 _cairo_pattern_alpha_range (const cairo_pattern_t *pattern,
2937 double alpha_min, alpha_max;
2939 switch (pattern->type) {
2940 case CAIRO_PATTERN_TYPE_SOLID: {
2941 const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
2942 alpha_min = alpha_max = solid->color.alpha;
2946 case CAIRO_PATTERN_TYPE_LINEAR:
2947 case CAIRO_PATTERN_TYPE_RADIAL: {
2948 const cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
2951 assert (gradient->n_stops >= 1);
2953 alpha_min = alpha_max = gradient->stops[0].color.alpha;
2954 for (i = 1; i < gradient->n_stops; i++) {
2955 if (alpha_min > gradient->stops[i].color.alpha)
2956 alpha_min = gradient->stops[i].color.alpha;
2957 else if (alpha_max < gradient->stops[i].color.alpha)
2958 alpha_max = gradient->stops[i].color.alpha;
2964 case CAIRO_PATTERN_TYPE_MESH: {
2965 const cairo_mesh_pattern_t *mesh = (const cairo_mesh_pattern_t *) pattern;
2966 const cairo_mesh_patch_t *patch = _cairo_array_index_const (&mesh->patches, 0);
2967 unsigned int i, j, n = _cairo_array_num_elements (&mesh->patches);
2971 alpha_min = alpha_max = patch[0].colors[0].alpha;
2972 for (i = 0; i < n; i++) {
2973 for (j = 0; j < 4; j++) {
2974 if (patch[i].colors[j].alpha < alpha_min)
2975 alpha_min = patch[i].colors[j].alpha;
2976 else if (patch[i].colors[j].alpha > alpha_max)
2977 alpha_max = patch[i].colors[j].alpha;
2988 case CAIRO_PATTERN_TYPE_SURFACE:
2989 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
2996 *out_min = alpha_min;
2998 *out_max = alpha_max;
3002 * _cairo_mesh_pattern_coord_box:
3004 * Convenience function to determine the range of the coordinates of
3005 * the points used to define the patches of the mesh.
3007 * This is guaranteed to contain the pattern extents, but might not be
3008 * tight, just like a Bezier curve is always inside the convex hull of
3009 * the control points.
3011 * This function cannot be used while the mesh is being constructed.
3013 * The function returns TRUE and sets the output parametes to define
3014 * the coodrinate range if the mesh pattern contains at least one
3015 * patch, otherwise it returns FALSE.
3018 _cairo_mesh_pattern_coord_box (const cairo_mesh_pattern_t *mesh,
3024 const cairo_mesh_patch_t *patch;
3025 unsigned int num_patches, i, j, k;
3026 double x0, y0, x1, y1;
3028 assert (mesh->current_patch == NULL);
3030 num_patches = _cairo_array_num_elements (&mesh->patches);
3032 if (num_patches == 0)
3035 patch = _cairo_array_index_const (&mesh->patches, 0);
3036 x0 = x1 = patch->points[0][0].x;
3037 y0 = y1 = patch->points[0][0].y;
3039 for (i = 0; i < num_patches; i++) {
3040 for (j = 0; j < 4; j++) {
3041 for (k = 0; k < 4; k++) {
3042 x0 = MIN (x0, patch[i].points[j][k].x);
3043 y0 = MIN (y0, patch[i].points[j][k].y);
3044 x1 = MAX (x1, patch[i].points[j][k].x);
3045 y1 = MAX (y1, patch[i].points[j][k].y);
3059 * _cairo_gradient_pattern_is_solid:
3061 * Convenience function to determine whether a gradient pattern is
3062 * a solid color within the given extents. In this case the color
3063 * argument is initialized to the color the pattern represents.
3064 * This functions doesn't handle completely transparent gradients,
3065 * thus it should be called only after _cairo_pattern_is_clear has
3068 * Return value: %TRUE if the pattern is a solid color.
3071 _cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient,
3072 const cairo_rectangle_int_t *extents,
3073 cairo_color_t *color)
3077 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
3078 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
3081 if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
3082 cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
3083 if (_linear_pattern_is_degenerate (linear)) {
3084 _gradient_color_average (gradient, color);
3088 if (gradient->base.extend == CAIRO_EXTEND_NONE) {
3091 /* We already know that the pattern is not clear, thus if some
3092 * part of it is clear, the whole is not solid.
3095 if (extents == NULL)
3098 _cairo_linear_pattern_box_to_parameter (linear,
3101 extents->x + extents->width,
3102 extents->y + extents->height,
3105 if (t[0] < 0.0 || t[1] > 1.0)
3111 for (i = 1; i < gradient->n_stops; i++)
3112 if (! _cairo_color_stop_equal (&gradient->stops[0].color,
3113 &gradient->stops[i].color))
3116 _cairo_color_init_rgba (color,
3117 gradient->stops[0].color.red,
3118 gradient->stops[0].color.green,
3119 gradient->stops[0].color.blue,
3120 gradient->stops[0].color.alpha);
3126 _mesh_is_clear (const cairo_mesh_pattern_t *mesh)
3128 double x1, y1, x2, y2;
3129 cairo_bool_t is_valid;
3131 is_valid = _cairo_mesh_pattern_coord_box (mesh, &x1, &y1, &x2, &y2);
3135 if (x2 - x1 < DBL_EPSILON || y2 - y1 < DBL_EPSILON)
3142 * _cairo_pattern_is_opaque_solid:
3144 * Convenience function to determine whether a pattern is an opaque
3145 * (alpha==1.0) solid color pattern. This is done by testing whether
3146 * the pattern's alpha value when converted to a byte is 255, so if a
3147 * backend actually supported deep alpha channels this function might
3148 * not do the right thing.
3150 * Return value: %TRUE if the pattern is an opaque, solid color.
3153 _cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern)
3155 cairo_solid_pattern_t *solid;
3157 if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
3160 solid = (cairo_solid_pattern_t *) pattern;
3162 return CAIRO_COLOR_IS_OPAQUE (&solid->color);
3166 _surface_is_opaque (const cairo_surface_pattern_t *pattern,
3167 const cairo_rectangle_int_t *sample)
3169 cairo_rectangle_int_t extents;
3171 if (pattern->surface->content & CAIRO_CONTENT_ALPHA)
3174 if (pattern->base.extend != CAIRO_EXTEND_NONE)
3177 if (! _cairo_surface_get_extents (pattern->surface, &extents))
3183 return _cairo_rectangle_contains_rectangle (&extents, sample);
3187 _raster_source_is_opaque (const cairo_raster_source_pattern_t *pattern,
3188 const cairo_rectangle_int_t *sample)
3190 if (pattern->content & CAIRO_CONTENT_ALPHA)
3193 if (pattern->base.extend != CAIRO_EXTEND_NONE)
3199 return _cairo_rectangle_contains_rectangle (&pattern->extents, sample);
3203 _surface_is_clear (const cairo_surface_pattern_t *pattern)
3205 cairo_rectangle_int_t extents;
3207 if (_cairo_surface_get_extents (pattern->surface, &extents) &&
3208 (extents.width == 0 || extents.height == 0))
3211 return pattern->surface->is_clear &&
3212 pattern->surface->content & CAIRO_CONTENT_ALPHA;
3216 _raster_source_is_clear (const cairo_raster_source_pattern_t *pattern)
3218 return pattern->extents.width == 0 || pattern->extents.height == 0;
3222 _gradient_is_opaque (const cairo_gradient_pattern_t *gradient,
3223 const cairo_rectangle_int_t *sample)
3227 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
3228 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
3230 if (gradient->n_stops == 0 ||
3231 (gradient->base.extend == CAIRO_EXTEND_NONE &&
3232 gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
3235 if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
3236 if (gradient->base.extend == CAIRO_EXTEND_NONE) {
3238 cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
3240 /* EXTEND_NONE degenerate radial gradients are clear */
3241 if (_linear_pattern_is_degenerate (linear))
3247 _cairo_linear_pattern_box_to_parameter (linear,
3250 sample->x + sample->width,
3251 sample->y + sample->height,
3254 if (t[0] < 0.0 || t[1] > 1.0)
3258 return FALSE; /* TODO: check actual intersection */
3260 for (i = 0; i < gradient->n_stops; i++)
3261 if (! CAIRO_COLOR_IS_OPAQUE (&gradient->stops[i].color))
3268 * _cairo_pattern_is_opaque:
3270 * Convenience function to determine whether a pattern is an opaque
3271 * pattern (of any type). The same caveats that apply to
3272 * _cairo_pattern_is_opaque_solid apply here as well.
3274 * Return value: %TRUE if the pattern is a opaque.
3277 _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern,
3278 const cairo_rectangle_int_t *sample)
3280 const cairo_pattern_union_t *pattern;
3282 if (abstract_pattern->has_component_alpha)
3285 pattern = (cairo_pattern_union_t *) abstract_pattern;
3286 switch (pattern->base.type) {
3287 case CAIRO_PATTERN_TYPE_SOLID:
3288 return _cairo_pattern_is_opaque_solid (abstract_pattern);
3289 case CAIRO_PATTERN_TYPE_SURFACE:
3290 return _surface_is_opaque (&pattern->surface, sample);
3291 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3292 return _raster_source_is_opaque (&pattern->raster_source, sample);
3293 case CAIRO_PATTERN_TYPE_LINEAR:
3294 case CAIRO_PATTERN_TYPE_RADIAL:
3295 return _gradient_is_opaque (&pattern->gradient.base, sample);
3296 case CAIRO_PATTERN_TYPE_MESH:
3305 _cairo_pattern_is_clear (const cairo_pattern_t *abstract_pattern)
3307 const cairo_pattern_union_t *pattern;
3309 if (abstract_pattern->has_component_alpha)
3312 pattern = (cairo_pattern_union_t *) abstract_pattern;
3313 switch (abstract_pattern->type) {
3314 case CAIRO_PATTERN_TYPE_SOLID:
3315 return CAIRO_COLOR_IS_CLEAR (&pattern->solid.color);
3316 case CAIRO_PATTERN_TYPE_SURFACE:
3317 return _surface_is_clear (&pattern->surface);
3318 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3319 return _raster_source_is_clear (&pattern->raster_source);
3320 case CAIRO_PATTERN_TYPE_LINEAR:
3321 case CAIRO_PATTERN_TYPE_RADIAL:
3322 return _gradient_is_clear (&pattern->gradient.base, NULL);
3323 case CAIRO_PATTERN_TYPE_MESH:
3324 return _mesh_is_clear (&pattern->mesh);
3332 * _cairo_pattern_analyze_filter:
3333 * @pattern: surface pattern
3334 * @pad_out: location to store necessary padding in the source image, or %NULL
3335 * Returns: the optimized #cairo_filter_t to use with @pattern.
3337 * Analyze the filter to determine how much extra needs to be sampled
3338 * from the source image to account for the filter radius and whether
3339 * we can optimize the filter to a simpler value.
3341 * XXX: We don't actually have any way of querying the backend for
3342 * the filter radius, so we just guess base on what we know that
3343 * backends do currently (see bug #10508)
3346 _cairo_pattern_analyze_filter (const cairo_pattern_t *pattern,
3350 cairo_filter_t optimized_filter;
3352 switch (pattern->filter) {
3353 case CAIRO_FILTER_GOOD:
3354 case CAIRO_FILTER_BEST:
3355 case CAIRO_FILTER_BILINEAR:
3356 /* If source pixels map 1:1 onto destination pixels, we do
3357 * not need to filter (and do not want to filter, since it
3358 * will cause blurriness)
3360 if (_cairo_matrix_is_pixel_exact (&pattern->matrix)) {
3362 optimized_filter = CAIRO_FILTER_NEAREST;
3364 /* 0.5 is enough for a bilinear filter. It's possible we
3365 * should defensively use more for CAIRO_FILTER_BEST, but
3366 * without a single example, it's hard to know how much
3367 * more would be defensive...
3370 optimized_filter = pattern->filter;
3374 case CAIRO_FILTER_FAST:
3375 case CAIRO_FILTER_NEAREST:
3376 case CAIRO_FILTER_GAUSSIAN:
3379 optimized_filter = pattern->filter;
3386 return optimized_filter;
3390 _cairo_pattern_sampled_area (const cairo_pattern_t *pattern,
3391 const cairo_rectangle_int_t *extents,
3392 cairo_rectangle_int_t *sample)
3394 cairo_filter_t filter;
3395 double x1, x2, y1, y2;
3398 filter = _cairo_pattern_analyze_filter (pattern, &pad);
3399 if (pad == 0.0 && _cairo_matrix_is_identity (&pattern->matrix)) {
3406 x2 = extents->x + (int) extents->width;
3407 y2 = extents->y + (int) extents->height;
3409 _cairo_matrix_transform_bounding_box (&pattern->matrix,
3412 if (x1 > CAIRO_RECT_INT_MIN)
3413 sample->x = floor (x1 - pad);
3415 sample->x = CAIRO_RECT_INT_MIN;
3417 if (y1 > CAIRO_RECT_INT_MIN)
3418 sample->y = floor (y1 - pad);
3420 sample->y = CAIRO_RECT_INT_MIN;
3422 if (x2 < CAIRO_RECT_INT_MAX)
3423 sample->width = ceil (x2 + pad);
3425 sample->width = CAIRO_RECT_INT_MAX;
3427 if (y2 < CAIRO_RECT_INT_MAX)
3428 sample->height = ceil (y2 + pad);
3430 sample->height = CAIRO_RECT_INT_MAX;
3432 sample->width -= sample->x;
3433 sample->height -= sample->y;
3439 * _cairo_pattern_get_extents:
3441 * Return the "target-space" extents of @pattern in @extents.
3443 * For unbounded patterns, the @extents will be initialized with
3444 * "infinite" extents, (minimum and maximum fixed-point values).
3446 * XXX: Currently, bounded gradient patterns will also return
3447 * "infinite" extents, though it would be possible to optimize these
3448 * with a little more work.
3451 _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
3452 cairo_rectangle_int_t *extents)
3454 double x1, y1, x2, y2;
3455 cairo_status_t status;
3457 switch (pattern->type) {
3458 case CAIRO_PATTERN_TYPE_SOLID:
3461 case CAIRO_PATTERN_TYPE_SURFACE:
3463 cairo_rectangle_int_t surface_extents;
3464 const cairo_surface_pattern_t *surface_pattern =
3465 (const cairo_surface_pattern_t *) pattern;
3466 cairo_surface_t *surface = surface_pattern->surface;
3469 if (! _cairo_surface_get_extents (surface, &surface_extents))
3472 if (surface_extents.width == 0 || surface_extents.height == 0)
3475 if (pattern->extend != CAIRO_EXTEND_NONE)
3478 /* The filter can effectively enlarge the extents of the
3479 * pattern, so extend as necessary.
3481 _cairo_pattern_analyze_filter (&surface_pattern->base, &pad);
3482 x1 = surface_extents.x - pad;
3483 y1 = surface_extents.y - pad;
3484 x2 = surface_extents.x + (int) surface_extents.width + pad;
3485 y2 = surface_extents.y + (int) surface_extents.height + pad;
3489 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3491 const cairo_raster_source_pattern_t *raster =
3492 (const cairo_raster_source_pattern_t *) pattern;
3495 if (raster->extents.width == 0 || raster->extents.height == 0)
3498 if (pattern->extend != CAIRO_EXTEND_NONE)
3501 /* The filter can effectively enlarge the extents of the
3502 * pattern, so extend as necessary.
3504 _cairo_pattern_analyze_filter (pattern, &pad);
3505 x1 = raster->extents.x - pad;
3506 y1 = raster->extents.y - pad;
3507 x2 = raster->extents.x + (int) raster->extents.width + pad;
3508 y2 = raster->extents.y + (int) raster->extents.height + pad;
3512 case CAIRO_PATTERN_TYPE_RADIAL:
3514 const cairo_radial_pattern_t *radial =
3515 (const cairo_radial_pattern_t *) pattern;
3520 if (_radial_pattern_is_degenerate (radial)) {
3521 /* cairo-gstate should have optimised degenerate
3522 * patterns to solid clear patterns, so we can ignore
3527 /* TODO: in some cases (focus outside/on the circle) it is
3529 if (pattern->extend != CAIRO_EXTEND_NONE)
3532 cx1 = radial->cd1.center.x;
3533 cy1 = radial->cd1.center.y;
3534 r1 = radial->cd1.radius;
3536 cx2 = radial->cd2.center.x;
3537 cy2 = radial->cd2.center.y;
3538 r2 = radial->cd2.radius;
3540 x1 = MIN (cx1 - r1, cx2 - r2);
3541 y1 = MIN (cy1 - r1, cy2 - r2);
3542 x2 = MAX (cx1 + r1, cx2 + r2);
3543 y2 = MAX (cy1 + r1, cy2 + r2);
3547 case CAIRO_PATTERN_TYPE_LINEAR:
3549 const cairo_linear_pattern_t *linear =
3550 (const cairo_linear_pattern_t *) pattern;
3552 if (pattern->extend != CAIRO_EXTEND_NONE)
3555 if (_linear_pattern_is_degenerate (linear)) {
3556 /* cairo-gstate should have optimised degenerate
3557 * patterns to solid ones, so we can again ignore
3562 /* TODO: to get tight extents, use the matrix to transform
3563 * the pattern instead of transforming the extents later. */
3564 if (pattern->matrix.xy != 0. || pattern->matrix.yx != 0.)
3567 if (linear->pd1.x == linear->pd2.x) {
3570 y1 = MIN (linear->pd1.y, linear->pd2.y);
3571 y2 = MAX (linear->pd1.y, linear->pd2.y);
3572 } else if (linear->pd1.y == linear->pd2.y) {
3573 x1 = MIN (linear->pd1.x, linear->pd2.x);
3574 x2 = MAX (linear->pd1.x, linear->pd2.x);
3583 case CAIRO_PATTERN_TYPE_MESH:
3585 const cairo_mesh_pattern_t *mesh =
3586 (const cairo_mesh_pattern_t *) pattern;
3588 cairo_bool_t is_valid;
3590 is_valid = _cairo_mesh_pattern_coord_box (mesh, &x1, &y1, &x2, &y2);
3595 cairo_matrix_transform_distance (&pattern->matrix, &padx, &pady);
3610 if (_cairo_matrix_is_translation (&pattern->matrix)) {
3611 x1 -= pattern->matrix.x0; x2 -= pattern->matrix.x0;
3612 y1 -= pattern->matrix.y0; y2 -= pattern->matrix.y0;
3614 cairo_matrix_t imatrix;
3616 imatrix = pattern->matrix;
3617 status = cairo_matrix_invert (&imatrix);
3618 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3619 assert (status == CAIRO_STATUS_SUCCESS);
3621 _cairo_matrix_transform_bounding_box (&imatrix,
3627 if (x1 < CAIRO_RECT_INT_MIN)
3628 x1 = CAIRO_RECT_INT_MIN;
3630 if (y1 < CAIRO_RECT_INT_MIN)
3631 y1 = CAIRO_RECT_INT_MIN;
3634 if (x2 > CAIRO_RECT_INT_MAX)
3635 x2 = CAIRO_RECT_INT_MAX;
3637 if (y2 > CAIRO_RECT_INT_MAX)
3638 y2 = CAIRO_RECT_INT_MAX;
3640 extents->x = x1; extents->width = x2 - x1;
3641 extents->y = y1; extents->height = y2 - y1;
3645 /* unbounded patterns -> 'infinite' extents */
3646 _cairo_unbounded_rectangle_init (extents);
3650 extents->x = extents->y = 0;
3651 extents->width = extents->height = 0;
3656 * _cairo_pattern_get_ink_extents:
3658 * Return the "target-space" inked extents of @pattern in @extents.
3661 _cairo_pattern_get_ink_extents (const cairo_pattern_t *pattern,
3662 cairo_rectangle_int_t *extents)
3664 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE &&
3665 pattern->extend == CAIRO_EXTEND_NONE)
3667 const cairo_surface_pattern_t *surface_pattern =
3668 (const cairo_surface_pattern_t *) pattern;
3669 cairo_surface_t *surface = surface_pattern->surface;
3671 surface = _cairo_surface_get_source (surface, NULL);
3672 if (_cairo_surface_is_recording (surface)) {
3673 cairo_matrix_t imatrix;
3675 cairo_status_t status;
3677 imatrix = pattern->matrix;
3678 status = cairo_matrix_invert (&imatrix);
3679 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3680 assert (status == CAIRO_STATUS_SUCCESS);
3682 status = _cairo_recording_surface_get_ink_bbox ((cairo_recording_surface_t *)surface,
3684 if (unlikely (status))
3687 _cairo_box_round_to_rectangle (&box, extents);
3688 return CAIRO_STATUS_SUCCESS;
3692 _cairo_pattern_get_extents (pattern, extents);
3693 return CAIRO_STATUS_SUCCESS;
3696 static unsigned long
3697 _cairo_solid_pattern_hash (unsigned long hash,
3698 const cairo_solid_pattern_t *solid)
3700 hash = _cairo_hash_bytes (hash, &solid->color, sizeof (solid->color));
3705 static unsigned long
3706 _cairo_gradient_color_stops_hash (unsigned long hash,
3707 const cairo_gradient_pattern_t *gradient)
3711 hash = _cairo_hash_bytes (hash,
3713 sizeof (gradient->n_stops));
3715 for (n = 0; n < gradient->n_stops; n++) {
3716 hash = _cairo_hash_bytes (hash,
3717 &gradient->stops[n].offset,
3719 hash = _cairo_hash_bytes (hash,
3720 &gradient->stops[n].color,
3721 sizeof (cairo_color_stop_t));
3728 _cairo_linear_pattern_hash (unsigned long hash,
3729 const cairo_linear_pattern_t *linear)
3731 hash = _cairo_hash_bytes (hash, &linear->pd1, sizeof (linear->pd1));
3732 hash = _cairo_hash_bytes (hash, &linear->pd2, sizeof (linear->pd2));
3734 return _cairo_gradient_color_stops_hash (hash, &linear->base);
3738 _cairo_radial_pattern_hash (unsigned long hash,
3739 const cairo_radial_pattern_t *radial)
3741 hash = _cairo_hash_bytes (hash, &radial->cd1.center, sizeof (radial->cd1.center));
3742 hash = _cairo_hash_bytes (hash, &radial->cd1.radius, sizeof (radial->cd1.radius));
3743 hash = _cairo_hash_bytes (hash, &radial->cd2.center, sizeof (radial->cd2.center));
3744 hash = _cairo_hash_bytes (hash, &radial->cd2.radius, sizeof (radial->cd2.radius));
3746 return _cairo_gradient_color_stops_hash (hash, &radial->base);
3749 static unsigned long
3750 _cairo_mesh_pattern_hash (unsigned long hash, const cairo_mesh_pattern_t *mesh)
3752 const cairo_mesh_patch_t *patch = _cairo_array_index_const (&mesh->patches, 0);
3753 unsigned int i, n = _cairo_array_num_elements (&mesh->patches);
3755 for (i = 0; i < n; i++)
3756 hash = _cairo_hash_bytes (hash, patch + i, sizeof (cairo_mesh_patch_t));
3761 static unsigned long
3762 _cairo_surface_pattern_hash (unsigned long hash,
3763 const cairo_surface_pattern_t *surface)
3765 hash ^= surface->surface->unique_id;
3770 static unsigned long
3771 _cairo_raster_source_pattern_hash (unsigned long hash,
3772 const cairo_raster_source_pattern_t *raster)
3774 hash ^= (uintptr_t)raster->user_data;
3780 _cairo_pattern_hash (const cairo_pattern_t *pattern)
3782 unsigned long hash = _CAIRO_HASH_INIT_VALUE;
3784 if (pattern->status)
3787 hash = _cairo_hash_bytes (hash, &pattern->type, sizeof (pattern->type));
3788 if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
3789 hash = _cairo_hash_bytes (hash,
3790 &pattern->matrix, sizeof (pattern->matrix));
3791 hash = _cairo_hash_bytes (hash,
3792 &pattern->filter, sizeof (pattern->filter));
3793 hash = _cairo_hash_bytes (hash,
3794 &pattern->extend, sizeof (pattern->extend));
3795 hash = _cairo_hash_bytes (hash,
3796 &pattern->has_component_alpha,
3797 sizeof (pattern->has_component_alpha));
3800 switch (pattern->type) {
3801 case CAIRO_PATTERN_TYPE_SOLID:
3802 return _cairo_solid_pattern_hash (hash, (cairo_solid_pattern_t *) pattern);
3803 case CAIRO_PATTERN_TYPE_LINEAR:
3804 return _cairo_linear_pattern_hash (hash, (cairo_linear_pattern_t *) pattern);
3805 case CAIRO_PATTERN_TYPE_RADIAL:
3806 return _cairo_radial_pattern_hash (hash, (cairo_radial_pattern_t *) pattern);
3807 case CAIRO_PATTERN_TYPE_MESH:
3808 return _cairo_mesh_pattern_hash (hash, (cairo_mesh_pattern_t *) pattern);
3809 case CAIRO_PATTERN_TYPE_SURFACE:
3810 return _cairo_surface_pattern_hash (hash, (cairo_surface_pattern_t *) pattern);
3811 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3812 return _cairo_raster_source_pattern_hash (hash, (cairo_raster_source_pattern_t *) pattern);
3820 _cairo_solid_pattern_equal (const cairo_solid_pattern_t *a,
3821 const cairo_solid_pattern_t *b)
3823 return _cairo_color_equal (&a->color, &b->color);
3827 _cairo_gradient_color_stops_equal (const cairo_gradient_pattern_t *a,
3828 const cairo_gradient_pattern_t *b)
3832 if (a->n_stops != b->n_stops)
3835 for (n = 0; n < a->n_stops; n++) {
3836 if (a->stops[n].offset != b->stops[n].offset)
3838 if (! _cairo_color_stop_equal (&a->stops[n].color, &b->stops[n].color))
3846 _cairo_linear_pattern_equal (const cairo_linear_pattern_t *a,
3847 const cairo_linear_pattern_t *b)
3849 if (a->pd1.x != b->pd1.x)
3852 if (a->pd1.y != b->pd1.y)
3855 if (a->pd2.x != b->pd2.x)
3858 if (a->pd2.y != b->pd2.y)
3861 return _cairo_gradient_color_stops_equal (&a->base, &b->base);
3865 _cairo_radial_pattern_equal (const cairo_radial_pattern_t *a,
3866 const cairo_radial_pattern_t *b)
3868 if (a->cd1.center.x != b->cd1.center.x)
3871 if (a->cd1.center.y != b->cd1.center.y)
3874 if (a->cd1.radius != b->cd1.radius)
3877 if (a->cd2.center.x != b->cd2.center.x)
3880 if (a->cd2.center.y != b->cd2.center.y)
3883 if (a->cd2.radius != b->cd2.radius)
3886 return _cairo_gradient_color_stops_equal (&a->base, &b->base);
3890 _cairo_mesh_pattern_equal (const cairo_mesh_pattern_t *a,
3891 const cairo_mesh_pattern_t *b)
3893 const cairo_mesh_patch_t *patch_a, *patch_b;
3894 unsigned int i, num_patches_a, num_patches_b;
3896 num_patches_a = _cairo_array_num_elements (&a->patches);
3897 num_patches_b = _cairo_array_num_elements (&b->patches);
3899 if (num_patches_a != num_patches_b)
3902 for (i = 0; i < num_patches_a; i++) {
3903 patch_a = _cairo_array_index_const (&a->patches, i);
3904 patch_b = _cairo_array_index_const (&a->patches, i);
3905 if (memcmp (patch_a, patch_b, sizeof(cairo_mesh_patch_t)) != 0)
3913 _cairo_surface_pattern_equal (const cairo_surface_pattern_t *a,
3914 const cairo_surface_pattern_t *b)
3916 return a->surface->unique_id == b->surface->unique_id;
3920 _cairo_raster_source_pattern_equal (const cairo_raster_source_pattern_t *a,
3921 const cairo_raster_source_pattern_t *b)
3923 return a->user_data == b->user_data;
3927 _cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b)
3929 if (a->status || b->status)
3935 if (a->type != b->type)
3938 if (a->has_component_alpha != b->has_component_alpha)
3941 if (a->type != CAIRO_PATTERN_TYPE_SOLID) {
3942 if (memcmp (&a->matrix, &b->matrix, sizeof (cairo_matrix_t)))
3945 if (a->filter != b->filter)
3948 if (a->extend != b->extend)
3953 case CAIRO_PATTERN_TYPE_SOLID:
3954 return _cairo_solid_pattern_equal ((cairo_solid_pattern_t *) a,
3955 (cairo_solid_pattern_t *) b);
3956 case CAIRO_PATTERN_TYPE_LINEAR:
3957 return _cairo_linear_pattern_equal ((cairo_linear_pattern_t *) a,
3958 (cairo_linear_pattern_t *) b);
3959 case CAIRO_PATTERN_TYPE_RADIAL:
3960 return _cairo_radial_pattern_equal ((cairo_radial_pattern_t *) a,
3961 (cairo_radial_pattern_t *) b);
3962 case CAIRO_PATTERN_TYPE_MESH:
3963 return _cairo_mesh_pattern_equal ((cairo_mesh_pattern_t *) a,
3964 (cairo_mesh_pattern_t *) b);
3965 case CAIRO_PATTERN_TYPE_SURFACE:
3966 return _cairo_surface_pattern_equal ((cairo_surface_pattern_t *) a,
3967 (cairo_surface_pattern_t *) b);
3968 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3969 return _cairo_raster_source_pattern_equal ((cairo_raster_source_pattern_t *) a,
3970 (cairo_raster_source_pattern_t *) b);
3978 * cairo_pattern_get_rgba:
3979 * @pattern: a #cairo_pattern_t
3980 * @red: return value for red component of color, or %NULL
3981 * @green: return value for green component of color, or %NULL
3982 * @blue: return value for blue component of color, or %NULL
3983 * @alpha: return value for alpha component of color, or %NULL
3985 * Gets the solid color for a solid color pattern.
3987 * Return value: %CAIRO_STATUS_SUCCESS, or
3988 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid
3994 cairo_pattern_get_rgba (cairo_pattern_t *pattern,
3995 double *red, double *green,
3996 double *blue, double *alpha)
3998 cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
3999 double r0, g0, b0, a0;
4001 if (pattern->status)
4002 return pattern->status;
4004 if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
4005 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4007 _cairo_color_get_rgba (&solid->color, &r0, &g0, &b0, &a0);
4018 return CAIRO_STATUS_SUCCESS;
4022 * cairo_pattern_get_surface:
4023 * @pattern: a #cairo_pattern_t
4024 * @surface: return value for surface of pattern, or %NULL
4026 * Gets the surface of a surface pattern. The reference returned in
4027 * @surface is owned by the pattern; the caller should call
4028 * cairo_surface_reference() if the surface is to be retained.
4030 * Return value: %CAIRO_STATUS_SUCCESS, or
4031 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a surface
4037 cairo_pattern_get_surface (cairo_pattern_t *pattern,
4038 cairo_surface_t **surface)
4040 cairo_surface_pattern_t *spat = (cairo_surface_pattern_t*) pattern;
4042 if (pattern->status)
4043 return pattern->status;
4045 if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
4046 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4049 *surface = spat->surface;
4051 return CAIRO_STATUS_SUCCESS;
4055 * cairo_pattern_get_color_stop_rgba:
4056 * @pattern: a #cairo_pattern_t
4057 * @index: index of the stop to return data for
4058 * @offset: return value for the offset of the stop, or %NULL
4059 * @red: return value for red component of color, or %NULL
4060 * @green: return value for green component of color, or %NULL
4061 * @blue: return value for blue component of color, or %NULL
4062 * @alpha: return value for alpha component of color, or %NULL
4064 * Gets the color and offset information at the given @index for a
4065 * gradient pattern. Values of @index are 0 to 1 less than the number
4066 * returned by cairo_pattern_get_color_stop_count().
4068 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
4069 * if @index is not valid for the given pattern. If the pattern is
4070 * not a gradient pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
4076 cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
4077 int index, double *offset,
4078 double *red, double *green,
4079 double *blue, double *alpha)
4081 cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
4083 if (pattern->status)
4084 return pattern->status;
4086 if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
4087 pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
4088 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4090 if (index < 0 || (unsigned int) index >= gradient->n_stops)
4091 return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4094 *offset = gradient->stops[index].offset;
4096 *red = gradient->stops[index].color.red;
4098 *green = gradient->stops[index].color.green;
4100 *blue = gradient->stops[index].color.blue;
4102 *alpha = gradient->stops[index].color.alpha;
4104 return CAIRO_STATUS_SUCCESS;
4108 * cairo_pattern_get_color_stop_count:
4109 * @pattern: a #cairo_pattern_t
4110 * @count: return value for the number of color stops, or %NULL
4112 * Gets the number of color stops specified in the given gradient
4115 * Return value: %CAIRO_STATUS_SUCCESS, or
4116 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
4122 cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
4125 cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
4127 if (pattern->status)
4128 return pattern->status;
4130 if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
4131 pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
4132 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4135 *count = gradient->n_stops;
4137 return CAIRO_STATUS_SUCCESS;
4141 * cairo_pattern_get_linear_points:
4142 * @pattern: a #cairo_pattern_t
4143 * @x0: return value for the x coordinate of the first point, or %NULL
4144 * @y0: return value for the y coordinate of the first point, or %NULL
4145 * @x1: return value for the x coordinate of the second point, or %NULL
4146 * @y1: return value for the y coordinate of the second point, or %NULL
4148 * Gets the gradient endpoints for a linear gradient.
4150 * Return value: %CAIRO_STATUS_SUCCESS, or
4151 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a linear
4157 cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
4158 double *x0, double *y0,
4159 double *x1, double *y1)
4161 cairo_linear_pattern_t *linear = (cairo_linear_pattern_t*) pattern;
4163 if (pattern->status)
4164 return pattern->status;
4166 if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR)
4167 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4170 *x0 = linear->pd1.x;
4172 *y0 = linear->pd1.y;
4174 *x1 = linear->pd2.x;
4176 *y1 = linear->pd2.y;
4178 return CAIRO_STATUS_SUCCESS;
4182 * cairo_pattern_get_radial_circles:
4183 * @pattern: a #cairo_pattern_t
4184 * @x0: return value for the x coordinate of the center of the first circle, or %NULL
4185 * @y0: return value for the y coordinate of the center of the first circle, or %NULL
4186 * @r0: return value for the radius of the first circle, or %NULL
4187 * @x1: return value for the x coordinate of the center of the second circle, or %NULL
4188 * @y1: return value for the y coordinate of the center of the second circle, or %NULL
4189 * @r1: return value for the radius of the second circle, or %NULL
4191 * Gets the gradient endpoint circles for a radial gradient, each
4192 * specified as a center coordinate and a radius.
4194 * Return value: %CAIRO_STATUS_SUCCESS, or
4195 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial
4201 cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
4202 double *x0, double *y0, double *r0,
4203 double *x1, double *y1, double *r1)
4205 cairo_radial_pattern_t *radial = (cairo_radial_pattern_t*) pattern;
4207 if (pattern->status)
4208 return pattern->status;
4210 if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
4211 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4214 *x0 = radial->cd1.center.x;
4216 *y0 = radial->cd1.center.y;
4218 *r0 = radial->cd1.radius;
4220 *x1 = radial->cd2.center.x;
4222 *y1 = radial->cd2.center.y;
4224 *r1 = radial->cd2.radius;
4226 return CAIRO_STATUS_SUCCESS;
4230 * cairo_mesh_pattern_get_patch_count:
4231 * @pattern: a #cairo_pattern_t
4232 * @count: return value for the number patches, or %NULL
4234 * Gets the number of patches specified in the given mesh pattern.
4236 * The number only includes patches which have been finished by
4237 * calling cairo_mesh_pattern_end_patch(). For example it will be 0
4238 * during the definition of the first patch.
4240 * Return value: %CAIRO_STATUS_SUCCESS, or
4241 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a mesh
4247 cairo_mesh_pattern_get_patch_count (cairo_pattern_t *pattern,
4248 unsigned int *count)
4250 cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
4252 if (unlikely (pattern->status))
4253 return pattern->status;
4255 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH))
4256 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4259 *count = _cairo_array_num_elements (&mesh->patches);
4260 if (mesh->current_patch)
4264 return CAIRO_STATUS_SUCCESS;
4266 slim_hidden_def (cairo_mesh_pattern_get_patch_count);
4269 * cairo_mesh_pattern_get_path:
4270 * @pattern: a #cairo_pattern_t
4271 * @patch_num: the patch number to return data for
4273 * Gets path defining the patch @patch_num for a mesh
4276 * @patch_num can range 0 to 1 less than the number returned by
4277 * cairo_mesh_pattern_get_patch_count().
4279 * Return value: the path defining the patch, or a path with status
4280 * %CAIRO_STATUS_INVALID_INDEX if @patch_num or @point_num is not
4281 * valid for @pattern. If @pattern is not a mesh pattern, a path with
4282 * status %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is returned.
4287 cairo_mesh_pattern_get_path (cairo_pattern_t *pattern,
4288 unsigned int patch_num)
4290 cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
4291 const cairo_mesh_patch_t *patch;
4293 cairo_path_data_t *data;
4294 unsigned int patch_count;
4295 int l, current_point;
4297 if (unlikely (pattern->status))
4298 return _cairo_path_create_in_error (pattern->status);
4300 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH))
4301 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH));
4303 patch_count = _cairo_array_num_elements (&mesh->patches);
4304 if (mesh->current_patch)
4307 if (unlikely (patch_num >= patch_count))
4308 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_INDEX));
4310 patch = _cairo_array_index_const (&mesh->patches, patch_num);
4312 path = malloc (sizeof (cairo_path_t));
4314 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
4316 path->num_data = 18;
4317 path->data = _cairo_malloc_ab (path->num_data,
4318 sizeof (cairo_path_data_t));
4319 if (path->data == NULL) {
4321 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
4325 data[0].header.type = CAIRO_PATH_MOVE_TO;
4326 data[0].header.length = 2;
4327 data[1].point.x = patch->points[0][0].x;
4328 data[1].point.y = patch->points[0][0].y;
4329 data += data[0].header.length;
4333 for (l = 0; l < 4; l++) {
4336 data[0].header.type = CAIRO_PATH_CURVE_TO;
4337 data[0].header.length = 4;
4339 for (k = 1; k < 4; k++) {
4340 current_point = (current_point + 1) % 12;
4341 i = mesh_path_point_i[current_point];
4342 j = mesh_path_point_j[current_point];
4343 data[k].point.x = patch->points[i][j].x;
4344 data[k].point.y = patch->points[i][j].y;
4347 data += data[0].header.length;
4350 path->status = CAIRO_STATUS_SUCCESS;
4354 slim_hidden_def (cairo_mesh_pattern_get_path);
4357 * cairo_mesh_pattern_get_corner_color_rgba:
4358 * @pattern: a #cairo_pattern_t
4359 * @patch_num: the patch number to return data for
4360 * @corner_num: the corner number to return data for
4361 * @red: return value for red component of color, or %NULL
4362 * @green: return value for green component of color, or %NULL
4363 * @blue: return value for blue component of color, or %NULL
4364 * @alpha: return value for alpha component of color, or %NULL
4366 * Gets the color information in corner @corner_num of patch
4367 * @patch_num for a mesh pattern.
4369 * @patch_num can range 0 to 1 less than the number returned by
4370 * cairo_mesh_pattern_get_patch_count().
4372 * Valid values for @corner_num are from 0 to 3 and identify the
4373 * corners as explained in cairo_pattern_create_mesh().
4375 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
4376 * if @patch_num or @corner_num is not valid for @pattern. If
4377 * @pattern is not a mesh pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH
4383 cairo_mesh_pattern_get_corner_color_rgba (cairo_pattern_t *pattern,
4384 unsigned int patch_num,
4385 unsigned int corner_num,
4386 double *red, double *green,
4387 double *blue, double *alpha)
4389 cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
4390 unsigned int patch_count;
4391 const cairo_mesh_patch_t *patch;
4393 if (unlikely (pattern->status))
4394 return pattern->status;
4396 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH))
4397 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4399 if (unlikely (corner_num > 3))
4400 return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4402 patch_count = _cairo_array_num_elements (&mesh->patches);
4403 if (mesh->current_patch)
4406 if (unlikely (patch_num >= patch_count))
4407 return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4409 patch = _cairo_array_index_const (&mesh->patches, patch_num);
4412 *red = patch->colors[corner_num].red;
4414 *green = patch->colors[corner_num].green;
4416 *blue = patch->colors[corner_num].blue;
4418 *alpha = patch->colors[corner_num].alpha;
4420 return CAIRO_STATUS_SUCCESS;
4422 slim_hidden_def (cairo_mesh_pattern_get_corner_color_rgba);
4425 * cairo_mesh_pattern_get_control_point:
4426 * @pattern: a #cairo_pattern_t
4427 * @patch_num: the patch number to return data for
4428 * @point_num: the control point number to return data for
4429 * @x: return value for the x coordinate of the control point, or %NULL
4430 * @y: return value for the y coordinate of the control point, or %NULL
4432 * Gets the control point @point_num of patch @patch_num for a mesh
4435 * @patch_num can range 0 to 1 less than the number returned by
4436 * cairo_mesh_pattern_get_patch_count().
4438 * Valid values for @point_num are from 0 to 3 and identify the
4439 * control points as explained in cairo_pattern_create_mesh().
4441 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
4442 * if @patch_num or @point_num is not valid for @pattern. If @pattern
4443 * is not a mesh pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
4449 cairo_mesh_pattern_get_control_point (cairo_pattern_t *pattern,
4450 unsigned int patch_num,
4451 unsigned int point_num,
4452 double *x, double *y)
4454 cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
4455 const cairo_mesh_patch_t *patch;
4456 unsigned int patch_count;
4459 if (pattern->status)
4460 return pattern->status;
4462 if (pattern->type != CAIRO_PATTERN_TYPE_MESH)
4463 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4466 return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4468 patch_count = _cairo_array_num_elements (&mesh->patches);
4469 if (mesh->current_patch)
4472 if (unlikely (patch_num >= patch_count))
4473 return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4475 patch = _cairo_array_index_const (&mesh->patches, patch_num);
4477 i = mesh_control_point_i[point_num];
4478 j = mesh_control_point_j[point_num];
4481 *x = patch->points[i][j].x;
4483 *y = patch->points[i][j].y;
4485 return CAIRO_STATUS_SUCCESS;
4487 slim_hidden_def (cairo_mesh_pattern_get_control_point);
4490 _cairo_pattern_reset_static_data (void)
4494 for (i = 0; i < ARRAY_LENGTH (freed_pattern_pool); i++)
4495 _freed_pool_reset (&freed_pattern_pool[i]);
4499 _cairo_debug_print_surface_pattern (FILE *file,
4500 const cairo_surface_pattern_t *pattern)
4502 printf (" surface type: %d\n", pattern->surface->type);
4506 _cairo_debug_print_raster_source_pattern (FILE *file,
4507 const cairo_raster_source_pattern_t *raster)
4509 printf (" content: %x, size %dx%d\n", raster->content, raster->extents.width, raster->extents.height);
4513 _cairo_debug_print_linear_pattern (FILE *file,
4514 const cairo_linear_pattern_t *pattern)
4519 _cairo_debug_print_radial_pattern (FILE *file,
4520 const cairo_radial_pattern_t *pattern)
4525 _cairo_debug_print_mesh_pattern (FILE *file,
4526 const cairo_mesh_pattern_t *pattern)
4531 _cairo_debug_print_pattern (FILE *file, const cairo_pattern_t *pattern)
4534 switch (pattern->type) {
4535 case CAIRO_PATTERN_TYPE_SOLID: s = "solid"; break;
4536 case CAIRO_PATTERN_TYPE_SURFACE: s = "surface"; break;
4537 case CAIRO_PATTERN_TYPE_LINEAR: s = "linear"; break;
4538 case CAIRO_PATTERN_TYPE_RADIAL: s = "radial"; break;
4539 case CAIRO_PATTERN_TYPE_MESH: s = "mesh"; break;
4540 case CAIRO_PATTERN_TYPE_RASTER_SOURCE: s = "raster"; break;
4541 default: s = "invalid"; ASSERT_NOT_REACHED; break;
4544 fprintf (file, "pattern: %s\n", s);
4545 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
4548 switch (pattern->extend) {
4549 case CAIRO_EXTEND_NONE: s = "none"; break;
4550 case CAIRO_EXTEND_REPEAT: s = "repeat"; break;
4551 case CAIRO_EXTEND_REFLECT: s = "reflect"; break;
4552 case CAIRO_EXTEND_PAD: s = "pad"; break;
4553 default: s = "invalid"; ASSERT_NOT_REACHED; break;
4555 fprintf (file, " extend: %s\n", s);
4557 switch (pattern->filter) {
4558 case CAIRO_FILTER_FAST: s = "fast"; break;
4559 case CAIRO_FILTER_GOOD: s = "good"; break;
4560 case CAIRO_FILTER_BEST: s = "best"; break;
4561 case CAIRO_FILTER_NEAREST: s = "nearest"; break;
4562 case CAIRO_FILTER_BILINEAR: s = "bilinear"; break;
4563 case CAIRO_FILTER_GAUSSIAN: s = "guassian"; break;
4564 default: s = "invalid"; ASSERT_NOT_REACHED; break;
4566 fprintf (file, " filter: %s\n", s);
4567 fprintf (file, " matrix: [%g %g %g %g %g %g]\n",
4568 pattern->matrix.xx, pattern->matrix.yx,
4569 pattern->matrix.xy, pattern->matrix.yy,
4570 pattern->matrix.x0, pattern->matrix.y0);
4571 switch (pattern->type) {
4573 case CAIRO_PATTERN_TYPE_SOLID:
4575 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4576 _cairo_debug_print_raster_source_pattern (file, (cairo_raster_source_pattern_t *)pattern);
4578 case CAIRO_PATTERN_TYPE_SURFACE:
4579 _cairo_debug_print_surface_pattern (file, (cairo_surface_pattern_t *)pattern);
4581 case CAIRO_PATTERN_TYPE_LINEAR:
4582 _cairo_debug_print_linear_pattern (file, (cairo_linear_pattern_t *)pattern);
4584 case CAIRO_PATTERN_TYPE_RADIAL:
4585 _cairo_debug_print_radial_pattern (file, (cairo_radial_pattern_t *)pattern);
4587 case CAIRO_PATTERN_TYPE_MESH:
4588 _cairo_debug_print_mesh_pattern (file, (cairo_mesh_pattern_t *)pattern);