~ubuntu-branches/ubuntu/karmic/moon/karmic

« back to all changes in this revision

Viewing changes to cairo/src/cairo-pattern.c

  • Committer: Bazaar Package Importer
  • Author(s): Jo Shields
  • Date: 2009-02-14 12:01:08 UTC
  • Revision ID: james.westby@ubuntu.com-20090214120108-06539vb25vhbd8bn
Tags: upstream-1.0
ImportĀ upstreamĀ versionĀ 1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
 
2
/* cairo - a vector graphics library with display and print output
 
3
 *
 
4
 * Copyright Ā© 2004 David Reveman
 
5
 * Copyright Ā© 2005 Red Hat, Inc.
 
6
 *
 
7
 * Permission to use, copy, modify, distribute, and sell this software
 
8
 * and its documentation for any purpose is hereby granted without
 
9
 * fee, provided that the above copyright notice appear in all copies
 
10
 * and that both that copyright notice and this permission notice
 
11
 * appear in supporting documentation, and that the name of David
 
12
 * Reveman not be used in advertising or publicity pertaining to
 
13
 * distribution of the software without specific, written prior
 
14
 * permission. David Reveman makes no representations about the
 
15
 * suitability of this software for any purpose.  It is provided "as
 
16
 * is" without express or implied warranty.
 
17
 *
 
18
 * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
 
19
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 
20
 * FITNESS, IN NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL,
 
21
 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
 
22
 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
 
23
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 
24
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
25
 *
 
26
 * Authors: David Reveman <davidr@novell.com>
 
27
 *          Keith Packard <keithp@keithp.com>
 
28
 *          Carl Worth <cworth@cworth.org>
 
29
 */
 
30
 
 
31
#include "cairoint.h"
 
32
 
 
33
const cairo_solid_pattern_t _cairo_pattern_nil = {
 
34
    { CAIRO_PATTERN_TYPE_SOLID,         /* type */
 
35
      CAIRO_REFERENCE_COUNT_INVALID,    /* ref_count */
 
36
      CAIRO_STATUS_NO_MEMORY,           /* status */
 
37
      { 0, 0, 0, NULL },                /* user_data */
 
38
      { 1., 0., 0., 1., 0., 0., },      /* matrix */
 
39
      CAIRO_FILTER_DEFAULT,             /* filter */
 
40
      CAIRO_EXTEND_GRADIENT_DEFAULT },  /* extend */
 
41
};
 
42
 
 
43
static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = {
 
44
    { CAIRO_PATTERN_TYPE_SOLID,         /* type */
 
45
      CAIRO_REFERENCE_COUNT_INVALID,    /* ref_count */
 
46
      CAIRO_STATUS_NULL_POINTER,        /* status */
 
47
      { 0, 0, 0, NULL },                /* user_data */
 
48
      { 1., 0., 0., 1., 0., 0., },      /* matrix */
 
49
      CAIRO_FILTER_DEFAULT,             /* filter */
 
50
      CAIRO_EXTEND_GRADIENT_DEFAULT },  /* extend */
 
51
};
 
52
 
 
53
const cairo_solid_pattern_t _cairo_pattern_none = {
 
54
    { CAIRO_PATTERN_TYPE_SOLID,         /* type */
 
55
      CAIRO_REFERENCE_COUNT_INVALID,    /* ref_count */
 
56
      CAIRO_STATUS_SUCCESS,             /* status */
 
57
      { 0, 0, 0, NULL },                /* user_data */
 
58
      { 1., 0., 0., 1., 0., 0., },      /* matrix */
 
59
      CAIRO_FILTER_DEFAULT,             /* filter */
 
60
      CAIRO_EXTEND_GRADIENT_DEFAULT },  /* extend */
 
61
};
 
62
 
 
63
/**
 
64
 * _cairo_pattern_set_error:
 
65
 * @pattern: a pattern
 
66
 * @status: a status value indicating an error
 
67
 *
 
68
 * Atomically sets pattern->status to @status and calls _cairo_error;
 
69
 * Does nothing if status is %CAIRO_STATUS_SUCCESS.
 
70
 *
 
71
 * All assignments of an error status to pattern->status should happen
 
72
 * through _cairo_pattern_set_error(). Note that due to the nature of
 
73
 * the atomic operation, it is not safe to call this function on the nil
 
74
 * objects.
 
75
 *
 
76
 * The purpose of this function is to allow the user to set a
 
77
 * breakpoint in _cairo_error() to generate a stack trace for when the
 
78
 * user causes cairo to detect an error.
 
79
 **/
 
80
static cairo_status_t
 
81
_cairo_pattern_set_error (cairo_pattern_t *pattern,
 
82
                          cairo_status_t status)
 
83
{
 
84
    if (status == CAIRO_STATUS_SUCCESS)
 
85
        return status;
 
86
 
 
87
    /* Don't overwrite an existing error. This preserves the first
 
88
     * error, which is the most significant. */
 
89
    _cairo_status_set_error (&pattern->status, status);
 
90
 
 
91
    return _cairo_error (status);
 
92
}
 
93
 
 
94
static void
 
95
_cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
 
96
{
 
97
    pattern->type      = type;
 
98
    pattern->status    = CAIRO_STATUS_SUCCESS;
 
99
 
 
100
    /* Set the reference count to zero for on-stack patterns.
 
101
     * Callers needs to explicitly increment the count for heap allocations. */
 
102
    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
 
103
 
 
104
    _cairo_user_data_array_init (&pattern->user_data);
 
105
 
 
106
    if (type == CAIRO_PATTERN_TYPE_SURFACE)
 
107
        pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
 
108
    else
 
109
        pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT;
 
110
 
 
111
    pattern->filter    = CAIRO_FILTER_DEFAULT;
 
112
 
 
113
    cairo_matrix_init_identity (&pattern->matrix);
 
114
}
 
115
 
 
116
static cairo_status_t
 
117
_cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t       *pattern,
 
118
                                   const cairo_gradient_pattern_t *other)
 
119
{
 
120
    if (other->base.type == CAIRO_PATTERN_TYPE_LINEAR)
 
121
    {
 
122
        cairo_linear_pattern_t *dst = (cairo_linear_pattern_t *) pattern;
 
123
        cairo_linear_pattern_t *src = (cairo_linear_pattern_t *) other;
 
124
 
 
125
        *dst = *src;
 
126
    }
 
127
    else
 
128
    {
 
129
        cairo_radial_pattern_t *dst = (cairo_radial_pattern_t *) pattern;
 
130
        cairo_radial_pattern_t *src = (cairo_radial_pattern_t *) other;
 
131
 
 
132
        *dst = *src;
 
133
    }
 
134
 
 
135
    if (other->stops == other->stops_embedded)
 
136
        pattern->stops = pattern->stops_embedded;
 
137
    else if (other->stops)
 
138
    {
 
139
        pattern->stops = _cairo_malloc_ab (other->stops_size,
 
140
                                           sizeof (cairo_gradient_stop_t));
 
141
        if (pattern->stops == NULL) {
 
142
            pattern->stops_size = 0;
 
143
            pattern->n_stops = 0;
 
144
            return _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
 
145
        }
 
146
 
 
147
        memcpy (pattern->stops, other->stops,
 
148
                other->n_stops * sizeof (cairo_gradient_stop_t));
 
149
    }
 
150
 
 
151
    return CAIRO_STATUS_SUCCESS;
 
152
}
 
153
 
 
154
cairo_status_t
 
155
_cairo_pattern_init_copy (cairo_pattern_t       *pattern,
 
156
                          const cairo_pattern_t *other)
 
157
{
 
158
    if (other->status)
 
159
        return _cairo_pattern_set_error (pattern, other->status);
 
160
 
 
161
    switch (other->type) {
 
162
    case CAIRO_PATTERN_TYPE_SOLID: {
 
163
        cairo_solid_pattern_t *dst = (cairo_solid_pattern_t *) pattern;
 
164
        cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) other;
 
165
 
 
166
        *dst = *src;
 
167
    } break;
 
168
    case CAIRO_PATTERN_TYPE_SURFACE: {
 
169
        cairo_surface_pattern_t *dst = (cairo_surface_pattern_t *) pattern;
 
170
        cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) other;
 
171
 
 
172
        *dst = *src;
 
173
        cairo_surface_reference (dst->surface);
 
174
    } break;
 
175
    case CAIRO_PATTERN_TYPE_LINEAR:
 
176
    case CAIRO_PATTERN_TYPE_RADIAL: {
 
177
        cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern;
 
178
        cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other;
 
179
        cairo_status_t status;
 
180
 
 
181
        status = _cairo_gradient_pattern_init_copy (dst, src);
 
182
        if (status)
 
183
            return status;
 
184
 
 
185
    } break;
 
186
    }
 
187
 
 
188
    /* The reference count and user_data array are unique to the copy. */
 
189
    CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
 
190
    _cairo_user_data_array_init (&pattern->user_data);
 
191
 
 
192
    return CAIRO_STATUS_SUCCESS;
 
193
}
 
194
 
 
195
cairo_status_t
 
196
_cairo_pattern_init_snapshot (cairo_pattern_t       *pattern,
 
197
                              const cairo_pattern_t *other)
 
198
{
 
199
    cairo_status_t status;
 
200
 
 
201
    /* We don't bother doing any fancy copy-on-write implementation
 
202
     * for the pattern's data. It's generally quite tiny. */
 
203
    status = _cairo_pattern_init_copy (pattern, other);
 
204
    if (status)
 
205
        return status;
 
206
 
 
207
    /* But we do let the surface snapshot stuff be as fancy as it
 
208
     * would like to be. */
 
209
    if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
 
210
        cairo_surface_pattern_t *surface_pattern =
 
211
            (cairo_surface_pattern_t *) pattern;
 
212
        cairo_surface_t *surface = surface_pattern->surface;
 
213
 
 
214
        surface_pattern->surface = _cairo_surface_snapshot (surface);
 
215
 
 
216
        cairo_surface_destroy (surface);
 
217
 
 
218
        if (surface_pattern->surface->status)
 
219
            return surface_pattern->surface->status;
 
220
    }
 
221
 
 
222
    return CAIRO_STATUS_SUCCESS;
 
223
}
 
224
 
 
225
void
 
226
_cairo_pattern_fini (cairo_pattern_t *pattern)
 
227
{
 
228
    _cairo_user_data_array_fini (&pattern->user_data);
 
229
 
 
230
    switch (pattern->type) {
 
231
    case CAIRO_PATTERN_TYPE_SOLID:
 
232
        break;
 
233
    case CAIRO_PATTERN_TYPE_SURFACE: {
 
234
        cairo_surface_pattern_t *surface_pattern =
 
235
            (cairo_surface_pattern_t *) pattern;
 
236
 
 
237
        cairo_surface_destroy (surface_pattern->surface);
 
238
    } break;
 
239
    case CAIRO_PATTERN_TYPE_LINEAR:
 
240
    case CAIRO_PATTERN_TYPE_RADIAL: {
 
241
        cairo_gradient_pattern_t *gradient =
 
242
            (cairo_gradient_pattern_t *) pattern;
 
243
 
 
244
        if (gradient->stops && gradient->stops != gradient->stops_embedded)
 
245
            free (gradient->stops);
 
246
    } break;
 
247
    }
 
248
}
 
249
 
 
250
cairo_status_t
 
251
_cairo_pattern_create_copy (cairo_pattern_t       **pattern,
 
252
                            const cairo_pattern_t  *other)
 
253
{
 
254
    cairo_status_t status;
 
255
 
 
256
    if (other->status)
 
257
        return other->status;
 
258
 
 
259
    switch (other->type) {
 
260
    case CAIRO_PATTERN_TYPE_SOLID:
 
261
        *pattern = malloc (sizeof (cairo_solid_pattern_t));
 
262
        break;
 
263
    case CAIRO_PATTERN_TYPE_SURFACE:
 
264
        *pattern = malloc (sizeof (cairo_surface_pattern_t));
 
265
        break;
 
266
    case CAIRO_PATTERN_TYPE_LINEAR:
 
267
        *pattern = malloc (sizeof (cairo_linear_pattern_t));
 
268
        break;
 
269
    case CAIRO_PATTERN_TYPE_RADIAL:
 
270
        *pattern = malloc (sizeof (cairo_radial_pattern_t));
 
271
        break;
 
272
    }
 
273
    if (*pattern == NULL)
 
274
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
275
 
 
276
    status = _cairo_pattern_init_copy (*pattern, other);
 
277
    if (status) {
 
278
        free (*pattern);
 
279
        return status;
 
280
    }
 
281
 
 
282
    CAIRO_REFERENCE_COUNT_INIT (&(*pattern)->ref_count, 1);
 
283
 
 
284
    return CAIRO_STATUS_SUCCESS;
 
285
}
 
286
 
 
287
 
 
288
void
 
289
_cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
 
290
                           const cairo_color_t   *color,
 
291
                           cairo_content_t        content)
 
292
{
 
293
    if (content == CAIRO_CONTENT_COLOR_ALPHA && CAIRO_COLOR_IS_OPAQUE (color))
 
294
        content = CAIRO_CONTENT_COLOR;
 
295
 
 
296
    _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
 
297
    pattern->color = *color;
 
298
    pattern->content = content;
 
299
}
 
300
 
 
301
void
 
302
_cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern,
 
303
                                 cairo_surface_t         *surface)
 
304
{
 
305
    if (surface->status) {
 
306
        /* Force to solid to simplify the pattern_fini process. */
 
307
        _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
 
308
        _cairo_pattern_set_error (&pattern->base, surface->status);
 
309
        return;
 
310
    }
 
311
 
 
312
    _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SURFACE);
 
313
 
 
314
    pattern->surface = cairo_surface_reference (surface);
 
315
}
 
316
 
 
317
static void
 
318
_cairo_pattern_init_gradient (cairo_gradient_pattern_t *pattern,
 
319
                              cairo_pattern_type_t     type)
 
320
{
 
321
    _cairo_pattern_init (&pattern->base, type);
 
322
 
 
323
    pattern->n_stops    = 0;
 
324
    pattern->stops_size = 0;
 
325
    pattern->stops      = NULL;
 
326
}
 
327
 
 
328
void
 
329
_cairo_pattern_init_linear (cairo_linear_pattern_t *pattern,
 
330
                            double x0, double y0, double x1, double y1)
 
331
{
 
332
    _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_LINEAR);
 
333
 
 
334
    pattern->p1.x = _cairo_fixed_from_double (x0);
 
335
    pattern->p1.y = _cairo_fixed_from_double (y0);
 
336
    pattern->p2.x = _cairo_fixed_from_double (x1);
 
337
    pattern->p2.y = _cairo_fixed_from_double (y1);
 
338
}
 
339
 
 
340
void
 
341
_cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
 
342
                            double cx0, double cy0, double radius0,
 
343
                            double cx1, double cy1, double radius1)
 
344
{
 
345
    _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL);
 
346
 
 
347
    pattern->c1.x = _cairo_fixed_from_double (cx0);
 
348
    pattern->c1.y = _cairo_fixed_from_double (cy0);
 
349
    pattern->r1   = _cairo_fixed_from_double (fabs (radius0));
 
350
    pattern->c2.x = _cairo_fixed_from_double (cx1);
 
351
    pattern->c2.y = _cairo_fixed_from_double (cy1);
 
352
    pattern->r2   = _cairo_fixed_from_double (fabs (radius1));
 
353
}
 
354
 
 
355
/* We use a small freed pattern cache here, because we don't want to
 
356
 * constantly reallocate simple colors. */
 
357
#define MAX_PATTERN_CACHE_SIZE 4
 
358
static struct {
 
359
    cairo_solid_pattern_t *patterns[MAX_PATTERN_CACHE_SIZE];
 
360
    int size;
 
361
} solid_pattern_cache;
 
362
 
 
363
cairo_pattern_t *
 
364
_cairo_pattern_create_solid (const cairo_color_t *color,
 
365
                             cairo_content_t      content)
 
366
{
 
367
    cairo_solid_pattern_t *pattern = NULL;
 
368
 
 
369
    CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
 
370
 
 
371
    if (solid_pattern_cache.size) {
 
372
        int i = --solid_pattern_cache.size %
 
373
            ARRAY_LENGTH (solid_pattern_cache.patterns);
 
374
        pattern = solid_pattern_cache.patterns[i];
 
375
        solid_pattern_cache.patterns[i] = NULL;
 
376
    }
 
377
 
 
378
    CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock);
 
379
 
 
380
    if (pattern == NULL) {
 
381
        /* None cached, need to create a new pattern. */
 
382
        pattern = malloc (sizeof (cairo_solid_pattern_t));
 
383
    }
 
384
 
 
385
    if (pattern == NULL) {
 
386
        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 
387
        pattern = (cairo_solid_pattern_t *) &_cairo_pattern_nil;
 
388
    } else {
 
389
        _cairo_pattern_init_solid (pattern, color, content);
 
390
        CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
 
391
    }
 
392
 
 
393
    return &pattern->base;
 
394
}
 
395
 
 
396
static void
 
397
_cairo_pattern_reset_solid_pattern_cache (void)
 
398
{
 
399
    int i;
 
400
 
 
401
    CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
 
402
 
 
403
    for (i = 0; i < MIN (ARRAY_LENGTH (solid_pattern_cache.patterns), solid_pattern_cache.size); i++) {
 
404
        if (solid_pattern_cache.patterns[i])
 
405
            free (solid_pattern_cache.patterns[i]);
 
406
        solid_pattern_cache.patterns[i] = NULL;
 
407
    }
 
408
    solid_pattern_cache.size = 0;
 
409
 
 
410
    CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock);
 
411
}
 
412
 
 
413
static const cairo_pattern_t *
 
414
_cairo_pattern_create_in_error (cairo_status_t status)
 
415
{
 
416
    cairo_pattern_t *pattern;
 
417
 
 
418
    if (status == CAIRO_STATUS_NO_MEMORY)
 
419
        return (cairo_pattern_t *)&_cairo_pattern_nil.base;
 
420
 
 
421
    CAIRO_MUTEX_INITIALIZE ();
 
422
 
 
423
    pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK, CAIRO_CONTENT_COLOR);
 
424
    if (pattern->status == CAIRO_STATUS_SUCCESS)
 
425
        status = _cairo_pattern_set_error (pattern, status);
 
426
 
 
427
    return pattern;
 
428
}
 
429
 
 
430
/**
 
431
 * cairo_pattern_create_rgb:
 
432
 * @red: red component of the color
 
433
 * @green: green component of the color
 
434
 * @blue: blue component of the color
 
435
 *
 
436
 * Creates a new #cairo_pattern_t corresponding to an opaque color.  The
 
437
 * color components are floating point numbers in the range 0 to 1.
 
438
 * If the values passed in are outside that range, they will be
 
439
 * clamped.
 
440
 *
 
441
 * Return value: the newly created #cairo_pattern_t if successful, or
 
442
 * an error pattern in case of no memory.  The caller owns the
 
443
 * returned object and should call cairo_pattern_destroy() when
 
444
 * finished with it.
 
445
 *
 
446
 * This function will always return a valid pointer, but if an error
 
447
 * occurred the pattern status will be set to an error.  To inspect
 
448
 * the status of a pattern use cairo_pattern_status().
 
449
 **/
 
450
cairo_pattern_t *
 
451
cairo_pattern_create_rgb (double red, double green, double blue)
 
452
{
 
453
    cairo_color_t color;
 
454
 
 
455
    _cairo_restrict_value (&red,   0.0, 1.0);
 
456
    _cairo_restrict_value (&green, 0.0, 1.0);
 
457
    _cairo_restrict_value (&blue,  0.0, 1.0);
 
458
 
 
459
    _cairo_color_init_rgb (&color, red, green, blue);
 
460
 
 
461
    CAIRO_MUTEX_INITIALIZE ();
 
462
 
 
463
    return _cairo_pattern_create_solid (&color, CAIRO_CONTENT_COLOR);
 
464
}
 
465
slim_hidden_def (cairo_pattern_create_rgb);
 
466
 
 
467
/**
 
468
 * cairo_pattern_create_rgba:
 
469
 * @red: red component of the color
 
470
 * @green: green component of the color
 
471
 * @blue: blue component of the color
 
472
 * @alpha: alpha component of the color
 
473
 *
 
474
 * Creates a new #cairo_pattern_t corresponding to a translucent color.
 
475
 * The color components are floating point numbers in the range 0 to
 
476
 * 1.  If the values passed in are outside that range, they will be
 
477
 * clamped.
 
478
 *
 
479
 * Return value: the newly created #cairo_pattern_t if successful, or
 
480
 * an error pattern in case of no memory.  The caller owns the
 
481
 * returned object and should call cairo_pattern_destroy() when
 
482
 * finished with it.
 
483
 *
 
484
 * This function will always return a valid pointer, but if an error
 
485
 * occurred the pattern status will be set to an error.  To inspect
 
486
 * the status of a pattern use cairo_pattern_status().
 
487
 **/
 
488
cairo_pattern_t *
 
489
cairo_pattern_create_rgba (double red, double green, double blue,
 
490
                           double alpha)
 
491
{
 
492
    cairo_color_t color;
 
493
 
 
494
    _cairo_restrict_value (&red,   0.0, 1.0);
 
495
    _cairo_restrict_value (&green, 0.0, 1.0);
 
496
    _cairo_restrict_value (&blue,  0.0, 1.0);
 
497
    _cairo_restrict_value (&alpha, 0.0, 1.0);
 
498
 
 
499
    _cairo_color_init_rgba (&color, red, green, blue, alpha);
 
500
 
 
501
    CAIRO_MUTEX_INITIALIZE ();
 
502
 
 
503
    return _cairo_pattern_create_solid (&color, CAIRO_CONTENT_COLOR_ALPHA);
 
504
}
 
505
slim_hidden_def (cairo_pattern_create_rgba);
 
506
 
 
507
/**
 
508
 * cairo_pattern_create_for_surface:
 
509
 * @surface: the surface
 
510
 *
 
511
 * Create a new #cairo_pattern_t for the given surface.
 
512
 *
 
513
 * Return value: the newly created #cairo_pattern_t if successful, or
 
514
 * an error pattern in case of no memory.  The caller owns the
 
515
 * returned object and should call cairo_pattern_destroy() when
 
516
 * finished with it.
 
517
 *
 
518
 * This function will always return a valid pointer, but if an error
 
519
 * occurred the pattern status will be set to an error.  To inspect
 
520
 * the status of a pattern use cairo_pattern_status().
 
521
 **/
 
522
cairo_pattern_t *
 
523
cairo_pattern_create_for_surface (cairo_surface_t *surface)
 
524
{
 
525
    cairo_surface_pattern_t *pattern;
 
526
 
 
527
    if (surface == NULL) {
 
528
        _cairo_error_throw (CAIRO_STATUS_NULL_POINTER);
 
529
        return (cairo_pattern_t*) &_cairo_pattern_nil_null_pointer;
 
530
    }
 
531
 
 
532
    if (surface->status)
 
533
        return (cairo_pattern_t*) _cairo_pattern_create_in_error (surface->status);
 
534
 
 
535
    pattern = malloc (sizeof (cairo_surface_pattern_t));
 
536
    if (pattern == NULL) {
 
537
        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 
538
        return (cairo_pattern_t *)&_cairo_pattern_nil.base;
 
539
    }
 
540
 
 
541
    CAIRO_MUTEX_INITIALIZE ();
 
542
 
 
543
    _cairo_pattern_init_for_surface (pattern, surface);
 
544
    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
 
545
 
 
546
    return &pattern->base;
 
547
}
 
548
slim_hidden_def (cairo_pattern_create_for_surface);
 
549
 
 
550
/**
 
551
 * cairo_pattern_create_linear:
 
552
 * @x0: x coordinate of the start point
 
553
 * @y0: y coordinate of the start point
 
554
 * @x1: x coordinate of the end point
 
555
 * @y1: y coordinate of the end point
 
556
 *
 
557
 * Create a new linear gradient #cairo_pattern_t along the line defined
 
558
 * by (x0, y0) and (x1, y1).  Before using the gradient pattern, a
 
559
 * number of color stops should be defined using
 
560
 * cairo_pattern_add_color_stop_rgb() or
 
561
 * cairo_pattern_add_color_stop_rgba().
 
562
 *
 
563
 * Note: The coordinates here are in pattern space. For a new pattern,
 
564
 * pattern space is identical to user space, but the relationship
 
565
 * between the spaces can be changed with cairo_pattern_set_matrix().
 
566
 *
 
567
 * Return value: the newly created #cairo_pattern_t if successful, or
 
568
 * an error pattern in case of no memory.  The caller owns the
 
569
 * returned object and should call cairo_pattern_destroy() when
 
570
 * finished with it.
 
571
 *
 
572
 * This function will always return a valid pointer, but if an error
 
573
 * occurred the pattern status will be set to an error.  To inspect
 
574
 * the status of a pattern use cairo_pattern_status().
 
575
 **/
 
576
cairo_pattern_t *
 
577
cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
 
578
{
 
579
    cairo_linear_pattern_t *pattern;
 
580
 
 
581
    pattern = malloc (sizeof (cairo_linear_pattern_t));
 
582
    if (pattern == NULL) {
 
583
        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 
584
        return (cairo_pattern_t *) &_cairo_pattern_nil.base;
 
585
    }
 
586
 
 
587
    CAIRO_MUTEX_INITIALIZE ();
 
588
 
 
589
    _cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
 
590
    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
 
591
 
 
592
    return &pattern->base.base;
 
593
}
 
594
 
 
595
/**
 
596
 * cairo_pattern_create_radial:
 
597
 * @cx0: x coordinate for the center of the start circle
 
598
 * @cy0: y coordinate for the center of the start circle
 
599
 * @radius0: radius of the start circle
 
600
 * @cx1: x coordinate for the center of the end circle
 
601
 * @cy1: y coordinate for the center of the end circle
 
602
 * @radius1: radius of the end circle
 
603
 *
 
604
 * Creates a new radial gradient #cairo_pattern_t between the two
 
605
 * circles defined by (cx0, cy0, radius0) and (cx1, cy1, radius1).  Before using the
 
606
 * gradient pattern, a number of color stops should be defined using
 
607
 * cairo_pattern_add_color_stop_rgb() or
 
608
 * cairo_pattern_add_color_stop_rgba().
 
609
 *
 
610
 * Note: The coordinates here are in pattern space. For a new pattern,
 
611
 * pattern space is identical to user space, but the relationship
 
612
 * between the spaces can be changed with cairo_pattern_set_matrix().
 
613
 *
 
614
 * Return value: the newly created #cairo_pattern_t if successful, or
 
615
 * an error pattern in case of no memory.  The caller owns the
 
616
 * returned object and should call cairo_pattern_destroy() when
 
617
 * finished with it.
 
618
 *
 
619
 * This function will always return a valid pointer, but if an error
 
620
 * occurred the pattern status will be set to an error.  To inspect
 
621
 * the status of a pattern use cairo_pattern_status().
 
622
 **/
 
623
cairo_pattern_t *
 
624
cairo_pattern_create_radial (double cx0, double cy0, double radius0,
 
625
                             double cx1, double cy1, double radius1)
 
626
{
 
627
    cairo_radial_pattern_t *pattern;
 
628
 
 
629
    pattern = malloc (sizeof (cairo_radial_pattern_t));
 
630
    if (pattern == NULL) {
 
631
        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
 
632
        return (cairo_pattern_t *) &_cairo_pattern_nil.base;
 
633
    }
 
634
 
 
635
    CAIRO_MUTEX_INITIALIZE ();
 
636
 
 
637
    _cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
 
638
    CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
 
639
 
 
640
    return &pattern->base.base;
 
641
}
 
642
 
 
643
/**
 
644
 * cairo_pattern_reference:
 
645
 * @pattern: a #cairo_pattern_t
 
646
 *
 
647
 * Increases the reference count on @pattern by one. This prevents
 
648
 * @pattern from being destroyed until a matching call to
 
649
 * cairo_pattern_destroy() is made.
 
650
 *
 
651
 * The number of references to a #cairo_pattern_t can be get using
 
652
 * cairo_pattern_get_reference_count().
 
653
 *
 
654
 * Return value: the referenced #cairo_pattern_t.
 
655
 **/
 
656
cairo_pattern_t *
 
657
cairo_pattern_reference (cairo_pattern_t *pattern)
 
658
{
 
659
    if (pattern == NULL ||
 
660
            CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
 
661
        return pattern;
 
662
 
 
663
    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
 
664
 
 
665
    _cairo_reference_count_inc (&pattern->ref_count);
 
666
 
 
667
    return pattern;
 
668
}
 
669
slim_hidden_def (cairo_pattern_reference);
 
670
 
 
671
/**
 
672
 * cairo_pattern_get_type:
 
673
 * @pattern: a #cairo_pattern_t
 
674
 *
 
675
 * This function returns the type a pattern.
 
676
 * See #cairo_pattern_type_t for available types.
 
677
 *
 
678
 * Return value: The type of @pattern.
 
679
 *
 
680
 * Since: 1.2
 
681
 **/
 
682
cairo_pattern_type_t
 
683
cairo_pattern_get_type (cairo_pattern_t *pattern)
 
684
{
 
685
    return pattern->type;
 
686
}
 
687
slim_hidden_def (cairo_pattern_get_type);
 
688
 
 
689
/**
 
690
 * cairo_pattern_status:
 
691
 * @pattern: a #cairo_pattern_t
 
692
 *
 
693
 * Checks whether an error has previously occurred for this
 
694
 * pattern.
 
695
 *
 
696
 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NO_MEMORY, or
 
697
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
 
698
 **/
 
699
cairo_status_t
 
700
cairo_pattern_status (cairo_pattern_t *pattern)
 
701
{
 
702
    return pattern->status;
 
703
}
 
704
slim_hidden_def (cairo_pattern_status);
 
705
 
 
706
/**
 
707
 * cairo_pattern_destroy:
 
708
 * @pattern: a #cairo_pattern_t
 
709
 *
 
710
 * Decreases the reference count on @pattern by one. If the result is
 
711
 * zero, then @pattern and all associated resources are freed.  See
 
712
 * cairo_pattern_reference().
 
713
 **/
 
714
void
 
715
cairo_pattern_destroy (cairo_pattern_t *pattern)
 
716
{
 
717
    if (pattern == NULL ||
 
718
            CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
 
719
        return;
 
720
 
 
721
    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
 
722
 
 
723
    if (! _cairo_reference_count_dec_and_test (&pattern->ref_count))
 
724
        return;
 
725
 
 
726
    _cairo_pattern_fini (pattern);
 
727
 
 
728
    /* maintain a small cache of freed patterns */
 
729
    if (pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
 
730
        int i;
 
731
 
 
732
        CAIRO_MUTEX_LOCK (_cairo_pattern_solid_pattern_cache_lock);
 
733
 
 
734
        i = solid_pattern_cache.size++ %
 
735
            ARRAY_LENGTH (solid_pattern_cache.patterns);
 
736
        /* swap an old pattern for this 'cache-hot' pattern */
 
737
        if (solid_pattern_cache.patterns[i])
 
738
            free (solid_pattern_cache.patterns[i]);
 
739
 
 
740
        solid_pattern_cache.patterns[i] = (cairo_solid_pattern_t *) pattern;
 
741
 
 
742
        CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_pattern_cache_lock);
 
743
    } else {
 
744
        free (pattern);
 
745
    }
 
746
}
 
747
slim_hidden_def (cairo_pattern_destroy);
 
748
 
 
749
/**
 
750
 * cairo_pattern_get_reference_count:
 
751
 * @pattern: a #cairo_pattern_t
 
752
 *
 
753
 * Returns the current reference count of @pattern.
 
754
 *
 
755
 * Return value: the current reference count of @pattern.  If the
 
756
 * object is a nil object, 0 will be returned.
 
757
 *
 
758
 * Since: 1.4
 
759
 **/
 
760
unsigned int
 
761
cairo_pattern_get_reference_count (cairo_pattern_t *pattern)
 
762
{
 
763
    if (pattern == NULL ||
 
764
            CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
 
765
        return 0;
 
766
 
 
767
    return CAIRO_REFERENCE_COUNT_GET_VALUE (&pattern->ref_count);
 
768
}
 
769
 
 
770
/**
 
771
 * cairo_pattern_get_user_data:
 
772
 * @pattern: a #cairo_pattern_t
 
773
 * @key: the address of the #cairo_user_data_key_t the user data was
 
774
 * attached to
 
775
 *
 
776
 * Return user data previously attached to @pattern using the
 
777
 * specified key.  If no user data has been attached with the given
 
778
 * key this function returns %NULL.
 
779
 *
 
780
 * Return value: the user data previously attached or %NULL.
 
781
 *
 
782
 * Since: 1.4
 
783
 **/
 
784
void *
 
785
cairo_pattern_get_user_data (cairo_pattern_t             *pattern,
 
786
                             const cairo_user_data_key_t *key)
 
787
{
 
788
    return _cairo_user_data_array_get_data (&pattern->user_data,
 
789
                                            key);
 
790
}
 
791
 
 
792
/**
 
793
 * cairo_pattern_set_user_data:
 
794
 * @pattern: a #cairo_pattern_t
 
795
 * @key: the address of a #cairo_user_data_key_t to attach the user data to
 
796
 * @user_data: the user data to attach to the #cairo_pattern_t
 
797
 * @destroy: a #cairo_destroy_func_t which will be called when the
 
798
 * #cairo_t is destroyed or when new user data is attached using the
 
799
 * same key.
 
800
 *
 
801
 * Attach user data to @pattern.  To remove user data from a surface,
 
802
 * call this function with the key that was used to set it and %NULL
 
803
 * for @data.
 
804
 *
 
805
 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
 
806
 * slot could not be allocated for the user data.
 
807
 *
 
808
 * Since: 1.4
 
809
 **/
 
810
cairo_status_t
 
811
cairo_pattern_set_user_data (cairo_pattern_t             *pattern,
 
812
                             const cairo_user_data_key_t *key,
 
813
                             void                        *user_data,
 
814
                             cairo_destroy_func_t         destroy)
 
815
{
 
816
    if (CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
 
817
        return pattern->status;
 
818
 
 
819
    return _cairo_user_data_array_set_data (&pattern->user_data,
 
820
                                            key, user_data, destroy);
 
821
}
 
822
 
 
823
/* make room for at least one more color stop */
 
824
static cairo_status_t
 
825
_cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
 
826
{
 
827
    cairo_gradient_stop_t *new_stops;
 
828
    int old_size = pattern->stops_size;
 
829
    int embedded_size = ARRAY_LENGTH (pattern->stops_embedded);
 
830
    int new_size = 2 * MAX (old_size, 4);
 
831
 
 
832
    /* we have a local buffer at pattern->stops_embedded.  try to fulfill the request
 
833
     * from there. */
 
834
    if (old_size < embedded_size) {
 
835
        pattern->stops = pattern->stops_embedded;
 
836
        pattern->stops_size = embedded_size;
 
837
        return CAIRO_STATUS_SUCCESS;
 
838
    }
 
839
 
 
840
    assert (pattern->n_stops <= pattern->stops_size);
 
841
 
 
842
    if (pattern->stops == pattern->stops_embedded) {
 
843
        new_stops = _cairo_malloc_ab (new_size, sizeof (cairo_gradient_stop_t));
 
844
        if (new_stops)
 
845
            memcpy (new_stops, pattern->stops, old_size * sizeof (cairo_gradient_stop_t));
 
846
    } else {
 
847
        new_stops = _cairo_realloc_ab (pattern->stops,
 
848
                                       new_size,
 
849
                                       sizeof (cairo_gradient_stop_t));
 
850
    }
 
851
 
 
852
    if (new_stops == NULL)
 
853
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
854
 
 
855
    pattern->stops = new_stops;
 
856
    pattern->stops_size = new_size;
 
857
 
 
858
    return CAIRO_STATUS_SUCCESS;
 
859
}
 
860
 
 
861
static void
 
862
_cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
 
863
                               double                    offset,
 
864
                               double                    red,
 
865
                               double                    green,
 
866
                               double                    blue,
 
867
                               double                    alpha)
 
868
{
 
869
    cairo_gradient_stop_t *stops;
 
870
    unsigned int           i;
 
871
 
 
872
    if (pattern->n_stops >= pattern->stops_size) {
 
873
        cairo_status_t status = _cairo_pattern_gradient_grow (pattern);
 
874
        if (status) {
 
875
            status = _cairo_pattern_set_error (&pattern->base, status);
 
876
            return;
 
877
        }
 
878
    }
 
879
 
 
880
    stops = pattern->stops;
 
881
 
 
882
    for (i = 0; i < pattern->n_stops; i++)
 
883
    {
 
884
        if (offset < stops[i].offset)
 
885
        {
 
886
            memmove (&stops[i + 1], &stops[i],
 
887
                     sizeof (cairo_gradient_stop_t) * (pattern->n_stops - i));
 
888
 
 
889
            break;
 
890
        }
 
891
    }
 
892
 
 
893
    stops[i].offset = offset;
 
894
 
 
895
    stops[i].color.red   = red;
 
896
    stops[i].color.green = green;
 
897
    stops[i].color.blue  = blue;
 
898
    stops[i].color.alpha = alpha;
 
899
 
 
900
    stops[i].color.red_short   = _cairo_color_double_to_short (red);
 
901
    stops[i].color.green_short = _cairo_color_double_to_short (green);
 
902
    stops[i].color.blue_short  = _cairo_color_double_to_short (blue);
 
903
    stops[i].color.alpha_short = _cairo_color_double_to_short (alpha);
 
904
 
 
905
    pattern->n_stops++;
 
906
}
 
907
 
 
908
/**
 
909
 * cairo_pattern_add_color_stop_rgb:
 
910
 * @pattern: a #cairo_pattern_t
 
911
 * @offset: an offset in the range [0.0 .. 1.0]
 
912
 * @red: red component of color
 
913
 * @green: green component of color
 
914
 * @blue: blue component of color
 
915
 *
 
916
 * Adds an opaque color stop to a gradient pattern. The offset
 
917
 * specifies the location along the gradient's control vector. For
 
918
 * example, a linear gradient's control vector is from (x0,y0) to
 
919
 * (x1,y1) while a radial gradient's control vector is from any point
 
920
 * on the start circle to the corresponding point on the end circle.
 
921
 *
 
922
 * The color is specified in the same way as in cairo_set_source_rgb().
 
923
 *
 
924
 * If two (or more) stops are specified with identical offset values,
 
925
 * they will be sorted according to the order in which the stops are
 
926
 * added, (stops added earlier will compare less than stops added
 
927
 * later). This can be useful for reliably making sharp color
 
928
 * transitions instead of the typical blend.
 
929
 *
 
930
 *
 
931
 * Note: If the pattern is not a gradient pattern, (eg. a linear or
 
932
 * radial pattern), then the pattern will be put into an error status
 
933
 * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
 
934
 **/
 
935
void
 
936
cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
 
937
                                  double           offset,
 
938
                                  double           red,
 
939
                                  double           green,
 
940
                                  double           blue)
 
941
{
 
942
    if (pattern->status)
 
943
        return;
 
944
 
 
945
    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
 
946
        pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
 
947
    {
 
948
        _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
 
949
        return;
 
950
    }
 
951
 
 
952
    _cairo_restrict_value (&offset, 0.0, 1.0);
 
953
    _cairo_restrict_value (&red,    0.0, 1.0);
 
954
    _cairo_restrict_value (&green,  0.0, 1.0);
 
955
    _cairo_restrict_value (&blue,   0.0, 1.0);
 
956
 
 
957
    _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
 
958
                                   offset, red, green, blue, 1.0);
 
959
}
 
960
 
 
961
/**
 
962
 * cairo_pattern_add_color_stop_rgba:
 
963
 * @pattern: a #cairo_pattern_t
 
964
 * @offset: an offset in the range [0.0 .. 1.0]
 
965
 * @red: red component of color
 
966
 * @green: green component of color
 
967
 * @blue: blue component of color
 
968
 * @alpha: alpha component of color
 
969
 *
 
970
 * Adds a translucent color stop to a gradient pattern. The offset
 
971
 * specifies the location along the gradient's control vector. For
 
972
 * example, a linear gradient's control vector is from (x0,y0) to
 
973
 * (x1,y1) while a radial gradient's control vector is from any point
 
974
 * on the start circle to the corresponding point on the end circle.
 
975
 *
 
976
 * The color is specified in the same way as in cairo_set_source_rgba().
 
977
 *
 
978
 * If two (or more) stops are specified with identical offset values,
 
979
 * they will be sorted according to the order in which the stops are
 
980
 * added, (stops added earlier will compare less than stops added
 
981
 * later). This can be useful for reliably making sharp color
 
982
 * transitions instead of the typical blend.
 
983
 *
 
984
 * Note: If the pattern is not a gradient pattern, (eg. a linear or
 
985
 * radial pattern), then the pattern will be put into an error status
 
986
 * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
 
987
 */
 
988
void
 
989
cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
 
990
                                   double          offset,
 
991
                                   double          red,
 
992
                                   double          green,
 
993
                                   double          blue,
 
994
                                   double          alpha)
 
995
{
 
996
    if (pattern->status)
 
997
        return;
 
998
 
 
999
    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
 
1000
        pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
 
1001
    {
 
1002
        _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
 
1003
        return;
 
1004
    }
 
1005
 
 
1006
    _cairo_restrict_value (&offset, 0.0, 1.0);
 
1007
    _cairo_restrict_value (&red,    0.0, 1.0);
 
1008
    _cairo_restrict_value (&green,  0.0, 1.0);
 
1009
    _cairo_restrict_value (&blue,   0.0, 1.0);
 
1010
    _cairo_restrict_value (&alpha,  0.0, 1.0);
 
1011
 
 
1012
    _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
 
1013
                                   offset, red, green, blue, alpha);
 
1014
}
 
1015
 
 
1016
/**
 
1017
 * cairo_pattern_set_matrix:
 
1018
 * @pattern: a #cairo_pattern_t
 
1019
 * @matrix: a #cairo_matrix_t
 
1020
 *
 
1021
 * Sets the pattern's transformation matrix to @matrix. This matrix is
 
1022
 * a transformation from user space to pattern space.
 
1023
 *
 
1024
 * When a pattern is first created it always has the identity matrix
 
1025
 * for its transformation matrix, which means that pattern space is
 
1026
 * initially identical to user space.
 
1027
 *
 
1028
 * Important: Please note that the direction of this transformation
 
1029
 * matrix is from user space to pattern space. This means that if you
 
1030
 * imagine the flow from a pattern to user space (and on to device
 
1031
 * space), then coordinates in that flow will be transformed by the
 
1032
 * inverse of the pattern matrix.
 
1033
 *
 
1034
 * For example, if you want to make a pattern appear twice as large as
 
1035
 * it does by default the correct code to use is:
 
1036
 *
 
1037
 * <informalexample><programlisting>
 
1038
 * cairo_matrix_init_scale (&amp;matrix, 0.5, 0.5);
 
1039
 * cairo_pattern_set_matrix (pattern, &amp;matrix);
 
1040
 * </programlisting></informalexample>
 
1041
 *
 
1042
 * Meanwhile, using values of 2.0 rather than 0.5 in the code above
 
1043
 * would cause the pattern to appear at half of its default size.
 
1044
 *
 
1045
 * Also, please note the discussion of the user-space locking
 
1046
 * semantics of cairo_set_source().
 
1047
 **/
 
1048
void
 
1049
cairo_pattern_set_matrix (cairo_pattern_t      *pattern,
 
1050
                          const cairo_matrix_t *matrix)
 
1051
{
 
1052
    cairo_matrix_t inverse;
 
1053
    cairo_status_t status;
 
1054
 
 
1055
    if (pattern->status)
 
1056
        return;
 
1057
 
 
1058
    pattern->matrix = *matrix;
 
1059
 
 
1060
    inverse = *matrix;
 
1061
    status = cairo_matrix_invert (&inverse);
 
1062
    if (status)
 
1063
        status = _cairo_pattern_set_error (pattern, status);
 
1064
}
 
1065
slim_hidden_def (cairo_pattern_set_matrix);
 
1066
 
 
1067
/**
 
1068
 * cairo_pattern_get_matrix:
 
1069
 * @pattern: a #cairo_pattern_t
 
1070
 * @matrix: return value for the matrix
 
1071
 *
 
1072
 * Stores the pattern's transformation matrix into @matrix.
 
1073
 **/
 
1074
void
 
1075
cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
 
1076
{
 
1077
    *matrix = pattern->matrix;
 
1078
}
 
1079
 
 
1080
/**
 
1081
 * cairo_pattern_set_filter:
 
1082
 * @pattern: a #cairo_pattern_t
 
1083
 * @filter: a #cairo_filter_t describing the filter to use for resizing
 
1084
 * the pattern
 
1085
 *
 
1086
 * Sets the filter to be used for resizing when using this pattern.
 
1087
 * See #cairo_filter_t for details on each filter.
 
1088
 *
 
1089
 * * Note that you might want to control filtering even when you do not
 
1090
 * have an explicit #cairo_pattern_t object, (for example when using
 
1091
 * cairo_set_source_surface()). In these cases, it is convenient to
 
1092
 * use cairo_get_source() to get access to the pattern that cairo
 
1093
 * creates implicitly. For example:
 
1094
 *
 
1095
 * <informalexample><programlisting>
 
1096
 * cairo_set_source_surface (cr, image, x, y);
 
1097
 * cairo_pattern_set_filter (cairo_get_source (cr), %CAIRO_FILTER_NEAREST);
 
1098
 * </programlisting></informalexample>
 
1099
 **/
 
1100
void
 
1101
cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
 
1102
{
 
1103
    if (pattern->status)
 
1104
        return;
 
1105
 
 
1106
    pattern->filter = filter;
 
1107
}
 
1108
 
 
1109
/**
 
1110
 * cairo_pattern_get_filter:
 
1111
 * @pattern: a #cairo_pattern_t
 
1112
 *
 
1113
 * Gets the current filter for a pattern.  See #cairo_filter_t
 
1114
 * for details on each filter.
 
1115
 *
 
1116
 * Return value: the current filter used for resizing the pattern.
 
1117
 **/
 
1118
cairo_filter_t
 
1119
cairo_pattern_get_filter (cairo_pattern_t *pattern)
 
1120
{
 
1121
    return pattern->filter;
 
1122
}
 
1123
 
 
1124
/**
 
1125
 * cairo_pattern_set_extend:
 
1126
 * @pattern: a #cairo_pattern_t
 
1127
 * @extend: a #cairo_extend_t describing how the area outside of the
 
1128
 * pattern will be drawn
 
1129
 *
 
1130
 * Sets the mode to be used for drawing outside the area of a pattern.
 
1131
 * See #cairo_extend_t for details on the semantics of each extend
 
1132
 * strategy.
 
1133
 *
 
1134
 * The default extend mode is %CAIRO_EXTEND_NONE for surface patterns
 
1135
 * and %CAIRO_EXTEND_PAD for gradient patterns.
 
1136
 **/
 
1137
void
 
1138
cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
 
1139
{
 
1140
    if (pattern->status)
 
1141
        return;
 
1142
 
 
1143
    pattern->extend = extend;
 
1144
}
 
1145
 
 
1146
/**
 
1147
 * cairo_pattern_get_extend:
 
1148
 * @pattern: a #cairo_pattern_t
 
1149
 *
 
1150
 * Gets the current extend mode for a pattern.  See #cairo_extend_t
 
1151
 * for details on the semantics of each extend strategy.
 
1152
 *
 
1153
 * Return value: the current extend strategy used for drawing the
 
1154
 * pattern.
 
1155
 **/
 
1156
cairo_extend_t
 
1157
cairo_pattern_get_extend (cairo_pattern_t *pattern)
 
1158
{
 
1159
    return pattern->extend;
 
1160
}
 
1161
slim_hidden_def (cairo_pattern_get_extend);
 
1162
 
 
1163
void
 
1164
_cairo_pattern_transform (cairo_pattern_t       *pattern,
 
1165
                          const cairo_matrix_t  *ctm_inverse)
 
1166
{
 
1167
    if (pattern->status)
 
1168
        return;
 
1169
 
 
1170
    cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
 
1171
}
 
1172
 
 
1173
static void
 
1174
_cairo_linear_pattern_classify (cairo_linear_pattern_t *pattern,
 
1175
                                double                 offset_x,
 
1176
                                double                 offset_y,
 
1177
                                int                    width,
 
1178
                                int                    height,
 
1179
                                cairo_bool_t           *is_horizontal,
 
1180
                                cairo_bool_t           *is_vertical)
 
1181
{
 
1182
    cairo_point_double_t point0, point1;
 
1183
    double a, b, c, d, tx, ty;
 
1184
    double scale, start, dx, dy;
 
1185
    cairo_fixed_t factors[3];
 
1186
    int i;
 
1187
 
 
1188
    /* To classify a pattern as horizontal or vertical, we first
 
1189
     * compute the (fixed point) factors at the corners of the
 
1190
     * pattern. We actually only need 3/4 corners, so we skip the
 
1191
     * fourth.
 
1192
     */
 
1193
    point0.x = _cairo_fixed_to_double (pattern->p1.x);
 
1194
    point0.y = _cairo_fixed_to_double (pattern->p1.y);
 
1195
    point1.x = _cairo_fixed_to_double (pattern->p2.x);
 
1196
    point1.y = _cairo_fixed_to_double (pattern->p2.y);
 
1197
 
 
1198
    _cairo_matrix_get_affine (&pattern->base.base.matrix,
 
1199
                              &a, &b, &c, &d, &tx, &ty);
 
1200
 
 
1201
    dx = point1.x - point0.x;
 
1202
    dy = point1.y - point0.y;
 
1203
    scale = dx * dx + dy * dy;
 
1204
    scale = (scale) ? 1.0 / scale : 1.0;
 
1205
 
 
1206
    start = dx * point0.x + dy * point0.y;
 
1207
 
 
1208
    for (i = 0; i < 3; i++) {
 
1209
        double qx_device = (i % 2) * (width - 1) + offset_x;
 
1210
        double qy_device = (i / 2) * (height - 1) + offset_y;
 
1211
 
 
1212
        /* transform fragment into pattern space */
 
1213
        double qx = a * qx_device + c * qy_device + tx;
 
1214
        double qy = b * qx_device + d * qy_device + ty;
 
1215
 
 
1216
        factors[i] = _cairo_fixed_from_double (((dx * qx + dy * qy) - start) * scale);
 
1217
    }
 
1218
 
 
1219
    /* We consider a pattern to be vertical if the fixed point factor
 
1220
     * at the two upper corners is the same. We could accept a small
 
1221
     * change, but determining what change is acceptable would require
 
1222
     * sorting the stops in the pattern and looking at the differences.
 
1223
     *
 
1224
     * Horizontal works the same way with the two left corners.
 
1225
     */
 
1226
 
 
1227
    *is_vertical = factors[1] == factors[0];
 
1228
    *is_horizontal = factors[2] == factors[0];
 
1229
}
 
1230
 
 
1231
static cairo_int_status_t
 
1232
_cairo_pattern_acquire_surface_for_gradient (cairo_gradient_pattern_t *pattern,
 
1233
                                             cairo_surface_t            *dst,
 
1234
                                             int                        x,
 
1235
                                             int                        y,
 
1236
                                             unsigned int               width,
 
1237
                                             unsigned int               height,
 
1238
                                             cairo_surface_t            **out,
 
1239
                                             cairo_surface_attributes_t *attr)
 
1240
{
 
1241
    cairo_image_surface_t *image;
 
1242
    pixman_image_t        *pixman_image;
 
1243
    pixman_transform_t    pixman_transform;
 
1244
    cairo_status_t        status;
 
1245
    cairo_bool_t          repeat = FALSE;
 
1246
 
 
1247
    pixman_gradient_stop_t pixman_stops_static[2];
 
1248
    pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
 
1249
    unsigned int i;
 
1250
 
 
1251
    if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
 
1252
        pixman_stops = _cairo_malloc_ab (pattern->n_stops, sizeof(pixman_gradient_stop_t));
 
1253
        if (pixman_stops == NULL)
 
1254
            return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1255
    }
 
1256
 
 
1257
    for (i = 0; i < pattern->n_stops; i++) {
 
1258
        pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
 
1259
        pixman_stops[i].color.red = pattern->stops[i].color.red_short;
 
1260
        pixman_stops[i].color.green = pattern->stops[i].color.green_short;
 
1261
        pixman_stops[i].color.blue = pattern->stops[i].color.blue_short;
 
1262
        pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
 
1263
    }
 
1264
 
 
1265
    if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR)
 
1266
    {
 
1267
        cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern;
 
1268
        pixman_point_fixed_t p1, p2;
 
1269
 
 
1270
        p1.x = _cairo_fixed_to_16_16 (linear->p1.x);
 
1271
        p1.y = _cairo_fixed_to_16_16 (linear->p1.y);
 
1272
        p2.x = _cairo_fixed_to_16_16 (linear->p2.x);
 
1273
        p2.y = _cairo_fixed_to_16_16 (linear->p2.y);
 
1274
 
 
1275
        pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
 
1276
                                                            pixman_stops,
 
1277
                                                            pattern->n_stops);
 
1278
    }
 
1279
    else
 
1280
    {
 
1281
        cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
 
1282
        pixman_point_fixed_t c1, c2;
 
1283
        pixman_fixed_t r1, r2;
 
1284
 
 
1285
        c1.x = _cairo_fixed_to_16_16 (radial->c1.x);
 
1286
        c1.y = _cairo_fixed_to_16_16 (radial->c1.y);
 
1287
        r1   = _cairo_fixed_to_16_16 (radial->r1);
 
1288
 
 
1289
        c2.x = _cairo_fixed_to_16_16 (radial->c2.x);
 
1290
        c2.y = _cairo_fixed_to_16_16 (radial->c2.y);
 
1291
        r2   = _cairo_fixed_to_16_16 (radial->r2);
 
1292
 
 
1293
        pixman_image = pixman_image_create_radial_gradient (&c1, &c2,
 
1294
                                                            r1, r2,
 
1295
                                                            pixman_stops,
 
1296
                                                            pattern->n_stops);
 
1297
    }
 
1298
 
 
1299
    if (pixman_stops != pixman_stops_static)
 
1300
        free (pixman_stops);
 
1301
 
 
1302
    if (pixman_image == NULL)
 
1303
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1304
 
 
1305
    if (_cairo_surface_is_image (dst))
 
1306
    {
 
1307
        image = (cairo_image_surface_t *)
 
1308
            _cairo_image_surface_create_for_pixman_image (pixman_image,
 
1309
                                                          PIXMAN_a8r8g8b8);
 
1310
        if (image->base.status)
 
1311
        {
 
1312
            pixman_image_unref (pixman_image);
 
1313
            return image->base.status;
 
1314
        }
 
1315
 
 
1316
        attr->x_offset = attr->y_offset = 0;
 
1317
        attr->matrix = pattern->base.matrix;
 
1318
        attr->extend = pattern->base.extend;
 
1319
        attr->filter = CAIRO_FILTER_NEAREST;
 
1320
        attr->acquired = FALSE;
 
1321
 
 
1322
        *out = &image->base;
 
1323
 
 
1324
        return CAIRO_STATUS_SUCCESS;
 
1325
    }
 
1326
 
 
1327
    if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
 
1328
        cairo_bool_t is_horizontal;
 
1329
        cairo_bool_t is_vertical;
 
1330
 
 
1331
        _cairo_linear_pattern_classify ((cairo_linear_pattern_t *)pattern,
 
1332
                                        x, y, width, height,
 
1333
                                        &is_horizontal, &is_vertical);
 
1334
        if (is_horizontal) {
 
1335
            height = 1;
 
1336
            repeat = TRUE;
 
1337
        }
 
1338
        /* width-1 repeating patterns are quite slow with scan-line based
 
1339
         * compositing code, so we use a wider strip and spend some extra
 
1340
         * expense in computing the gradient. It's possible that for narrow
 
1341
         * gradients we'd be better off using a 2 or 4 pixel strip; the
 
1342
         * wider the gradient, the more it's worth spending extra time
 
1343
         * computing a sample.
 
1344
         */
 
1345
        if (is_vertical && width > 8) {
 
1346
            width = 8;
 
1347
            repeat = TRUE;
 
1348
        }
 
1349
    }
 
1350
 
 
1351
    if (! pixman_image_set_filter (pixman_image, PIXMAN_FILTER_BILINEAR,
 
1352
                                   NULL, 0))
 
1353
    {
 
1354
        pixman_image_unref (pixman_image);
 
1355
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1356
    }
 
1357
 
 
1358
    image = (cairo_image_surface_t *)
 
1359
        cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
 
1360
    if (image->base.status) {
 
1361
        pixman_image_unref (pixman_image);
 
1362
        return image->base.status;
 
1363
    }
 
1364
 
 
1365
    _cairo_matrix_to_pixman_matrix (&pattern->base.matrix, &pixman_transform);
 
1366
    if (!pixman_image_set_transform (pixman_image, &pixman_transform)) {
 
1367
        cairo_surface_destroy (&image->base);
 
1368
        pixman_image_unref (pixman_image);
 
1369
        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
 
1370
    }
 
1371
 
 
1372
    switch (pattern->base.extend) {
 
1373
    case CAIRO_EXTEND_NONE:
 
1374
        pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NONE);
 
1375
        break;
 
1376
    case CAIRO_EXTEND_REPEAT:
 
1377
        pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NORMAL);
 
1378
        break;
 
1379
    case CAIRO_EXTEND_REFLECT:
 
1380
        pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_REFLECT);
 
1381
        break;
 
1382
    case CAIRO_EXTEND_PAD:
 
1383
        pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_PAD);
 
1384
        break;
 
1385
    }
 
1386
 
 
1387
    pixman_image_composite (PIXMAN_OP_SRC,
 
1388
                            pixman_image,
 
1389
                            NULL,
 
1390
                            image->pixman_image,
 
1391
                            x, y,
 
1392
                            0, 0,
 
1393
                            0, 0,
 
1394
                            width, height);
 
1395
 
 
1396
    pixman_image_unref (pixman_image);
 
1397
 
 
1398
    status = _cairo_surface_clone_similar (dst, &image->base,
 
1399
                                           0, 0, width, height, out);
 
1400
 
 
1401
    cairo_surface_destroy (&image->base);
 
1402
 
 
1403
    attr->x_offset = -x;
 
1404
    attr->y_offset = -y;
 
1405
    cairo_matrix_init_identity (&attr->matrix);
 
1406
    attr->extend = repeat ? CAIRO_EXTEND_REPEAT : CAIRO_EXTEND_NONE;
 
1407
    attr->filter = CAIRO_FILTER_NEAREST;
 
1408
    attr->acquired = FALSE;
 
1409
 
 
1410
    return status;
 
1411
}
 
1412
 
 
1413
/* We maintain a small cache here, because we don't want to constantly
 
1414
 * recreate surfaces for simple solid colors. */
 
1415
#define MAX_SURFACE_CACHE_SIZE 16
 
1416
static struct {
 
1417
    struct _cairo_pattern_solid_surface_cache{
 
1418
        cairo_content_t  content;
 
1419
        cairo_color_t    color;
 
1420
        cairo_surface_t *surface;
 
1421
    } cache[MAX_SURFACE_CACHE_SIZE];
 
1422
    int size;
 
1423
} solid_surface_cache;
 
1424
 
 
1425
static cairo_bool_t
 
1426
_cairo_pattern_solid_surface_matches (
 
1427
        const struct _cairo_pattern_solid_surface_cache     *cache,
 
1428
        const cairo_solid_pattern_t                         *pattern,
 
1429
        cairo_surface_t                                     *dst)
 
1430
{
 
1431
    if (cache->content != pattern->content)
 
1432
        return FALSE;
 
1433
 
 
1434
    if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache->surface->ref_count) != 1)
 
1435
        return FALSE;
 
1436
 
 
1437
    if (! _cairo_surface_is_similar (cache->surface, dst, pattern->content))
 
1438
        return FALSE;
 
1439
 
 
1440
    return TRUE;
 
1441
}
 
1442
 
 
1443
static cairo_bool_t
 
1444
_cairo_pattern_solid_surface_matches_color (
 
1445
        const struct _cairo_pattern_solid_surface_cache     *cache,
 
1446
        const cairo_solid_pattern_t                         *pattern,
 
1447
        cairo_surface_t                                     *dst)
 
1448
{
 
1449
    if (! _cairo_color_equal (&cache->color, &pattern->color))
 
1450
        return FALSE;
 
1451
 
 
1452
    return _cairo_pattern_solid_surface_matches (cache, pattern, dst);
 
1453
}
 
1454
 
 
1455
static cairo_int_status_t
 
1456
_cairo_pattern_acquire_surface_for_solid (cairo_solid_pattern_t      *pattern,
 
1457
                                          cairo_surface_t            *dst,
 
1458
                                          int                        x,
 
1459
                                          int                        y,
 
1460
                                          unsigned int               width,
 
1461
                                          unsigned int               height,
 
1462
                                          cairo_surface_t            **out,
 
1463
                                          cairo_surface_attributes_t *attribs)
 
1464
{
 
1465
    static int i;
 
1466
 
 
1467
    cairo_surface_t *surface, *to_destroy = NULL;
 
1468
    cairo_status_t   status;
 
1469
 
 
1470
    CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
 
1471
 
 
1472
    /* Check cache first */
 
1473
    if (i < solid_surface_cache.size &&
 
1474
        _cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i],
 
1475
                                                    pattern,
 
1476
                                                    dst))
 
1477
    {
 
1478
        status = _cairo_surface_reset (solid_surface_cache.cache[i].surface);
 
1479
        if (status)
 
1480
            goto UNLOCK;
 
1481
 
 
1482
        goto DONE;
 
1483
    }
 
1484
 
 
1485
    for (i = 0 ; i < solid_surface_cache.size; i++) {
 
1486
        if (_cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i],
 
1487
                                                        pattern,
 
1488
                                                        dst))
 
1489
        {
 
1490
            status = _cairo_surface_reset (solid_surface_cache.cache[i].surface);
 
1491
            if (status)
 
1492
                goto UNLOCK;
 
1493
 
 
1494
            goto DONE;
 
1495
        }
 
1496
    }
 
1497
 
 
1498
    /* Choose a surface to repaint/evict */
 
1499
    surface = NULL;
 
1500
    if (solid_surface_cache.size == MAX_SURFACE_CACHE_SIZE) {
 
1501
        i = rand () % MAX_SURFACE_CACHE_SIZE;
 
1502
        surface = solid_surface_cache.cache[i].surface;
 
1503
 
 
1504
        if (_cairo_pattern_solid_surface_matches (&solid_surface_cache.cache[i],
 
1505
                                                  pattern,
 
1506
                                                  dst))
 
1507
        {
 
1508
            /* Reuse the surface instead of evicting */
 
1509
 
 
1510
            status = _cairo_surface_reset (surface);
 
1511
            if (status)
 
1512
                goto EVICT;
 
1513
 
 
1514
            status = _cairo_surface_repaint_solid_pattern_surface (dst, surface, pattern);
 
1515
            if (status)
 
1516
                goto EVICT;
 
1517
 
 
1518
            cairo_surface_reference (surface);
 
1519
        }
 
1520
        else
 
1521
        {
 
1522
          EVICT:
 
1523
            surface = NULL;
 
1524
        }
 
1525
    }
 
1526
 
 
1527
    if (surface == NULL) {
 
1528
        /* Not cached, need to create new */
 
1529
        surface = _cairo_surface_create_solid_pattern_surface (dst, pattern);
 
1530
        if (surface->status) {
 
1531
            status = surface->status;
 
1532
            goto UNLOCK;
 
1533
        }
 
1534
 
 
1535
        if (! _cairo_surface_is_similar (surface, dst, pattern->content)) {
 
1536
            /* in the rare event of a substitute surface being returned (e.g.
 
1537
             * malloc failure) don't cache the fallback surface */
 
1538
            *out = surface;
 
1539
            goto NOCACHE;
 
1540
        }
 
1541
    }
 
1542
 
 
1543
    if (i == solid_surface_cache.size)
 
1544
        solid_surface_cache.size++;
 
1545
 
 
1546
    to_destroy = solid_surface_cache.cache[i].surface;
 
1547
    solid_surface_cache.cache[i].surface = surface;
 
1548
    solid_surface_cache.cache[i].color   = pattern->color;
 
1549
    solid_surface_cache.cache[i].content = pattern->content;
 
1550
 
 
1551
DONE:
 
1552
    *out = cairo_surface_reference (solid_surface_cache.cache[i].surface);
 
1553
 
 
1554
NOCACHE:
 
1555
    attribs->x_offset = attribs->y_offset = 0;
 
1556
    cairo_matrix_init_identity (&attribs->matrix);
 
1557
    attribs->extend = CAIRO_EXTEND_REPEAT;
 
1558
    attribs->filter = CAIRO_FILTER_NEAREST;
 
1559
    attribs->acquired = FALSE;
 
1560
 
 
1561
    status = CAIRO_STATUS_SUCCESS;
 
1562
 
 
1563
UNLOCK:
 
1564
    CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
 
1565
 
 
1566
    if (to_destroy)
 
1567
      cairo_surface_destroy (to_destroy);
 
1568
 
 
1569
    return status;
 
1570
}
 
1571
 
 
1572
static void
 
1573
_cairo_pattern_reset_solid_surface_cache (void)
 
1574
{
 
1575
    CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
 
1576
 
 
1577
    /* remove surfaces starting from the end so that solid_surface_cache.cache
 
1578
     * is always in a consistent state when we release the mutex. */
 
1579
    while (solid_surface_cache.size) {
 
1580
        cairo_surface_t *surface;
 
1581
 
 
1582
        solid_surface_cache.size--;
 
1583
        surface = solid_surface_cache.cache[solid_surface_cache.size].surface;
 
1584
        solid_surface_cache.cache[solid_surface_cache.size].surface = NULL;
 
1585
 
 
1586
        /* release the lock to avoid the possibility of a recursive
 
1587
         * deadlock when the scaled font destroy closure gets called */
 
1588
        CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
 
1589
        cairo_surface_destroy (surface);
 
1590
        CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
 
1591
    }
 
1592
 
 
1593
    CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
 
1594
}
 
1595
 
 
1596
/**
 
1597
 * _cairo_pattern_is_opaque_solid
 
1598
 *
 
1599
 * Convenience function to determine whether a pattern is an opaque
 
1600
 * (alpha==1.0) solid color pattern. This is done by testing whether
 
1601
 * the pattern's alpha value when converted to a byte is 255, so if a
 
1602
 * backend actually supported deep alpha channels this function might
 
1603
 * not do the right thing.
 
1604
 *
 
1605
 * Return value: %TRUE if the pattern is an opaque, solid color.
 
1606
 **/
 
1607
cairo_bool_t
 
1608
_cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern)
 
1609
{
 
1610
    cairo_solid_pattern_t *solid;
 
1611
 
 
1612
    if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
 
1613
        return FALSE;
 
1614
 
 
1615
    solid = (cairo_solid_pattern_t *) pattern;
 
1616
 
 
1617
    return CAIRO_COLOR_IS_OPAQUE (&solid->color);
 
1618
}
 
1619
 
 
1620
static cairo_bool_t
 
1621
_gradient_is_opaque (const cairo_gradient_pattern_t *gradient)
 
1622
{
 
1623
    unsigned int i;
 
1624
 
 
1625
    for (i = 0; i < gradient->n_stops; i++)
 
1626
        if (! CAIRO_COLOR_IS_OPAQUE (&gradient->stops[i].color))
 
1627
            return FALSE;
 
1628
 
 
1629
    return TRUE;
 
1630
}
 
1631
 
 
1632
/**
 
1633
 * _cairo_pattern_is_opaque
 
1634
 *
 
1635
 * Convenience function to determine whether a pattern is an opaque
 
1636
 * pattern (of any type). The same caveats that apply to
 
1637
 * _cairo_pattern_is_opaque_solid apply here as well.
 
1638
 *
 
1639
 * Return value: %TRUE if the pattern is a opaque.
 
1640
 **/
 
1641
cairo_bool_t
 
1642
_cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern)
 
1643
{
 
1644
    const cairo_pattern_union_t *pattern;
 
1645
 
 
1646
    pattern = (cairo_pattern_union_t *) abstract_pattern;
 
1647
    switch (pattern->base.type) {
 
1648
    case CAIRO_PATTERN_TYPE_SOLID:
 
1649
        return _cairo_pattern_is_opaque_solid (abstract_pattern);
 
1650
    case CAIRO_PATTERN_TYPE_SURFACE:
 
1651
        return cairo_surface_get_content (pattern->surface.surface) == CAIRO_CONTENT_COLOR;
 
1652
    case CAIRO_PATTERN_TYPE_LINEAR:
 
1653
    case CAIRO_PATTERN_TYPE_RADIAL:
 
1654
        return _gradient_is_opaque (&pattern->gradient.base);
 
1655
    }
 
1656
 
 
1657
    ASSERT_NOT_REACHED;
 
1658
    return FALSE;
 
1659
}
 
1660
 
 
1661
static cairo_int_status_t
 
1662
_cairo_pattern_acquire_surface_for_surface (cairo_surface_pattern_t   *pattern,
 
1663
                                            cairo_surface_t            *dst,
 
1664
                                            int                        x,
 
1665
                                            int                        y,
 
1666
                                            unsigned int               width,
 
1667
                                            unsigned int               height,
 
1668
                                            cairo_surface_t            **out,
 
1669
                                            cairo_surface_attributes_t *attr)
 
1670
{
 
1671
    cairo_int_status_t status;
 
1672
    int tx, ty;
 
1673
 
 
1674
    attr->acquired = FALSE;
 
1675
 
 
1676
    attr->extend = pattern->base.extend;
 
1677
    attr->filter = pattern->base.filter;
 
1678
    if (_cairo_matrix_is_integer_translation (&pattern->base.matrix,
 
1679
                                              &tx, &ty))
 
1680
    {
 
1681
        cairo_matrix_init_identity (&attr->matrix);
 
1682
        attr->x_offset = tx;
 
1683
        attr->y_offset = ty;
 
1684
        attr->filter = CAIRO_FILTER_NEAREST;
 
1685
    }
 
1686
    else
 
1687
    {
 
1688
        attr->matrix = pattern->base.matrix;
 
1689
        attr->x_offset = attr->y_offset = 0;
 
1690
        tx = 0;
 
1691
        ty = 0;
 
1692
    }
 
1693
 
 
1694
    /* XXX: Hack:
 
1695
     *
 
1696
     * The way we currently support CAIRO_EXTEND_REFLECT is to create
 
1697
     * an image twice bigger on each side, and create a pattern of four
 
1698
     * images such that the new image, when repeated, has the same effect
 
1699
     * of reflecting the original pattern.
 
1700
     *
 
1701
     * This is because the reflect support in pixman is broken and we
 
1702
     * pass repeat instead of reflect to pixman.  See
 
1703
     * _cairo_image_surface_set_attributes() for that.
 
1704
     */
 
1705
    if (attr->extend == CAIRO_EXTEND_REFLECT) {
 
1706
        cairo_t *cr;
 
1707
        int w,h;
 
1708
 
 
1709
        cairo_rectangle_int_t extents;
 
1710
        status = _cairo_surface_get_extents (pattern->surface, &extents);
 
1711
        if (status)
 
1712
            return status;
 
1713
 
 
1714
        attr->extend = CAIRO_EXTEND_REPEAT;
 
1715
 
 
1716
        /* TODO: Instead of rendering pattern->surface four times to
 
1717
         * out, we should first copy pattern->surface to surface similar
 
1718
         * to dst and then copy that four times to out.  This may cause
 
1719
         * an extra copy in the case of image destination, but for X servers,
 
1720
         * this will send pattern->surface just once over the wire instead
 
1721
         * of current four.
 
1722
         */
 
1723
        x = extents.x;
 
1724
        y = extents.y;
 
1725
        w = 2 * extents.width;
 
1726
        h = 2 * extents.height;
 
1727
 
 
1728
        *out = cairo_surface_create_similar (dst, dst->content, w, h);
 
1729
        status = cairo_surface_status (*out);
 
1730
        if (status) {
 
1731
            cairo_surface_destroy (*out);
 
1732
            *out = NULL;
 
1733
            return status;
 
1734
        }
 
1735
 
 
1736
        (*out)->device_transform = pattern->surface->device_transform;
 
1737
        (*out)->device_transform_inverse = pattern->surface->device_transform_inverse;
 
1738
 
 
1739
        cr = cairo_create (*out);
 
1740
 
 
1741
        cairo_set_source_surface (cr, pattern->surface, -x, -y);
 
1742
        cairo_paint (cr);
 
1743
 
 
1744
        cairo_scale (cr, -1, +1);
 
1745
        cairo_set_source_surface (cr, pattern->surface, x-w, -y);
 
1746
        cairo_paint (cr);
 
1747
 
 
1748
        cairo_scale (cr, +1, -1);
 
1749
        cairo_set_source_surface (cr, pattern->surface, x-w, y-h);
 
1750
        cairo_paint (cr);
 
1751
 
 
1752
        cairo_scale (cr, -1, +1);
 
1753
        cairo_set_source_surface (cr, pattern->surface, -x, y-h);
 
1754
        cairo_paint (cr);
 
1755
 
 
1756
        status = cairo_status (cr);
 
1757
        cairo_destroy (cr);
 
1758
 
 
1759
        if (status) {
 
1760
            cairo_surface_destroy (*out);
 
1761
            *out = NULL;
 
1762
        }
 
1763
 
 
1764
        return status;
 
1765
    }
 
1766
 
 
1767
    if (_cairo_surface_is_image (dst))
 
1768
    {
 
1769
        cairo_image_surface_t *image;
 
1770
 
 
1771
        status = _cairo_surface_acquire_source_image (pattern->surface,
 
1772
                                                      &image,
 
1773
                                                      &attr->extra);
 
1774
        if (status)
 
1775
            return status;
 
1776
 
 
1777
        *out = &image->base;
 
1778
        attr->acquired = TRUE;
 
1779
    }
 
1780
    else
 
1781
    {
 
1782
        cairo_rectangle_int_t extents;
 
1783
        status = _cairo_surface_get_extents (pattern->surface, &extents);
 
1784
        if (status)
 
1785
            return status;
 
1786
 
 
1787
        /* If we're repeating, we just play it safe and clone the entire surface. */
 
1788
        /* If requested width and height are -1, clone the entire surface.
 
1789
         * This is relied on in the svg backend. */
 
1790
        if (attr->extend == CAIRO_EXTEND_REPEAT ||
 
1791
            (width == (unsigned int) -1 && height == (unsigned int) -1)) {
 
1792
            x = extents.x;
 
1793
            y = extents.y;
 
1794
            width = extents.width;
 
1795
            height = extents.height;
 
1796
        } else {
 
1797
            /* Otherwise, we first transform the rectangle to the
 
1798
             * coordinate space of the source surface so that we can
 
1799
             * clone only that portion of the surface that will be
 
1800
             * read. */
 
1801
            if (! _cairo_matrix_is_identity (&attr->matrix)) {
 
1802
                double x1 = x;
 
1803
                double y1 = y;
 
1804
                double x2 = x + width;
 
1805
                double y2 = y + height;
 
1806
                cairo_bool_t is_tight;
 
1807
 
 
1808
                _cairo_matrix_transform_bounding_box  (&attr->matrix,
 
1809
                                                       &x1, &y1, &x2, &y2,
 
1810
                                                       &is_tight);
 
1811
 
 
1812
                /* The transform_bounding_box call may have resulted
 
1813
                 * in a region larger than the surface, but we never
 
1814
                 * want to clone more than the surface itself, (we
 
1815
                 * know we're not repeating at this point due to the
 
1816
                 * above.
 
1817
                 *
 
1818
                 * XXX: The one padding here is to account for filter
 
1819
                 * radius.  It's a workaround right now, until we get a
 
1820
                 * proper fix. (see bug #10508)
 
1821
                 */
 
1822
                x = MAX (0, floor (x1) - 1);
 
1823
                y = MAX (0, floor (y1) - 1);
 
1824
                width = MAX (MIN (extents.width, ceil (x2) + 1) - x, 0);
 
1825
                height = MAX (MIN (extents.height, ceil (y2) + 1) - y, 0);
 
1826
            }
 
1827
            x += tx;
 
1828
            y += ty;
 
1829
        }
 
1830
 
 
1831
        status = _cairo_surface_clone_similar (dst, pattern->surface,
 
1832
                                               x, y, width, height, out);
 
1833
    }
 
1834
 
 
1835
    return status;
 
1836
}
 
1837
 
 
1838
/**
 
1839
 * _cairo_pattern_acquire_surface:
 
1840
 * @pattern: a #cairo_pattern_t
 
1841
 * @dst: destination surface
 
1842
 * @x: X coordinate in source corresponding to left side of destination area
 
1843
 * @y: Y coordinate in source corresponding to top side of destination area
 
1844
 * @width: width of destination area
 
1845
 * @height: height of destination area
 
1846
 * @surface_out: location to store a pointer to a surface
 
1847
 * @attributes: surface attributes that destination backend should apply to
 
1848
 * the returned surface
 
1849
 *
 
1850
 * A convenience function to obtain a surface to use as the source for
 
1851
 * drawing on @dst.
 
1852
 *
 
1853
 * Return value: %CAIRO_STATUS_SUCCESS if a surface was stored in @surface_out.
 
1854
 **/
 
1855
cairo_int_status_t
 
1856
_cairo_pattern_acquire_surface (cairo_pattern_t            *pattern,
 
1857
                                cairo_surface_t            *dst,
 
1858
                                int                        x,
 
1859
                                int                        y,
 
1860
                                unsigned int               width,
 
1861
                                unsigned int               height,
 
1862
                                cairo_surface_t            **surface_out,
 
1863
                                cairo_surface_attributes_t *attributes)
 
1864
{
 
1865
    cairo_status_t status;
 
1866
 
 
1867
    if (pattern->status) {
 
1868
        *surface_out = NULL;
 
1869
        attributes->acquired = FALSE;
 
1870
        return pattern->status;
 
1871
    }
 
1872
 
 
1873
    switch (pattern->type) {
 
1874
    case CAIRO_PATTERN_TYPE_SOLID: {
 
1875
        cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) pattern;
 
1876
 
 
1877
        status = _cairo_pattern_acquire_surface_for_solid (src, dst,
 
1878
                                                           x, y, width, height,
 
1879
                                                           surface_out,
 
1880
                                                           attributes);
 
1881
        } break;
 
1882
    case CAIRO_PATTERN_TYPE_LINEAR:
 
1883
    case CAIRO_PATTERN_TYPE_RADIAL: {
 
1884
        cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) pattern;
 
1885
 
 
1886
        /* fast path for gradients with less than 2 color stops */
 
1887
        if (src->n_stops < 2)
 
1888
        {
 
1889
            cairo_solid_pattern_t solid;
 
1890
 
 
1891
            if (src->n_stops)
 
1892
            {
 
1893
                cairo_color_t color;
 
1894
 
 
1895
                _cairo_color_init_rgba (&color,
 
1896
                                        src->stops->color.red,
 
1897
                                        src->stops->color.green,
 
1898
                                        src->stops->color.blue,
 
1899
                                        src->stops->color.alpha);
 
1900
 
 
1901
                _cairo_pattern_init_solid (&solid, &color, CAIRO_CONTENT_COLOR_ALPHA);
 
1902
            }
 
1903
            else
 
1904
            {
 
1905
                _cairo_pattern_init_solid (&solid, CAIRO_COLOR_TRANSPARENT, CAIRO_CONTENT_ALPHA);
 
1906
            }
 
1907
 
 
1908
            status = _cairo_pattern_acquire_surface_for_solid (&solid, dst,
 
1909
                                                               x, y,
 
1910
                                                               width, height,
 
1911
                                                               surface_out,
 
1912
                                                               attributes);
 
1913
        }
 
1914
        else
 
1915
        {
 
1916
            status = _cairo_pattern_acquire_surface_for_gradient (src, dst,
 
1917
                                                                  x, y,
 
1918
                                                                  width, height,
 
1919
                                                                  surface_out,
 
1920
                                                                  attributes);
 
1921
        }
 
1922
    } break;
 
1923
    case CAIRO_PATTERN_TYPE_SURFACE: {
 
1924
        cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) pattern;
 
1925
 
 
1926
        status = _cairo_pattern_acquire_surface_for_surface (src, dst,
 
1927
                                                             x, y, width, height,
 
1928
                                                             surface_out,
 
1929
                                                             attributes);
 
1930
    } break;
 
1931
    default:
 
1932
        ASSERT_NOT_REACHED;
 
1933
        status = _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
 
1934
    }
 
1935
 
 
1936
    return status;
 
1937
}
 
1938
 
 
1939
/**
 
1940
 * _cairo_pattern_release_surface:
 
1941
 * @pattern: a #cairo_pattern_t
 
1942
 * @surface: a surface obtained by _cairo_pattern_acquire_surface
 
1943
 * @attributes: attributes obtained by _cairo_pattern_acquire_surface
 
1944
 *
 
1945
 * Releases resources obtained by _cairo_pattern_acquire_surface.
 
1946
 **/
 
1947
void
 
1948
_cairo_pattern_release_surface (cairo_pattern_t            *pattern,
 
1949
                                cairo_surface_t            *surface,
 
1950
                                cairo_surface_attributes_t *attributes)
 
1951
{
 
1952
    if (attributes->acquired)
 
1953
    {
 
1954
        cairo_surface_pattern_t *surface_pattern;
 
1955
 
 
1956
        assert (pattern->type == CAIRO_PATTERN_TYPE_SURFACE);
 
1957
        surface_pattern = (cairo_surface_pattern_t *) pattern;
 
1958
 
 
1959
        _cairo_surface_release_source_image (surface_pattern->surface,
 
1960
                                             (cairo_image_surface_t *) surface,
 
1961
                                             attributes->extra);
 
1962
    }
 
1963
    else
 
1964
    {
 
1965
        cairo_surface_destroy (surface);
 
1966
    }
 
1967
}
 
1968
 
 
1969
cairo_int_status_t
 
1970
_cairo_pattern_acquire_surfaces (cairo_pattern_t            *src,
 
1971
                                 cairo_pattern_t            *mask,
 
1972
                                 cairo_surface_t            *dst,
 
1973
                                 int                        src_x,
 
1974
                                 int                        src_y,
 
1975
                                 int                        mask_x,
 
1976
                                 int                        mask_y,
 
1977
                                 unsigned int               width,
 
1978
                                 unsigned int               height,
 
1979
                                 cairo_surface_t            **src_out,
 
1980
                                 cairo_surface_t            **mask_out,
 
1981
                                 cairo_surface_attributes_t *src_attributes,
 
1982
                                 cairo_surface_attributes_t *mask_attributes)
 
1983
{
 
1984
    cairo_int_status_t    status;
 
1985
    cairo_pattern_union_t src_tmp, mask_tmp;
 
1986
 
 
1987
    if (src->status)
 
1988
        return src->status;
 
1989
    if (mask && mask->status)
 
1990
        return mask->status;
 
1991
 
 
1992
    /* If src and mask are both solid, then the mask alpha can be
 
1993
     * combined into src and mask can be ignored. */
 
1994
 
 
1995
    /* XXX: This optimization assumes that there is no color
 
1996
     * information in mask, so this will need to change when we
 
1997
     * support RENDER-style 4-channel masks. */
 
1998
    if (src->type == CAIRO_PATTERN_TYPE_SOLID &&
 
1999
        mask && mask->type == CAIRO_PATTERN_TYPE_SOLID)
 
2000
    {
 
2001
        cairo_color_t combined;
 
2002
        cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src;
 
2003
        cairo_solid_pattern_t *mask_solid = (cairo_solid_pattern_t *) mask;
 
2004
 
 
2005
        combined = src_solid->color;
 
2006
        _cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
 
2007
 
 
2008
        _cairo_pattern_init_solid (&src_tmp.solid, &combined, CAIRO_CONTENT_COLOR_ALPHA);
 
2009
 
 
2010
        mask = NULL;
 
2011
    }
 
2012
    else
 
2013
    {
 
2014
        status = _cairo_pattern_init_copy (&src_tmp.base, src);
 
2015
        if (status)
 
2016
            return status;
 
2017
    }
 
2018
 
 
2019
    status = _cairo_pattern_acquire_surface (&src_tmp.base, dst,
 
2020
                                             src_x, src_y,
 
2021
                                             width, height,
 
2022
                                             src_out, src_attributes);
 
2023
    if (status) {
 
2024
        _cairo_pattern_fini (&src_tmp.base);
 
2025
        return status;
 
2026
    }
 
2027
 
 
2028
    if (mask == NULL)
 
2029
    {
 
2030
        _cairo_pattern_fini (&src_tmp.base);
 
2031
        *mask_out = NULL;
 
2032
        return CAIRO_STATUS_SUCCESS;
 
2033
    }
 
2034
 
 
2035
    status = _cairo_pattern_init_copy (&mask_tmp.base, mask);
 
2036
    if (status)
 
2037
        goto CLEANUP_SOURCE;
 
2038
 
 
2039
    status = _cairo_pattern_acquire_surface (&mask_tmp.base, dst,
 
2040
                                             mask_x, mask_y,
 
2041
                                             width, height,
 
2042
                                             mask_out, mask_attributes);
 
2043
 
 
2044
    _cairo_pattern_fini (&mask_tmp.base);
 
2045
 
 
2046
CLEANUP_SOURCE:
 
2047
    if (status)
 
2048
        _cairo_pattern_release_surface (&src_tmp.base,
 
2049
                                        *src_out, src_attributes);
 
2050
 
 
2051
    _cairo_pattern_fini (&src_tmp.base);
 
2052
 
 
2053
    return status;
 
2054
}
 
2055
 
 
2056
/**
 
2057
 * _cairo_pattern_get_extents:
 
2058
 *
 
2059
 * Return the "target-space" extents of @pattern in @extents.
 
2060
 *
 
2061
 * For unbounded patterns, the @extents will be initialized with
 
2062
 * "infinite" extents, (minimum and maximum fixed-point values).
 
2063
 *
 
2064
 * XXX: Currently, bounded gradient patterns will also return
 
2065
 * "infinite" extents, though it would be possible to optimize these
 
2066
 * with a little more work.
 
2067
 **/
 
2068
cairo_status_t
 
2069
_cairo_pattern_get_extents (cairo_pattern_t         *pattern,
 
2070
                            cairo_rectangle_int_t   *extents)
 
2071
{
 
2072
    if (pattern->extend == CAIRO_EXTEND_NONE &&
 
2073
        pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
 
2074
    {
 
2075
        cairo_status_t status;
 
2076
        cairo_rectangle_int_t surface_extents;
 
2077
        cairo_surface_pattern_t *surface_pattern =
 
2078
            (cairo_surface_pattern_t *) pattern;
 
2079
        cairo_surface_t *surface = surface_pattern->surface;
 
2080
        cairo_matrix_t imatrix;
 
2081
        double x1, y1, x2, y2;
 
2082
 
 
2083
        status = _cairo_surface_get_extents (surface, &surface_extents);
 
2084
        if (status)
 
2085
            return status;
 
2086
 
 
2087
        x1 = surface_extents.x;
 
2088
        y1 = surface_extents.y;
 
2089
        x2 = x1 + surface_extents.width;
 
2090
        y2 = y1 + surface_extents.height;
 
2091
 
 
2092
        imatrix = pattern->matrix;
 
2093
        status = cairo_matrix_invert (&imatrix);
 
2094
        /* cairo_pattern_set_matrix ensures the matrix is invertible */
 
2095
        assert (status == CAIRO_STATUS_SUCCESS);
 
2096
 
 
2097
        _cairo_matrix_transform_bounding_box (&imatrix,
 
2098
                                              &x1, &y1, &x2, &y2,
 
2099
                                              NULL);
 
2100
 
 
2101
        x1 = floor (x1);
 
2102
        if (x1 < 0)
 
2103
            x1 = 0;
 
2104
        y1 = floor (y1);
 
2105
        if (y1 < 0)
 
2106
            y1 = 0;
 
2107
 
 
2108
        x2 = ceil (x2);
 
2109
        if (x2 > CAIRO_RECT_INT_MAX)
 
2110
            x2 = CAIRO_RECT_INT_MAX;
 
2111
        y2 = ceil (y2);
 
2112
        if (y2 > CAIRO_RECT_INT_MAX)
 
2113
            y2 = CAIRO_RECT_INT_MAX;
 
2114
 
 
2115
        extents->x = x1; extents->width = x2 - x1;
 
2116
        extents->y = y1; extents->height = y2 - y1;
 
2117
 
 
2118
        return CAIRO_STATUS_SUCCESS;
 
2119
    }
 
2120
 
 
2121
    /* XXX: We could optimize gradients with pattern->extend of NONE
 
2122
     * here in some cases, (eg. radial gradients and 1 axis of
 
2123
     * horizontal/vertical linear gradients).
 
2124
     */
 
2125
 
 
2126
    /* unbounded patterns -> 'infinite' extents */
 
2127
    extents->x = CAIRO_RECT_INT_MIN;
 
2128
    extents->y = CAIRO_RECT_INT_MIN;
 
2129
    extents->width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
 
2130
    extents->height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
 
2131
 
 
2132
    return CAIRO_STATUS_SUCCESS;
 
2133
}
 
2134
 
 
2135
/**
 
2136
 * cairo_pattern_get_rgba
 
2137
 * @pattern: a #cairo_pattern_t
 
2138
 * @red: return value for red component of color, or %NULL
 
2139
 * @green: return value for green component of color, or %NULL
 
2140
 * @blue: return value for blue component of color, or %NULL
 
2141
 * @alpha: return value for alpha component of color, or %NULL
 
2142
 *
 
2143
 * Gets the solid color for a solid color pattern.
 
2144
 *
 
2145
 * Return value: %CAIRO_STATUS_SUCCESS, or
 
2146
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid
 
2147
 * color pattern.
 
2148
 *
 
2149
 * Since: 1.4
 
2150
 **/
 
2151
cairo_status_t
 
2152
cairo_pattern_get_rgba (cairo_pattern_t *pattern,
 
2153
                        double *red, double *green,
 
2154
                        double *blue, double *alpha)
 
2155
{
 
2156
    cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
 
2157
    double r0, g0, b0, a0;
 
2158
 
 
2159
    if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
 
2160
        return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
 
2161
 
 
2162
    _cairo_color_get_rgba (&solid->color, &r0, &g0, &b0, &a0);
 
2163
 
 
2164
    if (red)
 
2165
        *red = r0;
 
2166
    if (green)
 
2167
        *green = g0;
 
2168
    if (blue)
 
2169
        *blue = b0;
 
2170
    if (alpha)
 
2171
        *alpha = a0;
 
2172
 
 
2173
    return CAIRO_STATUS_SUCCESS;
 
2174
}
 
2175
 
 
2176
/**
 
2177
 * cairo_pattern_get_surface
 
2178
 * @pattern: a #cairo_pattern_t
 
2179
 * @surface: return value for surface of pattern, or %NULL
 
2180
 * 
 
2181
 * Gets the surface of a surface pattern.  The reference returned in
 
2182
 * @surface is owned by the pattern; the caller should call
 
2183
 * cairo_surface_reference() if the surface is to be retained.
 
2184
 *
 
2185
 * Return value: %CAIRO_STATUS_SUCCESS, or
 
2186
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a surface
 
2187
 * pattern.
 
2188
 *
 
2189
 * Since: 1.4
 
2190
 **/
 
2191
cairo_status_t
 
2192
cairo_pattern_get_surface (cairo_pattern_t *pattern,
 
2193
                           cairo_surface_t **surface)
 
2194
{
 
2195
    cairo_surface_pattern_t *spat = (cairo_surface_pattern_t*) pattern;
 
2196
 
 
2197
    if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
 
2198
        return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
 
2199
 
 
2200
    if (surface)
 
2201
        *surface = spat->surface;
 
2202
 
 
2203
    return CAIRO_STATUS_SUCCESS;
 
2204
}
 
2205
 
 
2206
/**
 
2207
 * cairo_pattern_get_color_stop_rgba
 
2208
 * @pattern: a #cairo_pattern_t
 
2209
 * @index: index of the stop to return data for
 
2210
 * @offset: return value for the offset of the stop, or %NULL
 
2211
 * @red: return value for red component of color, or %NULL
 
2212
 * @green: return value for green component of color, or %NULL
 
2213
 * @blue: return value for blue component of color, or %NULL
 
2214
 * @alpha: return value for alpha component of color, or %NULL
 
2215
 *
 
2216
 * Gets the color and offset information at the given @index for a
 
2217
 * gradient pattern.  Values of @index are 0 to 1 less than the number
 
2218
 * returned by cairo_pattern_get_color_stop_count().
 
2219
 *
 
2220
 * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
 
2221
 * if @index is not valid for the given pattern.  If the pattern is
 
2222
 * not a gradient pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
 
2223
 * returned.
 
2224
 *
 
2225
 * Since: 1.4
 
2226
 **/
 
2227
cairo_status_t
 
2228
cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
 
2229
                                   int index, double *offset,
 
2230
                                   double *red, double *green,
 
2231
                                   double *blue, double *alpha)
 
2232
{
 
2233
    cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
 
2234
 
 
2235
    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
 
2236
        pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
 
2237
        return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
 
2238
 
 
2239
    if (index < 0 || (unsigned int) index >= gradient->n_stops)
 
2240
        return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
 
2241
 
 
2242
    if (offset)
 
2243
        *offset = gradient->stops[index].offset;
 
2244
    if (red)
 
2245
        *red = gradient->stops[index].color.red;
 
2246
    if (green)
 
2247
        *green = gradient->stops[index].color.green;
 
2248
    if (blue)
 
2249
        *blue = gradient->stops[index].color.blue;
 
2250
    if (alpha)
 
2251
        *alpha = gradient->stops[index].color.alpha;
 
2252
 
 
2253
    return CAIRO_STATUS_SUCCESS;
 
2254
}
 
2255
 
 
2256
/**
 
2257
 * cairo_pattern_get_color_stop_count
 
2258
 * @pattern: a #cairo_pattern_t
 
2259
 * @count: return value for the number of color stops, or %NULL
 
2260
 *
 
2261
 * Gets the number of color stops specified in the given gradient
 
2262
 * pattern.
 
2263
 *
 
2264
 * Return value: %CAIRO_STATUS_SUCCESS, or
 
2265
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
 
2266
 * pattern.
 
2267
 *
 
2268
 * Since: 1.4
 
2269
 */
 
2270
cairo_status_t
 
2271
cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
 
2272
                                    int *count)
 
2273
{
 
2274
    cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
 
2275
 
 
2276
    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
 
2277
        pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
 
2278
        return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
 
2279
 
 
2280
    if (count)
 
2281
        *count = gradient->n_stops;
 
2282
 
 
2283
    return CAIRO_STATUS_SUCCESS;
 
2284
}
 
2285
 
 
2286
/**
 
2287
 * cairo_pattern_get_linear_points
 
2288
 * @pattern: a #cairo_pattern_t
 
2289
 * @x0: return value for the x coordinate of the first point, or %NULL
 
2290
 * @y0: return value for the y coordinate of the first point, or %NULL
 
2291
 * @x1: return value for the x coordinate of the second point, or %NULL
 
2292
 * @y1: return value for the y coordinate of the second point, or %NULL
 
2293
 *
 
2294
 * Gets the gradient endpoints for a linear gradient.
 
2295
 *
 
2296
 * Return value: %CAIRO_STATUS_SUCCESS, or
 
2297
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a linear
 
2298
 * gradient pattern.
 
2299
 *
 
2300
 * Since: 1.4
 
2301
 **/
 
2302
cairo_status_t
 
2303
cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
 
2304
                                 double *x0, double *y0,
 
2305
                                 double *x1, double *y1)
 
2306
{
 
2307
    cairo_linear_pattern_t *linear = (cairo_linear_pattern_t*) pattern;
 
2308
 
 
2309
    if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR)
 
2310
        return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
 
2311
 
 
2312
    if (x0)
 
2313
        *x0 = _cairo_fixed_to_double (linear->p1.x);
 
2314
    if (y0)
 
2315
        *y0 = _cairo_fixed_to_double (linear->p1.y);
 
2316
    if (x1)
 
2317
        *x1 = _cairo_fixed_to_double (linear->p2.x);
 
2318
    if (y1)
 
2319
        *y1 = _cairo_fixed_to_double (linear->p2.y);
 
2320
 
 
2321
    return CAIRO_STATUS_SUCCESS;
 
2322
}
 
2323
 
 
2324
/**
 
2325
 * cairo_pattern_get_radial_circles
 
2326
 * @pattern: a #cairo_pattern_t
 
2327
 * @x0: return value for the x coordinate of the center of the first circle, or %NULL
 
2328
 * @y0: return value for the y coordinate of the center of the first circle, or %NULL
 
2329
 * @r0: return value for the radius of the first circle, or %NULL
 
2330
 * @x1: return value for the x coordinate of the center of the second circle, or %NULL
 
2331
 * @y1: return value for the y coordinate of the center of the second circle, or %NULL
 
2332
 * @r1: return value for the radius of the second circle, or %NULL
 
2333
 *
 
2334
 * Gets the gradient endpoint circles for a radial gradient, each
 
2335
 * specified as a center coordinate and a radius.
 
2336
 *
 
2337
 * Return value: %CAIRO_STATUS_SUCCESS, or
 
2338
 * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial
 
2339
 * gradient pattern.
 
2340
 *
 
2341
 * Since: 1.4
 
2342
 **/
 
2343
cairo_status_t
 
2344
cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
 
2345
                                  double *x0, double *y0, double *r0,
 
2346
                                  double *x1, double *y1, double *r1)
 
2347
{
 
2348
    cairo_radial_pattern_t *radial = (cairo_radial_pattern_t*) pattern;
 
2349
 
 
2350
    if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
 
2351
        return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
 
2352
 
 
2353
    if (x0)
 
2354
        *x0 = _cairo_fixed_to_double (radial->c1.x);
 
2355
    if (y0)
 
2356
        *y0 = _cairo_fixed_to_double (radial->c1.y);
 
2357
    if (r0)
 
2358
        *r0 = _cairo_fixed_to_double (radial->r1);
 
2359
    if (x1)
 
2360
        *x1 = _cairo_fixed_to_double (radial->c2.x);
 
2361
    if (y1)
 
2362
        *y1 = _cairo_fixed_to_double (radial->c2.y);
 
2363
    if (r1)
 
2364
        *r1 = _cairo_fixed_to_double (radial->r2);
 
2365
 
 
2366
    return CAIRO_STATUS_SUCCESS;
 
2367
}
 
2368
 
 
2369
void
 
2370
_cairo_pattern_reset_static_data (void)
 
2371
{
 
2372
    _cairo_pattern_reset_solid_pattern_cache ();
 
2373
    _cairo_pattern_reset_solid_surface_cache ();
 
2374
}