Subversion Repositories Kolibri OS

Rev

Rev 1892 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 1892 Rev 3959
Line 27... Line 27...
27
 *	    Keith Packard 
27
 *	    Keith Packard 
28
 *	    Carl Worth 
28
 *	    Carl Worth 
29
 */
29
 */
Line 30... Line 30...
30
 
30
 
-
 
31
#include "cairoint.h"
-
 
32
 
31
#include "cairoint.h"
33
#include "cairo-array-private.h"
32
#include "cairo-error-private.h"
34
#include "cairo-error-private.h"
-
 
35
#include "cairo-freed-pool-private.h"
-
 
36
#include "cairo-image-surface-private.h"
-
 
37
#include "cairo-list-inline.h"
-
 
38
#include "cairo-path-private.h"
-
 
39
#include "cairo-pattern-private.h"
-
 
40
#include "cairo-recording-surface-inline.h"
-
 
41
#include "cairo-surface-snapshot-inline.h"
-
 
42
 
-
 
43
#include 
-
 
44
 
Line 33... Line 45...
33
#include "cairo-freed-pool-private.h"
45
#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
34
 
46
 
35
/**
47
/**
36
 * SECTION:cairo-pattern
48
 * SECTION:cairo-pattern
Line 42... Line 54...
42
 * The primary use of patterns is as the source for all cairo drawing 
54
 * The primary use of patterns is as the source for all cairo drawing 
43
 * operations, although they can also be used as masks, that is, as the 
55
 * operations, although they can also be used as masks, that is, as the 
44
 * brush too.
56
 * brush too.
45
 *
57
 *
46
 * A cairo pattern is created by using one of the many constructors,
58
 * A cairo pattern is created by using one of the many constructors,
-
 
59
 * of the form
47
 * of the form cairo_pattern_create_type()
60
 * cairo_pattern_create_type()
48
 * or implicitly through
61
 * or implicitly through
49
 * cairo_set_source_type() functions.
62
 * cairo_set_source_type()
-
 
63
 * functions.
50
 */
64
 **/
Line 51... Line -...
51
 
-
 
52
#if HAS_FREED_POOL
65
 
53
static freed_pool_t freed_pattern_pool[4];
-
 
Line 54... Line 66...
54
#endif
66
static freed_pool_t freed_pattern_pool[5];
55
 
67
 
56
static const cairo_solid_pattern_t _cairo_pattern_nil = {
68
static const cairo_solid_pattern_t _cairo_pattern_nil = {
57
    { CAIRO_PATTERN_TYPE_SOLID,		/* type */
69
    {
58
      CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
70
      CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
59
      CAIRO_STATUS_NO_MEMORY,		/* status */
71
      CAIRO_STATUS_NO_MEMORY,		/* status */
-
 
72
      { 0, 0, 0, NULL },		/* user_data */
-
 
73
      { NULL, NULL },			/* observers */
60
      { 0, 0, 0, NULL },		/* user_data */
74
 
61
      { 1., 0., 0., 1., 0., 0., },	/* matrix */
75
      CAIRO_PATTERN_TYPE_SOLID,		/* type */
-
 
76
      CAIRO_FILTER_DEFAULT,		/* filter */
-
 
77
      CAIRO_EXTEND_GRADIENT_DEFAULT,	/* extend */
-
 
78
      FALSE,				/* has component alpha */
-
 
79
      { 1., 0., 0., 1., 0., 0., },	/* matrix */
62
      CAIRO_FILTER_DEFAULT,		/* filter */
80
      1.0                               /* opacity */
Line 63... Line 81...
63
      CAIRO_EXTEND_GRADIENT_DEFAULT },	/* extend */
81
    }
64
};
82
};
65
 
83
 
66
static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = {
84
static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = {
67
    { CAIRO_PATTERN_TYPE_SOLID,		/* type */
85
    {
68
      CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
86
      CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
-
 
87
      CAIRO_STATUS_NULL_POINTER,	/* status */
-
 
88
      { 0, 0, 0, NULL },		/* user_data */
69
      CAIRO_STATUS_NULL_POINTER,	/* status */
89
      { NULL, NULL },			/* observers */
70
      { 0, 0, 0, NULL },		/* user_data */
90
 
-
 
91
      CAIRO_PATTERN_TYPE_SOLID,		/* type */
-
 
92
      CAIRO_FILTER_DEFAULT,		/* filter */
-
 
93
      CAIRO_EXTEND_GRADIENT_DEFAULT,	/* extend */
-
 
94
      FALSE,				/* has component alpha */
71
      { 1., 0., 0., 1., 0., 0., },	/* matrix */
95
      { 1., 0., 0., 1., 0., 0., },	/* matrix */
Line 72... Line 96...
72
      CAIRO_FILTER_DEFAULT,		/* filter */
96
      1.0                               /* opacity */
73
      CAIRO_EXTEND_GRADIENT_DEFAULT },	/* extend */
97
    }
74
};
98
};
75
 
99
 
76
const cairo_solid_pattern_t _cairo_pattern_black = {
100
const cairo_solid_pattern_t _cairo_pattern_black = {
-
 
101
    {
-
 
102
      CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
-
 
103
      CAIRO_STATUS_SUCCESS,		/* status */
-
 
104
      { 0, 0, 0, NULL },		/* user_data */
-
 
105
      { NULL, NULL },			/* observers */
-
 
106
 
77
    { CAIRO_PATTERN_TYPE_SOLID,		/* type */
107
      CAIRO_PATTERN_TYPE_SOLID,		/* type */
78
      CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
108
      CAIRO_FILTER_NEAREST,		/* filter */
79
      CAIRO_STATUS_SUCCESS,		/* status */
109
      CAIRO_EXTEND_REPEAT,		/* extend */
80
      { 0, 0, 0, NULL },		/* user_data */
110
      FALSE,				/* has component alpha */
81
      { 1., 0., 0., 1., 0., 0., },	/* matrix */
111
      { 1., 0., 0., 1., 0., 0., },	/* matrix */
Line 82... Line 112...
82
      CAIRO_FILTER_DEFAULT,		/* filter */
112
      1.0                               /* opacity */
83
      CAIRO_EXTEND_GRADIENT_DEFAULT},	/* extend */
113
    },
84
    { 0., 0., 0., 1., 0, 0, 0, 0xffff },/* color (double rgba, short rgba) */
114
    { 0., 0., 0., 1., 0, 0, 0, 0xffff },/* color (double rgba, short rgba) */
85
};
115
};
86
 
116
 
-
 
117
const cairo_solid_pattern_t _cairo_pattern_clear = {
-
 
118
    {
-
 
119
      CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
-
 
120
      CAIRO_STATUS_SUCCESS,		/* status */
-
 
121
      { 0, 0, 0, NULL },		/* user_data */
-
 
122
      { NULL, NULL },			/* observers */
87
const cairo_solid_pattern_t _cairo_pattern_clear = {
123
 
88
    { CAIRO_PATTERN_TYPE_SOLID,		/* type */
124
      CAIRO_PATTERN_TYPE_SOLID,		/* type */
89
      CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
125
      CAIRO_FILTER_NEAREST,		/* filter */
90
      CAIRO_STATUS_SUCCESS,		/* status */
126
      CAIRO_EXTEND_REPEAT,		/* extend */
91
      { 0, 0, 0, NULL },		/* user_data */
127
      FALSE,				/* has component alpha */
Line 92... Line 128...
92
      { 1., 0., 0., 1., 0., 0., },	/* matrix */
128
      { 1., 0., 0., 1., 0., 0., },	/* matrix */
93
      CAIRO_FILTER_DEFAULT,		/* filter */
129
      1.0                               /* opacity */
94
      CAIRO_EXTEND_GRADIENT_DEFAULT},	/* extend */
130
    },
95
    { 0., 0., 0., 0., 0, 0, 0, 0 },/* color (double rgba, short rgba) */
131
    { 0., 0., 0., 0., 0, 0, 0, 0 },/* color (double rgba, short rgba) */
96
};
132
};
-
 
133
 
-
 
134
const cairo_solid_pattern_t _cairo_pattern_white = {
-
 
135
    {
-
 
136
      CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
-
 
137
      CAIRO_STATUS_SUCCESS,		/* status */
-
 
138
      { 0, 0, 0, NULL },		/* user_data */
97
 
139
      { NULL, NULL },			/* observers */
98
const cairo_solid_pattern_t _cairo_pattern_white = {
140
 
99
    { CAIRO_PATTERN_TYPE_SOLID,		/* type */
141
      CAIRO_PATTERN_TYPE_SOLID,		/* type */
100
      CAIRO_REFERENCE_COUNT_INVALID,	/* ref_count */
142
      CAIRO_FILTER_NEAREST,		/* filter */
101
      CAIRO_STATUS_SUCCESS,		/* status */
143
      CAIRO_EXTEND_REPEAT,		/* extend */
Line -... Line 144...
-
 
144
      FALSE,				/* has component alpha */
-
 
145
      { 1., 0., 0., 1., 0., 0., },	/* matrix */
-
 
146
      1.0                               /* opacity */
-
 
147
    },
-
 
148
    { 1., 1., 1., 1., 0xffff, 0xffff, 0xffff, 0xffff },/* color (double rgba, short rgba) */
-
 
149
};
-
 
150
 
-
 
151
static void
-
 
152
_cairo_pattern_notify_observers (cairo_pattern_t *pattern,
-
 
153
				 unsigned int flags)
102
      { 0, 0, 0, NULL },		/* user_data */
154
{
103
      { 1., 0., 0., 1., 0., 0., },	/* matrix */
155
    cairo_pattern_observer_t *pos;
104
      CAIRO_FILTER_DEFAULT,		/* filter */
156
 
105
      CAIRO_EXTEND_GRADIENT_DEFAULT},	/* extend */
157
    cairo_list_foreach_entry (pos, cairo_pattern_observer_t, &pattern->observers, link)
106
    { 1., 1., 1., 1., 0xffff, 0xffff, 0xffff, 0xffff },/* color (double rgba, short rgba) */
158
	pos->notify (pos, pattern, flags);
Line 135... Line 187...
135
    _cairo_status_set_error (&pattern->status, status);
187
    _cairo_status_set_error (&pattern->status, status);
Line 136... Line 188...
136
 
188
 
137
    return _cairo_error (status);
189
    return _cairo_error (status);
Line 138... Line 190...
138
}
190
}
139
 
191
 
140
static void
192
void
141
_cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
193
_cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
142
{
194
{
143
#if HAVE_VALGRIND
195
#if HAVE_VALGRIND
Line 152... Line 204...
152
	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t));
204
	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t));
153
	break;
205
	break;
154
    case CAIRO_PATTERN_TYPE_RADIAL:
206
    case CAIRO_PATTERN_TYPE_RADIAL:
155
	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t));
207
	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t));
156
	break;
208
	break;
-
 
209
    case CAIRO_PATTERN_TYPE_MESH:
-
 
210
	VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t));
-
 
211
	break;
-
 
212
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
-
 
213
	break;
157
    }
214
    }
158
#endif
215
#endif
Line 159... Line 216...
159
 
216
 
160
    pattern->type      = type;
217
    pattern->type      = type;
Line 164... Line 221...
164
     * Callers needs to explicitly increment the count for heap allocations. */
221
     * Callers needs to explicitly increment the count for heap allocations. */
165
    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
222
    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
Line 166... Line 223...
166
 
223
 
Line 167... Line 224...
167
    _cairo_user_data_array_init (&pattern->user_data);
224
    _cairo_user_data_array_init (&pattern->user_data);
-
 
225
 
168
 
226
    if (type == CAIRO_PATTERN_TYPE_SURFACE ||
169
    if (type == CAIRO_PATTERN_TYPE_SURFACE)
227
	type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
170
	pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
228
	pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
Line 171... Line 229...
171
    else
229
    else
-
 
230
	pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT;
Line 172... Line 231...
172
	pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT;
231
 
Line 173... Line 232...
173
 
232
    pattern->filter    = CAIRO_FILTER_DEFAULT;
-
 
233
    pattern->opacity   = 1.0;
-
 
234
 
174
    pattern->filter    = CAIRO_FILTER_DEFAULT;
235
    pattern->has_component_alpha = FALSE;
Line 175... Line 236...
175
 
236
 
176
    pattern->has_component_alpha = FALSE;
237
    cairo_matrix_init_identity (&pattern->matrix);
177
 
238
 
Line 217... Line 278...
217
    }
278
    }
Line 218... Line 279...
218
 
279
 
219
    return CAIRO_STATUS_SUCCESS;
280
    return CAIRO_STATUS_SUCCESS;
Line -... Line 281...
-
 
281
}
-
 
282
 
-
 
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));
220
}
293
}
221
 
294
 
222
cairo_status_t
295
cairo_status_t
223
_cairo_pattern_init_copy (cairo_pattern_t	*pattern,
296
_cairo_pattern_init_copy (cairo_pattern_t	*pattern,
-
 
297
			  const cairo_pattern_t *other)
-
 
298
{
224
			  const cairo_pattern_t *other)
299
    cairo_status_t status;
225
{
300
 
Line 226... Line 301...
226
    if (other->status)
301
    if (other->status)
227
	return _cairo_pattern_set_error (pattern, other->status);
302
	return _cairo_pattern_set_error (pattern, other->status);
Line 246... Line 321...
246
    } break;
321
    } break;
247
    case CAIRO_PATTERN_TYPE_LINEAR:
322
    case CAIRO_PATTERN_TYPE_LINEAR:
248
    case CAIRO_PATTERN_TYPE_RADIAL: {
323
    case CAIRO_PATTERN_TYPE_RADIAL: {
249
	cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern;
324
	cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern;
250
	cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other;
325
	cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other;
251
	cairo_status_t status;
-
 
Line 252... Line 326...
252
 
326
 
253
	if (other->type == CAIRO_PATTERN_TYPE_LINEAR) {
327
	if (other->type == CAIRO_PATTERN_TYPE_LINEAR) {
254
	    VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t)));
328
	    VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t)));
255
	} else {
329
	} else {
Line 259... Line 333...
259
	status = _cairo_gradient_pattern_init_copy (dst, src);
333
	status = _cairo_gradient_pattern_init_copy (dst, src);
260
	if (unlikely (status))
334
	if (unlikely (status))
261
	    return status;
335
	    return status;
Line 262... Line 336...
262
 
336
 
-
 
337
    } break;
-
 
338
    case CAIRO_PATTERN_TYPE_MESH: {
-
 
339
	cairo_mesh_pattern_t *dst = (cairo_mesh_pattern_t *) pattern;
-
 
340
	cairo_mesh_pattern_t *src = (cairo_mesh_pattern_t *) other;
-
 
341
 
-
 
342
	VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_mesh_pattern_t)));
-
 
343
 
-
 
344
	status = _cairo_mesh_pattern_init_copy (dst, src);
-
 
345
	if (unlikely (status))
-
 
346
	    return status;
-
 
347
 
-
 
348
    } break;
-
 
349
 
-
 
350
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE: {
-
 
351
	status = _cairo_raster_source_pattern_init_copy (pattern, other);
-
 
352
	if (unlikely (status))
-
 
353
	    return status;
263
    } break;
354
    } break;
Line 264... Line 355...
264
    }
355
    }
265
 
356
 
266
    /* The reference count and user_data array are unique to the copy. */
357
    /* The reference count and user_data array are unique to the copy. */
Line 291... Line 382...
291
	size = sizeof (cairo_linear_pattern_t);
382
	size = sizeof (cairo_linear_pattern_t);
292
	break;
383
	break;
293
    case CAIRO_PATTERN_TYPE_RADIAL:
384
    case CAIRO_PATTERN_TYPE_RADIAL:
294
	size = sizeof (cairo_radial_pattern_t);
385
	size = sizeof (cairo_radial_pattern_t);
295
	break;
386
	break;
-
 
387
    case CAIRO_PATTERN_TYPE_MESH:
-
 
388
	size = sizeof (cairo_mesh_pattern_t);
-
 
389
	break;
-
 
390
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
-
 
391
	size = sizeof (cairo_raster_source_pattern_t);
-
 
392
	break;
296
    }
393
    }
Line 297... Line 394...
297
 
394
 
Line 298... Line 395...
298
    memcpy (pattern, other, size);
395
    memcpy (pattern, other, size);
Line 322... Line 419...
322
 
419
 
Line 323... Line 420...
323
	surface_pattern->surface = _cairo_surface_snapshot (surface);
420
	surface_pattern->surface = _cairo_surface_snapshot (surface);
Line 324... Line 421...
324
 
421
 
-
 
422
	cairo_surface_destroy (surface);
325
	cairo_surface_destroy (surface);
423
 
326
 
-
 
Line 327... Line 424...
327
	if (surface_pattern->surface->status)
424
	status = surface_pattern->surface->status;
328
	    return surface_pattern->surface->status;
425
    } else if (pattern->type == CAIRO_PATTERN_TYPE_RASTER_SOURCE)
Line 329... Line 426...
329
    }
426
	status = _cairo_raster_source_pattern_snapshot (pattern);
330
 
427
 
331
    return CAIRO_STATUS_SUCCESS;
428
    return status;
Line 351... Line 448...
351
	    (cairo_gradient_pattern_t *) pattern;
448
	    (cairo_gradient_pattern_t *) pattern;
Line 352... Line 449...
352
 
449
 
353
	if (gradient->stops && gradient->stops != gradient->stops_embedded)
450
	if (gradient->stops && gradient->stops != gradient->stops_embedded)
354
	    free (gradient->stops);
451
	    free (gradient->stops);
-
 
452
    } break;
-
 
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);
355
    } break;
461
	break;
Line 356... Line 462...
356
    }
462
    }
357
 
463
 
358
#if HAVE_VALGRIND
464
#if HAVE_VALGRIND
Line 367... Line 473...
367
	VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_linear_pattern_t));
473
	VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_linear_pattern_t));
368
	break;
474
	break;
369
    case CAIRO_PATTERN_TYPE_RADIAL:
475
    case CAIRO_PATTERN_TYPE_RADIAL:
370
	VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_radial_pattern_t));
476
	VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_radial_pattern_t));
371
	break;
477
	break;
-
 
478
    case CAIRO_PATTERN_TYPE_MESH:
-
 
479
	VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_mesh_pattern_t));
-
 
480
	break;
-
 
481
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
-
 
482
	break;
372
    }
483
    }
373
#endif
484
#endif
374
}
485
}
Line 375... Line 486...
375
 
486
 
Line 394... Line 505...
394
	pattern = malloc (sizeof (cairo_linear_pattern_t));
505
	pattern = malloc (sizeof (cairo_linear_pattern_t));
395
	break;
506
	break;
396
    case CAIRO_PATTERN_TYPE_RADIAL:
507
    case CAIRO_PATTERN_TYPE_RADIAL:
397
	pattern = malloc (sizeof (cairo_radial_pattern_t));
508
	pattern = malloc (sizeof (cairo_radial_pattern_t));
398
	break;
509
	break;
-
 
510
    case CAIRO_PATTERN_TYPE_MESH:
-
 
511
	pattern = malloc (sizeof (cairo_mesh_pattern_t));
-
 
512
	break;
-
 
513
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
-
 
514
	pattern = malloc (sizeof (cairo_raster_source_pattern_t));
-
 
515
	break;
399
    default:
516
    default:
400
	ASSERT_NOT_REACHED;
517
	ASSERT_NOT_REACHED;
401
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
518
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
402
    }
519
    }
403
    if (unlikely (pattern == NULL))
520
    if (unlikely (pattern == NULL))
Line 412... Line 529...
412
    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
529
    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
413
    *pattern_out = pattern;
530
    *pattern_out = pattern;
414
    return CAIRO_STATUS_SUCCESS;
531
    return CAIRO_STATUS_SUCCESS;
415
}
532
}
Line 416... Line -...
416
 
-
 
417
 
533
 
418
void
534
void
419
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
535
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
420
			   const cairo_color_t	 *color)
536
			   const cairo_color_t	 *color)
421
{
537
{
Line 448... Line 564...
448
    pattern->n_stops    = 0;
564
    pattern->n_stops    = 0;
449
    pattern->stops_size = 0;
565
    pattern->stops_size = 0;
450
    pattern->stops      = NULL;
566
    pattern->stops      = NULL;
451
}
567
}
Line 452... Line 568...
452
 
568
 
453
void
569
static void
454
_cairo_pattern_init_linear (cairo_linear_pattern_t *pattern,
570
_cairo_pattern_init_linear (cairo_linear_pattern_t *pattern,
455
			    double x0, double y0, double x1, double y1)
571
			    double x0, double y0, double x1, double y1)
456
{
572
{
Line 457... Line 573...
457
    _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_LINEAR);
573
    _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_LINEAR);
458
 
574
 
459
    pattern->p1.x = _cairo_fixed_from_double (x0);
575
    pattern->pd1.x = x0;
460
    pattern->p1.y = _cairo_fixed_from_double (y0);
576
    pattern->pd1.y = y0;
461
    pattern->p2.x = _cairo_fixed_from_double (x1);
577
    pattern->pd2.x = x1;
Line 462... Line 578...
462
    pattern->p2.y = _cairo_fixed_from_double (y1);
578
    pattern->pd2.y = y1;
463
}
579
}
464
 
580
 
465
void
581
static void
466
_cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
582
_cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
467
			    double cx0, double cy0, double radius0,
583
			    double cx0, double cy0, double radius0,
Line 468... Line 584...
468
			    double cx1, double cy1, double radius1)
584
			    double cx1, double cy1, double radius1)
469
{
585
{
470
    _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL);
586
    _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL);
471
 
587
 
472
    pattern->c1.x = _cairo_fixed_from_double (cx0);
588
    pattern->cd1.center.x = cx0;
473
    pattern->c1.y = _cairo_fixed_from_double (cy0);
589
    pattern->cd1.center.y = cy0;
474
    pattern->r1   = _cairo_fixed_from_double (fabs (radius0));
590
    pattern->cd1.radius   = fabs (radius0);
Line 475... Line 591...
475
    pattern->c2.x = _cairo_fixed_from_double (cx1);
591
    pattern->cd2.center.x = cx1;
476
    pattern->c2.y = _cairo_fixed_from_double (cy1);
592
    pattern->cd2.center.y = cy1;
477
    pattern->r2   = _cairo_fixed_from_double (fabs (radius1));
593
    pattern->cd2.radius   = fabs (radius1);
Line 533... Line 649...
533
 * finished with it.
649
 * finished with it.
534
 *
650
 *
535
 * This function will always return a valid pointer, but if an error
651
 * This function will always return a valid pointer, but if an error
536
 * occurred the pattern status will be set to an error.  To inspect
652
 * occurred the pattern status will be set to an error.  To inspect
537
 * the status of a pattern use cairo_pattern_status().
653
 * the status of a pattern use cairo_pattern_status().
-
 
654
 *
-
 
655
 * Since: 1.0
538
 **/
656
 **/
539
cairo_pattern_t *
657
cairo_pattern_t *
540
cairo_pattern_create_rgb (double red, double green, double blue)
658
cairo_pattern_create_rgb (double red, double green, double blue)
541
{
659
{
542
    cairo_color_t color;
-
 
543
 
-
 
544
    red   = _cairo_restrict_value (red,   0.0, 1.0);
-
 
545
    green = _cairo_restrict_value (green, 0.0, 1.0);
-
 
546
    blue  = _cairo_restrict_value (blue,  0.0, 1.0);
-
 
547
 
-
 
548
    _cairo_color_init_rgb (&color, red, green, blue);
-
 
549
 
-
 
550
    CAIRO_MUTEX_INITIALIZE ();
-
 
551
 
-
 
552
    return _cairo_pattern_create_solid (&color);
660
    return cairo_pattern_create_rgba (red, green, blue, 1.0);
553
}
661
}
554
slim_hidden_def (cairo_pattern_create_rgb);
662
slim_hidden_def (cairo_pattern_create_rgb);
Line 555... Line 663...
555
 
663
 
556
/**
664
/**
Line 571... Line 679...
571
 * finished with it.
679
 * finished with it.
572
 *
680
 *
573
 * This function will always return a valid pointer, but if an error
681
 * This function will always return a valid pointer, but if an error
574
 * occurred the pattern status will be set to an error.  To inspect
682
 * occurred the pattern status will be set to an error.  To inspect
575
 * the status of a pattern use cairo_pattern_status().
683
 * the status of a pattern use cairo_pattern_status().
-
 
684
 *
-
 
685
 * Since: 1.0
576
 **/
686
 **/
577
cairo_pattern_t *
687
cairo_pattern_t *
578
cairo_pattern_create_rgba (double red, double green, double blue,
688
cairo_pattern_create_rgba (double red, double green, double blue,
579
			   double alpha)
689
			   double alpha)
580
{
690
{
Line 605... Line 715...
605
 * finished with it.
715
 * finished with it.
606
 *
716
 *
607
 * This function will always return a valid pointer, but if an error
717
 * This function will always return a valid pointer, but if an error
608
 * occurred the pattern status will be set to an error.  To inspect
718
 * occurred the pattern status will be set to an error.  To inspect
609
 * the status of a pattern use cairo_pattern_status().
719
 * the status of a pattern use cairo_pattern_status().
-
 
720
 *
-
 
721
 * Since: 1.0
610
 **/
722
 **/
611
cairo_pattern_t *
723
cairo_pattern_t *
612
cairo_pattern_create_for_surface (cairo_surface_t *surface)
724
cairo_pattern_create_for_surface (cairo_surface_t *surface)
613
{
725
{
614
    cairo_surface_pattern_t *pattern;
726
    cairo_surface_pattern_t *pattern;
Line 663... Line 775...
663
 * finished with it.
775
 * finished with it.
664
 *
776
 *
665
 * This function will always return a valid pointer, but if an error
777
 * This function will always return a valid pointer, but if an error
666
 * occurred the pattern status will be set to an error.  To inspect
778
 * occurred the pattern status will be set to an error.  To inspect
667
 * the status of a pattern use cairo_pattern_status().
779
 * the status of a pattern use cairo_pattern_status().
-
 
780
 *
-
 
781
 * Since: 1.0
668
 **/
782
 **/
669
cairo_pattern_t *
783
cairo_pattern_t *
670
cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
784
cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
671
{
785
{
672
    cairo_linear_pattern_t *pattern;
786
    cairo_linear_pattern_t *pattern;
Line 714... Line 828...
714
 * finished with it.
828
 * finished with it.
715
 *
829
 *
716
 * This function will always return a valid pointer, but if an error
830
 * This function will always return a valid pointer, but if an error
717
 * occurred the pattern status will be set to an error.  To inspect
831
 * occurred the pattern status will be set to an error.  To inspect
718
 * the status of a pattern use cairo_pattern_status().
832
 * the status of a pattern use cairo_pattern_status().
-
 
833
 *
-
 
834
 * Since: 1.0
719
 **/
835
 **/
720
cairo_pattern_t *
836
cairo_pattern_t *
721
cairo_pattern_create_radial (double cx0, double cy0, double radius0,
837
cairo_pattern_create_radial (double cx0, double cy0, double radius0,
722
			     double cx1, double cy1, double radius1)
838
			     double cx1, double cy1, double radius1)
723
{
839
{
Line 739... Line 855...
739
    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
855
    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
Line 740... Line 856...
740
 
856
 
741
    return &pattern->base.base;
857
    return &pattern->base.base;
Line -... Line 858...
-
 
858
}
-
 
859
 
-
 
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
 
-
 
867
/**
-
 
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;
742
}
1038
}
743
 
1039
 
744
/**
1040
/**
745
 * cairo_pattern_reference:
1041
 * cairo_pattern_reference:
746
 * @pattern: a #cairo_pattern_t
1042
 * @pattern: a #cairo_pattern_t
Line 751... Line 1047...
751
 *
1047
 *
752
 * The number of references to a #cairo_pattern_t can be get using
1048
 * The number of references to a #cairo_pattern_t can be get using
753
 * cairo_pattern_get_reference_count().
1049
 * cairo_pattern_get_reference_count().
754
 *
1050
 *
755
 * Return value: the referenced #cairo_pattern_t.
1051
 * Return value: the referenced #cairo_pattern_t.
-
 
1052
 *
-
 
1053
 * Since: 1.0
756
 **/
1054
 **/
757
cairo_pattern_t *
1055
cairo_pattern_t *
758
cairo_pattern_reference (cairo_pattern_t *pattern)
1056
cairo_pattern_reference (cairo_pattern_t *pattern)
759
{
1057
{
760
    if (pattern == NULL ||
1058
    if (pattern == NULL ||
Line 791... Line 1089...
791
 * @pattern: a #cairo_pattern_t
1089
 * @pattern: a #cairo_pattern_t
792
 *
1090
 *
793
 * Checks whether an error has previously occurred for this
1091
 * Checks whether an error has previously occurred for this
794
 * pattern.
1092
 * pattern.
795
 *
1093
 *
796
 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NO_MEMORY, or
1094
 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NO_MEMORY,
-
 
1095
 * %CAIRO_STATUS_INVALID_MATRIX, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH,
797
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
1096
 * or %CAIRO_STATUS_INVALID_MESH_CONSTRUCTION.
-
 
1097
 *
-
 
1098
 * Since: 1.0
798
 **/
1099
 **/
799
cairo_status_t
1100
cairo_status_t
800
cairo_pattern_status (cairo_pattern_t *pattern)
1101
cairo_pattern_status (cairo_pattern_t *pattern)
801
{
1102
{
802
    return pattern->status;
1103
    return pattern->status;
Line 807... Line 1108...
807
 * @pattern: a #cairo_pattern_t
1108
 * @pattern: a #cairo_pattern_t
808
 *
1109
 *
809
 * Decreases the reference count on @pattern by one. If the result is
1110
 * Decreases the reference count on @pattern by one. If the result is
810
 * zero, then @pattern and all associated resources are freed.  See
1111
 * zero, then @pattern and all associated resources are freed.  See
811
 * cairo_pattern_reference().
1112
 * cairo_pattern_reference().
-
 
1113
 *
-
 
1114
 * Since: 1.0
812
 **/
1115
 **/
813
void
1116
void
814
cairo_pattern_destroy (cairo_pattern_t *pattern)
1117
cairo_pattern_destroy (cairo_pattern_t *pattern)
815
{
1118
{
816
    cairo_pattern_type_t type;
1119
    cairo_pattern_type_t type;
Line 826... Line 1129...
826
 
1129
 
827
    type = pattern->type;
1130
    type = pattern->type;
Line 828... Line 1131...
828
    _cairo_pattern_fini (pattern);
1131
    _cairo_pattern_fini (pattern);
-
 
1132
 
829
 
1133
    /* maintain a small cache of freed patterns */
-
 
1134
    if (type < ARRAY_LENGTH (freed_pattern_pool))
-
 
1135
	_freed_pool_put (&freed_pattern_pool[type], pattern);
830
    /* maintain a small cache of freed patterns */
1136
    else
831
    _freed_pool_put (&freed_pattern_pool[type], pattern);
1137
	free (pattern);
Line 832... Line 1138...
832
}
1138
}
833
slim_hidden_def (cairo_pattern_destroy);
1139
slim_hidden_def (cairo_pattern_destroy);
Line 904... Line 1210...
904
 
1210
 
905
    return _cairo_user_data_array_set_data (&pattern->user_data,
1211
    return _cairo_user_data_array_set_data (&pattern->user_data,
906
					    key, user_data, destroy);
1212
					    key, user_data, destroy);
Line -... Line 1213...
-
 
1213
}
-
 
1214
 
-
 
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;
907
}
1658
}
908
 
1659
 
909
/* make room for at least one more color stop */
1660
/* make room for at least one more color stop */
910
static cairo_status_t
1661
static cairo_status_t
911
_cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
1662
_cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
Line 946... Line 1697...
946
 
1697
 
947
    return CAIRO_STATUS_SUCCESS;
1698
    return CAIRO_STATUS_SUCCESS;
Line 948... Line 1699...
948
}
1699
}
-
 
1700
 
-
 
1701
static void
-
 
1702
_cairo_mesh_pattern_set_corner_color (cairo_mesh_pattern_t *mesh,
-
 
1703
				      unsigned int     corner_num,
-
 
1704
				      double red, double green, double blue,
-
 
1705
				      double alpha)
-
 
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);
949
 
1820
 
950
static void
1821
static void
951
_cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
1822
_cairo_pattern_add_color_stop (cairo_gradient_pattern_t	*pattern,
952
			       double			 offset,
1823
			       double			 offset,
953
			       double			 red,
1824
			       double			 red,
Line 1018... Line 1889...
1018
 *
1889
 *
1019
 *
1890
 *
1020
 * Note: If the pattern is not a gradient pattern, (eg. a linear or
1891
 * Note: If the pattern is not a gradient pattern, (eg. a linear or
1021
 * radial pattern), then the pattern will be put into an error status
1892
 * radial pattern), then the pattern will be put into an error status
1022
 * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
1893
 * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
-
 
1894
 *
-
 
1895
 * Since: 1.0
1023
 **/
1896
 **/
1024
void
1897
void
1025
cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
1898
cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
1026
				  double	   offset,
1899
				  double	   offset,
1027
				  double	   red,
1900
				  double	   red,
1028
				  double	   green,
1901
				  double	   green,
1029
				  double	   blue)
1902
				  double	   blue)
1030
{
1903
{
1031
    if (pattern->status)
-
 
1032
	return;
-
 
1033
 
-
 
1034
    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
-
 
1035
	pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
-
 
1036
    {
-
 
1037
	_cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
-
 
1038
	return;
-
 
1039
    }
-
 
1040
 
-
 
1041
    offset = _cairo_restrict_value (offset, 0.0, 1.0);
-
 
1042
    red    = _cairo_restrict_value (red,    0.0, 1.0);
-
 
1043
    green  = _cairo_restrict_value (green,  0.0, 1.0);
-
 
1044
    blue   = _cairo_restrict_value (blue,   0.0, 1.0);
-
 
1045
 
-
 
1046
    _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
1904
    cairo_pattern_add_color_stop_rgba (pattern, offset, red, green, blue, 1.0);
1047
				   offset, red, green, blue, 1.0);
-
 
1048
}
1905
}
Line 1049... Line 1906...
1049
 
1906
 
1050
/**
1907
/**
1051
 * cairo_pattern_add_color_stop_rgba:
1908
 * cairo_pattern_add_color_stop_rgba:
Line 1071... Line 1928...
1071
 * transitions instead of the typical blend.
1928
 * transitions instead of the typical blend.
1072
 *
1929
 *
1073
 * Note: If the pattern is not a gradient pattern, (eg. a linear or
1930
 * Note: If the pattern is not a gradient pattern, (eg. a linear or
1074
 * radial pattern), then the pattern will be put into an error status
1931
 * radial pattern), then the pattern will be put into an error status
1075
 * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
1932
 * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
-
 
1933
 *
-
 
1934
 * Since: 1.0
1076
 */
1935
 **/
1077
void
1936
void
1078
cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
1937
cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
1079
				   double	   offset,
1938
				   double	   offset,
1080
				   double	   red,
1939
				   double	   red,
1081
				   double	   green,
1940
				   double	   green,
Line 1099... Line 1958...
1099
    alpha  = _cairo_restrict_value (alpha,  0.0, 1.0);
1958
    alpha  = _cairo_restrict_value (alpha,  0.0, 1.0);
Line 1100... Line 1959...
1100
 
1959
 
1101
    _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
1960
    _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
1102
				   offset, red, green, blue, alpha);
1961
				   offset, red, green, blue, alpha);
-
 
1962
}
Line 1103... Line 1963...
1103
}
1963
slim_hidden_def (cairo_pattern_add_color_stop_rgba);
1104
 
1964
 
1105
/**
1965
/**
1106
 * cairo_pattern_set_matrix:
1966
 * cairo_pattern_set_matrix:
Line 1131... Line 1991...
1131
 * Meanwhile, using values of 2.0 rather than 0.5 in the code above
1991
 * Meanwhile, using values of 2.0 rather than 0.5 in the code above
1132
 * would cause the pattern to appear at half of its default size.
1992
 * would cause the pattern to appear at half of its default size.
1133
 *
1993
 *
1134
 * Also, please note the discussion of the user-space locking
1994
 * Also, please note the discussion of the user-space locking
1135
 * semantics of cairo_set_source().
1995
 * semantics of cairo_set_source().
-
 
1996
 *
-
 
1997
 * Since: 1.0
1136
 **/
1998
 **/
1137
void
1999
void
1138
cairo_pattern_set_matrix (cairo_pattern_t      *pattern,
2000
cairo_pattern_set_matrix (cairo_pattern_t      *pattern,
1139
			  const cairo_matrix_t *matrix)
2001
			  const cairo_matrix_t *matrix)
1140
{
2002
{
Line 1146... Line 2008...
1146
 
2008
 
1147
    if (memcmp (&pattern->matrix, matrix, sizeof (cairo_matrix_t)) == 0)
2009
    if (memcmp (&pattern->matrix, matrix, sizeof (cairo_matrix_t)) == 0)
Line 1148... Line 2010...
1148
	return;
2010
	return;
-
 
2011
 
Line 1149... Line 2012...
1149
 
2012
    pattern->matrix = *matrix;
1150
    pattern->matrix = *matrix;
2013
    _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_MATRIX);
1151
 
2014
 
1152
    inverse = *matrix;
2015
    inverse = *matrix;
Line 1160... Line 2023...
1160
 * cairo_pattern_get_matrix:
2023
 * cairo_pattern_get_matrix:
1161
 * @pattern: a #cairo_pattern_t
2024
 * @pattern: a #cairo_pattern_t
1162
 * @matrix: return value for the matrix
2025
 * @matrix: return value for the matrix
1163
 *
2026
 *
1164
 * Stores the pattern's transformation matrix into @matrix.
2027
 * Stores the pattern's transformation matrix into @matrix.
-
 
2028
 *
-
 
2029
 * Since: 1.0
1165
 **/
2030
 **/
1166
void
2031
void
1167
cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
2032
cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
1168
{
2033
{
1169
    *matrix = pattern->matrix;
2034
    *matrix = pattern->matrix;
Line 1186... Line 2051...
1186
 *
2051
 *
1187
 * 
2052
 * 
1188
 * cairo_set_source_surface (cr, image, x, y);
2053
 * cairo_set_source_surface (cr, image, x, y);
1189
 * cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
2054
 * cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
1190
 * 
2055
 * 
-
 
2056
 *
-
 
2057
 * Since: 1.0
1191
 **/
2058
 **/
1192
void
2059
void
1193
cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
2060
cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
1194
{
2061
{
1195
    if (pattern->status)
2062
    if (pattern->status)
1196
	return;
2063
	return;
Line 1197... Line 2064...
1197
 
2064
 
-
 
2065
    pattern->filter = filter;
1198
    pattern->filter = filter;
2066
    _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_FILTER);
Line 1199... Line 2067...
1199
}
2067
}
1200
 
2068
 
1201
/**
2069
/**
1202
 * cairo_pattern_get_filter:
2070
 * cairo_pattern_get_filter:
1203
 * @pattern: a #cairo_pattern_t
2071
 * @pattern: a #cairo_pattern_t
1204
 *
2072
 *
1205
 * Gets the current filter for a pattern.  See #cairo_filter_t
2073
 * Gets the current filter for a pattern.  See #cairo_filter_t
1206
 * for details on each filter.
2074
 * for details on each filter.
-
 
2075
 *
-
 
2076
 * Return value: the current filter used for resizing the pattern.
1207
 *
2077
 *
1208
 * Return value: the current filter used for resizing the pattern.
2078
 * Since: 1.0
1209
 **/
2079
 **/
1210
cairo_filter_t
2080
cairo_filter_t
1211
cairo_pattern_get_filter (cairo_pattern_t *pattern)
2081
cairo_pattern_get_filter (cairo_pattern_t *pattern)
Line 1223... Line 2093...
1223
 * See #cairo_extend_t for details on the semantics of each extend
2093
 * See #cairo_extend_t for details on the semantics of each extend
1224
 * strategy.
2094
 * strategy.
1225
 *
2095
 *
1226
 * The default extend mode is %CAIRO_EXTEND_NONE for surface patterns
2096
 * The default extend mode is %CAIRO_EXTEND_NONE for surface patterns
1227
 * and %CAIRO_EXTEND_PAD for gradient patterns.
2097
 * and %CAIRO_EXTEND_PAD for gradient patterns.
-
 
2098
 *
-
 
2099
 * Since: 1.0
1228
 **/
2100
 **/
1229
void
2101
void
1230
cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
2102
cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
1231
{
2103
{
1232
    if (pattern->status)
2104
    if (pattern->status)
1233
	return;
2105
	return;
Line 1234... Line 2106...
1234
 
2106
 
-
 
2107
    pattern->extend = extend;
1235
    pattern->extend = extend;
2108
    _cairo_pattern_notify_observers (pattern, CAIRO_PATTERN_NOTIFY_EXTEND);
Line 1236... Line 2109...
1236
}
2109
}
1237
 
2110
 
1238
/**
2111
/**
Line 1242... Line 2115...
1242
 * Gets the current extend mode for a pattern.  See #cairo_extend_t
2115
 * Gets the current extend mode for a pattern.  See #cairo_extend_t
1243
 * for details on the semantics of each extend strategy.
2116
 * for details on the semantics of each extend strategy.
1244
 *
2117
 *
1245
 * Return value: the current extend strategy used for drawing the
2118
 * Return value: the current extend strategy used for drawing the
1246
 * pattern.
2119
 * pattern.
-
 
2120
 *
-
 
2121
 * Since: 1.0
1247
 **/
2122
 **/
1248
cairo_extend_t
2123
cairo_extend_t
1249
cairo_pattern_get_extend (cairo_pattern_t *pattern)
2124
cairo_pattern_get_extend (cairo_pattern_t *pattern)
1250
{
2125
{
1251
    return pattern->extend;
2126
    return pattern->extend;
Line 1260... Line 2135...
1260
	return;
2135
	return;
Line 1261... Line 2136...
1261
 
2136
 
1262
    cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
2137
    cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
Line 1263... Line 2138...
1263
}
2138
}
1264
 
2139
 
1265
static void
-
 
1266
_cairo_linear_pattern_classify (cairo_linear_pattern_t *pattern,
-
 
1267
				double		       offset_x,
-
 
1268
				double		       offset_y,
-
 
1269
				int		       width,
-
 
1270
				int		       height,
-
 
1271
				cairo_bool_t           *is_horizontal,
2140
static cairo_bool_t
1272
				cairo_bool_t           *is_vertical)
-
 
1273
{
-
 
1274
    cairo_point_double_t point0, point1;
-
 
1275
    double a, b, c, d, tx, ty;
-
 
1276
    double scale, start, dx, dy;
-
 
1277
    cairo_fixed_t factors[3];
-
 
1278
    int i;
-
 
1279
 
2141
_linear_pattern_is_degenerate (const cairo_linear_pattern_t *linear)
1280
    /* To classify a pattern as horizontal or vertical, we first
-
 
1281
     * compute the (fixed point) factors at the corners of the
-
 
1282
     * pattern. We actually only need 3/4 corners, so we skip the
-
 
1283
     * fourth.
-
 
1284
     */
-
 
1285
    point0.x = _cairo_fixed_to_double (pattern->p1.x);
-
 
1286
    point0.y = _cairo_fixed_to_double (pattern->p1.y);
-
 
1287
    point1.x = _cairo_fixed_to_double (pattern->p2.x);
-
 
1288
    point1.y = _cairo_fixed_to_double (pattern->p2.y);
-
 
1289
 
-
 
1290
    _cairo_matrix_get_affine (&pattern->base.base.matrix,
-
 
1291
			      &a, &b, &c, &d, &tx, &ty);
-
 
1292
 
-
 
1293
    dx = point1.x - point0.x;
-
 
1294
    dy = point1.y - point0.y;
-
 
1295
    scale = dx * dx + dy * dy;
-
 
1296
    scale = (scale) ? 1.0 / scale : 1.0;
2142
{
1297
 
-
 
1298
    start = dx * point0.x + dy * point0.y;
-
 
1299
 
-
 
1300
    for (i = 0; i < 3; i++) {
-
 
1301
	double qx_device = (i % 2) * (width - 1) + offset_x;
-
 
1302
	double qy_device = (i / 2) * (height - 1) + offset_y;
-
 
1303
 
-
 
1304
	/* transform fragment into pattern space */
-
 
1305
	double qx = a * qx_device + c * qy_device + tx;
-
 
1306
	double qy = b * qx_device + d * qy_device + ty;
-
 
1307
 
2143
    return fabs (linear->pd1.x - linear->pd2.x) < DBL_EPSILON &&
Line -... Line 2144...
-
 
2144
	   fabs (linear->pd1.y - linear->pd2.y) < DBL_EPSILON;
-
 
2145
}
-
 
2146
 
1308
	factors[i] = _cairo_fixed_from_double (((dx * qx + dy * qy) - start) * scale);
2147
static cairo_bool_t
1309
    }
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
     *
1310
 
2154
     * 1) The radii are both very small:
1311
    /* We consider a pattern to be vertical if the fixed point factor
2155
     *      |dr| < DBL_EPSILON && min (r0, r1) < DBL_EPSILON
-
 
2156
     *
-
 
2157
     * 2) The two circles have about the same radius and are very
1312
     * at the two upper corners is the same. We could accept a small
2158
     *    close to each other (approximately a cylinder gradient that
1313
     * change, but determining what change is acceptable would require
2159
     *    doesn't move with the parameter):
-
 
2160
     *      |dr| < DBL_EPSILON && max (|dx|, |dy|) < 2 * DBL_EPSILON
1314
     * sorting the stops in the pattern and looking at the differences.
2161
     *
Line -... Line 2162...
-
 
2162
     * These checks are consistent with the assumptions used in
-
 
2163
     * _cairo_radial_pattern_box_to_parameter ().
1315
     *
2164
     */
1316
     * Horizontal works the same way with the two left corners.
2165
 
1317
     */
2166
    return fabs (radial->cd1.radius - radial->cd2.radius) < DBL_EPSILON &&
Line 1318... Line 2167...
1318
 
2167
	(MIN (radial->cd1.radius, radial->cd2.radius) < DBL_EPSILON ||
1319
    *is_vertical = factors[1] == factors[0];
2168
	 MAX (fabs (radial->cd1.center.x - radial->cd2.center.x),
1320
    *is_horizontal = factors[2] == factors[0];
2169
	      fabs (radial->cd1.center.y - radial->cd2.center.y)) < 2 * DBL_EPSILON);
1321
}
2170
}
1322
 
2171
 
1323
static cairo_int_status_t
-
 
1324
_cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pattern,
-
 
1325
					     cairo_surface_t	        *dst,
-
 
1326
					     int			x,
-
 
1327
					     int			y,
2172
static void
1328
					     unsigned int		width,
-
 
1329
					     unsigned int	        height,
-
 
1330
					     cairo_surface_t	        **out,
-
 
1331
					     cairo_surface_attributes_t *attr)
-
 
1332
{
-
 
1333
    cairo_image_surface_t *image;
-
 
1334
    pixman_image_t	  *pixman_image;
-
 
1335
    pixman_transform_t	  pixman_transform;
-
 
1336
    cairo_status_t	  status;
-
 
1337
    cairo_bool_t	  repeat = FALSE;
2173
_cairo_linear_pattern_box_to_parameter (const cairo_linear_pattern_t *linear,
1338
    cairo_bool_t          opaque = TRUE;
2174
					double x0, double y0,
1339
 
-
 
1340
    pixman_gradient_stop_t pixman_stops_static[2];
-
 
1341
    pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
-
 
1342
    unsigned int i;
-
 
Line 1343... Line -...
1343
    int clone_offset_x, clone_offset_y;
-
 
1344
    cairo_matrix_t matrix = pattern->base.matrix;
-
 
1345
 
-
 
1346
    if (CAIRO_INJECT_FAULT ())
-
 
1347
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2175
					double x1, double y1,
1348
 
-
 
Line -... Line 2176...
-
 
2176
					double range[2])
1349
    if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
2177
{
1350
	pixman_stops = _cairo_malloc_ab (pattern->n_stops,
2178
    double t0, tdx, tdy;
1351
					 sizeof(pixman_gradient_stop_t));
2179
    double p1x, p1y, pdx, pdy, invsqnorm;
1352
	if (unlikely (pixman_stops == NULL))
2180
 
-
 
2181
    assert (! _linear_pattern_is_degenerate (linear));
1353
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2182
 
-
 
2183
    /*
-
 
2184
     * Linear gradients are othrogonal to the line passing through
-
 
2185
     * their extremes. Because of convexity, the parameter range can
1354
    }
2186
     * be computed as the convex hull (one the real line) of the
1355
 
2187
     * parameter values of the 4 corners of the box.
1356
    for (i = 0; i < pattern->n_stops; i++) {
2188
     *
1357
	pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
2189
     * The parameter value t for a point (x,y) can be computed as:
Line 1358... Line 2190...
1358
	pixman_stops[i].color.red = pattern->stops[i].color.red_short;
2190
     *
1359
	pixman_stops[i].color.green = pattern->stops[i].color.green_short;
2191
     *   t = (p2 - p1) . (x,y) / |p2 - p1|^2
1360
	pixman_stops[i].color.blue = pattern->stops[i].color.blue_short;
2192
     *
1361
	pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
2193
     * t0  is the t value for the top left corner
-
 
2194
     * tdx is the difference between left and right corners
1362
	if (! CAIRO_ALPHA_SHORT_IS_OPAQUE (pixman_stops[i].color.alpha))
2195
     * tdy is the difference between top and bottom corners
-
 
2196
     */
Line 1363... Line 2197...
1363
	    opaque = FALSE;
2197
 
-
 
2198
    p1x = linear->pd1.x;
1364
    }
2199
    p1y = linear->pd1.y;
Line 1365... Line 2200...
1365
 
2200
    pdx = linear->pd2.x - p1x;
1366
    if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR)
2201
    pdy = linear->pd2.y - p1y;
1367
    {
-
 
1368
	cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern;
-
 
1369
	pixman_point_fixed_t p1, p2;
-
 
1370
	cairo_fixed_t xdim, ydim;
2202
    invsqnorm = 1.0 / (pdx * pdx + pdy * pdy);
1371
 
2203
    pdx *= invsqnorm;
1372
	xdim = linear->p2.x - linear->p1.x;
2204
    pdy *= invsqnorm;
1373
	ydim = linear->p2.y - linear->p1.y;
2205
 
1374
 
2206
    t0 = (x0 - p1x) * pdx + (y0 - p1y) * pdy;
1375
	/*
-
 
1376
	 * Transform the matrix to avoid overflow when converting between
-
 
1377
	 * cairo_fixed_t and pixman_fixed_t (without incurring performance
-
 
1378
	 * loss when the transformation is unnecessary).
-
 
1379
	 *
-
 
Line -... Line 2207...
-
 
2207
    tdx = (x1 - x0) * pdx;
1380
	 * XXX: Consider converting out-of-range co-ordinates and transforms.
2208
    tdy = (y1 - y0) * pdy;
1381
	 * Having a function to compute the required transformation to
2209
 
1382
	 * "normalize" a given bounding box would be generally useful -
2210
    /*
1383
	 * cf linear patterns, gradient patterns, surface patterns...
2211
     * Because of the linearity of the t value, tdx can simply be
Line 1384... Line -...
1384
	 */
-
 
1385
#define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
-
 
1386
	if (_cairo_fixed_integer_ceil (xdim) > PIXMAN_MAX_INT ||
-
 
1387
	    _cairo_fixed_integer_ceil (ydim) > PIXMAN_MAX_INT)
-
 
1388
	{
-
 
1389
	    double sf;
2212
     * added the t0 to move along the top edge. After this, range[0]
1390
 
2213
     * and range[1] represent the parameter range for the top edge, so
1391
	    if (xdim > ydim)
2214
     * extending it to include the whole box simply requires adding
1392
		sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (xdim);
-
 
1393
	    else
-
 
1394
		sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (ydim);
-
 
1395
 
-
 
1396
	    p1.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.x) * sf);
2215
     * tdy to the correct extreme.
1397
	    p1.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.y) * sf);
2216
     */
Line 1398... Line -...
1398
	    p2.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.x) * sf);
-
 
1399
	    p2.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.y) * sf);
2217
 
1400
 
2218
    range[0] = range[1] = t0;
1401
	    cairo_matrix_scale (&matrix, sf, sf);
-
 
1402
	}
-
 
1403
	else
2219
    if (tdx < 0)
1404
	{
2220
	range[0] += tdx;
1405
	    p1.x = _cairo_fixed_to_16_16 (linear->p1.x);
2221
    else
1406
	    p1.y = _cairo_fixed_to_16_16 (linear->p1.y);
2222
	range[1] += tdx;
1407
	    p2.x = _cairo_fixed_to_16_16 (linear->p2.x);
-
 
1408
	    p2.y = _cairo_fixed_to_16_16 (linear->p2.y);
2223
 
1409
	}
2224
    if (tdy < 0)
1410
 
2225
	range[0] += tdy;
Line 1411... Line -...
1411
	pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
-
 
1412
							    pixman_stops,
-
 
1413
							    pattern->n_stops);
-
 
1414
    }
-
 
1415
    else
-
 
1416
    {
-
 
1417
	cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
-
 
1418
	pixman_point_fixed_t c1, c2;
2226
    else
1419
	pixman_fixed_t r1, r2;
2227
	range[1] += tdy;
Line -... Line 2228...
-
 
2228
}
1420
 
2229
 
1421
	c1.x = _cairo_fixed_to_16_16 (radial->c1.x);
-
 
1422
	c1.y = _cairo_fixed_to_16_16 (radial->c1.y);
2230
static cairo_bool_t
1423
	r1   = _cairo_fixed_to_16_16 (radial->r1);
2231
_extend_range (double range[2], double value, cairo_bool_t valid)
1424
 
2232
{
1425
	c2.x = _cairo_fixed_to_16_16 (radial->c2.x);
-
 
-
 
2233
    if (!valid)
1426
	c2.y = _cairo_fixed_to_16_16 (radial->c2.y);
2234
	range[0] = range[1] = value;
1427
	r2   = _cairo_fixed_to_16_16 (radial->r2);
2235
    else if (value < range[0])
-
 
2236
	range[0] = value;
1428
 
2237
    else if (value > range[1])
1429
	pixman_image = pixman_image_create_radial_gradient (&c1, &c2,
2238
	range[1] = value;
1430
							    r1, r2,
2239
 
-
 
2240
    return TRUE;
-
 
2241
}
1431
							    pixman_stops,
2242
 
-
 
2243
/*
1432
							    pattern->n_stops);
2244
 * _cairo_radial_pattern_focus_is_inside:
1433
    }
-
 
1434
 
2245
 *
1435
    if (pixman_stops != pixman_stops_static)
-
 
1436
	free (pixman_stops);
-
 
1437
 
-
 
1438
    if (unlikely (pixman_image == NULL))
-
 
1439
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1440
 
-
 
1441
    if (_cairo_surface_is_image (dst))
-
 
Line -... Line 2246...
-
 
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
1442
    {
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
Line 1443... Line 2252...
1443
	image = (cairo_image_surface_t *)
2252
 * which case the circles are tangent in the focus point), it is not
1444
	    _cairo_image_surface_create_for_pixman_image (pixman_image,
2253
 * considered as contained in the circle, hence this function returns
Line -... Line 2254...
-
 
2254
 * %FALSE.
1445
							  PIXMAN_a8r8g8b8);
2255
 *
-
 
2256
 */
-
 
2257
cairo_bool_t
1446
	if (image->base.status)
2258
_cairo_radial_pattern_focus_is_inside (const cairo_radial_pattern_t *radial)
-
 
2259
{
-
 
2260
    double cx, cy, cr, dx, dy, dr;
-
 
2261
 
-
 
2262
    cx = radial->cd1.center.x;
-
 
2263
    cy = radial->cd1.center.y;
1447
	{
2264
    cr = radial->cd1.radius;
1448
	    pixman_image_unref (pixman_image);
2265
    dx = radial->cd2.center.x - cx;
1449
	    return image->base.status;
2266
    dy = radial->cd2.center.y - cy;
1450
	}
2267
    dr = radial->cd2.radius   - cr;
1451
 
2268
 
-
 
2269
    return dx*dx + dy*dy < dr*dr;
1452
	attr->x_offset = attr->y_offset = 0;
2270
}
-
 
2271
 
1453
	attr->matrix = matrix;
2272
static void
1454
	attr->extend = pattern->base.extend;
2273
_cairo_radial_pattern_box_to_parameter (const cairo_radial_pattern_t *radial,
1455
	attr->filter = CAIRO_FILTER_NEAREST;
2274
					double x0, double y0,
1456
	attr->has_component_alpha = pattern->base.has_component_alpha;
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;
1457
 
2281
    double mindr, minx, miny, maxx, maxy;
1458
	*out = &image->base;
2282
    cairo_bool_t valid;
-
 
2283
 
1459
 
2284
    assert (! _radial_pattern_is_degenerate (radial));
-
 
2285
    assert (x0 < x1);
-
 
2286
    assert (y0 < y1);
-
 
2287
 
-
 
2288
    tolerance = MAX (tolerance, DBL_EPSILON);
-
 
2289
 
1460
	return CAIRO_STATUS_SUCCESS;
2290
    range[0] = range[1] = 0;
-
 
2291
    valid = FALSE;
-
 
2292
 
-
 
2293
    x_focus = y_focus = 0; /* silence gcc */
-
 
2294
 
1461
    }
2295
    cx = radial->cd1.center.x;
1462
 
2296
    cy = radial->cd1.center.y;
-
 
2297
    cr = radial->cd1.radius;
-
 
2298
    dx = radial->cd2.center.x - cx;
1463
    if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
2299
    dy = radial->cd2.center.y - cy;
1464
	cairo_bool_t is_horizontal;
2300
    dr = radial->cd2.radius   - cr;
-
 
2301
 
1465
	cairo_bool_t is_vertical;
2302
    /* translate by -(cx, cy) to simplify computations */
1466
 
2303
    x0 -= cx;
-
 
2304
    y0 -= cy;
-
 
2305
    x1 -= cx;
1467
	_cairo_linear_pattern_classify ((cairo_linear_pattern_t *)pattern,
2306
    y1 -= cy;
Line -... Line 2307...
-
 
2307
 
-
 
2308
    /* enlarge boundaries slightly to avoid rounding problems in the
1468
					x, y, width, height,
2309
     * parameter range computation */
-
 
2310
    x0 -= DBL_EPSILON;
1469
					&is_horizontal, &is_vertical);
2311
    y0 -= DBL_EPSILON;
1470
	if (is_horizontal) {
2312
    x1 += DBL_EPSILON;
1471
	    height = 1;
2313
    y1 += DBL_EPSILON;
-
 
2314
 
1472
	    repeat = TRUE;
2315
    /* enlarge boundaries even more to avoid rounding problems when
1473
	}
2316
     * testing if a point belongs to the box */
Line -... Line 2317...
-
 
2317
    minx = x0 - DBL_EPSILON;
1474
	/* width-1 repeating patterns are quite slow with scan-line based
2318
    miny = y0 - DBL_EPSILON;
-
 
2319
    maxx = x1 + DBL_EPSILON;
1475
	 * compositing code, so we use a wider strip and spend some extra
2320
    maxy = y1 + DBL_EPSILON;
1476
	 * expense in computing the gradient. It's possible that for narrow
2321
 
-
 
2322
    /* we dont' allow negative radiuses, so we will be checking that
1477
	 * gradients we'd be better off using a 2 or 4 pixel strip; the
2323
     * t*dr >= mindr to consider t valid */
1478
	 * wider the gradient, the more it's worth spending extra time
2324
    mindr = -(cr + DBL_EPSILON);
1479
	 * computing a sample.
2325
 
-
 
2326
    /*
-
 
2327
     * After the previous transformations, the start circle is
Line 1480... Line 2328...
1480
	 */
2328
     * centered in the origin and has radius cr. A 1-unit change in
1481
	if (is_vertical && width > 8) {
2329
     * the t parameter corresponds to dx,dy,dr changes in the x,y,r of
1482
	    width = 8;
2330
     * the circle (center coordinates, radius).
1483
	    repeat = TRUE;
2331
     *
1484
	}
2332
     * To compute the minimum range needed to correctly draw the
-
 
2333
     * pattern, we start with an empty range and extend it to include
1485
    }
2334
     * the circles touching the bounding box or within it.
1486
 
2335
     */
1487
    if (! pixman_image_set_filter (pixman_image, PIXMAN_FILTER_BILINEAR,
-
 
1488
				   NULL, 0))
-
 
1489
    {
-
 
1490
	pixman_image_unref (pixman_image);
-
 
1491
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
 
1492
    }
-
 
1493
 
-
 
1494
    image = (cairo_image_surface_t *)
-
 
1495
	cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
-
 
1496
    if (image->base.status) {
-
 
1497
	pixman_image_unref (pixman_image);
-
 
1498
	return image->base.status;
-
 
1499
    }
-
 
1500
 
-
 
1501
    _cairo_matrix_to_pixman_matrix (&matrix, &pixman_transform,
2336
 
Line -... Line 2337...
-
 
2337
    /*
-
 
2338
     * Focus, the point where the circle has radius == 0.
-
 
2339
     *
1502
				    width/2., height/2.);
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
     */
1503
    if (!pixman_image_set_transform (pixman_image, &pixman_transform)) {
2346
    if (fabs (dr) >= DBL_EPSILON) {
1504
	cairo_surface_destroy (&image->base);
2347
	double t_focus;
1505
	pixman_image_unref (pixman_image);
2348
 
-
 
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)
-
 
2354
	{
-
 
2355
	    valid = _extend_range (range, t_focus, valid);
-
 
2356
	}
1506
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2357
    }
1507
    }
2358
 
-
 
2359
    /*
-
 
2360
     * Circles externally tangent to box edges.
-
 
2361
     *
-
 
2362
     * All circles have center in (dx, dy) * t
1508
 
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)
1509
    switch (pattern->base.extend) {
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
1510
    case CAIRO_EXTEND_NONE:
2380
     *   t = (x0 - cr) / (dx + dr)
-
 
2381
     *   y = dy * t
-
 
2382
     *
-
 
2383
     * in the code this becomes:
-
 
2384
     *
1511
	pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NONE);
2385
     *   t_edge = (num) / (den)
Line 1512... Line 2386...
1512
	break;
2386
     *   v = (delta) * t_edge
Line -... Line 2387...
-
 
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
1513
    case CAIRO_EXTEND_REPEAT:
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)				\
1514
	pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NORMAL);
2394
    if (fabs (den) >= DBL_EPSILON) {					\
-
 
2395
	double t_edge, v;						\
-
 
2396
									\
-
 
2397
	t_edge = (num) / (den);						\
1515
	break;
2398
	v = t_edge * (delta);						\
-
 
2399
	if (t_edge * dr >= mindr && (lower) <= v && v <= (upper))	\
-
 
2400
	    valid = _extend_range (range, t_edge, valid);		\
-
 
2401
    }
-
 
2402
 
-
 
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);
-
 
2408
 
-
 
2409
#undef T_EDGE
-
 
2410
 
1516
    case CAIRO_EXTEND_REFLECT:
2411
    /*
-
 
2412
     * Circles passing through a corner.
-
 
2413
     *
-
 
2414
     * A circle passing through the point (x,y) satisfies:
1517
	pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_REFLECT);
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;
-
 
2428
 
-
 
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:
Line -... Line 2438...
-
 
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
1518
	break;
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);
-
 
2462
 
-
 
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)
Line 1519... Line -...
1519
    case CAIRO_EXTEND_PAD:
-
 
1520
	pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_PAD);
2498
	 *   v = -((edge) * (delta) + cr*dr) / (den) - v_focus
1521
	break;
-
 
1522
    }
-
 
1523
 
-
 
1524
    pixman_image_composite32 (PIXMAN_OP_SRC,
-
 
Line -... Line 2499...
-
 
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);				\
1525
                              pixman_image,
2510
		d2 = u*u + v*v;					\
-
 
2511
		if (maxd2 < d2)					\
-
 
2512
		    maxd2 = d2;					\
-
 
2513
	    }							\
-
 
2514
	}
-
 
2515
 
-
 
2516
	maxd2 = 0;
1526
                              NULL,
2517
 
Line -... Line 2518...
-
 
2518
	/* degenerate circles (lines) passing through each edge */
1527
                              image->pixman_image,
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);
-
 
2523
 
-
 
2524
#undef T_EDGE
1528
                              x, y,
2525
 
-
 
2526
	/*
-
 
2527
	 * The limit circle can be transformed rigidly to the y=0 line
1529
                              0, 0,
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
1530
                              0, 0,
2531
	 *
1531
                              width, height);
2532
	 * y is the distance from the line, in our case tolerance;
1532
 
2533
	 * x is the distance along the line, i.e. sqrt(maxd2),
1533
    pixman_image_unref (pixman_image);
2534
	 * so:
1534
 
2535
	 *
1535
    _cairo_debug_check_image_surface_is_defined (&image->base);
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;
1536
 
2542
	    t_limit /= 2 * tolerance * dr;
-
 
2543
	    valid = _extend_range (range, t_limit, valid);
-
 
2544
	}
-
 
2545
 
-
 
2546
	/*
Line 1537... Line 2547...
1537
    status = _cairo_surface_clone_similar (dst, &image->base,
2547
	 * Nondegenerate, nonlimit circles passing through the corners.
1538
					   0, 0, width, height,
-
 
1539
					   &clone_offset_x,
-
 
1540
					   &clone_offset_y,
-
 
1541
					   out);
2548
	 *
1542
 
-
 
1543
    cairo_surface_destroy (&image->base);
-
 
1544
 
2549
	 * a == 0 && a*t^2 - 2*b*t + c == 0
Line 1545... Line -...
1545
    attr->x_offset = -x;
-
 
1546
    attr->y_offset = -y;
2550
	 *
Line -... Line 2551...
-
 
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;				\
1547
    cairo_matrix_init_identity (&attr->matrix);
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
	}
-
 
2569
 
-
 
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);
-
 
2575
 
-
 
2576
#undef T_CORNER
-
 
2577
    } else {
-
 
2578
	double inva, b, c, d;
-
 
2579
 
-
 
2580
	inva = 1 / a;
1548
    attr->extend = repeat ? CAIRO_EXTEND_REPEAT : CAIRO_EXTEND_NONE;
2581
 
Line 1549... Line 2582...
1549
    attr->filter = CAIRO_FILTER_NEAREST;
2582
	/*
1550
    attr->has_component_alpha = pattern->base.has_component_alpha;
2583
	 * Nondegenerate, nonlimit circles passing through the corners.
1551
 
-
 
1552
    return status;
-
 
1553
}
-
 
1554
 
-
 
1555
/* We maintain a small cache here, because we don't want to constantly
-
 
1556
 * recreate surfaces for simple solid colors. */
-
 
1557
#define MAX_SURFACE_CACHE_SIZE 16
-
 
1558
static struct {
-
 
1559
    struct _cairo_pattern_solid_surface_cache{
-
 
1560
	cairo_color_t    color;
-
 
1561
	cairo_surface_t *surface;
-
 
1562
    } cache[MAX_SURFACE_CACHE_SIZE];
2584
	 *
Line -... Line 2585...
-
 
2585
	 * a != 0 && a*t^2 - 2*b*t + c == 0
1563
    int size;
2586
	 *
-
 
2587
	 * t = (b +- sqrt (b*b - a*c)) / a
1564
} solid_surface_cache;
2588
	 *
1565
 
2589
	 * If the argument of sqrt() is negative, then no circle
1566
static cairo_bool_t
-
 
1567
_cairo_pattern_solid_surface_matches (
-
 
1568
	const struct _cairo_pattern_solid_surface_cache	    *cache,
2590
	 * passes through the corner.
-
 
2591
	 */
1569
	const cairo_solid_pattern_t			    *pattern,
2592
#define T_CORNER(x,y)							\
1570
	cairo_surface_t					    *dst)
2593
	b = (x) * dx + (y) * dy + cr * dr;				\
1571
{
2594
	c = (x) * (x) + (y) * (y) - cr * cr;				\
1572
    if (cairo_surface_get_content (cache->surface) != _cairo_color_get_content (&pattern->color))
2595
	d = b * b - a * c;						\
1573
	return FALSE;
2596
	if (d >= 0) {							\
1574
 
2597
	    double t_corner;						\
1575
    if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache->surface->ref_count) != 1)
-
 
1576
	return FALSE;
-
 
1577
 
2598
									\
1578
    if (! _cairo_surface_is_similar (cache->surface, dst))
2599
	    d = sqrt (d);						\
1579
	return FALSE;
-
 
1580
 
2600
	    t_corner = (b + d) * inva;					\
1581
    return TRUE;
2601
	    if (t_corner * dr >= mindr)					\
1582
}
-
 
1583
 
2602
		valid = _extend_range (range, t_corner, valid);		\
1584
static cairo_bool_t
2603
	    t_corner = (b - d) * inva;					\
1585
_cairo_pattern_solid_surface_matches_color (
2604
	    if (t_corner * dr >= mindr)					\
-
 
2605
		valid = _extend_range (range, t_corner, valid);		\
1586
	const struct _cairo_pattern_solid_surface_cache	    *cache,
2606
	}
1587
	const cairo_solid_pattern_t			    *pattern,
-
 
Line 1588... Line 2607...
1588
	cairo_surface_t					    *dst)
2607
 
1589
{
2608
	/* circles touching each corner */
1590
    if (! _cairo_color_equal (&cache->color, &pattern->color))
2609
	T_CORNER (x0, y0);
1591
	return FALSE;
2610
	T_CORNER (x0, y1);
1592
 
-
 
-
 
2611
	T_CORNER (x1, y0);
1593
    return _cairo_pattern_solid_surface_matches (cache, pattern, dst);
2612
	T_CORNER (x1, y1);
1594
}
2613
 
1595
 
2614
#undef T_CORNER
Line -... Line 2615...
-
 
2615
    }
1596
static cairo_int_status_t
2616
}
1597
_cairo_pattern_acquire_surface_for_solid (const cairo_solid_pattern_t	     *pattern,
2617
 
1598
					  cairo_surface_t	     *dst,
2618
/**
1599
					  int			     x,
2619
 * _cairo_gradient_pattern_box_to_parameter:
1600
					  int			     y,
2620
 *
-
 
2621
 * Compute a interpolation range sufficient to draw (within the given
1601
					  unsigned int		     width,
2622
 * tolerance) the gradient in the given box getting the same result as
1602
					  unsigned int		     height,
2623
 * using the (-inf, +inf) range.
1603
					  cairo_surface_t	     **out,
2624
 *
1604
					  cairo_surface_attributes_t *attribs)
2625
 * Assumes that the pattern is not degenerate. This can be guaranteed
1605
{
2626
 * by simplifying it to a solid clear if _cairo_pattern_is_clear or to
1606
    static int i;
2627
 * a solid color if _cairo_gradient_pattern_is_solid.
1607
 
2628
 *
1608
    cairo_surface_t *surface, *to_destroy = NULL;
-
 
1609
    cairo_status_t   status;
-
 
Line 1610... Line 2629...
1610
 
2629
 * The range isn't guaranteed to be minimal, but it tries to.
1611
    CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
-
 
1612
 
-
 
1613
    /* Check cache first */
-
 
1614
    if (i < solid_surface_cache.size &&
-
 
1615
	_cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i],
-
 
1616
						    pattern,
-
 
1617
						    dst))
-
 
Line 1618... Line 2630...
1618
    {
2630
 **/
1619
	goto DONE;
2631
void
1620
    }
2632
_cairo_gradient_pattern_box_to_parameter (const cairo_gradient_pattern_t *gradient,
1621
 
2633
					  double x0, double y0,
1622
    for (i = 0 ; i < solid_surface_cache.size; i++) {
2634
					  double x1, double y1,
1623
	if (_cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i],
2635
					  double tolerance,
1624
							pattern,
-
 
1625
							dst))
2636
					  double out_range[2])
-
 
2637
{
1626
	{
2638
    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
1627
	    goto DONE;
2639
	    gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
1628
	}
2640
 
Line 1629... Line -...
1629
    }
-
 
1630
 
-
 
1631
    /* Choose a surface to repaint/evict */
-
 
1632
    surface = NULL;
-
 
1633
    if (solid_surface_cache.size == MAX_SURFACE_CACHE_SIZE) {
2641
    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
1634
	i = rand () % MAX_SURFACE_CACHE_SIZE;
-
 
1635
	surface = solid_surface_cache.cache[i].surface;
-
 
1636
 
2642
	_cairo_linear_pattern_box_to_parameter ((cairo_linear_pattern_t *) gradient,
1637
	if (_cairo_pattern_solid_surface_matches (&solid_surface_cache.cache[i],
-
 
1638
						  pattern,
-
 
1639
						  dst))
-
 
1640
	{
-
 
1641
	    /* Reuse the surface instead of evicting */
-
 
1642
	    status = _cairo_surface_repaint_solid_pattern_surface (dst, surface, pattern);
-
 
1643
	    if (unlikely (status))
-
 
1644
		goto EVICT;
-
 
1645
 
-
 
1646
	    cairo_surface_reference (surface);
-
 
1647
	}
-
 
Line 1648... Line -...
1648
	else
-
 
1649
	{
-
 
1650
	  EVICT:
-
 
1651
	    surface = NULL;
-
 
1652
	}
-
 
1653
    }
-
 
Line 1654... Line -...
1654
 
-
 
1655
    if (surface == NULL) {
2643
						x0, y0, x1, y1, out_range);
1656
	/* Not cached, need to create new */
-
 
1657
	surface = _cairo_surface_create_solid_pattern_surface (dst, pattern);
2644
    } else {
1658
	if (surface == NULL) {
2645
	_cairo_radial_pattern_box_to_parameter ((cairo_radial_pattern_t *) gradient,
1659
	    status = CAIRO_INT_STATUS_UNSUPPORTED;
2646
						x0, y0, x1, y1, tolerance, out_range);
-
 
2647
    }
1660
	    goto UNLOCK;
2648
}
1661
	}
2649
 
-
 
2650
/**
1662
	if (unlikely (surface->status)) {
2651
 * _cairo_gradient_pattern_interpolate:
1663
	    status = surface->status;
2652
 *
1664
	    goto UNLOCK;
2653
 * Interpolate between the start and end objects of linear or radial
1665
	}
2654
 * gradients.  The interpolated object is stored in out_circle, with
1666
 
2655
 * the radius being zero in the linear gradient case.
-
 
2656
 **/
-
 
2657
void
-
 
2658
_cairo_gradient_pattern_interpolate (const cairo_gradient_pattern_t *gradient,
1667
	if (unlikely (! _cairo_surface_is_similar (surface, dst)))
2659
				     double			     t,
1668
	{
-
 
1669
	    /* In the rare event of a substitute surface being returned,
-
 
1670
	     * don't cache the fallback.
-
 
1671
	     */
-
 
1672
	    *out = surface;
-
 
1673
	    goto NOCACHE;
-
 
1674
	}
-
 
1675
    }
-
 
1676
 
-
 
1677
    if (i == solid_surface_cache.size)
-
 
1678
	solid_surface_cache.size++;
-
 
1679
 
-
 
1680
    to_destroy = solid_surface_cache.cache[i].surface;
-
 
1681
    solid_surface_cache.cache[i].surface = surface;
-
 
1682
    solid_surface_cache.cache[i].color   = pattern->color;
-
 
1683
 
-
 
1684
DONE:
2660
				     cairo_circle_double_t	    *out_circle)
1685
    *out = cairo_surface_reference (solid_surface_cache.cache[i].surface);
-
 
1686
 
-
 
1687
NOCACHE:
-
 
Line 1688... Line -...
1688
    attribs->x_offset = attribs->y_offset = 0;
-
 
1689
    cairo_matrix_init_identity (&attribs->matrix);
2661
{
1690
    attribs->extend = CAIRO_EXTEND_REPEAT;
2662
    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
1691
    attribs->filter = CAIRO_FILTER_NEAREST;
-
 
1692
    attribs->has_component_alpha = pattern->base.has_component_alpha;
-
 
1693
 
-
 
1694
    status = CAIRO_STATUS_SUCCESS;
-
 
Line 1695... Line -...
1695
 
-
 
1696
UNLOCK:
-
 
1697
    CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
2663
	    gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
1698
 
2664
 
1699
    if (to_destroy)
-
 
1700
      cairo_surface_destroy (to_destroy);
-
 
1701
 
-
 
Line -... Line 2665...
-
 
2665
#define lerp(a,b) (a)*(1-t) + (b)*t
-
 
2666
 
-
 
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);
1702
    return status;
2671
	out_circle->radius = 0;
1703
}
2672
    } else {
1704
 
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);
-
 
2677
    }
Line 1705... Line 2678...
1705
static void
2678
 
1706
_cairo_pattern_reset_solid_surface_cache (void)
-
 
1707
{
-
 
1708
    CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
-
 
1709
 
2679
#undef lerp
Line 1710... Line 2680...
1710
    /* remove surfaces starting from the end so that solid_surface_cache.cache
2680
}
1711
     * is always in a consistent state when we release the mutex. */
2681
 
-
 
2682
 
-
 
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.
1712
    while (solid_surface_cache.size) {
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
 **/
1713
	cairo_surface_t *surface;
2694
void
1714
 
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;
-
 
2701
 
Line 1715... Line 2702...
1715
	solid_surface_cache.size--;
2702
    assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
1716
	surface = solid_surface_cache.cache[solid_surface_cache.size].surface;
2703
	    gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
1717
	solid_surface_cache.cache[solid_surface_cache.size].surface = NULL;
2704
 
1718
 
2705
    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
1719
	/* release the lock to avoid the possibility of a recursive
2706
	cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
1720
	 * deadlock when the surface destroy closure gets called */
-
 
1721
	CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
-
 
1722
	cairo_surface_destroy (surface);
-
 
1723
	CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
-
 
1724
    }
-
 
1725
 
-
 
1726
    CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
-
 
1727
}
2707
 
Line 1728... Line 2708...
1728
 
2708
	out_circle[0].center = linear->pd1;
1729
static void
2709
	out_circle[0].radius = 0;
1730
_extents_to_linear_parameter (const cairo_linear_pattern_t *linear,
2710
	out_circle[1].center = linear->pd2;
Line 1784... Line 2764...
1784
    if (gradient->n_stops == 0 ||
2764
    if (gradient->n_stops == 0 ||
1785
	(gradient->base.extend == CAIRO_EXTEND_NONE &&
2765
	(gradient->base.extend == CAIRO_EXTEND_NONE &&
1786
	 gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
2766
	 gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
1787
	return TRUE;
2767
	return TRUE;
Line 1788... Line -...
1788
 
-
 
1789
    /* Check if the extents intersect the drawn part of the pattern. */
2768
 
1790
    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
2769
    if (gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL) {
1791
	if (gradient->base.extend == CAIRO_EXTEND_NONE) {
2770
	/* degenerate radial gradients are clear */
-
 
2771
	if (_radial_pattern_is_degenerate ((cairo_radial_pattern_t *) gradient))
-
 
2772
	    return TRUE;
1792
	    cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
2773
    } else if (gradient->base.extend == CAIRO_EXTEND_NONE) {
1793
	    /* EXTEND_NONE degenerate linear gradients are clear */
2774
	/* EXTEND_NONE degenerate linear gradients are clear */
1794
	    if (_linear_pattern_is_degenerate (linear))
2775
	if (_linear_pattern_is_degenerate ((cairo_linear_pattern_t *) gradient))
-
 
2776
	    return TRUE;
Line -... Line 2777...
-
 
2777
    }
1795
		return TRUE;
2778
 
-
 
2779
    /* Check if the extents intersect the drawn part of the pattern. */
-
 
2780
    if (extents != NULL &&
-
 
2781
	(gradient->base.extend == CAIRO_EXTEND_NONE ||
1796
 
2782
	 gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL))
-
 
2783
    {
1797
	    if (extents != NULL) {
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);
1798
		double t[2];
2793
 
-
 
2794
	if (gradient->base.extend == CAIRO_EXTEND_NONE &&
-
 
2795
	    (t[0] >= gradient->stops[gradient->n_stops - 1].offset ||
1799
		_extents_to_linear_parameter (linear, extents, t);
2796
	     t[1] <= gradient->stops[0].offset))
1800
		if ((t[0] <= 0.0 && t[1] <= 0.0) || (t[0] >= 1.0 && t[1] >= 1.0))
2797
	{
1801
		    return TRUE;
2798
		return TRUE;
1802
	    }
2799
	}
1803
	}
-
 
1804
    } else {
-
 
1805
	cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
-
 
1806
	/* degenerate radial gradients are clear */
2800
 
1807
	if (_radial_pattern_is_degenerate (radial))
-
 
1808
	    return TRUE;
2801
	if (t[0] == t[1])
Line 1809... Line 2802...
1809
	/* TODO: check actual intersection */
2802
	    return TRUE;
1810
    }
2803
    }
1811
 
2804
 
Line 1925... Line 2918...
1925
 
2918
 
1926
    _cairo_color_init_rgba (color, r * .5, g * .5, b * .5, a * .5);
2919
    _cairo_color_init_rgba (color, r * .5, g * .5, b * .5, a * .5);
Line 1927... Line 2920...
1927
}
2920
}
-
 
2921
 
-
 
2922
/**
-
 
2923
 * _cairo_pattern_alpha_range:
-
 
2924
 *
-
 
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
}
1928
 
3057
 
1929
/**
3058
/**
1930
 * _cairo_gradient_pattern_is_solid
3059
 * _cairo_gradient_pattern_is_solid:
1931
 *
3060
 *
1932
 * Convenience function to determine whether a gradient pattern is
3061
 * Convenience function to determine whether a gradient pattern is
1933
 * a solid color within the given extents. In this case the color
3062
 * a solid color within the given extents. In this case the color
Line 1964... Line 3093...
1964
	     */
3093
	     */
Line 1965... Line 3094...
1965
 
3094
 
1966
	    if (extents == NULL)
3095
	    if (extents == NULL)
Line 1967... Line 3096...
1967
		return FALSE;
3096
		return FALSE;
-
 
3097
 
-
 
3098
	    _cairo_linear_pattern_box_to_parameter (linear,
-
 
3099
						    extents->x,
-
 
3100
						    extents->y,
-
 
3101
						    extents->x + extents->width,
-
 
3102
						    extents->y + extents->height,
1968
 
3103
						    t);
1969
	    _extents_to_linear_parameter (linear, extents, t);
3104
 
1970
	    if (t[0] < 0.0 || t[1] > 1.0)
3105
	    if (t[0] < 0.0 || t[1] > 1.0)
1971
		return FALSE;
3106
		return FALSE;
1972
	}
3107
	}
Line 1985... Line 3120...
1985
			    gradient->stops[0].color.alpha);
3120
			    gradient->stops[0].color.alpha);
Line 1986... Line 3121...
1986
 
3121
 
1987
    return TRUE;
3122
    return TRUE;
Line -... Line 3123...
-
 
3123
}
-
 
3124
 
-
 
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;
1988
}
3139
}
1989
 
3140
 
1990
/**
3141
/**
1991
 * _cairo_pattern_is_opaque_solid
3142
 * _cairo_pattern_is_opaque_solid:
1992
 *
3143
 *
1993
 * Convenience function to determine whether a pattern is an opaque
3144
 * Convenience function to determine whether a pattern is an opaque
1994
 * (alpha==1.0) solid color pattern. This is done by testing whether
3145
 * (alpha==1.0) solid color pattern. This is done by testing whether
Line 2011... Line 3162...
2011
    return CAIRO_COLOR_IS_OPAQUE (&solid->color);
3162
    return CAIRO_COLOR_IS_OPAQUE (&solid->color);
2012
}
3163
}
Line 2013... Line 3164...
2013
 
3164
 
2014
static cairo_bool_t
3165
static cairo_bool_t
2015
_surface_is_opaque (const cairo_surface_pattern_t *pattern,
3166
_surface_is_opaque (const cairo_surface_pattern_t *pattern,
2016
		    const cairo_rectangle_int_t *r)
3167
		    const cairo_rectangle_int_t *sample)
-
 
3168
{
-
 
3169
    cairo_rectangle_int_t extents;
2017
{
3170
 
2018
    if (pattern->surface->content & CAIRO_CONTENT_ALPHA)
3171
    if (pattern->surface->content & CAIRO_CONTENT_ALPHA)
Line 2019... Line 3172...
2019
	return FALSE;
3172
	return FALSE;
2020
 
3173
 
Line 2021... Line -...
2021
    if (pattern->base.extend != CAIRO_EXTEND_NONE)
-
 
2022
	return TRUE;
-
 
2023
 
-
 
2024
    if (r != NULL) {
3174
    if (pattern->base.extend != CAIRO_EXTEND_NONE)
2025
	cairo_rectangle_int_t extents;
3175
	return TRUE;
Line 2026... Line 3176...
2026
 
3176
 
2027
	if (! _cairo_surface_get_extents (pattern->surface, &extents))
3177
    if (! _cairo_surface_get_extents (pattern->surface, &extents))
-
 
3178
	return TRUE;
2028
	    return TRUE;
3179
 
-
 
3180
    if (sample == NULL)
-
 
3181
	return FALSE;
-
 
3182
 
-
 
3183
    return _cairo_rectangle_contains_rectangle (&extents, sample);
2029
 
3184
}
2030
	if (r->x >= extents.x &&
3185
 
-
 
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
{
2031
	    r->y >= extents.y &&
3190
    if (pattern->content & CAIRO_CONTENT_ALPHA)
2032
	    r->x + r->width <= extents.x + extents.width &&
-
 
2033
	    r->y + r->height <= extents.y + extents.height)
-
 
Line -... Line 3191...
-
 
3191
	return FALSE;
2034
	{
3192
 
-
 
3193
    if (pattern->base.extend != CAIRO_EXTEND_NONE)
-
 
3194
	return TRUE;
2035
	    return TRUE;
3195
 
Line 2036... Line 3196...
2036
	}
3196
    if (sample == NULL)
2037
    }
3197
	return FALSE;
2038
 
3198
 
Line 2051... Line 3211...
2051
    return pattern->surface->is_clear &&
3211
    return pattern->surface->is_clear &&
2052
	pattern->surface->content & CAIRO_CONTENT_ALPHA;
3212
	pattern->surface->content & CAIRO_CONTENT_ALPHA;
2053
}
3213
}
Line 2054... Line 3214...
2054
 
3214
 
-
 
3215
static cairo_bool_t
-
 
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
 
2055
static cairo_bool_t
3221
static cairo_bool_t
2056
_gradient_is_opaque (const cairo_gradient_pattern_t *gradient,
3222
_gradient_is_opaque (const cairo_gradient_pattern_t *gradient,
2057
		     const cairo_rectangle_int_t *extents)
3223
		     const cairo_rectangle_int_t *sample)
2058
{
3224
{
Line 2059... Line 3225...
2059
    unsigned int i;
3225
    unsigned int i;
2060
 
3226
 
Line 2073... Line 3239...
2073
 
3239
 
2074
	    /* EXTEND_NONE degenerate radial gradients are clear */
3240
	    /* EXTEND_NONE degenerate radial gradients are clear */
2075
	    if (_linear_pattern_is_degenerate (linear))
3241
	    if (_linear_pattern_is_degenerate (linear))
Line 2076... Line 3242...
2076
		return FALSE;
3242
		return FALSE;
2077
 
3243
 
Line 2078... Line 3244...
2078
	    if (extents == NULL)
3244
	    if (sample == NULL)
-
 
3245
		return FALSE;
-
 
3246
 
-
 
3247
	    _cairo_linear_pattern_box_to_parameter (linear,
-
 
3248
						    sample->x,
-
 
3249
						    sample->y,
-
 
3250
						    sample->x + sample->width,
2079
		return FALSE;
3251
						    sample->y + sample->height,
2080
 
3252
						    t);
2081
	    _extents_to_linear_parameter (linear, extents, t);
3253
 
2082
	    if (t[0] < 0.0 || t[1] > 1.0)
3254
	    if (t[0] < 0.0 || t[1] > 1.0)
2083
		return FALSE;
3255
		return FALSE;
Line 2091... Line 3263...
2091
 
3263
 
2092
    return TRUE;
3264
    return TRUE;
Line 2093... Line 3265...
2093
}
3265
}
2094
 
3266
 
2095
/**
3267
/**
2096
 * _cairo_pattern_is_opaque
3268
 * _cairo_pattern_is_opaque:
2097
 *
3269
 *
2098
 * Convenience function to determine whether a pattern is an opaque
3270
 * Convenience function to determine whether a pattern is an opaque
2099
 * pattern (of any type). The same caveats that apply to
3271
 * pattern (of any type). The same caveats that apply to
2100
 * _cairo_pattern_is_opaque_solid apply here as well.
3272
 * _cairo_pattern_is_opaque_solid apply here as well.
2101
 *
3273
 *
2102
 * Return value: %TRUE if the pattern is a opaque.
3274
 * Return value: %TRUE if the pattern is a opaque.
2103
 **/
3275
 **/
2104
cairo_bool_t
3276
cairo_bool_t
2105
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern,
3277
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern,
2106
			  const cairo_rectangle_int_t *extents)
3278
			  const cairo_rectangle_int_t *sample)
Line 2107... Line 3279...
2107
{
3279
{
2108
    const cairo_pattern_union_t *pattern;
3280
    const cairo_pattern_union_t *pattern;
Line 2113... Line 3285...
2113
    pattern = (cairo_pattern_union_t *) abstract_pattern;
3285
    pattern = (cairo_pattern_union_t *) abstract_pattern;
2114
    switch (pattern->base.type) {
3286
    switch (pattern->base.type) {
2115
    case CAIRO_PATTERN_TYPE_SOLID:
3287
    case CAIRO_PATTERN_TYPE_SOLID:
2116
	return _cairo_pattern_is_opaque_solid (abstract_pattern);
3288
	return _cairo_pattern_is_opaque_solid (abstract_pattern);
2117
    case CAIRO_PATTERN_TYPE_SURFACE:
3289
    case CAIRO_PATTERN_TYPE_SURFACE:
2118
	return _surface_is_opaque (&pattern->surface, extents);
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);
2119
    case CAIRO_PATTERN_TYPE_LINEAR:
3293
    case CAIRO_PATTERN_TYPE_LINEAR:
2120
    case CAIRO_PATTERN_TYPE_RADIAL:
3294
    case CAIRO_PATTERN_TYPE_RADIAL:
2121
	return _gradient_is_opaque (&pattern->gradient.base, extents);
3295
	return _gradient_is_opaque (&pattern->gradient.base, sample);
-
 
3296
    case CAIRO_PATTERN_TYPE_MESH:
-
 
3297
	return FALSE;
2122
    }
3298
    }
Line 2123... Line 3299...
2123
 
3299
 
2124
    ASSERT_NOT_REACHED;
3300
    ASSERT_NOT_REACHED;
2125
    return FALSE;
3301
    return FALSE;
Line 2132... Line 3308...
2132
 
3308
 
2133
    if (abstract_pattern->has_component_alpha)
3309
    if (abstract_pattern->has_component_alpha)
Line 2134... Line 3310...
2134
	return FALSE;
3310
	return FALSE;
2135
 
3311
 
2136
    pattern = (cairo_pattern_union_t *) abstract_pattern;
3312
    pattern = (cairo_pattern_union_t *) abstract_pattern;
2137
    switch (pattern->type) {
3313
    switch (abstract_pattern->type) {
2138
    case CAIRO_PATTERN_TYPE_SOLID:
3314
    case CAIRO_PATTERN_TYPE_SOLID:
2139
	return CAIRO_COLOR_IS_CLEAR (&pattern->solid.color);
3315
	return CAIRO_COLOR_IS_CLEAR (&pattern->solid.color);
-
 
3316
    case CAIRO_PATTERN_TYPE_SURFACE:
-
 
3317
	return _surface_is_clear (&pattern->surface);
2140
    case CAIRO_PATTERN_TYPE_SURFACE:
3318
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
2141
	return _surface_is_clear (&pattern->surface);
3319
	return _raster_source_is_clear (&pattern->raster_source);
2142
    case CAIRO_PATTERN_TYPE_LINEAR:
3320
    case CAIRO_PATTERN_TYPE_LINEAR:
-
 
3321
    case CAIRO_PATTERN_TYPE_RADIAL:
-
 
3322
	return _gradient_is_clear (&pattern->gradient.base, NULL);
2143
    case CAIRO_PATTERN_TYPE_RADIAL:
3323
    case CAIRO_PATTERN_TYPE_MESH:
Line 2144... Line 3324...
2144
	return _gradient_is_clear (&pattern->gradient.base, NULL);
3324
	return _mesh_is_clear (&pattern->mesh);
2145
    }
3325
    }
2146
 
3326
 
Line 2159... Line 3339...
2159
 * we can optimize the filter to a simpler value.
3339
 * we can optimize the filter to a simpler value.
2160
 *
3340
 *
2161
 * XXX: We don't actually have any way of querying the backend for
3341
 * XXX: We don't actually have any way of querying the backend for
2162
 *      the filter radius, so we just guess base on what we know that
3342
 *      the filter radius, so we just guess base on what we know that
2163
 *      backends do currently (see bug #10508)
3343
 *      backends do currently (see bug #10508)
2164
 */
3344
 **/
2165
cairo_filter_t
3345
cairo_filter_t
2166
_cairo_pattern_analyze_filter (const cairo_pattern_t	*pattern,
3346
_cairo_pattern_analyze_filter (const cairo_pattern_t	*pattern,
2167
			       double			*pad_out)
3347
			       double			*pad_out)
2168
{
3348
{
2169
    double pad;
3349
    double pad;
Line 2204... Line 3384...
2204
	*pad_out = pad;
3384
	*pad_out = pad;
Line 2205... Line 3385...
2205
 
3385
 
2206
    return optimized_filter;
3386
    return optimized_filter;
Line 2207... Line -...
2207
}
-
 
2208
 
-
 
2209
 
-
 
2210
static double
-
 
2211
_pixman_nearest_sample (double d)
-
 
2212
{
-
 
2213
    return ceil (d - .5);
-
 
2214
}
3387
}
2215
 
3388
 
2216
static cairo_int_status_t
3389
cairo_filter_t
2217
_cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t   *pattern,
-
 
2218
					    cairo_surface_t	       *dst,
-
 
2219
					    int			       x,
-
 
2220
					    int			       y,
-
 
2221
					    unsigned int	       width,
-
 
2222
					    unsigned int	       height,
-
 
2223
					    unsigned int	       flags,
3390
_cairo_pattern_sampled_area (const cairo_pattern_t *pattern,
2224
					    cairo_surface_t	       **out,
3391
			     const cairo_rectangle_int_t *extents,
2225
					    cairo_surface_attributes_t *attr)
3392
			     cairo_rectangle_int_t *sample)
2226
{
-
 
2227
    cairo_surface_t *surface;
-
 
2228
    cairo_rectangle_int_t extents;
3393
{
2229
    cairo_rectangle_int_t sampled_area;
-
 
2230
    double x1, y1, x2, y2;
3394
    cairo_filter_t filter;
2231
    int tx, ty;
-
 
2232
    double pad;
-
 
2233
    cairo_bool_t is_identity;
-
 
2234
    cairo_bool_t is_empty;
-
 
2235
    cairo_bool_t is_bounded;
-
 
2236
    cairo_int_status_t status;
-
 
2237
 
-
 
2238
    surface = cairo_surface_reference (pattern->surface);
-
 
2239
 
-
 
2240
    is_identity = FALSE;
-
 
2241
    attr->matrix = pattern->base.matrix;
-
 
2242
    attr->extend = pattern->base.extend;
-
 
2243
    attr->filter = _cairo_pattern_analyze_filter (&pattern->base, &pad);
-
 
2244
    attr->has_component_alpha = pattern->base.has_component_alpha;
-
 
2245
 
-
 
2246
    attr->x_offset = attr->y_offset = tx = ty = 0;
-
 
2247
    if (_cairo_matrix_is_integer_translation (&attr->matrix, &tx, &ty)) {
-
 
2248
	cairo_matrix_init_identity (&attr->matrix);
-
 
2249
	attr->x_offset = tx;
-
 
2250
	attr->y_offset = ty;
-
 
2251
	is_identity = TRUE;
-
 
2252
    } else if (attr->filter == CAIRO_FILTER_NEAREST) {
-
 
2253
	/*
-
 
2254
	 * For NEAREST, we can remove the fractional translation component
-
 
2255
	 * from the transformation - this ensures that the pattern will always
-
 
2256
	 * hit fast-paths in the backends for simple transformations that
-
 
2257
	 * become (almost) identity, without loss of quality.
-
 
2258
	 */
-
 
2259
	attr->matrix.x0 = 0;
-
 
2260
	attr->matrix.y0 = 0;
-
 
2261
	if (_cairo_matrix_is_pixel_exact (&attr->matrix)) {
-
 
2262
	    /* The rounding here is rather peculiar as it needs to match the
-
 
2263
	     * rounding performed on the sample coordinate used by pixman.
-
 
2264
	     */
-
 
2265
	    attr->matrix.x0 = _pixman_nearest_sample (pattern->base.matrix.x0);
-
 
2266
	    attr->matrix.y0 = _pixman_nearest_sample (pattern->base.matrix.y0);
-
 
2267
	} else {
-
 
2268
	    attr->matrix.x0 = pattern->base.matrix.x0;
-
 
2269
	    attr->matrix.y0 = pattern->base.matrix.y0;
-
 
2270
	}
-
 
2271
 
-
 
2272
	if (_cairo_matrix_is_integer_translation (&attr->matrix, &tx, &ty)) {
-
 
2273
	    cairo_matrix_init_identity (&attr->matrix);
-
 
2274
	    attr->x_offset = tx;
-
 
2275
	    attr->y_offset = ty;
-
 
2276
	    is_identity = TRUE;
-
 
2277
	}
-
 
2278
    }
-
 
2279
 
-
 
2280
    /* XXX: Hack:
-
 
2281
     *
-
 
2282
     * The way we currently support CAIRO_EXTEND_REFLECT is to create
-
 
2283
     * an image twice bigger on each side, and create a pattern of four
-
 
2284
     * images such that the new image, when repeated, has the same effect
-
 
2285
     * of reflecting the original pattern.
-
 
2286
     */
-
 
2287
    if (flags & CAIRO_PATTERN_ACQUIRE_NO_REFLECT &&
-
 
2288
	attr->extend == CAIRO_EXTEND_REFLECT)
-
 
2289
    {
-
 
2290
	cairo_t *cr;
-
 
2291
	cairo_surface_t *src;
-
 
2292
	int w, h;
-
 
2293
 
-
 
2294
	is_bounded = _cairo_surface_get_extents (surface, &extents);
-
 
2295
	assert (is_bounded);
-
 
2296
 
-
 
2297
	status = _cairo_surface_clone_similar (dst, surface,
-
 
2298
					       extents.x, extents.y,
-
 
2299
					       extents.width, extents.height,
-
 
2300
					       &extents.x, &extents.y, &src);
-
 
2301
	if (unlikely (status))
-
 
2302
	    goto BAIL;
-
 
2303
 
-
 
Line 2304... Line -...
2304
	w = 2 * extents.width;
-
 
2305
	h = 2 * extents.height;
3395
    double x1, x2, y1, y2;
2306
 
-
 
2307
	if (is_identity) {
-
 
2308
	    attr->x_offset = -x;
-
 
2309
	    x += tx;
-
 
2310
	    while (x <= -w)
-
 
2311
		x += w;
-
 
2312
	    while (x >= w)
-
 
2313
		x -= w;
-
 
2314
	    extents.x += x;
3396
    double pad;
2315
	    tx = x = 0;
-
 
2316
 
-
 
2317
	    attr->y_offset = -y;
-
 
2318
	    y += ty;
-
 
2319
	    while (y <= -h)
-
 
2320
		y += h;
3397
 
2321
	    while (y >= h)
3398
    filter = _cairo_pattern_analyze_filter (pattern, &pad);
2322
		y -= h;
3399
    if (pad == 0.0 && _cairo_matrix_is_identity (&pattern->matrix)) {
Line 2323... Line -...
2323
	    extents.y += y;
-
 
2324
	    ty = y = 0;
-
 
2325
	}
-
 
2326
 
-
 
2327
	cairo_surface_destroy (surface);
3400
	*sample = *extents;
2328
	surface = _cairo_surface_create_similar_solid (dst,
-
 
2329
						       dst->content, w, h,
-
 
2330
						       CAIRO_COLOR_TRANSPARENT,
-
 
2331
						       FALSE);
-
 
2332
	if (surface == NULL)
3401
	return filter;
2333
	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
 
2334
	if (unlikely (surface->status)) {
-
 
2335
	    cairo_surface_destroy (src);
-
 
2336
	    return surface->status;
-
 
2337
	}
-
 
2338
 
-
 
2339
	surface->device_transform = pattern->surface->device_transform;
-
 
2340
	surface->device_transform_inverse = pattern->surface->device_transform_inverse;
-
 
2341
 
-
 
2342
	cr = cairo_create (surface);
-
 
2343
 
-
 
2344
	cairo_set_source_surface (cr, src, -extents.x, -extents.y);
-
 
2345
	cairo_paint (cr);
-
 
2346
 
3402
    }
2347
	cairo_scale (cr, -1, +1);
-
 
2348
	cairo_set_source_surface (cr, src, extents.x-w, -extents.y);
-
 
2349
	cairo_paint (cr);
-
 
2350
	cairo_set_source_surface (cr, src, extents.x, -extents.y);
-
 
2351
	cairo_paint (cr);
-
 
2352
 
-
 
2353
	cairo_scale (cr, +1, -1);
-
 
2354
	cairo_set_source_surface (cr, src, extents.x-w, extents.y-h);
-
 
2355
	cairo_paint (cr);
-
 
2356
	cairo_set_source_surface (cr, src, extents.x, extents.y-h);
3403
 
2357
	cairo_paint (cr);
-
 
2358
	cairo_set_source_surface (cr, src, extents.x-w, extents.y);
-
 
2359
	cairo_paint (cr);
-
 
2360
	cairo_set_source_surface (cr, src, extents.x, extents.y);
-
 
2361
	cairo_paint (cr);
-
 
2362
 
-
 
2363
	cairo_scale (cr, -1, +1);
-
 
2364
	cairo_set_source_surface (cr, src, -extents.x, extents.y-h);
-
 
2365
	cairo_paint (cr);
-
 
2366
	cairo_set_source_surface (cr, src, -extents.x, extents.y);
-
 
2367
	cairo_paint (cr);
-
 
2368
 
-
 
2369
	status = cairo_status (cr);
-
 
2370
	cairo_destroy (cr);
-
 
2371
 
-
 
2372
	cairo_surface_destroy (src);
-
 
2373
 
-
 
2374
	if (unlikely (status))
-
 
Line 2375... Line -...
2375
	    goto BAIL;
-
 
2376
 
-
 
2377
	attr->extend = CAIRO_EXTEND_REPEAT;
-
 
2378
    }
-
 
2379
 
-
 
2380
    /* We first transform the rectangle to the coordinate space of the
-
 
2381
     * source surface so that we only need to clone that portion of the
-
 
2382
     * surface that will be read.
-
 
2383
     */
-
 
2384
    x1 = x;
3404
    x1 = extents->x;
2385
    y1 = y;
3405
    y1 = extents->y;
2386
    x2 = x + (int) width;
3406
    x2 = extents->x + (int) extents->width;
2387
    y2 = y + (int) height;
-
 
2388
    if (! is_identity) {
-
 
2389
	_cairo_matrix_transform_bounding_box (&attr->matrix,
3407
    y2 = extents->y + (int) extents->height;
2390
					      &x1, &y1, &x2, &y2,
3408
 
2391
					      NULL);
-
 
2392
    }
-
 
2393
 
-
 
2394
    sampled_area.x = floor (x1 - pad);
-
 
2395
    sampled_area.y = floor (y1 - pad);
-
 
2396
    sampled_area.width  = ceil (x2 + pad) - sampled_area.x;
-
 
2397
    sampled_area.height = ceil (y2 + pad) - sampled_area.y;
-
 
2398
 
-
 
2399
    sampled_area.x += tx;
-
 
2400
    sampled_area.y += ty;
-
 
2401
 
3409
    _cairo_matrix_transform_bounding_box (&pattern->matrix,
2402
    if ( _cairo_surface_get_extents (surface, &extents)) {
-
 
2403
	if (attr->extend == CAIRO_EXTEND_NONE) {
-
 
2404
	    /* Never acquire a larger area than the source itself */
-
 
2405
	    is_empty = _cairo_rectangle_intersect (&extents, &sampled_area);
-
 
2406
	} else {
-
 
2407
	    int trim = 0;
-
 
2408
 
-
 
2409
	    if (sampled_area.x >= extents.x &&
-
 
2410
		sampled_area.x + (int) sampled_area.width <= extents.x + (int) extents.width)
-
 
2411
	    {
-
 
2412
		/* source is horizontally contained within extents, trim */
-
 
2413
		extents.x = sampled_area.x;
-
 
2414
		extents.width = sampled_area.width;
-
 
2415
		trim |= 0x1;
-
 
2416
	    }
-
 
2417
 
-
 
2418
	    if (sampled_area.y >= extents.y &&
-
 
2419
		sampled_area.y + (int) sampled_area.height <= extents.y + (int) extents.height)
-
 
2420
	    {
-
 
2421
		/* source is vertically contained within extents, trim */
-
 
2422
		extents.y = sampled_area.y;
-
 
2423
		extents.height = sampled_area.height;
-
 
2424
		trim |= 0x2;
3410
					  &x1, &y1, &x2, &y2,
2425
	    }
-
 
2426
 
-
 
2427
	    if (trim == 0x3) {
-
 
2428
		/* source is wholly contained within extents, drop the REPEAT */
-
 
2429
		attr->extend = CAIRO_EXTEND_NONE;
-
 
2430
	    }
-
 
2431
 
-
 
2432
	    is_empty = extents.width == 0 || extents.height == 0;
-
 
2433
	}
-
 
2434
    }
-
 
2435
 
-
 
2436
    /* XXX can we use is_empty? */
-
 
2437
 
-
 
2438
    status = _cairo_surface_clone_similar (dst, surface,
-
 
2439
					   extents.x, extents.y,
-
 
2440
					   extents.width, extents.height,
-
 
2441
					   &x, &y, out);
-
 
2442
    if (unlikely (status))
-
 
2443
	goto BAIL;
-
 
2444
 
-
 
2445
    if (x != 0 || y != 0) {
-
 
2446
	if (is_identity) {
-
 
2447
	    attr->x_offset -= x;
-
 
2448
	    attr->y_offset -= y;
-
 
2449
	} else {
-
 
2450
	    cairo_matrix_t m;
-
 
2451
 
-
 
2452
	    x -= attr->x_offset;
-
 
2453
	    y -= attr->y_offset;
-
 
2454
	    attr->x_offset = 0;
-
 
2455
	    attr->y_offset = 0;
-
 
2456
 
-
 
2457
	    cairo_matrix_init_translate (&m, -x, -y);
-
 
2458
	    cairo_matrix_multiply (&attr->matrix, &attr->matrix, &m);
-
 
2459
	}
-
 
2460
    }
-
 
2461
 
-
 
2462
    /* reduce likelihood of range overflow with large downscaling */
-
 
2463
    if (! is_identity) {
-
 
2464
	cairo_matrix_t m;
-
 
2465
	cairo_status_t invert_status;
-
 
2466
 
-
 
2467
	m = attr->matrix;
-
 
2468
	invert_status = cairo_matrix_invert (&m);
-
 
2469
	assert (invert_status == CAIRO_STATUS_SUCCESS);
-
 
2470
 
-
 
2471
	if (m.x0 != 0. || m.y0 != 0.) {
-
 
2472
	    /* pixman also limits the [xy]_offset to 16 bits so evenly
-
 
2473
	     * spread the bits between the two.
-
 
2474
	     */
-
 
2475
	    x = floor (m.x0 / 2);
-
 
2476
	    y = floor (m.y0 / 2);
-
 
2477
	    attr->x_offset -= x;
-
 
2478
	    attr->y_offset -= y;
-
 
2479
	    cairo_matrix_init_translate (&m, x, y);
-
 
2480
	    cairo_matrix_multiply (&attr->matrix, &m, &attr->matrix);
-
 
2481
	}
-
 
2482
    }
-
 
2483
 
-
 
2484
  BAIL:
-
 
2485
    cairo_surface_destroy (surface);
-
 
2486
    return status;
-
 
2487
}
-
 
2488
 
-
 
2489
/**
-
 
2490
 * _cairo_pattern_acquire_surface:
-
 
2491
 * @pattern: a #cairo_pattern_t
-
 
2492
 * @dst: destination surface
-
 
2493
 * @x: X coordinate in source corresponding to left side of destination area
-
 
2494
 * @y: Y coordinate in source corresponding to top side of destination area
-
 
2495
 * @width: width of destination area
-
 
2496
 * @height: height of destination area
-
 
2497
 * @surface_out: location to store a pointer to a surface
-
 
2498
 * @attributes: surface attributes that destination backend should apply to
-
 
2499
 * the returned surface
-
 
2500
 *
-
 
2501
 * A convenience function to obtain a surface to use as the source for
-
 
2502
 * drawing on @dst.
-
 
2503
 *
-
 
2504
 * Note that this function is only suitable for use when the destination
-
 
2505
 * surface is pixel based and 1 device unit maps to one pixel.
-
 
2506
 *
-
 
2507
 * Return value: %CAIRO_STATUS_SUCCESS if a surface was stored in @surface_out.
-
 
2508
 **/
-
 
2509
cairo_int_status_t
-
 
2510
_cairo_pattern_acquire_surface (const cairo_pattern_t	   *pattern,
-
 
2511
				cairo_surface_t		   *dst,
-
 
2512
				int			   x,
-
 
2513
				int			   y,
-
 
2514
				unsigned int		   width,
-
 
2515
				unsigned int		   height,
-
 
2516
				unsigned int		   flags,
-
 
2517
				cairo_surface_t		   **surface_out,
-
 
2518
				cairo_surface_attributes_t *attributes)
-
 
2519
{
-
 
2520
    if (unlikely (pattern->status)) {
-
 
2521
	*surface_out = NULL;
-
 
2522
	return pattern->status;
-
 
2523
    }
-
 
2524
 
-
 
2525
    switch (pattern->type) {
-
 
2526
    case CAIRO_PATTERN_TYPE_SOLID:
-
 
2527
	return _cairo_pattern_acquire_surface_for_solid ((cairo_solid_pattern_t *) pattern,
-
 
2528
							 dst, x, y, width, height,
-
 
2529
							 surface_out,
-
 
2530
							 attributes);
-
 
2531
 
-
 
2532
    case CAIRO_PATTERN_TYPE_LINEAR:
-
 
2533
    case CAIRO_PATTERN_TYPE_RADIAL:
-
 
2534
	return _cairo_pattern_acquire_surface_for_gradient ((cairo_gradient_pattern_t *) pattern,
-
 
2535
							    dst, x, y, width, height,
-
 
2536
							    surface_out,
-
 
2537
							    attributes);
-
 
2538
 
-
 
2539
    case CAIRO_PATTERN_TYPE_SURFACE:
-
 
2540
	return _cairo_pattern_acquire_surface_for_surface ((cairo_surface_pattern_t *) pattern,
-
 
2541
							   dst, x, y, width, height,
-
 
2542
							   flags,
-
 
2543
							   surface_out,
-
 
2544
							   attributes);
-
 
2545
 
-
 
2546
    default:
-
 
2547
	ASSERT_NOT_REACHED;
-
 
2548
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
-
 
2549
    }
-
 
2550
}
-
 
2551
 
-
 
2552
/**
-
 
2553
 * _cairo_pattern_release_surface:
-
 
2554
 * @pattern: a #cairo_pattern_t
-
 
2555
 * @surface: a surface obtained by _cairo_pattern_acquire_surface
-
 
2556
 * @attributes: attributes obtained by _cairo_pattern_acquire_surface
-
 
2557
 *
-
 
2558
 * Releases resources obtained by _cairo_pattern_acquire_surface.
-
 
2559
 **/
-
 
2560
void
-
 
2561
_cairo_pattern_release_surface (const cairo_pattern_t *pattern,
-
 
Line 2562... Line -...
2562
				cairo_surface_t		   *surface,
-
 
2563
				cairo_surface_attributes_t *attributes)
-
 
2564
{
-
 
2565
    cairo_surface_destroy (surface);
-
 
2566
}
-
 
2567
 
-
 
2568
cairo_int_status_t
-
 
2569
_cairo_pattern_acquire_surfaces (const cairo_pattern_t	    *src,
-
 
2570
				 const cairo_pattern_t	    *mask,
-
 
2571
				 cairo_surface_t	    *dst,
-
 
2572
				 int			    src_x,
-
 
2573
				 int			    src_y,
-
 
2574
				 int			    mask_x,
-
 
2575
				 int			    mask_y,
-
 
2576
				 unsigned int		    width,
-
 
2577
				 unsigned int		    height,
-
 
2578
				 unsigned int		    flags,
-
 
2579
				 cairo_surface_t	    **src_out,
-
 
2580
				 cairo_surface_t	    **mask_out,
-
 
2581
				 cairo_surface_attributes_t *src_attributes,
-
 
2582
				 cairo_surface_attributes_t *mask_attributes)
-
 
2583
{
-
 
2584
    cairo_int_status_t	  status;
-
 
2585
    cairo_pattern_union_t src_tmp;
-
 
2586
 
-
 
2587
    if (unlikely (src->status))
-
 
2588
	return src->status;
-
 
2589
    if (unlikely (mask != NULL && mask->status))
3411
					  NULL);
2590
	return mask->status;
-
 
2591
 
3412
    if (x1 > CAIRO_RECT_INT_MIN)
2592
    /* If src and mask are both solid, then the mask alpha can be
-
 
2593
     * combined into src and mask can be ignored. */
3413
	sample->x = floor (x1 - pad);
2594
 
-
 
2595
    if (src->type == CAIRO_PATTERN_TYPE_SOLID &&
-
 
2596
	mask &&
-
 
2597
	! mask->has_component_alpha &&
-
 
2598
	mask->type == CAIRO_PATTERN_TYPE_SOLID)
3414
    else
2599
    {
-
 
2600
	cairo_color_t combined;
-
 
2601
	cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src;
-
 
2602
	cairo_solid_pattern_t *mask_solid = (cairo_solid_pattern_t *) mask;
-
 
2603
 
-
 
2604
	combined = src_solid->color;
-
 
2605
	_cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
-
 
2606
 
-
 
2607
	_cairo_pattern_init_solid (&src_tmp.solid, &combined);
-
 
2608
 
-
 
2609
	src = &src_tmp.base;
-
 
2610
	mask = NULL;
-
 
2611
    }
-
 
2612
 
-
 
2613
    status = _cairo_pattern_acquire_surface (src, dst,
-
 
Line 2614... Line 3415...
2614
					     src_x, src_y,
3415
	sample->x = CAIRO_RECT_INT_MIN;
2615
					     width, height,
3416
 
2616
					     flags,
-
 
2617
					     src_out, src_attributes);
3417
    if (y1 > CAIRO_RECT_INT_MIN)
-
 
3418
	sample->y = floor (y1 - pad);
Line 2618... Line -...
2618
    if (unlikely (status))
-
 
2619
	goto BAIL;
3419
    else
2620
 
3420
	sample->y = CAIRO_RECT_INT_MIN;
2621
    if (mask == NULL) {
3421
 
2622
	*mask_out = NULL;
3422
    if (x2 < CAIRO_RECT_INT_MAX)
2623
	goto BAIL;
-
 
2624
    }
-
 
Line 2625... Line -...
2625
 
-
 
2626
    status = _cairo_pattern_acquire_surface (mask, dst,
3423
	sample->width = ceil (x2 + pad);
2627
					     mask_x, mask_y,
3424
    else
Line 2628... Line 3425...
2628
					     width, height,
3425
	sample->width = CAIRO_RECT_INT_MAX;
2629
					     flags,
3426
 
Line 2630... Line 3427...
2630
					     mask_out, mask_attributes);
3427
    if (y2 < CAIRO_RECT_INT_MAX)
2631
    if (unlikely (status))
3428
	sample->height = ceil (y2 + pad);
2632
	_cairo_pattern_release_surface (src, *src_out, src_attributes);
3429
    else
Line 2687... Line 3484...
2687
	    x2 = surface_extents.x + (int) surface_extents.width  + pad;
3484
	    x2 = surface_extents.x + (int) surface_extents.width  + pad;
2688
	    y2 = surface_extents.y + (int) surface_extents.height + pad;
3485
	    y2 = surface_extents.y + (int) surface_extents.height + pad;
2689
	}
3486
	}
2690
	break;
3487
	break;
Line -... Line 3488...
-
 
3488
 
-
 
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;
2691
 
3511
 
2692
    case CAIRO_PATTERN_TYPE_RADIAL:
3512
    case CAIRO_PATTERN_TYPE_RADIAL:
2693
	{
3513
	{
2694
	    const cairo_radial_pattern_t *radial =
3514
	    const cairo_radial_pattern_t *radial =
2695
		(const cairo_radial_pattern_t *) pattern;
3515
		(const cairo_radial_pattern_t *) pattern;
2696
	    double cx1, cy1;
3516
	    double cx1, cy1;
2697
	    double cx2, cy2;
3517
	    double cx2, cy2;
Line 2698... Line 3518...
2698
	    double r, D;
3518
	    double r1, r2;
-
 
3519
 
-
 
3520
	    if (_radial_pattern_is_degenerate (radial)) {
-
 
3521
		/* cairo-gstate should have optimised degenerate
2699
 
3522
		 * patterns to solid clear patterns, so we can ignore
-
 
3523
		 * them here. */
Line 2700... Line -...
2700
	    if (radial->r1 == 0 && radial->r2 == 0)
-
 
2701
		goto EMPTY;
3524
		goto EMPTY;
2702
 
-
 
2703
	    cx1 = _cairo_fixed_to_double (radial->c1.x);
3525
	    }
2704
	    cy1 = _cairo_fixed_to_double (radial->c1.y);
-
 
2705
	    r = _cairo_fixed_to_double (radial->r1);
-
 
2706
	    x1 = cx1 - r; x2 = cx1 + r;
-
 
2707
	    y1 = cy1 - r; y2 = cy1 + r;
-
 
2708
 
-
 
2709
	    cx2 = _cairo_fixed_to_double (radial->c2.x);
-
 
2710
	    cy2 = _cairo_fixed_to_double (radial->c2.y);
3526
 
2711
	    r = fabs (_cairo_fixed_to_double (radial->r2));
3527
	    /* TODO: in some cases (focus outside/on the circle) it is
Line 2712... Line 3528...
2712
 
3528
	     * half-bounded. */
2713
	    if (pattern->extend != CAIRO_EXTEND_NONE)
-
 
2714
		goto UNBOUNDED;
-
 
2715
 
3529
	    if (pattern->extend != CAIRO_EXTEND_NONE)
2716
	    /* We need to be careful, as if the circles are not
3530
		goto UNBOUNDED;
2717
	     * self-contained, then the solution is actually unbounded.
-
 
2718
	     */
3531
 
2719
	    D = (cx1-cx2)*(cx1-cx2) + (cy1-cy2)*(cy1-cy2);
3532
	    cx1 = radial->cd1.center.x;
2720
	    if (D > r*r - 1e-5)
-
 
2721
		goto UNBOUNDED;
3533
	    cy1 = radial->cd1.center.y;
2722
 
3534
	    r1  = radial->cd1.radius;
2723
	    if (cx2 - r < x1)
3535
 
2724
		x1 = cx2 - r;
3536
	    cx2 = radial->cd2.center.x;
2725
	    if (cx2 + r > x2)
3537
	    cy2 = radial->cd2.center.y;
2726
		x2 = cx2 + r;
3538
	    r2  = radial->cd2.radius;
2727
 
3539
 
2728
	    if (cy2 - r < y1)
3540
	    x1 = MIN (cx1 - r1, cx2 - r2);
2729
		y1 = cy2 - r;
3541
	    y1 = MIN (cy1 - r1, cy2 - r2);
Line 2730... Line 3542...
2730
	    if (cy2 + r > y2)
3542
	    x2 = MAX (cx1 + r1, cx2 + r2);
2731
		y2 = cy2 + r;
3543
	    y2 = MAX (cy1 + r1, cy2 + r2);
Line 2738... Line 3550...
2738
		(const cairo_linear_pattern_t *) pattern;
3550
		(const cairo_linear_pattern_t *) pattern;
Line 2739... Line 3551...
2739
 
3551
 
2740
	    if (pattern->extend != CAIRO_EXTEND_NONE)
3552
	    if (pattern->extend != CAIRO_EXTEND_NONE)
Line 2741... Line 3553...
2741
		goto UNBOUNDED;
3553
		goto UNBOUNDED;
-
 
3554
 
-
 
3555
	    if (_linear_pattern_is_degenerate (linear)) {
-
 
3556
		/* cairo-gstate should have optimised degenerate
2742
 
3557
		 * patterns to solid ones, so we can again ignore
-
 
3558
		 * them here. */
Line -... Line 3559...
-
 
3559
		goto EMPTY;
-
 
3560
	    }
2743
	    if (linear->p1.x == linear->p2.x && linear->p1.y == linear->p2.y)
3561
 
2744
		goto EMPTY;
3562
	    /* TODO: to get tight extents, use the matrix to transform
Line 2745... Line 3563...
2745
 
3563
	     * the pattern instead of transforming the extents later. */
2746
	    if (pattern->matrix.xy != 0. || pattern->matrix.yx != 0.)
3564
	    if (pattern->matrix.xy != 0. || pattern->matrix.yx != 0.)
2747
		goto UNBOUNDED;
3565
		goto UNBOUNDED;
2748
 
3566
 
2749
	    if (linear->p1.x == linear->p2.x) {
3567
	    if (linear->pd1.x == linear->pd2.x) {
2750
		x1 = -HUGE_VAL;
3568
		x1 = -HUGE_VAL;
2751
		x2 = HUGE_VAL;
3569
		x2 = HUGE_VAL;
2752
		y1 = _cairo_fixed_to_double (MIN (linear->p1.y, linear->p2.y));
3570
		y1 = MIN (linear->pd1.y, linear->pd2.y);
2753
		y2 = _cairo_fixed_to_double (MAX (linear->p1.y, linear->p2.y));
3571
		y2 = MAX (linear->pd1.y, linear->pd2.y);
2754
	    } else if (linear->p1.y == linear->p2.y) {
3572
	    } else if (linear->pd1.y == linear->pd2.y) {
2755
		x1 = _cairo_fixed_to_double (MIN (linear->p1.x, linear->p2.x));
3573
		x1 = MIN (linear->pd1.x, linear->pd2.x);
2756
		x2 = _cairo_fixed_to_double (MAX (linear->p1.x, linear->p2.x));
3574
		x2 = MAX (linear->pd1.x, linear->pd2.x);
2757
		y1 = -HUGE_VAL;
3575
		y1 = -HUGE_VAL;
2758
		y2 = HUGE_VAL;
3576
		y2 = HUGE_VAL;
2759
	    } else {
3577
	    } else {
Line -... Line 3578...
-
 
3578
		goto  UNBOUNDED;
-
 
3579
	    }
-
 
3580
	}
-
 
3581
	break;
-
 
3582
 
-
 
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;
2760
		goto  UNBOUNDED;
3601
	    x2 += padx;
2761
	    }
3602
	    y2 += pady;
2762
	}
3603
	}
Line 2763... Line 3604...
2763
	break;
3604
	break;
Line 2809... Line 3650...
2809
    extents->x = extents->y = 0;
3650
    extents->x = extents->y = 0;
2810
    extents->width = extents->height = 0;
3651
    extents->width = extents->height = 0;
2811
    return;
3652
    return;
2812
}
3653
}
Line -... Line 3654...
-
 
3654
 
-
 
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;
-
 
3670
 
-
 
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;
Line 2813... Line 3694...
2813
 
3694
}
2814
 
3695
 
2815
static unsigned long
3696
static unsigned long
2816
_cairo_solid_pattern_hash (unsigned long hash,
3697
_cairo_solid_pattern_hash (unsigned long hash,
2817
			   const cairo_pattern_t *pattern)
-
 
2818
{
-
 
2819
    const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
3698
			   const cairo_solid_pattern_t *solid)
Line 2820... Line 3699...
2820
 
3699
{
2821
    hash = _cairo_hash_bytes (hash, &solid->color, sizeof (solid->color));
3700
    hash = _cairo_hash_bytes (hash, &solid->color, sizeof (solid->color));
Line 2837... Line 3716...
2837
	hash = _cairo_hash_bytes (hash,
3716
	hash = _cairo_hash_bytes (hash,
2838
				  &gradient->stops[n].offset,
3717
				  &gradient->stops[n].offset,
2839
				  sizeof (double));
3718
				  sizeof (double));
2840
	hash = _cairo_hash_bytes (hash,
3719
	hash = _cairo_hash_bytes (hash,
2841
				  &gradient->stops[n].color,
3720
				  &gradient->stops[n].color,
2842
				  sizeof (cairo_color_t));
3721
				  sizeof (cairo_color_stop_t));
2843
    }
3722
    }
Line 2844... Line 3723...
2844
 
3723
 
2845
    return hash;
3724
    return hash;
Line 2846... Line 3725...
2846
}
3725
}
2847
 
3726
 
2848
unsigned long
3727
unsigned long
2849
_cairo_linear_pattern_hash (unsigned long hash,
3728
_cairo_linear_pattern_hash (unsigned long hash,
2850
			    const cairo_linear_pattern_t *linear)
3729
			    const cairo_linear_pattern_t *linear)
2851
{
3730
{
Line 2852... Line 3731...
2852
    hash = _cairo_hash_bytes (hash, &linear->p1, sizeof (linear->p1));
3731
    hash = _cairo_hash_bytes (hash, &linear->pd1, sizeof (linear->pd1));
2853
    hash = _cairo_hash_bytes (hash, &linear->p2, sizeof (linear->p2));
3732
    hash = _cairo_hash_bytes (hash, &linear->pd2, sizeof (linear->pd2));
Line 2854... Line 3733...
2854
 
3733
 
2855
    return _cairo_gradient_color_stops_hash (hash, &linear->base);
3734
    return _cairo_gradient_color_stops_hash (hash, &linear->base);
2856
}
3735
}
2857
 
3736
 
2858
unsigned long
3737
unsigned long
2859
_cairo_radial_pattern_hash (unsigned long hash,
3738
_cairo_radial_pattern_hash (unsigned long hash,
2860
			    const cairo_radial_pattern_t *radial)
3739
			    const cairo_radial_pattern_t *radial)
2861
{
3740
{
Line 2862... Line 3741...
2862
    hash = _cairo_hash_bytes (hash, &radial->c1, sizeof (radial->c1));
3741
    hash = _cairo_hash_bytes (hash, &radial->cd1.center, sizeof (radial->cd1.center));
2863
    hash = _cairo_hash_bytes (hash, &radial->r1, sizeof (radial->r1));
3742
    hash = _cairo_hash_bytes (hash, &radial->cd1.radius, sizeof (radial->cd1.radius));
Line 2864... Line 3743...
2864
    hash = _cairo_hash_bytes (hash, &radial->c2, sizeof (radial->c2));
3743
    hash = _cairo_hash_bytes (hash, &radial->cd2.center, sizeof (radial->cd2.center));
2865
    hash = _cairo_hash_bytes (hash, &radial->r2, sizeof (radial->r2));
3744
    hash = _cairo_hash_bytes (hash, &radial->cd2.radius, sizeof (radial->cd2.radius));
2866
 
-
 
2867
    return _cairo_gradient_color_stops_hash (hash, &radial->base);
3745
 
2868
}
3746
    return _cairo_gradient_color_stops_hash (hash, &radial->base);
-
 
3747
}
Line -... Line 3748...
-
 
3748
 
-
 
3749
static unsigned long
-
 
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
 
2869
 
3758
    return hash;
Line 2870... Line 3759...
2870
static unsigned long
3759
}
2871
_cairo_surface_pattern_hash (unsigned long hash,
3760
 
Line -... Line 3761...
-
 
3761
static unsigned long
-
 
3762
_cairo_surface_pattern_hash (unsigned long hash,
-
 
3763
			     const cairo_surface_pattern_t *surface)
-
 
3764
{
-
 
3765
    hash ^= surface->surface->unique_id;
-
 
3766
 
-
 
3767
    return hash;
-
 
3768
}
-
 
3769
 
2872
			     const cairo_pattern_t *pattern)
3770
static unsigned long
2873
{
3771
_cairo_raster_source_pattern_hash (unsigned long hash,
2874
    const cairo_surface_pattern_t *surface = (cairo_surface_pattern_t *) pattern;
3772
				   const cairo_raster_source_pattern_t *raster)
2875
 
3773
{
Line 2899... Line 3797...
2899
				  sizeof (pattern->has_component_alpha));
3797
				  sizeof (pattern->has_component_alpha));
2900
    }
3798
    }
Line 2901... Line 3799...
2901
 
3799
 
2902
    switch (pattern->type) {
3800
    switch (pattern->type) {
2903
    case CAIRO_PATTERN_TYPE_SOLID:
3801
    case CAIRO_PATTERN_TYPE_SOLID:
2904
	return _cairo_solid_pattern_hash (hash, pattern);
3802
	return _cairo_solid_pattern_hash (hash, (cairo_solid_pattern_t *) pattern);
2905
    case CAIRO_PATTERN_TYPE_LINEAR:
3803
    case CAIRO_PATTERN_TYPE_LINEAR:
2906
	return _cairo_linear_pattern_hash (hash, (cairo_linear_pattern_t *) pattern);
3804
	return _cairo_linear_pattern_hash (hash, (cairo_linear_pattern_t *) pattern);
2907
    case CAIRO_PATTERN_TYPE_RADIAL:
3805
    case CAIRO_PATTERN_TYPE_RADIAL:
-
 
3806
	return _cairo_radial_pattern_hash (hash, (cairo_radial_pattern_t *) pattern);
-
 
3807
    case CAIRO_PATTERN_TYPE_MESH:
2908
	return _cairo_radial_pattern_hash (hash, (cairo_radial_pattern_t *) pattern);
3808
	return _cairo_mesh_pattern_hash (hash, (cairo_mesh_pattern_t *) pattern);
2909
    case CAIRO_PATTERN_TYPE_SURFACE:
3809
    case CAIRO_PATTERN_TYPE_SURFACE:
-
 
3810
	return _cairo_surface_pattern_hash (hash, (cairo_surface_pattern_t *) pattern);
-
 
3811
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
2910
	return _cairo_surface_pattern_hash (hash, pattern);
3812
	return _cairo_raster_source_pattern_hash (hash, (cairo_raster_source_pattern_t *) pattern);
2911
    default:
3813
    default:
2912
	ASSERT_NOT_REACHED;
3814
	ASSERT_NOT_REACHED;
2913
	return FALSE;
3815
	return FALSE;
2914
    }
3816
    }
Line 2915... Line -...
2915
}
-
 
2916
 
-
 
2917
static unsigned long
-
 
2918
_cairo_gradient_pattern_color_stops_size (const cairo_pattern_t *pattern)
-
 
2919
{
-
 
2920
    cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
-
 
2921
 
-
 
2922
    return gradient->n_stops * (sizeof (double) + sizeof (cairo_color_t));
-
 
2923
}
-
 
2924
 
-
 
2925
unsigned long
-
 
2926
_cairo_pattern_size (const cairo_pattern_t *pattern)
-
 
2927
{
-
 
2928
    if (pattern->status)
-
 
2929
	return 0;
-
 
2930
 
-
 
2931
    /* XXX */
-
 
2932
    switch (pattern->type) {
-
 
2933
    case CAIRO_PATTERN_TYPE_SOLID:
-
 
2934
	return sizeof (cairo_solid_pattern_t);
-
 
2935
	break;
-
 
2936
    case CAIRO_PATTERN_TYPE_SURFACE:
-
 
2937
	return sizeof (cairo_surface_pattern_t);
-
 
2938
	break;
-
 
2939
    case CAIRO_PATTERN_TYPE_LINEAR:
-
 
2940
	return sizeof (cairo_linear_pattern_t) +
-
 
2941
	    _cairo_gradient_pattern_color_stops_size (pattern);
-
 
2942
	break;
-
 
2943
    case CAIRO_PATTERN_TYPE_RADIAL:
-
 
2944
	return sizeof (cairo_radial_pattern_t) +
-
 
2945
	    _cairo_gradient_pattern_color_stops_size (pattern);
-
 
2946
    default:
-
 
2947
	ASSERT_NOT_REACHED;
-
 
2948
	return 0;
-
 
2949
    }
-
 
2950
}
-
 
2951
 
3817
}
2952
 
3818
 
2953
static cairo_bool_t
3819
static cairo_bool_t
2954
_cairo_solid_pattern_equal (const cairo_pattern_t *A,
3820
_cairo_solid_pattern_equal (const cairo_solid_pattern_t *a,
2955
			    const cairo_pattern_t *B)
-
 
2956
{
-
 
2957
    const cairo_solid_pattern_t *a = (cairo_solid_pattern_t *) A;
-
 
2958
    const cairo_solid_pattern_t *b = (cairo_solid_pattern_t *) B;
3821
			    const cairo_solid_pattern_t *b)
2959
 
3822
{
Line 2960... Line 3823...
2960
    return _cairo_color_equal (&a->color, &b->color);
3823
    return _cairo_color_equal (&a->color, &b->color);
2961
}
3824
}
Line 2981... Line 3844...
2981
 
3844
 
2982
cairo_bool_t
3845
cairo_bool_t
2983
_cairo_linear_pattern_equal (const cairo_linear_pattern_t *a,
3846
_cairo_linear_pattern_equal (const cairo_linear_pattern_t *a,
2984
			     const cairo_linear_pattern_t *b)
3847
			     const cairo_linear_pattern_t *b)
2985
{
3848
{
2986
    if (a->p1.x != b->p1.x)
3849
    if (a->pd1.x != b->pd1.x)
Line 2987... Line 3850...
2987
	return FALSE;
3850
	return FALSE;
2988
 
3851
 
Line 2989... Line 3852...
2989
    if (a->p1.y != b->p1.y)
3852
    if (a->pd1.y != b->pd1.y)
2990
	return FALSE;
3853
	return FALSE;
Line 2991... Line 3854...
2991
 
3854
 
2992
    if (a->p2.x != b->p2.x)
3855
    if (a->pd2.x != b->pd2.x)
Line 2993... Line 3856...
2993
	return FALSE;
3856
	return FALSE;
2994
 
3857
 
Line 2995... Line 3858...
2995
    if (a->p2.y != b->p2.y)
3858
    if (a->pd2.y != b->pd2.y)
2996
	return FALSE;
3859
	return FALSE;
2997
 
3860
 
2998
    return _cairo_gradient_color_stops_equal (&a->base, &b->base);
3861
    return _cairo_gradient_color_stops_equal (&a->base, &b->base);
2999
}
3862
}
3000
 
3863
 
Line 3001... Line 3864...
3001
cairo_bool_t
3864
cairo_bool_t
3002
_cairo_radial_pattern_equal (const cairo_radial_pattern_t *a,
3865
_cairo_radial_pattern_equal (const cairo_radial_pattern_t *a,
Line 3003... Line 3866...
3003
			     const cairo_radial_pattern_t *b)
3866
			     const cairo_radial_pattern_t *b)
3004
{
3867
{
Line 3005... Line 3868...
3005
    if (a->c1.x != b->c1.x)
3868
    if (a->cd1.center.x != b->cd1.center.x)
3006
	return FALSE;
3869
	return FALSE;
Line 3007... Line 3870...
3007
 
3870
 
3008
    if (a->c1.y != b->c1.y)
3871
    if (a->cd1.center.y != b->cd1.center.y)
Line 3009... Line 3872...
3009
	return FALSE;
3872
	return FALSE;
3010
 
3873
 
Line 3011... Line 3874...
3011
    if (a->r1 != b->r1)
3874
    if (a->cd1.radius != b->cd1.radius)
3012
	return FALSE;
3875
	return FALSE;
Line 3013... Line 3876...
3013
 
3876
 
3014
    if (a->c2.x != b->c2.x)
3877
    if (a->cd2.center.x != b->cd2.center.x)
3015
	return FALSE;
3878
	return FALSE;
3016
 
3879
 
3017
    if (a->c2.y != b->c2.y)
3880
    if (a->cd2.center.y != b->cd2.center.y)
-
 
3881
	return FALSE;
-
 
3882
 
-
 
3883
    if (a->cd2.radius != b->cd2.radius)
3018
	return FALSE;
3884
	return FALSE;
Line -... Line 3885...
-
 
3885
 
-
 
3886
    return _cairo_gradient_color_stops_equal (&a->base, &b->base);
-
 
3887
}
-
 
3888
 
-
 
3889
static cairo_bool_t
-
 
3890
_cairo_mesh_pattern_equal (const cairo_mesh_pattern_t *a,
-
 
3891
			   const cairo_mesh_pattern_t *b)
-
 
3892
{
-
 
3893
    const cairo_mesh_patch_t *patch_a, *patch_b;
-
 
3894
    unsigned int i, num_patches_a, num_patches_b;
-
 
3895
 
-
 
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
 
3019
 
3902
    for (i = 0; i < num_patches_a; i++) {
3020
    if (a->r2 != b->r2)
3903
	patch_a = _cairo_array_index_const (&a->patches, i);
Line -... Line 3904...
-
 
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
}
3021
	return FALSE;
3911
 
3022
 
3912
static cairo_bool_t
3023
    return _cairo_gradient_color_stops_equal (&a->base, &b->base);
3913
_cairo_surface_pattern_equal (const cairo_surface_pattern_t *a,
3024
}
3914
			      const cairo_surface_pattern_t *b)
3025
 
3915
{
Line 3059... Line 3949...
3059
	    return FALSE;
3949
	    return FALSE;
3060
    }
3950
    }
Line 3061... Line 3951...
3061
 
3951
 
3062
    switch (a->type) {
3952
    switch (a->type) {
-
 
3953
    case CAIRO_PATTERN_TYPE_SOLID:
3063
    case CAIRO_PATTERN_TYPE_SOLID:
3954
	return _cairo_solid_pattern_equal ((cairo_solid_pattern_t *) a,
3064
	return _cairo_solid_pattern_equal (a, b);
3955
					   (cairo_solid_pattern_t *) b);
3065
    case CAIRO_PATTERN_TYPE_LINEAR:
3956
    case CAIRO_PATTERN_TYPE_LINEAR:
3066
	return _cairo_linear_pattern_equal ((cairo_linear_pattern_t *) a,
3957
	return _cairo_linear_pattern_equal ((cairo_linear_pattern_t *) a,
3067
					    (cairo_linear_pattern_t *) b);
3958
					    (cairo_linear_pattern_t *) b);
3068
    case CAIRO_PATTERN_TYPE_RADIAL:
3959
    case CAIRO_PATTERN_TYPE_RADIAL:
3069
	return _cairo_radial_pattern_equal ((cairo_radial_pattern_t *) a,
3960
	return _cairo_radial_pattern_equal ((cairo_radial_pattern_t *) a,
-
 
3961
					    (cairo_radial_pattern_t *) b);
-
 
3962
    case CAIRO_PATTERN_TYPE_MESH:
-
 
3963
	return _cairo_mesh_pattern_equal ((cairo_mesh_pattern_t *) a,
3070
					    (cairo_radial_pattern_t *) b);
3964
					  (cairo_mesh_pattern_t *) b);
-
 
3965
    case CAIRO_PATTERN_TYPE_SURFACE:
3071
    case CAIRO_PATTERN_TYPE_SURFACE:
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,
3072
	return _cairo_surface_pattern_equal (a, b);
3970
						   (cairo_raster_source_pattern_t *) b);
3073
    default:
3971
    default:
3074
	ASSERT_NOT_REACHED;
3972
	ASSERT_NOT_REACHED;
3075
	return FALSE;
3973
	return FALSE;
3076
    }
3974
    }
Line 3077... Line 3975...
3077
}
3975
}
3078
 
3976
 
3079
/**
3977
/**
3080
 * cairo_pattern_get_rgba
3978
 * cairo_pattern_get_rgba:
3081
 * @pattern: a #cairo_pattern_t
3979
 * @pattern: a #cairo_pattern_t
3082
 * @red: return value for red component of color, or %NULL
3980
 * @red: return value for red component of color, or %NULL
3083
 * @green: return value for green component of color, or %NULL
3981
 * @green: return value for green component of color, or %NULL
Line 3119... Line 4017...
3119
 
4017
 
3120
    return CAIRO_STATUS_SUCCESS;
4018
    return CAIRO_STATUS_SUCCESS;
Line 3121... Line 4019...
3121
}
4019
}
3122
 
4020
 
3123
/**
4021
/**
3124
 * cairo_pattern_get_surface
4022
 * cairo_pattern_get_surface:
3125
 * @pattern: a #cairo_pattern_t
4023
 * @pattern: a #cairo_pattern_t
3126
 * @surface: return value for surface of pattern, or %NULL
4024
 * @surface: return value for surface of pattern, or %NULL
3127
 * 
4025
 * 
Line 3152... Line 4050...
3152
 
4050
 
3153
    return CAIRO_STATUS_SUCCESS;
4051
    return CAIRO_STATUS_SUCCESS;
Line 3154... Line 4052...
3154
}
4052
}
3155
 
4053
 
3156
/**
4054
/**
3157
 * cairo_pattern_get_color_stop_rgba
4055
 * cairo_pattern_get_color_stop_rgba:
3158
 * @pattern: a #cairo_pattern_t
4056
 * @pattern: a #cairo_pattern_t
3159
 * @index: index of the stop to return data for
4057
 * @index: index of the stop to return data for
3160
 * @offset: return value for the offset of the stop, or %NULL
4058
 * @offset: return value for the offset of the stop, or %NULL
Line 3205... Line 4103...
3205
 
4103
 
3206
    return CAIRO_STATUS_SUCCESS;
4104
    return CAIRO_STATUS_SUCCESS;
Line 3207... Line 4105...
3207
}
4105
}
3208
 
4106
 
3209
/**
4107
/**
3210
 * cairo_pattern_get_color_stop_count
4108
 * cairo_pattern_get_color_stop_count:
3211
 * @pattern: a #cairo_pattern_t
4109
 * @pattern: a #cairo_pattern_t
3212
 * @count: return value for the number of color stops, or %NULL
4110
 * @count: return value for the number of color stops, or %NULL
3213
 *
4111
 *
Line 3217... Line 4115...
3217
 * Return value: %CAIRO_STATUS_SUCCESS, or
4115
 * Return value: %CAIRO_STATUS_SUCCESS, or
3218
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
4116
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
3219
 * pattern.
4117
 * pattern.
3220
 *
4118
 *
3221
 * Since: 1.4
4119
 * Since: 1.4
3222
 */
4120
 **/
3223
cairo_status_t
4121
cairo_status_t
3224
cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
4122
cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
3225
				    int *count)
4123
				    int *count)
3226
{
4124
{
3227
    cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
4125
    cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
Line 3238... Line 4136...
3238
 
4136
 
3239
    return CAIRO_STATUS_SUCCESS;
4137
    return CAIRO_STATUS_SUCCESS;
Line 3240... Line 4138...
3240
}
4138
}
3241
 
4139
 
3242
/**
4140
/**
3243
 * cairo_pattern_get_linear_points
4141
 * cairo_pattern_get_linear_points:
3244
 * @pattern: a #cairo_pattern_t
4142
 * @pattern: a #cairo_pattern_t
3245
 * @x0: return value for the x coordinate of the first point, or %NULL
4143
 * @x0: return value for the x coordinate of the first point, or %NULL
3246
 * @y0: return value for the y coordinate of the first point, or %NULL
4144
 * @y0: return value for the y coordinate of the first point, or %NULL
Line 3267... Line 4165...
3267
 
4165
 
3268
    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR)
4166
    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR)
Line 3269... Line 4167...
3269
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4167
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
3270
 
4168
 
3271
    if (x0)
4169
    if (x0)
3272
	*x0 = _cairo_fixed_to_double (linear->p1.x);
4170
	*x0 = linear->pd1.x;
3273
    if (y0)
4171
    if (y0)
3274
	*y0 = _cairo_fixed_to_double (linear->p1.y);
4172
	*y0 = linear->pd1.y;
3275
    if (x1)
4173
    if (x1)
3276
	*x1 = _cairo_fixed_to_double (linear->p2.x);
4174
	*x1 = linear->pd2.x;
Line 3277... Line 4175...
3277
    if (y1)
4175
    if (y1)
3278
	*y1 = _cairo_fixed_to_double (linear->p2.y);
4176
	*y1 = linear->pd2.y;
Line 3279... Line 4177...
3279
 
4177
 
3280
    return CAIRO_STATUS_SUCCESS;
4178
    return CAIRO_STATUS_SUCCESS;
3281
}
4179
}
3282
 
4180
 
3283
/**
4181
/**
3284
 * cairo_pattern_get_radial_circles
4182
 * cairo_pattern_get_radial_circles:
3285
 * @pattern: a #cairo_pattern_t
4183
 * @pattern: a #cairo_pattern_t
Line 3311... Line 4209...
3311
 
4209
 
3312
    if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
4210
    if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
Line 3313... Line 4211...
3313
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
4211
	return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
3314
 
4212
 
3315
    if (x0)
4213
    if (x0)
3316
	*x0 = _cairo_fixed_to_double (radial->c1.x);
4214
	*x0 = radial->cd1.center.x;
3317
    if (y0)
4215
    if (y0)
3318
	*y0 = _cairo_fixed_to_double (radial->c1.y);
4216
	*y0 = radial->cd1.center.y;
3319
    if (r0)
4217
    if (r0)
3320
	*r0 = _cairo_fixed_to_double (radial->r1);
4218
	*r0 = radial->cd1.radius;
3321
    if (x1)
4219
    if (x1)
3322
	*x1 = _cairo_fixed_to_double (radial->c2.x);
4220
	*x1 = radial->cd2.center.x;
3323
    if (y1)
4221
    if (y1)
-
 
4222
	*y1 = radial->cd2.center.y;
-
 
4223
    if (r1)
-
 
4224
	*r1 = radial->cd2.radius;
-
 
4225
 
-
 
4226
    return CAIRO_STATUS_SUCCESS;
-
 
4227
}
-
 
4228
 
-
 
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);
3324
	*y1 = _cairo_fixed_to_double (radial->c2.y);
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;
Line 3325... Line 4482...
3325
    if (r1)
4482
    if (y)
3326
	*r1 = _cairo_fixed_to_double (radial->r2);
4483
	*y = patch->points[i][j].y;
-
 
4484
 
Line 3327... Line 4485...
3327
 
4485
    return CAIRO_STATUS_SUCCESS;
3328
    return CAIRO_STATUS_SUCCESS;
4486
}
3329
}
4487
slim_hidden_def (cairo_mesh_pattern_get_control_point);
3330
 
-
 
3331
void
4488
 
Line 3332... Line 4489...
3332
_cairo_pattern_reset_static_data (void)
4489
void
3333
{
4490
_cairo_pattern_reset_static_data (void)
3334
#if HAS_FREED_POOL
4491
{
Line -... Line 4492...
-
 
4492
    int i;
-
 
4493
 
-
 
4494
    for (i = 0; i < ARRAY_LENGTH (freed_pattern_pool); i++)
-
 
4495
	_freed_pool_reset (&freed_pattern_pool[i]);
-
 
4496
}
-
 
4497
 
-
 
4498
static void
-
 
4499
_cairo_debug_print_surface_pattern (FILE *file,
-
 
4500
				    const cairo_surface_pattern_t *pattern)
3335
    int i;
4501
{
-
 
4502
    printf ("  surface type: %d\n", pattern->surface->type);
-
 
4503
}
-
 
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:
3336
 
4585
	_cairo_debug_print_radial_pattern (file, (cairo_radial_pattern_t *)pattern);