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_pretransform (cairo_pattern_t
*pattern
,
2132 const cairo_matrix_t
*ctm
)
2134 if (pattern
->status
)
2137 cairo_matrix_multiply (&pattern
->matrix
, &pattern
->matrix
, ctm
);
2141 _cairo_pattern_transform (cairo_pattern_t
*pattern
,
2142 const cairo_matrix_t
*ctm_inverse
)
2144 if (pattern
->status
)
2147 cairo_matrix_multiply (&pattern
->matrix
, ctm_inverse
, &pattern
->matrix
);
2151 _linear_pattern_is_degenerate (const cairo_linear_pattern_t
*linear
)
2153 return fabs (linear
->pd1
.x
- linear
->pd2
.x
) < DBL_EPSILON
&&
2154 fabs (linear
->pd1
.y
- linear
->pd2
.y
) < DBL_EPSILON
;
2158 _radial_pattern_is_degenerate (const cairo_radial_pattern_t
*radial
)
2160 /* A radial pattern is considered degenerate if it can be
2161 * represented as a solid or clear pattern. This corresponds to
2162 * one of the two cases:
2164 * 1) The radii are both very small:
2165 * |dr| < DBL_EPSILON && min (r0, r1) < DBL_EPSILON
2167 * 2) The two circles have about the same radius and are very
2168 * close to each other (approximately a cylinder gradient that
2169 * doesn't move with the parameter):
2170 * |dr| < DBL_EPSILON && max (|dx|, |dy|) < 2 * DBL_EPSILON
2172 * These checks are consistent with the assumptions used in
2173 * _cairo_radial_pattern_box_to_parameter ().
2176 return fabs (radial
->cd1
.radius
- radial
->cd2
.radius
) < DBL_EPSILON
&&
2177 (MIN (radial
->cd1
.radius
, radial
->cd2
.radius
) < DBL_EPSILON
||
2178 MAX (fabs (radial
->cd1
.center
.x
- radial
->cd2
.center
.x
),
2179 fabs (radial
->cd1
.center
.y
- radial
->cd2
.center
.y
)) < 2 * DBL_EPSILON
);
2183 _cairo_linear_pattern_box_to_parameter (const cairo_linear_pattern_t
*linear
,
2184 double x0
, double y0
,
2185 double x1
, double y1
,
2188 double t0
, tdx
, tdy
;
2189 double p1x
, p1y
, pdx
, pdy
, invsqnorm
;
2191 assert (! _linear_pattern_is_degenerate (linear
));
2194 * Linear gradients are othrogonal to the line passing through
2195 * their extremes. Because of convexity, the parameter range can
2196 * be computed as the convex hull (one the real line) of the
2197 * parameter values of the 4 corners of the box.
2199 * The parameter value t for a point (x,y) can be computed as:
2201 * t = (p2 - p1) . (x,y) / |p2 - p1|^2
2203 * t0 is the t value for the top left corner
2204 * tdx is the difference between left and right corners
2205 * tdy is the difference between top and bottom corners
2208 p1x
= linear
->pd1
.x
;
2209 p1y
= linear
->pd1
.y
;
2210 pdx
= linear
->pd2
.x
- p1x
;
2211 pdy
= linear
->pd2
.y
- p1y
;
2212 invsqnorm
= 1.0 / (pdx
* pdx
+ pdy
* pdy
);
2216 t0
= (x0
- p1x
) * pdx
+ (y0
- p1y
) * pdy
;
2217 tdx
= (x1
- x0
) * pdx
;
2218 tdy
= (y1
- y0
) * pdy
;
2221 * Because of the linearity of the t value, tdx can simply be
2222 * added the t0 to move along the top edge. After this, range[0]
2223 * and range[1] represent the parameter range for the top edge, so
2224 * extending it to include the whole box simply requires adding
2225 * tdy to the correct extreme.
2228 range
[0] = range
[1] = t0
;
2241 _extend_range (double range
[2], double value
, cairo_bool_t valid
)
2244 range
[0] = range
[1] = value
;
2245 else if (value
< range
[0])
2247 else if (value
> range
[1])
2254 * _cairo_radial_pattern_focus_is_inside:
2256 * Returns %TRUE if and only if the focus point exists and is
2257 * contained in one of the two extreme circles. This condition is
2258 * equivalent to one of the two extreme circles being completely
2259 * contained in the other one.
2261 * Note: if the focus is on the border of one of the two circles (in
2262 * which case the circles are tangent in the focus point), it is not
2263 * considered as contained in the circle, hence this function returns
2268 _cairo_radial_pattern_focus_is_inside (const cairo_radial_pattern_t
*radial
)
2270 double cx
, cy
, cr
, dx
, dy
, dr
;
2272 cx
= radial
->cd1
.center
.x
;
2273 cy
= radial
->cd1
.center
.y
;
2274 cr
= radial
->cd1
.radius
;
2275 dx
= radial
->cd2
.center
.x
- cx
;
2276 dy
= radial
->cd2
.center
.y
- cy
;
2277 dr
= radial
->cd2
.radius
- cr
;
2279 return dx
*dx
+ dy
*dy
< dr
*dr
;
2283 _cairo_radial_pattern_box_to_parameter (const cairo_radial_pattern_t
*radial
,
2284 double x0
, double y0
,
2285 double x1
, double y1
,
2289 double cx
, cy
, cr
, dx
, dy
, dr
;
2290 double a
, x_focus
, y_focus
;
2291 double mindr
, minx
, miny
, maxx
, maxy
;
2294 assert (! _radial_pattern_is_degenerate (radial
));
2298 tolerance
= MAX (tolerance
, DBL_EPSILON
);
2300 range
[0] = range
[1] = 0;
2303 x_focus
= y_focus
= 0; /* silence gcc */
2305 cx
= radial
->cd1
.center
.x
;
2306 cy
= radial
->cd1
.center
.y
;
2307 cr
= radial
->cd1
.radius
;
2308 dx
= radial
->cd2
.center
.x
- cx
;
2309 dy
= radial
->cd2
.center
.y
- cy
;
2310 dr
= radial
->cd2
.radius
- cr
;
2312 /* translate by -(cx, cy) to simplify computations */
2318 /* enlarge boundaries slightly to avoid rounding problems in the
2319 * parameter range computation */
2325 /* enlarge boundaries even more to avoid rounding problems when
2326 * testing if a point belongs to the box */
2327 minx
= x0
- DBL_EPSILON
;
2328 miny
= y0
- DBL_EPSILON
;
2329 maxx
= x1
+ DBL_EPSILON
;
2330 maxy
= y1
+ DBL_EPSILON
;
2332 /* we dont' allow negative radiuses, so we will be checking that
2333 * t*dr >= mindr to consider t valid */
2334 mindr
= -(cr
+ DBL_EPSILON
);
2337 * After the previous transformations, the start circle is
2338 * centered in the origin and has radius cr. A 1-unit change in
2339 * the t parameter corresponds to dx,dy,dr changes in the x,y,r of
2340 * the circle (center coordinates, radius).
2342 * To compute the minimum range needed to correctly draw the
2343 * pattern, we start with an empty range and extend it to include
2344 * the circles touching the bounding box or within it.
2348 * Focus, the point where the circle has radius == 0.
2350 * r = cr + t * dr = 0
2353 * If the radius is constant (dr == 0) there is no focus (the
2354 * gradient represents a cylinder instead of a cone).
2356 if (fabs (dr
) >= DBL_EPSILON
) {
2360 x_focus
= t_focus
* dx
;
2361 y_focus
= t_focus
* dy
;
2362 if (minx
<= x_focus
&& x_focus
<= maxx
&&
2363 miny
<= y_focus
&& y_focus
<= maxy
)
2365 valid
= _extend_range (range
, t_focus
, valid
);
2370 * Circles externally tangent to box edges.
2372 * All circles have center in (dx, dy) * t
2374 * If the circle is tangent to the line defined by the edge of the
2375 * box, then at least one of the following holds true:
2377 * (dx*t) + (cr + dr*t) == x0 (left edge)
2378 * (dx*t) - (cr + dr*t) == x1 (right edge)
2379 * (dy*t) + (cr + dr*t) == y0 (top edge)
2380 * (dy*t) - (cr + dr*t) == y1 (bottom edge)
2382 * The solution is only valid if the tangent point is actually on
2383 * the edge, i.e. if its y coordinate is in [y0,y1] for left/right
2384 * edges and if its x coordinate is in [x0,x1] for top/bottom
2387 * For the first equation:
2389 * (dx + dr) * t = x0 - cr
2390 * t = (x0 - cr) / (dx + dr)
2393 * in the code this becomes:
2395 * t_edge = (num) / (den)
2396 * v = (delta) * t_edge
2398 * If the denominator in t is 0, the pattern is tangent to a line
2399 * parallel to the edge under examination. The corner-case where
2400 * the boundary line is the same as the edge is handled by the
2401 * focus point case and/or by the a==0 case.
2403 #define T_EDGE(num,den,delta,lower,upper) \
2404 if (fabs (den) >= DBL_EPSILON) { \
2407 t_edge = (num) / (den); \
2408 v = t_edge * (delta); \
2409 if (t_edge * dr >= mindr && (lower) <= v && v <= (upper)) \
2410 valid = _extend_range (range, t_edge, valid); \
2413 /* circles tangent (externally) to left/right/top/bottom edge */
2414 T_EDGE (x0
- cr
, dx
+ dr
, dy
, miny
, maxy
);
2415 T_EDGE (x1
+ cr
, dx
- dr
, dy
, miny
, maxy
);
2416 T_EDGE (y0
- cr
, dy
+ dr
, dx
, minx
, maxx
);
2417 T_EDGE (y1
+ cr
, dy
- dr
, dx
, minx
, maxx
);
2422 * Circles passing through a corner.
2424 * A circle passing through the point (x,y) satisfies:
2426 * (x-t*dx)^2 + (y-t*dy)^2 == (cr + t*dr)^2
2429 * a = dx^2 + dy^2 - dr^2
2430 * b = x*dx + y*dy + cr*dr
2431 * c = x^2 + y^2 - cr^2
2433 * a*t^2 - 2*b*t + c == 0
2435 a
= dx
* dx
+ dy
* dy
- dr
* dr
;
2436 if (fabs (a
) < DBL_EPSILON
* DBL_EPSILON
) {
2439 /* Ensure that gradients with both a and dr small are
2440 * considered degenerate.
2441 * The floating point version of the degeneracy test implemented
2442 * in _radial_pattern_is_degenerate() is:
2444 * 1) The circles are practically the same size:
2445 * |dr| < DBL_EPSILON
2447 * 2a) The circles are both very small:
2448 * min (r0, r1) < DBL_EPSILON
2450 * 2b) The circles are very close to each other:
2451 * max (|dx|, |dy|) < 2 * DBL_EPSILON
2453 * Assuming that the gradient is not degenerate, we want to
2454 * show that |a| < DBL_EPSILON^2 implies |dr| >= DBL_EPSILON.
2456 * If the gradient is not degenerate yet it has |dr| <
2457 * DBL_EPSILON, (2b) is false, thus:
2459 * max (|dx|, |dy|) >= 2*DBL_EPSILON
2461 * 4*DBL_EPSILON^2 <= max (|dx|, |dy|)^2 <= dx^2 + dy^2
2463 * From the definition of a, we get:
2464 * a = dx^2 + dy^2 - dr^2 < DBL_EPSILON^2
2465 * dx^2 + dy^2 - DBL_EPSILON^2 < dr^2
2466 * 3*DBL_EPSILON^2 < dr^2
2468 * which is inconsistent with the hypotheses, thus |dr| <
2469 * DBL_EPSILON is false or the gradient is degenerate.
2471 assert (fabs (dr
) >= DBL_EPSILON
);
2474 * If a == 0, all the circles are tangent to a line in the
2475 * focus point. If this line is within the box extents, we
2476 * should add the circle with infinite radius, but this would
2477 * make the range unbounded, so we add the smallest circle whose
2478 * distance to the desired (degenerate) circle within the
2479 * bounding box does not exceed tolerance.
2481 * The equation of the line is b==0, i.e.:
2482 * x*dx + y*dy + cr*dr == 0
2484 * We compute the intersection of the line with the box and
2485 * keep the intersection with maximum square distance (maxd2)
2486 * from the focus point.
2488 * In the code the intersection is represented in another
2489 * coordinate system, whose origin is the focus point and
2490 * which has a u,v axes, which are respectively orthogonal and
2491 * parallel to the edge being intersected.
2493 * The intersection is valid only if it belongs to the box,
2494 * otherwise it is ignored.
2499 * x*dx + y0*dy + cr*dr == 0
2500 * x = -(y0*dy + cr*dr) / dx
2502 * which in (u,v) is:
2504 * v = -(y0*dy + cr*dr) / dx - x_focus
2507 * u = (edge) - (u_origin)
2508 * v = -((edge) * (delta) + cr*dr) / (den) - v_focus
2510 #define T_EDGE(edge,delta,den,lower,upper,u_origin,v_origin) \
2511 if (fabs (den) >= DBL_EPSILON) { \
2514 v = -((edge) * (delta) + cr * dr) / (den); \
2515 if ((lower) <= v && v <= (upper)) { \
2518 u = (edge) - (u_origin); \
2528 /* degenerate circles (lines) passing through each edge */
2529 T_EDGE (y0
, dy
, dx
, minx
, maxx
, y_focus
, x_focus
);
2530 T_EDGE (y1
, dy
, dx
, minx
, maxx
, y_focus
, x_focus
);
2531 T_EDGE (x0
, dx
, dy
, miny
, maxy
, x_focus
, y_focus
);
2532 T_EDGE (x1
, dx
, dy
, miny
, maxy
, x_focus
, y_focus
);
2537 * The limit circle can be transformed rigidly to the y=0 line
2538 * and the circles tangent to it in (0,0) are:
2540 * x^2 + (y-r)^2 = r^2 <=> x^2 + y^2 - 2*y*r = 0
2542 * y is the distance from the line, in our case tolerance;
2543 * x is the distance along the line, i.e. sqrt(maxd2),
2546 * r = cr + dr * t = (maxd2 + tolerance^2) / (2*tolerance)
2547 * t = (r - cr) / dr =
2548 * (maxd2 + tolerance^2 - 2*tolerance*cr) / (2*tolerance*dr)
2551 double t_limit
= maxd2
+ tolerance
*tolerance
- 2*tolerance
*cr
;
2552 t_limit
/= 2 * tolerance
* dr
;
2553 valid
= _extend_range (range
, t_limit
, valid
);
2557 * Nondegenerate, nonlimit circles passing through the corners.
2559 * a == 0 && a*t^2 - 2*b*t + c == 0
2563 * The b == 0 case has just been handled, so we only have to
2564 * compute this if b != 0.
2566 #define T_CORNER(x,y) \
2567 b = (x) * dx + (y) * dy + cr * dr; \
2568 if (fabs (b) >= DBL_EPSILON) { \
2570 double x2 = (x) * (x); \
2571 double y2 = (y) * (y); \
2572 double cr2 = (cr) * (cr); \
2573 double c = x2 + y2 - cr2; \
2575 t_corner = 0.5 * c / b; \
2576 if (t_corner * dr >= mindr) \
2577 valid = _extend_range (range, t_corner, valid); \
2580 /* circles touching each corner */
2588 double inva
, b
, c
, d
;
2593 * Nondegenerate, nonlimit circles passing through the corners.
2595 * a != 0 && a*t^2 - 2*b*t + c == 0
2597 * t = (b +- sqrt (b*b - a*c)) / a
2599 * If the argument of sqrt() is negative, then no circle
2600 * passes through the corner.
2602 #define T_CORNER(x,y) \
2603 b = (x) * dx + (y) * dy + cr * dr; \
2604 c = (x) * (x) + (y) * (y) - cr * cr; \
2605 d = b * b - a * c; \
2610 t_corner = (b + d) * inva; \
2611 if (t_corner * dr >= mindr) \
2612 valid = _extend_range (range, t_corner, valid); \
2613 t_corner = (b - d) * inva; \
2614 if (t_corner * dr >= mindr) \
2615 valid = _extend_range (range, t_corner, valid); \
2618 /* circles touching each corner */
2629 * _cairo_gradient_pattern_box_to_parameter:
2631 * Compute a interpolation range sufficient to draw (within the given
2632 * tolerance) the gradient in the given box getting the same result as
2633 * using the (-inf, +inf) range.
2635 * Assumes that the pattern is not degenerate. This can be guaranteed
2636 * by simplifying it to a solid clear if _cairo_pattern_is_clear or to
2637 * a solid color if _cairo_gradient_pattern_is_solid.
2639 * The range isn't guaranteed to be minimal, but it tries to.
2642 _cairo_gradient_pattern_box_to_parameter (const cairo_gradient_pattern_t
*gradient
,
2643 double x0
, double y0
,
2644 double x1
, double y1
,
2646 double out_range
[2])
2648 assert (gradient
->base
.type
== CAIRO_PATTERN_TYPE_LINEAR
||
2649 gradient
->base
.type
== CAIRO_PATTERN_TYPE_RADIAL
);
2651 if (gradient
->base
.type
== CAIRO_PATTERN_TYPE_LINEAR
) {
2652 _cairo_linear_pattern_box_to_parameter ((cairo_linear_pattern_t
*) gradient
,
2653 x0
, y0
, x1
, y1
, out_range
);
2655 _cairo_radial_pattern_box_to_parameter ((cairo_radial_pattern_t
*) gradient
,
2656 x0
, y0
, x1
, y1
, tolerance
, out_range
);
2661 * _cairo_gradient_pattern_interpolate:
2663 * Interpolate between the start and end objects of linear or radial
2664 * gradients. The interpolated object is stored in out_circle, with
2665 * the radius being zero in the linear gradient case.
2668 _cairo_gradient_pattern_interpolate (const cairo_gradient_pattern_t
*gradient
,
2670 cairo_circle_double_t
*out_circle
)
2672 assert (gradient
->base
.type
== CAIRO_PATTERN_TYPE_LINEAR
||
2673 gradient
->base
.type
== CAIRO_PATTERN_TYPE_RADIAL
);
2675 #define lerp(a,b) (a)*(1-t) + (b)*t
2677 if (gradient
->base
.type
== CAIRO_PATTERN_TYPE_LINEAR
) {
2678 cairo_linear_pattern_t
*linear
= (cairo_linear_pattern_t
*) gradient
;
2679 out_circle
->center
.x
= lerp (linear
->pd1
.x
, linear
->pd2
.x
);
2680 out_circle
->center
.y
= lerp (linear
->pd1
.y
, linear
->pd2
.y
);
2681 out_circle
->radius
= 0;
2683 cairo_radial_pattern_t
*radial
= (cairo_radial_pattern_t
*) gradient
;
2684 out_circle
->center
.x
= lerp (radial
->cd1
.center
.x
, radial
->cd2
.center
.x
);
2685 out_circle
->center
.y
= lerp (radial
->cd1
.center
.y
, radial
->cd2
.center
.y
);
2686 out_circle
->radius
= lerp (radial
->cd1
.radius
, radial
->cd2
.radius
);
2694 * _cairo_gradient_pattern_fit_to_range:
2696 * Scale the extremes of a gradient to guarantee that the coordinates
2697 * and their deltas are within the range (-max_value, max_value). The
2698 * new extremes are stored in out_circle.
2700 * The pattern matrix is scaled to guarantee that the aspect of the
2701 * gradient is the same and the result is stored in out_matrix.
2705 _cairo_gradient_pattern_fit_to_range (const cairo_gradient_pattern_t
*gradient
,
2707 cairo_matrix_t
*out_matrix
,
2708 cairo_circle_double_t out_circle
[2])
2712 assert (gradient
->base
.type
== CAIRO_PATTERN_TYPE_LINEAR
||
2713 gradient
->base
.type
== CAIRO_PATTERN_TYPE_RADIAL
);
2715 if (gradient
->base
.type
== CAIRO_PATTERN_TYPE_LINEAR
) {
2716 cairo_linear_pattern_t
*linear
= (cairo_linear_pattern_t
*) gradient
;
2718 out_circle
[0].center
= linear
->pd1
;
2719 out_circle
[0].radius
= 0;
2720 out_circle
[1].center
= linear
->pd2
;
2721 out_circle
[1].radius
= 0;
2723 dim
= fabs (linear
->pd1
.x
);
2724 dim
= MAX (dim
, fabs (linear
->pd1
.y
));
2725 dim
= MAX (dim
, fabs (linear
->pd2
.x
));
2726 dim
= MAX (dim
, fabs (linear
->pd2
.y
));
2727 dim
= MAX (dim
, fabs (linear
->pd1
.x
- linear
->pd2
.x
));
2728 dim
= MAX (dim
, fabs (linear
->pd1
.y
- linear
->pd2
.y
));
2730 cairo_radial_pattern_t
*radial
= (cairo_radial_pattern_t
*) gradient
;
2732 out_circle
[0] = radial
->cd1
;
2733 out_circle
[1] = radial
->cd2
;
2735 dim
= fabs (radial
->cd1
.center
.x
);
2736 dim
= MAX (dim
, fabs (radial
->cd1
.center
.y
));
2737 dim
= MAX (dim
, fabs (radial
->cd1
.radius
));
2738 dim
= MAX (dim
, fabs (radial
->cd2
.center
.x
));
2739 dim
= MAX (dim
, fabs (radial
->cd2
.center
.y
));
2740 dim
= MAX (dim
, fabs (radial
->cd2
.radius
));
2741 dim
= MAX (dim
, fabs (radial
->cd1
.center
.x
- radial
->cd2
.center
.x
));
2742 dim
= MAX (dim
, fabs (radial
->cd1
.center
.y
- radial
->cd2
.center
.y
));
2743 dim
= MAX (dim
, fabs (radial
->cd1
.radius
- radial
->cd2
.radius
));
2746 if (unlikely (dim
> max_value
)) {
2747 cairo_matrix_t scale
;
2749 dim
= max_value
/ dim
;
2751 out_circle
[0].center
.x
*= dim
;
2752 out_circle
[0].center
.y
*= dim
;
2753 out_circle
[0].radius
*= dim
;
2754 out_circle
[1].center
.x
*= dim
;
2755 out_circle
[1].center
.y
*= dim
;
2756 out_circle
[1].radius
*= dim
;
2758 cairo_matrix_init_scale (&scale
, dim
, dim
);
2759 cairo_matrix_multiply (out_matrix
, &gradient
->base
.matrix
, &scale
);
2761 *out_matrix
= gradient
->base
.matrix
;
2766 _gradient_is_clear (const cairo_gradient_pattern_t
*gradient
,
2767 const cairo_rectangle_int_t
*extents
)
2771 assert (gradient
->base
.type
== CAIRO_PATTERN_TYPE_LINEAR
||
2772 gradient
->base
.type
== CAIRO_PATTERN_TYPE_RADIAL
);
2774 if (gradient
->n_stops
== 0 ||
2775 (gradient
->base
.extend
== CAIRO_EXTEND_NONE
&&
2776 gradient
->stops
[0].offset
== gradient
->stops
[gradient
->n_stops
- 1].offset
))
2779 if (gradient
->base
.type
== CAIRO_PATTERN_TYPE_RADIAL
) {
2780 /* degenerate radial gradients are clear */
2781 if (_radial_pattern_is_degenerate ((cairo_radial_pattern_t
*) gradient
))
2783 } else if (gradient
->base
.extend
== CAIRO_EXTEND_NONE
) {
2784 /* EXTEND_NONE degenerate linear gradients are clear */
2785 if (_linear_pattern_is_degenerate ((cairo_linear_pattern_t
*) gradient
))
2789 /* Check if the extents intersect the drawn part of the pattern. */
2790 if (extents
!= NULL
&&
2791 (gradient
->base
.extend
== CAIRO_EXTEND_NONE
||
2792 gradient
->base
.type
== CAIRO_PATTERN_TYPE_RADIAL
))
2796 _cairo_gradient_pattern_box_to_parameter (gradient
,
2799 extents
->x
+ extents
->width
,
2800 extents
->y
+ extents
->height
,
2804 if (gradient
->base
.extend
== CAIRO_EXTEND_NONE
&&
2805 (t
[0] >= gradient
->stops
[gradient
->n_stops
- 1].offset
||
2806 t
[1] <= gradient
->stops
[0].offset
))
2815 for (i
= 0; i
< gradient
->n_stops
; i
++)
2816 if (! CAIRO_COLOR_IS_CLEAR (&gradient
->stops
[i
].color
))
2823 _gradient_color_average (const cairo_gradient_pattern_t
*gradient
,
2824 cairo_color_t
*color
)
2826 double delta0
, delta1
;
2828 unsigned int i
, start
= 1, end
;
2830 assert (gradient
->n_stops
> 0);
2831 assert (gradient
->base
.extend
!= CAIRO_EXTEND_NONE
);
2833 if (gradient
->n_stops
== 1) {
2834 _cairo_color_init_rgba (color
,
2835 gradient
->stops
[0].color
.red
,
2836 gradient
->stops
[0].color
.green
,
2837 gradient
->stops
[0].color
.blue
,
2838 gradient
->stops
[0].color
.alpha
);
2842 end
= gradient
->n_stops
- 1;
2844 switch (gradient
->base
.extend
) {
2845 case CAIRO_EXTEND_REPEAT
:
2847 * Sa, Sb and Sy, Sz are the first two and last two stops respectively.
2848 * The weight of the first and last stop can be computed as the area of
2849 * the following triangles (taken with height 1, since the whole [0-1]
2850 * will have total weight 1 this way): b*h/2
2856 * ~~~~~+---+---+---+~~~~~~~+-------+---+---+~~~~~
2857 * -1+Sz 0 Sa Sb Sy Sz 1 1+Sa
2859 * For the first stop: (Sb-(-1+Sz)/2 = (1+Sb-Sz)/2
2860 * For the last stop: ((1+Sa)-Sy)/2 = (1+Sa-Sy)/2
2861 * Halving the result is done after summing up all the areas.
2863 delta0
= 1.0 + gradient
->stops
[1].offset
- gradient
->stops
[end
].offset
;
2864 delta1
= 1.0 + gradient
->stops
[0].offset
- gradient
->stops
[end
-1].offset
;
2867 case CAIRO_EXTEND_REFLECT
:
2869 * Sa, Sb and Sy, Sz are the first two and last two stops respectively.
2870 * The weight of the first and last stop can be computed as the area of
2871 * the following trapezoids (taken with height 1, since the whole [0-1]
2872 * will have total weight 1 this way): (b+B)*h/2
2878 * +-------+---+~~~~~~~+-------+---+
2881 * For the first stop: (Sa+Sb)/2
2882 * For the last stop: ((1-Sz) + (1-Sy))/2 = (2-Sy-Sz)/2
2883 * Halving the result is done after summing up all the areas.
2885 delta0
= gradient
->stops
[0].offset
+ gradient
->stops
[1].offset
;
2886 delta1
= 2.0 - gradient
->stops
[end
-1].offset
- gradient
->stops
[end
].offset
;
2889 case CAIRO_EXTEND_PAD
:
2890 /* PAD is computed as the average of the first and last stop:
2891 * - take both of them with weight 1 (they will be halved
2892 * after the whole sum has been computed).
2893 * - avoid summing any of the inner stops.
2895 delta0
= delta1
= 1.0;
2899 case CAIRO_EXTEND_NONE
:
2902 _cairo_color_init_rgba (color
, 0, 0, 0, 0);
2906 r
= delta0
* gradient
->stops
[0].color
.red
;
2907 g
= delta0
* gradient
->stops
[0].color
.green
;
2908 b
= delta0
* gradient
->stops
[0].color
.blue
;
2909 a
= delta0
* gradient
->stops
[0].color
.alpha
;
2911 for (i
= start
; i
< end
; ++i
) {
2912 /* Inner stops weight is the same as the area of the triangle they influence
2913 * (which goes from the stop before to the stop after), again with height 1
2914 * since the whole must sum up to 1: b*h/2
2915 * Halving is done after the whole sum has been computed.
2917 double delta
= gradient
->stops
[i
+1].offset
- gradient
->stops
[i
-1].offset
;
2918 r
+= delta
* gradient
->stops
[i
].color
.red
;
2919 g
+= delta
* gradient
->stops
[i
].color
.green
;
2920 b
+= delta
* gradient
->stops
[i
].color
.blue
;
2921 a
+= delta
* gradient
->stops
[i
].color
.alpha
;
2924 r
+= delta1
* gradient
->stops
[end
].color
.red
;
2925 g
+= delta1
* gradient
->stops
[end
].color
.green
;
2926 b
+= delta1
* gradient
->stops
[end
].color
.blue
;
2927 a
+= delta1
* gradient
->stops
[end
].color
.alpha
;
2929 _cairo_color_init_rgba (color
, r
* .5, g
* .5, b
* .5, a
* .5);
2933 * _cairo_pattern_alpha_range:
2935 * Convenience function to determine the minimum and maximum alpha in
2936 * the drawn part of a pattern (i.e. ignoring clear parts caused by
2937 * extend modes and/or pattern shape).
2939 * If not NULL, out_min and out_max will be set respectively to the
2940 * minimum and maximum alpha value of the pattern.
2943 _cairo_pattern_alpha_range (const cairo_pattern_t
*pattern
,
2947 double alpha_min
, alpha_max
;
2949 switch (pattern
->type
) {
2950 case CAIRO_PATTERN_TYPE_SOLID
: {
2951 const cairo_solid_pattern_t
*solid
= (cairo_solid_pattern_t
*) pattern
;
2952 alpha_min
= alpha_max
= solid
->color
.alpha
;
2956 case CAIRO_PATTERN_TYPE_LINEAR
:
2957 case CAIRO_PATTERN_TYPE_RADIAL
: {
2958 const cairo_gradient_pattern_t
*gradient
= (cairo_gradient_pattern_t
*) pattern
;
2961 assert (gradient
->n_stops
>= 1);
2963 alpha_min
= alpha_max
= gradient
->stops
[0].color
.alpha
;
2964 for (i
= 1; i
< gradient
->n_stops
; i
++) {
2965 if (alpha_min
> gradient
->stops
[i
].color
.alpha
)
2966 alpha_min
= gradient
->stops
[i
].color
.alpha
;
2967 else if (alpha_max
< gradient
->stops
[i
].color
.alpha
)
2968 alpha_max
= gradient
->stops
[i
].color
.alpha
;
2974 case CAIRO_PATTERN_TYPE_MESH
: {
2975 const cairo_mesh_pattern_t
*mesh
= (const cairo_mesh_pattern_t
*) pattern
;
2976 const cairo_mesh_patch_t
*patch
= _cairo_array_index_const (&mesh
->patches
, 0);
2977 unsigned int i
, j
, n
= _cairo_array_num_elements (&mesh
->patches
);
2981 alpha_min
= alpha_max
= patch
[0].colors
[0].alpha
;
2982 for (i
= 0; i
< n
; i
++) {
2983 for (j
= 0; j
< 4; j
++) {
2984 if (patch
[i
].colors
[j
].alpha
< alpha_min
)
2985 alpha_min
= patch
[i
].colors
[j
].alpha
;
2986 else if (patch
[i
].colors
[j
].alpha
> alpha_max
)
2987 alpha_max
= patch
[i
].colors
[j
].alpha
;
2998 case CAIRO_PATTERN_TYPE_SURFACE
:
2999 case CAIRO_PATTERN_TYPE_RASTER_SOURCE
:
3006 *out_min
= alpha_min
;
3008 *out_max
= alpha_max
;
3012 * _cairo_mesh_pattern_coord_box:
3014 * Convenience function to determine the range of the coordinates of
3015 * the points used to define the patches of the mesh.
3017 * This is guaranteed to contain the pattern extents, but might not be
3018 * tight, just like a Bezier curve is always inside the convex hull of
3019 * the control points.
3021 * This function cannot be used while the mesh is being constructed.
3023 * The function returns TRUE and sets the output parametes to define
3024 * the coodrinate range if the mesh pattern contains at least one
3025 * patch, otherwise it returns FALSE.
3028 _cairo_mesh_pattern_coord_box (const cairo_mesh_pattern_t
*mesh
,
3034 const cairo_mesh_patch_t
*patch
;
3035 unsigned int num_patches
, i
, j
, k
;
3036 double x0
, y0
, x1
, y1
;
3038 assert (mesh
->current_patch
== NULL
);
3040 num_patches
= _cairo_array_num_elements (&mesh
->patches
);
3042 if (num_patches
== 0)
3045 patch
= _cairo_array_index_const (&mesh
->patches
, 0);
3046 x0
= x1
= patch
->points
[0][0].x
;
3047 y0
= y1
= patch
->points
[0][0].y
;
3049 for (i
= 0; i
< num_patches
; i
++) {
3050 for (j
= 0; j
< 4; j
++) {
3051 for (k
= 0; k
< 4; k
++) {
3052 x0
= MIN (x0
, patch
[i
].points
[j
][k
].x
);
3053 y0
= MIN (y0
, patch
[i
].points
[j
][k
].y
);
3054 x1
= MAX (x1
, patch
[i
].points
[j
][k
].x
);
3055 y1
= MAX (y1
, patch
[i
].points
[j
][k
].y
);
3069 * _cairo_gradient_pattern_is_solid:
3071 * Convenience function to determine whether a gradient pattern is
3072 * a solid color within the given extents. In this case the color
3073 * argument is initialized to the color the pattern represents.
3074 * This functions doesn't handle completely transparent gradients,
3075 * thus it should be called only after _cairo_pattern_is_clear has
3078 * Return value: %TRUE if the pattern is a solid color.
3081 _cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t
*gradient
,
3082 const cairo_rectangle_int_t
*extents
,
3083 cairo_color_t
*color
)
3087 assert (gradient
->base
.type
== CAIRO_PATTERN_TYPE_LINEAR
||
3088 gradient
->base
.type
== CAIRO_PATTERN_TYPE_RADIAL
);
3091 if (gradient
->base
.type
== CAIRO_PATTERN_TYPE_LINEAR
) {
3092 cairo_linear_pattern_t
*linear
= (cairo_linear_pattern_t
*) gradient
;
3093 if (_linear_pattern_is_degenerate (linear
)) {
3094 _gradient_color_average (gradient
, color
);
3098 if (gradient
->base
.extend
== CAIRO_EXTEND_NONE
) {
3101 /* We already know that the pattern is not clear, thus if some
3102 * part of it is clear, the whole is not solid.
3105 if (extents
== NULL
)
3108 _cairo_linear_pattern_box_to_parameter (linear
,
3111 extents
->x
+ extents
->width
,
3112 extents
->y
+ extents
->height
,
3115 if (t
[0] < 0.0 || t
[1] > 1.0)
3121 for (i
= 1; i
< gradient
->n_stops
; i
++)
3122 if (! _cairo_color_stop_equal (&gradient
->stops
[0].color
,
3123 &gradient
->stops
[i
].color
))
3126 _cairo_color_init_rgba (color
,
3127 gradient
->stops
[0].color
.red
,
3128 gradient
->stops
[0].color
.green
,
3129 gradient
->stops
[0].color
.blue
,
3130 gradient
->stops
[0].color
.alpha
);
3136 _mesh_is_clear (const cairo_mesh_pattern_t
*mesh
)
3138 double x1
, y1
, x2
, y2
;
3139 cairo_bool_t is_valid
;
3141 is_valid
= _cairo_mesh_pattern_coord_box (mesh
, &x1
, &y1
, &x2
, &y2
);
3145 if (x2
- x1
< DBL_EPSILON
|| y2
- y1
< DBL_EPSILON
)
3152 * _cairo_pattern_is_opaque_solid:
3154 * Convenience function to determine whether a pattern is an opaque
3155 * (alpha==1.0) solid color pattern. This is done by testing whether
3156 * the pattern's alpha value when converted to a byte is 255, so if a
3157 * backend actually supported deep alpha channels this function might
3158 * not do the right thing.
3160 * Return value: %TRUE if the pattern is an opaque, solid color.
3163 _cairo_pattern_is_opaque_solid (const cairo_pattern_t
*pattern
)
3165 cairo_solid_pattern_t
*solid
;
3167 if (pattern
->type
!= CAIRO_PATTERN_TYPE_SOLID
)
3170 solid
= (cairo_solid_pattern_t
*) pattern
;
3172 return CAIRO_COLOR_IS_OPAQUE (&solid
->color
);
3176 _surface_is_opaque (const cairo_surface_pattern_t
*pattern
,
3177 const cairo_rectangle_int_t
*sample
)
3179 cairo_rectangle_int_t extents
;
3181 if (pattern
->surface
->content
& CAIRO_CONTENT_ALPHA
)
3184 if (pattern
->base
.extend
!= CAIRO_EXTEND_NONE
)
3187 if (! _cairo_surface_get_extents (pattern
->surface
, &extents
))
3193 return _cairo_rectangle_contains_rectangle (&extents
, sample
);
3197 _raster_source_is_opaque (const cairo_raster_source_pattern_t
*pattern
,
3198 const cairo_rectangle_int_t
*sample
)
3200 if (pattern
->content
& CAIRO_CONTENT_ALPHA
)
3203 if (pattern
->base
.extend
!= CAIRO_EXTEND_NONE
)
3209 return _cairo_rectangle_contains_rectangle (&pattern
->extents
, sample
);
3213 _surface_is_clear (const cairo_surface_pattern_t
*pattern
)
3215 cairo_rectangle_int_t extents
;
3217 if (_cairo_surface_get_extents (pattern
->surface
, &extents
) &&
3218 (extents
.width
== 0 || extents
.height
== 0))
3221 return pattern
->surface
->is_clear
&&
3222 pattern
->surface
->content
& CAIRO_CONTENT_ALPHA
;
3226 _raster_source_is_clear (const cairo_raster_source_pattern_t
*pattern
)
3228 return pattern
->extents
.width
== 0 || pattern
->extents
.height
== 0;
3232 _gradient_is_opaque (const cairo_gradient_pattern_t
*gradient
,
3233 const cairo_rectangle_int_t
*sample
)
3237 assert (gradient
->base
.type
== CAIRO_PATTERN_TYPE_LINEAR
||
3238 gradient
->base
.type
== CAIRO_PATTERN_TYPE_RADIAL
);
3240 if (gradient
->n_stops
== 0 ||
3241 (gradient
->base
.extend
== CAIRO_EXTEND_NONE
&&
3242 gradient
->stops
[0].offset
== gradient
->stops
[gradient
->n_stops
- 1].offset
))
3245 if (gradient
->base
.type
== CAIRO_PATTERN_TYPE_LINEAR
) {
3246 if (gradient
->base
.extend
== CAIRO_EXTEND_NONE
) {
3248 cairo_linear_pattern_t
*linear
= (cairo_linear_pattern_t
*) gradient
;
3250 /* EXTEND_NONE degenerate radial gradients are clear */
3251 if (_linear_pattern_is_degenerate (linear
))
3257 _cairo_linear_pattern_box_to_parameter (linear
,
3260 sample
->x
+ sample
->width
,
3261 sample
->y
+ sample
->height
,
3264 if (t
[0] < 0.0 || t
[1] > 1.0)
3268 return FALSE
; /* TODO: check actual intersection */
3270 for (i
= 0; i
< gradient
->n_stops
; i
++)
3271 if (! CAIRO_COLOR_IS_OPAQUE (&gradient
->stops
[i
].color
))
3278 * _cairo_pattern_is_opaque:
3280 * Convenience function to determine whether a pattern is an opaque
3281 * pattern (of any type). The same caveats that apply to
3282 * _cairo_pattern_is_opaque_solid apply here as well.
3284 * Return value: %TRUE if the pattern is a opaque.
3287 _cairo_pattern_is_opaque (const cairo_pattern_t
*abstract_pattern
,
3288 const cairo_rectangle_int_t
*sample
)
3290 const cairo_pattern_union_t
*pattern
;
3292 if (abstract_pattern
->has_component_alpha
)
3295 pattern
= (cairo_pattern_union_t
*) abstract_pattern
;
3296 switch (pattern
->base
.type
) {
3297 case CAIRO_PATTERN_TYPE_SOLID
:
3298 return _cairo_pattern_is_opaque_solid (abstract_pattern
);
3299 case CAIRO_PATTERN_TYPE_SURFACE
:
3300 return _surface_is_opaque (&pattern
->surface
, sample
);
3301 case CAIRO_PATTERN_TYPE_RASTER_SOURCE
:
3302 return _raster_source_is_opaque (&pattern
->raster_source
, sample
);
3303 case CAIRO_PATTERN_TYPE_LINEAR
:
3304 case CAIRO_PATTERN_TYPE_RADIAL
:
3305 return _gradient_is_opaque (&pattern
->gradient
.base
, sample
);
3306 case CAIRO_PATTERN_TYPE_MESH
:
3315 _cairo_pattern_is_clear (const cairo_pattern_t
*abstract_pattern
)
3317 const cairo_pattern_union_t
*pattern
;
3319 if (abstract_pattern
->has_component_alpha
)
3322 pattern
= (cairo_pattern_union_t
*) abstract_pattern
;
3323 switch (abstract_pattern
->type
) {
3324 case CAIRO_PATTERN_TYPE_SOLID
:
3325 return CAIRO_COLOR_IS_CLEAR (&pattern
->solid
.color
);
3326 case CAIRO_PATTERN_TYPE_SURFACE
:
3327 return _surface_is_clear (&pattern
->surface
);
3328 case CAIRO_PATTERN_TYPE_RASTER_SOURCE
:
3329 return _raster_source_is_clear (&pattern
->raster_source
);
3330 case CAIRO_PATTERN_TYPE_LINEAR
:
3331 case CAIRO_PATTERN_TYPE_RADIAL
:
3332 return _gradient_is_clear (&pattern
->gradient
.base
, NULL
);
3333 case CAIRO_PATTERN_TYPE_MESH
:
3334 return _mesh_is_clear (&pattern
->mesh
);
3342 * Will given row of back-translation matrix work with bilinear scale?
3343 * This is true for scales larger than 1. Also it was judged acceptable
3344 * for scales larger than .75. And if there is integer translation
3345 * then a scale of exactly .5 works.
3348 use_bilinear(double x
, double y
, double t
)
3350 /* This is the inverse matrix! */
3351 double h
= x
*x
+ y
*y
;
3352 if (h
< 1.0 / (0.75 * 0.75))
3353 return TRUE
; /* scale > .75 */
3354 if ((h
> 3.99 && h
< 4.01) /* scale is 1/2 */
3355 && !_cairo_fixed_from_double(x
*y
) /* parallel to an axis */
3356 && _cairo_fixed_is_integer (_cairo_fixed_from_double (t
)))
3362 * _cairo_pattern_analyze_filter:
3363 * @pattern: surface pattern
3364 * Returns: the optimized #cairo_filter_t to use with @pattern.
3366 * Possibly optimize the filter to a simpler value depending on transformation
3369 _cairo_pattern_analyze_filter (const cairo_pattern_t
*pattern
)
3371 switch (pattern
->filter
) {
3372 case CAIRO_FILTER_GOOD
:
3373 case CAIRO_FILTER_BEST
:
3374 case CAIRO_FILTER_BILINEAR
:
3375 case CAIRO_FILTER_FAST
:
3376 /* If source pixels map 1:1 onto destination pixels, we do
3377 * not need to filter (and do not want to filter, since it
3378 * will cause blurriness)
3380 if (_cairo_matrix_is_pixel_exact (&pattern
->matrix
)) {
3381 return CAIRO_FILTER_NEAREST
;
3383 /* Use BILINEAR for any scale greater than .75 instead
3384 * of GOOD. For scales of 1 and larger this is identical,
3385 * for the smaller sizes it was judged that the artifacts
3386 * were not worse than the artifacts from a box filer.
3387 * BILINEAR can also be used if the scale is exactly .5
3388 * and the translation in that direction is an integer.
3390 if (pattern
->filter
== CAIRO_FILTER_GOOD
&&
3391 use_bilinear (pattern
->matrix
.xx
, pattern
->matrix
.xy
,
3392 pattern
->matrix
.x0
) &&
3393 use_bilinear (pattern
->matrix
.yx
, pattern
->matrix
.yy
,
3394 pattern
->matrix
.y0
))
3395 return CAIRO_FILTER_BILINEAR
;
3399 case CAIRO_FILTER_NEAREST
:
3400 case CAIRO_FILTER_GAUSSIAN
:
3405 return pattern
->filter
;
3410 * Returns: value similar to hypot(@x,@y)
3412 * May want to replace this with Manhattan distance (abs(x)+abs(y)) if
3413 * hypot is too slow, as there is no need for accuracy here.
3415 static inline double
3416 _cairo_hypot(double x
, double y
)
3422 * _cairo_pattern_sampled_area:
3424 * Return region of @pattern that will be sampled to fill @extents,
3425 * based on the transformation and filter.
3427 * This does not include pixels that are mulitiplied by values very
3428 * close to zero by the ends of filters. This is so that transforms
3429 * that should be the identity or 90 degree rotations do not expand
3430 * the source unexpectedly.
3432 * XXX: We don't actually have any way of querying the backend for
3433 * the filter radius, so we just guess base on what we know that
3434 * backends do currently (see bug #10508)
3437 _cairo_pattern_sampled_area (const cairo_pattern_t
*pattern
,
3438 const cairo_rectangle_int_t
*extents
,
3439 cairo_rectangle_int_t
*sample
)
3441 double x1
, x2
, y1
, y2
;
3444 /* Assume filters are interpolating, which means identity
3445 cannot change the image */
3446 if (_cairo_matrix_is_identity (&pattern
->matrix
)) {
3451 /* Transform the centers of the corner pixels */
3452 x1
= extents
->x
+ 0.5;
3453 y1
= extents
->y
+ 0.5;
3454 x2
= x1
+ (extents
->width
- 1);
3455 y2
= y1
+ (extents
->height
- 1);
3456 _cairo_matrix_transform_bounding_box (&pattern
->matrix
,
3460 /* How far away from center will it actually sample?
3461 * This is the distance from a transformed pixel center to the
3462 * furthest sample of reasonable size.
3464 switch (pattern
->filter
) {
3465 case CAIRO_FILTER_NEAREST
:
3466 case CAIRO_FILTER_FAST
:
3467 /* Correct value is zero, but when the sample is on an integer
3468 * it is unknown if the backend will sample the pixel to the
3469 * left or right. This value makes it include both possible pixels.
3471 padx
= pady
= 0.004;
3473 case CAIRO_FILTER_BILINEAR
:
3474 case CAIRO_FILTER_GAUSSIAN
:
3476 /* Correct value is .5 */
3477 padx
= pady
= 0.495;
3479 case CAIRO_FILTER_GOOD
:
3480 /* Correct value is max(width,1)*.5 */
3481 padx
= _cairo_hypot (pattern
->matrix
.xx
, pattern
->matrix
.xy
);
3482 if (padx
<= 1.0) padx
= 0.495;
3483 else if (padx
>= 16.0) padx
= 7.92;
3485 pady
= _cairo_hypot (pattern
->matrix
.yx
, pattern
->matrix
.yy
);
3486 if (pady
<= 1.0) pady
= 0.495;
3487 else if (pady
>= 16.0) pady
= 7.92;
3490 case CAIRO_FILTER_BEST
:
3491 /* Correct value is width*2 */
3492 padx
= _cairo_hypot (pattern
->matrix
.xx
, pattern
->matrix
.xy
) * 1.98;
3493 if (padx
> 7.92) padx
= 7.92;
3494 pady
= _cairo_hypot (pattern
->matrix
.yx
, pattern
->matrix
.yy
) * 1.98;
3495 if (pady
> 7.92) pady
= 7.92;
3499 /* round furthest samples to edge of pixels */
3500 x1
= floor (x1
- padx
);
3501 if (x1
< CAIRO_RECT_INT_MIN
) x1
= CAIRO_RECT_INT_MIN
;
3504 y1
= floor (y1
- pady
);
3505 if (y1
< CAIRO_RECT_INT_MIN
) y1
= CAIRO_RECT_INT_MIN
;
3508 x2
= floor (x2
+ padx
) + 1.0;
3509 if (x2
> CAIRO_RECT_INT_MAX
) x2
= CAIRO_RECT_INT_MAX
;
3510 sample
->width
= x2
- x1
;
3512 y2
= floor (y2
+ pady
) + 1.0;
3513 if (y2
> CAIRO_RECT_INT_MAX
) y2
= CAIRO_RECT_INT_MAX
;
3514 sample
->height
= y2
- y1
;
3518 * _cairo_pattern_get_extents:
3520 * Return the "target-space" extents of @pattern in @extents.
3522 * For unbounded patterns, the @extents will be initialized with
3523 * "infinite" extents, (minimum and maximum fixed-point values).
3525 * XXX: Currently, bounded gradient patterns will also return
3526 * "infinite" extents, though it would be possible to optimize these
3527 * with a little more work.
3530 _cairo_pattern_get_extents (const cairo_pattern_t
*pattern
,
3531 cairo_rectangle_int_t
*extents
)
3533 double x1
, y1
, x2
, y2
;
3534 int ix1
, ix2
, iy1
, iy2
;
3535 cairo_bool_t round_x
= FALSE
;
3536 cairo_bool_t round_y
= FALSE
;
3538 switch (pattern
->type
) {
3539 case CAIRO_PATTERN_TYPE_SOLID
:
3542 case CAIRO_PATTERN_TYPE_SURFACE
:
3544 cairo_rectangle_int_t surface_extents
;
3545 const cairo_surface_pattern_t
*surface_pattern
=
3546 (const cairo_surface_pattern_t
*) pattern
;
3547 cairo_surface_t
*surface
= surface_pattern
->surface
;
3549 if (! _cairo_surface_get_extents (surface
, &surface_extents
))
3552 if (surface_extents
.width
== 0 || surface_extents
.height
== 0)
3555 if (pattern
->extend
!= CAIRO_EXTEND_NONE
)
3558 x1
= surface_extents
.x
;
3559 y1
= surface_extents
.y
;
3560 x2
= surface_extents
.x
+ (int) surface_extents
.width
;
3561 y2
= surface_extents
.y
+ (int) surface_extents
.height
;
3567 case CAIRO_PATTERN_TYPE_RASTER_SOURCE
:
3569 const cairo_raster_source_pattern_t
*raster
=
3570 (const cairo_raster_source_pattern_t
*) pattern
;
3572 if (raster
->extents
.width
== 0 || raster
->extents
.height
== 0)
3575 if (pattern
->extend
!= CAIRO_EXTEND_NONE
)
3578 x1
= raster
->extents
.x
;
3579 y1
= raster
->extents
.y
;
3580 x2
= raster
->extents
.x
+ (int) raster
->extents
.width
;
3581 y2
= raster
->extents
.y
+ (int) raster
->extents
.height
;
3584 switch (pattern
->filter
) {
3585 case CAIRO_FILTER_NEAREST
:
3586 case CAIRO_FILTER_FAST
:
3587 round_x
= round_y
= TRUE
;
3588 /* We don't know which way .5 will go, so fudge it slightly. */
3594 case CAIRO_FILTER_BEST
:
3595 /* Assume best filter will produce nice antialiased edges */
3597 case CAIRO_FILTER_BILINEAR
:
3598 case CAIRO_FILTER_GAUSSIAN
:
3599 case CAIRO_FILTER_GOOD
:
3601 /* These filters can blur the edge out 1/2 pixel when scaling up */
3602 if (_cairo_hypot (pattern
->matrix
.xx
, pattern
->matrix
.yx
) < 1.0) {
3607 if (_cairo_hypot (pattern
->matrix
.xy
, pattern
->matrix
.yy
) < 1.0) {
3616 case CAIRO_PATTERN_TYPE_RADIAL
:
3618 const cairo_radial_pattern_t
*radial
=
3619 (const cairo_radial_pattern_t
*) pattern
;
3624 if (_radial_pattern_is_degenerate (radial
)) {
3625 /* cairo-gstate should have optimised degenerate
3626 * patterns to solid clear patterns, so we can ignore
3631 /* TODO: in some cases (focus outside/on the circle) it is
3633 if (pattern
->extend
!= CAIRO_EXTEND_NONE
)
3636 cx1
= radial
->cd1
.center
.x
;
3637 cy1
= radial
->cd1
.center
.y
;
3638 r1
= radial
->cd1
.radius
;
3640 cx2
= radial
->cd2
.center
.x
;
3641 cy2
= radial
->cd2
.center
.y
;
3642 r2
= radial
->cd2
.radius
;
3644 x1
= MIN (cx1
- r1
, cx2
- r2
);
3645 y1
= MIN (cy1
- r1
, cy2
- r2
);
3646 x2
= MAX (cx1
+ r1
, cx2
+ r2
);
3647 y2
= MAX (cy1
+ r1
, cy2
+ r2
);
3651 case CAIRO_PATTERN_TYPE_LINEAR
:
3653 const cairo_linear_pattern_t
*linear
=
3654 (const cairo_linear_pattern_t
*) pattern
;
3656 if (pattern
->extend
!= CAIRO_EXTEND_NONE
)
3659 if (_linear_pattern_is_degenerate (linear
)) {
3660 /* cairo-gstate should have optimised degenerate
3661 * patterns to solid ones, so we can again ignore
3666 /* TODO: to get tight extents, use the matrix to transform
3667 * the pattern instead of transforming the extents later. */
3668 if (pattern
->matrix
.xy
!= 0. || pattern
->matrix
.yx
!= 0.)
3671 if (linear
->pd1
.x
== linear
->pd2
.x
) {
3674 y1
= MIN (linear
->pd1
.y
, linear
->pd2
.y
);
3675 y2
= MAX (linear
->pd1
.y
, linear
->pd2
.y
);
3676 } else if (linear
->pd1
.y
== linear
->pd2
.y
) {
3677 x1
= MIN (linear
->pd1
.x
, linear
->pd2
.x
);
3678 x2
= MAX (linear
->pd1
.x
, linear
->pd2
.x
);
3685 /* The current linear renderer just point-samples in the middle
3686 of the pixels, similar to the NEAREST filter: */
3687 round_x
= round_y
= TRUE
;
3691 case CAIRO_PATTERN_TYPE_MESH
:
3693 const cairo_mesh_pattern_t
*mesh
=
3694 (const cairo_mesh_pattern_t
*) pattern
;
3695 if (! _cairo_mesh_pattern_coord_box (mesh
, &x1
, &y1
, &x2
, &y2
))
3704 if (_cairo_matrix_is_translation (&pattern
->matrix
)) {
3705 x1
-= pattern
->matrix
.x0
; x2
-= pattern
->matrix
.x0
;
3706 y1
-= pattern
->matrix
.y0
; y2
-= pattern
->matrix
.y0
;
3708 cairo_matrix_t imatrix
;
3709 cairo_status_t status
;
3711 imatrix
= pattern
->matrix
;
3712 status
= cairo_matrix_invert (&imatrix
);
3713 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3714 assert (status
== CAIRO_STATUS_SUCCESS
);
3716 _cairo_matrix_transform_bounding_box (&imatrix
,
3725 if (x1
< CAIRO_RECT_INT_MIN
)
3726 ix1
= CAIRO_RECT_INT_MIN
;
3728 ix1
= _cairo_lround (x1
);
3729 if (x2
> CAIRO_RECT_INT_MAX
)
3730 ix2
= CAIRO_RECT_INT_MAX
;
3732 ix2
= _cairo_lround (x2
);
3733 extents
->x
= ix1
; extents
->width
= ix2
- ix1
;
3739 if (y1
< CAIRO_RECT_INT_MIN
)
3740 iy1
= CAIRO_RECT_INT_MIN
;
3742 iy1
= _cairo_lround (y1
);
3743 if (y2
> CAIRO_RECT_INT_MAX
)
3744 iy2
= CAIRO_RECT_INT_MAX
;
3746 iy2
= _cairo_lround (y2
);
3747 extents
->y
= iy1
; extents
->height
= iy2
- iy1
;
3752 /* unbounded patterns -> 'infinite' extents */
3753 _cairo_unbounded_rectangle_init (extents
);
3757 extents
->x
= extents
->y
= 0;
3758 extents
->width
= extents
->height
= 0;
3763 * _cairo_pattern_get_ink_extents:
3765 * Return the "target-space" inked extents of @pattern in @extents.
3768 _cairo_pattern_get_ink_extents (const cairo_pattern_t
*pattern
,
3769 cairo_rectangle_int_t
*extents
)
3771 if (pattern
->type
== CAIRO_PATTERN_TYPE_SURFACE
&&
3772 pattern
->extend
== CAIRO_EXTEND_NONE
)
3774 const cairo_surface_pattern_t
*surface_pattern
=
3775 (const cairo_surface_pattern_t
*) pattern
;
3776 cairo_surface_t
*surface
= surface_pattern
->surface
;
3778 surface
= _cairo_surface_get_source (surface
, NULL
);
3779 if (_cairo_surface_is_recording (surface
)) {
3780 cairo_matrix_t imatrix
;
3782 cairo_status_t status
;
3784 imatrix
= pattern
->matrix
;
3785 status
= cairo_matrix_invert (&imatrix
);
3786 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3787 assert (status
== CAIRO_STATUS_SUCCESS
);
3789 status
= _cairo_recording_surface_get_ink_bbox ((cairo_recording_surface_t
*)surface
,
3791 if (unlikely (status
))
3794 _cairo_box_round_to_rectangle (&box
, extents
);
3795 return CAIRO_STATUS_SUCCESS
;
3799 _cairo_pattern_get_extents (pattern
, extents
);
3800 return CAIRO_STATUS_SUCCESS
;
3803 static unsigned long
3804 _cairo_solid_pattern_hash (unsigned long hash
,
3805 const cairo_solid_pattern_t
*solid
)
3807 hash
= _cairo_hash_bytes (hash
, &solid
->color
, sizeof (solid
->color
));
3812 static unsigned long
3813 _cairo_gradient_color_stops_hash (unsigned long hash
,
3814 const cairo_gradient_pattern_t
*gradient
)
3818 hash
= _cairo_hash_bytes (hash
,
3820 sizeof (gradient
->n_stops
));
3822 for (n
= 0; n
< gradient
->n_stops
; n
++) {
3823 hash
= _cairo_hash_bytes (hash
,
3824 &gradient
->stops
[n
].offset
,
3826 hash
= _cairo_hash_bytes (hash
,
3827 &gradient
->stops
[n
].color
,
3828 sizeof (cairo_color_stop_t
));
3835 _cairo_linear_pattern_hash (unsigned long hash
,
3836 const cairo_linear_pattern_t
*linear
)
3838 hash
= _cairo_hash_bytes (hash
, &linear
->pd1
, sizeof (linear
->pd1
));
3839 hash
= _cairo_hash_bytes (hash
, &linear
->pd2
, sizeof (linear
->pd2
));
3841 return _cairo_gradient_color_stops_hash (hash
, &linear
->base
);
3845 _cairo_radial_pattern_hash (unsigned long hash
,
3846 const cairo_radial_pattern_t
*radial
)
3848 hash
= _cairo_hash_bytes (hash
, &radial
->cd1
.center
, sizeof (radial
->cd1
.center
));
3849 hash
= _cairo_hash_bytes (hash
, &radial
->cd1
.radius
, sizeof (radial
->cd1
.radius
));
3850 hash
= _cairo_hash_bytes (hash
, &radial
->cd2
.center
, sizeof (radial
->cd2
.center
));
3851 hash
= _cairo_hash_bytes (hash
, &radial
->cd2
.radius
, sizeof (radial
->cd2
.radius
));
3853 return _cairo_gradient_color_stops_hash (hash
, &radial
->base
);
3856 static unsigned long
3857 _cairo_mesh_pattern_hash (unsigned long hash
, const cairo_mesh_pattern_t
*mesh
)
3859 const cairo_mesh_patch_t
*patch
= _cairo_array_index_const (&mesh
->patches
, 0);
3860 unsigned int i
, n
= _cairo_array_num_elements (&mesh
->patches
);
3862 for (i
= 0; i
< n
; i
++)
3863 hash
= _cairo_hash_bytes (hash
, patch
+ i
, sizeof (cairo_mesh_patch_t
));
3868 static unsigned long
3869 _cairo_surface_pattern_hash (unsigned long hash
,
3870 const cairo_surface_pattern_t
*surface
)
3872 hash
^= surface
->surface
->unique_id
;
3877 static unsigned long
3878 _cairo_raster_source_pattern_hash (unsigned long hash
,
3879 const cairo_raster_source_pattern_t
*raster
)
3881 hash
^= (uintptr_t)raster
->user_data
;
3887 _cairo_pattern_hash (const cairo_pattern_t
*pattern
)
3889 unsigned long hash
= _CAIRO_HASH_INIT_VALUE
;
3891 if (pattern
->status
)
3894 hash
= _cairo_hash_bytes (hash
, &pattern
->type
, sizeof (pattern
->type
));
3895 if (pattern
->type
!= CAIRO_PATTERN_TYPE_SOLID
) {
3896 hash
= _cairo_hash_bytes (hash
,
3897 &pattern
->matrix
, sizeof (pattern
->matrix
));
3898 hash
= _cairo_hash_bytes (hash
,
3899 &pattern
->filter
, sizeof (pattern
->filter
));
3900 hash
= _cairo_hash_bytes (hash
,
3901 &pattern
->extend
, sizeof (pattern
->extend
));
3902 hash
= _cairo_hash_bytes (hash
,
3903 &pattern
->has_component_alpha
,
3904 sizeof (pattern
->has_component_alpha
));
3907 switch (pattern
->type
) {
3908 case CAIRO_PATTERN_TYPE_SOLID
:
3909 return _cairo_solid_pattern_hash (hash
, (cairo_solid_pattern_t
*) pattern
);
3910 case CAIRO_PATTERN_TYPE_LINEAR
:
3911 return _cairo_linear_pattern_hash (hash
, (cairo_linear_pattern_t
*) pattern
);
3912 case CAIRO_PATTERN_TYPE_RADIAL
:
3913 return _cairo_radial_pattern_hash (hash
, (cairo_radial_pattern_t
*) pattern
);
3914 case CAIRO_PATTERN_TYPE_MESH
:
3915 return _cairo_mesh_pattern_hash (hash
, (cairo_mesh_pattern_t
*) pattern
);
3916 case CAIRO_PATTERN_TYPE_SURFACE
:
3917 return _cairo_surface_pattern_hash (hash
, (cairo_surface_pattern_t
*) pattern
);
3918 case CAIRO_PATTERN_TYPE_RASTER_SOURCE
:
3919 return _cairo_raster_source_pattern_hash (hash
, (cairo_raster_source_pattern_t
*) pattern
);
3927 _cairo_solid_pattern_equal (const cairo_solid_pattern_t
*a
,
3928 const cairo_solid_pattern_t
*b
)
3930 return _cairo_color_equal (&a
->color
, &b
->color
);
3934 _cairo_gradient_color_stops_equal (const cairo_gradient_pattern_t
*a
,
3935 const cairo_gradient_pattern_t
*b
)
3939 if (a
->n_stops
!= b
->n_stops
)
3942 for (n
= 0; n
< a
->n_stops
; n
++) {
3943 if (a
->stops
[n
].offset
!= b
->stops
[n
].offset
)
3945 if (! _cairo_color_stop_equal (&a
->stops
[n
].color
, &b
->stops
[n
].color
))
3953 _cairo_linear_pattern_equal (const cairo_linear_pattern_t
*a
,
3954 const cairo_linear_pattern_t
*b
)
3956 if (a
->pd1
.x
!= b
->pd1
.x
)
3959 if (a
->pd1
.y
!= b
->pd1
.y
)
3962 if (a
->pd2
.x
!= b
->pd2
.x
)
3965 if (a
->pd2
.y
!= b
->pd2
.y
)
3968 return _cairo_gradient_color_stops_equal (&a
->base
, &b
->base
);
3972 _cairo_radial_pattern_equal (const cairo_radial_pattern_t
*a
,
3973 const cairo_radial_pattern_t
*b
)
3975 if (a
->cd1
.center
.x
!= b
->cd1
.center
.x
)
3978 if (a
->cd1
.center
.y
!= b
->cd1
.center
.y
)
3981 if (a
->cd1
.radius
!= b
->cd1
.radius
)
3984 if (a
->cd2
.center
.x
!= b
->cd2
.center
.x
)
3987 if (a
->cd2
.center
.y
!= b
->cd2
.center
.y
)
3990 if (a
->cd2
.radius
!= b
->cd2
.radius
)
3993 return _cairo_gradient_color_stops_equal (&a
->base
, &b
->base
);
3997 _cairo_mesh_pattern_equal (const cairo_mesh_pattern_t
*a
,
3998 const cairo_mesh_pattern_t
*b
)
4000 const cairo_mesh_patch_t
*patch_a
, *patch_b
;
4001 unsigned int i
, num_patches_a
, num_patches_b
;
4003 num_patches_a
= _cairo_array_num_elements (&a
->patches
);
4004 num_patches_b
= _cairo_array_num_elements (&b
->patches
);
4006 if (num_patches_a
!= num_patches_b
)
4009 for (i
= 0; i
< num_patches_a
; i
++) {
4010 patch_a
= _cairo_array_index_const (&a
->patches
, i
);
4011 patch_b
= _cairo_array_index_const (&b
->patches
, i
);
4012 if (memcmp (patch_a
, patch_b
, sizeof(cairo_mesh_patch_t
)) != 0)
4020 _cairo_surface_pattern_equal (const cairo_surface_pattern_t
*a
,
4021 const cairo_surface_pattern_t
*b
)
4023 return a
->surface
->unique_id
== b
->surface
->unique_id
;
4027 _cairo_raster_source_pattern_equal (const cairo_raster_source_pattern_t
*a
,
4028 const cairo_raster_source_pattern_t
*b
)
4030 return a
->user_data
== b
->user_data
;
4034 _cairo_pattern_equal (const cairo_pattern_t
*a
, const cairo_pattern_t
*b
)
4036 if (a
->status
|| b
->status
)
4042 if (a
->type
!= b
->type
)
4045 if (a
->has_component_alpha
!= b
->has_component_alpha
)
4048 if (a
->type
!= CAIRO_PATTERN_TYPE_SOLID
) {
4049 if (memcmp (&a
->matrix
, &b
->matrix
, sizeof (cairo_matrix_t
)))
4052 if (a
->filter
!= b
->filter
)
4055 if (a
->extend
!= b
->extend
)
4060 case CAIRO_PATTERN_TYPE_SOLID
:
4061 return _cairo_solid_pattern_equal ((cairo_solid_pattern_t
*) a
,
4062 (cairo_solid_pattern_t
*) b
);
4063 case CAIRO_PATTERN_TYPE_LINEAR
:
4064 return _cairo_linear_pattern_equal ((cairo_linear_pattern_t
*) a
,
4065 (cairo_linear_pattern_t
*) b
);
4066 case CAIRO_PATTERN_TYPE_RADIAL
:
4067 return _cairo_radial_pattern_equal ((cairo_radial_pattern_t
*) a
,
4068 (cairo_radial_pattern_t
*) b
);
4069 case CAIRO_PATTERN_TYPE_MESH
:
4070 return _cairo_mesh_pattern_equal ((cairo_mesh_pattern_t
*) a
,
4071 (cairo_mesh_pattern_t
*) b
);
4072 case CAIRO_PATTERN_TYPE_SURFACE
:
4073 return _cairo_surface_pattern_equal ((cairo_surface_pattern_t
*) a
,
4074 (cairo_surface_pattern_t
*) b
);
4075 case CAIRO_PATTERN_TYPE_RASTER_SOURCE
:
4076 return _cairo_raster_source_pattern_equal ((cairo_raster_source_pattern_t
*) a
,
4077 (cairo_raster_source_pattern_t
*) b
);
4085 * cairo_pattern_get_rgba:
4086 * @pattern: a #cairo_pattern_t
4087 * @red: return value for red component of color, or %NULL
4088 * @green: return value for green component of color, or %NULL
4089 * @blue: return value for blue component of color, or %NULL
4090 * @alpha: return value for alpha component of color, or %NULL
4092 * Gets the solid color for a solid color pattern.
4094 * Return value: %CAIRO_STATUS_SUCCESS, or
4095 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid
4101 cairo_pattern_get_rgba (cairo_pattern_t
*pattern
,
4102 double *red
, double *green
,
4103 double *blue
, double *alpha
)
4105 cairo_solid_pattern_t
*solid
= (cairo_solid_pattern_t
*) pattern
;
4106 double r0
, g0
, b0
, a0
;
4108 if (pattern
->status
)
4109 return pattern
->status
;
4111 if (pattern
->type
!= CAIRO_PATTERN_TYPE_SOLID
)
4112 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
4114 _cairo_color_get_rgba (&solid
->color
, &r0
, &g0
, &b0
, &a0
);
4125 return CAIRO_STATUS_SUCCESS
;
4129 * cairo_pattern_get_surface:
4130 * @pattern: a #cairo_pattern_t
4131 * @surface: return value for surface of pattern, or %NULL
4133 * Gets the surface of a surface pattern. The reference returned in
4134 * @surface is owned by the pattern; the caller should call
4135 * cairo_surface_reference() if the surface is to be retained.
4137 * Return value: %CAIRO_STATUS_SUCCESS, or
4138 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a surface
4144 cairo_pattern_get_surface (cairo_pattern_t
*pattern
,
4145 cairo_surface_t
**surface
)
4147 cairo_surface_pattern_t
*spat
= (cairo_surface_pattern_t
*) pattern
;
4149 if (pattern
->status
)
4150 return pattern
->status
;
4152 if (pattern
->type
!= CAIRO_PATTERN_TYPE_SURFACE
)
4153 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
4156 *surface
= spat
->surface
;
4158 return CAIRO_STATUS_SUCCESS
;
4162 * cairo_pattern_get_color_stop_rgba:
4163 * @pattern: a #cairo_pattern_t
4164 * @index: index of the stop to return data for
4165 * @offset: return value for the offset of the stop, or %NULL
4166 * @red: return value for red component of color, or %NULL
4167 * @green: return value for green component of color, or %NULL
4168 * @blue: return value for blue component of color, or %NULL
4169 * @alpha: return value for alpha component of color, or %NULL
4171 * Gets the color and offset information at the given @index for a
4172 * gradient pattern. Values of @index range from 0 to n-1
4173 * where n is the number returned
4174 * by cairo_pattern_get_color_stop_count().
4176 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
4177 * if @index is not valid for the given pattern. If the pattern is
4178 * not a gradient pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
4184 cairo_pattern_get_color_stop_rgba (cairo_pattern_t
*pattern
,
4185 int index
, double *offset
,
4186 double *red
, double *green
,
4187 double *blue
, double *alpha
)
4189 cairo_gradient_pattern_t
*gradient
= (cairo_gradient_pattern_t
*) pattern
;
4191 if (pattern
->status
)
4192 return pattern
->status
;
4194 if (pattern
->type
!= CAIRO_PATTERN_TYPE_LINEAR
&&
4195 pattern
->type
!= CAIRO_PATTERN_TYPE_RADIAL
)
4196 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
4198 if (index
< 0 || (unsigned int) index
>= gradient
->n_stops
)
4199 return _cairo_error (CAIRO_STATUS_INVALID_INDEX
);
4202 *offset
= gradient
->stops
[index
].offset
;
4204 *red
= gradient
->stops
[index
].color
.red
;
4206 *green
= gradient
->stops
[index
].color
.green
;
4208 *blue
= gradient
->stops
[index
].color
.blue
;
4210 *alpha
= gradient
->stops
[index
].color
.alpha
;
4212 return CAIRO_STATUS_SUCCESS
;
4216 * cairo_pattern_get_color_stop_count:
4217 * @pattern: a #cairo_pattern_t
4218 * @count: return value for the number of color stops, or %NULL
4220 * Gets the number of color stops specified in the given gradient
4223 * Return value: %CAIRO_STATUS_SUCCESS, or
4224 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
4230 cairo_pattern_get_color_stop_count (cairo_pattern_t
*pattern
,
4233 cairo_gradient_pattern_t
*gradient
= (cairo_gradient_pattern_t
*) pattern
;
4235 if (pattern
->status
)
4236 return pattern
->status
;
4238 if (pattern
->type
!= CAIRO_PATTERN_TYPE_LINEAR
&&
4239 pattern
->type
!= CAIRO_PATTERN_TYPE_RADIAL
)
4240 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
4243 *count
= gradient
->n_stops
;
4245 return CAIRO_STATUS_SUCCESS
;
4249 * cairo_pattern_get_linear_points:
4250 * @pattern: a #cairo_pattern_t
4251 * @x0: return value for the x coordinate of the first point, or %NULL
4252 * @y0: return value for the y coordinate of the first point, or %NULL
4253 * @x1: return value for the x coordinate of the second point, or %NULL
4254 * @y1: return value for the y coordinate of the second point, or %NULL
4256 * Gets the gradient endpoints for a linear gradient.
4258 * Return value: %CAIRO_STATUS_SUCCESS, or
4259 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a linear
4265 cairo_pattern_get_linear_points (cairo_pattern_t
*pattern
,
4266 double *x0
, double *y0
,
4267 double *x1
, double *y1
)
4269 cairo_linear_pattern_t
*linear
= (cairo_linear_pattern_t
*) pattern
;
4271 if (pattern
->status
)
4272 return pattern
->status
;
4274 if (pattern
->type
!= CAIRO_PATTERN_TYPE_LINEAR
)
4275 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
4278 *x0
= linear
->pd1
.x
;
4280 *y0
= linear
->pd1
.y
;
4282 *x1
= linear
->pd2
.x
;
4284 *y1
= linear
->pd2
.y
;
4286 return CAIRO_STATUS_SUCCESS
;
4290 * cairo_pattern_get_radial_circles:
4291 * @pattern: a #cairo_pattern_t
4292 * @x0: return value for the x coordinate of the center of the first circle, or %NULL
4293 * @y0: return value for the y coordinate of the center of the first circle, or %NULL
4294 * @r0: return value for the radius of the first circle, or %NULL
4295 * @x1: return value for the x coordinate of the center of the second circle, or %NULL
4296 * @y1: return value for the y coordinate of the center of the second circle, or %NULL
4297 * @r1: return value for the radius of the second circle, or %NULL
4299 * Gets the gradient endpoint circles for a radial gradient, each
4300 * specified as a center coordinate and a radius.
4302 * Return value: %CAIRO_STATUS_SUCCESS, or
4303 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial
4309 cairo_pattern_get_radial_circles (cairo_pattern_t
*pattern
,
4310 double *x0
, double *y0
, double *r0
,
4311 double *x1
, double *y1
, double *r1
)
4313 cairo_radial_pattern_t
*radial
= (cairo_radial_pattern_t
*) pattern
;
4315 if (pattern
->status
)
4316 return pattern
->status
;
4318 if (pattern
->type
!= CAIRO_PATTERN_TYPE_RADIAL
)
4319 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
4322 *x0
= radial
->cd1
.center
.x
;
4324 *y0
= radial
->cd1
.center
.y
;
4326 *r0
= radial
->cd1
.radius
;
4328 *x1
= radial
->cd2
.center
.x
;
4330 *y1
= radial
->cd2
.center
.y
;
4332 *r1
= radial
->cd2
.radius
;
4334 return CAIRO_STATUS_SUCCESS
;
4338 * cairo_mesh_pattern_get_patch_count:
4339 * @pattern: a #cairo_pattern_t
4340 * @count: return value for the number patches, or %NULL
4342 * Gets the number of patches specified in the given mesh pattern.
4344 * The number only includes patches which have been finished by
4345 * calling cairo_mesh_pattern_end_patch(). For example it will be 0
4346 * during the definition of the first patch.
4348 * Return value: %CAIRO_STATUS_SUCCESS, or
4349 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a mesh
4355 cairo_mesh_pattern_get_patch_count (cairo_pattern_t
*pattern
,
4356 unsigned int *count
)
4358 cairo_mesh_pattern_t
*mesh
= (cairo_mesh_pattern_t
*) pattern
;
4360 if (unlikely (pattern
->status
))
4361 return pattern
->status
;
4363 if (unlikely (pattern
->type
!= CAIRO_PATTERN_TYPE_MESH
))
4364 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
4367 *count
= _cairo_array_num_elements (&mesh
->patches
);
4368 if (mesh
->current_patch
)
4372 return CAIRO_STATUS_SUCCESS
;
4374 slim_hidden_def (cairo_mesh_pattern_get_patch_count
);
4377 * cairo_mesh_pattern_get_path:
4378 * @pattern: a #cairo_pattern_t
4379 * @patch_num: the patch number to return data for
4381 * Gets path defining the patch @patch_num for a mesh
4384 * @patch_num can range from 0 to n-1 where n is the number returned by
4385 * cairo_mesh_pattern_get_patch_count().
4387 * Return value: the path defining the patch, or a path with status
4388 * %CAIRO_STATUS_INVALID_INDEX if @patch_num or @point_num is not
4389 * valid for @pattern. If @pattern is not a mesh pattern, a path with
4390 * status %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is returned.
4395 cairo_mesh_pattern_get_path (cairo_pattern_t
*pattern
,
4396 unsigned int patch_num
)
4398 cairo_mesh_pattern_t
*mesh
= (cairo_mesh_pattern_t
*) pattern
;
4399 const cairo_mesh_patch_t
*patch
;
4401 cairo_path_data_t
*data
;
4402 unsigned int patch_count
;
4403 int l
, current_point
;
4405 if (unlikely (pattern
->status
))
4406 return _cairo_path_create_in_error (pattern
->status
);
4408 if (unlikely (pattern
->type
!= CAIRO_PATTERN_TYPE_MESH
))
4409 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
));
4411 patch_count
= _cairo_array_num_elements (&mesh
->patches
);
4412 if (mesh
->current_patch
)
4415 if (unlikely (patch_num
>= patch_count
))
4416 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_INDEX
));
4418 patch
= _cairo_array_index_const (&mesh
->patches
, patch_num
);
4420 path
= malloc (sizeof (cairo_path_t
));
4422 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
4424 path
->num_data
= 18;
4425 path
->data
= _cairo_malloc_ab (path
->num_data
,
4426 sizeof (cairo_path_data_t
));
4427 if (path
->data
== NULL
) {
4429 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY
));
4433 data
[0].header
.type
= CAIRO_PATH_MOVE_TO
;
4434 data
[0].header
.length
= 2;
4435 data
[1].point
.x
= patch
->points
[0][0].x
;
4436 data
[1].point
.y
= patch
->points
[0][0].y
;
4437 data
+= data
[0].header
.length
;
4441 for (l
= 0; l
< 4; l
++) {
4444 data
[0].header
.type
= CAIRO_PATH_CURVE_TO
;
4445 data
[0].header
.length
= 4;
4447 for (k
= 1; k
< 4; k
++) {
4448 current_point
= (current_point
+ 1) % 12;
4449 i
= mesh_path_point_i
[current_point
];
4450 j
= mesh_path_point_j
[current_point
];
4451 data
[k
].point
.x
= patch
->points
[i
][j
].x
;
4452 data
[k
].point
.y
= patch
->points
[i
][j
].y
;
4455 data
+= data
[0].header
.length
;
4458 path
->status
= CAIRO_STATUS_SUCCESS
;
4462 slim_hidden_def (cairo_mesh_pattern_get_path
);
4465 * cairo_mesh_pattern_get_corner_color_rgba:
4466 * @pattern: a #cairo_pattern_t
4467 * @patch_num: the patch number to return data for
4468 * @corner_num: the corner number to return data for
4469 * @red: return value for red component of color, or %NULL
4470 * @green: return value for green component of color, or %NULL
4471 * @blue: return value for blue component of color, or %NULL
4472 * @alpha: return value for alpha component of color, or %NULL
4474 * Gets the color information in corner @corner_num of patch
4475 * @patch_num for a mesh pattern.
4477 * @patch_num can range from 0 to n-1 where n is the number returned by
4478 * cairo_mesh_pattern_get_patch_count().
4480 * Valid values for @corner_num are from 0 to 3 and identify the
4481 * corners as explained in cairo_pattern_create_mesh().
4483 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
4484 * if @patch_num or @corner_num is not valid for @pattern. If
4485 * @pattern is not a mesh pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH
4491 cairo_mesh_pattern_get_corner_color_rgba (cairo_pattern_t
*pattern
,
4492 unsigned int patch_num
,
4493 unsigned int corner_num
,
4494 double *red
, double *green
,
4495 double *blue
, double *alpha
)
4497 cairo_mesh_pattern_t
*mesh
= (cairo_mesh_pattern_t
*) pattern
;
4498 unsigned int patch_count
;
4499 const cairo_mesh_patch_t
*patch
;
4501 if (unlikely (pattern
->status
))
4502 return pattern
->status
;
4504 if (unlikely (pattern
->type
!= CAIRO_PATTERN_TYPE_MESH
))
4505 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
4507 if (unlikely (corner_num
> 3))
4508 return _cairo_error (CAIRO_STATUS_INVALID_INDEX
);
4510 patch_count
= _cairo_array_num_elements (&mesh
->patches
);
4511 if (mesh
->current_patch
)
4514 if (unlikely (patch_num
>= patch_count
))
4515 return _cairo_error (CAIRO_STATUS_INVALID_INDEX
);
4517 patch
= _cairo_array_index_const (&mesh
->patches
, patch_num
);
4520 *red
= patch
->colors
[corner_num
].red
;
4522 *green
= patch
->colors
[corner_num
].green
;
4524 *blue
= patch
->colors
[corner_num
].blue
;
4526 *alpha
= patch
->colors
[corner_num
].alpha
;
4528 return CAIRO_STATUS_SUCCESS
;
4530 slim_hidden_def (cairo_mesh_pattern_get_corner_color_rgba
);
4533 * cairo_mesh_pattern_get_control_point:
4534 * @pattern: a #cairo_pattern_t
4535 * @patch_num: the patch number to return data for
4536 * @point_num: the control point number to return data for
4537 * @x: return value for the x coordinate of the control point, or %NULL
4538 * @y: return value for the y coordinate of the control point, or %NULL
4540 * Gets the control point @point_num of patch @patch_num for a mesh
4543 * @patch_num can range from 0 to n-1 where n is the number returned by
4544 * cairo_mesh_pattern_get_patch_count().
4546 * Valid values for @point_num are from 0 to 3 and identify the
4547 * control points as explained in cairo_pattern_create_mesh().
4549 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
4550 * if @patch_num or @point_num is not valid for @pattern. If @pattern
4551 * is not a mesh pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
4557 cairo_mesh_pattern_get_control_point (cairo_pattern_t
*pattern
,
4558 unsigned int patch_num
,
4559 unsigned int point_num
,
4560 double *x
, double *y
)
4562 cairo_mesh_pattern_t
*mesh
= (cairo_mesh_pattern_t
*) pattern
;
4563 const cairo_mesh_patch_t
*patch
;
4564 unsigned int patch_count
;
4567 if (pattern
->status
)
4568 return pattern
->status
;
4570 if (pattern
->type
!= CAIRO_PATTERN_TYPE_MESH
)
4571 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH
);
4574 return _cairo_error (CAIRO_STATUS_INVALID_INDEX
);
4576 patch_count
= _cairo_array_num_elements (&mesh
->patches
);
4577 if (mesh
->current_patch
)
4580 if (unlikely (patch_num
>= patch_count
))
4581 return _cairo_error (CAIRO_STATUS_INVALID_INDEX
);
4583 patch
= _cairo_array_index_const (&mesh
->patches
, patch_num
);
4585 i
= mesh_control_point_i
[point_num
];
4586 j
= mesh_control_point_j
[point_num
];
4589 *x
= patch
->points
[i
][j
].x
;
4591 *y
= patch
->points
[i
][j
].y
;
4593 return CAIRO_STATUS_SUCCESS
;
4595 slim_hidden_def (cairo_mesh_pattern_get_control_point
);
4598 _cairo_pattern_reset_static_data (void)
4602 for (i
= 0; i
< ARRAY_LENGTH (freed_pattern_pool
); i
++)
4603 _freed_pool_reset (&freed_pattern_pool
[i
]);
4607 _cairo_debug_print_surface_pattern (FILE *file
,
4608 const cairo_surface_pattern_t
*pattern
)
4610 printf (" surface type: %d\n", pattern
->surface
->type
);
4614 _cairo_debug_print_raster_source_pattern (FILE *file
,
4615 const cairo_raster_source_pattern_t
*raster
)
4617 printf (" content: %x, size %dx%d\n", raster
->content
, raster
->extents
.width
, raster
->extents
.height
);
4621 _cairo_debug_print_linear_pattern (FILE *file
,
4622 const cairo_linear_pattern_t
*pattern
)
4627 _cairo_debug_print_radial_pattern (FILE *file
,
4628 const cairo_radial_pattern_t
*pattern
)
4633 _cairo_debug_print_mesh_pattern (FILE *file
,
4634 const cairo_mesh_pattern_t
*pattern
)
4639 _cairo_debug_print_pattern (FILE *file
, const cairo_pattern_t
*pattern
)
4642 switch (pattern
->type
) {
4643 case CAIRO_PATTERN_TYPE_SOLID
: s
= "solid"; break;
4644 case CAIRO_PATTERN_TYPE_SURFACE
: s
= "surface"; break;
4645 case CAIRO_PATTERN_TYPE_LINEAR
: s
= "linear"; break;
4646 case CAIRO_PATTERN_TYPE_RADIAL
: s
= "radial"; break;
4647 case CAIRO_PATTERN_TYPE_MESH
: s
= "mesh"; break;
4648 case CAIRO_PATTERN_TYPE_RASTER_SOURCE
: s
= "raster"; break;
4649 default: s
= "invalid"; ASSERT_NOT_REACHED
; break;
4652 fprintf (file
, "pattern: %s\n", s
);
4653 if (pattern
->type
== CAIRO_PATTERN_TYPE_SOLID
)
4656 switch (pattern
->extend
) {
4657 case CAIRO_EXTEND_NONE
: s
= "none"; break;
4658 case CAIRO_EXTEND_REPEAT
: s
= "repeat"; break;
4659 case CAIRO_EXTEND_REFLECT
: s
= "reflect"; break;
4660 case CAIRO_EXTEND_PAD
: s
= "pad"; break;
4661 default: s
= "invalid"; ASSERT_NOT_REACHED
; break;
4663 fprintf (file
, " extend: %s\n", s
);
4665 switch (pattern
->filter
) {
4666 case CAIRO_FILTER_FAST
: s
= "fast"; break;
4667 case CAIRO_FILTER_GOOD
: s
= "good"; break;
4668 case CAIRO_FILTER_BEST
: s
= "best"; break;
4669 case CAIRO_FILTER_NEAREST
: s
= "nearest"; break;
4670 case CAIRO_FILTER_BILINEAR
: s
= "bilinear"; break;
4671 case CAIRO_FILTER_GAUSSIAN
: s
= "guassian"; break;
4672 default: s
= "invalid"; ASSERT_NOT_REACHED
; break;
4674 fprintf (file
, " filter: %s\n", s
);
4675 fprintf (file
, " matrix: [%g %g %g %g %g %g]\n",
4676 pattern
->matrix
.xx
, pattern
->matrix
.yx
,
4677 pattern
->matrix
.xy
, pattern
->matrix
.yy
,
4678 pattern
->matrix
.x0
, pattern
->matrix
.y0
);
4679 switch (pattern
->type
) {
4681 case CAIRO_PATTERN_TYPE_SOLID
:
4683 case CAIRO_PATTERN_TYPE_RASTER_SOURCE
:
4684 _cairo_debug_print_raster_source_pattern (file
, (cairo_raster_source_pattern_t
*)pattern
);
4686 case CAIRO_PATTERN_TYPE_SURFACE
:
4687 _cairo_debug_print_surface_pattern (file
, (cairo_surface_pattern_t
*)pattern
);
4689 case CAIRO_PATTERN_TYPE_LINEAR
:
4690 _cairo_debug_print_linear_pattern (file
, (cairo_linear_pattern_t
*)pattern
);
4692 case CAIRO_PATTERN_TYPE_RADIAL
:
4693 _cairo_debug_print_radial_pattern (file
, (cairo_radial_pattern_t
*)pattern
);
4695 case CAIRO_PATTERN_TYPE_MESH
:
4696 _cairo_debug_print_mesh_pattern (file
, (cairo_mesh_pattern_t
*)pattern
);