beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-pattern.c
blobac5d7af20a2a91673587529cbe2dbedb0bcf4431
1 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2 /* cairo - a vector graphics library with display and print output
4 * Copyright © 2004 David Reveman
5 * Copyright © 2005 Red Hat, Inc.
7 * Permission to use, copy, modify, distribute, and sell this software
8 * and its documentation for any purpose is hereby granted without
9 * fee, provided that the above copyright notice appear in all copies
10 * and that both that copyright notice and this permission notice
11 * appear in supporting documentation, and that the name of David
12 * Reveman not be used in advertising or publicity pertaining to
13 * distribution of the software without specific, written prior
14 * permission. David Reveman makes no representations about the
15 * suitability of this software for any purpose. It is provided "as
16 * is" without express or implied warranty.
18 * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
19 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS, IN NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL,
21 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
22 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
23 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
24 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26 * Authors: David Reveman <davidr@novell.com>
27 * Keith Packard <keithp@keithp.com>
28 * Carl Worth <cworth@cworth.org>
31 #include "cairoint.h"
33 #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"
43 #include <float.h>
45 #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
47 /**
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
56 * brush too.
58 * A cairo pattern is created by using one of the many constructors,
59 * of the form
60 * <function>cairo_pattern_create_<emphasis>type</emphasis>()</function>
61 * or implicitly through
62 * <function>cairo_set_source_<emphasis>type</emphasis>()</function>
63 * functions.
64 **/
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 */
80 1.0 /* opacity */
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 */
96 1.0 /* opacity */
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 */
112 1.0 /* opacity */
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 */
129 1.0 /* opacity */
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 */
146 1.0 /* opacity */
148 { 1., 1., 1., 1., 0xffff, 0xffff, 0xffff, 0xffff },/* color (double rgba, short rgba) */
151 static void
152 _cairo_pattern_notify_observers (cairo_pattern_t *pattern,
153 unsigned int flags)
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
172 * objects.
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)
183 return status;
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);
192 void
193 _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
195 #if HAVE_VALGRIND
196 switch (type) {
197 case CAIRO_PATTERN_TYPE_SOLID:
198 VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t));
199 break;
200 case CAIRO_PATTERN_TYPE_SURFACE:
201 VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t));
202 break;
203 case CAIRO_PATTERN_TYPE_LINEAR:
204 VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t));
205 break;
206 case CAIRO_PATTERN_TYPE_RADIAL:
207 VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t));
208 break;
209 case CAIRO_PATTERN_TYPE_MESH:
210 VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t));
211 break;
212 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
213 break;
215 #endif
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;
229 else
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;
254 *dst = *src;
256 else
258 cairo_radial_pattern_t *dst = (cairo_radial_pattern_t *) pattern;
259 cairo_radial_pattern_t *src = (cairo_radial_pattern_t *) other;
261 *dst = *src;
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)
287 *pattern = *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));
295 cairo_status_t
296 _cairo_pattern_init_copy (cairo_pattern_t *pattern,
297 const cairo_pattern_t *other)
299 cairo_status_t status;
301 if (other->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)));
311 *dst = *src;
312 } break;
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)));
319 *dst = *src;
320 cairo_surface_reference (dst->surface);
321 } break;
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)));
329 } else {
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))
335 return status;
337 } break;
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))
346 return status;
348 } break;
350 case CAIRO_PATTERN_TYPE_RASTER_SOURCE: {
351 status = _cairo_raster_source_pattern_init_copy (pattern, other);
352 if (unlikely (status))
353 return status;
354 } break;
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;
364 void
365 _cairo_pattern_init_static_copy (cairo_pattern_t *pattern,
366 const cairo_pattern_t *other)
368 int size;
370 assert (other->status == CAIRO_STATUS_SUCCESS);
372 switch (other->type) {
373 default:
374 ASSERT_NOT_REACHED;
375 case CAIRO_PATTERN_TYPE_SOLID:
376 size = sizeof (cairo_solid_pattern_t);
377 break;
378 case CAIRO_PATTERN_TYPE_SURFACE:
379 size = sizeof (cairo_surface_pattern_t);
380 break;
381 case CAIRO_PATTERN_TYPE_LINEAR:
382 size = sizeof (cairo_linear_pattern_t);
383 break;
384 case CAIRO_PATTERN_TYPE_RADIAL:
385 size = sizeof (cairo_radial_pattern_t);
386 break;
387 case CAIRO_PATTERN_TYPE_MESH:
388 size = sizeof (cairo_mesh_pattern_t);
389 break;
390 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
391 size = sizeof (cairo_raster_source_pattern_t);
392 break;
395 memcpy (pattern, other, size);
397 CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
398 _cairo_user_data_array_init (&pattern->user_data);
401 cairo_status_t
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))
411 return 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);
428 return status;
431 void
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:
438 break;
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);
444 } break;
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);
452 } break;
453 case CAIRO_PATTERN_TYPE_MESH: {
454 cairo_mesh_pattern_t *mesh =
455 (cairo_mesh_pattern_t *) pattern;
457 _cairo_array_fini (&mesh->patches);
458 } break;
459 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
460 _cairo_raster_source_pattern_finish (pattern);
461 break;
464 #if HAVE_VALGRIND
465 switch (pattern->type) {
466 case CAIRO_PATTERN_TYPE_SOLID:
467 VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_solid_pattern_t));
468 break;
469 case CAIRO_PATTERN_TYPE_SURFACE:
470 VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_surface_pattern_t));
471 break;
472 case CAIRO_PATTERN_TYPE_LINEAR:
473 VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_linear_pattern_t));
474 break;
475 case CAIRO_PATTERN_TYPE_RADIAL:
476 VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_radial_pattern_t));
477 break;
478 case CAIRO_PATTERN_TYPE_MESH:
479 VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_mesh_pattern_t));
480 break;
481 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
482 break;
484 #endif
487 cairo_status_t
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;
494 if (other->status)
495 return other->status;
497 switch (other->type) {
498 case CAIRO_PATTERN_TYPE_SOLID:
499 pattern = malloc (sizeof (cairo_solid_pattern_t));
500 break;
501 case CAIRO_PATTERN_TYPE_SURFACE:
502 pattern = malloc (sizeof (cairo_surface_pattern_t));
503 break;
504 case CAIRO_PATTERN_TYPE_LINEAR:
505 pattern = malloc (sizeof (cairo_linear_pattern_t));
506 break;
507 case CAIRO_PATTERN_TYPE_RADIAL:
508 pattern = malloc (sizeof (cairo_radial_pattern_t));
509 break;
510 case CAIRO_PATTERN_TYPE_MESH:
511 pattern = malloc (sizeof (cairo_mesh_pattern_t));
512 break;
513 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
514 pattern = malloc (sizeof (cairo_raster_source_pattern_t));
515 break;
516 default:
517 ASSERT_NOT_REACHED;
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)) {
525 free (pattern);
526 return status;
529 CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
530 *pattern_out = pattern;
531 return CAIRO_STATUS_SUCCESS;
534 void
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;
542 void
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);
550 return;
553 _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SURFACE);
555 pattern->surface = cairo_surface_reference (surface);
558 static void
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;
569 static void
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);
575 pattern->pd1.x = x0;
576 pattern->pd1.y = y0;
577 pattern->pd2.x = x1;
578 pattern->pd2.y = y1;
581 static void
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);
596 cairo_pattern_t *
597 _cairo_pattern_create_solid (const cairo_color_t *color)
599 cairo_solid_pattern_t *pattern;
601 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;
618 cairo_pattern_t *
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);
632 return pattern;
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
644 * clamped.
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
649 * finished with it.
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().
655 * Since: 1.0
657 cairo_pattern_t *
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
674 * clamped.
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
679 * finished with it.
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().
685 * Since: 1.0
687 cairo_pattern_t *
688 cairo_pattern_create_rgba (double red, double green, double blue,
689 double alpha)
691 cairo_color_t color;
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
715 * finished with it.
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().
721 * Since: 1.0
723 cairo_pattern_t *
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;
733 if (surface->status)
734 return _cairo_pattern_create_in_error (surface->status);
736 pattern =
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
775 * finished with it.
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().
781 * Since: 1.0
783 cairo_pattern_t *
784 cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
786 cairo_linear_pattern_t *pattern;
788 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
828 * finished with it.
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().
834 * Since: 1.0
836 cairo_pattern_t *
837 cairo_pattern_create_radial (double cx0, double cy0, double radius0,
838 double cx1, double cy1, double radius1)
840 cairo_radial_pattern_t *pattern;
842 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
888 * patch.
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>
894 * C1 Side 1 C2
895 * +---------------+
896 * | |
897 * | P1 P2 |
898 * | |
899 * Side 0 | | Side 2
900 * | |
901 * | |
902 * | P0 P3 |
903 * | |
904 * +---------------+
905 * C0 Side 3 C3
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
948 * the color of C0.
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 * /&ast; Add a Coons patch &ast;/
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 * /&ast; Add a Gouraud-shaded triangle &ast;/
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
997 * detail.
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
1007 * it.
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().
1013 * Since: 1.12
1015 cairo_pattern_t *
1016 cairo_pattern_create_mesh (void)
1018 cairo_mesh_pattern_t *pattern;
1020 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.
1053 * Since: 1.0
1055 cairo_pattern_t *
1056 cairo_pattern_reference (cairo_pattern_t *pattern)
1058 if (pattern == NULL ||
1059 CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1060 return pattern;
1062 assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
1064 _cairo_reference_count_inc (&pattern->ref_count);
1066 return pattern;
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.
1079 * Since: 1.2
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
1092 * pattern.
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.
1098 * Since: 1.0
1100 cairo_status_t
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().
1114 * Since: 1.0
1116 void
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))
1123 return;
1125 assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
1127 if (! _cairo_reference_count_dec_and_test (&pattern->ref_count))
1128 return;
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);
1136 else
1137 free (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.
1150 * Since: 1.4
1152 unsigned int
1153 cairo_pattern_get_reference_count (cairo_pattern_t *pattern)
1155 if (pattern == NULL ||
1156 CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1157 return 0;
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
1166 * attached to
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.
1174 * Since: 1.4
1176 void *
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,
1181 key);
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
1191 * same key.
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
1195 * for @data.
1197 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
1198 * slot could not be allocated for the user data.
1200 * Since: 1.4
1202 cairo_status_t
1203 cairo_pattern_set_user_data (cairo_pattern_t *pattern,
1204 const cairo_user_data_key_t *key,
1205 void *user_data,
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.
1234 * Since: 1.12
1236 void
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;
1242 int i;
1244 if (unlikely (pattern->status))
1245 return;
1247 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1248 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1249 return;
1252 mesh = (cairo_mesh_pattern_t *) pattern;
1253 if (unlikely (mesh->current_patch)) {
1254 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1255 return;
1258 status = _cairo_array_allocate (&mesh->patches, 1, (void **) &current_patch);
1259 if (unlikely (status)) {
1260 _cairo_pattern_set_error (pattern, status);
1261 return;
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;
1275 static void
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:
1281 * P11 = S(1/3, 1/3)
1282 * P12 = S(1/3, 2/3)
1283 * P21 = S(2/3, 1/3)
1284 * P22 = S(2/3, 2/3)
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
1291 * patch.
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.
1335 * Since: 1.12
1337 void
1338 cairo_mesh_pattern_end_patch (cairo_pattern_t *pattern)
1340 cairo_mesh_pattern_t *mesh;
1341 cairo_mesh_patch_t *current_patch;
1342 int i;
1344 if (unlikely (pattern->status))
1345 return;
1347 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1348 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1349 return;
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);
1356 return;
1359 if (unlikely (mesh->current_side == -2)) {
1360 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1361 return;
1364 while (mesh->current_side < 3) {
1365 int corner_num;
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,
1408 * @y1).
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.
1419 * Since: 1.12
1421 void
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))
1431 return;
1433 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1434 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1435 return;
1438 mesh = (cairo_mesh_pattern_t *) pattern;
1439 if (unlikely (!mesh->current_patch)) {
1440 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1441 return;
1444 if (unlikely (mesh->current_side == 3)) {
1445 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1446 return;
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;
1459 current_point++;
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;
1465 current_point++;
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;
1471 current_point++;
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.
1503 * Since: 1.12
1505 void
1506 cairo_mesh_pattern_line_to (cairo_pattern_t *pattern,
1507 double x, double y)
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))
1514 return;
1516 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1517 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1518 return;
1521 mesh = (cairo_mesh_pattern_t *) pattern;
1522 if (unlikely (!mesh->current_patch)) {
1523 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1524 return;
1527 if (unlikely (mesh->current_side == 3)) {
1528 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1529 return;
1532 if (mesh->current_side == -2) {
1533 cairo_mesh_pattern_move_to (pattern, x, y);
1534 return;
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),
1548 x, y);
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.
1569 * Since: 1.12
1571 void
1572 cairo_mesh_pattern_move_to (cairo_pattern_t *pattern,
1573 double x, double y)
1575 cairo_mesh_pattern_t *mesh;
1577 if (unlikely (pattern->status))
1578 return;
1580 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1581 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1582 return;
1585 mesh = (cairo_mesh_pattern_t *) pattern;
1586 if (unlikely (!mesh->current_patch)) {
1587 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1588 return;
1591 if (unlikely (mesh->current_side >= 0)) {
1592 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1593 return;
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.
1622 * Since: 1.12
1624 void
1625 cairo_mesh_pattern_set_control_point (cairo_pattern_t *pattern,
1626 unsigned int point_num,
1627 double x,
1628 double y)
1630 cairo_mesh_pattern_t *mesh;
1631 int i, j;
1633 if (unlikely (pattern->status))
1634 return;
1636 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1637 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1638 return;
1641 if (unlikely (point_num > 3)) {
1642 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_INDEX);
1643 return;
1646 mesh = (cairo_mesh_pattern_t *) pattern;
1647 if (unlikely (!mesh->current_patch)) {
1648 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1649 return;
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
1670 * from there. */
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));
1684 if (new_stops)
1685 memcpy (new_stops, pattern->stops, old_size * sizeof (cairo_gradient_stop_t));
1686 } else {
1687 new_stops = _cairo_realloc_ab (pattern->stops,
1688 new_size,
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;
1701 static void
1702 _cairo_mesh_pattern_set_corner_color (cairo_mesh_pattern_t *mesh,
1703 unsigned int corner_num,
1704 double red, double green, double blue,
1705 double alpha)
1707 cairo_color_t *color;
1709 assert (mesh->current_patch);
1710 assert (corner_num <= 3);
1712 color = &mesh->current_patch->colors[corner_num];
1713 color->red = red;
1714 color->green = green;
1715 color->blue = blue;
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.
1749 * Since: 1.12
1751 void
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.
1783 * Since: 1.12
1785 void
1786 cairo_mesh_pattern_set_corner_color_rgba (cairo_pattern_t *pattern,
1787 unsigned int corner_num,
1788 double red, double green, double blue,
1789 double alpha)
1791 cairo_mesh_pattern_t *mesh;
1793 if (unlikely (pattern->status))
1794 return;
1796 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1797 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1798 return;
1801 if (unlikely (corner_num > 3)) {
1802 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_INDEX);
1803 return;
1806 mesh = (cairo_mesh_pattern_t *) pattern;
1807 if (unlikely (!mesh->current_patch)) {
1808 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1809 return;
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);
1821 static void
1822 _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
1823 double offset,
1824 double red,
1825 double green,
1826 double blue,
1827 double alpha)
1829 cairo_gradient_stop_t *stops;
1830 unsigned int i;
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);
1836 return;
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));
1849 break;
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);
1865 pattern->n_stops++;
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.
1895 * Since: 1.0
1897 void
1898 cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
1899 double offset,
1900 double red,
1901 double green,
1902 double blue)
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.
1934 * Since: 1.0
1936 void
1937 cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
1938 double offset,
1939 double red,
1940 double green,
1941 double blue,
1942 double alpha)
1944 if (pattern->status)
1945 return;
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);
1951 return;
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 (&amp;matrix, 0.5, 0.5);
1988 * cairo_pattern_set_matrix (pattern, &amp;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().
1997 * Since: 1.0
1999 void
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)
2007 return;
2009 if (memcmp (&pattern->matrix, matrix, sizeof (cairo_matrix_t)) == 0)
2010 return;
2012 pattern->matrix = *matrix;
2013 _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_MATRIX);
2015 inverse = *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.
2029 * Since: 1.0
2031 void
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
2041 * the pattern
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>
2057 * Since: 1.0
2059 void
2060 cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
2062 if (pattern->status)
2063 return;
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.
2078 * Since: 1.0
2080 cairo_filter_t
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
2094 * strategy.
2096 * The default extend mode is %CAIRO_EXTEND_NONE for surface patterns
2097 * and %CAIRO_EXTEND_PAD for gradient patterns.
2099 * Since: 1.0
2101 void
2102 cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
2104 if (pattern->status)
2105 return;
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
2119 * pattern.
2121 * Since: 1.0
2123 cairo_extend_t
2124 cairo_pattern_get_extend (cairo_pattern_t *pattern)
2126 return pattern->extend;
2128 slim_hidden_def (cairo_pattern_get_extend);
2130 void
2131 _cairo_pattern_pretransform (cairo_pattern_t *pattern,
2132 const cairo_matrix_t *ctm)
2134 if (pattern->status)
2135 return;
2137 cairo_matrix_multiply (&pattern->matrix, &pattern->matrix, ctm);
2140 void
2141 _cairo_pattern_transform (cairo_pattern_t *pattern,
2142 const cairo_matrix_t *ctm_inverse)
2144 if (pattern->status)
2145 return;
2147 cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
2150 static cairo_bool_t
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;
2157 static cairo_bool_t
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);
2182 static void
2183 _cairo_linear_pattern_box_to_parameter (const cairo_linear_pattern_t *linear,
2184 double x0, double y0,
2185 double x1, double y1,
2186 double range[2])
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);
2213 pdx *= invsqnorm;
2214 pdy *= invsqnorm;
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;
2229 if (tdx < 0)
2230 range[0] += tdx;
2231 else
2232 range[1] += tdx;
2234 if (tdy < 0)
2235 range[0] += tdy;
2236 else
2237 range[1] += tdy;
2240 static cairo_bool_t
2241 _extend_range (double range[2], double value, cairo_bool_t valid)
2243 if (!valid)
2244 range[0] = range[1] = value;
2245 else if (value < range[0])
2246 range[0] = value;
2247 else if (value > range[1])
2248 range[1] = value;
2250 return TRUE;
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
2264 * %FALSE.
2267 cairo_bool_t
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;
2282 static void
2283 _cairo_radial_pattern_box_to_parameter (const cairo_radial_pattern_t *radial,
2284 double x0, double y0,
2285 double x1, double y1,
2286 double tolerance,
2287 double range[2])
2289 double cx, cy, cr, dx, dy, dr;
2290 double a, x_focus, y_focus;
2291 double mindr, minx, miny, maxx, maxy;
2292 cairo_bool_t valid;
2294 assert (! _radial_pattern_is_degenerate (radial));
2295 assert (x0 < x1);
2296 assert (y0 < y1);
2298 tolerance = MAX (tolerance, DBL_EPSILON);
2300 range[0] = range[1] = 0;
2301 valid = FALSE;
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 */
2313 x0 -= cx;
2314 y0 -= cy;
2315 x1 -= cx;
2316 y1 -= cy;
2318 /* enlarge boundaries slightly to avoid rounding problems in the
2319 * parameter range computation */
2320 x0 -= DBL_EPSILON;
2321 y0 -= DBL_EPSILON;
2322 x1 += DBL_EPSILON;
2323 y1 += DBL_EPSILON;
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
2351 * t = -cr / dr
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) {
2357 double t_focus;
2359 t_focus = -cr / dr;
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
2385 * edges.
2387 * For the first equation:
2389 * (dx + dr) * t = x0 - cr
2390 * t = (x0 - cr) / (dx + dr)
2391 * y = dy * t
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) { \
2405 double t_edge, v; \
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);
2419 #undef T_EDGE
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
2428 * If we set:
2429 * a = dx^2 + dy^2 - dr^2
2430 * b = x*dx + y*dy + cr*dr
2431 * c = x^2 + y^2 - cr^2
2432 * we have:
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) {
2437 double b, maxd2;
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
2446 * AND
2447 * 2a) The circles are both very small:
2448 * min (r0, r1) < DBL_EPSILON
2449 * OR
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
2460 * which implies:
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.
2496 * For example:
2498 * y = y0
2499 * x*dx + y0*dy + cr*dr == 0
2500 * x = -(y0*dy + cr*dr) / dx
2502 * which in (u,v) is:
2503 * u = y0 - y_focus
2504 * v = -(y0*dy + cr*dr) / dx - x_focus
2506 * In the code:
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) { \
2512 double v; \
2514 v = -((edge) * (delta) + cr * dr) / (den); \
2515 if ((lower) <= v && v <= (upper)) { \
2516 double u, d2; \
2518 u = (edge) - (u_origin); \
2519 v -= (v_origin); \
2520 d2 = u*u + v*v; \
2521 if (maxd2 < d2) \
2522 maxd2 = d2; \
2526 maxd2 = 0;
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);
2534 #undef T_EDGE
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),
2544 * so:
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)
2550 if (maxd2 > 0) {
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
2561 * t = c / (2*b)
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) { \
2569 double t_corner; \
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 */
2581 T_CORNER (x0, y0);
2582 T_CORNER (x0, y1);
2583 T_CORNER (x1, y0);
2584 T_CORNER (x1, y1);
2586 #undef T_CORNER
2587 } else {
2588 double inva, b, c, d;
2590 inva = 1 / a;
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; \
2606 if (d >= 0) { \
2607 double t_corner; \
2609 d = sqrt (d); \
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 */
2619 T_CORNER (x0, y0);
2620 T_CORNER (x0, y1);
2621 T_CORNER (x1, y0);
2622 T_CORNER (x1, y1);
2624 #undef T_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.
2641 void
2642 _cairo_gradient_pattern_box_to_parameter (const cairo_gradient_pattern_t *gradient,
2643 double x0, double y0,
2644 double x1, double y1,
2645 double tolerance,
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);
2654 } else {
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.
2667 void
2668 _cairo_gradient_pattern_interpolate (const cairo_gradient_pattern_t *gradient,
2669 double t,
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;
2682 } else {
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);
2689 #undef lerp
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.
2704 void
2705 _cairo_gradient_pattern_fit_to_range (const cairo_gradient_pattern_t *gradient,
2706 double max_value,
2707 cairo_matrix_t *out_matrix,
2708 cairo_circle_double_t out_circle[2])
2710 double dim;
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));
2729 } else {
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);
2760 } else {
2761 *out_matrix = gradient->base.matrix;
2765 static cairo_bool_t
2766 _gradient_is_clear (const cairo_gradient_pattern_t *gradient,
2767 const cairo_rectangle_int_t *extents)
2769 unsigned int i;
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))
2777 return TRUE;
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))
2782 return TRUE;
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))
2786 return TRUE;
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))
2794 double t[2];
2796 _cairo_gradient_pattern_box_to_parameter (gradient,
2797 extents->x,
2798 extents->y,
2799 extents->x + extents->width,
2800 extents->y + extents->height,
2801 DBL_EPSILON,
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))
2808 return TRUE;
2811 if (t[0] == t[1])
2812 return TRUE;
2815 for (i = 0; i < gradient->n_stops; i++)
2816 if (! CAIRO_COLOR_IS_CLEAR (&gradient->stops[i].color))
2817 return FALSE;
2819 return TRUE;
2822 static void
2823 _gradient_color_average (const cairo_gradient_pattern_t *gradient,
2824 cairo_color_t *color)
2826 double delta0, delta1;
2827 double r, g, b, a;
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);
2839 return;
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
2852 * + +
2853 * / |\ / | \
2854 * / | \ / | \
2855 * / | \ / | \
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;
2865 break;
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
2874 * +-------+ +---+
2875 * | |\ / | |
2876 * | | \ / | |
2877 * | | \ / | |
2878 * +-------+---+~~~~~~~+-------+---+
2879 * 0 Sa Sb Sy Sz 1
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;
2887 break;
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;
2896 start = end;
2897 break;
2899 case CAIRO_EXTEND_NONE:
2900 default:
2901 ASSERT_NOT_REACHED;
2902 _cairo_color_init_rgba (color, 0, 0, 0, 0);
2903 return;
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.
2942 void
2943 _cairo_pattern_alpha_range (const cairo_pattern_t *pattern,
2944 double *out_min,
2945 double *out_max)
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;
2953 break;
2956 case CAIRO_PATTERN_TYPE_LINEAR:
2957 case CAIRO_PATTERN_TYPE_RADIAL: {
2958 const cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
2959 unsigned int i;
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;
2971 break;
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);
2979 assert (n >= 1);
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;
2991 break;
2994 default:
2995 ASSERT_NOT_REACHED;
2996 /* fall through */
2998 case CAIRO_PATTERN_TYPE_SURFACE:
2999 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3000 alpha_min = 0;
3001 alpha_max = 1;
3002 break;
3005 if (out_min)
3006 *out_min = alpha_min;
3007 if (out_max)
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.
3027 cairo_bool_t
3028 _cairo_mesh_pattern_coord_box (const cairo_mesh_pattern_t *mesh,
3029 double *out_xmin,
3030 double *out_ymin,
3031 double *out_xmax,
3032 double *out_ymax)
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)
3043 return FALSE;
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);
3060 *out_xmin = x0;
3061 *out_ymin = y0;
3062 *out_xmax = x1;
3063 *out_ymax = y1;
3065 return TRUE;
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
3076 * returned FALSE.
3078 * Return value: %TRUE if the pattern is a solid color.
3080 cairo_bool_t
3081 _cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient,
3082 const cairo_rectangle_int_t *extents,
3083 cairo_color_t *color)
3085 unsigned int i;
3087 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
3088 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
3090 /* TODO: 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);
3095 return TRUE;
3098 if (gradient->base.extend == CAIRO_EXTEND_NONE) {
3099 double t[2];
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)
3106 return FALSE;
3108 _cairo_linear_pattern_box_to_parameter (linear,
3109 extents->x,
3110 extents->y,
3111 extents->x + extents->width,
3112 extents->y + extents->height,
3115 if (t[0] < 0.0 || t[1] > 1.0)
3116 return FALSE;
3118 } else
3119 return FALSE;
3121 for (i = 1; i < gradient->n_stops; i++)
3122 if (! _cairo_color_stop_equal (&gradient->stops[0].color,
3123 &gradient->stops[i].color))
3124 return FALSE;
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);
3132 return TRUE;
3135 static cairo_bool_t
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);
3142 if (!is_valid)
3143 return TRUE;
3145 if (x2 - x1 < DBL_EPSILON || y2 - y1 < DBL_EPSILON)
3146 return TRUE;
3148 return FALSE;
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.
3162 cairo_bool_t
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)
3168 return FALSE;
3170 solid = (cairo_solid_pattern_t *) pattern;
3172 return CAIRO_COLOR_IS_OPAQUE (&solid->color);
3175 static cairo_bool_t
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)
3182 return FALSE;
3184 if (pattern->base.extend != CAIRO_EXTEND_NONE)
3185 return TRUE;
3187 if (! _cairo_surface_get_extents (pattern->surface, &extents))
3188 return TRUE;
3190 if (sample == NULL)
3191 return FALSE;
3193 return _cairo_rectangle_contains_rectangle (&extents, sample);
3196 static cairo_bool_t
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)
3201 return FALSE;
3203 if (pattern->base.extend != CAIRO_EXTEND_NONE)
3204 return TRUE;
3206 if (sample == NULL)
3207 return FALSE;
3209 return _cairo_rectangle_contains_rectangle (&pattern->extents, sample);
3212 static cairo_bool_t
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))
3219 return TRUE;
3221 return pattern->surface->is_clear &&
3222 pattern->surface->content & CAIRO_CONTENT_ALPHA;
3225 static cairo_bool_t
3226 _raster_source_is_clear (const cairo_raster_source_pattern_t *pattern)
3228 return pattern->extents.width == 0 || pattern->extents.height == 0;
3231 static cairo_bool_t
3232 _gradient_is_opaque (const cairo_gradient_pattern_t *gradient,
3233 const cairo_rectangle_int_t *sample)
3235 unsigned int i;
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))
3243 return FALSE;
3245 if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
3246 if (gradient->base.extend == CAIRO_EXTEND_NONE) {
3247 double t[2];
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))
3252 return FALSE;
3254 if (sample == NULL)
3255 return FALSE;
3257 _cairo_linear_pattern_box_to_parameter (linear,
3258 sample->x,
3259 sample->y,
3260 sample->x + sample->width,
3261 sample->y + sample->height,
3264 if (t[0] < 0.0 || t[1] > 1.0)
3265 return FALSE;
3267 } else
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))
3272 return FALSE;
3274 return TRUE;
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.
3286 cairo_bool_t
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)
3293 return FALSE;
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:
3307 return FALSE;
3310 ASSERT_NOT_REACHED;
3311 return FALSE;
3314 cairo_bool_t
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)
3320 return FALSE;
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);
3337 ASSERT_NOT_REACHED;
3338 return FALSE;
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.
3347 static int
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)))
3357 return TRUE;
3358 return FALSE;
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
3368 cairo_filter_t
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;
3382 } else {
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;
3397 break;
3399 case CAIRO_FILTER_NEAREST:
3400 case CAIRO_FILTER_GAUSSIAN:
3401 default:
3402 break;
3405 return pattern->filter;
3409 * _cairo_hypot:
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)
3418 return hypot(x, 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)
3436 void
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;
3442 double padx, pady;
3444 /* Assume filters are interpolating, which means identity
3445 cannot change the image */
3446 if (_cairo_matrix_is_identity (&pattern->matrix)) {
3447 *sample = *extents;
3448 return;
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,
3457 &x1, &y1, &x2, &y2,
3458 NULL);
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;
3472 break;
3473 case CAIRO_FILTER_BILINEAR:
3474 case CAIRO_FILTER_GAUSSIAN:
3475 default:
3476 /* Correct value is .5 */
3477 padx = pady = 0.495;
3478 break;
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;
3484 else padx *= 0.495;
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;
3488 else pady *= 0.495;
3489 break;
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;
3496 break;
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;
3502 sample->x = x1;
3504 y1 = floor (y1 - pady);
3505 if (y1 < CAIRO_RECT_INT_MIN) y1 = CAIRO_RECT_INT_MIN;
3506 sample->y = y1;
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.
3529 void
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:
3540 goto UNBOUNDED;
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))
3550 goto UNBOUNDED;
3552 if (surface_extents.width == 0 || surface_extents.height == 0)
3553 goto EMPTY;
3555 if (pattern->extend != CAIRO_EXTEND_NONE)
3556 goto UNBOUNDED;
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;
3563 goto HANDLE_FILTER;
3565 break;
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)
3573 goto EMPTY;
3575 if (pattern->extend != CAIRO_EXTEND_NONE)
3576 goto UNBOUNDED;
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;
3583 HANDLE_FILTER:
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. */
3589 x1 -= 0.004;
3590 y1 -= 0.004;
3591 x2 += 0.004;
3592 y2 += 0.004;
3593 break;
3594 case CAIRO_FILTER_BEST:
3595 /* Assume best filter will produce nice antialiased edges */
3596 break;
3597 case CAIRO_FILTER_BILINEAR:
3598 case CAIRO_FILTER_GAUSSIAN:
3599 case CAIRO_FILTER_GOOD:
3600 default:
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) {
3603 x1 -= 0.5;
3604 x2 += 0.5;
3605 round_x = TRUE;
3607 if (_cairo_hypot (pattern->matrix.xy, pattern->matrix.yy) < 1.0) {
3608 y1 -= 0.5;
3609 y2 += 0.5;
3610 round_y = TRUE;
3612 break;
3614 break;
3616 case CAIRO_PATTERN_TYPE_RADIAL:
3618 const cairo_radial_pattern_t *radial =
3619 (const cairo_radial_pattern_t *) pattern;
3620 double cx1, cy1;
3621 double cx2, cy2;
3622 double r1, r2;
3624 if (_radial_pattern_is_degenerate (radial)) {
3625 /* cairo-gstate should have optimised degenerate
3626 * patterns to solid clear patterns, so we can ignore
3627 * them here. */
3628 goto EMPTY;
3631 /* TODO: in some cases (focus outside/on the circle) it is
3632 * half-bounded. */
3633 if (pattern->extend != CAIRO_EXTEND_NONE)
3634 goto UNBOUNDED;
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);
3649 break;
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)
3657 goto UNBOUNDED;
3659 if (_linear_pattern_is_degenerate (linear)) {
3660 /* cairo-gstate should have optimised degenerate
3661 * patterns to solid ones, so we can again ignore
3662 * them here. */
3663 goto EMPTY;
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.)
3669 goto UNBOUNDED;
3671 if (linear->pd1.x == linear->pd2.x) {
3672 x1 = -HUGE_VAL;
3673 x2 = HUGE_VAL;
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);
3679 y1 = -HUGE_VAL;
3680 y2 = HUGE_VAL;
3681 } else {
3682 goto UNBOUNDED;
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;
3689 break;
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))
3696 goto EMPTY;
3698 break;
3700 default:
3701 ASSERT_NOT_REACHED;
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;
3707 } else {
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,
3717 &x1, &y1, &x2, &y2,
3718 NULL);
3721 if (!round_x) {
3722 x1 -= 0.5;
3723 x2 += 0.5;
3725 if (x1 < CAIRO_RECT_INT_MIN)
3726 ix1 = CAIRO_RECT_INT_MIN;
3727 else
3728 ix1 = _cairo_lround (x1);
3729 if (x2 > CAIRO_RECT_INT_MAX)
3730 ix2 = CAIRO_RECT_INT_MAX;
3731 else
3732 ix2 = _cairo_lround (x2);
3733 extents->x = ix1; extents->width = ix2 - ix1;
3735 if (!round_y) {
3736 y1 -= 0.5;
3737 y2 += 0.5;
3739 if (y1 < CAIRO_RECT_INT_MIN)
3740 iy1 = CAIRO_RECT_INT_MIN;
3741 else
3742 iy1 = _cairo_lround (y1);
3743 if (y2 > CAIRO_RECT_INT_MAX)
3744 iy2 = CAIRO_RECT_INT_MAX;
3745 else
3746 iy2 = _cairo_lround (y2);
3747 extents->y = iy1; extents->height = iy2 - iy1;
3749 return;
3751 UNBOUNDED:
3752 /* unbounded patterns -> 'infinite' extents */
3753 _cairo_unbounded_rectangle_init (extents);
3754 return;
3756 EMPTY:
3757 extents->x = extents->y = 0;
3758 extents->width = extents->height = 0;
3759 return;
3763 * _cairo_pattern_get_ink_extents:
3765 * Return the "target-space" inked extents of @pattern in @extents.
3767 cairo_int_status_t
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;
3781 cairo_box_t box;
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,
3790 &box, &imatrix);
3791 if (unlikely (status))
3792 return 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));
3809 return hash;
3812 static unsigned long
3813 _cairo_gradient_color_stops_hash (unsigned long hash,
3814 const cairo_gradient_pattern_t *gradient)
3816 unsigned int n;
3818 hash = _cairo_hash_bytes (hash,
3819 &gradient->n_stops,
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,
3825 sizeof (double));
3826 hash = _cairo_hash_bytes (hash,
3827 &gradient->stops[n].color,
3828 sizeof (cairo_color_stop_t));
3831 return hash;
3834 unsigned long
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);
3844 unsigned long
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));
3865 return hash;
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;
3874 return hash;
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;
3883 return hash;
3886 unsigned long
3887 _cairo_pattern_hash (const cairo_pattern_t *pattern)
3889 unsigned long hash = _CAIRO_HASH_INIT_VALUE;
3891 if (pattern->status)
3892 return 0;
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);
3920 default:
3921 ASSERT_NOT_REACHED;
3922 return FALSE;
3926 static cairo_bool_t
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);
3933 static cairo_bool_t
3934 _cairo_gradient_color_stops_equal (const cairo_gradient_pattern_t *a,
3935 const cairo_gradient_pattern_t *b)
3937 unsigned int n;
3939 if (a->n_stops != b->n_stops)
3940 return FALSE;
3942 for (n = 0; n < a->n_stops; n++) {
3943 if (a->stops[n].offset != b->stops[n].offset)
3944 return FALSE;
3945 if (! _cairo_color_stop_equal (&a->stops[n].color, &b->stops[n].color))
3946 return FALSE;
3949 return TRUE;
3952 cairo_bool_t
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)
3957 return FALSE;
3959 if (a->pd1.y != b->pd1.y)
3960 return FALSE;
3962 if (a->pd2.x != b->pd2.x)
3963 return FALSE;
3965 if (a->pd2.y != b->pd2.y)
3966 return FALSE;
3968 return _cairo_gradient_color_stops_equal (&a->base, &b->base);
3971 cairo_bool_t
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)
3976 return FALSE;
3978 if (a->cd1.center.y != b->cd1.center.y)
3979 return FALSE;
3981 if (a->cd1.radius != b->cd1.radius)
3982 return FALSE;
3984 if (a->cd2.center.x != b->cd2.center.x)
3985 return FALSE;
3987 if (a->cd2.center.y != b->cd2.center.y)
3988 return FALSE;
3990 if (a->cd2.radius != b->cd2.radius)
3991 return FALSE;
3993 return _cairo_gradient_color_stops_equal (&a->base, &b->base);
3996 static cairo_bool_t
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)
4007 return FALSE;
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)
4013 return FALSE;
4016 return TRUE;
4019 static cairo_bool_t
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;
4026 static cairo_bool_t
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;
4033 cairo_bool_t
4034 _cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b)
4036 if (a->status || b->status)
4037 return FALSE;
4039 if (a == b)
4040 return TRUE;
4042 if (a->type != b->type)
4043 return FALSE;
4045 if (a->has_component_alpha != b->has_component_alpha)
4046 return FALSE;
4048 if (a->type != CAIRO_PATTERN_TYPE_SOLID) {
4049 if (memcmp (&a->matrix, &b->matrix, sizeof (cairo_matrix_t)))
4050 return FALSE;
4052 if (a->filter != b->filter)
4053 return FALSE;
4055 if (a->extend != b->extend)
4056 return FALSE;
4059 switch (a->type) {
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);
4078 default:
4079 ASSERT_NOT_REACHED;
4080 return FALSE;
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
4096 * color pattern.
4098 * Since: 1.4
4100 cairo_status_t
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);
4116 if (red)
4117 *red = r0;
4118 if (green)
4119 *green = g0;
4120 if (blue)
4121 *blue = b0;
4122 if (alpha)
4123 *alpha = 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
4139 * pattern.
4141 * Since: 1.4
4143 cairo_status_t
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);
4155 if (surface)
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
4179 * returned.
4181 * Since: 1.4
4183 cairo_status_t
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);
4201 if (offset)
4202 *offset = gradient->stops[index].offset;
4203 if (red)
4204 *red = gradient->stops[index].color.red;
4205 if (green)
4206 *green = gradient->stops[index].color.green;
4207 if (blue)
4208 *blue = gradient->stops[index].color.blue;
4209 if (alpha)
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
4221 * pattern.
4223 * Return value: %CAIRO_STATUS_SUCCESS, or
4224 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
4225 * pattern.
4227 * Since: 1.4
4229 cairo_status_t
4230 cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
4231 int *count)
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);
4242 if (count)
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
4260 * gradient pattern.
4262 * Since: 1.4
4264 cairo_status_t
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);
4277 if (x0)
4278 *x0 = linear->pd1.x;
4279 if (y0)
4280 *y0 = linear->pd1.y;
4281 if (x1)
4282 *x1 = linear->pd2.x;
4283 if (y1)
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
4304 * gradient pattern.
4306 * Since: 1.4
4308 cairo_status_t
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);
4321 if (x0)
4322 *x0 = radial->cd1.center.x;
4323 if (y0)
4324 *y0 = radial->cd1.center.y;
4325 if (r0)
4326 *r0 = radial->cd1.radius;
4327 if (x1)
4328 *x1 = radial->cd2.center.x;
4329 if (y1)
4330 *y1 = radial->cd2.center.y;
4331 if (r1)
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
4350 * pattern.
4352 * Since: 1.12
4354 cairo_status_t
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);
4366 if (count) {
4367 *count = _cairo_array_num_elements (&mesh->patches);
4368 if (mesh->current_patch)
4369 *count -= 1;
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
4382 * pattern.
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.
4392 * Since: 1.12
4394 cairo_path_t *
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;
4400 cairo_path_t *path;
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)
4413 patch_count--;
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));
4421 if (path == NULL)
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) {
4428 free (path);
4429 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
4432 data = path->data;
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;
4439 current_point = 0;
4441 for (l = 0; l < 4; l++) {
4442 int i, j, k;
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;
4460 return path;
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
4486 * is returned.
4488 * Since: 1.12
4490 cairo_status_t
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)
4512 patch_count--;
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);
4519 if (red)
4520 *red = patch->colors[corner_num].red;
4521 if (green)
4522 *green = patch->colors[corner_num].green;
4523 if (blue)
4524 *blue = patch->colors[corner_num].blue;
4525 if (alpha)
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
4541 * pattern.
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
4552 * returned.
4554 * Since: 1.12
4556 cairo_status_t
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;
4565 int i, j;
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);
4573 if (point_num > 3)
4574 return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4576 patch_count = _cairo_array_num_elements (&mesh->patches);
4577 if (mesh->current_patch)
4578 patch_count--;
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];
4588 if (x)
4589 *x = patch->points[i][j].x;
4590 if (y)
4591 *y = patch->points[i][j].y;
4593 return CAIRO_STATUS_SUCCESS;
4595 slim_hidden_def (cairo_mesh_pattern_get_control_point);
4597 void
4598 _cairo_pattern_reset_static_data (void)
4600 int i;
4602 for (i = 0; i < ARRAY_LENGTH (freed_pattern_pool); i++)
4603 _freed_pool_reset (&freed_pattern_pool[i]);
4606 static void
4607 _cairo_debug_print_surface_pattern (FILE *file,
4608 const cairo_surface_pattern_t *pattern)
4610 printf (" surface type: %d\n", pattern->surface->type);
4613 static void
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);
4620 static void
4621 _cairo_debug_print_linear_pattern (FILE *file,
4622 const cairo_linear_pattern_t *pattern)
4626 static void
4627 _cairo_debug_print_radial_pattern (FILE *file,
4628 const cairo_radial_pattern_t *pattern)
4632 static void
4633 _cairo_debug_print_mesh_pattern (FILE *file,
4634 const cairo_mesh_pattern_t *pattern)
4638 void
4639 _cairo_debug_print_pattern (FILE *file, const cairo_pattern_t *pattern)
4641 const char *s;
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)
4654 return;
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) {
4680 default:
4681 case CAIRO_PATTERN_TYPE_SOLID:
4682 break;
4683 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4684 _cairo_debug_print_raster_source_pattern (file, (cairo_raster_source_pattern_t *)pattern);
4685 break;
4686 case CAIRO_PATTERN_TYPE_SURFACE:
4687 _cairo_debug_print_surface_pattern (file, (cairo_surface_pattern_t *)pattern);
4688 break;
4689 case CAIRO_PATTERN_TYPE_LINEAR:
4690 _cairo_debug_print_linear_pattern (file, (cairo_linear_pattern_t *)pattern);
4691 break;
4692 case CAIRO_PATTERN_TYPE_RADIAL:
4693 _cairo_debug_print_radial_pattern (file, (cairo_radial_pattern_t *)pattern);
4694 break;
4695 case CAIRO_PATTERN_TYPE_MESH:
4696 _cairo_debug_print_mesh_pattern (file, (cairo_mesh_pattern_t *)pattern);
4697 break;