Subversion Repositories Kolibri OS

Rev

Rev 1892 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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