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
3 *
4 * Copyright © 2004 David Reveman
5 * Copyright © 2005 Red Hat, Inc.
6 *
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.
17 *
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.
25 *
26 * Authors: David Reveman <davidr@novell.com>
27 * Keith Packard <keithp@keithp.com>
28 * Carl Worth <cworth@cworth.org>
29 */
30
31 #include "cairoint.h"
32
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"
42
43 #include <float.h>
44
45 #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
46
47 /**
48 * SECTION:cairo-pattern
49 * @Title: cairo_pattern_t
50 * @Short_Description: Sources for drawing
51 * @See_Also: #cairo_t, #cairo_surface_t
52 *
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.
57 *
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 **/
65
66 static freed_pool_t freed_pattern_pool[5];
67
68 static const cairo_solid_pattern_t _cairo_pattern_nil = {
69 {
70 CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
71 CAIRO_STATUS_NO_MEMORY, /* status */
72 { 0, 0, 0, NULL }, /* user_data */
73 { NULL, NULL }, /* observers */
74
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 */
81 }
82 };
83
84 static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = {
85 {
86 CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
87 CAIRO_STATUS_NULL_POINTER, /* status */
88 { 0, 0, 0, NULL }, /* user_data */
89 { NULL, NULL }, /* observers */
90
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 */
97 }
98 };
99
100 const cairo_solid_pattern_t _cairo_pattern_black = {
101 {
102 CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
103 CAIRO_STATUS_SUCCESS, /* status */
104 { 0, 0, 0, NULL }, /* user_data */
105 { NULL, NULL }, /* observers */
106
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 */
113 },
114 { 0., 0., 0., 1., 0, 0, 0, 0xffff },/* color (double rgba, short rgba) */
115 };
116
117 const cairo_solid_pattern_t _cairo_pattern_clear = {
118 {
119 CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
120 CAIRO_STATUS_SUCCESS, /* status */
121 { 0, 0, 0, NULL }, /* user_data */
122 { NULL, NULL }, /* observers */
123
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 */
130 },
131 { 0., 0., 0., 0., 0, 0, 0, 0 },/* color (double rgba, short rgba) */
132 };
133
134 const cairo_solid_pattern_t _cairo_pattern_white = {
135 {
136 CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */
137 CAIRO_STATUS_SUCCESS, /* status */
138 { 0, 0, 0, NULL }, /* user_data */
139 { NULL, NULL }, /* observers */
140
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 */
147 },
148 { 1., 1., 1., 1., 0xffff, 0xffff, 0xffff, 0xffff },/* color (double rgba, short rgba) */
149 };
150
151 static void
_cairo_pattern_notify_observers(cairo_pattern_t * pattern,unsigned int flags)152 _cairo_pattern_notify_observers (cairo_pattern_t *pattern,
153 unsigned int flags)
154 {
155 cairo_pattern_observer_t *pos;
156
157 cairo_list_foreach_entry (pos, cairo_pattern_observer_t, &pattern->observers, link)
158 pos->notify (pos, pattern, flags);
159 }
160
161 /**
162 * _cairo_pattern_set_error:
163 * @pattern: a pattern
164 * @status: a status value indicating an error
165 *
166 * Atomically sets pattern->status to @status and calls _cairo_error;
167 * Does nothing if status is %CAIRO_STATUS_SUCCESS.
168 *
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.
173 *
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.
177 **/
178 static cairo_status_t
_cairo_pattern_set_error(cairo_pattern_t * pattern,cairo_status_t status)179 _cairo_pattern_set_error (cairo_pattern_t *pattern,
180 cairo_status_t status)
181 {
182 if (status == CAIRO_STATUS_SUCCESS)
183 return status;
184
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);
188
189 return _cairo_error (status);
190 }
191
192 void
_cairo_pattern_init(cairo_pattern_t * pattern,cairo_pattern_type_t type)193 _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
194 {
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;
214 }
215 #endif
216
217 pattern->type = type;
218 pattern->status = CAIRO_STATUS_SUCCESS;
219
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);
223
224 _cairo_user_data_array_init (&pattern->user_data);
225
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;
231
232 pattern->filter = CAIRO_FILTER_DEFAULT;
233 pattern->opacity = 1.0;
234
235 pattern->has_component_alpha = FALSE;
236
237 cairo_matrix_init_identity (&pattern->matrix);
238
239 cairo_list_init (&pattern->observers);
240 }
241
242 static cairo_status_t
_cairo_gradient_pattern_init_copy(cairo_gradient_pattern_t * pattern,const cairo_gradient_pattern_t * other)243 _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t *pattern,
244 const cairo_gradient_pattern_t *other)
245 {
246 if (CAIRO_INJECT_FAULT ())
247 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
248
249 if (other->base.type == CAIRO_PATTERN_TYPE_LINEAR)
250 {
251 cairo_linear_pattern_t *dst = (cairo_linear_pattern_t *) pattern;
252 cairo_linear_pattern_t *src = (cairo_linear_pattern_t *) other;
253
254 *dst = *src;
255 }
256 else
257 {
258 cairo_radial_pattern_t *dst = (cairo_radial_pattern_t *) pattern;
259 cairo_radial_pattern_t *src = (cairo_radial_pattern_t *) other;
260
261 *dst = *src;
262 }
263
264 if (other->stops == other->stops_embedded)
265 pattern->stops = pattern->stops_embedded;
266 else if (other->stops)
267 {
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);
274 }
275
276 memcpy (pattern->stops, other->stops,
277 other->n_stops * sizeof (cairo_gradient_stop_t));
278 }
279
280 return CAIRO_STATUS_SUCCESS;
281 }
282
283 static cairo_status_t
_cairo_mesh_pattern_init_copy(cairo_mesh_pattern_t * pattern,const cairo_mesh_pattern_t * other)284 _cairo_mesh_pattern_init_copy (cairo_mesh_pattern_t *pattern,
285 const cairo_mesh_pattern_t *other)
286 {
287 *pattern = *other;
288
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));
293 }
294
295 cairo_status_t
_cairo_pattern_init_copy(cairo_pattern_t * pattern,const cairo_pattern_t * other)296 _cairo_pattern_init_copy (cairo_pattern_t *pattern,
297 const cairo_pattern_t *other)
298 {
299 cairo_status_t status;
300
301 if (other->status)
302 return _cairo_pattern_set_error (pattern, other->status);
303
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;
308
309 VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t)));
310
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;
316
317 VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t)));
318
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;
326
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)));
331 }
332
333 status = _cairo_gradient_pattern_init_copy (dst, src);
334 if (unlikely (status))
335 return status;
336
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;
341
342 VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t)));
343
344 status = _cairo_mesh_pattern_init_copy (dst, src);
345 if (unlikely (status))
346 return status;
347
348 } break;
349
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;
355 }
356
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);
360 cairo_list_init (&pattern->observers);
361
362 return CAIRO_STATUS_SUCCESS;
363 }
364
365 void
_cairo_pattern_init_static_copy(cairo_pattern_t * pattern,const cairo_pattern_t * other)366 _cairo_pattern_init_static_copy (cairo_pattern_t *pattern,
367 const cairo_pattern_t *other)
368 {
369 int size;
370
371 assert (other->status == CAIRO_STATUS_SUCCESS);
372
373 switch (other->type) {
374 default:
375 ASSERT_NOT_REACHED;
376 case CAIRO_PATTERN_TYPE_SOLID:
377 size = sizeof (cairo_solid_pattern_t);
378 break;
379 case CAIRO_PATTERN_TYPE_SURFACE:
380 size = sizeof (cairo_surface_pattern_t);
381 break;
382 case CAIRO_PATTERN_TYPE_LINEAR:
383 size = sizeof (cairo_linear_pattern_t);
384 break;
385 case CAIRO_PATTERN_TYPE_RADIAL:
386 size = sizeof (cairo_radial_pattern_t);
387 break;
388 case CAIRO_PATTERN_TYPE_MESH:
389 size = sizeof (cairo_mesh_pattern_t);
390 break;
391 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
392 size = sizeof (cairo_raster_source_pattern_t);
393 break;
394 }
395
396 memcpy (pattern, other, size);
397
398 CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
399 _cairo_user_data_array_init (&pattern->user_data);
400 cairo_list_init (&pattern->observers);
401 }
402
403 cairo_status_t
_cairo_pattern_init_snapshot(cairo_pattern_t * pattern,const cairo_pattern_t * other)404 _cairo_pattern_init_snapshot (cairo_pattern_t *pattern,
405 const cairo_pattern_t *other)
406 {
407 cairo_status_t status;
408
409 /* We don't bother doing any fancy copy-on-write implementation
410 * for the pattern's data. It's generally quite tiny. */
411 status = _cairo_pattern_init_copy (pattern, other);
412 if (unlikely (status))
413 return status;
414
415 /* But we do let the surface snapshot stuff be as fancy as it
416 * would like to be. */
417 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
418 cairo_surface_pattern_t *surface_pattern =
419 (cairo_surface_pattern_t *) pattern;
420 cairo_surface_t *surface = surface_pattern->surface;
421
422 surface_pattern->surface = _cairo_surface_snapshot (surface);
423
424 cairo_surface_destroy (surface);
425
426 status = surface_pattern->surface->status;
427 } else if (pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
428 status = _cairo_raster_source_pattern_snapshot (pattern);
429
430 return status;
431 }
432
433 void
_cairo_pattern_fini(cairo_pattern_t * pattern)434 _cairo_pattern_fini (cairo_pattern_t *pattern)
435 {
436 _cairo_user_data_array_fini (&pattern->user_data);
437
438 switch (pattern->type) {
439 case CAIRO_PATTERN_TYPE_SOLID:
440 break;
441 case CAIRO_PATTERN_TYPE_SURFACE: {
442 cairo_surface_pattern_t *surface_pattern =
443 (cairo_surface_pattern_t *) pattern;
444
445 cairo_surface_destroy (surface_pattern->surface);
446 } break;
447 case CAIRO_PATTERN_TYPE_LINEAR:
448 case CAIRO_PATTERN_TYPE_RADIAL: {
449 cairo_gradient_pattern_t *gradient =
450 (cairo_gradient_pattern_t *) pattern;
451
452 if (gradient->stops && gradient->stops != gradient->stops_embedded)
453 free (gradient->stops);
454 } break;
455 case CAIRO_PATTERN_TYPE_MESH: {
456 cairo_mesh_pattern_t *mesh =
457 (cairo_mesh_pattern_t *) pattern;
458
459 _cairo_array_fini (&mesh->patches);
460 } break;
461 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
462 _cairo_raster_source_pattern_finish (pattern);
463 break;
464 }
465
466 #if HAVE_VALGRIND
467 switch (pattern->type) {
468 case CAIRO_PATTERN_TYPE_SOLID:
469 VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t));
470 break;
471 case CAIRO_PATTERN_TYPE_SURFACE:
472 VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t));
473 break;
474 case CAIRO_PATTERN_TYPE_LINEAR:
475 VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t));
476 break;
477 case CAIRO_PATTERN_TYPE_RADIAL:
478 VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t));
479 break;
480 case CAIRO_PATTERN_TYPE_MESH:
481 VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t));
482 break;
483 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
484 break;
485 }
486 #endif
487 }
488
489 cairo_status_t
_cairo_pattern_create_copy(cairo_pattern_t ** pattern_out,const cairo_pattern_t * other)490 _cairo_pattern_create_copy (cairo_pattern_t **pattern_out,
491 const cairo_pattern_t *other)
492 {
493 cairo_pattern_t *pattern;
494 cairo_status_t status;
495
496 if (other->status)
497 return other->status;
498
499 switch (other->type) {
500 case CAIRO_PATTERN_TYPE_SOLID:
501 pattern = _cairo_malloc (sizeof (cairo_solid_pattern_t));
502 break;
503 case CAIRO_PATTERN_TYPE_SURFACE:
504 pattern = _cairo_malloc (sizeof (cairo_surface_pattern_t));
505 break;
506 case CAIRO_PATTERN_TYPE_LINEAR:
507 pattern = _cairo_malloc (sizeof (cairo_linear_pattern_t));
508 break;
509 case CAIRO_PATTERN_TYPE_RADIAL:
510 pattern = _cairo_malloc (sizeof (cairo_radial_pattern_t));
511 break;
512 case CAIRO_PATTERN_TYPE_MESH:
513 pattern = _cairo_malloc (sizeof (cairo_mesh_pattern_t));
514 break;
515 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
516 pattern = _cairo_malloc (sizeof (cairo_raster_source_pattern_t));
517 break;
518 default:
519 ASSERT_NOT_REACHED;
520 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
521 }
522 if (unlikely (pattern == NULL))
523 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
524
525 status = _cairo_pattern_init_copy (pattern, other);
526 if (unlikely (status)) {
527 free (pattern);
528 return status;
529 }
530
531 CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
532 *pattern_out = pattern;
533 return CAIRO_STATUS_SUCCESS;
534 }
535
536 void
_cairo_pattern_init_solid(cairo_solid_pattern_t * pattern,const cairo_color_t * color)537 _cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
538 const cairo_color_t *color)
539 {
540 _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
541 pattern->color = *color;
542 }
543
544 void
_cairo_pattern_init_for_surface(cairo_surface_pattern_t * pattern,cairo_surface_t * surface)545 _cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern,
546 cairo_surface_t *surface)
547 {
548 if (surface->status) {
549 /* Force to solid to simplify the pattern_fini process. */
550 _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
551 _cairo_pattern_set_error (&pattern->base, surface->status);
552 return;
553 }
554
555 _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SURFACE);
556
557 pattern->surface = cairo_surface_reference (surface);
558 }
559
560 static void
_cairo_pattern_init_gradient(cairo_gradient_pattern_t * pattern,cairo_pattern_type_t type)561 _cairo_pattern_init_gradient (cairo_gradient_pattern_t *pattern,
562 cairo_pattern_type_t type)
563 {
564 _cairo_pattern_init (&pattern->base, type);
565
566 pattern->n_stops = 0;
567 pattern->stops_size = 0;
568 pattern->stops = NULL;
569 }
570
571 static void
_cairo_pattern_init_linear(cairo_linear_pattern_t * pattern,double x0,double y0,double x1,double y1)572 _cairo_pattern_init_linear (cairo_linear_pattern_t *pattern,
573 double x0, double y0, double x1, double y1)
574 {
575 _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_LINEAR);
576
577 pattern->pd1.x = x0;
578 pattern->pd1.y = y0;
579 pattern->pd2.x = x1;
580 pattern->pd2.y = y1;
581 }
582
583 static void
_cairo_pattern_init_radial(cairo_radial_pattern_t * pattern,double cx0,double cy0,double radius0,double cx1,double cy1,double radius1)584 _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
585 double cx0, double cy0, double radius0,
586 double cx1, double cy1, double radius1)
587 {
588 _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL);
589
590 pattern->cd1.center.x = cx0;
591 pattern->cd1.center.y = cy0;
592 pattern->cd1.radius = fabs (radius0);
593 pattern->cd2.center.x = cx1;
594 pattern->cd2.center.y = cy1;
595 pattern->cd2.radius = fabs (radius1);
596 }
597
598 cairo_pattern_t *
_cairo_pattern_create_solid(const cairo_color_t * color)599 _cairo_pattern_create_solid (const cairo_color_t *color)
600 {
601 cairo_solid_pattern_t *pattern;
602
603 pattern =
604 _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SOLID]);
605 if (unlikely (pattern == NULL)) {
606 /* None cached, need to create a new pattern. */
607 pattern = _cairo_malloc (sizeof (cairo_solid_pattern_t));
608 if (unlikely (pattern == NULL)) {
609 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
610 return (cairo_pattern_t *) &_cairo_pattern_nil;
611 }
612 }
613
614 _cairo_pattern_init_solid (pattern, color);
615 CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
616
617 return &pattern->base;
618 }
619
620 cairo_pattern_t *
_cairo_pattern_create_in_error(cairo_status_t status)621 _cairo_pattern_create_in_error (cairo_status_t status)
622 {
623 cairo_pattern_t *pattern;
624
625 if (status == CAIRO_STATUS_NO_MEMORY)
626 return (cairo_pattern_t *)&_cairo_pattern_nil.base;
627
628 CAIRO_MUTEX_INITIALIZE ();
629
630 pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
631 if (pattern->status == CAIRO_STATUS_SUCCESS)
632 status = _cairo_pattern_set_error (pattern, status);
633
634 return pattern;
635 }
636
637 /**
638 * cairo_pattern_create_rgb:
639 * @red: red component of the color
640 * @green: green component of the color
641 * @blue: blue component of the color
642 *
643 * Creates a new #cairo_pattern_t corresponding to an opaque color. The
644 * color components are floating point numbers in the range 0 to 1.
645 * If the values passed in are outside that range, they will be
646 * clamped.
647 *
648 * Return value: the newly created #cairo_pattern_t if successful, or
649 * an error pattern in case of no memory. The caller owns the
650 * returned object and should call cairo_pattern_destroy() when
651 * finished with it.
652 *
653 * This function will always return a valid pointer, but if an error
654 * occurred the pattern status will be set to an error. To inspect
655 * the status of a pattern use cairo_pattern_status().
656 *
657 * Since: 1.0
658 **/
659 cairo_pattern_t *
cairo_pattern_create_rgb(double red,double green,double blue)660 cairo_pattern_create_rgb (double red, double green, double blue)
661 {
662 return cairo_pattern_create_rgba (red, green, blue, 1.0);
663 }
664 slim_hidden_def (cairo_pattern_create_rgb);
665
666 /**
667 * cairo_pattern_create_rgba:
668 * @red: red component of the color
669 * @green: green component of the color
670 * @blue: blue component of the color
671 * @alpha: alpha component of the color
672 *
673 * Creates a new #cairo_pattern_t corresponding to a translucent color.
674 * The color components are floating point numbers in the range 0 to
675 * 1. If the values passed in are outside that range, they will be
676 * clamped.
677 *
678 * Return value: the newly created #cairo_pattern_t if successful, or
679 * an error pattern in case of no memory. The caller owns the
680 * returned object and should call cairo_pattern_destroy() when
681 * finished with it.
682 *
683 * This function will always return a valid pointer, but if an error
684 * occurred the pattern status will be set to an error. To inspect
685 * the status of a pattern use cairo_pattern_status().
686 *
687 * Since: 1.0
688 **/
689 cairo_pattern_t *
cairo_pattern_create_rgba(double red,double green,double blue,double alpha)690 cairo_pattern_create_rgba (double red, double green, double blue,
691 double alpha)
692 {
693 cairo_color_t color;
694
695 red = _cairo_restrict_value (red, 0.0, 1.0);
696 green = _cairo_restrict_value (green, 0.0, 1.0);
697 blue = _cairo_restrict_value (blue, 0.0, 1.0);
698 alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
699
700 _cairo_color_init_rgba (&color, red, green, blue, alpha);
701
702 CAIRO_MUTEX_INITIALIZE ();
703
704 return _cairo_pattern_create_solid (&color);
705 }
706 slim_hidden_def (cairo_pattern_create_rgba);
707
708 /**
709 * cairo_pattern_create_for_surface:
710 * @surface: the surface
711 *
712 * Create a new #cairo_pattern_t for the given surface.
713 *
714 * Return value: the newly created #cairo_pattern_t if successful, or
715 * an error pattern in case of no memory. The caller owns the
716 * returned object and should call cairo_pattern_destroy() when
717 * finished with it.
718 *
719 * This function will always return a valid pointer, but if an error
720 * occurred the pattern status will be set to an error. To inspect
721 * the status of a pattern use cairo_pattern_status().
722 *
723 * Since: 1.0
724 **/
725 cairo_pattern_t *
cairo_pattern_create_for_surface(cairo_surface_t * surface)726 cairo_pattern_create_for_surface (cairo_surface_t *surface)
727 {
728 cairo_surface_pattern_t *pattern;
729
730 if (surface == NULL) {
731 _cairo_error_throw (CAIRO_STATUS_NULL_POINTER);
732 return (cairo_pattern_t*) &_cairo_pattern_nil_null_pointer;
733 }
734
735 if (surface->status)
736 return _cairo_pattern_create_in_error (surface->status);
737
738 pattern =
739 _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SURFACE]);
740 if (unlikely (pattern == NULL)) {
741 pattern = _cairo_malloc (sizeof (cairo_surface_pattern_t));
742 if (unlikely (pattern == NULL)) {
743 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
744 return (cairo_pattern_t *)&_cairo_pattern_nil.base;
745 }
746 }
747
748 CAIRO_MUTEX_INITIALIZE ();
749
750 _cairo_pattern_init_for_surface (pattern, surface);
751 CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
752
753 return &pattern->base;
754 }
755 slim_hidden_def (cairo_pattern_create_for_surface);
756
757 /**
758 * cairo_pattern_create_linear:
759 * @x0: x coordinate of the start point
760 * @y0: y coordinate of the start point
761 * @x1: x coordinate of the end point
762 * @y1: y coordinate of the end point
763 *
764 * Create a new linear gradient #cairo_pattern_t along the line defined
765 * by (x0, y0) and (x1, y1). Before using the gradient pattern, a
766 * number of color stops should be defined using
767 * cairo_pattern_add_color_stop_rgb() or
768 * cairo_pattern_add_color_stop_rgba().
769 *
770 * Note: The coordinates here are in pattern space. For a new pattern,
771 * pattern space is identical to user space, but the relationship
772 * between the spaces can be changed with cairo_pattern_set_matrix().
773 *
774 * Return value: the newly created #cairo_pattern_t if successful, or
775 * an error pattern in case of no memory. The caller owns the
776 * returned object and should call cairo_pattern_destroy() when
777 * finished with it.
778 *
779 * This function will always return a valid pointer, but if an error
780 * occurred the pattern status will be set to an error. To inspect
781 * the status of a pattern use cairo_pattern_status().
782 *
783 * Since: 1.0
784 **/
785 cairo_pattern_t *
cairo_pattern_create_linear(double x0,double y0,double x1,double y1)786 cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
787 {
788 cairo_linear_pattern_t *pattern;
789
790 pattern =
791 _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_LINEAR]);
792 if (unlikely (pattern == NULL)) {
793 pattern = _cairo_malloc (sizeof (cairo_linear_pattern_t));
794 if (unlikely (pattern == NULL)) {
795 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
796 return (cairo_pattern_t *) &_cairo_pattern_nil.base;
797 }
798 }
799
800 CAIRO_MUTEX_INITIALIZE ();
801
802 _cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
803 CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
804
805 return &pattern->base.base;
806 }
807
808 /**
809 * cairo_pattern_create_radial:
810 * @cx0: x coordinate for the center of the start circle
811 * @cy0: y coordinate for the center of the start circle
812 * @radius0: radius of the start circle
813 * @cx1: x coordinate for the center of the end circle
814 * @cy1: y coordinate for the center of the end circle
815 * @radius1: radius of the end circle
816 *
817 * Creates a new radial gradient #cairo_pattern_t between the two
818 * circles defined by (cx0, cy0, radius0) and (cx1, cy1, radius1). Before using the
819 * gradient pattern, a number of color stops should be defined using
820 * cairo_pattern_add_color_stop_rgb() or
821 * cairo_pattern_add_color_stop_rgba().
822 *
823 * Note: The coordinates here are in pattern space. For a new pattern,
824 * pattern space is identical to user space, but the relationship
825 * between the spaces can be changed with cairo_pattern_set_matrix().
826 *
827 * Return value: the newly created #cairo_pattern_t if successful, or
828 * an error pattern in case of no memory. The caller owns the
829 * returned object and should call cairo_pattern_destroy() when
830 * finished with it.
831 *
832 * This function will always return a valid pointer, but if an error
833 * occurred the pattern status will be set to an error. To inspect
834 * the status of a pattern use cairo_pattern_status().
835 *
836 * Since: 1.0
837 **/
838 cairo_pattern_t *
cairo_pattern_create_radial(double cx0,double cy0,double radius0,double cx1,double cy1,double radius1)839 cairo_pattern_create_radial (double cx0, double cy0, double radius0,
840 double cx1, double cy1, double radius1)
841 {
842 cairo_radial_pattern_t *pattern;
843
844 pattern =
845 _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_RADIAL]);
846 if (unlikely (pattern == NULL)) {
847 pattern = _cairo_malloc (sizeof (cairo_radial_pattern_t));
848 if (unlikely (pattern == NULL)) {
849 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
850 return (cairo_pattern_t *) &_cairo_pattern_nil.base;
851 }
852 }
853
854 CAIRO_MUTEX_INITIALIZE ();
855
856 _cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
857 CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
858
859 return &pattern->base.base;
860 }
861
862 /* This order is specified in the diagram in the documentation for
863 * cairo_pattern_create_mesh() */
864 static const int mesh_path_point_i[12] = { 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1 };
865 static const int mesh_path_point_j[12] = { 0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0 };
866 static const int mesh_control_point_i[4] = { 1, 1, 2, 2 };
867 static const int mesh_control_point_j[4] = { 1, 2, 2, 1 };
868
869 /**
870 * cairo_pattern_create_mesh:
871 *
872 * Create a new mesh pattern.
873 *
874 * Mesh patterns are tensor-product patch meshes (type 7 shadings in
875 * PDF). Mesh patterns may also be used to create other types of
876 * shadings that are special cases of tensor-product patch meshes such
877 * as Coons patch meshes (type 6 shading in PDF) and Gouraud-shaded
878 * triangle meshes (type 4 and 5 shadings in PDF).
879 *
880 * Mesh patterns consist of one or more tensor-product patches, which
881 * should be defined before using the mesh pattern. Using a mesh
882 * pattern with a partially defined patch as source or mask will put
883 * the context in an error status with a status of
884 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
885 *
886 * A tensor-product patch is defined by 4 Bézier curves (side 0, 1, 2,
887 * 3) and by 4 additional control points (P0, P1, P2, P3) that provide
888 * further control over the patch and complete the definition of the
889 * tensor-product patch. The corner C0 is the first point of the
890 * patch.
891 *
892 * Degenerate sides are permitted so straight lines may be used. A
893 * zero length line on one side may be used to create 3 sided patches.
894 *
895 * <informalexample><screen>
896 * C1 Side 1 C2
897 * +---------------+
898 * | |
899 * | P1 P2 |
900 * | |
901 * Side 0 | | Side 2
902 * | |
903 * | |
904 * | P0 P3 |
905 * | |
906 * +---------------+
907 * C0 Side 3 C3
908 * </screen></informalexample>
909 *
910 * Each patch is constructed by first calling
911 * cairo_mesh_pattern_begin_patch(), then cairo_mesh_pattern_move_to()
912 * to specify the first point in the patch (C0). Then the sides are
913 * specified with calls to cairo_mesh_pattern_curve_to() and
914 * cairo_mesh_pattern_line_to().
915 *
916 * The four additional control points (P0, P1, P2, P3) in a patch can
917 * be specified with cairo_mesh_pattern_set_control_point().
918 *
919 * At each corner of the patch (C0, C1, C2, C3) a color may be
920 * specified with cairo_mesh_pattern_set_corner_color_rgb() or
921 * cairo_mesh_pattern_set_corner_color_rgba(). Any corner whose color
922 * is not explicitly specified defaults to transparent black.
923 *
924 * A Coons patch is a special case of the tensor-product patch where
925 * the control points are implicitly defined by the sides of the
926 * patch. The default value for any control point not specified is the
927 * implicit value for a Coons patch, i.e. if no control points are
928 * specified the patch is a Coons patch.
929 *
930 * A triangle is a special case of the tensor-product patch where the
931 * control points are implicitly defined by the sides of the patch,
932 * all the sides are lines and one of them has length 0, i.e. if the
933 * patch is specified using just 3 lines, it is a triangle. If the
934 * corners connected by the 0-length side have the same color, the
935 * patch is a Gouraud-shaded triangle.
936 *
937 * Patches may be oriented differently to the above diagram. For
938 * example the first point could be at the top left. The diagram only
939 * shows the relationship between the sides, corners and control
940 * points. Regardless of where the first point is located, when
941 * specifying colors, corner 0 will always be the first point, corner
942 * 1 the point between side 0 and side 1 etc.
943 *
944 * Calling cairo_mesh_pattern_end_patch() completes the current
945 * patch. If less than 4 sides have been defined, the first missing
946 * side is defined as a line from the current point to the first point
947 * of the patch (C0) and the other sides are degenerate lines from C0
948 * to C0. The corners between the added sides will all be coincident
949 * with C0 of the patch and their color will be set to be the same as
950 * the color of C0.
951 *
952 * Additional patches may be added with additional calls to
953 * cairo_mesh_pattern_begin_patch()/cairo_mesh_pattern_end_patch().
954 *
955 * <informalexample><programlisting>
956 * cairo_pattern_t *pattern = cairo_pattern_create_mesh ();
957 *
958 * /* Add a Coons patch */
959 * cairo_mesh_pattern_begin_patch (pattern);
960 * cairo_mesh_pattern_move_to (pattern, 0, 0);
961 * cairo_mesh_pattern_curve_to (pattern, 30, -30, 60, 30, 100, 0);
962 * cairo_mesh_pattern_curve_to (pattern, 60, 30, 130, 60, 100, 100);
963 * cairo_mesh_pattern_curve_to (pattern, 60, 70, 30, 130, 0, 100);
964 * cairo_mesh_pattern_curve_to (pattern, 30, 70, -30, 30, 0, 0);
965 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 0, 1, 0, 0);
966 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 1, 0, 1, 0);
967 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 2, 0, 0, 1);
968 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 3, 1, 1, 0);
969 * cairo_mesh_pattern_end_patch (pattern);
970 *
971 * /* Add a Gouraud-shaded triangle */
972 * cairo_mesh_pattern_begin_patch (pattern)
973 * cairo_mesh_pattern_move_to (pattern, 100, 100);
974 * cairo_mesh_pattern_line_to (pattern, 130, 130);
975 * cairo_mesh_pattern_line_to (pattern, 130, 70);
976 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 0, 1, 0, 0);
977 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 1, 0, 1, 0);
978 * cairo_mesh_pattern_set_corner_color_rgb (pattern, 2, 0, 0, 1);
979 * cairo_mesh_pattern_end_patch (pattern)
980 * </programlisting></informalexample>
981 *
982 * When two patches overlap, the last one that has been added is drawn
983 * over the first one.
984 *
985 * When a patch folds over itself, points are sorted depending on
986 * their parameter coordinates inside the patch. The v coordinate
987 * ranges from 0 to 1 when moving from side 3 to side 1; the u
988 * coordinate ranges from 0 to 1 when going from side 0 to side
989 * 2. Points with higher v coordinate hide points with lower v
990 * coordinate. When two points have the same v coordinate, the one
991 * with higher u coordinate is above. This means that points nearer to
992 * side 1 are above points nearer to side 3; when this is not
993 * sufficient to decide which point is above (for example when both
994 * points belong to side 1 or side 3) points nearer to side 2 are
995 * above points nearer to side 0.
996 *
997 * For a complete definition of tensor-product patches, see the PDF
998 * specification (ISO32000), which describes the parametrization in
999 * detail.
1000 *
1001 * Note: The coordinates are always in pattern space. For a new
1002 * pattern, pattern space is identical to user space, but the
1003 * relationship between the spaces can be changed with
1004 * cairo_pattern_set_matrix().
1005 *
1006 * Return value: the newly created #cairo_pattern_t if successful, or
1007 * an error pattern in case of no memory. The caller owns the returned
1008 * object and should call cairo_pattern_destroy() when finished with
1009 * it.
1010 *
1011 * This function will always return a valid pointer, but if an error
1012 * occurred the pattern status will be set to an error. To inspect the
1013 * status of a pattern use cairo_pattern_status().
1014 *
1015 * Since: 1.12
1016 **/
1017 cairo_pattern_t *
cairo_pattern_create_mesh(void)1018 cairo_pattern_create_mesh (void)
1019 {
1020 cairo_mesh_pattern_t *pattern;
1021
1022 pattern =
1023 _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_MESH]);
1024 if (unlikely (pattern == NULL)) {
1025 pattern = _cairo_malloc (sizeof (cairo_mesh_pattern_t));
1026 if (unlikely (pattern == NULL)) {
1027 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1028 return (cairo_pattern_t *) &_cairo_pattern_nil.base;
1029 }
1030 }
1031
1032 CAIRO_MUTEX_INITIALIZE ();
1033
1034 _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_MESH);
1035 _cairo_array_init (&pattern->patches, sizeof (cairo_mesh_patch_t));
1036 pattern->current_patch = NULL;
1037 CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
1038
1039 return &pattern->base;
1040 }
1041
1042 /**
1043 * cairo_pattern_reference:
1044 * @pattern: a #cairo_pattern_t
1045 *
1046 * Increases the reference count on @pattern by one. This prevents
1047 * @pattern from being destroyed until a matching call to
1048 * cairo_pattern_destroy() is made.
1049 *
1050 * Use cairo_pattern_get_reference_count() to get the number of
1051 * references to a #cairo_pattern_t.
1052 *
1053 * Return value: the referenced #cairo_pattern_t.
1054 *
1055 * Since: 1.0
1056 **/
1057 cairo_pattern_t *
cairo_pattern_reference(cairo_pattern_t * pattern)1058 cairo_pattern_reference (cairo_pattern_t *pattern)
1059 {
1060 if (pattern == NULL ||
1061 CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1062 return pattern;
1063
1064 assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
1065
1066 _cairo_reference_count_inc (&pattern->ref_count);
1067
1068 return pattern;
1069 }
1070 slim_hidden_def (cairo_pattern_reference);
1071
1072 /**
1073 * cairo_pattern_get_type:
1074 * @pattern: a #cairo_pattern_t
1075 *
1076 * Get the pattern's type. See #cairo_pattern_type_t for available
1077 * types.
1078 *
1079 * Return value: The type of @pattern.
1080 *
1081 * Since: 1.2
1082 **/
1083 cairo_pattern_type_t
cairo_pattern_get_type(cairo_pattern_t * pattern)1084 cairo_pattern_get_type (cairo_pattern_t *pattern)
1085 {
1086 return pattern->type;
1087 }
1088
1089 /**
1090 * cairo_pattern_status:
1091 * @pattern: a #cairo_pattern_t
1092 *
1093 * Checks whether an error has previously occurred for this
1094 * pattern.
1095 *
1096 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NO_MEMORY,
1097 * %CAIRO_STATUS_INVALID_MATRIX, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH,
1098 * or %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1099 *
1100 * Since: 1.0
1101 **/
1102 cairo_status_t
cairo_pattern_status(cairo_pattern_t * pattern)1103 cairo_pattern_status (cairo_pattern_t *pattern)
1104 {
1105 return pattern->status;
1106 }
1107
1108 /**
1109 * cairo_pattern_destroy:
1110 * @pattern: a #cairo_pattern_t
1111 *
1112 * Decreases the reference count on @pattern by one. If the result is
1113 * zero, then @pattern and all associated resources are freed. See
1114 * cairo_pattern_reference().
1115 *
1116 * Since: 1.0
1117 **/
1118 void
cairo_pattern_destroy(cairo_pattern_t * pattern)1119 cairo_pattern_destroy (cairo_pattern_t *pattern)
1120 {
1121 cairo_pattern_type_t type;
1122
1123 if (pattern == NULL ||
1124 CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1125 return;
1126
1127 assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
1128
1129 if (! _cairo_reference_count_dec_and_test (&pattern->ref_count))
1130 return;
1131
1132 type = pattern->type;
1133 _cairo_pattern_fini (pattern);
1134
1135 /* maintain a small cache of freed patterns */
1136 if (type < ARRAY_LENGTH (freed_pattern_pool))
1137 _freed_pool_put (&freed_pattern_pool[type], pattern);
1138 else
1139 free (pattern);
1140 }
1141 slim_hidden_def (cairo_pattern_destroy);
1142
1143 /**
1144 * cairo_pattern_get_reference_count:
1145 * @pattern: a #cairo_pattern_t
1146 *
1147 * Returns the current reference count of @pattern.
1148 *
1149 * Return value: the current reference count of @pattern. If the
1150 * object is a nil object, 0 will be returned.
1151 *
1152 * Since: 1.4
1153 **/
1154 unsigned int
cairo_pattern_get_reference_count(cairo_pattern_t * pattern)1155 cairo_pattern_get_reference_count (cairo_pattern_t *pattern)
1156 {
1157 if (pattern == NULL ||
1158 CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1159 return 0;
1160
1161 return CAIRO_REFERENCE_COUNT_GET_VALUE (&pattern->ref_count);
1162 }
1163
1164 /**
1165 * cairo_pattern_get_user_data:
1166 * @pattern: a #cairo_pattern_t
1167 * @key: the address of the #cairo_user_data_key_t the user data was
1168 * attached to
1169 *
1170 * Return user data previously attached to @pattern using the
1171 * specified key. If no user data has been attached with the given
1172 * key this function returns %NULL.
1173 *
1174 * Return value: the user data previously attached or %NULL.
1175 *
1176 * Since: 1.4
1177 **/
1178 void *
cairo_pattern_get_user_data(cairo_pattern_t * pattern,const cairo_user_data_key_t * key)1179 cairo_pattern_get_user_data (cairo_pattern_t *pattern,
1180 const cairo_user_data_key_t *key)
1181 {
1182 return _cairo_user_data_array_get_data (&pattern->user_data,
1183 key);
1184 }
1185
1186 /**
1187 * cairo_pattern_set_user_data:
1188 * @pattern: a #cairo_pattern_t
1189 * @key: the address of a #cairo_user_data_key_t to attach the user data to
1190 * @user_data: the user data to attach to the #cairo_pattern_t
1191 * @destroy: a #cairo_destroy_func_t which will be called when the
1192 * #cairo_t is destroyed or when new user data is attached using the
1193 * same key.
1194 *
1195 * Attach user data to @pattern. To remove user data from a surface,
1196 * call this function with the key that was used to set it and %NULL
1197 * for @data.
1198 *
1199 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
1200 * slot could not be allocated for the user data.
1201 *
1202 * Since: 1.4
1203 **/
1204 cairo_status_t
cairo_pattern_set_user_data(cairo_pattern_t * pattern,const cairo_user_data_key_t * key,void * user_data,cairo_destroy_func_t destroy)1205 cairo_pattern_set_user_data (cairo_pattern_t *pattern,
1206 const cairo_user_data_key_t *key,
1207 void *user_data,
1208 cairo_destroy_func_t destroy)
1209 {
1210 if (CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
1211 return pattern->status;
1212
1213 return _cairo_user_data_array_set_data (&pattern->user_data,
1214 key, user_data, destroy);
1215 }
1216
1217 /**
1218 * cairo_mesh_pattern_begin_patch:
1219 * @pattern: a #cairo_pattern_t
1220 *
1221 * Begin a patch in a mesh pattern.
1222 *
1223 * After calling this function, the patch shape should be defined with
1224 * cairo_mesh_pattern_move_to(), cairo_mesh_pattern_line_to() and
1225 * cairo_mesh_pattern_curve_to().
1226 *
1227 * After defining the patch, cairo_mesh_pattern_end_patch() must be
1228 * called before using @pattern as a source or mask.
1229 *
1230 * Note: If @pattern is not a mesh pattern then @pattern will be put
1231 * into an error status with a status of
1232 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern already has a
1233 * current patch, it will be put into an error status with a status of
1234 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1235 *
1236 * Since: 1.12
1237 **/
1238 void
cairo_mesh_pattern_begin_patch(cairo_pattern_t * pattern)1239 cairo_mesh_pattern_begin_patch (cairo_pattern_t *pattern)
1240 {
1241 cairo_mesh_pattern_t *mesh;
1242 cairo_status_t status;
1243 cairo_mesh_patch_t *current_patch;
1244 int i;
1245
1246 if (unlikely (pattern->status))
1247 return;
1248
1249 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1250 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1251 return;
1252 }
1253
1254 mesh = (cairo_mesh_pattern_t *) pattern;
1255 if (unlikely (mesh->current_patch)) {
1256 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1257 return;
1258 }
1259
1260 status = _cairo_array_allocate (&mesh->patches, 1, (void **) ¤t_patch);
1261 if (unlikely (status)) {
1262 _cairo_pattern_set_error (pattern, status);
1263 return;
1264 }
1265
1266 mesh->current_patch = current_patch;
1267 mesh->current_side = -2; /* no current point */
1268
1269 for (i = 0; i < 4; i++)
1270 mesh->has_control_point[i] = FALSE;
1271
1272 for (i = 0; i < 4; i++)
1273 mesh->has_color[i] = FALSE;
1274 }
1275
1276
1277 static void
_calc_control_point(cairo_mesh_patch_t * patch,int control_point)1278 _calc_control_point (cairo_mesh_patch_t *patch, int control_point)
1279 {
1280 /* The Coons patch is a special case of the Tensor Product patch
1281 * where the four control points are:
1282 *
1283 * P11 = S(1/3, 1/3)
1284 * P12 = S(1/3, 2/3)
1285 * P21 = S(2/3, 1/3)
1286 * P22 = S(2/3, 2/3)
1287 *
1288 * where S is the gradient surface.
1289 *
1290 * When one or more control points has not been specified
1291 * calculated the Coons patch control points are substituted. If
1292 * no control points are specified the gradient will be a Coons
1293 * patch.
1294 *
1295 * The equations below are defined in the ISO32000 standard.
1296 */
1297 cairo_point_double_t *p[3][3];
1298 int cp_i, cp_j, i, j;
1299
1300 cp_i = mesh_control_point_i[control_point];
1301 cp_j = mesh_control_point_j[control_point];
1302
1303 for (i = 0; i < 3; i++)
1304 for (j = 0; j < 3; j++)
1305 p[i][j] = &patch->points[cp_i ^ i][cp_j ^ j];
1306
1307 p[0][0]->x = (- 4 * p[1][1]->x
1308 + 6 * (p[1][0]->x + p[0][1]->x)
1309 - 2 * (p[1][2]->x + p[2][1]->x)
1310 + 3 * (p[2][0]->x + p[0][2]->x)
1311 - 1 * p[2][2]->x) * (1. / 9);
1312
1313 p[0][0]->y = (- 4 * p[1][1]->y
1314 + 6 * (p[1][0]->y + p[0][1]->y)
1315 - 2 * (p[1][2]->y + p[2][1]->y)
1316 + 3 * (p[2][0]->y + p[0][2]->y)
1317 - 1 * p[2][2]->y) * (1. / 9);
1318 }
1319
1320 /**
1321 * cairo_mesh_pattern_end_patch:
1322 * @pattern: a #cairo_pattern_t
1323 *
1324 * Indicates the end of the current patch in a mesh pattern.
1325 *
1326 * If the current patch has less than 4 sides, it is closed with a
1327 * straight line from the current point to the first point of the
1328 * patch as if cairo_mesh_pattern_line_to() was used.
1329 *
1330 * Note: If @pattern is not a mesh pattern then @pattern will be put
1331 * into an error status with a status of
1332 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
1333 * patch or the current patch has no current point, @pattern will be
1334 * put into an error status with a status of
1335 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1336 *
1337 * Since: 1.12
1338 **/
1339 void
cairo_mesh_pattern_end_patch(cairo_pattern_t * pattern)1340 cairo_mesh_pattern_end_patch (cairo_pattern_t *pattern)
1341 {
1342 cairo_mesh_pattern_t *mesh;
1343 cairo_mesh_patch_t *current_patch;
1344 int i;
1345
1346 if (unlikely (pattern->status))
1347 return;
1348
1349 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1350 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1351 return;
1352 }
1353
1354 mesh = (cairo_mesh_pattern_t *) pattern;
1355 current_patch = mesh->current_patch;
1356 if (unlikely (!current_patch)) {
1357 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1358 return;
1359 }
1360
1361 if (unlikely (mesh->current_side == -2)) {
1362 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1363 return;
1364 }
1365
1366 while (mesh->current_side < 3) {
1367 int corner_num;
1368
1369 cairo_mesh_pattern_line_to (pattern,
1370 current_patch->points[0][0].x,
1371 current_patch->points[0][0].y);
1372
1373 corner_num = mesh->current_side + 1;
1374 if (corner_num < 4 && ! mesh->has_color[corner_num]) {
1375 current_patch->colors[corner_num] = current_patch->colors[0];
1376 mesh->has_color[corner_num] = TRUE;
1377 }
1378 }
1379
1380 for (i = 0; i < 4; i++) {
1381 if (! mesh->has_control_point[i])
1382 _calc_control_point (current_patch, i);
1383 }
1384
1385 for (i = 0; i < 4; i++) {
1386 if (! mesh->has_color[i])
1387 current_patch->colors[i] = *CAIRO_COLOR_TRANSPARENT;
1388 }
1389
1390 mesh->current_patch = NULL;
1391 }
1392
1393 /**
1394 * cairo_mesh_pattern_curve_to:
1395 * @pattern: a #cairo_pattern_t
1396 * @x1: the X coordinate of the first control point
1397 * @y1: the Y coordinate of the first control point
1398 * @x2: the X coordinate of the second control point
1399 * @y2: the Y coordinate of the second control point
1400 * @x3: the X coordinate of the end of the curve
1401 * @y3: the Y coordinate of the end of the curve
1402 *
1403 * Adds a cubic Bézier spline to the current patch from the current
1404 * point to position (@x3, @y3) in pattern-space coordinates, using
1405 * (@x1, @y1) and (@x2, @y2) as the control points.
1406 *
1407 * If the current patch has no current point before the call to
1408 * cairo_mesh_pattern_curve_to(), this function will behave as if
1409 * preceded by a call to cairo_mesh_pattern_move_to(@pattern, @x1,
1410 * @y1).
1411 *
1412 * After this call the current point will be (@x3, @y3).
1413 *
1414 * Note: If @pattern is not a mesh pattern then @pattern will be put
1415 * into an error status with a status of
1416 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
1417 * patch or the current patch already has 4 sides, @pattern will be
1418 * put into an error status with a status of
1419 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1420 *
1421 * Since: 1.12
1422 **/
1423 void
cairo_mesh_pattern_curve_to(cairo_pattern_t * pattern,double x1,double y1,double x2,double y2,double x3,double y3)1424 cairo_mesh_pattern_curve_to (cairo_pattern_t *pattern,
1425 double x1, double y1,
1426 double x2, double y2,
1427 double x3, double y3)
1428 {
1429 cairo_mesh_pattern_t *mesh;
1430 int current_point, i, j;
1431
1432 if (unlikely (pattern->status))
1433 return;
1434
1435 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1436 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1437 return;
1438 }
1439
1440 mesh = (cairo_mesh_pattern_t *) pattern;
1441 if (unlikely (!mesh->current_patch)) {
1442 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1443 return;
1444 }
1445
1446 if (unlikely (mesh->current_side == 3)) {
1447 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1448 return;
1449 }
1450
1451 if (mesh->current_side == -2)
1452 cairo_mesh_pattern_move_to (pattern, x1, y1);
1453
1454 assert (mesh->current_side >= -1);
1455 assert (pattern->status == CAIRO_STATUS_SUCCESS);
1456
1457 mesh->current_side++;
1458
1459 current_point = 3 * mesh->current_side;
1460
1461 current_point++;
1462 i = mesh_path_point_i[current_point];
1463 j = mesh_path_point_j[current_point];
1464 mesh->current_patch->points[i][j].x = x1;
1465 mesh->current_patch->points[i][j].y = y1;
1466
1467 current_point++;
1468 i = mesh_path_point_i[current_point];
1469 j = mesh_path_point_j[current_point];
1470 mesh->current_patch->points[i][j].x = x2;
1471 mesh->current_patch->points[i][j].y = y2;
1472
1473 current_point++;
1474 if (current_point < 12) {
1475 i = mesh_path_point_i[current_point];
1476 j = mesh_path_point_j[current_point];
1477 mesh->current_patch->points[i][j].x = x3;
1478 mesh->current_patch->points[i][j].y = y3;
1479 }
1480 }
1481 slim_hidden_def (cairo_mesh_pattern_curve_to);
1482
1483 /**
1484 * cairo_mesh_pattern_line_to:
1485 * @pattern: a #cairo_pattern_t
1486 * @x: the X coordinate of the end of the new line
1487 * @y: the Y coordinate of the end of the new line
1488 *
1489 * Adds a line to the current patch from the current point to position
1490 * (@x, @y) in pattern-space coordinates.
1491 *
1492 * If there is no current point before the call to
1493 * cairo_mesh_pattern_line_to() this function will behave as
1494 * cairo_mesh_pattern_move_to(@pattern, @x, @y).
1495 *
1496 * After this call the current point will be (@x, @y).
1497 *
1498 * Note: If @pattern is not a mesh pattern then @pattern will be put
1499 * into an error status with a status of
1500 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
1501 * patch or the current patch already has 4 sides, @pattern will be
1502 * put into an error status with a status of
1503 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1504 *
1505 * Since: 1.12
1506 **/
1507 void
cairo_mesh_pattern_line_to(cairo_pattern_t * pattern,double x,double y)1508 cairo_mesh_pattern_line_to (cairo_pattern_t *pattern,
1509 double x, double y)
1510 {
1511 cairo_mesh_pattern_t *mesh;
1512 cairo_point_double_t last_point;
1513 int last_point_idx, i, j;
1514
1515 if (unlikely (pattern->status))
1516 return;
1517
1518 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1519 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1520 return;
1521 }
1522
1523 mesh = (cairo_mesh_pattern_t *) pattern;
1524 if (unlikely (!mesh->current_patch)) {
1525 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1526 return;
1527 }
1528
1529 if (unlikely (mesh->current_side == 3)) {
1530 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1531 return;
1532 }
1533
1534 if (mesh->current_side == -2) {
1535 cairo_mesh_pattern_move_to (pattern, x, y);
1536 return;
1537 }
1538
1539 last_point_idx = 3 * (mesh->current_side + 1);
1540 i = mesh_path_point_i[last_point_idx];
1541 j = mesh_path_point_j[last_point_idx];
1542
1543 last_point = mesh->current_patch->points[i][j];
1544
1545 cairo_mesh_pattern_curve_to (pattern,
1546 (2 * last_point.x + x) * (1. / 3),
1547 (2 * last_point.y + y) * (1. / 3),
1548 (last_point.x + 2 * x) * (1. / 3),
1549 (last_point.y + 2 * y) * (1. / 3),
1550 x, y);
1551 }
1552 slim_hidden_def (cairo_mesh_pattern_line_to);
1553
1554 /**
1555 * cairo_mesh_pattern_move_to:
1556 * @pattern: a #cairo_pattern_t
1557 * @x: the X coordinate of the new position
1558 * @y: the Y coordinate of the new position
1559 *
1560 * Define the first point of the current patch in a mesh pattern.
1561 *
1562 * After this call the current point will be (@x, @y).
1563 *
1564 * Note: If @pattern is not a mesh pattern then @pattern will be put
1565 * into an error status with a status of
1566 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @pattern has no current
1567 * patch or the current patch already has at least one side, @pattern
1568 * will be put into an error status with a status of
1569 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1570 *
1571 * Since: 1.12
1572 **/
1573 void
cairo_mesh_pattern_move_to(cairo_pattern_t * pattern,double x,double y)1574 cairo_mesh_pattern_move_to (cairo_pattern_t *pattern,
1575 double x, double y)
1576 {
1577 cairo_mesh_pattern_t *mesh;
1578
1579 if (unlikely (pattern->status))
1580 return;
1581
1582 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1583 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1584 return;
1585 }
1586
1587 mesh = (cairo_mesh_pattern_t *) pattern;
1588 if (unlikely (!mesh->current_patch)) {
1589 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1590 return;
1591 }
1592
1593 if (unlikely (mesh->current_side >= 0)) {
1594 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1595 return;
1596 }
1597
1598 mesh->current_side = -1;
1599 mesh->current_patch->points[0][0].x = x;
1600 mesh->current_patch->points[0][0].y = y;
1601 }
1602 slim_hidden_def (cairo_mesh_pattern_move_to);
1603
1604 /**
1605 * cairo_mesh_pattern_set_control_point:
1606 * @pattern: a #cairo_pattern_t
1607 * @point_num: the control point to set the position for
1608 * @x: the X coordinate of the control point
1609 * @y: the Y coordinate of the control point
1610 *
1611 * Set an internal control point of the current patch.
1612 *
1613 * Valid values for @point_num are from 0 to 3 and identify the
1614 * control points as explained in cairo_pattern_create_mesh().
1615 *
1616 * Note: If @pattern is not a mesh pattern then @pattern will be put
1617 * into an error status with a status of
1618 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @point_num is not valid,
1619 * @pattern will be put into an error status with a status of
1620 * %CAIRO_STATUS_INVALID_INDEX. If @pattern has no current patch,
1621 * @pattern will be put into an error status with a status of
1622 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1623 *
1624 * Since: 1.12
1625 **/
1626 void
cairo_mesh_pattern_set_control_point(cairo_pattern_t * pattern,unsigned int point_num,double x,double y)1627 cairo_mesh_pattern_set_control_point (cairo_pattern_t *pattern,
1628 unsigned int point_num,
1629 double x,
1630 double y)
1631 {
1632 cairo_mesh_pattern_t *mesh;
1633 int i, j;
1634
1635 if (unlikely (pattern->status))
1636 return;
1637
1638 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1639 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1640 return;
1641 }
1642
1643 if (unlikely (point_num > 3)) {
1644 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_INDEX);
1645 return;
1646 }
1647
1648 mesh = (cairo_mesh_pattern_t *) pattern;
1649 if (unlikely (!mesh->current_patch)) {
1650 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1651 return;
1652 }
1653
1654 i = mesh_control_point_i[point_num];
1655 j = mesh_control_point_j[point_num];
1656
1657 mesh->current_patch->points[i][j].x = x;
1658 mesh->current_patch->points[i][j].y = y;
1659 mesh->has_control_point[point_num] = TRUE;
1660 }
1661
1662 /* make room for at least one more color stop */
1663 static cairo_status_t
_cairo_pattern_gradient_grow(cairo_gradient_pattern_t * pattern)1664 _cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
1665 {
1666 cairo_gradient_stop_t *new_stops;
1667 int old_size = pattern->stops_size;
1668 int embedded_size = ARRAY_LENGTH (pattern->stops_embedded);
1669 int new_size = 2 * MAX (old_size, 4);
1670
1671 /* we have a local buffer at pattern->stops_embedded. try to fulfill the request
1672 * from there. */
1673 if (old_size < embedded_size) {
1674 pattern->stops = pattern->stops_embedded;
1675 pattern->stops_size = embedded_size;
1676 return CAIRO_STATUS_SUCCESS;
1677 }
1678
1679 if (CAIRO_INJECT_FAULT ())
1680 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1681
1682 assert (pattern->n_stops <= pattern->stops_size);
1683
1684 if (pattern->stops == pattern->stops_embedded) {
1685 new_stops = _cairo_malloc_ab (new_size, sizeof (cairo_gradient_stop_t));
1686 if (new_stops)
1687 memcpy (new_stops, pattern->stops, old_size * sizeof (cairo_gradient_stop_t));
1688 } else {
1689 new_stops = _cairo_realloc_ab (pattern->stops,
1690 new_size,
1691 sizeof (cairo_gradient_stop_t));
1692 }
1693
1694 if (unlikely (new_stops == NULL))
1695 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1696
1697 pattern->stops = new_stops;
1698 pattern->stops_size = new_size;
1699
1700 return CAIRO_STATUS_SUCCESS;
1701 }
1702
1703 static void
_cairo_mesh_pattern_set_corner_color(cairo_mesh_pattern_t * mesh,unsigned int corner_num,double red,double green,double blue,double alpha)1704 _cairo_mesh_pattern_set_corner_color (cairo_mesh_pattern_t *mesh,
1705 unsigned int corner_num,
1706 double red, double green, double blue,
1707 double alpha)
1708 {
1709 cairo_color_t *color;
1710
1711 assert (mesh->current_patch);
1712 assert (corner_num <= 3);
1713
1714 color = &mesh->current_patch->colors[corner_num];
1715 color->red = red;
1716 color->green = green;
1717 color->blue = blue;
1718 color->alpha = alpha;
1719
1720 color->red_short = _cairo_color_double_to_short (red);
1721 color->green_short = _cairo_color_double_to_short (green);
1722 color->blue_short = _cairo_color_double_to_short (blue);
1723 color->alpha_short = _cairo_color_double_to_short (alpha);
1724
1725 mesh->has_color[corner_num] = TRUE;
1726 }
1727
1728 /**
1729 * cairo_mesh_pattern_set_corner_color_rgb:
1730 * @pattern: a #cairo_pattern_t
1731 * @corner_num: the corner to set the color for
1732 * @red: red component of color
1733 * @green: green component of color
1734 * @blue: blue component of color
1735 *
1736 * Sets the color of a corner of the current patch in a mesh pattern.
1737 *
1738 * The color is specified in the same way as in cairo_set_source_rgb().
1739 *
1740 * Valid values for @corner_num are from 0 to 3 and identify the
1741 * corners as explained in cairo_pattern_create_mesh().
1742 *
1743 * Note: If @pattern is not a mesh pattern then @pattern will be put
1744 * into an error status with a status of
1745 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @corner_num is not valid,
1746 * @pattern will be put into an error status with a status of
1747 * %CAIRO_STATUS_INVALID_INDEX. If @pattern has no current patch,
1748 * @pattern will be put into an error status with a status of
1749 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1750 *
1751 * Since: 1.12
1752 **/
1753 void
cairo_mesh_pattern_set_corner_color_rgb(cairo_pattern_t * pattern,unsigned int corner_num,double red,double green,double blue)1754 cairo_mesh_pattern_set_corner_color_rgb (cairo_pattern_t *pattern,
1755 unsigned int corner_num,
1756 double red, double green, double blue)
1757 {
1758 cairo_mesh_pattern_set_corner_color_rgba (pattern, corner_num, red, green, blue, 1.0);
1759 }
1760
1761 /**
1762 * cairo_mesh_pattern_set_corner_color_rgba:
1763 * @pattern: a #cairo_pattern_t
1764 * @corner_num: the corner to set the color for
1765 * @red: red component of color
1766 * @green: green component of color
1767 * @blue: blue component of color
1768 * @alpha: alpha component of color
1769 *
1770 * Sets the color of a corner of the current patch in a mesh pattern.
1771 *
1772 * The color is specified in the same way as in cairo_set_source_rgba().
1773 *
1774 * Valid values for @corner_num are from 0 to 3 and identify the
1775 * corners as explained in cairo_pattern_create_mesh().
1776 *
1777 * Note: If @pattern is not a mesh pattern then @pattern will be put
1778 * into an error status with a status of
1779 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH. If @corner_num is not valid,
1780 * @pattern will be put into an error status with a status of
1781 * %CAIRO_STATUS_INVALID_INDEX. If @pattern has no current patch,
1782 * @pattern will be put into an error status with a status of
1783 * %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
1784 *
1785 * Since: 1.12
1786 **/
1787 void
cairo_mesh_pattern_set_corner_color_rgba(cairo_pattern_t * pattern,unsigned int corner_num,double red,double green,double blue,double alpha)1788 cairo_mesh_pattern_set_corner_color_rgba (cairo_pattern_t *pattern,
1789 unsigned int corner_num,
1790 double red, double green, double blue,
1791 double alpha)
1792 {
1793 cairo_mesh_pattern_t *mesh;
1794
1795 if (unlikely (pattern->status))
1796 return;
1797
1798 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH)) {
1799 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1800 return;
1801 }
1802
1803 if (unlikely (corner_num > 3)) {
1804 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_INDEX);
1805 return;
1806 }
1807
1808 mesh = (cairo_mesh_pattern_t *) pattern;
1809 if (unlikely (!mesh->current_patch)) {
1810 _cairo_pattern_set_error (pattern, CAIRO_STATUS_INVALID_MESH_CONSTRUCTION);
1811 return;
1812 }
1813
1814 red = _cairo_restrict_value (red, 0.0, 1.0);
1815 green = _cairo_restrict_value (green, 0.0, 1.0);
1816 blue = _cairo_restrict_value (blue, 0.0, 1.0);
1817 alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
1818
1819 _cairo_mesh_pattern_set_corner_color (mesh, corner_num, red, green, blue, alpha);
1820 }
1821 slim_hidden_def (cairo_mesh_pattern_set_corner_color_rgba);
1822
1823 static void
_cairo_pattern_add_color_stop(cairo_gradient_pattern_t * pattern,double offset,double red,double green,double blue,double alpha)1824 _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
1825 double offset,
1826 double red,
1827 double green,
1828 double blue,
1829 double alpha)
1830 {
1831 cairo_gradient_stop_t *stops;
1832 unsigned int i;
1833
1834 if (pattern->n_stops >= pattern->stops_size) {
1835 cairo_status_t status = _cairo_pattern_gradient_grow (pattern);
1836 if (unlikely (status)) {
1837 status = _cairo_pattern_set_error (&pattern->base, status);
1838 return;
1839 }
1840 }
1841
1842 stops = pattern->stops;
1843
1844 for (i = 0; i < pattern->n_stops; i++)
1845 {
1846 if (offset < stops[i].offset)
1847 {
1848 memmove (&stops[i + 1], &stops[i],
1849 sizeof (cairo_gradient_stop_t) * (pattern->n_stops - i));
1850
1851 break;
1852 }
1853 }
1854
1855 stops[i].offset = offset;
1856
1857 stops[i].color.red = red;
1858 stops[i].color.green = green;
1859 stops[i].color.blue = blue;
1860 stops[i].color.alpha = alpha;
1861
1862 stops[i].color.red_short = _cairo_color_double_to_short (red);
1863 stops[i].color.green_short = _cairo_color_double_to_short (green);
1864 stops[i].color.blue_short = _cairo_color_double_to_short (blue);
1865 stops[i].color.alpha_short = _cairo_color_double_to_short (alpha);
1866
1867 pattern->n_stops++;
1868 }
1869
1870 /**
1871 * cairo_pattern_add_color_stop_rgb:
1872 * @pattern: a #cairo_pattern_t
1873 * @offset: an offset in the range [0.0 .. 1.0]
1874 * @red: red component of color
1875 * @green: green component of color
1876 * @blue: blue component of color
1877 *
1878 * Adds an opaque color stop to a gradient pattern. The offset
1879 * specifies the location along the gradient's control vector. For
1880 * example, a linear gradient's control vector is from (x0,y0) to
1881 * (x1,y1) while a radial gradient's control vector is from any point
1882 * on the start circle to the corresponding point on the end circle.
1883 *
1884 * The color is specified in the same way as in cairo_set_source_rgb().
1885 *
1886 * If two (or more) stops are specified with identical offset values,
1887 * they will be sorted according to the order in which the stops are
1888 * added, (stops added earlier will compare less than stops added
1889 * later). This can be useful for reliably making sharp color
1890 * transitions instead of the typical blend.
1891 *
1892 *
1893 * Note: If the pattern is not a gradient pattern, (eg. a linear or
1894 * radial pattern), then the pattern will be put into an error status
1895 * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
1896 *
1897 * Since: 1.0
1898 **/
1899 void
cairo_pattern_add_color_stop_rgb(cairo_pattern_t * pattern,double offset,double red,double green,double blue)1900 cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
1901 double offset,
1902 double red,
1903 double green,
1904 double blue)
1905 {
1906 cairo_pattern_add_color_stop_rgba (pattern, offset, red, green, blue, 1.0);
1907 }
1908
1909 /**
1910 * cairo_pattern_add_color_stop_rgba:
1911 * @pattern: a #cairo_pattern_t
1912 * @offset: an offset in the range [0.0 .. 1.0]
1913 * @red: red component of color
1914 * @green: green component of color
1915 * @blue: blue component of color
1916 * @alpha: alpha component of color
1917 *
1918 * Adds a translucent color stop to a gradient pattern. The offset
1919 * specifies the location along the gradient's control vector. For
1920 * example, a linear gradient's control vector is from (x0,y0) to
1921 * (x1,y1) while a radial gradient's control vector is from any point
1922 * on the start circle to the corresponding point on the end circle.
1923 *
1924 * The color is specified in the same way as in cairo_set_source_rgba().
1925 *
1926 * If two (or more) stops are specified with identical offset values,
1927 * they will be sorted according to the order in which the stops are
1928 * added, (stops added earlier will compare less than stops added
1929 * later). This can be useful for reliably making sharp color
1930 * transitions instead of the typical blend.
1931 *
1932 * Note: If the pattern is not a gradient pattern, (eg. a linear or
1933 * radial pattern), then the pattern will be put into an error status
1934 * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
1935 *
1936 * Since: 1.0
1937 **/
1938 void
cairo_pattern_add_color_stop_rgba(cairo_pattern_t * pattern,double offset,double red,double green,double blue,double alpha)1939 cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
1940 double offset,
1941 double red,
1942 double green,
1943 double blue,
1944 double alpha)
1945 {
1946 if (pattern->status)
1947 return;
1948
1949 if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
1950 pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
1951 {
1952 _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
1953 return;
1954 }
1955
1956 offset = _cairo_restrict_value (offset, 0.0, 1.0);
1957 red = _cairo_restrict_value (red, 0.0, 1.0);
1958 green = _cairo_restrict_value (green, 0.0, 1.0);
1959 blue = _cairo_restrict_value (blue, 0.0, 1.0);
1960 alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
1961
1962 _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
1963 offset, red, green, blue, alpha);
1964 }
1965 slim_hidden_def (cairo_pattern_add_color_stop_rgba);
1966
1967 /**
1968 * cairo_pattern_set_matrix:
1969 * @pattern: a #cairo_pattern_t
1970 * @matrix: a #cairo_matrix_t
1971 *
1972 * Sets the pattern's transformation matrix to @matrix. This matrix is
1973 * a transformation from user space to pattern space.
1974 *
1975 * When a pattern is first created it always has the identity matrix
1976 * for its transformation matrix, which means that pattern space is
1977 * initially identical to user space.
1978 *
1979 * Important: Please note that the direction of this transformation
1980 * matrix is from user space to pattern space. This means that if you
1981 * imagine the flow from a pattern to user space (and on to device
1982 * space), then coordinates in that flow will be transformed by the
1983 * inverse of the pattern matrix.
1984 *
1985 * For example, if you want to make a pattern appear twice as large as
1986 * it does by default the correct code to use is:
1987 *
1988 * <informalexample><programlisting>
1989 * cairo_matrix_init_scale (&matrix, 0.5, 0.5);
1990 * cairo_pattern_set_matrix (pattern, &matrix);
1991 * </programlisting></informalexample>
1992 *
1993 * Meanwhile, using values of 2.0 rather than 0.5 in the code above
1994 * would cause the pattern to appear at half of its default size.
1995 *
1996 * Also, please note the discussion of the user-space locking
1997 * semantics of cairo_set_source().
1998 *
1999 * Since: 1.0
2000 **/
2001 void
cairo_pattern_set_matrix(cairo_pattern_t * pattern,const cairo_matrix_t * matrix)2002 cairo_pattern_set_matrix (cairo_pattern_t *pattern,
2003 const cairo_matrix_t *matrix)
2004 {
2005 cairo_matrix_t inverse;
2006 cairo_status_t status;
2007
2008 if (pattern->status)
2009 return;
2010
2011 if (memcmp (&pattern->matrix, matrix, sizeof (cairo_matrix_t)) == 0)
2012 return;
2013
2014 pattern->matrix = *matrix;
2015 _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_MATRIX);
2016
2017 inverse = *matrix;
2018 status = cairo_matrix_invert (&inverse);
2019 if (unlikely (status))
2020 status = _cairo_pattern_set_error (pattern, status);
2021 }
2022 slim_hidden_def (cairo_pattern_set_matrix);
2023
2024 /**
2025 * cairo_pattern_get_matrix:
2026 * @pattern: a #cairo_pattern_t
2027 * @matrix: return value for the matrix
2028 *
2029 * Stores the pattern's transformation matrix into @matrix.
2030 *
2031 * Since: 1.0
2032 **/
2033 void
cairo_pattern_get_matrix(cairo_pattern_t * pattern,cairo_matrix_t * matrix)2034 cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
2035 {
2036 *matrix = pattern->matrix;
2037 }
2038
2039 /**
2040 * cairo_pattern_set_filter:
2041 * @pattern: a #cairo_pattern_t
2042 * @filter: a #cairo_filter_t describing the filter to use for resizing
2043 * the pattern
2044 *
2045 * Sets the filter to be used for resizing when using this pattern.
2046 * See #cairo_filter_t for details on each filter.
2047 *
2048 * * Note that you might want to control filtering even when you do not
2049 * have an explicit #cairo_pattern_t object, (for example when using
2050 * cairo_set_source_surface()). In these cases, it is convenient to
2051 * use cairo_get_source() to get access to the pattern that cairo
2052 * creates implicitly. For example:
2053 *
2054 * <informalexample><programlisting>
2055 * cairo_set_source_surface (cr, image, x, y);
2056 * cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
2057 * </programlisting></informalexample>
2058 *
2059 * Since: 1.0
2060 **/
2061 void
cairo_pattern_set_filter(cairo_pattern_t * pattern,cairo_filter_t filter)2062 cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
2063 {
2064 if (pattern->status)
2065 return;
2066
2067 pattern->filter = filter;
2068 _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_FILTER);
2069 }
2070
2071 /**
2072 * cairo_pattern_get_filter:
2073 * @pattern: a #cairo_pattern_t
2074 *
2075 * Gets the current filter for a pattern. See #cairo_filter_t
2076 * for details on each filter.
2077 *
2078 * Return value: the current filter used for resizing the pattern.
2079 *
2080 * Since: 1.0
2081 **/
2082 cairo_filter_t
cairo_pattern_get_filter(cairo_pattern_t * pattern)2083 cairo_pattern_get_filter (cairo_pattern_t *pattern)
2084 {
2085 return pattern->filter;
2086 }
2087
2088 /**
2089 * cairo_pattern_set_extend:
2090 * @pattern: a #cairo_pattern_t
2091 * @extend: a #cairo_extend_t describing how the area outside of the
2092 * pattern will be drawn
2093 *
2094 * Sets the mode to be used for drawing outside the area of a pattern.
2095 * See #cairo_extend_t for details on the semantics of each extend
2096 * strategy.
2097 *
2098 * The default extend mode is %CAIRO_EXTEND_NONE for surface patterns
2099 * and %CAIRO_EXTEND_PAD for gradient patterns.
2100 *
2101 * Since: 1.0
2102 **/
2103 void
cairo_pattern_set_extend(cairo_pattern_t * pattern,cairo_extend_t extend)2104 cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
2105 {
2106 if (pattern->status)
2107 return;
2108
2109 pattern->extend = extend;
2110 _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_EXTEND);
2111 }
2112
2113 /**
2114 * cairo_pattern_get_extend:
2115 * @pattern: a #cairo_pattern_t
2116 *
2117 * Gets the current extend mode for a pattern. See #cairo_extend_t
2118 * for details on the semantics of each extend strategy.
2119 *
2120 * Return value: the current extend strategy used for drawing the
2121 * pattern.
2122 *
2123 * Since: 1.0
2124 **/
2125 cairo_extend_t
cairo_pattern_get_extend(cairo_pattern_t * pattern)2126 cairo_pattern_get_extend (cairo_pattern_t *pattern)
2127 {
2128 return pattern->extend;
2129 }
2130 slim_hidden_def (cairo_pattern_get_extend);
2131
2132 void
_cairo_pattern_pretransform(cairo_pattern_t * pattern,const cairo_matrix_t * ctm)2133 _cairo_pattern_pretransform (cairo_pattern_t *pattern,
2134 const cairo_matrix_t *ctm)
2135 {
2136 if (pattern->status)
2137 return;
2138
2139 cairo_matrix_multiply (&pattern->matrix, &pattern->matrix, ctm);
2140 }
2141
2142 void
_cairo_pattern_transform(cairo_pattern_t * pattern,const cairo_matrix_t * ctm_inverse)2143 _cairo_pattern_transform (cairo_pattern_t *pattern,
2144 const cairo_matrix_t *ctm_inverse)
2145 {
2146 if (pattern->status)
2147 return;
2148
2149 cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
2150 }
2151
2152 static cairo_bool_t
_linear_pattern_is_degenerate(const cairo_linear_pattern_t * linear)2153 _linear_pattern_is_degenerate (const cairo_linear_pattern_t *linear)
2154 {
2155 return fabs (linear->pd1.x - linear->pd2.x) < DBL_EPSILON &&
2156 fabs (linear->pd1.y - linear->pd2.y) < DBL_EPSILON;
2157 }
2158
2159 static cairo_bool_t
_radial_pattern_is_degenerate(const cairo_radial_pattern_t * radial)2160 _radial_pattern_is_degenerate (const cairo_radial_pattern_t *radial)
2161 {
2162 /* A radial pattern is considered degenerate if it can be
2163 * represented as a solid or clear pattern. This corresponds to
2164 * one of the two cases:
2165 *
2166 * 1) The radii are both very small:
2167 * |dr| < DBL_EPSILON && min (r0, r1) < DBL_EPSILON
2168 *
2169 * 2) The two circles have about the same radius and are very
2170 * close to each other (approximately a cylinder gradient that
2171 * doesn't move with the parameter):
2172 * |dr| < DBL_EPSILON && max (|dx|, |dy|) < 2 * DBL_EPSILON
2173 *
2174 * These checks are consistent with the assumptions used in
2175 * _cairo_radial_pattern_box_to_parameter ().
2176 */
2177
2178 return fabs (radial->cd1.radius - radial->cd2.radius) < DBL_EPSILON &&
2179 (MIN (radial->cd1.radius, radial->cd2.radius) < DBL_EPSILON ||
2180 MAX (fabs (radial->cd1.center.x - radial->cd2.center.x),
2181 fabs (radial->cd1.center.y - radial->cd2.center.y)) < 2 * DBL_EPSILON);
2182 }
2183
2184 static void
_cairo_linear_pattern_box_to_parameter(const cairo_linear_pattern_t * linear,double x0,double y0,double x1,double y1,double range[2])2185 _cairo_linear_pattern_box_to_parameter (const cairo_linear_pattern_t *linear,
2186 double x0, double y0,
2187 double x1, double y1,
2188 double range[2])
2189 {
2190 double t0, tdx, tdy;
2191 double p1x, p1y, pdx, pdy, invsqnorm;
2192
2193 assert (! _linear_pattern_is_degenerate (linear));
2194
2195 /*
2196 * Linear gradients are othrogonal to the line passing through
2197 * their extremes. Because of convexity, the parameter range can
2198 * be computed as the convex hull (one the real line) of the
2199 * parameter values of the 4 corners of the box.
2200 *
2201 * The parameter value t for a point (x,y) can be computed as:
2202 *
2203 * t = (p2 - p1) . (x,y) / |p2 - p1|^2
2204 *
2205 * t0 is the t value for the top left corner
2206 * tdx is the difference between left and right corners
2207 * tdy is the difference between top and bottom corners
2208 */
2209
2210 p1x = linear->pd1.x;
2211 p1y = linear->pd1.y;
2212 pdx = linear->pd2.x - p1x;
2213 pdy = linear->pd2.y - p1y;
2214 invsqnorm = 1.0 / (pdx * pdx + pdy * pdy);
2215 pdx *= invsqnorm;
2216 pdy *= invsqnorm;
2217
2218 t0 = (x0 - p1x) * pdx + (y0 - p1y) * pdy;
2219 tdx = (x1 - x0) * pdx;
2220 tdy = (y1 - y0) * pdy;
2221
2222 /*
2223 * Because of the linearity of the t value, tdx can simply be
2224 * added the t0 to move along the top edge. After this, range[0]
2225 * and range[1] represent the parameter range for the top edge, so
2226 * extending it to include the whole box simply requires adding
2227 * tdy to the correct extreme.
2228 */
2229
2230 range[0] = range[1] = t0;
2231 if (tdx < 0)
2232 range[0] += tdx;
2233 else
2234 range[1] += tdx;
2235
2236 if (tdy < 0)
2237 range[0] += tdy;
2238 else
2239 range[1] += tdy;
2240 }
2241
2242 static cairo_bool_t
_extend_range(double range[2],double value,cairo_bool_t valid)2243 _extend_range (double range[2], double value, cairo_bool_t valid)
2244 {
2245 if (!valid)
2246 range[0] = range[1] = value;
2247 else if (value < range[0])
2248 range[0] = value;
2249 else if (value > range[1])
2250 range[1] = value;
2251
2252 return TRUE;
2253 }
2254
2255 /*
2256 * _cairo_radial_pattern_focus_is_inside:
2257 *
2258 * Returns %TRUE if and only if the focus point exists and is
2259 * contained in one of the two extreme circles. This condition is
2260 * equivalent to one of the two extreme circles being completely
2261 * contained in the other one.
2262 *
2263 * Note: if the focus is on the border of one of the two circles (in
2264 * which case the circles are tangent in the focus point), it is not
2265 * considered as contained in the circle, hence this function returns
2266 * %FALSE.
2267 *
2268 */
2269 cairo_bool_t
_cairo_radial_pattern_focus_is_inside(const cairo_radial_pattern_t * radial)2270 _cairo_radial_pattern_focus_is_inside (const cairo_radial_pattern_t *radial)
2271 {
2272 double cx, cy, cr, dx, dy, dr;
2273
2274 cx = radial->cd1.center.x;
2275 cy = radial->cd1.center.y;
2276 cr = radial->cd1.radius;
2277 dx = radial->cd2.center.x - cx;
2278 dy = radial->cd2.center.y - cy;
2279 dr = radial->cd2.radius - cr;
2280
2281 return dx*dx + dy*dy < dr*dr;
2282 }
2283
2284 static void
_cairo_radial_pattern_box_to_parameter(const cairo_radial_pattern_t * radial,double x0,double y0,double x1,double y1,double tolerance,double range[2])2285 _cairo_radial_pattern_box_to_parameter (const cairo_radial_pattern_t *radial,
2286 double x0, double y0,
2287 double x1, double y1,
2288 double tolerance,
2289 double range[2])
2290 {
2291 double cx, cy, cr, dx, dy, dr;
2292 double a, x_focus, y_focus;
2293 double mindr, minx, miny, maxx, maxy;
2294 cairo_bool_t valid;
2295
2296 assert (! _radial_pattern_is_degenerate (radial));
2297 assert (x0 < x1);
2298 assert (y0 < y1);
2299
2300 tolerance = MAX (tolerance, DBL_EPSILON);
2301
2302 range[0] = range[1] = 0;
2303 valid = FALSE;
2304
2305 x_focus = y_focus = 0; /* silence gcc */
2306
2307 cx = radial->cd1.center.x;
2308 cy = radial->cd1.center.y;
2309 cr = radial->cd1.radius;
2310 dx = radial->cd2.center.x - cx;
2311 dy = radial->cd2.center.y - cy;
2312 dr = radial->cd2.radius - cr;
2313
2314 /* translate by -(cx, cy) to simplify computations */
2315 x0 -= cx;
2316 y0 -= cy;
2317 x1 -= cx;
2318 y1 -= cy;
2319
2320 /* enlarge boundaries slightly to avoid rounding problems in the
2321 * parameter range computation */
2322 x0 -= DBL_EPSILON;
2323 y0 -= DBL_EPSILON;
2324 x1 += DBL_EPSILON;
2325 y1 += DBL_EPSILON;
2326
2327 /* enlarge boundaries even more to avoid rounding problems when
2328 * testing if a point belongs to the box */
2329 minx = x0 - DBL_EPSILON;
2330 miny = y0 - DBL_EPSILON;
2331 maxx = x1 + DBL_EPSILON;
2332 maxy = y1 + DBL_EPSILON;
2333
2334 /* we don't allow negative radiuses, so we will be checking that
2335 * t*dr >= mindr to consider t valid */
2336 mindr = -(cr + DBL_EPSILON);
2337
2338 /*
2339 * After the previous transformations, the start circle is
2340 * centered in the origin and has radius cr. A 1-unit change in
2341 * the t parameter corresponds to dx,dy,dr changes in the x,y,r of
2342 * the circle (center coordinates, radius).
2343 *
2344 * To compute the minimum range needed to correctly draw the
2345 * pattern, we start with an empty range and extend it to include
2346 * the circles touching the bounding box or within it.
2347 */
2348
2349 /*
2350 * Focus, the point where the circle has radius == 0.
2351 *
2352 * r = cr + t * dr = 0
2353 * t = -cr / dr
2354 *
2355 * If the radius is constant (dr == 0) there is no focus (the
2356 * gradient represents a cylinder instead of a cone).
2357 */
2358 if (fabs (dr) >= DBL_EPSILON) {
2359 double t_focus;
2360
2361 t_focus = -cr / dr;
2362 x_focus = t_focus * dx;
2363 y_focus = t_focus * dy;
2364 if (minx <= x_focus && x_focus <= maxx &&
2365 miny <= y_focus && y_focus <= maxy)
2366 {
2367 valid = _extend_range (range, t_focus, valid);
2368 }
2369 }
2370
2371 /*
2372 * Circles externally tangent to box edges.
2373 *
2374 * All circles have center in (dx, dy) * t
2375 *
2376 * If the circle is tangent to the line defined by the edge of the
2377 * box, then at least one of the following holds true:
2378 *
2379 * (dx*t) + (cr + dr*t) == x0 (left edge)
2380 * (dx*t) - (cr + dr*t) == x1 (right edge)
2381 * (dy*t) + (cr + dr*t) == y0 (top edge)
2382 * (dy*t) - (cr + dr*t) == y1 (bottom edge)
2383 *
2384 * The solution is only valid if the tangent point is actually on
2385 * the edge, i.e. if its y coordinate is in [y0,y1] for left/right
2386 * edges and if its x coordinate is in [x0,x1] for top/bottom
2387 * edges.
2388 *
2389 * For the first equation:
2390 *
2391 * (dx + dr) * t = x0 - cr
2392 * t = (x0 - cr) / (dx + dr)
2393 * y = dy * t
2394 *
2395 * in the code this becomes:
2396 *
2397 * t_edge = (num) / (den)
2398 * v = (delta) * t_edge
2399 *
2400 * If the denominator in t is 0, the pattern is tangent to a line
2401 * parallel to the edge under examination. The corner-case where
2402 * the boundary line is the same as the edge is handled by the
2403 * focus point case and/or by the a==0 case.
2404 */
2405 #define T_EDGE(num,den,delta,lower,upper) \
2406 if (fabs (den) >= DBL_EPSILON) { \
2407 double t_edge, v; \
2408 \
2409 t_edge = (num) / (den); \
2410 v = t_edge * (delta); \
2411 if (t_edge * dr >= mindr && (lower) <= v && v <= (upper)) \
2412 valid = _extend_range (range, t_edge, valid); \
2413 }
2414
2415 /* circles tangent (externally) to left/right/top/bottom edge */
2416 T_EDGE (x0 - cr, dx + dr, dy, miny, maxy);
2417 T_EDGE (x1 + cr, dx - dr, dy, miny, maxy);
2418 T_EDGE (y0 - cr, dy + dr, dx, minx, maxx);
2419 T_EDGE (y1 + cr, dy - dr, dx, minx, maxx);
2420
2421 #undef T_EDGE
2422
2423 /*
2424 * Circles passing through a corner.
2425 *
2426 * A circle passing through the point (x,y) satisfies:
2427 *
2428 * (x-t*dx)^2 + (y-t*dy)^2 == (cr + t*dr)^2
2429 *
2430 * If we set:
2431 * a = dx^2 + dy^2 - dr^2
2432 * b = x*dx + y*dy + cr*dr
2433 * c = x^2 + y^2 - cr^2
2434 * we have:
2435 * a*t^2 - 2*b*t + c == 0
2436 */
2437 a = dx * dx + dy * dy - dr * dr;
2438 if (fabs (a) < DBL_EPSILON * DBL_EPSILON) {
2439 double b, maxd2;
2440
2441 /* Ensure that gradients with both a and dr small are
2442 * considered degenerate.
2443 * The floating point version of the degeneracy test implemented
2444 * in _radial_pattern_is_degenerate() is:
2445 *
2446 * 1) The circles are practically the same size:
2447 * |dr| < DBL_EPSILON
2448 * AND
2449 * 2a) The circles are both very small:
2450 * min (r0, r1) < DBL_EPSILON
2451 * OR
2452 * 2b) The circles are very close to each other:
2453 * max (|dx|, |dy|) < 2 * DBL_EPSILON
2454 *
2455 * Assuming that the gradient is not degenerate, we want to
2456 * show that |a| < DBL_EPSILON^2 implies |dr| >= DBL_EPSILON.
2457 *
2458 * If the gradient is not degenerate yet it has |dr| <
2459 * DBL_EPSILON, (2b) is false, thus:
2460 *
2461 * max (|dx|, |dy|) >= 2*DBL_EPSILON
2462 * which implies:
2463 * 4*DBL_EPSILON^2 <= max (|dx|, |dy|)^2 <= dx^2 + dy^2
2464 *
2465 * From the definition of a, we get:
2466 * a = dx^2 + dy^2 - dr^2 < DBL_EPSILON^2
2467 * dx^2 + dy^2 - DBL_EPSILON^2 < dr^2
2468 * 3*DBL_EPSILON^2 < dr^2
2469 *
2470 * which is inconsistent with the hypotheses, thus |dr| <
2471 * DBL_EPSILON is false or the gradient is degenerate.
2472 */
2473 assert (fabs (dr) >= DBL_EPSILON);
2474
2475 /*
2476 * If a == 0, all the circles are tangent to a line in the
2477 * focus point. If this line is within the box extents, we
2478 * should add the circle with infinite radius, but this would
2479 * make the range unbounded, so we add the smallest circle whose
2480 * distance to the desired (degenerate) circle within the
2481 * bounding box does not exceed tolerance.
2482 *
2483 * The equation of the line is b==0, i.e.:
2484 * x*dx + y*dy + cr*dr == 0
2485 *
2486 * We compute the intersection of the line with the box and
2487 * keep the intersection with maximum square distance (maxd2)
2488 * from the focus point.
2489 *
2490 * In the code the intersection is represented in another
2491 * coordinate system, whose origin is the focus point and
2492 * which has a u,v axes, which are respectively orthogonal and
2493 * parallel to the edge being intersected.
2494 *
2495 * The intersection is valid only if it belongs to the box,
2496 * otherwise it is ignored.
2497 *
2498 * For example:
2499 *
2500 * y = y0
2501 * x*dx + y0*dy + cr*dr == 0
2502 * x = -(y0*dy + cr*dr) / dx
2503 *
2504 * which in (u,v) is:
2505 * u = y0 - y_focus
2506 * v = -(y0*dy + cr*dr) / dx - x_focus
2507 *
2508 * In the code:
2509 * u = (edge) - (u_origin)
2510 * v = -((edge) * (delta) + cr*dr) / (den) - v_focus
2511 */
2512 #define T_EDGE(edge,delta,den,lower,upper,u_origin,v_origin) \
2513 if (fabs (den) >= DBL_EPSILON) { \
2514 double v; \
2515 \
2516 v = -((edge) * (delta) + cr * dr) / (den); \
2517 if ((lower) <= v && v <= (upper)) { \
2518 double u, d2; \
2519 \
2520 u = (edge) - (u_origin); \
2521 v -= (v_origin); \
2522 d2 = u*u + v*v; \
2523 if (maxd2 < d2) \
2524 maxd2 = d2; \
2525 } \
2526 }
2527
2528 maxd2 = 0;
2529
2530 /* degenerate circles (lines) passing through each edge */
2531 T_EDGE (y0, dy, dx, minx, maxx, y_focus, x_focus);
2532 T_EDGE (y1, dy, dx, minx, maxx, y_focus, x_focus);
2533 T_EDGE (x0, dx, dy, miny, maxy, x_focus, y_focus);
2534 T_EDGE (x1, dx, dy, miny, maxy, x_focus, y_focus);
2535
2536 #undef T_EDGE
2537
2538 /*
2539 * The limit circle can be transformed rigidly to the y=0 line
2540 * and the circles tangent to it in (0,0) are:
2541 *
2542 * x^2 + (y-r)^2 = r^2 <=> x^2 + y^2 - 2*y*r = 0
2543 *
2544 * y is the distance from the line, in our case tolerance;
2545 * x is the distance along the line, i.e. sqrt(maxd2),
2546 * so:
2547 *
2548 * r = cr + dr * t = (maxd2 + tolerance^2) / (2*tolerance)
2549 * t = (r - cr) / dr =
2550 * (maxd2 + tolerance^2 - 2*tolerance*cr) / (2*tolerance*dr)
2551 */
2552 if (maxd2 > 0) {
2553 double t_limit = maxd2 + tolerance*tolerance - 2*tolerance*cr;
2554 t_limit /= 2 * tolerance * dr;
2555 valid = _extend_range (range, t_limit, valid);
2556 }
2557
2558 /*
2559 * Nondegenerate, nonlimit circles passing through the corners.
2560 *
2561 * a == 0 && a*t^2 - 2*b*t + c == 0
2562 *
2563 * t = c / (2*b)
2564 *
2565 * The b == 0 case has just been handled, so we only have to
2566 * compute this if b != 0.
2567 */
2568 #define T_CORNER(x,y) \
2569 b = (x) * dx + (y) * dy + cr * dr; \
2570 if (fabs (b) >= DBL_EPSILON) { \
2571 double t_corner; \
2572 double x2 = (x) * (x); \
2573 double y2 = (y) * (y); \
2574 double cr2 = (cr) * (cr); \
2575 double c = x2 + y2 - cr2; \
2576 \
2577 t_corner = 0.5 * c / b; \
2578 if (t_corner * dr >= mindr) \
2579 valid = _extend_range (range, t_corner, valid); \
2580 }
2581
2582 /* circles touching each corner */
2583 T_CORNER (x0, y0);
2584 T_CORNER (x0, y1);
2585 T_CORNER (x1, y0);
2586 T_CORNER (x1, y1);
2587
2588 #undef T_CORNER
2589 } else {
2590 double inva, b, c, d;
2591
2592 inva = 1 / a;
2593
2594 /*
2595 * Nondegenerate, nonlimit circles passing through the corners.
2596 *
2597 * a != 0 && a*t^2 - 2*b*t + c == 0
2598 *
2599 * t = (b +- sqrt (b*b - a*c)) / a
2600 *
2601 * If the argument of sqrt() is negative, then no circle
2602 * passes through the corner.
2603 */
2604 #define T_CORNER(x,y) \
2605 b = (x) * dx + (y) * dy + cr * dr; \
2606 c = (x) * (x) + (y) * (y) - cr * cr; \
2607 d = b * b - a * c; \
2608 if (d >= 0) { \
2609 double t_corner; \
2610 \
2611 d = sqrt (d); \
2612 t_corner = (b + d) * inva; \
2613 if (t_corner * dr >= mindr) \
2614 valid = _extend_range (range, t_corner, valid); \
2615 t_corner = (b - d) * inva; \
2616 if (t_corner * dr >= mindr) \
2617 valid = _extend_range (range, t_corner, valid); \
2618 }
2619
2620 /* circles touching each corner */
2621 T_CORNER (x0, y0);
2622 T_CORNER (x0, y1);
2623 T_CORNER (x1, y0);
2624 T_CORNER (x1, y1);
2625
2626 #undef T_CORNER
2627 }
2628 }
2629
2630 /**
2631 * _cairo_gradient_pattern_box_to_parameter:
2632 *
2633 * Compute a interpolation range sufficient to draw (within the given
2634 * tolerance) the gradient in the given box getting the same result as
2635 * using the (-inf, +inf) range.
2636 *
2637 * Assumes that the pattern is not degenerate. This can be guaranteed
2638 * by simplifying it to a solid clear if _cairo_pattern_is_clear or to
2639 * a solid color if _cairo_gradient_pattern_is_solid.
2640 *
2641 * The range isn't guaranteed to be minimal, but it tries to.
2642 **/
2643 void
_cairo_gradient_pattern_box_to_parameter(const cairo_gradient_pattern_t * gradient,double x0,double y0,double x1,double y1,double tolerance,double out_range[2])2644 _cairo_gradient_pattern_box_to_parameter (const cairo_gradient_pattern_t *gradient,
2645 double x0, double y0,
2646 double x1, double y1,
2647 double tolerance,
2648 double out_range[2])
2649 {
2650 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
2651 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
2652
2653 if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
2654 _cairo_linear_pattern_box_to_parameter ((cairo_linear_pattern_t *) gradient,
2655 x0, y0, x1, y1, out_range);
2656 } else {
2657 _cairo_radial_pattern_box_to_parameter ((cairo_radial_pattern_t *) gradient,
2658 x0, y0, x1, y1, tolerance, out_range);
2659 }
2660 }
2661
2662 /**
2663 * _cairo_gradient_pattern_interpolate:
2664 *
2665 * Interpolate between the start and end objects of linear or radial
2666 * gradients. The interpolated object is stored in out_circle, with
2667 * the radius being zero in the linear gradient case.
2668 **/
2669 void
_cairo_gradient_pattern_interpolate(const cairo_gradient_pattern_t * gradient,double t,cairo_circle_double_t * out_circle)2670 _cairo_gradient_pattern_interpolate (const cairo_gradient_pattern_t *gradient,
2671 double t,
2672 cairo_circle_double_t *out_circle)
2673 {
2674 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
2675 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
2676
2677 #define lerp(a,b) (a)*(1-t) + (b)*t
2678
2679 if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
2680 cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
2681 out_circle->center.x = lerp (linear->pd1.x, linear->pd2.x);
2682 out_circle->center.y = lerp (linear->pd1.y, linear->pd2.y);
2683 out_circle->radius = 0;
2684 } else {
2685 cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
2686 out_circle->center.x = lerp (radial->cd1.center.x, radial->cd2.center.x);
2687 out_circle->center.y = lerp (radial->cd1.center.y, radial->cd2.center.y);
2688 out_circle->radius = lerp (radial->cd1.radius , radial->cd2.radius);
2689 }
2690
2691 #undef lerp
2692 }
2693
2694
2695 /**
2696 * _cairo_gradient_pattern_fit_to_range:
2697 *
2698 * Scale the extremes of a gradient to guarantee that the coordinates
2699 * and their deltas are within the range (-max_value, max_value). The
2700 * new extremes are stored in out_circle.
2701 *
2702 * The pattern matrix is scaled to guarantee that the aspect of the
2703 * gradient is the same and the result is stored in out_matrix.
2704 *
2705 **/
2706 void
_cairo_gradient_pattern_fit_to_range(const cairo_gradient_pattern_t * gradient,double max_value,cairo_matrix_t * out_matrix,cairo_circle_double_t out_circle[2])2707 _cairo_gradient_pattern_fit_to_range (const cairo_gradient_pattern_t *gradient,
2708 double max_value,
2709 cairo_matrix_t *out_matrix,
2710 cairo_circle_double_t out_circle[2])
2711 {
2712 double dim;
2713
2714 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
2715 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
2716
2717 if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
2718 cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
2719
2720 out_circle[0].center = linear->pd1;
2721 out_circle[0].radius = 0;
2722 out_circle[1].center = linear->pd2;
2723 out_circle[1].radius = 0;
2724
2725 dim = fabs (linear->pd1.x);
2726 dim = MAX (dim, fabs (linear->pd1.y));
2727 dim = MAX (dim, fabs (linear->pd2.x));
2728 dim = MAX (dim, fabs (linear->pd2.y));
2729 dim = MAX (dim, fabs (linear->pd1.x - linear->pd2.x));
2730 dim = MAX (dim, fabs (linear->pd1.y - linear->pd2.y));
2731 } else {
2732 cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
2733
2734 out_circle[0] = radial->cd1;
2735 out_circle[1] = radial->cd2;
2736
2737 dim = fabs (radial->cd1.center.x);
2738 dim = MAX (dim, fabs (radial->cd1.center.y));
2739 dim = MAX (dim, fabs (radial->cd1.radius));
2740 dim = MAX (dim, fabs (radial->cd2.center.x));
2741 dim = MAX (dim, fabs (radial->cd2.center.y));
2742 dim = MAX (dim, fabs (radial->cd2.radius));
2743 dim = MAX (dim, fabs (radial->cd1.center.x - radial->cd2.center.x));
2744 dim = MAX (dim, fabs (radial->cd1.center.y - radial->cd2.center.y));
2745 dim = MAX (dim, fabs (radial->cd1.radius - radial->cd2.radius));
2746 }
2747
2748 if (unlikely (dim > max_value)) {
2749 cairo_matrix_t scale;
2750
2751 dim = max_value / dim;
2752
2753 out_circle[0].center.x *= dim;
2754 out_circle[0].center.y *= dim;
2755 out_circle[0].radius *= dim;
2756 out_circle[1].center.x *= dim;
2757 out_circle[1].center.y *= dim;
2758 out_circle[1].radius *= dim;
2759
2760 cairo_matrix_init_scale (&scale, dim, dim);
2761 cairo_matrix_multiply (out_matrix, &gradient->base.matrix, &scale);
2762 } else {
2763 *out_matrix = gradient->base.matrix;
2764 }
2765 }
2766
2767 static cairo_bool_t
_gradient_is_clear(const cairo_gradient_pattern_t * gradient,const cairo_rectangle_int_t * extents)2768 _gradient_is_clear (const cairo_gradient_pattern_t *gradient,
2769 const cairo_rectangle_int_t *extents)
2770 {
2771 unsigned int i;
2772
2773 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
2774 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
2775
2776 if (gradient->n_stops == 0 ||
2777 (gradient->base.extend == CAIRO_EXTEND_NONE &&
2778 gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
2779 return TRUE;
2780
2781 if (gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL) {
2782 /* degenerate radial gradients are clear */
2783 if (_radial_pattern_is_degenerate ((cairo_radial_pattern_t *) gradient))
2784 return TRUE;
2785 } else if (gradient->base.extend == CAIRO_EXTEND_NONE) {
2786 /* EXTEND_NONE degenerate linear gradients are clear */
2787 if (_linear_pattern_is_degenerate ((cairo_linear_pattern_t *) gradient))
2788 return TRUE;
2789 }
2790
2791 /* Check if the extents intersect the drawn part of the pattern. */
2792 if (extents != NULL &&
2793 (gradient->base.extend == CAIRO_EXTEND_NONE ||
2794 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL))
2795 {
2796 double t[2];
2797
2798 _cairo_gradient_pattern_box_to_parameter (gradient,
2799 extents->x,
2800 extents->y,
2801 extents->x + extents->width,
2802 extents->y + extents->height,
2803 DBL_EPSILON,
2804 t);
2805
2806 if (gradient->base.extend == CAIRO_EXTEND_NONE &&
2807 (t[0] >= gradient->stops[gradient->n_stops - 1].offset ||
2808 t[1] <= gradient->stops[0].offset))
2809 {
2810 return TRUE;
2811 }
2812
2813 if (t[0] == t[1])
2814 return TRUE;
2815 }
2816
2817 for (i = 0; i < gradient->n_stops; i++)
2818 if (! CAIRO_COLOR_IS_CLEAR (&gradient->stops[i].color))
2819 return FALSE;
2820
2821 return TRUE;
2822 }
2823
2824 static void
_gradient_color_average(const cairo_gradient_pattern_t * gradient,cairo_color_t * color)2825 _gradient_color_average (const cairo_gradient_pattern_t *gradient,
2826 cairo_color_t *color)
2827 {
2828 double delta0, delta1;
2829 double r, g, b, a;
2830 unsigned int i, start = 1, end;
2831
2832 assert (gradient->n_stops > 0);
2833 assert (gradient->base.extend != CAIRO_EXTEND_NONE);
2834
2835 if (gradient->n_stops == 1) {
2836 _cairo_color_init_rgba (color,
2837 gradient->stops[0].color.red,
2838 gradient->stops[0].color.green,
2839 gradient->stops[0].color.blue,
2840 gradient->stops[0].color.alpha);
2841 return;
2842 }
2843
2844 end = gradient->n_stops - 1;
2845
2846 switch (gradient->base.extend) {
2847 case CAIRO_EXTEND_REPEAT:
2848 /*
2849 * Sa, Sb and Sy, Sz are the first two and last two stops respectively.
2850 * The weight of the first and last stop can be computed as the area of
2851 * the following triangles (taken with height 1, since the whole [0-1]
2852 * will have total weight 1 this way): b*h/2
2853 *
2854 * + +
2855 * / |\ / | \
2856 * / | \ / | \
2857 * / | \ / | \
2858 * ~~~~~+---+---+---+~~~~~~~+-------+---+---+~~~~~
2859 * -1+Sz 0 Sa Sb Sy Sz 1 1+Sa
2860 *
2861 * For the first stop: (Sb-(-1+Sz)/2 = (1+Sb-Sz)/2
2862 * For the last stop: ((1+Sa)-Sy)/2 = (1+Sa-Sy)/2
2863 * Halving the result is done after summing up all the areas.
2864 */
2865 delta0 = 1.0 + gradient->stops[1].offset - gradient->stops[end].offset;
2866 delta1 = 1.0 + gradient->stops[0].offset - gradient->stops[end-1].offset;
2867 break;
2868
2869 case CAIRO_EXTEND_REFLECT:
2870 /*
2871 * Sa, Sb and Sy, Sz are the first two and last two stops respectively.
2872 * The weight of the first and last stop can be computed as the area of
2873 * the following trapezoids (taken with height 1, since the whole [0-1]
2874 * will have total weight 1 this way): (b+B)*h/2
2875 *
2876 * +-------+ +---+
2877 * | |\ / | |
2878 * | | \ / | |
2879 * | | \ / | |
2880 * +-------+---+~~~~~~~+-------+---+
2881 * 0 Sa Sb Sy Sz 1
2882 *
2883 * For the first stop: (Sa+Sb)/2
2884 * For the last stop: ((1-Sz) + (1-Sy))/2 = (2-Sy-Sz)/2
2885 * Halving the result is done after summing up all the areas.
2886 */
2887 delta0 = gradient->stops[0].offset + gradient->stops[1].offset;
2888 delta1 = 2.0 - gradient->stops[end-1].offset - gradient->stops[end].offset;
2889 break;
2890
2891 case CAIRO_EXTEND_PAD:
2892 /* PAD is computed as the average of the first and last stop:
2893 * - take both of them with weight 1 (they will be halved
2894 * after the whole sum has been computed).
2895 * - avoid summing any of the inner stops.
2896 */
2897 delta0 = delta1 = 1.0;
2898 start = end;
2899 break;
2900
2901 case CAIRO_EXTEND_NONE:
2902 default:
2903 ASSERT_NOT_REACHED;
2904 _cairo_color_init_rgba (color, 0, 0, 0, 0);
2905 return;
2906 }
2907
2908 r = delta0 * gradient->stops[0].color.red;
2909 g = delta0 * gradient->stops[0].color.green;
2910 b = delta0 * gradient->stops[0].color.blue;
2911 a = delta0 * gradient->stops[0].color.alpha;
2912
2913 for (i = start; i < end; ++i) {
2914 /* Inner stops weight is the same as the area of the triangle they influence
2915 * (which goes from the stop before to the stop after), again with height 1
2916 * since the whole must sum up to 1: b*h/2
2917 * Halving is done after the whole sum has been computed.
2918 */
2919 double delta = gradient->stops[i+1].offset - gradient->stops[i-1].offset;
2920 r += delta * gradient->stops[i].color.red;
2921 g += delta * gradient->stops[i].color.green;
2922 b += delta * gradient->stops[i].color.blue;
2923 a += delta * gradient->stops[i].color.alpha;
2924 }
2925
2926 r += delta1 * gradient->stops[end].color.red;
2927 g += delta1 * gradient->stops[end].color.green;
2928 b += delta1 * gradient->stops[end].color.blue;
2929 a += delta1 * gradient->stops[end].color.alpha;
2930
2931 _cairo_color_init_rgba (color, r * .5, g * .5, b * .5, a * .5);
2932 }
2933
2934 /**
2935 * _cairo_pattern_alpha_range:
2936 *
2937 * Convenience function to determine the minimum and maximum alpha in
2938 * the drawn part of a pattern (i.e. ignoring clear parts caused by
2939 * extend modes and/or pattern shape).
2940 *
2941 * If not NULL, out_min and out_max will be set respectively to the
2942 * minimum and maximum alpha value of the pattern.
2943 **/
2944 void
_cairo_pattern_alpha_range(const cairo_pattern_t * pattern,double * out_min,double * out_max)2945 _cairo_pattern_alpha_range (const cairo_pattern_t *pattern,
2946 double *out_min,
2947 double *out_max)
2948 {
2949 double alpha_min, alpha_max;
2950
2951 switch (pattern->type) {
2952 case CAIRO_PATTERN_TYPE_SOLID: {
2953 const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
2954 alpha_min = alpha_max = solid->color.alpha;
2955 break;
2956 }
2957
2958 case CAIRO_PATTERN_TYPE_LINEAR:
2959 case CAIRO_PATTERN_TYPE_RADIAL: {
2960 const cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
2961 unsigned int i;
2962
2963 assert (gradient->n_stops >= 1);
2964
2965 alpha_min = alpha_max = gradient->stops[0].color.alpha;
2966 for (i = 1; i < gradient->n_stops; i++) {
2967 if (alpha_min > gradient->stops[i].color.alpha)
2968 alpha_min = gradient->stops[i].color.alpha;
2969 else if (alpha_max < gradient->stops[i].color.alpha)
2970 alpha_max = gradient->stops[i].color.alpha;
2971 }
2972
2973 break;
2974 }
2975
2976 case CAIRO_PATTERN_TYPE_MESH: {
2977 const cairo_mesh_pattern_t *mesh = (const cairo_mesh_pattern_t *) pattern;
2978 const cairo_mesh_patch_t *patch = _cairo_array_index_const (&mesh->patches, 0);
2979 unsigned int i, j, n = _cairo_array_num_elements (&mesh->patches);
2980
2981 assert (n >= 1);
2982
2983 alpha_min = alpha_max = patch[0].colors[0].alpha;
2984 for (i = 0; i < n; i++) {
2985 for (j = 0; j < 4; j++) {
2986 if (patch[i].colors[j].alpha < alpha_min)
2987 alpha_min = patch[i].colors[j].alpha;
2988 else if (patch[i].colors[j].alpha > alpha_max)
2989 alpha_max = patch[i].colors[j].alpha;
2990 }
2991 }
2992
2993 break;
2994 }
2995
2996 default:
2997 ASSERT_NOT_REACHED;
2998 /* fall through */
2999
3000 case CAIRO_PATTERN_TYPE_SURFACE:
3001 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3002 alpha_min = 0;
3003 alpha_max = 1;
3004 break;
3005 }
3006
3007 if (out_min)
3008 *out_min = alpha_min;
3009 if (out_max)
3010 *out_max = alpha_max;
3011 }
3012
3013 /**
3014 * _cairo_mesh_pattern_coord_box:
3015 *
3016 * Convenience function to determine the range of the coordinates of
3017 * the points used to define the patches of the mesh.
3018 *
3019 * This is guaranteed to contain the pattern extents, but might not be
3020 * tight, just like a Bezier curve is always inside the convex hull of
3021 * the control points.
3022 *
3023 * This function cannot be used while the mesh is being constructed.
3024 *
3025 * The function returns TRUE and sets the output parameters to define
3026 * the coordinate range if the mesh pattern contains at least one
3027 * patch, otherwise it returns FALSE.
3028 **/
3029 cairo_bool_t
_cairo_mesh_pattern_coord_box(const cairo_mesh_pattern_t * mesh,double * out_xmin,double * out_ymin,double * out_xmax,double * out_ymax)3030 _cairo_mesh_pattern_coord_box (const cairo_mesh_pattern_t *mesh,
3031 double *out_xmin,
3032 double *out_ymin,
3033 double *out_xmax,
3034 double *out_ymax)
3035 {
3036 const cairo_mesh_patch_t *patch;
3037 unsigned int num_patches, i, j, k;
3038 double x0, y0, x1, y1;
3039
3040 assert (mesh->current_patch == NULL);
3041
3042 num_patches = _cairo_array_num_elements (&mesh->patches);
3043
3044 if (num_patches == 0)
3045 return FALSE;
3046
3047 patch = _cairo_array_index_const (&mesh->patches, 0);
3048 x0 = x1 = patch->points[0][0].x;
3049 y0 = y1 = patch->points[0][0].y;
3050
3051 for (i = 0; i < num_patches; i++) {
3052 for (j = 0; j < 4; j++) {
3053 for (k = 0; k < 4; k++) {
3054 x0 = MIN (x0, patch[i].points[j][k].x);
3055 y0 = MIN (y0, patch[i].points[j][k].y);
3056 x1 = MAX (x1, patch[i].points[j][k].x);
3057 y1 = MAX (y1, patch[i].points[j][k].y);
3058 }
3059 }
3060 }
3061
3062 *out_xmin = x0;
3063 *out_ymin = y0;
3064 *out_xmax = x1;
3065 *out_ymax = y1;
3066
3067 return TRUE;
3068 }
3069
3070 /**
3071 * _cairo_gradient_pattern_is_solid:
3072 *
3073 * Convenience function to determine whether a gradient pattern is
3074 * a solid color within the given extents. In this case the color
3075 * argument is initialized to the color the pattern represents.
3076 * This functions doesn't handle completely transparent gradients,
3077 * thus it should be called only after _cairo_pattern_is_clear has
3078 * returned FALSE.
3079 *
3080 * Return value: %TRUE if the pattern is a solid color.
3081 **/
3082 cairo_bool_t
_cairo_gradient_pattern_is_solid(const cairo_gradient_pattern_t * gradient,const cairo_rectangle_int_t * extents,cairo_color_t * color)3083 _cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient,
3084 const cairo_rectangle_int_t *extents,
3085 cairo_color_t *color)
3086 {
3087 unsigned int i;
3088
3089 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
3090 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
3091
3092 /* TODO: radial */
3093 if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
3094 cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
3095 if (_linear_pattern_is_degenerate (linear)) {
3096 _gradient_color_average (gradient, color);
3097 return TRUE;
3098 }
3099
3100 if (gradient->base.extend == CAIRO_EXTEND_NONE) {
3101 double t[2];
3102
3103 /* We already know that the pattern is not clear, thus if some
3104 * part of it is clear, the whole is not solid.
3105 */
3106
3107 if (extents == NULL)
3108 return FALSE;
3109
3110 _cairo_linear_pattern_box_to_parameter (linear,
3111 extents->x,
3112 extents->y,
3113 extents->x + extents->width,
3114 extents->y + extents->height,
3115 t);
3116
3117 if (t[0] < 0.0 || t[1] > 1.0)
3118 return FALSE;
3119 }
3120 } else
3121 return FALSE;
3122
3123 for (i = 1; i < gradient->n_stops; i++)
3124 if (! _cairo_color_stop_equal (&gradient->stops[0].color,
3125 &gradient->stops[i].color))
3126 return FALSE;
3127
3128 _cairo_color_init_rgba (color,
3129 gradient->stops[0].color.red,
3130 gradient->stops[0].color.green,
3131 gradient->stops[0].color.blue,
3132 gradient->stops[0].color.alpha);
3133
3134 return TRUE;
3135 }
3136
3137 /**
3138 * _cairo_pattern_is_constant_alpha:
3139 *
3140 * Convenience function to determine whether a pattern has constant
3141 * alpha within the given extents. In this case the alpha argument is
3142 * initialized to the alpha within the extents.
3143 *
3144 * Return value: %TRUE if the pattern has constant alpha.
3145 **/
3146 cairo_bool_t
_cairo_pattern_is_constant_alpha(const cairo_pattern_t * abstract_pattern,const cairo_rectangle_int_t * extents,double * alpha)3147 _cairo_pattern_is_constant_alpha (const cairo_pattern_t *abstract_pattern,
3148 const cairo_rectangle_int_t *extents,
3149 double *alpha)
3150 {
3151 const cairo_pattern_union_t *pattern;
3152 cairo_color_t color;
3153
3154 if (_cairo_pattern_is_clear (abstract_pattern)) {
3155 *alpha = 0.0;
3156 return TRUE;
3157 }
3158
3159 if (_cairo_pattern_is_opaque (abstract_pattern, extents)) {
3160 *alpha = 1.0;
3161 return TRUE;
3162 }
3163
3164 pattern = (cairo_pattern_union_t *) abstract_pattern;
3165 switch (pattern->base.type) {
3166 case CAIRO_PATTERN_TYPE_SOLID:
3167 *alpha = pattern->solid.color.alpha;
3168 return TRUE;
3169
3170 case CAIRO_PATTERN_TYPE_LINEAR:
3171 case CAIRO_PATTERN_TYPE_RADIAL:
3172 if (_cairo_gradient_pattern_is_solid (&pattern->gradient.base, extents, &color)) {
3173 *alpha = color.alpha;
3174 return TRUE;
3175 } else {
3176 return FALSE;
3177 }
3178
3179 /* TODO: need to test these as well */
3180 case CAIRO_PATTERN_TYPE_SURFACE:
3181 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3182 case CAIRO_PATTERN_TYPE_MESH:
3183 return FALSE;
3184 }
3185
3186 ASSERT_NOT_REACHED;
3187 return FALSE;
3188 }
3189
3190 static cairo_bool_t
_mesh_is_clear(const cairo_mesh_pattern_t * mesh)3191 _mesh_is_clear (const cairo_mesh_pattern_t *mesh)
3192 {
3193 double x1, y1, x2, y2;
3194 cairo_bool_t is_valid;
3195
3196 is_valid = _cairo_mesh_pattern_coord_box (mesh, &x1, &y1, &x2, &y2);
3197 if (!is_valid)
3198 return TRUE;
3199
3200 if (x2 - x1 < DBL_EPSILON || y2 - y1 < DBL_EPSILON)
3201 return TRUE;
3202
3203 return FALSE;
3204 }
3205
3206 /**
3207 * _cairo_pattern_is_opaque_solid:
3208 *
3209 * Convenience function to determine whether a pattern is an opaque
3210 * (alpha==1.0) solid color pattern. This is done by testing whether
3211 * the pattern's alpha value when converted to a byte is 255, so if a
3212 * backend actually supported deep alpha channels this function might
3213 * not do the right thing.
3214 *
3215 * Return value: %TRUE if the pattern is an opaque, solid color.
3216 **/
3217 cairo_bool_t
_cairo_pattern_is_opaque_solid(const cairo_pattern_t * pattern)3218 _cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern)
3219 {
3220 cairo_solid_pattern_t *solid;
3221
3222 if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
3223 return FALSE;
3224
3225 solid = (cairo_solid_pattern_t *) pattern;
3226
3227 return CAIRO_COLOR_IS_OPAQUE (&solid->color);
3228 }
3229
3230 static cairo_bool_t
_surface_is_opaque(const cairo_surface_pattern_t * pattern,const cairo_rectangle_int_t * sample)3231 _surface_is_opaque (const cairo_surface_pattern_t *pattern,
3232 const cairo_rectangle_int_t *sample)
3233 {
3234 cairo_rectangle_int_t extents;
3235
3236 if (pattern->surface->content & CAIRO_CONTENT_ALPHA)
3237 return FALSE;
3238
3239 if (pattern->base.extend != CAIRO_EXTEND_NONE)
3240 return TRUE;
3241
3242 if (! _cairo_surface_get_extents (pattern->surface, &extents))
3243 return TRUE;
3244
3245 if (sample == NULL)
3246 return FALSE;
3247
3248 return _cairo_rectangle_contains_rectangle (&extents, sample);
3249 }
3250
3251 static cairo_bool_t
_raster_source_is_opaque(const cairo_raster_source_pattern_t * pattern,const cairo_rectangle_int_t * sample)3252 _raster_source_is_opaque (const cairo_raster_source_pattern_t *pattern,
3253 const cairo_rectangle_int_t *sample)
3254 {
3255 if (pattern->content & CAIRO_CONTENT_ALPHA)
3256 return FALSE;
3257
3258 if (pattern->base.extend != CAIRO_EXTEND_NONE)
3259 return TRUE;
3260
3261 if (sample == NULL)
3262 return FALSE;
3263
3264 return _cairo_rectangle_contains_rectangle (&pattern->extents, sample);
3265 }
3266
3267 static cairo_bool_t
_surface_is_clear(const cairo_surface_pattern_t * pattern)3268 _surface_is_clear (const cairo_surface_pattern_t *pattern)
3269 {
3270 cairo_rectangle_int_t extents;
3271
3272 if (_cairo_surface_get_extents (pattern->surface, &extents) &&
3273 (extents.width == 0 || extents.height == 0))
3274 return TRUE;
3275
3276 return pattern->surface->is_clear &&
3277 pattern->surface->content & CAIRO_CONTENT_ALPHA;
3278 }
3279
3280 static cairo_bool_t
_raster_source_is_clear(const cairo_raster_source_pattern_t * pattern)3281 _raster_source_is_clear (const cairo_raster_source_pattern_t *pattern)
3282 {
3283 return pattern->extents.width == 0 || pattern->extents.height == 0;
3284 }
3285
3286 static cairo_bool_t
_gradient_is_opaque(const cairo_gradient_pattern_t * gradient,const cairo_rectangle_int_t * sample)3287 _gradient_is_opaque (const cairo_gradient_pattern_t *gradient,
3288 const cairo_rectangle_int_t *sample)
3289 {
3290 unsigned int i;
3291
3292 assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
3293 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
3294
3295 if (gradient->n_stops == 0 ||
3296 (gradient->base.extend == CAIRO_EXTEND_NONE &&
3297 gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
3298 return FALSE;
3299
3300 if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
3301 if (gradient->base.extend == CAIRO_EXTEND_NONE) {
3302 double t[2];
3303 cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
3304
3305 /* EXTEND_NONE degenerate radial gradients are clear */
3306 if (_linear_pattern_is_degenerate (linear))
3307 return FALSE;
3308
3309 if (sample == NULL)
3310 return FALSE;
3311
3312 _cairo_linear_pattern_box_to_parameter (linear,
3313 sample->x,
3314 sample->y,
3315 sample->x + sample->width,
3316 sample->y + sample->height,
3317 t);
3318
3319 if (t[0] < 0.0 || t[1] > 1.0)
3320 return FALSE;
3321 }
3322 } else
3323 return FALSE; /* TODO: check actual intersection */
3324
3325 for (i = 0; i < gradient->n_stops; i++)
3326 if (! CAIRO_COLOR_IS_OPAQUE (&gradient->stops[i].color))
3327 return FALSE;
3328
3329 return TRUE;
3330 }
3331
3332 /**
3333 * _cairo_pattern_is_opaque:
3334 *
3335 * Convenience function to determine whether a pattern is an opaque
3336 * pattern (of any type). The same caveats that apply to
3337 * _cairo_pattern_is_opaque_solid apply here as well.
3338 *
3339 * Return value: %TRUE if the pattern is a opaque.
3340 **/
3341 cairo_bool_t
_cairo_pattern_is_opaque(const cairo_pattern_t * abstract_pattern,const cairo_rectangle_int_t * sample)3342 _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern,
3343 const cairo_rectangle_int_t *sample)
3344 {
3345 const cairo_pattern_union_t *pattern;
3346
3347 if (abstract_pattern->has_component_alpha)
3348 return FALSE;
3349
3350 pattern = (cairo_pattern_union_t *) abstract_pattern;
3351 switch (pattern->base.type) {
3352 case CAIRO_PATTERN_TYPE_SOLID:
3353 return _cairo_pattern_is_opaque_solid (abstract_pattern);
3354 case CAIRO_PATTERN_TYPE_SURFACE:
3355 return _surface_is_opaque (&pattern->surface, sample);
3356 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3357 return _raster_source_is_opaque (&pattern->raster_source, sample);
3358 case CAIRO_PATTERN_TYPE_LINEAR:
3359 case CAIRO_PATTERN_TYPE_RADIAL:
3360 return _gradient_is_opaque (&pattern->gradient.base, sample);
3361 case CAIRO_PATTERN_TYPE_MESH:
3362 return FALSE;
3363 }
3364
3365 ASSERT_NOT_REACHED;
3366 return FALSE;
3367 }
3368
3369 cairo_bool_t
_cairo_pattern_is_clear(const cairo_pattern_t * abstract_pattern)3370 _cairo_pattern_is_clear (const cairo_pattern_t *abstract_pattern)
3371 {
3372 const cairo_pattern_union_t *pattern;
3373
3374 if (abstract_pattern->has_component_alpha)
3375 return FALSE;
3376
3377 pattern = (cairo_pattern_union_t *) abstract_pattern;
3378 switch (abstract_pattern->type) {
3379 case CAIRO_PATTERN_TYPE_SOLID:
3380 return CAIRO_COLOR_IS_CLEAR (&pattern->solid.color);
3381 case CAIRO_PATTERN_TYPE_SURFACE:
3382 return _surface_is_clear (&pattern->surface);
3383 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3384 return _raster_source_is_clear (&pattern->raster_source);
3385 case CAIRO_PATTERN_TYPE_LINEAR:
3386 case CAIRO_PATTERN_TYPE_RADIAL:
3387 return _gradient_is_clear (&pattern->gradient.base, NULL);
3388 case CAIRO_PATTERN_TYPE_MESH:
3389 return _mesh_is_clear (&pattern->mesh);
3390 }
3391
3392 ASSERT_NOT_REACHED;
3393 return FALSE;
3394 }
3395
3396 /*
3397 * Will given row of back-translation matrix work with bilinear scale?
3398 * This is true for scales larger than 1. Also it was judged acceptable
3399 * for scales larger than .75. And if there is integer translation
3400 * then a scale of exactly .5 works.
3401 */
3402 static int
use_bilinear(double x,double y,double t)3403 use_bilinear(double x, double y, double t)
3404 {
3405 /* This is the inverse matrix! */
3406 double h = x*x + y*y;
3407 if (h < 1.0 / (0.75 * 0.75))
3408 return TRUE; /* scale > .75 */
3409 if ((h > 3.99 && h < 4.01) /* scale is 1/2 */
3410 && !_cairo_fixed_from_double(x*y) /* parallel to an axis */
3411 && _cairo_fixed_is_integer (_cairo_fixed_from_double (t)))
3412 return TRUE;
3413 return FALSE;
3414 }
3415
3416 /**
3417 * _cairo_pattern_analyze_filter:
3418 * @pattern: surface pattern
3419 * Returns: the optimized #cairo_filter_t to use with @pattern.
3420 *
3421 * Possibly optimize the filter to a simpler value depending on transformation
3422 **/
3423 cairo_filter_t
_cairo_pattern_analyze_filter(const cairo_pattern_t * pattern)3424 _cairo_pattern_analyze_filter (const cairo_pattern_t *pattern)
3425 {
3426 switch (pattern->filter) {
3427 case CAIRO_FILTER_GOOD:
3428 case CAIRO_FILTER_BEST:
3429 case CAIRO_FILTER_BILINEAR:
3430 case CAIRO_FILTER_FAST:
3431 /* If source pixels map 1:1 onto destination pixels, we do
3432 * not need to filter (and do not want to filter, since it
3433 * will cause blurriness)
3434 */
3435 if (_cairo_matrix_is_pixel_exact (&pattern->matrix)) {
3436 return CAIRO_FILTER_NEAREST;
3437 } else {
3438 /* Use BILINEAR for any scale greater than .75 instead
3439 * of GOOD. For scales of 1 and larger this is identical,
3440 * for the smaller sizes it was judged that the artifacts
3441 * were not worse than the artifacts from a box filer.
3442 * BILINEAR can also be used if the scale is exactly .5
3443 * and the translation in that direction is an integer.
3444 */
3445 if (pattern->filter == CAIRO_FILTER_GOOD &&
3446 use_bilinear (pattern->matrix.xx, pattern->matrix.xy,
3447 pattern->matrix.x0) &&
3448 use_bilinear (pattern->matrix.yx, pattern->matrix.yy,
3449 pattern->matrix.y0))
3450 return CAIRO_FILTER_BILINEAR;
3451 }
3452 break;
3453
3454 case CAIRO_FILTER_NEAREST:
3455 case CAIRO_FILTER_GAUSSIAN:
3456 default:
3457 break;
3458 }
3459
3460 return pattern->filter;
3461 }
3462
3463 /**
3464 * _cairo_hypot:
3465 * Returns: value similar to hypot(@x,@y)
3466 *
3467 * May want to replace this with Manhattan distance (abs(x)+abs(y)) if
3468 * hypot is too slow, as there is no need for accuracy here.
3469 **/
3470 static inline double
_cairo_hypot(double x,double y)3471 _cairo_hypot(double x, double y)
3472 {
3473 return hypot(x, y);
3474 }
3475
3476 /**
3477 * _cairo_pattern_sampled_area:
3478 *
3479 * Return region of @pattern that will be sampled to fill @extents,
3480 * based on the transformation and filter.
3481 *
3482 * This does not include pixels that are mulitiplied by values very
3483 * close to zero by the ends of filters. This is so that transforms
3484 * that should be the identity or 90 degree rotations do not expand
3485 * the source unexpectedly.
3486 *
3487 * XXX: We don't actually have any way of querying the backend for
3488 * the filter radius, so we just guess base on what we know that
3489 * backends do currently (see bug #10508)
3490 **/
3491 void
_cairo_pattern_sampled_area(const cairo_pattern_t * pattern,const cairo_rectangle_int_t * extents,cairo_rectangle_int_t * sample)3492 _cairo_pattern_sampled_area (const cairo_pattern_t *pattern,
3493 const cairo_rectangle_int_t *extents,
3494 cairo_rectangle_int_t *sample)
3495 {
3496 double x1, x2, y1, y2;
3497 double padx, pady;
3498
3499 /* Assume filters are interpolating, which means identity
3500 cannot change the image */
3501 if (_cairo_matrix_is_identity (&pattern->matrix)) {
3502 *sample = *extents;
3503 return;
3504 }
3505
3506 /* Transform the centers of the corner pixels */
3507 x1 = extents->x + 0.5;
3508 y1 = extents->y + 0.5;
3509 x2 = x1 + (extents->width - 1);
3510 y2 = y1 + (extents->height - 1);
3511 _cairo_matrix_transform_bounding_box (&pattern->matrix,
3512 &x1, &y1, &x2, &y2,
3513 NULL);
3514
3515 /* How far away from center will it actually sample?
3516 * This is the distance from a transformed pixel center to the
3517 * furthest sample of reasonable size.
3518 */
3519 switch (pattern->filter) {
3520 case CAIRO_FILTER_NEAREST:
3521 case CAIRO_FILTER_FAST:
3522 /* Correct value is zero, but when the sample is on an integer
3523 * it is unknown if the backend will sample the pixel to the
3524 * left or right. This value makes it include both possible pixels.
3525 */
3526 padx = pady = 0.004;
3527 break;
3528 case CAIRO_FILTER_BILINEAR:
3529 case CAIRO_FILTER_GAUSSIAN:
3530 default:
3531 /* Correct value is .5 */
3532 padx = pady = 0.495;
3533 break;
3534 case CAIRO_FILTER_GOOD:
3535 /* Correct value is max(width,1)*.5 */
3536 padx = _cairo_hypot (pattern->matrix.xx, pattern->matrix.xy);
3537 if (padx <= 1.0) padx = 0.495;
3538 else if (padx >= 16.0) padx = 7.92;
3539 else padx *= 0.495;
3540 pady = _cairo_hypot (pattern->matrix.yx, pattern->matrix.yy);
3541 if (pady <= 1.0) pady = 0.495;
3542 else if (pady >= 16.0) pady = 7.92;
3543 else pady *= 0.495;
3544 break;
3545 case CAIRO_FILTER_BEST:
3546 /* Correct value is width*2 */
3547 padx = _cairo_hypot (pattern->matrix.xx, pattern->matrix.xy) * 1.98;
3548 if (padx > 7.92) padx = 7.92;
3549 pady = _cairo_hypot (pattern->matrix.yx, pattern->matrix.yy) * 1.98;
3550 if (pady > 7.92) pady = 7.92;
3551 break;
3552 }
3553
3554 /* round furthest samples to edge of pixels */
3555 x1 = floor (x1 - padx);
3556 if (x1 < CAIRO_RECT_INT_MIN) x1 = CAIRO_RECT_INT_MIN;
3557 sample->x = x1;
3558
3559 y1 = floor (y1 - pady);
3560 if (y1 < CAIRO_RECT_INT_MIN) y1 = CAIRO_RECT_INT_MIN;
3561 sample->y = y1;
3562
3563 x2 = floor (x2 + padx) + 1.0;
3564 if (x2 > CAIRO_RECT_INT_MAX) x2 = CAIRO_RECT_INT_MAX;
3565 sample->width = x2 - x1;
3566
3567 y2 = floor (y2 + pady) + 1.0;
3568 if (y2 > CAIRO_RECT_INT_MAX) y2 = CAIRO_RECT_INT_MAX;
3569 sample->height = y2 - y1;
3570 }
3571
3572 /**
3573 * _cairo_pattern_get_extents:
3574 *
3575 * Return the "target-space" extents of @pattern in @extents.
3576 *
3577 * For unbounded patterns, the @extents will be initialized with
3578 * "infinite" extents, (minimum and maximum fixed-point values).
3579 *
3580 * When is_vector is TRUE, avoid rounding to zero widths or heights that
3581 * are less than 1 unit.
3582 *
3583 * XXX: Currently, bounded gradient patterns will also return
3584 * "infinite" extents, though it would be possible to optimize these
3585 * with a little more work.
3586 **/
3587 void
_cairo_pattern_get_extents(const cairo_pattern_t * pattern,cairo_rectangle_int_t * extents,cairo_bool_t is_vector)3588 _cairo_pattern_get_extents (const cairo_pattern_t *pattern,
3589 cairo_rectangle_int_t *extents,
3590 cairo_bool_t is_vector)
3591 {
3592 double x1, y1, x2, y2;
3593 int ix1, ix2, iy1, iy2;
3594 cairo_bool_t round_x = FALSE;
3595 cairo_bool_t round_y = FALSE;
3596
3597 switch (pattern->type) {
3598 case CAIRO_PATTERN_TYPE_SOLID:
3599 goto UNBOUNDED;
3600
3601 case CAIRO_PATTERN_TYPE_SURFACE:
3602 {
3603 cairo_rectangle_int_t surface_extents;
3604 const cairo_surface_pattern_t *surface_pattern =
3605 (const cairo_surface_pattern_t *) pattern;
3606 cairo_surface_t *surface = surface_pattern->surface;
3607
3608 if (! _cairo_surface_get_extents (surface, &surface_extents))
3609 goto UNBOUNDED;
3610
3611 if (surface_extents.width == 0 || surface_extents.height == 0)
3612 goto EMPTY;
3613
3614 if (pattern->extend != CAIRO_EXTEND_NONE)
3615 goto UNBOUNDED;
3616
3617 x1 = surface_extents.x;
3618 y1 = surface_extents.y;
3619 x2 = surface_extents.x + (int) surface_extents.width;
3620 y2 = surface_extents.y + (int) surface_extents.height;
3621
3622 goto HANDLE_FILTER;
3623 }
3624 break;
3625
3626 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3627 {
3628 const cairo_raster_source_pattern_t *raster =
3629 (const cairo_raster_source_pattern_t *) pattern;
3630
3631 if (raster->extents.width == 0 || raster->extents.height == 0)
3632 goto EMPTY;
3633
3634 if (pattern->extend != CAIRO_EXTEND_NONE)
3635 goto UNBOUNDED;
3636
3637 x1 = raster->extents.x;
3638 y1 = raster->extents.y;
3639 x2 = raster->extents.x + (int) raster->extents.width;
3640 y2 = raster->extents.y + (int) raster->extents.height;
3641 }
3642 HANDLE_FILTER:
3643 switch (pattern->filter) {
3644 case CAIRO_FILTER_NEAREST:
3645 case CAIRO_FILTER_FAST:
3646 round_x = round_y = TRUE;
3647 /* We don't know which way .5 will go, so fudge it slightly. */
3648 x1 -= 0.004;
3649 y1 -= 0.004;
3650 x2 += 0.004;
3651 y2 += 0.004;
3652 break;
3653 case CAIRO_FILTER_BEST:
3654 /* Assume best filter will produce nice antialiased edges */
3655 break;
3656 case CAIRO_FILTER_BILINEAR:
3657 case CAIRO_FILTER_GAUSSIAN:
3658 case CAIRO_FILTER_GOOD:
3659 default:
3660 /* These filters can blur the edge out 1/2 pixel when scaling up */
3661 if (_cairo_hypot (pattern->matrix.xx, pattern->matrix.yx) < 1.0) {
3662 x1 -= 0.5;
3663 x2 += 0.5;
3664 round_x = TRUE;
3665 }
3666 if (_cairo_hypot (pattern->matrix.xy, pattern->matrix.yy) < 1.0) {
3667 y1 -= 0.5;
3668 y2 += 0.5;
3669 round_y = TRUE;
3670 }
3671 break;
3672 }
3673 break;
3674
3675 case CAIRO_PATTERN_TYPE_RADIAL:
3676 {
3677 const cairo_radial_pattern_t *radial =
3678 (const cairo_radial_pattern_t *) pattern;
3679 double cx1, cy1;
3680 double cx2, cy2;
3681 double r1, r2;
3682
3683 if (_radial_pattern_is_degenerate (radial)) {
3684 /* cairo-gstate should have optimised degenerate
3685 * patterns to solid clear patterns, so we can ignore
3686 * them here. */
3687 goto EMPTY;
3688 }
3689
3690 /* TODO: in some cases (focus outside/on the circle) it is
3691 * half-bounded. */
3692 if (pattern->extend != CAIRO_EXTEND_NONE)
3693 goto UNBOUNDED;
3694
3695 cx1 = radial->cd1.center.x;
3696 cy1 = radial->cd1.center.y;
3697 r1 = radial->cd1.radius;
3698
3699 cx2 = radial->cd2.center.x;
3700 cy2 = radial->cd2.center.y;
3701 r2 = radial->cd2.radius;
3702
3703 x1 = MIN (cx1 - r1, cx2 - r2);
3704 y1 = MIN (cy1 - r1, cy2 - r2);
3705 x2 = MAX (cx1 + r1, cx2 + r2);
3706 y2 = MAX (cy1 + r1, cy2 + r2);
3707 }
3708 break;
3709
3710 case CAIRO_PATTERN_TYPE_LINEAR:
3711 {
3712 const cairo_linear_pattern_t *linear =
3713 (const cairo_linear_pattern_t *) pattern;
3714
3715 if (pattern->extend != CAIRO_EXTEND_NONE)
3716 goto UNBOUNDED;
3717
3718 if (_linear_pattern_is_degenerate (linear)) {
3719 /* cairo-gstate should have optimised degenerate
3720 * patterns to solid ones, so we can again ignore
3721 * them here. */
3722 goto EMPTY;
3723 }
3724
3725 /* TODO: to get tight extents, use the matrix to transform
3726 * the pattern instead of transforming the extents later. */
3727 if (pattern->matrix.xy != 0. || pattern->matrix.yx != 0.)
3728 goto UNBOUNDED;
3729
3730 if (linear->pd1.x == linear->pd2.x) {
3731 x1 = -HUGE_VAL;
3732 x2 = HUGE_VAL;
3733 y1 = MIN (linear->pd1.y, linear->pd2.y);
3734 y2 = MAX (linear->pd1.y, linear->pd2.y);
3735 } else if (linear->pd1.y == linear->pd2.y) {
3736 x1 = MIN (linear->pd1.x, linear->pd2.x);
3737 x2 = MAX (linear->pd1.x, linear->pd2.x);
3738 y1 = -HUGE_VAL;
3739 y2 = HUGE_VAL;
3740 } else {
3741 goto UNBOUNDED;
3742 }
3743
3744 /* The current linear renderer just point-samples in the middle
3745 of the pixels, similar to the NEAREST filter: */
3746 round_x = round_y = TRUE;
3747 }
3748 break;
3749
3750 case CAIRO_PATTERN_TYPE_MESH:
3751 {
3752 const cairo_mesh_pattern_t *mesh =
3753 (const cairo_mesh_pattern_t *) pattern;
3754 if (! _cairo_mesh_pattern_coord_box (mesh, &x1, &y1, &x2, &y2))
3755 goto EMPTY;
3756 }
3757 break;
3758
3759 default:
3760 ASSERT_NOT_REACHED;
3761 }
3762
3763 if (_cairo_matrix_is_translation (&pattern->matrix)) {
3764 x1 -= pattern->matrix.x0; x2 -= pattern->matrix.x0;
3765 y1 -= pattern->matrix.y0; y2 -= pattern->matrix.y0;
3766 } else {
3767 cairo_matrix_t imatrix;
3768 cairo_status_t status;
3769
3770 imatrix = pattern->matrix;
3771 status = cairo_matrix_invert (&imatrix);
3772 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3773 assert (status == CAIRO_STATUS_SUCCESS);
3774
3775 _cairo_matrix_transform_bounding_box (&imatrix,
3776 &x1, &y1, &x2, &y2,
3777 NULL);
3778 }
3779
3780 if (!round_x) {
3781 x1 -= 0.5;
3782 x2 += 0.5;
3783 }
3784 if (x1 < CAIRO_RECT_INT_MIN)
3785 ix1 = CAIRO_RECT_INT_MIN;
3786 else
3787 ix1 = _cairo_lround (x1);
3788 if (x2 > CAIRO_RECT_INT_MAX)
3789 ix2 = CAIRO_RECT_INT_MAX;
3790 else
3791 ix2 = _cairo_lround (x2);
3792 extents->x = ix1; extents->width = ix2 - ix1;
3793 if (is_vector && extents->width == 0 && x1 != x2)
3794 extents->width += 1;
3795
3796 if (!round_y) {
3797 y1 -= 0.5;
3798 y2 += 0.5;
3799 }
3800 if (y1 < CAIRO_RECT_INT_MIN)
3801 iy1 = CAIRO_RECT_INT_MIN;
3802 else
3803 iy1 = _cairo_lround (y1);
3804 if (y2 > CAIRO_RECT_INT_MAX)
3805 iy2 = CAIRO_RECT_INT_MAX;
3806 else
3807 iy2 = _cairo_lround (y2);
3808 extents->y = iy1; extents->height = iy2 - iy1;
3809 if (is_vector && extents->height == 0 && y1 != y2)
3810 extents->height += 1;
3811
3812 return;
3813
3814 UNBOUNDED:
3815 /* unbounded patterns -> 'infinite' extents */
3816 _cairo_unbounded_rectangle_init (extents);
3817 return;
3818
3819 EMPTY:
3820 extents->x = extents->y = 0;
3821 extents->width = extents->height = 0;
3822 return;
3823 }
3824
3825 /**
3826 * _cairo_pattern_get_ink_extents:
3827 *
3828 * Return the "target-space" inked extents of @pattern in @extents.
3829 **/
3830 cairo_int_status_t
_cairo_pattern_get_ink_extents(const cairo_pattern_t * pattern,cairo_rectangle_int_t * extents)3831 _cairo_pattern_get_ink_extents (const cairo_pattern_t *pattern,
3832 cairo_rectangle_int_t *extents)
3833 {
3834 if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE &&
3835 pattern->extend == CAIRO_EXTEND_NONE)
3836 {
3837 const cairo_surface_pattern_t *surface_pattern =
3838 (const cairo_surface_pattern_t *) pattern;
3839 cairo_surface_t *surface = surface_pattern->surface;
3840
3841 surface = _cairo_surface_get_source (surface, NULL);
3842 if (_cairo_surface_is_recording (surface)) {
3843 cairo_matrix_t imatrix;
3844 cairo_box_t box;
3845 cairo_status_t status;
3846
3847 imatrix = pattern->matrix;
3848 status = cairo_matrix_invert (&imatrix);
3849 /* cairo_pattern_set_matrix ensures the matrix is invertible */
3850 assert (status == CAIRO_STATUS_SUCCESS);
3851
3852 status = _cairo_recording_surface_get_ink_bbox ((cairo_recording_surface_t *)surface,
3853 &box, &imatrix);
3854 if (unlikely (status))
3855 return status;
3856
3857 _cairo_box_round_to_rectangle (&box, extents);
3858 return CAIRO_STATUS_SUCCESS;
3859 }
3860 }
3861
3862 _cairo_pattern_get_extents (pattern, extents, TRUE);
3863 return CAIRO_STATUS_SUCCESS;
3864 }
3865
3866 static unsigned long
_cairo_solid_pattern_hash(unsigned long hash,const cairo_solid_pattern_t * solid)3867 _cairo_solid_pattern_hash (unsigned long hash,
3868 const cairo_solid_pattern_t *solid)
3869 {
3870 hash = _cairo_hash_bytes (hash, &solid->color, sizeof (solid->color));
3871
3872 return hash;
3873 }
3874
3875 static unsigned long
_cairo_gradient_color_stops_hash(unsigned long hash,const cairo_gradient_pattern_t * gradient)3876 _cairo_gradient_color_stops_hash (unsigned long hash,
3877 const cairo_gradient_pattern_t *gradient)
3878 {
3879 unsigned int n;
3880
3881 hash = _cairo_hash_bytes (hash,
3882 &gradient->n_stops,
3883 sizeof (gradient->n_stops));
3884
3885 for (n = 0; n < gradient->n_stops; n++) {
3886 hash = _cairo_hash_bytes (hash,
3887 &gradient->stops[n].offset,
3888 sizeof (double));
3889 hash = _cairo_hash_bytes (hash,
3890 &gradient->stops[n].color,
3891 sizeof (cairo_color_stop_t));
3892 }
3893
3894 return hash;
3895 }
3896
3897 unsigned long
_cairo_linear_pattern_hash(unsigned long hash,const cairo_linear_pattern_t * linear)3898 _cairo_linear_pattern_hash (unsigned long hash,
3899 const cairo_linear_pattern_t *linear)
3900 {
3901 hash = _cairo_hash_bytes (hash, &linear->pd1, sizeof (linear->pd1));
3902 hash = _cairo_hash_bytes (hash, &linear->pd2, sizeof (linear->pd2));
3903
3904 return _cairo_gradient_color_stops_hash (hash, &linear->base);
3905 }
3906
3907 unsigned long
_cairo_radial_pattern_hash(unsigned long hash,const cairo_radial_pattern_t * radial)3908 _cairo_radial_pattern_hash (unsigned long hash,
3909 const cairo_radial_pattern_t *radial)
3910 {
3911 hash = _cairo_hash_bytes (hash, &radial->cd1.center, sizeof (radial->cd1.center));
3912 hash = _cairo_hash_bytes (hash, &radial->cd1.radius, sizeof (radial->cd1.radius));
3913 hash = _cairo_hash_bytes (hash, &radial->cd2.center, sizeof (radial->cd2.center));
3914 hash = _cairo_hash_bytes (hash, &radial->cd2.radius, sizeof (radial->cd2.radius));
3915
3916 return _cairo_gradient_color_stops_hash (hash, &radial->base);
3917 }
3918
3919 static unsigned long
_cairo_mesh_pattern_hash(unsigned long hash,const cairo_mesh_pattern_t * mesh)3920 _cairo_mesh_pattern_hash (unsigned long hash, const cairo_mesh_pattern_t *mesh)
3921 {
3922 const cairo_mesh_patch_t *patch = _cairo_array_index_const (&mesh->patches, 0);
3923 unsigned int i, n = _cairo_array_num_elements (&mesh->patches);
3924
3925 for (i = 0; i < n; i++)
3926 hash = _cairo_hash_bytes (hash, patch + i, sizeof (cairo_mesh_patch_t));
3927
3928 return hash;
3929 }
3930
3931 static unsigned long
_cairo_surface_pattern_hash(unsigned long hash,const cairo_surface_pattern_t * surface)3932 _cairo_surface_pattern_hash (unsigned long hash,
3933 const cairo_surface_pattern_t *surface)
3934 {
3935 hash ^= surface->surface->unique_id;
3936
3937 return hash;
3938 }
3939
3940 static unsigned long
_cairo_raster_source_pattern_hash(unsigned long hash,const cairo_raster_source_pattern_t * raster)3941 _cairo_raster_source_pattern_hash (unsigned long hash,
3942 const cairo_raster_source_pattern_t *raster)
3943 {
3944 hash ^= (uintptr_t)raster->user_data;
3945
3946 return hash;
3947 }
3948
3949 unsigned long
_cairo_pattern_hash(const cairo_pattern_t * pattern)3950 _cairo_pattern_hash (const cairo_pattern_t *pattern)
3951 {
3952 unsigned long hash = _CAIRO_HASH_INIT_VALUE;
3953
3954 if (pattern->status)
3955 return 0;
3956
3957 hash = _cairo_hash_bytes (hash, &pattern->type, sizeof (pattern->type));
3958 if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
3959 hash = _cairo_hash_bytes (hash,
3960 &pattern->matrix, sizeof (pattern->matrix));
3961 hash = _cairo_hash_bytes (hash,
3962 &pattern->filter, sizeof (pattern->filter));
3963 hash = _cairo_hash_bytes (hash,
3964 &pattern->extend, sizeof (pattern->extend));
3965 hash = _cairo_hash_bytes (hash,
3966 &pattern->has_component_alpha,
3967 sizeof (pattern->has_component_alpha));
3968 }
3969
3970 switch (pattern->type) {
3971 case CAIRO_PATTERN_TYPE_SOLID:
3972 return _cairo_solid_pattern_hash (hash, (cairo_solid_pattern_t *) pattern);
3973 case CAIRO_PATTERN_TYPE_LINEAR:
3974 return _cairo_linear_pattern_hash (hash, (cairo_linear_pattern_t *) pattern);
3975 case CAIRO_PATTERN_TYPE_RADIAL:
3976 return _cairo_radial_pattern_hash (hash, (cairo_radial_pattern_t *) pattern);
3977 case CAIRO_PATTERN_TYPE_MESH:
3978 return _cairo_mesh_pattern_hash (hash, (cairo_mesh_pattern_t *) pattern);
3979 case CAIRO_PATTERN_TYPE_SURFACE:
3980 return _cairo_surface_pattern_hash (hash, (cairo_surface_pattern_t *) pattern);
3981 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
3982 return _cairo_raster_source_pattern_hash (hash, (cairo_raster_source_pattern_t *) pattern);
3983 default:
3984 ASSERT_NOT_REACHED;
3985 return FALSE;
3986 }
3987 }
3988
3989 static cairo_bool_t
_cairo_solid_pattern_equal(const cairo_solid_pattern_t * a,const cairo_solid_pattern_t * b)3990 _cairo_solid_pattern_equal (const cairo_solid_pattern_t *a,
3991 const cairo_solid_pattern_t *b)
3992 {
3993 return _cairo_color_equal (&a->color, &b->color);
3994 }
3995
3996 static cairo_bool_t
_cairo_gradient_color_stops_equal(const cairo_gradient_pattern_t * a,const cairo_gradient_pattern_t * b)3997 _cairo_gradient_color_stops_equal (const cairo_gradient_pattern_t *a,
3998 const cairo_gradient_pattern_t *b)
3999 {
4000 unsigned int n;
4001
4002 if (a->n_stops != b->n_stops)
4003 return FALSE;
4004
4005 for (n = 0; n < a->n_stops; n++) {
4006 if (a->stops[n].offset != b->stops[n].offset)
4007 return FALSE;
4008 if (! _cairo_color_stop_equal (&a->stops[n].color, &b->stops[n].color))
4009 return FALSE;
4010 }
4011
4012 return TRUE;
4013 }
4014
4015 cairo_bool_t
_cairo_linear_pattern_equal(const cairo_linear_pattern_t * a,const cairo_linear_pattern_t * b)4016 _cairo_linear_pattern_equal (const cairo_linear_pattern_t *a,
4017 const cairo_linear_pattern_t *b)
4018 {
4019 if (a->pd1.x != b->pd1.x)
4020 return FALSE;
4021
4022 if (a->pd1.y != b->pd1.y)
4023 return FALSE;
4024
4025 if (a->pd2.x != b->pd2.x)
4026 return FALSE;
4027
4028 if (a->pd2.y != b->pd2.y)
4029 return FALSE;
4030
4031 return _cairo_gradient_color_stops_equal (&a->base, &b->base);
4032 }
4033
4034 cairo_bool_t
_cairo_radial_pattern_equal(const cairo_radial_pattern_t * a,const cairo_radial_pattern_t * b)4035 _cairo_radial_pattern_equal (const cairo_radial_pattern_t *a,
4036 const cairo_radial_pattern_t *b)
4037 {
4038 if (a->cd1.center.x != b->cd1.center.x)
4039 return FALSE;
4040
4041 if (a->cd1.center.y != b->cd1.center.y)
4042 return FALSE;
4043
4044 if (a->cd1.radius != b->cd1.radius)
4045 return FALSE;
4046
4047 if (a->cd2.center.x != b->cd2.center.x)
4048 return FALSE;
4049
4050 if (a->cd2.center.y != b->cd2.center.y)
4051 return FALSE;
4052
4053 if (a->cd2.radius != b->cd2.radius)
4054 return FALSE;
4055
4056 return _cairo_gradient_color_stops_equal (&a->base, &b->base);
4057 }
4058
4059 static cairo_bool_t
_cairo_mesh_pattern_equal(const cairo_mesh_pattern_t * a,const cairo_mesh_pattern_t * b)4060 _cairo_mesh_pattern_equal (const cairo_mesh_pattern_t *a,
4061 const cairo_mesh_pattern_t *b)
4062 {
4063 const cairo_mesh_patch_t *patch_a, *patch_b;
4064 unsigned int i, num_patches_a, num_patches_b;
4065
4066 num_patches_a = _cairo_array_num_elements (&a->patches);
4067 num_patches_b = _cairo_array_num_elements (&b->patches);
4068
4069 if (num_patches_a != num_patches_b)
4070 return FALSE;
4071
4072 for (i = 0; i < num_patches_a; i++) {
4073 patch_a = _cairo_array_index_const (&a->patches, i);
4074 patch_b = _cairo_array_index_const (&b->patches, i);
4075 if (memcmp (patch_a, patch_b, sizeof(cairo_mesh_patch_t)) != 0)
4076 return FALSE;
4077 }
4078
4079 return TRUE;
4080 }
4081
4082 static cairo_bool_t
_cairo_surface_pattern_equal(const cairo_surface_pattern_t * a,const cairo_surface_pattern_t * b)4083 _cairo_surface_pattern_equal (const cairo_surface_pattern_t *a,
4084 const cairo_surface_pattern_t *b)
4085 {
4086 return a->surface->unique_id == b->surface->unique_id;
4087 }
4088
4089 static cairo_bool_t
_cairo_raster_source_pattern_equal(const cairo_raster_source_pattern_t * a,const cairo_raster_source_pattern_t * b)4090 _cairo_raster_source_pattern_equal (const cairo_raster_source_pattern_t *a,
4091 const cairo_raster_source_pattern_t *b)
4092 {
4093 return a->user_data == b->user_data;
4094 }
4095
4096 cairo_bool_t
_cairo_pattern_equal(const cairo_pattern_t * a,const cairo_pattern_t * b)4097 _cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b)
4098 {
4099 if (a->status || b->status)
4100 return FALSE;
4101
4102 if (a == b)
4103 return TRUE;
4104
4105 if (a->type != b->type)
4106 return FALSE;
4107
4108 if (a->has_component_alpha != b->has_component_alpha)
4109 return FALSE;
4110
4111 if (a->type != CAIRO_PATTERN_TYPE_SOLID) {
4112 if (memcmp (&a->matrix, &b->matrix, sizeof (cairo_matrix_t)))
4113 return FALSE;
4114
4115 if (a->filter != b->filter)
4116 return FALSE;
4117
4118 if (a->extend != b->extend)
4119 return FALSE;
4120 }
4121
4122 switch (a->type) {
4123 case CAIRO_PATTERN_TYPE_SOLID:
4124 return _cairo_solid_pattern_equal ((cairo_solid_pattern_t *) a,
4125 (cairo_solid_pattern_t *) b);
4126 case CAIRO_PATTERN_TYPE_LINEAR:
4127 return _cairo_linear_pattern_equal ((cairo_linear_pattern_t *) a,
4128 (cairo_linear_pattern_t *) b);
4129 case CAIRO_PATTERN_TYPE_RADIAL:
4130 return _cairo_radial_pattern_equal ((cairo_radial_pattern_t *) a,
4131 (cairo_radial_pattern_t *) b);
4132 case CAIRO_PATTERN_TYPE_MESH:
4133 return _cairo_mesh_pattern_equal ((cairo_mesh_pattern_t *) a,
4134 (cairo_mesh_pattern_t *) b);
4135 case CAIRO_PATTERN_TYPE_SURFACE:
4136 return _cairo_surface_pattern_equal ((cairo_surface_pattern_t *) a,
4137 (cairo_surface_pattern_t *) b);
4138 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4139 return _cairo_raster_source_pattern_equal ((cairo_raster_source_pattern_t *) a,
4140 (cairo_raster_source_pattern_t *) b);
4141 default:
4142 ASSERT_NOT_REACHED;
4143 return FALSE;
4144 }
4145 }
4146
4147 /**
4148 * cairo_pattern_get_rgba:
4149 * @pattern: a #cairo_pattern_t
4150 * @red: return value for red component of color, or %NULL
4151 * @green: return value for green component of color, or %NULL
4152 * @blue: return value for blue component of color, or %NULL
4153 * @alpha: return value for alpha component of color, or %NULL
4154 *
4155 * Gets the solid color for a solid color pattern.
4156 *
4157 * Return value: %CAIRO_STATUS_SUCCESS, or
4158 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid
4159 * color pattern.
4160 *
4161 * Since: 1.4
4162 **/
4163 cairo_status_t
cairo_pattern_get_rgba(cairo_pattern_t * pattern,double * red,double * green,double * blue,double * alpha)4164 cairo_pattern_get_rgba (cairo_pattern_t *pattern,
4165 double *red, double *green,
4166 double *blue, double *alpha)
4167 {
4168 cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
4169 double r0, g0, b0, a0;
4170
4171 if (pattern->status)
4172 return pattern->status;
4173
4174 if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
4175 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4176
4177 _cairo_color_get_rgba (&solid->color, &r0, &g0, &b0, &a0);
4178
4179 if (red)
4180 *red = r0;
4181 if (green)
4182 *green = g0;
4183 if (blue)
4184 *blue = b0;
4185 if (alpha)
4186 *alpha = a0;
4187
4188 return CAIRO_STATUS_SUCCESS;
4189 }
4190
4191 /**
4192 * cairo_pattern_get_surface:
4193 * @pattern: a #cairo_pattern_t
4194 * @surface: return value for surface of pattern, or %NULL
4195 *
4196 * Gets the surface of a surface pattern. The reference returned in
4197 * @surface is owned by the pattern; the caller should call
4198 * cairo_surface_reference() if the surface is to be retained.
4199 *
4200 * Return value: %CAIRO_STATUS_SUCCESS, or
4201 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a surface
4202 * pattern.
4203 *
4204 * Since: 1.4
4205 **/
4206 cairo_status_t
cairo_pattern_get_surface(cairo_pattern_t * pattern,cairo_surface_t ** surface)4207 cairo_pattern_get_surface (cairo_pattern_t *pattern,
4208 cairo_surface_t **surface)
4209 {
4210 cairo_surface_pattern_t *spat = (cairo_surface_pattern_t*) pattern;
4211
4212 if (pattern->status)
4213 return pattern->status;
4214
4215 if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
4216 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4217
4218 if (surface)
4219 *surface = spat->surface;
4220
4221 return CAIRO_STATUS_SUCCESS;
4222 }
4223
4224 /**
4225 * cairo_pattern_get_color_stop_rgba:
4226 * @pattern: a #cairo_pattern_t
4227 * @index: index of the stop to return data for
4228 * @offset: return value for the offset of the stop, or %NULL
4229 * @red: return value for red component of color, or %NULL
4230 * @green: return value for green component of color, or %NULL
4231 * @blue: return value for blue component of color, or %NULL
4232 * @alpha: return value for alpha component of color, or %NULL
4233 *
4234 * Gets the color and offset information at the given @index for a
4235 * gradient pattern. Values of @index range from 0 to n-1
4236 * where n is the number returned
4237 * by cairo_pattern_get_color_stop_count().
4238 *
4239 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
4240 * if @index is not valid for the given pattern. If the pattern is
4241 * not a gradient pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
4242 * returned.
4243 *
4244 * Since: 1.4
4245 **/
4246 cairo_status_t
cairo_pattern_get_color_stop_rgba(cairo_pattern_t * pattern,int index,double * offset,double * red,double * green,double * blue,double * alpha)4247 cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
4248 int index, double *offset,
4249 double *red, double *green,
4250 double *blue, double *alpha)
4251 {
4252 cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
4253
4254 if (pattern->status)
4255 return pattern->status;
4256
4257 if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
4258 pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
4259 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4260
4261 if (index < 0 || (unsigned int) index >= gradient->n_stops)
4262 return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4263
4264 if (offset)
4265 *offset = gradient->stops[index].offset;
4266 if (red)
4267 *red = gradient->stops[index].color.red;
4268 if (green)
4269 *green = gradient->stops[index].color.green;
4270 if (blue)
4271 *blue = gradient->stops[index].color.blue;
4272 if (alpha)
4273 *alpha = gradient->stops[index].color.alpha;
4274
4275 return CAIRO_STATUS_SUCCESS;
4276 }
4277
4278 /**
4279 * cairo_pattern_get_color_stop_count:
4280 * @pattern: a #cairo_pattern_t
4281 * @count: return value for the number of color stops, or %NULL
4282 *
4283 * Gets the number of color stops specified in the given gradient
4284 * pattern.
4285 *
4286 * Return value: %CAIRO_STATUS_SUCCESS, or
4287 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
4288 * pattern.
4289 *
4290 * Since: 1.4
4291 **/
4292 cairo_status_t
cairo_pattern_get_color_stop_count(cairo_pattern_t * pattern,int * count)4293 cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
4294 int *count)
4295 {
4296 cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
4297
4298 if (pattern->status)
4299 return pattern->status;
4300
4301 if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
4302 pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
4303 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4304
4305 if (count)
4306 *count = gradient->n_stops;
4307
4308 return CAIRO_STATUS_SUCCESS;
4309 }
4310
4311 /**
4312 * cairo_pattern_get_linear_points:
4313 * @pattern: a #cairo_pattern_t
4314 * @x0: return value for the x coordinate of the first point, or %NULL
4315 * @y0: return value for the y coordinate of the first point, or %NULL
4316 * @x1: return value for the x coordinate of the second point, or %NULL
4317 * @y1: return value for the y coordinate of the second point, or %NULL
4318 *
4319 * Gets the gradient endpoints for a linear gradient.
4320 *
4321 * Return value: %CAIRO_STATUS_SUCCESS, or
4322 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a linear
4323 * gradient pattern.
4324 *
4325 * Since: 1.4
4326 **/
4327 cairo_status_t
cairo_pattern_get_linear_points(cairo_pattern_t * pattern,double * x0,double * y0,double * x1,double * y1)4328 cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
4329 double *x0, double *y0,
4330 double *x1, double *y1)
4331 {
4332 cairo_linear_pattern_t *linear = (cairo_linear_pattern_t*) pattern;
4333
4334 if (pattern->status)
4335 return pattern->status;
4336
4337 if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR)
4338 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4339
4340 if (x0)
4341 *x0 = linear->pd1.x;
4342 if (y0)
4343 *y0 = linear->pd1.y;
4344 if (x1)
4345 *x1 = linear->pd2.x;
4346 if (y1)
4347 *y1 = linear->pd2.y;
4348
4349 return CAIRO_STATUS_SUCCESS;
4350 }
4351
4352 /**
4353 * cairo_pattern_get_radial_circles:
4354 * @pattern: a #cairo_pattern_t
4355 * @x0: return value for the x coordinate of the center of the first circle, or %NULL
4356 * @y0: return value for the y coordinate of the center of the first circle, or %NULL
4357 * @r0: return value for the radius of the first circle, or %NULL
4358 * @x1: return value for the x coordinate of the center of the second circle, or %NULL
4359 * @y1: return value for the y coordinate of the center of the second circle, or %NULL
4360 * @r1: return value for the radius of the second circle, or %NULL
4361 *
4362 * Gets the gradient endpoint circles for a radial gradient, each
4363 * specified as a center coordinate and a radius.
4364 *
4365 * Return value: %CAIRO_STATUS_SUCCESS, or
4366 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial
4367 * gradient pattern.
4368 *
4369 * Since: 1.4
4370 **/
4371 cairo_status_t
cairo_pattern_get_radial_circles(cairo_pattern_t * pattern,double * x0,double * y0,double * r0,double * x1,double * y1,double * r1)4372 cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
4373 double *x0, double *y0, double *r0,
4374 double *x1, double *y1, double *r1)
4375 {
4376 cairo_radial_pattern_t *radial = (cairo_radial_pattern_t*) pattern;
4377
4378 if (pattern->status)
4379 return pattern->status;
4380
4381 if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
4382 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4383
4384 if (x0)
4385 *x0 = radial->cd1.center.x;
4386 if (y0)
4387 *y0 = radial->cd1.center.y;
4388 if (r0)
4389 *r0 = radial->cd1.radius;
4390 if (x1)
4391 *x1 = radial->cd2.center.x;
4392 if (y1)
4393 *y1 = radial->cd2.center.y;
4394 if (r1)
4395 *r1 = radial->cd2.radius;
4396
4397 return CAIRO_STATUS_SUCCESS;
4398 }
4399
4400 /**
4401 * cairo_mesh_pattern_get_patch_count:
4402 * @pattern: a #cairo_pattern_t
4403 * @count: return value for the number patches, or %NULL
4404 *
4405 * Gets the number of patches specified in the given mesh pattern.
4406 *
4407 * The number only includes patches which have been finished by
4408 * calling cairo_mesh_pattern_end_patch(). For example it will be 0
4409 * during the definition of the first patch.
4410 *
4411 * Return value: %CAIRO_STATUS_SUCCESS, or
4412 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a mesh
4413 * pattern.
4414 *
4415 * Since: 1.12
4416 **/
4417 cairo_status_t
cairo_mesh_pattern_get_patch_count(cairo_pattern_t * pattern,unsigned int * count)4418 cairo_mesh_pattern_get_patch_count (cairo_pattern_t *pattern,
4419 unsigned int *count)
4420 {
4421 cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
4422
4423 if (unlikely (pattern->status))
4424 return pattern->status;
4425
4426 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH))
4427 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4428
4429 if (count) {
4430 *count = _cairo_array_num_elements (&mesh->patches);
4431 if (mesh->current_patch)
4432 *count -= 1;
4433 }
4434
4435 return CAIRO_STATUS_SUCCESS;
4436 }
4437 slim_hidden_def (cairo_mesh_pattern_get_patch_count);
4438
4439 /**
4440 * cairo_mesh_pattern_get_path:
4441 * @pattern: a #cairo_pattern_t
4442 * @patch_num: the patch number to return data for
4443 *
4444 * Gets path defining the patch @patch_num for a mesh
4445 * pattern.
4446 *
4447 * @patch_num can range from 0 to n-1 where n is the number returned by
4448 * cairo_mesh_pattern_get_patch_count().
4449 *
4450 * Return value: the path defining the patch, or a path with status
4451 * %CAIRO_STATUS_INVALID_INDEX if @patch_num or @point_num is not
4452 * valid for @pattern. If @pattern is not a mesh pattern, a path with
4453 * status %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is returned.
4454 *
4455 * Since: 1.12
4456 **/
4457 cairo_path_t *
cairo_mesh_pattern_get_path(cairo_pattern_t * pattern,unsigned int patch_num)4458 cairo_mesh_pattern_get_path (cairo_pattern_t *pattern,
4459 unsigned int patch_num)
4460 {
4461 cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
4462 const cairo_mesh_patch_t *patch;
4463 cairo_path_t *path;
4464 cairo_path_data_t *data;
4465 unsigned int patch_count;
4466 int l, current_point;
4467
4468 if (unlikely (pattern->status))
4469 return _cairo_path_create_in_error (pattern->status);
4470
4471 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH))
4472 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH));
4473
4474 patch_count = _cairo_array_num_elements (&mesh->patches);
4475 if (mesh->current_patch)
4476 patch_count--;
4477
4478 if (unlikely (patch_num >= patch_count))
4479 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_INDEX));
4480
4481 patch = _cairo_array_index_const (&mesh->patches, patch_num);
4482
4483 path = _cairo_malloc (sizeof (cairo_path_t));
4484 if (path == NULL)
4485 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
4486
4487 path->num_data = 18;
4488 path->data = _cairo_malloc_ab (path->num_data,
4489 sizeof (cairo_path_data_t));
4490 if (path->data == NULL) {
4491 free (path);
4492 return _cairo_path_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
4493 }
4494
4495 data = path->data;
4496 data[0].header.type = CAIRO_PATH_MOVE_TO;
4497 data[0].header.length = 2;
4498 data[1].point.x = patch->points[0][0].x;
4499 data[1].point.y = patch->points[0][0].y;
4500 data += data[0].header.length;
4501
4502 current_point = 0;
4503
4504 for (l = 0; l < 4; l++) {
4505 int i, j, k;
4506
4507 data[0].header.type = CAIRO_PATH_CURVE_TO;
4508 data[0].header.length = 4;
4509
4510 for (k = 1; k < 4; k++) {
4511 current_point = (current_point + 1) % 12;
4512 i = mesh_path_point_i[current_point];
4513 j = mesh_path_point_j[current_point];
4514 data[k].point.x = patch->points[i][j].x;
4515 data[k].point.y = patch->points[i][j].y;
4516 }
4517
4518 data += data[0].header.length;
4519 }
4520
4521 path->status = CAIRO_STATUS_SUCCESS;
4522
4523 return path;
4524 }
4525 slim_hidden_def (cairo_mesh_pattern_get_path);
4526
4527 /**
4528 * cairo_mesh_pattern_get_corner_color_rgba:
4529 * @pattern: a #cairo_pattern_t
4530 * @patch_num: the patch number to return data for
4531 * @corner_num: the corner number to return data for
4532 * @red: return value for red component of color, or %NULL
4533 * @green: return value for green component of color, or %NULL
4534 * @blue: return value for blue component of color, or %NULL
4535 * @alpha: return value for alpha component of color, or %NULL
4536 *
4537 * Gets the color information in corner @corner_num of patch
4538 * @patch_num for a mesh pattern.
4539 *
4540 * @patch_num can range from 0 to n-1 where n is the number returned by
4541 * cairo_mesh_pattern_get_patch_count().
4542 *
4543 * Valid values for @corner_num are from 0 to 3 and identify the
4544 * corners as explained in cairo_pattern_create_mesh().
4545 *
4546 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
4547 * if @patch_num or @corner_num is not valid for @pattern. If
4548 * @pattern is not a mesh pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH
4549 * is returned.
4550 *
4551 * Since: 1.12
4552 **/
4553 cairo_status_t
cairo_mesh_pattern_get_corner_color_rgba(cairo_pattern_t * pattern,unsigned int patch_num,unsigned int corner_num,double * red,double * green,double * blue,double * alpha)4554 cairo_mesh_pattern_get_corner_color_rgba (cairo_pattern_t *pattern,
4555 unsigned int patch_num,
4556 unsigned int corner_num,
4557 double *red, double *green,
4558 double *blue, double *alpha)
4559 {
4560 cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
4561 unsigned int patch_count;
4562 const cairo_mesh_patch_t *patch;
4563
4564 if (unlikely (pattern->status))
4565 return pattern->status;
4566
4567 if (unlikely (pattern->type != CAIRO_PATTERN_TYPE_MESH))
4568 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4569
4570 if (unlikely (corner_num > 3))
4571 return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4572
4573 patch_count = _cairo_array_num_elements (&mesh->patches);
4574 if (mesh->current_patch)
4575 patch_count--;
4576
4577 if (unlikely (patch_num >= patch_count))
4578 return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4579
4580 patch = _cairo_array_index_const (&mesh->patches, patch_num);
4581
4582 if (red)
4583 *red = patch->colors[corner_num].red;
4584 if (green)
4585 *green = patch->colors[corner_num].green;
4586 if (blue)
4587 *blue = patch->colors[corner_num].blue;
4588 if (alpha)
4589 *alpha = patch->colors[corner_num].alpha;
4590
4591 return CAIRO_STATUS_SUCCESS;
4592 }
4593 slim_hidden_def (cairo_mesh_pattern_get_corner_color_rgba);
4594
4595 /**
4596 * cairo_mesh_pattern_get_control_point:
4597 * @pattern: a #cairo_pattern_t
4598 * @patch_num: the patch number to return data for
4599 * @point_num: the control point number to return data for
4600 * @x: return value for the x coordinate of the control point, or %NULL
4601 * @y: return value for the y coordinate of the control point, or %NULL
4602 *
4603 * Gets the control point @point_num of patch @patch_num for a mesh
4604 * pattern.
4605 *
4606 * @patch_num can range from 0 to n-1 where n is the number returned by
4607 * cairo_mesh_pattern_get_patch_count().
4608 *
4609 * Valid values for @point_num are from 0 to 3 and identify the
4610 * control points as explained in cairo_pattern_create_mesh().
4611 *
4612 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
4613 * if @patch_num or @point_num is not valid for @pattern. If @pattern
4614 * is not a mesh pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
4615 * returned.
4616 *
4617 * Since: 1.12
4618 **/
4619 cairo_status_t
cairo_mesh_pattern_get_control_point(cairo_pattern_t * pattern,unsigned int patch_num,unsigned int point_num,double * x,double * y)4620 cairo_mesh_pattern_get_control_point (cairo_pattern_t *pattern,
4621 unsigned int patch_num,
4622 unsigned int point_num,
4623 double *x, double *y)
4624 {
4625 cairo_mesh_pattern_t *mesh = (cairo_mesh_pattern_t *) pattern;
4626 const cairo_mesh_patch_t *patch;
4627 unsigned int patch_count;
4628 int i, j;
4629
4630 if (pattern->status)
4631 return pattern->status;
4632
4633 if (pattern->type != CAIRO_PATTERN_TYPE_MESH)
4634 return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4635
4636 if (point_num > 3)
4637 return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4638
4639 patch_count = _cairo_array_num_elements (&mesh->patches);
4640 if (mesh->current_patch)
4641 patch_count--;
4642
4643 if (unlikely (patch_num >= patch_count))
4644 return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
4645
4646 patch = _cairo_array_index_const (&mesh->patches, patch_num);
4647
4648 i = mesh_control_point_i[point_num];
4649 j = mesh_control_point_j[point_num];
4650
4651 if (x)
4652 *x = patch->points[i][j].x;
4653 if (y)
4654 *y = patch->points[i][j].y;
4655
4656 return CAIRO_STATUS_SUCCESS;
4657 }
4658 slim_hidden_def (cairo_mesh_pattern_get_control_point);
4659
4660 void
_cairo_pattern_reset_static_data(void)4661 _cairo_pattern_reset_static_data (void)
4662 {
4663 int i;
4664
4665 for (i = 0; i < ARRAY_LENGTH (freed_pattern_pool); i++)
4666 _freed_pool_reset (&freed_pattern_pool[i]);
4667 }
4668
4669 static void
_cairo_debug_print_surface_pattern(FILE * file,const cairo_surface_pattern_t * pattern)4670 _cairo_debug_print_surface_pattern (FILE *file,
4671 const cairo_surface_pattern_t *pattern)
4672 {
4673 const char *s;
4674 switch (pattern->surface->type) {
4675 case CAIRO_SURFACE_TYPE_IMAGE: s = "image"; break;
4676 case CAIRO_SURFACE_TYPE_PDF: s = "pdf"; break;
4677 case CAIRO_SURFACE_TYPE_PS: s = "ps"; break;
4678 case CAIRO_SURFACE_TYPE_XLIB: s = "xlib"; break;
4679 case CAIRO_SURFACE_TYPE_XCB: s = "xcb"; break;
4680 case CAIRO_SURFACE_TYPE_GLITZ: s = "glitz"; break;
4681 case CAIRO_SURFACE_TYPE_QUARTZ: s = "quartz"; break;
4682 case CAIRO_SURFACE_TYPE_WIN32: s = "win32"; break;
4683 case CAIRO_SURFACE_TYPE_BEOS: s = "beos"; break;
4684 case CAIRO_SURFACE_TYPE_DIRECTFB: s = "directfb"; break;
4685 case CAIRO_SURFACE_TYPE_SVG: s = "svg"; break;
4686 case CAIRO_SURFACE_TYPE_OS2: s = "os2"; break;
4687 case CAIRO_SURFACE_TYPE_WIN32_PRINTING: s = "win32_printing"; break;
4688 case CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: s = "quartz_image"; break;
4689 case CAIRO_SURFACE_TYPE_SCRIPT: s = "script"; break;
4690 case CAIRO_SURFACE_TYPE_QT: s = "qt"; break;
4691 case CAIRO_SURFACE_TYPE_RECORDING: s = "recording"; break;
4692 case CAIRO_SURFACE_TYPE_VG: s = "vg"; break;
4693 case CAIRO_SURFACE_TYPE_GL: s = "gl"; break;
4694 case CAIRO_SURFACE_TYPE_DRM: s = "drm"; break;
4695 case CAIRO_SURFACE_TYPE_TEE: s = "tee"; break;
4696 case CAIRO_SURFACE_TYPE_XML: s = "xml"; break;
4697 case CAIRO_SURFACE_TYPE_SKIA: s = "skia"; break; /* Deprecated */
4698 case CAIRO_SURFACE_TYPE_SUBSURFACE: s = "subsurface"; break;
4699 case CAIRO_SURFACE_TYPE_COGL: s = "cogl"; break;
4700 default: s = "invalid"; ASSERT_NOT_REACHED; break;
4701 }
4702 fprintf (file, " surface type: %s\n", s);
4703 }
4704
4705 static void
_cairo_debug_print_raster_source_pattern(FILE * file,const cairo_raster_source_pattern_t * raster)4706 _cairo_debug_print_raster_source_pattern (FILE *file,
4707 const cairo_raster_source_pattern_t *raster)
4708 {
4709 fprintf (file, " content: %x, size %dx%d\n", raster->content, raster->extents.width, raster->extents.height);
4710 }
4711
4712 static void
_cairo_debug_print_linear_pattern(FILE * file,const cairo_linear_pattern_t * pattern)4713 _cairo_debug_print_linear_pattern (FILE *file,
4714 const cairo_linear_pattern_t *pattern)
4715 {
4716 }
4717
4718 static void
_cairo_debug_print_radial_pattern(FILE * file,const cairo_radial_pattern_t * pattern)4719 _cairo_debug_print_radial_pattern (FILE *file,
4720 const cairo_radial_pattern_t *pattern)
4721 {
4722 }
4723
4724 static void
_cairo_debug_print_mesh_pattern(FILE * file,const cairo_mesh_pattern_t * pattern)4725 _cairo_debug_print_mesh_pattern (FILE *file,
4726 const cairo_mesh_pattern_t *pattern)
4727 {
4728 }
4729
4730 void
_cairo_debug_print_pattern(FILE * file,const cairo_pattern_t * pattern)4731 _cairo_debug_print_pattern (FILE *file, const cairo_pattern_t *pattern)
4732 {
4733 const char *s;
4734 switch (pattern->type) {
4735 case CAIRO_PATTERN_TYPE_SOLID: s = "solid"; break;
4736 case CAIRO_PATTERN_TYPE_SURFACE: s = "surface"; break;
4737 case CAIRO_PATTERN_TYPE_LINEAR: s = "linear"; break;
4738 case CAIRO_PATTERN_TYPE_RADIAL: s = "radial"; break;
4739 case CAIRO_PATTERN_TYPE_MESH: s = "mesh"; break;
4740 case CAIRO_PATTERN_TYPE_RASTER_SOURCE: s = "raster"; break;
4741 default: s = "invalid"; ASSERT_NOT_REACHED; break;
4742 }
4743
4744 fprintf (file, "pattern: %s\n", s);
4745 if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
4746 return;
4747
4748 switch (pattern->extend) {
4749 case CAIRO_EXTEND_NONE: s = "none"; break;
4750 case CAIRO_EXTEND_REPEAT: s = "repeat"; break;
4751 case CAIRO_EXTEND_REFLECT: s = "reflect"; break;
4752 case CAIRO_EXTEND_PAD: s = "pad"; break;
4753 default: s = "invalid"; ASSERT_NOT_REACHED; break;
4754 }
4755 fprintf (file, " extend: %s\n", s);
4756
4757 switch (pattern->filter) {
4758 case CAIRO_FILTER_FAST: s = "fast"; break;
4759 case CAIRO_FILTER_GOOD: s = "good"; break;
4760 case CAIRO_FILTER_BEST: s = "best"; break;
4761 case CAIRO_FILTER_NEAREST: s = "nearest"; break;
4762 case CAIRO_FILTER_BILINEAR: s = "bilinear"; break;
4763 case CAIRO_FILTER_GAUSSIAN: s = "gaussian"; break;
4764 default: s = "invalid"; ASSERT_NOT_REACHED; break;
4765 }
4766 fprintf (file, " filter: %s\n", s);
4767 fprintf (file, " matrix: [%g %g %g %g %g %g]\n",
4768 pattern->matrix.xx, pattern->matrix.yx,
4769 pattern->matrix.xy, pattern->matrix.yy,
4770 pattern->matrix.x0, pattern->matrix.y0);
4771 switch (pattern->type) {
4772 default:
4773 case CAIRO_PATTERN_TYPE_SOLID:
4774 break;
4775 case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
4776 _cairo_debug_print_raster_source_pattern (file, (cairo_raster_source_pattern_t *)pattern);
4777 break;
4778 case CAIRO_PATTERN_TYPE_SURFACE:
4779 _cairo_debug_print_surface_pattern (file, (cairo_surface_pattern_t *)pattern);
4780 break;
4781 case CAIRO_PATTERN_TYPE_LINEAR:
4782 _cairo_debug_print_linear_pattern (file, (cairo_linear_pattern_t *)pattern);
4783 break;
4784 case CAIRO_PATTERN_TYPE_RADIAL:
4785 _cairo_debug_print_radial_pattern (file, (cairo_radial_pattern_t *)pattern);
4786 break;
4787 case CAIRO_PATTERN_TYPE_MESH:
4788 _cairo_debug_print_mesh_pattern (file, (cairo_mesh_pattern_t *)pattern);
4789 break;
4790 }
4791 }
4792