Bug Summary

File:root/firefox-clang/gfx/cairo/cairo/src/cairo-pattern.c
Warning:line 662, column 2
Value stored to 'status' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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