Subversion Repositories Scribus

Rev

Rev 14952 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
14952 fschmid 1
/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2
/* cairo - a vector graphics library with display and print output
3
 *
4
 * Copyright © 2002 University of Southern California
5
 * Copyright © 2005 Red Hat, Inc.
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it either under the terms of the GNU Lesser General Public
9
 * License version 2.1 as published by the Free Software Foundation
10
 * (the "LGPL") or, at your option, under the terms of the Mozilla
11
 * Public License Version 1.1 (the "MPL"). If you do not alter this
12
 * notice, a recipient may use your version of this file under either
13
 * the MPL or the LGPL.
14
 *
15
 * You should have received a copy of the LGPL along with this library
16
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
18122 mrdocs 17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14952 fschmid 18
 * You should have received a copy of the MPL along with this library
19
 * in the file COPYING-MPL-1.1
20
 *
21
 * The contents of this file are subject to the Mozilla Public License
22
 * Version 1.1 (the "License"); you may not use this file except in
23
 * compliance with the License. You may obtain a copy of the License at
24
 * http://www.mozilla.org/MPL/
25
 *
26
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28
 * the specific language governing rights and limitations.
29
 *
30
 * The Original Code is the cairo graphics library.
31
 *
32
 * The Initial Developer of the Original Code is University of Southern
33
 * California.
34
 *
35
 * Contributor(s):
36
 *      Carl D. Worth <cworth@cworth.org>
37
 */
38
 
39
#include "cairoint.h"
40
 
41
#include "cairo-surface-fallback-private.h"
42
#include "cairo-clip-private.h"
43
#include "cairo-meta-surface-private.h"
44
#include "cairo-region-private.h"
45
#include "cairo-tee-surface-private.h"
46
 
47
#define DEFINE_NIL_SURFACE(status, name)                        \
48
const cairo_surface_t name = {                                  \
49
    NULL,                               /* backend */           \
50
    CAIRO_SURFACE_TYPE_IMAGE,           /* type */              \
51
    CAIRO_CONTENT_COLOR,                /* content */           \
52
    CAIRO_REFERENCE_COUNT_INVALID,      /* ref_count */         \
53
    status,                             /* status */            \
54
    FALSE,                              /* finished */          \
55
    0,                                  /* unique id */         \
56
    { 0, 0, 0, NULL, },                 /* user_data */         \
57
    { 0, 0, 0, NULL, },                 /* mime_data */         \
58
    { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 },   /* device_transform */  \
59
    { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 },   /* device_transform_inverse */  \
60
    0.0,                                /* x_resolution */      \
61
    0.0,                                /* y_resolution */      \
62
    0.0,                                /* x_fallback_resolution */     \
63
    0.0,                                /* y_fallback_resolution */     \
64
    NULL,                               /* snapshot_of */       \
65
    NULL,                               /* snapshot_detach */   \
66
    { 0,        /* size */                                      \
67
      0,        /* num_elements */                              \
68
      0,        /* element_size */                              \
69
      NULL,     /* elements */                                  \
70
    },                                  /* snapshots */         \
71
    FALSE,                              /* has_font_options */  \
72
    { CAIRO_ANTIALIAS_DEFAULT,          /* antialias */         \
73
      CAIRO_SUBPIXEL_ORDER_DEFAULT,     /* subpixel_order */    \
74
      CAIRO_HINT_STYLE_DEFAULT,         /* hint_style */        \
75
      CAIRO_HINT_METRICS_DEFAULT        /* hint_metrics */      \
76
    }                                   /* font_options */      \
77
}
78
 
79
/* XXX error object! */
80
 
81
static DEFINE_NIL_SURFACE(CAIRO_STATUS_NO_MEMORY, _cairo_surface_nil);
82
static DEFINE_NIL_SURFACE(CAIRO_STATUS_SURFACE_TYPE_MISMATCH, _cairo_surface_nil_surface_type_mismatch);
83
static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_STATUS, _cairo_surface_nil_invalid_status);
84
static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_CONTENT, _cairo_surface_nil_invalid_content);
85
static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_FORMAT, _cairo_surface_nil_invalid_format);
86
static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_VISUAL, _cairo_surface_nil_invalid_visual);
87
static DEFINE_NIL_SURFACE(CAIRO_STATUS_FILE_NOT_FOUND, _cairo_surface_nil_file_not_found);
88
static DEFINE_NIL_SURFACE(CAIRO_STATUS_TEMP_FILE_ERROR, _cairo_surface_nil_temp_file_error);
89
static DEFINE_NIL_SURFACE(CAIRO_STATUS_READ_ERROR, _cairo_surface_nil_read_error);
90
static DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error);
91
static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_STRIDE, _cairo_surface_nil_invalid_stride);
92
static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_SIZE, _cairo_surface_nil_invalid_size);
93
 
94
static void
95
_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t **pattern,
96
                                             cairo_surface_t *destination,
97
                                             cairo_pattern_t *pattern_copy);
98
 
99
/**
100
 * _cairo_surface_set_error:
101
 * @surface: a surface
102
 * @status: a status value indicating an error
103
 *
104
 * Atomically sets surface->status to @status and calls _cairo_error;
105
 * Does nothing if status is %CAIRO_STATUS_SUCCESS or any of the internal
106
 * status values.
107
 *
108
 * All assignments of an error status to surface->status should happen
109
 * through _cairo_surface_set_error(). Note that due to the nature of
110
 * the atomic operation, it is not safe to call this function on the
111
 * nil objects.
112
 *
113
 * The purpose of this function is to allow the user to set a
114
 * breakpoint in _cairo_error() to generate a stack trace for when the
115
 * user causes cairo to detect an error.
116
 *
117
 * Return value: the error status.
118
 **/
119
cairo_status_t
120
_cairo_surface_set_error (cairo_surface_t *surface,
121
                          cairo_status_t status)
122
{
123
    if (status == CAIRO_STATUS_SUCCESS || status >= CAIRO_INT_STATUS_UNSUPPORTED)
124
        return status;
125
 
126
    /* Don't overwrite an existing error. This preserves the first
127
     * error, which is the most significant. */
128
    _cairo_status_set_error (&surface->status, status);
129
 
130
    return _cairo_error (status);
131
}
132
 
133
/**
134
 * cairo_surface_get_type:
135
 * @surface: a #cairo_surface_t
136
 *
137
 * This function returns the type of the backend used to create
138
 * a surface. See #cairo_surface_type_t for available types.
139
 *
140
 * Return value: The type of @surface.
141
 *
142
 * Since: 1.2
143
 **/
144
cairo_surface_type_t
145
cairo_surface_get_type (cairo_surface_t *surface)
146
{
147
    /* We don't use surface->backend->type here so that some of the
148
     * special "wrapper" surfaces such as cairo_paginated_surface_t
149
     * can override surface->type with the type of the "child"
150
     * surface. */
151
    return surface->type;
152
}
153
slim_hidden_def (cairo_surface_get_type);
154
 
155
/**
156
 * cairo_surface_get_content:
157
 * @surface: a #cairo_surface_t
158
 *
159
 * This function returns the content type of @surface which indicates
160
 * whether the surface contains color and/or alpha information. See
161
 * #cairo_content_t.
162
 *
163
 * Return value: The content type of @surface.
164
 *
165
 * Since: 1.2
166
 **/
167
cairo_content_t
168
cairo_surface_get_content (cairo_surface_t *surface)
169
{
170
    return surface->content;
171
}
172
slim_hidden_def(cairo_surface_get_content);
173
 
174
/**
175
 * cairo_surface_status:
176
 * @surface: a #cairo_surface_t
177
 *
178
 * Checks whether an error has previously occurred for this
179
 * surface.
180
 *
181
 * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NULL_POINTER,
182
 * %CAIRO_STATUS_NO_MEMORY, %CAIRO_STATUS_READ_ERROR,
183
 * %CAIRO_STATUS_INVALID_CONTENT, %CAIRO_STATUS_INVALID_FORMAT, or
184
 * %CAIRO_STATUS_INVALID_VISUAL.
185
 **/
186
cairo_status_t
187
cairo_surface_status (cairo_surface_t *surface)
188
{
189
    return surface->status;
190
}
191
slim_hidden_def (cairo_surface_status);
192
 
193
static unsigned int
194
_cairo_surface_allocate_unique_id (void)
195
{
196
    static unsigned int unique_id;
197
 
198
#if CAIRO_NO_MUTEX
199
    if (++unique_id == 0)
200
        unique_id = 1;
201
    return unique_id;
202
#else
203
    unsigned int old, id;
204
 
205
    do {
206
        old = _cairo_atomic_uint_get (&unique_id);
207
        id = old + 1;
208
        if (id == 0)
209
            id = 1;
210
    } while (! _cairo_atomic_uint_cmpxchg (&unique_id, old, id));
211
 
212
    return id;
213
#endif
214
}
215
 
216
static cairo_bool_t
217
_cairo_surface_has_snapshots (cairo_surface_t *surface)
218
{
219
    return surface->snapshots.num_elements != 0;
220
}
221
 
222
static void
223
_cairo_surface_detach_snapshots (cairo_surface_t *surface)
224
{
225
    cairo_surface_t **snapshots;
226
    unsigned int i;
227
 
228
    if (! _cairo_surface_has_snapshots (surface))
229
        return;
230
 
231
    /* XXX do something intelligent! */
232
 
233
    snapshots = _cairo_array_index (&surface->snapshots, 0);
234
    for (i = 0; i < surface->snapshots.num_elements; i++) {
235
        snapshots[i]->snapshot_of = NULL;
236
 
237
        if (snapshots[i]->snapshot_detach != NULL)
238
            snapshots[i]->snapshot_detach (snapshots[i]);
239
 
240
        cairo_surface_destroy (snapshots[i]);
241
    }
242
    surface->snapshots.num_elements = 0;
243
 
244
    assert (! _cairo_surface_has_snapshots (surface));
245
}
246
 
247
cairo_status_t
248
_cairo_surface_attach_snapshot (cairo_surface_t *surface,
249
                                cairo_surface_t *snapshot,
250
                                cairo_surface_func_t detach_func)
251
{
252
    cairo_status_t status;
253
 
254
    assert (surface != snapshot);
255
 
256
    if (snapshot->snapshot_of != NULL)
257
        _cairo_surface_detach_snapshot (snapshot);
258
 
259
    snapshot->snapshot_of = surface;
260
    snapshot->snapshot_detach = detach_func;
261
 
262
    status = _cairo_array_append (&surface->snapshots, &snapshot);
263
    if (unlikely (status))
264
        return status;
265
 
266
    cairo_surface_reference (snapshot);
267
    return CAIRO_STATUS_SUCCESS;
268
}
269
 
270
cairo_surface_t *
271
_cairo_surface_has_snapshot (cairo_surface_t *surface,
272
                             const cairo_surface_backend_t *backend,
273
                             cairo_content_t content)
274
{
275
    cairo_surface_t **snapshots;
276
    unsigned int i;
277
 
278
    snapshots = _cairo_array_index (&surface->snapshots, 0);
279
    for (i = 0; i < surface->snapshots.num_elements; i++) {
280
        if (snapshots[i]->backend == backend &&
281
            snapshots[i]->content == content)
282
        {
283
            return snapshots[i];
284
        }
285
    }
286
 
287
    return NULL;
288
}
289
 
290
void
291
_cairo_surface_detach_snapshot (cairo_surface_t *snapshot)
292
{
293
    cairo_surface_t *surface;
294
    cairo_surface_t **snapshots;
295
    unsigned int i;
296
 
297
    assert (snapshot->snapshot_of != NULL);
298
    surface = snapshot->snapshot_of;
299
 
300
    snapshots = _cairo_array_index (&surface->snapshots, 0);
301
    for (i = 0; i < surface->snapshots.num_elements; i++) {
302
        if (snapshots[i] == snapshot)
303
            break;
304
    }
305
    assert (i < surface->snapshots.num_elements);
306
 
307
    surface->snapshots.num_elements--;
308
    memmove (&snapshots[i],
309
             &snapshots[i+1],
310
             sizeof (cairo_surface_t *)*(surface->snapshots.num_elements - i));
311
 
312
    snapshot->snapshot_of = NULL;
313
 
314
    if (snapshot->snapshot_detach != NULL)
315
        snapshot->snapshot_detach (snapshot);
316
 
317
    cairo_surface_destroy (snapshot);
318
}
319
 
320
static cairo_bool_t
321
_cairo_surface_is_writable (cairo_surface_t *surface)
322
{
323
    return ! surface->finished &&
324
           surface->snapshot_of == NULL &&
325
           ! _cairo_surface_has_snapshots (surface);
326
}
327
 
328
static void
329
_cairo_surface_begin_modification (cairo_surface_t *surface)
330
{
331
    assert (surface->status == CAIRO_STATUS_SUCCESS);
332
    assert (! surface->finished);
333
    assert (surface->snapshot_of == NULL);
334
 
335
    _cairo_surface_detach_snapshots (surface);
336
}
337
 
338
void
339
_cairo_surface_init (cairo_surface_t                    *surface,
340
                     const cairo_surface_backend_t      *backend,
341
                     cairo_content_t                     content)
342
{
343
    CAIRO_MUTEX_INITIALIZE ();
344
 
345
    surface->backend = backend;
346
    surface->content = content;
347
    surface->type = backend->type;
348
 
349
    CAIRO_REFERENCE_COUNT_INIT (&surface->ref_count, 1);
350
    surface->status = CAIRO_STATUS_SUCCESS;
351
    surface->finished = FALSE;
352
    surface->unique_id = _cairo_surface_allocate_unique_id ();
353
 
354
    _cairo_user_data_array_init (&surface->user_data);
355
    _cairo_user_data_array_init (&surface->mime_data);
356
 
357
    cairo_matrix_init_identity (&surface->device_transform);
358
    cairo_matrix_init_identity (&surface->device_transform_inverse);
359
 
360
    surface->x_resolution = CAIRO_SURFACE_RESOLUTION_DEFAULT;
361
    surface->y_resolution = CAIRO_SURFACE_RESOLUTION_DEFAULT;
362
 
363
    surface->x_fallback_resolution = CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT;
364
    surface->y_fallback_resolution = CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT;
365
 
366
    _cairo_array_init (&surface->snapshots, sizeof (cairo_surface_t *));
367
    surface->snapshot_of = NULL;
368
 
369
    surface->has_font_options = FALSE;
370
}
371
 
372
static void
373
_cairo_surface_copy_similar_properties (cairo_surface_t *surface,
374
                                        cairo_surface_t *other)
375
{
376
    if (other->has_font_options || other->backend != surface->backend) {
377
        cairo_font_options_t options;
378
 
379
        cairo_surface_get_font_options (other, &options);
380
        _cairo_surface_set_font_options (surface, &options);
381
    }
382
 
383
    cairo_surface_set_fallback_resolution (surface,
384
                                           other->x_fallback_resolution,
385
                                           other->y_fallback_resolution);
386
}
387
 
388
cairo_surface_t *
389
_cairo_surface_create_similar_scratch (cairo_surface_t *other,
390
                                       cairo_content_t  content,
391
                                       int              width,
392
                                       int              height)
393
{
394
    cairo_surface_t *surface;
395
 
396
    if (unlikely (other->status))
397
        return _cairo_surface_create_in_error (other->status);
398
 
399
    if (other->backend->create_similar == NULL)
400
        return NULL;
401
 
402
    surface = other->backend->create_similar (other,
403
                                              content, width, height);
404
    if (surface == NULL || surface->status)
405
        return surface;
406
 
407
    _cairo_surface_copy_similar_properties (surface, other);
408
 
409
    return surface;
410
}
411
 
412
/**
413
 * cairo_surface_create_similar:
414
 * @other: an existing surface used to select the backend of the new surface
415
 * @content: the content for the new surface
416
 * @width: width of the new surface, (in device-space units)
417
 * @height: height of the new surface (in device-space units)
418
 *
419
 * Create a new surface that is as compatible as possible with an
420
 * existing surface. For example the new surface will have the same
421
 * fallback resolution and font options as @other. Generally, the new
422
 * surface will also use the same backend as @other, unless that is
423
 * not possible for some reason. The type of the returned surface may
424
 * be examined with cairo_surface_get_type().
425
 *
426
 * Initially the surface contents are all 0 (transparent if contents
427
 * have transparency, black otherwise.)
428
 *
429
 * Return value: a pointer to the newly allocated surface. The caller
430
 * owns the surface and should call cairo_surface_destroy() when done
431
 * with it.
432
 *
433
 * This function always returns a valid pointer, but it will return a
434
 * pointer to a "nil" surface if @other is already in an error state
435
 * or any other error occurs.
436
 **/
437
cairo_surface_t *
438
cairo_surface_create_similar (cairo_surface_t  *other,
439
                              cairo_content_t   content,
440
                              int               width,
441
                              int               height)
442
{
443
    if (unlikely (other->status))
444
        return _cairo_surface_create_in_error (other->status);
445
 
446
    if (unlikely (! CAIRO_CONTENT_VALID (content)))
447
        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT));
448
 
449
    return _cairo_surface_create_similar_solid (other,
450
                                                content, width, height,
451
                                                CAIRO_COLOR_TRANSPARENT,
452
                                                TRUE);
453
}
454
 
455
cairo_surface_t *
456
_cairo_surface_create_similar_solid (cairo_surface_t     *other,
457
                                     cairo_content_t      content,
458
                                     int                  width,
459
                                     int                  height,
460
                                     const cairo_color_t *color,
461
                                     cairo_bool_t allow_fallback)
462
{
463
    cairo_status_t status;
464
    cairo_surface_t *surface;
465
    cairo_solid_pattern_t pattern;
466
 
467
    surface = _cairo_surface_create_similar_scratch (other, content,
468
                                                     width, height);
469
    if (surface == NULL && allow_fallback)
470
        surface = _cairo_image_surface_create_with_content (content,
471
                                                            width, height);
472
    if (surface == NULL || surface->status)
473
        return surface;
474
 
475
    _cairo_pattern_init_solid (&pattern, color, content);
476
    status = _cairo_surface_paint (surface,
477
                                   color == CAIRO_COLOR_TRANSPARENT ?
478
                                   CAIRO_OPERATOR_CLEAR : CAIRO_OPERATOR_SOURCE,
479
                                   &pattern.base, NULL);
480
    if (unlikely (status)) {
481
        cairo_surface_destroy (surface);
482
        surface = _cairo_surface_create_in_error (status);
483
    }
484
 
485
    return surface;
486
}
487
 
488
cairo_surface_t *
489
_cairo_surface_create_solid_pattern_surface (cairo_surface_t       *other,
490
                                             const cairo_solid_pattern_t *solid_pattern)
491
{
492
    if (other->backend->create_solid_pattern_surface != NULL) {
493
        cairo_surface_t *surface;
494
 
495
        surface = other->backend->create_solid_pattern_surface (other,
496
                                                                solid_pattern);
497
        if (surface)
498
            return surface;
499
    }
500
 
501
    return _cairo_surface_create_similar_solid (other,
502
                                                solid_pattern->content,
503
                                                1, 1,
504
                                                &solid_pattern->color,
505
                                                FALSE);
506
}
507
 
508
cairo_int_status_t
509
_cairo_surface_repaint_solid_pattern_surface (cairo_surface_t       *other,
510
                                              cairo_surface_t       *solid_surface,
511
                                              const cairo_solid_pattern_t *solid_pattern)
512
{
513
    /* Solid pattern surface for these backends are special and not trivial
514
     * to repaint.  Skip repainting.
515
     *
516
     * This does not work optimally with things like analysis surface that
517
     * are proxies.  But returning UNSUPPORTED is *safe* as it only
518
     * disables some caching.
519
     */
520
    if (other->backend->create_solid_pattern_surface != NULL &&
521
        ! other->backend->can_repaint_solid_pattern_surface (solid_surface,
522
                                                             solid_pattern))
523
    {
524
        return CAIRO_INT_STATUS_UNSUPPORTED;
525
    }
526
 
527
    return _cairo_surface_paint (solid_surface,
528
                                 CAIRO_OPERATOR_SOURCE,
529
                                 &solid_pattern->base,
530
                                 NULL);
531
}
532
 
533
/**
534
 * cairo_surface_reference:
535
 * @surface: a #cairo_surface_t
536
 *
537
 * Increases the reference count on @surface by one. This prevents
538
 * @surface from being destroyed until a matching call to
539
 * cairo_surface_destroy() is made.
540
 *
541
 * The number of references to a #cairo_surface_t can be get using
542
 * cairo_surface_get_reference_count().
543
 *
544
 * Return value: the referenced #cairo_surface_t.
545
 **/
546
cairo_surface_t *
547
cairo_surface_reference (cairo_surface_t *surface)
548
{
549
    if (surface == NULL ||
550
            CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
551
        return surface;
552
 
553
    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count));
554
 
555
    _cairo_reference_count_inc (&surface->ref_count);
556
 
557
    return surface;
558
}
559
slim_hidden_def (cairo_surface_reference);
560
 
561
/**
562
 * cairo_surface_destroy:
563
 * @surface: a #cairo_surface_t
564
 *
565
 * Decreases the reference count on @surface by one. If the result is
566
 * zero, then @surface and all associated resources are freed.  See
567
 * cairo_surface_reference().
568
 **/
569
void
570
cairo_surface_destroy (cairo_surface_t *surface)
571
{
572
    if (surface == NULL ||
573
            CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
574
        return;
575
 
576
    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count));
577
 
578
    if (! _cairo_reference_count_dec_and_test (&surface->ref_count))
579
        return;
580
 
581
    assert (surface->snapshot_of == NULL);
582
 
583
    if (! surface->finished)
584
        cairo_surface_finish (surface);
585
 
586
    _cairo_user_data_array_fini (&surface->user_data);
587
    _cairo_user_data_array_fini (&surface->mime_data);
588
    _cairo_array_fini (&surface->snapshots);
589
 
590
    free (surface);
591
}
592
slim_hidden_def(cairo_surface_destroy);
593
 
594
/**
595
 * cairo_surface_get_reference_count:
596
 * @surface: a #cairo_surface_t
597
 *
598
 * Returns the current reference count of @surface.
599
 *
600
 * Return value: the current reference count of @surface.  If the
601
 * object is a nil object, 0 will be returned.
602
 *
603
 * Since: 1.4
604
 **/
605
unsigned int
606
cairo_surface_get_reference_count (cairo_surface_t *surface)
607
{
608
    if (surface == NULL ||
609
            CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
610
        return 0;
611
 
612
    return CAIRO_REFERENCE_COUNT_GET_VALUE (&surface->ref_count);
613
}
614
 
615
/**
616
 * cairo_surface_finish:
617
 * @surface: the #cairo_surface_t to finish
618
 *
619
 * This function finishes the surface and drops all references to
620
 * external resources.  For example, for the Xlib backend it means
621
 * that cairo will no longer access the drawable, which can be freed.
622
 * After calling cairo_surface_finish() the only valid operations on a
623
 * surface are getting and setting user, referencing and
624
 * destroying, and flushing and finishing it.
625
 * Further drawing to the surface will not affect the
626
 * surface but will instead trigger a %CAIRO_STATUS_SURFACE_FINISHED
627
 * error.
628
 *
629
 * When the last call to cairo_surface_destroy() decreases the
630
 * reference count to zero, cairo will call cairo_surface_finish() if
631
 * it hasn't been called already, before freeing the resources
632
 * associated with the surface.
633
 **/
634
void
635
cairo_surface_finish (cairo_surface_t *surface)
636
{
637
    cairo_status_t status;
638
 
639
    if (surface == NULL)
640
        return;
641
 
642
    if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
643
        return;
644
 
645
    if (surface->finished)
646
        return;
647
 
648
    cairo_surface_flush (surface);
649
 
650
    /* call finish even if in error mode */
651
    if (surface->backend->finish) {
652
        status = surface->backend->finish (surface);
653
        if (unlikely (status))
654
            status = _cairo_surface_set_error (surface, status);
655
    }
656
 
657
    surface->finished = TRUE;
658
 
659
    if (surface->snapshot_of != NULL)
660
        _cairo_surface_detach_snapshot (surface);
661
}
662
slim_hidden_def (cairo_surface_finish);
663
 
664
/**
665
 * cairo_surface_get_user_data:
666
 * @surface: a #cairo_surface_t
667
 * @key: the address of the #cairo_user_data_key_t the user data was
668
 * attached to
669
 *
670
 * Return user data previously attached to @surface using the specified
671
 * key.  If no user data has been attached with the given key this
672
 * function returns %NULL.
673
 *
674
 * Return value: the user data previously attached or %NULL.
675
 **/
676
void *
677
cairo_surface_get_user_data (cairo_surface_t             *surface,
678
                             const cairo_user_data_key_t *key)
679
{
680
    return _cairo_user_data_array_get_data (&surface->user_data,
681
                                            key);
682
}
683
 
684
/**
685
 * cairo_surface_set_user_data:
686
 * @surface: a #cairo_surface_t
687
 * @key: the address of a #cairo_user_data_key_t to attach the user data to
688
 * @user_data: the user data to attach to the surface
689
 * @destroy: a #cairo_destroy_func_t which will be called when the
690
 * surface is destroyed or when new user data is attached using the
691
 * same key.
692
 *
693
 * Attach user data to @surface.  To remove user data from a surface,
694
 * call this function with the key that was used to set it and %NULL
695
 * for @data.
696
 *
697
 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
698
 * slot could not be allocated for the user data.
699
 **/
700
cairo_status_t
701
cairo_surface_set_user_data (cairo_surface_t             *surface,
702
                             const cairo_user_data_key_t *key,
703
                             void                        *user_data,
704
                             cairo_destroy_func_t        destroy)
705
{
706
    if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
707
        return surface->status;
708
 
709
    return _cairo_user_data_array_set_data (&surface->user_data,
710
                                            key, user_data, destroy);
711
}
712
 
713
/**
714
 * cairo_surface_get_mime_data:
715
 * @surface: a #cairo_surface_t
716
 * @mime_type: the mime type of the image data
717
 * @data: the image data to attached to the surface
718
 * @length: the length of the image data
719
 *
720
 * Return mime data previously attached to @surface using the
721
 * specified mime type.  If no data has been attached with the given
722
 * mime type, @data is set %NULL.
723
 *
724
 * Since: 1.10
725
 **/
726
void
727
cairo_surface_get_mime_data (cairo_surface_t            *surface,
728
                             const char                 *mime_type,
729
                             const unsigned char       **data,
730
                             unsigned int               *length)
731
{
732
    cairo_user_data_slot_t *slots;
733
    int i, num_slots;
734
 
735
    *data = NULL;
736
    *length = 0;
737
    if (unlikely (surface->status))
738
        return;
739
 
740
    /* The number of mime-types attached to a surface is usually small,
741
     * typically zero. Therefore it is quicker to do a strcmp() against
742
     * each key than it is to intern the string (i.e. compute a hash,
743
     * search the hash table, and do a final strcmp).
744
     */
745
    num_slots = surface->mime_data.num_elements;
746
    slots = _cairo_array_index (&surface->mime_data, 0);
747
    for (i = 0; i < num_slots; i++) {
748
        if (strcmp ((char *) slots[i].key, mime_type) == 0) {
749
            cairo_mime_data_t *mime_data = slots[i].user_data;
750
 
751
            *data = mime_data->data;
752
            *length = mime_data->length;
753
            return;
754
        }
755
    }
756
}
757
slim_hidden_def (cairo_surface_get_mime_data);
758
 
759
static void
760
_cairo_mime_data_destroy (void *ptr)
761
{
762
    cairo_mime_data_t *mime_data = ptr;
763
 
764
    if (! _cairo_reference_count_dec_and_test (&mime_data->ref_count))
765
        return;
766
 
767
    if (mime_data->destroy && mime_data->closure)
768
        mime_data->destroy (mime_data->closure);
769
 
770
    free (mime_data);
771
}
772
 
773
/**
774
 * cairo_surface_set_mime_data:
775
 * @surface: a #cairo_surface_t
776
 * @mime_type: the mime type of the image data
777
 * @data: the image data to attach to the surface
778
 * @length: the length of the image data
779
 * @destroy: a #cairo_destroy_func_t which will be called when the
780
 * surface is destroyed or when new image data is attached using the
781
 * same mime type.
782
 * @closure: the data to be passed to the @destroy notifier
783
 *
784
 * Attach an image in the format @mime_type to @surface. To remove
785
 * the data from a surface, call this function with same mime type
786
 * and %NULL for @data.
787
 *
788
 * Since: 1.10
789
 *
790
 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
791
 * slot could not be allocated for the user data.
792
 **/
793
cairo_status_t
794
cairo_surface_set_mime_data (cairo_surface_t            *surface,
795
                             const char                 *mime_type,
796
                             const unsigned char        *data,
797
                             unsigned int                length,
798
                             cairo_destroy_func_t        destroy,
799
                             void                       *closure)
800
{
801
    cairo_status_t status;
802
    cairo_mime_data_t *mime_data;
803
 
804
    if (unlikely (surface->status))
805
        return surface->status;
806
 
807
    status = _cairo_intern_string (&mime_type, -1);
808
    if (unlikely (status))
809
        return _cairo_surface_set_error (surface, status);
810
 
811
    if (data != NULL) {
812
        mime_data = malloc (sizeof (cairo_mime_data_t));
813
        if (unlikely (mime_data == NULL))
814
            return _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_NO_MEMORY));
815
 
816
        CAIRO_REFERENCE_COUNT_INIT (&mime_data->ref_count, 1);
817
 
818
        mime_data->data = (unsigned char *) data;
819
        mime_data->length = length;
820
        mime_data->destroy = destroy;
821
        mime_data->closure = closure;
822
    } else
823
        mime_data = NULL;
824
 
825
    status = _cairo_user_data_array_set_data (&surface->mime_data,
826
                                              (cairo_user_data_key_t *) mime_type,
827
                                              mime_data,
828
                                              _cairo_mime_data_destroy);
829
    if (unlikely (status)) {
830
        if (mime_data != NULL)
831
            free (mime_data);
832
 
833
        return _cairo_surface_set_error (surface, status);
834
    }
835
 
836
    return CAIRO_STATUS_SUCCESS;
837
}
838
slim_hidden_def (cairo_surface_set_mime_data);
839
 
840
static void
841
_cairo_mime_data_reference (const void *key, void *elt, void *closure)
842
{
843
    cairo_mime_data_t *mime_data = elt;
844
 
845
    _cairo_reference_count_inc (&mime_data->ref_count);
846
}
847
 
848
cairo_status_t
849
_cairo_surface_copy_mime_data (cairo_surface_t *dst,
850
                               cairo_surface_t *src)
851
{
852
    cairo_status_t status;
853
 
854
    if (dst->status)
855
        return dst->status;
856
 
857
    if (src->status)
858
        return _cairo_surface_set_error (dst, src->status);
859
 
860
    /* first copy the mime-data, discarding any already set on dst */
861
    status = _cairo_user_data_array_copy (&dst->mime_data, &src->mime_data);
862
    if (unlikely (status))
863
        return _cairo_surface_set_error (dst, status);
864
 
865
    /* now increment the reference counters for the copies */
866
    _cairo_user_data_array_foreach (&dst->mime_data,
867
                                    _cairo_mime_data_reference,
868
                                    NULL);
869
 
870
    return CAIRO_STATUS_SUCCESS;
871
}
872
 
873
/**
874
 * _cairo_surface_set_font_options:
875
 * @surface: a #cairo_surface_t
876
 * @options: a #cairo_font_options_t object that contains the
877
 *   options to use for this surface instead of backend's default
878
 *   font options.
879
 *
880
 * Sets the default font rendering options for the surface.
881
 * This is useful to correctly propagate default font options when
882
 * falling back to an image surface in a backend implementation.
883
 * This affects the options returned in cairo_surface_get_font_options().
884
 *
885
 * If @options is %NULL the surface options are reset to those of
886
 * the backend default.
887
 **/
888
void
889
_cairo_surface_set_font_options (cairo_surface_t       *surface,
890
                                 cairo_font_options_t  *options)
891
{
892
    cairo_status_t status;
893
 
894
    if (surface->status)
895
        return;
896
 
897
    assert (surface->snapshot_of == NULL);
898
 
899
    if (surface->finished) {
900
        status = _cairo_surface_set_error (surface,
901
                                           CAIRO_STATUS_SURFACE_FINISHED);
902
        return;
903
    }
904
 
905
    if (options) {
906
        surface->has_font_options = TRUE;
907
        _cairo_font_options_init_copy (&surface->font_options, options);
908
    } else {
909
        surface->has_font_options = FALSE;
910
    }
911
}
912
 
913
/**
914
 * cairo_surface_get_font_options:
915
 * @surface: a #cairo_surface_t
916
 * @options: a #cairo_font_options_t object into which to store
917
 *   the retrieved options. All existing values are overwritten
918
 *
919
 * Retrieves the default font rendering options for the surface.
920
 * This allows display surfaces to report the correct subpixel order
921
 * for rendering on them, print surfaces to disable hinting of
922
 * metrics and so forth. The result can then be used with
923
 * cairo_scaled_font_create().
924
 **/
925
void
926
cairo_surface_get_font_options (cairo_surface_t       *surface,
927
                                cairo_font_options_t  *options)
928
{
929
    if (cairo_font_options_status (options))
930
        return;
931
 
932
    if (surface->status) {
933
        _cairo_font_options_init_default (options);
934
        return;
935
    }
936
 
937
    if (! surface->has_font_options) {
938
        surface->has_font_options = TRUE;
939
 
940
        _cairo_font_options_init_default (&surface->font_options);
941
 
942
        if (!surface->finished && surface->backend->get_font_options) {
943
            surface->backend->get_font_options (surface, &surface->font_options);
944
        }
945
    }
946
 
947
    _cairo_font_options_init_copy (options, &surface->font_options);
948
}
949
slim_hidden_def (cairo_surface_get_font_options);
950
 
951
/**
952
 * cairo_surface_flush:
953
 * @surface: a #cairo_surface_t
954
 *
955
 * Do any pending drawing for the surface and also restore any
956
 * temporary modification's cairo has made to the surface's
957
 * state. This function must be called before switching from
958
 * drawing on the surface with cairo to drawing on it directly
959
 * with native APIs. If the surface doesn't support direct access,
960
 * then this function does nothing.
961
 **/
962
void
963
cairo_surface_flush (cairo_surface_t *surface)
964
{
965
    cairo_status_t status;
966
 
967
    if (surface->status)
968
        return;
969
 
970
    if (surface->finished)
971
        return;
972
 
973
    /* update the current snapshots *before* the user updates the surface */
974
    _cairo_surface_detach_snapshots (surface);
975
 
976
    if (surface->backend->flush) {
977
        status = surface->backend->flush (surface);
978
        if (unlikely (status))
979
            status = _cairo_surface_set_error (surface, status);
980
    }
981
}
982
slim_hidden_def (cairo_surface_flush);
983
 
984
/**
985
 * cairo_surface_mark_dirty:
986
 * @surface: a #cairo_surface_t
987
 *
988
 * Tells cairo that drawing has been done to surface using means other
989
 * than cairo, and that cairo should reread any cached areas. Note
990
 * that you must call cairo_surface_flush() before doing such drawing.
991
 */
992
void
993
cairo_surface_mark_dirty (cairo_surface_t *surface)
994
{
995
    cairo_surface_mark_dirty_rectangle (surface, 0, 0, -1, -1);
996
}
997
 
998
/**
999
 * cairo_surface_mark_dirty_rectangle:
1000
 * @surface: a #cairo_surface_t
1001
 * @x: X coordinate of dirty rectangle
1002
 * @y: Y coordinate of dirty rectangle
1003
 * @width: width of dirty rectangle
1004
 * @height: height of dirty rectangle
1005
 *
1006
 * Like cairo_surface_mark_dirty(), but drawing has been done only to
1007
 * the specified rectangle, so that cairo can retain cached contents
1008
 * for other parts of the surface.
1009
 *
1010
 * Any cached clip set on the surface will be reset by this function,
1011
 * to make sure that future cairo calls have the clip set that they
1012
 * expect.
1013
 */
1014
void
1015
cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
1016
                                    int              x,
1017
                                    int              y,
1018
                                    int              width,
1019
                                    int              height)
1020
{
1021
    cairo_status_t status;
1022
 
1023
    if (surface->status)
1024
        return;
1025
 
1026
    assert (surface->snapshot_of == NULL);
1027
 
1028
    if (surface->finished) {
1029
        status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
1030
        return;
1031
    }
1032
 
1033
    /* The application *should* have called cairo_surface_flush() before
1034
     * modifying the surface independently of cairo (and thus having to
1035
     * call mark_dirty()). */
1036
    assert (! _cairo_surface_has_snapshots (surface));
1037
 
1038
    if (surface->backend->mark_dirty_rectangle != NULL) {
1039
        /* XXX: FRAGILE: We're ignoring the scaling component of
1040
         * device_transform here. I don't know what the right thing to
1041
         * do would actually be if there were some scaling here, but
1042
         * we avoid this since device_transfom scaling is not exported
1043
         * publicly and mark_dirty is not used internally. */
1044
        status = surface->backend->mark_dirty_rectangle (surface,
1045
                                                         x + surface->device_transform.x0,
1046
                                                         y + surface->device_transform.y0,
1047
                                                         width, height);
1048
 
1049
        if (unlikely (status))
1050
            status = _cairo_surface_set_error (surface, status);
1051
    }
1052
}
1053
slim_hidden_def (cairo_surface_mark_dirty_rectangle);
1054
 
1055
/**
1056
 * _cairo_surface_set_device_scale:
1057
 * @surface: a #cairo_surface_t
1058
 * @sx: a scale factor in the X direction
1059
 * @sy: a scale factor in the Y direction
1060
 *
1061
 * Private function for setting an extra scale factor to affect all
1062
 * drawing to a surface. This is used, for example, when replaying a
1063
 * meta surface to an image fallback intended for an eventual
1064
 * vector-oriented backend. Since the meta surface will record
1065
 * coordinates in one backend space, but the image fallback uses a
1066
 * different backend space, (differing by the fallback resolution
1067
 * scale factors), we need a scale factor correction.
1068
 *
1069
 * Caution: Not all places we use device transform correctly handle
1070
 * both a translate and a scale.  An audit would be nice.
1071
 **/
1072
void
1073
_cairo_surface_set_device_scale (cairo_surface_t *surface,
1074
                                 double           sx,
1075
                                 double           sy)
1076
{
1077
    cairo_status_t status;
1078
 
1079
    if (surface->status)
1080
        return;
1081
 
1082
    assert (surface->snapshot_of == NULL);
1083
 
1084
    if (surface->finished) {
1085
        status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
1086
        return;
1087
    }
1088
 
1089
    _cairo_surface_begin_modification (surface);
1090
 
1091
    surface->device_transform.xx = sx;
1092
    surface->device_transform.yy = sy;
1093
    surface->device_transform.xy = 0.0;
1094
    surface->device_transform.yx = 0.0;
1095
 
1096
    surface->device_transform_inverse = surface->device_transform;
1097
    status = cairo_matrix_invert (&surface->device_transform_inverse);
1098
    /* should always be invertible unless given pathological input */
1099
    assert (status == CAIRO_STATUS_SUCCESS);
1100
}
1101
 
1102
/**
1103
 * cairo_surface_set_device_offset:
1104
 * @surface: a #cairo_surface_t
1105
 * @x_offset: the offset in the X direction, in device units
1106
 * @y_offset: the offset in the Y direction, in device units
1107
 *
1108
 * Sets an offset that is added to the device coordinates determined
1109
 * by the CTM when drawing to @surface. One use case for this function
1110
 * is when we want to create a #cairo_surface_t that redirects drawing
1111
 * for a portion of an onscreen surface to an offscreen surface in a
1112
 * way that is completely invisible to the user of the cairo
1113
 * API. Setting a transformation via cairo_translate() isn't
1114
 * sufficient to do this, since functions like
1115
 * cairo_device_to_user() will expose the hidden offset.
1116
 *
1117
 * Note that the offset affects drawing to the surface as well as
1118
 * using the surface in a source pattern.
1119
 **/
1120
void
1121
cairo_surface_set_device_offset (cairo_surface_t *surface,
1122
                                 double           x_offset,
1123
                                 double           y_offset)
1124
{
1125
    cairo_status_t status;
1126
 
1127
    if (surface->status)
1128
        return;
1129
 
1130
    assert (surface->snapshot_of == NULL);
1131
 
1132
    if (surface->finished) {
1133
        status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
1134
        return;
1135
    }
1136
 
1137
    _cairo_surface_begin_modification (surface);
1138
 
1139
    surface->device_transform.x0 = x_offset;
1140
    surface->device_transform.y0 = y_offset;
1141
 
1142
    surface->device_transform_inverse = surface->device_transform;
1143
    status = cairo_matrix_invert (&surface->device_transform_inverse);
1144
    /* should always be invertible unless given pathological input */
1145
    assert (status == CAIRO_STATUS_SUCCESS);
1146
}
1147
slim_hidden_def (cairo_surface_set_device_offset);
1148
 
1149
/**
1150
 * cairo_surface_get_device_offset:
1151
 * @surface: a #cairo_surface_t
1152
 * @x_offset: the offset in the X direction, in device units
1153
 * @y_offset: the offset in the Y direction, in device units
1154
 *
1155
 * This function returns the previous device offset set by
1156
 * cairo_surface_set_device_offset().
1157
 *
1158
 * Since: 1.2
1159
 **/
1160
void
1161
cairo_surface_get_device_offset (cairo_surface_t *surface,
1162
                                 double          *x_offset,
1163
                                 double          *y_offset)
1164
{
1165
    if (x_offset)
1166
        *x_offset = surface->device_transform.x0;
1167
    if (y_offset)
1168
        *y_offset = surface->device_transform.y0;
1169
}
1170
slim_hidden_def (cairo_surface_get_device_offset);
1171
 
1172
/**
1173
 * cairo_surface_set_fallback_resolution:
1174
 * @surface: a #cairo_surface_t
1175
 * @x_pixels_per_inch: horizontal setting for pixels per inch
1176
 * @y_pixels_per_inch: vertical setting for pixels per inch
1177
 *
1178
 * Set the horizontal and vertical resolution for image fallbacks.
1179
 *
1180
 * When certain operations aren't supported natively by a backend,
1181
 * cairo will fallback by rendering operations to an image and then
1182
 * overlaying that image onto the output. For backends that are
1183
 * natively vector-oriented, this function can be used to set the
1184
 * resolution used for these image fallbacks, (larger values will
1185
 * result in more detailed images, but also larger file sizes).
1186
 *
1187
 * Some examples of natively vector-oriented backends are the ps, pdf,
1188
 * and svg backends.
1189
 *
1190
 * For backends that are natively raster-oriented, image fallbacks are
1191
 * still possible, but they are always performed at the native
1192
 * device resolution. So this function has no effect on those
1193
 * backends.
1194
 *
1195
 * Note: The fallback resolution only takes effect at the time of
1196
 * completing a page (with cairo_show_page() or cairo_copy_page()) so
1197
 * there is currently no way to have more than one fallback resolution
1198
 * in effect on a single page.
1199
 *
1200
 * The default fallback resoultion is 300 pixels per inch in both
1201
 * dimensions.
1202
 *
1203
 * Since: 1.2
1204
 **/
1205
void
1206
cairo_surface_set_fallback_resolution (cairo_surface_t  *surface,
1207
                                       double            x_pixels_per_inch,
1208
                                       double            y_pixels_per_inch)
1209
{
1210
    cairo_status_t status;
1211
 
1212
    if (surface->status)
1213
        return;
1214
 
1215
    assert (surface->snapshot_of == NULL);
1216
 
1217
    if (surface->finished) {
1218
        status = _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
1219
        return;
1220
    }
1221
 
1222
    if (x_pixels_per_inch <= 0 || y_pixels_per_inch <= 0) {
1223
        /* XXX Could delay raising the error until we fallback, but throwing
1224
         * the error here means that we can catch the real culprit.
1225
         */
1226
        status = _cairo_surface_set_error (surface, CAIRO_STATUS_INVALID_MATRIX);
1227
        return;
1228
    }
1229
 
1230
    _cairo_surface_begin_modification (surface);
1231
 
1232
    surface->x_fallback_resolution = x_pixels_per_inch;
1233
    surface->y_fallback_resolution = y_pixels_per_inch;
1234
}
1235
slim_hidden_def (cairo_surface_set_fallback_resolution);
1236
 
1237
/**
1238
 * cairo_surface_get_fallback_resolution:
1239
 * @surface: a #cairo_surface_t
1240
 * @x_pixels_per_inch: horizontal pixels per inch
1241
 * @y_pixels_per_inch: vertical pixels per inch
1242
 *
1243
 * This function returns the previous fallback resolution set by
1244
 * cairo_surface_set_fallback_resolution(), or default fallback
1245
 * resolution if never set.
1246
 *
1247
 * Since: 1.8
1248
 **/
1249
void
1250
cairo_surface_get_fallback_resolution (cairo_surface_t  *surface,
1251
                                       double           *x_pixels_per_inch,
1252
                                       double           *y_pixels_per_inch)
1253
{
1254
    if (x_pixels_per_inch)
1255
        *x_pixels_per_inch = surface->x_fallback_resolution;
1256
    if (y_pixels_per_inch)
1257
        *y_pixels_per_inch = surface->y_fallback_resolution;
1258
}
1259
 
1260
cairo_bool_t
1261
_cairo_surface_has_device_transform (cairo_surface_t *surface)
1262
{
1263
    return ! _cairo_matrix_is_identity (&surface->device_transform);
1264
}
1265
 
1266
/**
1267
 * _cairo_surface_acquire_source_image:
1268
 * @surface: a #cairo_surface_t
1269
 * @image_out: location to store a pointer to an image surface that
1270
 *    has identical contents to @surface. This surface could be @surface
1271
 *    itself, a surface held internal to @surface, or it could be a new
1272
 *    surface with a copy of the relevant portion of @surface.
1273
 * @image_extra: location to store image specific backend data
1274
 *
1275
 * Gets an image surface to use when drawing as a fallback when drawing with
1276
 * @surface as a source. _cairo_surface_release_source_image() must be called
1277
 * when finished.
1278
 *
1279
 * Return value: %CAIRO_STATUS_SUCCESS if an image was stored in @image_out.
1280
 * %CAIRO_INT_STATUS_UNSUPPORTED if an image cannot be retrieved for the specified
1281
 * surface. Or %CAIRO_STATUS_NO_MEMORY.
1282
 **/
1283
cairo_status_t
1284
_cairo_surface_acquire_source_image (cairo_surface_t         *surface,
1285
                                     cairo_image_surface_t  **image_out,
1286
                                     void                   **image_extra)
1287
{
1288
    cairo_status_t status;
1289
 
1290
    if (surface->status)
1291
        return surface->status;
1292
 
1293
    assert (!surface->finished);
1294
 
1295
    if (surface->backend->acquire_source_image == NULL)
1296
        return CAIRO_INT_STATUS_UNSUPPORTED;
1297
 
1298
    status = surface->backend->acquire_source_image (surface,
1299
                                                     image_out, image_extra);
1300
    if (unlikely (status))
1301
        return _cairo_surface_set_error (surface, status);
1302
 
1303
    _cairo_debug_check_image_surface_is_defined (&(*image_out)->base);
1304
 
1305
    return CAIRO_STATUS_SUCCESS;
1306
}
1307
 
1308
/**
1309
 * _cairo_surface_release_source_image:
1310
 * @surface: a #cairo_surface_t
1311
 * @image_extra: same as return from the matching _cairo_surface_acquire_source_image()
1312
 *
1313
 * Releases any resources obtained with _cairo_surface_acquire_source_image()
1314
 **/
1315
void
1316
_cairo_surface_release_source_image (cairo_surface_t        *surface,
1317
                                     cairo_image_surface_t  *image,
1318
                                     void                   *image_extra)
1319
{
1320
    assert (!surface->finished);
1321
 
1322
    if (surface->backend->release_source_image)
1323
        surface->backend->release_source_image (surface, image, image_extra);
1324
}
1325
 
1326
/**
1327
 * _cairo_surface_acquire_dest_image:
1328
 * @surface: a #cairo_surface_t
1329
 * @interest_rect: area of @surface for which fallback drawing is being done.
1330
 *    A value of %NULL indicates that the entire surface is desired.
1331
 *    XXXX I'd like to get rid of being able to pass %NULL here (nothing seems to)
1332
 * @image_out: location to store a pointer to an image surface that includes at least
1333
 *    the intersection of @interest_rect with the visible area of @surface.
1334
 *    This surface could be @surface itself, a surface held internal to @surface,
1335
 *    or it could be a new surface with a copy of the relevant portion of @surface.
1336
 *    If a new surface is created, it should have the same channels and depth
1337
 *    as @surface so that copying to and from it is exact.
1338
 * @image_rect: location to store area of the original surface occupied
1339
 *    by the surface stored in @image.
1340
 * @image_extra: location to store image specific backend data
1341
 *
1342
 * Retrieves a local image for a surface for implementing a fallback drawing
1343
 * operation. After calling this function, the implementation of the fallback
1344
 * drawing operation draws the primitive to the surface stored in @image_out
1345
 * then calls _cairo_surface_release_dest_image(),
1346
 * which, if a temporary surface was created, copies the bits back to the
1347
 * main surface and frees the temporary surface.
1348
 *
1349
 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY.
1350
 *  %CAIRO_INT_STATUS_UNSUPPORTED can be returned but this will mean that
1351
 *  the backend can't draw with fallbacks. It's possible for the routine
1352
 *  to store %NULL in @local_out and return %CAIRO_STATUS_SUCCESS;
1353
 *  that indicates that no part of @interest_rect is visible, so no drawing
1354
 *  is necessary. _cairo_surface_release_dest_image() should not be called in that
1355
 *  case.
1356
 **/
1357
cairo_status_t
1358
_cairo_surface_acquire_dest_image (cairo_surface_t         *surface,
1359
                                   cairo_rectangle_int_t   *interest_rect,
1360
                                   cairo_image_surface_t  **image_out,
1361
                                   cairo_rectangle_int_t   *image_rect,
1362
                                   void                   **image_extra)
1363
{
1364
    cairo_status_t status;
1365
 
1366
    if (surface->status)
1367
        return surface->status;
1368
 
1369
    assert (_cairo_surface_is_writable (surface));
1370
 
1371
    if (surface->backend->acquire_dest_image == NULL)
1372
        return CAIRO_INT_STATUS_UNSUPPORTED;
1373
 
1374
    status = surface->backend->acquire_dest_image (surface,
1375
                                                   interest_rect,
1376
                                                   image_out,
1377
                                                   image_rect,
1378
                                                   image_extra);
1379
    if (unlikely (status))
1380
        return _cairo_surface_set_error (surface, status);
1381
 
1382
    _cairo_debug_check_image_surface_is_defined (&(*image_out)->base);
1383
 
1384
    return CAIRO_STATUS_SUCCESS;
1385
}
1386
 
1387
/**
1388
 * _cairo_surface_release_dest_image:
1389
 * @surface: a #cairo_surface_t
1390
 * @interest_rect: same as passed to the matching _cairo_surface_acquire_dest_image()
1391
 * @image: same as returned from the matching _cairo_surface_acquire_dest_image()
1392
 * @image_rect: same as returned from the matching _cairo_surface_acquire_dest_image()
1393
 * @image_extra: same as return from the matching _cairo_surface_acquire_dest_image()
1394
 *
1395
 * Finishes the operation started with _cairo_surface_acquire_dest_image(), by, if
1396
 * necessary, copying the image from @image back to @surface and freeing any
1397
 * resources that were allocated.
1398
 **/
1399
void
1400
_cairo_surface_release_dest_image (cairo_surface_t         *surface,
1401
                                   cairo_rectangle_int_t   *interest_rect,
1402
                                   cairo_image_surface_t   *image,
1403
                                   cairo_rectangle_int_t   *image_rect,
1404
                                   void                    *image_extra)
1405
{
1406
    assert (_cairo_surface_is_writable (surface));
1407
 
1408
    if (surface->backend->release_dest_image)
1409
        surface->backend->release_dest_image (surface, interest_rect,
1410
                                              image, image_rect, image_extra);
1411
}
1412
 
1413
static cairo_status_t
1414
_cairo_meta_surface_clone_similar (cairo_surface_t  *surface,
1415
                                   cairo_surface_t  *src,
1416
                                   cairo_content_t   content,
1417
                                   int               src_x,
1418
                                   int               src_y,
1419
                                   int               width,
1420
                                   int               height,
1421
                                   int              *clone_offset_x,
1422
                                   int              *clone_offset_y,
1423
                                   cairo_surface_t **clone_out)
1424
{
1425
    cairo_meta_surface_t *meta = (cairo_meta_surface_t *) src;
1426
    cairo_surface_t *similar;
1427
    cairo_status_t status;
1428
 
1429
    similar = _cairo_surface_has_snapshot (src,
1430
                                           surface->backend,
1431
                                           src->content & content);
1432
    if (similar != NULL) {
1433
        *clone_out = cairo_surface_reference (similar);
1434
        *clone_offset_x = 0;
1435
        *clone_offset_y = 0;
1436
        return CAIRO_STATUS_SUCCESS;
1437
    }
1438
 
1439
    if (meta->unbounded ||
1440
        width*height*8 < meta->extents.width*meta->extents.height)
1441
    {
1442
        /* XXX use _solid to perform an initial CLEAR? */
1443
        similar = _cairo_surface_create_similar_scratch (surface,
1444
                                                         src->content & content,
1445
                                                         width, height);
1446
        if (similar == NULL)
1447
            return CAIRO_INT_STATUS_UNSUPPORTED;
1448
        if (unlikely (similar->status))
1449
            return similar->status;
1450
 
1451
        cairo_surface_set_device_offset (similar, -src_x, -src_y);
1452
 
1453
        status = cairo_meta_surface_replay (src, similar);
1454
        if (unlikely (status)) {
1455
            cairo_surface_destroy (similar);
1456
            return status;
1457
        }
1458
    } else {
1459
        similar = _cairo_surface_create_similar_scratch (surface,
1460
                                                         src->content & content,
1461
                                                         meta->extents.width,
1462
                                                         meta->extents.height);
1463
        if (similar == NULL)
1464
            return CAIRO_INT_STATUS_UNSUPPORTED;
1465
        if (unlikely (similar->status))
1466
            return similar->status;
1467
 
1468
        status = cairo_meta_surface_replay (src, similar);
1469
        if (unlikely (status)) {
1470
            cairo_surface_destroy (similar);
1471
            return status;
1472
        }
1473
 
1474
        status = _cairo_surface_attach_snapshot (src, similar, NULL);
1475
        if (unlikely (status)) {
1476
            cairo_surface_destroy (similar);
1477
            return status;
1478
        }
1479
 
1480
        src_x = src_y = 0;
1481
    }
1482
 
1483
    *clone_out = similar;
1484
    *clone_offset_x = src_x;
1485
    *clone_offset_y = src_y;
1486
    return CAIRO_STATUS_SUCCESS;
1487
}
1488
 
1489
/**
1490
 * _cairo_surface_clone_similar:
1491
 * @surface: a #cairo_surface_t
1492
 * @src: the source image
1493
 * @content: target content mask
1494
 * @src_x: extent for the rectangle in src we actually care about
1495
 * @src_y: extent for the rectangle in src we actually care about
1496
 * @width: extent for the rectangle in src we actually care about
1497
 * @height: extent for the rectangle in src we actually care about
1498
 * @clone_out: location to store a surface compatible with @surface
1499
 *   and with contents identical to @src. The caller must call
1500
 *   cairo_surface_destroy() on the result.
1501
 *
1502
 * Creates a surface with contents identical to @src but that
1503
 *   can be used efficiently with @surface. If @surface and @src are
1504
 *   already compatible then it may return a new reference to @src.
1505
 *
1506
 * Return value: %CAIRO_STATUS_SUCCESS if a surface was created and stored
1507
 *   in @clone_out. Otherwise %CAIRO_INT_STATUS_UNSUPPORTED or another
1508
 *   error like %CAIRO_STATUS_NO_MEMORY.
1509
 **/
1510
cairo_status_t
1511
_cairo_surface_clone_similar (cairo_surface_t  *surface,
1512
                              cairo_surface_t  *src,
1513
                              cairo_content_t   content,
1514
                              int               src_x,
1515
                              int               src_y,
1516
                              int               width,
1517
                              int               height,
1518
                              int              *clone_offset_x,
1519
                              int              *clone_offset_y,
1520
                              cairo_surface_t **clone_out)
1521
{
1522
    cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
1523
    cairo_image_surface_t *image;
1524
    void *image_extra;
1525
 
1526
    if (unlikely (surface->status))
1527
        return surface->status;
1528
 
1529
    if (unlikely (surface->finished))
1530
        return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
1531
 
1532
    if (src->type == CAIRO_SURFACE_TYPE_TEE) {
1533
        cairo_surface_t *match;
1534
 
1535
        match = _cairo_tee_surface_find_match (src,
1536
                                               surface->backend,
1537
                                               content);
1538
        if (match != NULL)
1539
            src = match;
1540
    }
1541
 
1542
    if (surface->backend->clone_similar != NULL) {
1543
        status = surface->backend->clone_similar (surface, src,
1544
                                                  content,
1545
                                                  src_x, src_y,
1546
                                                  width, height,
1547
                                                  clone_offset_x,
1548
                                                  clone_offset_y,
1549
                                                  clone_out);
1550
        if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1551
            if (_cairo_surface_is_image (src))
1552
                return CAIRO_INT_STATUS_UNSUPPORTED;
1553
 
1554
            /* First check to see if we can replay to a similar surface */
1555
            if (_cairo_surface_is_meta (src)) {
1556
                return _cairo_meta_surface_clone_similar (surface, src,
1557
                                                          content,
1558
                                                          src_x, src_y,
1559
                                                          width, height,
1560
                                                          clone_offset_x,
1561
                                                          clone_offset_y,
1562
                                                          clone_out);
1563
            }
1564
 
1565
            /* If we failed, try again with an image surface */
1566
            status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
1567
            if (status == CAIRO_STATUS_SUCCESS) {
1568
                status =
1569
                    surface->backend->clone_similar (surface, &image->base,
1570
                                                     content,
1571
                                                     src_x, src_y,
1572
                                                     width, height,
1573
                                                     clone_offset_x,
1574
                                                     clone_offset_y,
1575
                                                     clone_out);
1576
 
1577
                _cairo_surface_release_source_image (src, image, image_extra);
1578
            }
1579
        }
1580
    }
1581
 
1582
    /* If we're still unsupported, hit our fallback path to get a clone */
1583
    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
1584
        status =
1585
            _cairo_surface_fallback_clone_similar (surface, src,
1586
                                                   content,
1587
                                                   src_x, src_y,
1588
                                                   width, height,
1589
                                                   clone_offset_x,
1590
                                                   clone_offset_y,
1591
                                                   clone_out);
1592
    }
1593
 
1594
    if (unlikely (status))
1595
        return status;
1596
 
1597
    /* Update the clone's device_transform (which the underlying surface
1598
     * backend knows nothing about) */
1599
    if (*clone_out != src) {
1600
        (*clone_out)->device_transform = src->device_transform;
1601
        (*clone_out)->device_transform_inverse = src->device_transform_inverse;
1602
    }
1603
 
1604
    return status;
1605
}
1606
 
1607
/* XXX: Shouldn't really need to do this here. */
1608
#include "cairo-meta-surface-private.h"
1609
 
1610
/**
1611
 * _cairo_surface_snapshot
1612
 * @surface: a #cairo_surface_t
1613
 *
1614
 * Make an immutable copy of @surface. It is an error to call a
1615
 * surface-modifying function on the result of this function.
1616
 *
1617
 * The caller owns the return value and should call
1618
 * cairo_surface_destroy() when finished with it. This function will not
1619
 * return %NULL, but will return a nil surface instead.
1620
 *
1621
 * Return value: The snapshot surface. Note that the return surface
1622
 * may not necessarily be of the same type as @surface.
1623
 **/
1624
cairo_surface_t *
1625
_cairo_surface_snapshot (cairo_surface_t *surface)
1626
{
1627
    cairo_surface_t *snapshot;
1628
    cairo_status_t status;
1629
 
1630
    if (surface->status)
1631
        return _cairo_surface_create_in_error (surface->status);
1632
 
1633
    if (surface->finished)
1634
        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
1635
 
1636
    if (surface->snapshot_of != NULL)
1637
        return cairo_surface_reference (surface);
1638
 
1639
    snapshot = _cairo_surface_has_snapshot (surface,
1640
                                            surface->backend,
1641
                                            surface->content);
1642
    if (snapshot != NULL)
1643
        return cairo_surface_reference (snapshot);
1644
 
1645
    if (surface->backend->snapshot != NULL) {
1646
        snapshot = surface->backend->snapshot (surface);
1647
        if (snapshot != NULL) {
1648
            if (unlikely (snapshot->status))
1649
                return snapshot;
1650
 
1651
            /* Is this surface just a proxy - e.g. paginated surfaces? */
1652
            if (snapshot->backend != surface->backend) {
1653
                cairo_surface_t *previous;
1654
 
1655
                previous = _cairo_surface_has_snapshot (surface,
1656
                                                        snapshot->backend,
1657
                                                        snapshot->content);
1658
                if (previous != NULL) {
1659
                    cairo_surface_destroy (snapshot);
1660
                    return cairo_surface_reference (previous);
1661
                }
1662
            }
1663
        }
1664
    }
1665
 
1666
    if (snapshot == NULL) {
1667
        snapshot = _cairo_surface_has_snapshot (surface,
1668
                                                &_cairo_image_surface_backend,
1669
                                                surface->content);
1670
        if (snapshot != NULL)
1671
            return cairo_surface_reference (snapshot);
1672
 
1673
        snapshot = _cairo_surface_fallback_snapshot (surface);
1674
        if (unlikely (snapshot->status))
1675
            return snapshot;
1676
    }
1677
 
1678
    status = _cairo_surface_copy_mime_data (snapshot, surface);
1679
    if (unlikely (status)) {
1680
        cairo_surface_destroy (snapshot);
1681
        return _cairo_surface_create_in_error (status);
1682
    }
1683
 
1684
    snapshot->device_transform = surface->device_transform;
1685
    snapshot->device_transform_inverse = surface->device_transform_inverse;
1686
 
1687
    status = _cairo_surface_attach_snapshot (surface, snapshot, NULL);
1688
    if (unlikely (status)) {
1689
        cairo_surface_destroy (snapshot);
1690
        return _cairo_surface_create_in_error (status);
1691
    }
1692
 
1693
    return snapshot;
1694
}
1695
 
1696
/**
1697
 * _cairo_surface_is_similar
1698
 * @surface_a: a #cairo_surface_t
1699
 * @surface_b: a #cairo_surface_t
1700
 * @content: a #cairo_content_t
1701
 *
1702
 * Find out whether the given surfaces share the same backend,
1703
 * and if so, whether they can be considered similar.
1704
 *
1705
 * The definition of "similar" depends on the backend. In
1706
 * general, it means that the surface is equivalent to one
1707
 * that would have been generated by a call to cairo_surface_create_similar().
1708
 *
1709
 * Return value: %TRUE if the surfaces are similar.
1710
 **/
1711
cairo_bool_t
1712
_cairo_surface_is_similar (cairo_surface_t *surface_a,
1713
                           cairo_surface_t *surface_b,
1714
                           cairo_content_t content)
1715
{
1716
    if (surface_a->backend != surface_b->backend)
1717
        return FALSE;
1718
 
1719
    if (surface_a->backend->is_similar != NULL)
1720
        return surface_a->backend->is_similar (surface_a, surface_b, content);
1721
 
1722
    return TRUE;
1723
}
1724
 
1725
cairo_status_t
1726
_cairo_surface_composite (cairo_operator_t      op,
1727
                          const cairo_pattern_t *src,
1728
                          const cairo_pattern_t *mask,
1729
                          cairo_surface_t       *dst,
1730
                          int                   src_x,
1731
                          int                   src_y,
1732
                          int                   mask_x,
1733
                          int                   mask_y,
1734
                          int                   dst_x,
1735
                          int                   dst_y,
1736
                          unsigned int          width,
1737
                          unsigned int          height,
1738
                          cairo_region_t        *clip_region)
1739
{
1740
    cairo_int_status_t status;
1741
 
1742
    if (unlikely (dst->status))
1743
        return dst->status;
1744
 
1745
    assert (_cairo_surface_is_writable (dst));
1746
 
1747
    if (mask) {
1748
        /* These operators aren't interpreted the same way by the backends;
1749
         * they are implemented in terms of other operators in cairo-gstate.c
1750
         */
1751
        assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR);
1752
    }
1753
 
1754
    if (dst->backend->composite) {
1755
        status = dst->backend->composite (op,
1756
                                          src, mask, dst,
1757
                                          src_x, src_y,
1758
                                          mask_x, mask_y,
1759
                                          dst_x, dst_y,
1760
                                          width, height,
1761
                                          clip_region);
1762
        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1763
            return _cairo_surface_set_error (dst, status);
1764
    }
1765
 
1766
    return _cairo_surface_set_error (dst,
1767
            _cairo_surface_fallback_composite (op,
1768
                                              src, mask, dst,
1769
                                              src_x, src_y,
1770
                                              mask_x, mask_y,
1771
                                              dst_x, dst_y,
1772
                                              width, height,
1773
                                              clip_region));
1774
}
1775
 
1776
/**
1777
 * _cairo_surface_fill_rectangle:
1778
 * @surface: a #cairo_surface_t
1779
 * @op: the operator to apply to the rectangle
1780
 * @color: the source color
1781
 * @x: X coordinate of rectangle, in backend coordinates
1782
 * @y: Y coordinate of rectangle, in backend coordinates
1783
 * @width: width of rectangle, in backend coordinates
1784
 * @height: height of rectangle, in backend coordinates
1785
 *
1786
 * Applies an operator to a rectangle using a solid color as the source.
1787
 * See _cairo_surface_fill_rectangles() for full details.
1788
 *
1789
 * Return value: %CAIRO_STATUS_SUCCESS or the error that occurred
1790
 **/
1791
cairo_status_t
1792
_cairo_surface_fill_rectangle (cairo_surface_t     *surface,
1793
                               cairo_operator_t     op,
1794
                               const cairo_color_t *color,
1795
                               int                  x,
1796
                               int                  y,
1797
                               int                  width,
1798
                               int                  height)
1799
{
1800
    cairo_rectangle_int_t rect;
1801
 
1802
    if (surface->status)
1803
        return surface->status;
1804
 
1805
    assert (_cairo_surface_is_writable (surface));
1806
 
1807
    rect.x = x;
1808
    rect.y = y;
1809
    rect.width = width;
1810
    rect.height = height;
1811
 
1812
    return _cairo_surface_fill_rectangles (surface, op, color, &rect, 1);
1813
}
1814
 
1815
/**
1816
 * _cairo_surface_fill_region:
1817
 * @surface: a #cairo_surface_t
1818
 * @op: the operator to apply to the region
1819
 * @color: the source color
1820
 * @region: the region to modify, in backend coordinates
1821
 *
1822
 * Applies an operator to a set of rectangles specified as a
1823
 * #cairo_region_t using a solid color as the source.
1824
 * See _cairo_surface_fill_rectangles() for full details.
1825
 *
1826
 * Return value: %CAIRO_STATUS_SUCCESS or the error that occurred
1827
 **/
1828
cairo_status_t
1829
_cairo_surface_fill_region (cairo_surface_t        *surface,
1830
                            cairo_operator_t        op,
1831
                            const cairo_color_t    *color,
1832
                            cairo_region_t         *region)
1833
{
1834
    int num_rects;
1835
    cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
1836
    cairo_rectangle_int_t *rects = stack_rects;
1837
    cairo_status_t status;
1838
    int i;
1839
 
1840
    if (surface->status)
1841
        return surface->status;
1842
 
1843
    assert (_cairo_surface_is_writable (surface));
1844
 
1845
    num_rects = cairo_region_num_rectangles (region);
1846
    if (num_rects == 0)
1847
        return CAIRO_STATUS_SUCCESS;
1848
 
1849
    if (num_rects > ARRAY_LENGTH (stack_rects)) {
1850
        rects = _cairo_malloc_ab (num_rects,
1851
                                  sizeof (cairo_rectangle_int_t));
1852
        if (rects == NULL) {
1853
            return _cairo_surface_set_error (surface,
1854
                                             _cairo_error (CAIRO_STATUS_NO_MEMORY));
1855
        }
1856
    }
1857
 
1858
    for (i = 0; i < num_rects; i++)
1859
        cairo_region_get_rectangle (region, i, &rects[i]);
1860
 
1861
    status =  _cairo_surface_fill_rectangles (surface,
1862
                                              op, color, rects, num_rects);
1863
 
1864
    if (rects != stack_rects)
1865
        free (rects);
1866
 
1867
    return _cairo_surface_set_error (surface, status);
1868
}
1869
 
1870
/**
1871
 * _cairo_surface_fill_rectangles:
1872
 * @surface: a #cairo_surface_t
1873
 * @op: the operator to apply to the region
1874
 * @color: the source color
1875
 * @rects: the rectangles to modify, in backend coordinates
1876
 * @num_rects: the number of rectangles in @rects
1877
 *
1878
 * Applies an operator to a set of rectangles using a solid color
1879
 * as the source. Note that even if the operator is an unbounded operator
1880
 * such as %CAIRO_OPERATOR_IN, only the given set of rectangles
1881
 * is affected. This differs from _cairo_surface_composite_trapezoids()
1882
 * where the entire destination rectangle is cleared.
1883
 *
1884
 * Return value: %CAIRO_STATUS_SUCCESS or the error that occurred
1885
 **/
1886
cairo_status_t
1887
_cairo_surface_fill_rectangles (cairo_surface_t         *surface,
1888
                                cairo_operator_t         op,
1889
                                const cairo_color_t     *color,
1890
                                cairo_rectangle_int_t   *rects,
1891
                                int                      num_rects)
1892
{
1893
    cairo_int_status_t status;
1894
 
1895
    if (surface->status)
1896
        return surface->status;
1897
 
1898
    assert (_cairo_surface_is_writable (surface));
1899
 
1900
    if (num_rects == 0)
1901
        return CAIRO_STATUS_SUCCESS;
1902
 
1903
    if (surface->backend->fill_rectangles) {
1904
        status = surface->backend->fill_rectangles (surface,
1905
                                                    op, color,
1906
                                                    rects, num_rects);
1907
        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1908
            return _cairo_surface_set_error (surface, status);
1909
    }
1910
 
1911
    return _cairo_surface_set_error (surface,
1912
            _cairo_surface_fallback_fill_rectangles (surface,
1913
                                                     op, color,
1914
                                                     rects, num_rects));
1915
}
1916
 
1917
cairo_status_t
1918
_cairo_surface_paint (cairo_surface_t   *surface,
1919
                      cairo_operator_t   op,
1920
                      const cairo_pattern_t *source,
1921
                      cairo_clip_t          *clip)
1922
{
1923
    cairo_status_t status;
1924
    cairo_pattern_union_t dev_source;
1925
 
1926
    if (unlikely (surface->status))
1927
        return surface->status;
1928
 
1929
    if (clip && clip->all_clipped)
1930
        return CAIRO_STATUS_SUCCESS;
1931
 
1932
    _cairo_surface_begin_modification (surface);
1933
 
1934
    _cairo_surface_copy_pattern_for_destination (&source,
1935
                                                 surface,
1936
                                                 &dev_source.base);
1937
 
1938
    if (surface->backend->paint != NULL) {
1939
        status = surface->backend->paint (surface, op, source, clip);
1940
        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1941
            goto FINISH;
1942
    }
1943
 
1944
    status = _cairo_surface_fallback_paint (surface, op, source, clip);
1945
 
1946
 FINISH:
1947
    return _cairo_surface_set_error (surface, status);
1948
}
1949
 
1950
cairo_status_t
1951
_cairo_surface_mask (cairo_surface_t            *surface,
1952
                     cairo_operator_t            op,
1953
                     const cairo_pattern_t      *source,
1954
                     const cairo_pattern_t      *mask,
1955
                     cairo_clip_t               *clip)
1956
{
1957
    cairo_status_t status;
1958
    cairo_pattern_union_t dev_source;
1959
    cairo_pattern_union_t dev_mask;
1960
 
1961
    if (unlikely (surface->status))
1962
        return surface->status;
1963
 
1964
    if (clip && clip->all_clipped)
1965
        return CAIRO_STATUS_SUCCESS;
1966
 
1967
    _cairo_surface_begin_modification (surface);
1968
 
1969
    _cairo_surface_copy_pattern_for_destination (&source, surface,
1970
                                                 &dev_source.base);
1971
    _cairo_surface_copy_pattern_for_destination (&mask, surface,
1972
                                                 &dev_mask.base);
1973
 
1974
    if (surface->backend->mask != NULL) {
1975
        status = surface->backend->mask (surface, op, source, mask, clip);
1976
        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
1977
            goto FINISH;
1978
    }
1979
 
1980
    status = _cairo_surface_fallback_mask (surface, op, source, mask, clip);
1981
 
1982
 FINISH:
1983
    return _cairo_surface_set_error (surface, status);
1984
}
1985
 
1986
cairo_status_t
1987
_cairo_surface_fill_stroke (cairo_surface_t         *surface,
1988
                            cairo_operator_t         fill_op,
1989
                            const cairo_pattern_t   *fill_source,
1990
                            cairo_fill_rule_t        fill_rule,
1991
                            double                   fill_tolerance,
1992
                            cairo_antialias_t        fill_antialias,
1993
                            cairo_path_fixed_t      *path,
1994
                            cairo_operator_t         stroke_op,
1995
                            const cairo_pattern_t   *stroke_source,
1996
                            cairo_stroke_style_t    *stroke_style,
1997
                            cairo_matrix_t          *stroke_ctm,
1998
                            cairo_matrix_t          *stroke_ctm_inverse,
1999
                            double                   stroke_tolerance,
2000
                            cairo_antialias_t        stroke_antialias,
2001
                            cairo_clip_t            *clip)
2002
{
2003
    cairo_status_t status;
2004
 
2005
    if (unlikely (surface->status))
2006
        return surface->status;
2007
 
2008
    if (clip && clip->all_clipped)
2009
        return CAIRO_STATUS_SUCCESS;
2010
 
2011
    _cairo_surface_begin_modification (surface);
2012
 
2013
    if (surface->backend->fill_stroke) {
2014
        cairo_pattern_union_t dev_stroke_source;
2015
        cairo_pattern_union_t dev_fill_source;
2016
        cairo_matrix_t dev_ctm = *stroke_ctm;
2017
        cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse;
2018
 
2019
        _cairo_surface_copy_pattern_for_destination (&stroke_source, surface,
2020
                                                     &dev_stroke_source.base);
2021
        _cairo_surface_copy_pattern_for_destination (&fill_source, surface,
2022
                                                     &dev_fill_source.base);
2023
 
2024
        status = surface->backend->fill_stroke (surface,
2025
                                                fill_op, fill_source, fill_rule,
2026
                                                fill_tolerance, fill_antialias,
2027
                                                path,
2028
                                                stroke_op, stroke_source,
2029
                                                stroke_style,
2030
                                                &dev_ctm, &dev_ctm_inverse,
2031
                                                stroke_tolerance, stroke_antialias,
2032
                                                clip);
2033
 
2034
        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
2035
            return _cairo_surface_set_error (surface, status);
2036
    }
2037
 
2038
    status = _cairo_surface_fill (surface, fill_op, fill_source, path,
2039
                                  fill_rule, fill_tolerance, fill_antialias,
2040
                                  clip);
2041
    if (unlikely (status))
2042
        return _cairo_surface_set_error (surface, status);
2043
 
2044
    status = _cairo_surface_stroke (surface, stroke_op, stroke_source, path,
2045
                                    stroke_style, stroke_ctm, stroke_ctm_inverse,
2046
                                    stroke_tolerance, stroke_antialias,
2047
                                    clip);
2048
    if (unlikely (status))
2049
        return _cairo_surface_set_error (surface, status);
2050
 
2051
    return CAIRO_STATUS_SUCCESS;
2052
}
2053
 
2054
cairo_status_t
2055
_cairo_surface_stroke (cairo_surface_t          *surface,
2056
                       cairo_operator_t          op,
2057
                       const cairo_pattern_t    *source,
2058
                       cairo_path_fixed_t       *path,
2059
                       cairo_stroke_style_t     *stroke_style,
2060
                       cairo_matrix_t           *ctm,
2061
                       cairo_matrix_t           *ctm_inverse,
2062
                       double                    tolerance,
2063
                       cairo_antialias_t         antialias,
2064
                       cairo_clip_t             *clip)
2065
{
2066
    cairo_status_t status;
2067
    cairo_pattern_union_t dev_source;
2068
 
2069
    if (unlikely (surface->status))
2070
        return surface->status;
2071
 
2072
    if (clip && clip->all_clipped)
2073
        return CAIRO_STATUS_SUCCESS;
2074
 
2075
    _cairo_surface_begin_modification (surface);
2076
 
2077
    _cairo_surface_copy_pattern_for_destination (&source, surface,
2078
                                                 &dev_source.base);
2079
 
2080
    if (surface->backend->stroke != NULL) {
2081
        status = surface->backend->stroke (surface, op, source,
2082
                                           path, stroke_style,
2083
                                           ctm, ctm_inverse,
2084
                                           tolerance, antialias,
2085
                                           clip);
2086
 
2087
        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
2088
            goto FINISH;
2089
    }
2090
 
2091
    status = _cairo_surface_fallback_stroke (surface, op, source,
2092
                                             path, stroke_style,
2093
                                             ctm, ctm_inverse,
2094
                                             tolerance, antialias,
2095
                                             clip);
2096
 
2097
 FINISH:
2098
    return _cairo_surface_set_error (surface, status);
2099
}
2100
 
2101
cairo_status_t
2102
_cairo_surface_fill (cairo_surface_t    *surface,
2103
                     cairo_operator_t    op,
2104
                     const cairo_pattern_t *source,
2105
                     cairo_path_fixed_t *path,
2106
                     cairo_fill_rule_t   fill_rule,
2107
                     double              tolerance,
2108
                     cairo_antialias_t   antialias,
2109
                     cairo_clip_t       *clip)
2110
{
2111
    cairo_status_t status;
2112
    cairo_pattern_union_t dev_source;
2113
 
2114
    if (unlikely (surface->status))
2115
        return surface->status;
2116
 
2117
    if (clip && clip->all_clipped)
2118
        return CAIRO_STATUS_SUCCESS;
2119
 
2120
    _cairo_surface_begin_modification (surface);
2121
 
2122
    _cairo_surface_copy_pattern_for_destination (&source, surface,
2123
                                                 &dev_source.base);
2124
    if (surface->backend->fill != NULL) {
2125
        status = surface->backend->fill (surface, op, source,
2126
                                         path, fill_rule,
2127
                                         tolerance, antialias,
2128
                                         clip);
2129
 
2130
        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
2131
            goto FINISH;
2132
    }
2133
 
2134
    status = _cairo_surface_fallback_fill (surface, op, source,
2135
                                           path, fill_rule,
2136
                                           tolerance, antialias,
2137
                                           clip);
2138
 
2139
 FINISH:
2140
    return _cairo_surface_set_error (surface, status);
2141
}
2142
 
2143
cairo_status_t
2144
_cairo_surface_composite_trapezoids (cairo_operator_t           op,
2145
                                     const cairo_pattern_t      *pattern,
2146
                                     cairo_surface_t            *dst,
2147
                                     cairo_antialias_t          antialias,
2148
                                     int                        src_x,
2149
                                     int                        src_y,
2150
                                     int                        dst_x,
2151
                                     int                        dst_y,
2152
                                     unsigned int               width,
2153
                                     unsigned int               height,
2154
                                     cairo_trapezoid_t          *traps,
2155
                                     int                        num_traps,
2156
                                     cairo_region_t             *clip_region)
2157
{
2158
    cairo_int_status_t status;
2159
 
2160
    if (dst->status)
2161
        return dst->status;
2162
 
2163
    assert (_cairo_surface_is_writable (dst));
2164
 
2165
    /* These operators aren't interpreted the same way by the backends;
2166
     * they are implemented in terms of other operators in cairo-gstate.c
2167
     */
2168
    assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR);
2169
 
2170
    if (dst->backend->composite_trapezoids) {
2171
        status = dst->backend->composite_trapezoids (op,
2172
                                                     pattern, dst,
2173
                                                     antialias,
2174
                                                     src_x, src_y,
2175
                                                     dst_x, dst_y,
2176
                                                     width, height,
2177
                                                     traps, num_traps,
2178
                                                     clip_region);
2179
        if (status != CAIRO_INT_STATUS_UNSUPPORTED)
2180
            return _cairo_surface_set_error (dst, status);
2181
    }
2182
 
2183
    return  _cairo_surface_set_error (dst,
2184
            _cairo_surface_fallback_composite_trapezoids (op, pattern, dst,
2185
                                                          antialias,
2186
                                                          src_x, src_y,
2187
                                                          dst_x, dst_y,
2188
                                                          width, height,
2189
                                                          traps, num_traps,
2190
                                                          clip_region));
2191
}
2192
 
2193
cairo_span_renderer_t *
2194
_cairo_surface_create_span_renderer (cairo_operator_t            op,
2195
                                     const cairo_pattern_t      *pattern,
2196
                                     cairo_surface_t            *dst,
2197
                                     cairo_antialias_t           antialias,
2198
                                     const cairo_composite_rectangles_t *rects,
2199
                                     cairo_region_t             *clip_region)
2200
{
2201
    assert (dst->snapshot_of == NULL);
2202
 
2203
    if (unlikely (dst->status))
2204
        return _cairo_span_renderer_create_in_error (dst->status);
2205
 
2206
    if (unlikely (dst->finished))
2207
        return _cairo_span_renderer_create_in_error (CAIRO_STATUS_SURFACE_FINISHED);
2208
 
2209
    if (dst->backend->create_span_renderer) {
2210
        return dst->backend->create_span_renderer (op,
2211
                                                   pattern, dst,
2212
                                                   antialias,
2213
                                                   rects,
2214
                                                   clip_region);
2215
    }
2216
    ASSERT_NOT_REACHED;
2217
    return _cairo_span_renderer_create_in_error (CAIRO_INT_STATUS_UNSUPPORTED);
2218
}
2219
 
2220
cairo_bool_t
2221
_cairo_surface_check_span_renderer (cairo_operator_t             op,
2222
                                    const cairo_pattern_t       *pattern,
2223
                                    cairo_surface_t             *dst,
2224
                                    cairo_antialias_t            antialias)
2225
{
2226
    assert (dst->snapshot_of == NULL);
2227
    assert (dst->status == CAIRO_STATUS_SUCCESS);
2228
    assert (! dst->finished);
2229
 
2230
    /* XXX: Currently we have no mono span renderer */
2231
    if (antialias == CAIRO_ANTIALIAS_NONE)
2232
        return FALSE;
2233
 
2234
    if (dst->backend->check_span_renderer != NULL)
2235
        return dst->backend->check_span_renderer (op, pattern, dst, antialias);
2236
 
2237
    return FALSE;
2238
}
2239
 
2240
/**
2241
 * cairo_surface_copy_page:
2242
 * @surface: a #cairo_surface_t
2243
 *
2244
 * Emits the current page for backends that support multiple pages,
2245
 * but doesn't clear it, so that the contents of the current page will
2246
 * be retained for the next page.  Use cairo_surface_show_page() if you
2247
 * want to get an empty page after the emission.
2248
 *
2249
 * There is a convenience function for this that takes a #cairo_t,
2250
 * namely cairo_copy_page().
2251
 *
2252
 * Since: 1.6
2253
 */
2254
void
2255
cairo_surface_copy_page (cairo_surface_t *surface)
2256
{
2257
    cairo_status_t status_ignored;
2258
 
2259
    if (surface->status)
2260
        return;
2261
 
2262
    assert (surface->snapshot_of == NULL);
2263
 
2264
    if (surface->finished) {
2265
        status_ignored = _cairo_surface_set_error (surface,
2266
                                                 CAIRO_STATUS_SURFACE_FINISHED);
2267
        return;
2268
    }
2269
 
2270
    /* It's fine if some backends don't implement copy_page */
2271
    if (surface->backend->copy_page == NULL)
2272
        return;
2273
 
2274
    status_ignored = _cairo_surface_set_error (surface,
2275
                                         surface->backend->copy_page (surface));
2276
}
2277
slim_hidden_def (cairo_surface_copy_page);
2278
 
2279
/**
2280
 * cairo_surface_show_page:
2281
 * @surface: a #cairo_Surface_t
2282
 *
2283
 * Emits and clears the current page for backends that support multiple
2284
 * pages.  Use cairo_surface_copy_page() if you don't want to clear the page.
2285
 *
2286
 * There is a convenience function for this that takes a #cairo_t,
2287
 * namely cairo_show_page().
2288
 *
2289
 * Since: 1.6
2290
 **/
2291
void
2292
cairo_surface_show_page (cairo_surface_t *surface)
2293
{
2294
    cairo_status_t status_ignored;
2295
 
2296
    if (surface->status)
2297
        return;
2298
 
2299
    _cairo_surface_begin_modification (surface);
2300
 
2301
    if (surface->finished) {
2302
        status_ignored = _cairo_surface_set_error (surface,
2303
                                                 CAIRO_STATUS_SURFACE_FINISHED);
2304
        return;
2305
    }
2306
 
2307
    /* It's fine if some backends don't implement show_page */
2308
    if (surface->backend->show_page == NULL)
2309
        return;
2310
 
2311
    status_ignored = _cairo_surface_set_error (surface,
2312
                                         surface->backend->show_page (surface));
2313
}
2314
slim_hidden_def (cairo_surface_show_page);
2315
 
2316
/**
2317
 * _cairo_surface_get_extents:
2318
 * @surface: the #cairo_surface_t to fetch extents for
2319
 *
2320
 * This function returns a bounding box for the surface.  The surface
2321
 * bounds are defined as a region beyond which no rendering will
2322
 * possibly be recorded, in other words, it is the maximum extent of
2323
 * potentially usable coordinates.
2324
 *
2325
 * For vector surfaces, (PDF, PS, SVG and meta-surfaces), the surface
2326
 * might be conceived as unbounded, but we force the user to provide a
2327
 * maximum size at the time of surface_create. So get_extents uses
2328
 * that size.
2329
 *
2330
 * Note: The coordinates returned are in "backend" space rather than
2331
 * "surface" space. That is, they are relative to the true (0,0)
2332
 * origin rather than the device_transform origin. This might seem a
2333
 * bit inconsistent with other #cairo_surface_t interfaces, but all
2334
 * current callers are within the surface layer where backend space is
2335
 * desired.
2336
 *
2337
 * This behavior would have to be changed is we ever exported a public
2338
 * variant of this function.
2339
 */
2340
cairo_bool_t
2341
_cairo_surface_get_extents (cairo_surface_t         *surface,
2342
                            cairo_rectangle_int_t   *extents)
2343
{
2344
    cairo_bool_t bounded = FALSE;
2345
 
2346
    if (unlikely (surface->status || surface->finished))
2347
        return TRUE;
2348
 
2349
    if (surface->backend->get_extents != NULL)
2350
        bounded = surface->backend->get_extents (surface, extents);
2351
 
2352
    if (! bounded)
2353
        _cairo_unbounded_rectangle_init (extents);
2354
 
2355
    return bounded;
2356
}
2357
 
2358
/**
2359
 * cairo_surface_has_show_text_glyphs:
2360
 * @surface: a #cairo_surface_t
2361
 *
2362
 * Returns whether the surface supports
2363
 * sophisticated cairo_show_text_glyphs() operations.  That is,
2364
 * whether it actually uses the provided text and cluster data
2365
 * to a cairo_show_text_glyphs() call.
2366
 *
2367
 * Note: Even if this function returns %FALSE, a
2368
 * cairo_show_text_glyphs() operation targeted at @surface will
2369
 * still succeed.  It just will
2370
 * act like a cairo_show_glyphs() operation.  Users can use this
2371
 * function to avoid computing UTF-8 text and cluster mapping if the
2372
 * target surface does not use it.
2373
 *
2374
 * Return value: %TRUE if @surface supports
2375
 *               cairo_show_text_glyphs(), %FALSE otherwise
2376
 *
2377
 * Since: 1.8
2378
 **/
2379
cairo_bool_t
2380
cairo_surface_has_show_text_glyphs (cairo_surface_t         *surface)
2381
{
2382
    cairo_status_t status_ignored;
2383
 
2384
    if (surface->status)
2385
        return FALSE;
2386
 
2387
    if (surface->finished) {
2388
        status_ignored = _cairo_surface_set_error (surface,
2389
                                                   CAIRO_STATUS_SURFACE_FINISHED);
2390
        return FALSE;
2391
    }
2392
 
2393
    if (surface->backend->has_show_text_glyphs)
2394
        return surface->backend->has_show_text_glyphs (surface);
2395
    else
2396
        return surface->backend->show_text_glyphs != NULL;
2397
}
2398
slim_hidden_def (cairo_surface_has_show_text_glyphs);
2399
 
2400
/* Note: the backends may modify the contents of the glyph array as long as
2401
 * they do not return %CAIRO_INT_STATUS_UNSUPPORTED. This makes it possible to
2402
 * avoid copying the array again and again, and edit it in-place.
2403
 * Backends are in fact free to use the array as a generic buffer as they
2404
 * see fit.
2405
 *
2406
 * For show_glyphs backend method, and NOT for show_text_glyphs method,
2407
 * when they do return UNSUPPORTED, they may adjust remaining_glyphs to notify
2408
 * that they have successfully rendered some of the glyphs (from the beginning
2409
 * of the array), but not all.  If they don't touch remaining_glyphs, it
2410
 * defaults to all glyphs.
2411
 *
2412
 * See commits 5a9642c5746fd677aed35ce620ce90b1029b1a0c and
2413
 * 1781e6018c17909311295a9cc74b70500c6b4d0a for the rationale.
2414
 */
2415
cairo_status_t
2416
_cairo_surface_show_text_glyphs (cairo_surface_t            *surface,
2417
                                 cairo_operator_t            op,
2418
                                 const cairo_pattern_t      *source,
2419
                                 const char                 *utf8,
2420
                                 int                         utf8_len,
2421
                                 cairo_glyph_t              *glyphs,
2422
                                 int                         num_glyphs,
2423
                                 const cairo_text_cluster_t *clusters,
2424
                                 int                         num_clusters,
2425
                                 cairo_text_cluster_flags_t  cluster_flags,
2426
                                 cairo_scaled_font_t        *scaled_font,
2427
                                 cairo_clip_t               *clip)
2428
{
2429
    cairo_status_t status;
2430
    cairo_scaled_font_t *dev_scaled_font = scaled_font;
2431
    cairo_pattern_union_t dev_source;
2432
 
2433
    if (unlikely (surface->status))
2434
        return surface->status;
2435
 
2436
    if (num_glyphs == 0 && utf8_len == 0)
2437
        return CAIRO_STATUS_SUCCESS;
2438
 
2439
    if (clip && clip->all_clipped)
2440
        return CAIRO_STATUS_SUCCESS;
2441
 
2442
    _cairo_surface_begin_modification (surface);
2443
 
2444
    _cairo_surface_copy_pattern_for_destination (&source, surface,
2445
                                                 &dev_source.base);
2446
 
2447
    if (_cairo_surface_has_device_transform (surface) &&
2448
        ! _cairo_matrix_is_integer_translation (&surface->device_transform, NULL, NULL))
2449
    {
2450
        cairo_font_options_t font_options;
2451
        cairo_matrix_t dev_ctm, font_matrix;
2452
 
2453
        cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix);
2454
        cairo_scaled_font_get_ctm (scaled_font, &dev_ctm);
2455
        cairo_matrix_multiply (&dev_ctm, &dev_ctm, &surface->device_transform);
2456
        cairo_scaled_font_get_font_options (scaled_font, &font_options);
2457
        dev_scaled_font = cairo_scaled_font_create (cairo_scaled_font_get_font_face (scaled_font),
2458
                                                    &font_matrix,
2459
                                                    &dev_ctm,
2460
                                                    &font_options);
2461
    }
2462
    status = cairo_scaled_font_status (dev_scaled_font);
2463
    if (unlikely (status))
2464
        return _cairo_surface_set_error (surface, status);
2465
 
2466
    status = CAIRO_INT_STATUS_UNSUPPORTED;
2467
 
2468
    /* The logic here is duplicated in _cairo_analysis_surface show_glyphs and
2469
     * show_text_glyphs.  Keep in synch. */
2470
    if (clusters) {
2471
        /* A real show_text_glyphs call.  Try show_text_glyphs backend
2472
         * method first */
2473
        if (surface->backend->show_text_glyphs != NULL) {
2474
            status = surface->backend->show_text_glyphs (surface, op,
2475
                                                         source,
2476
                                                         utf8, utf8_len,
2477
                                                         glyphs, num_glyphs,
2478
                                                         clusters, num_clusters, cluster_flags,
2479
                                                         dev_scaled_font,
2480
                                                         clip);
2481
        }
2482
        if (status == CAIRO_INT_STATUS_UNSUPPORTED &&
2483
            surface->backend->show_glyphs)
2484
        {
2485
            int remaining_glyphs = num_glyphs;
2486
            status = surface->backend->show_glyphs (surface, op,
2487
                                                    source,
2488
                                                    glyphs, num_glyphs,
2489
                                                    dev_scaled_font,
2490
                                                    clip,
2491
                                                    &remaining_glyphs);
2492
            glyphs += num_glyphs - remaining_glyphs;
2493
            num_glyphs = remaining_glyphs;
2494
            if (status == CAIRO_INT_STATUS_UNSUPPORTED && remaining_glyphs == 0)
2495
                status = CAIRO_STATUS_SUCCESS;
2496
        }
2497
    } else {
2498
        /* A mere show_glyphs call.  Try show_glyphs backend method first */
2499
        if (surface->backend->show_glyphs != NULL) {
2500
            int remaining_glyphs = num_glyphs;
2501
            status = surface->backend->show_glyphs (surface, op,
2502
                                                    source,
2503
                                                    glyphs, num_glyphs,
2504
                                                    dev_scaled_font,
2505
                                                    clip,
2506
                                                    &remaining_glyphs);
2507
            glyphs += num_glyphs - remaining_glyphs;
2508
            num_glyphs = remaining_glyphs;
2509
            if (status == CAIRO_INT_STATUS_UNSUPPORTED && remaining_glyphs == 0)
2510
                status = CAIRO_STATUS_SUCCESS;
2511
        } else if (surface->backend->show_text_glyphs != NULL) {
2512
            /* Intentionally only try show_text_glyphs method for show_glyphs
2513
             * calls if backend does not have show_glyphs.  If backend has
2514
             * both methods implemented, we don't fallback from show_glyphs to
2515
             * show_text_glyphs, and hence the backend can assume in its
2516
             * show_text_glyphs call that clusters is not NULL (which also
2517
             * implies that UTF-8 is not NULL, unless the text is
2518
             * zero-length).
2519
             */
2520
            status = surface->backend->show_text_glyphs (surface, op,
2521
                                                         source,
2522
                                                         utf8, utf8_len,
2523
                                                         glyphs, num_glyphs,
2524
                                                         clusters, num_clusters, cluster_flags,
2525
                                                         dev_scaled_font,
2526
                                                         clip);
2527
        }
2528
    }
2529
 
2530
    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
2531
        status = _cairo_surface_fallback_show_glyphs (surface, op,
2532
                                                      source,
2533
                                                      glyphs, num_glyphs,
2534
                                                      dev_scaled_font,
2535
                                                      clip);
2536
    }
2537
 
2538
    if (dev_scaled_font != scaled_font)
2539
        cairo_scaled_font_destroy (dev_scaled_font);
2540
 
2541
    return _cairo_surface_set_error (surface, status);
2542
}
2543
 
2544
/* XXX: Previously, we had a function named _cairo_surface_show_glyphs
2545
 * with not-so-useful semantics. We've now got a
2546
 * _cairo_surface_show_text_glyphs with the proper semantics, and its
2547
 * fallback still uses this old function (which still needs to be
2548
 * cleaned up in terms of both semantics and naming). */
2549
cairo_status_t
2550
_cairo_surface_old_show_glyphs (cairo_scaled_font_t     *scaled_font,
2551
                                cairo_operator_t         op,
2552
                                const cairo_pattern_t   *pattern,
2553
                                cairo_surface_t         *dst,
2554
                                int                      source_x,
2555
                                int                      source_y,
2556
                                int                      dest_x,
2557
                                int                      dest_y,
2558
                                unsigned int             width,
2559
                                unsigned int             height,
2560
                                cairo_glyph_t           *glyphs,
2561
                                int                      num_glyphs,
2562
                                cairo_region_t          *clip_region)
2563
{
2564
    cairo_status_t status;
2565
 
2566
    if (dst->status)
2567
        return dst->status;
2568
 
2569
    assert (_cairo_surface_is_writable (dst));
2570
 
2571
    if (dst->backend->old_show_glyphs) {
2572
        status = dst->backend->old_show_glyphs (scaled_font,
2573
                                                op, pattern, dst,
2574
                                                source_x, source_y,
2575
                                                dest_x, dest_y,
2576
                                                width, height,
2577
                                                glyphs, num_glyphs,
2578
                                                clip_region);
2579
    } else
2580
        status = CAIRO_INT_STATUS_UNSUPPORTED;
2581
 
2582
    return _cairo_surface_set_error (dst, status);
2583
}
2584
 
2585
static cairo_status_t
2586
_cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t         *dst,
2587
                                                   cairo_rectangle_int_t   *src_rectangle,
2588
                                                   cairo_rectangle_int_t   *mask_rectangle,
2589
                                                   int                      dst_x,
2590
                                                   int                      dst_y,
2591
                                                   unsigned int             width,
2592
                                                   unsigned int             height,
2593
                                                   cairo_region_t           *clip_region)
2594
{
2595
    cairo_rectangle_int_t dst_rectangle;
2596
    cairo_region_t clear_region;
2597
    cairo_status_t status;
2598
 
2599
    /* The area that was drawn is the area in the destination rectangle but
2600
     * not within the source or the mask.
2601
     */
2602
    dst_rectangle.x = dst_x;
2603
    dst_rectangle.y = dst_y;
2604
    dst_rectangle.width = width;
2605
    dst_rectangle.height = height;
2606
 
2607
    _cairo_region_init_rectangle (&clear_region, &dst_rectangle);
2608
 
2609
    if (clip_region != NULL) {
2610
        status = cairo_region_intersect (&clear_region, clip_region);
2611
        if (unlikely (status))
2612
            goto CLEANUP_REGIONS;
2613
    }
2614
 
2615
    if (src_rectangle != NULL) {
2616
        if (! _cairo_rectangle_intersect (&dst_rectangle, src_rectangle))
2617
            goto EMPTY;
2618
    }
2619
 
2620
    if (mask_rectangle != NULL) {
2621
        if (! _cairo_rectangle_intersect (&dst_rectangle, mask_rectangle))
2622
            goto EMPTY;
2623
    }
2624
 
2625
    /* Now compute the area that is in dst but not drawn */
2626
    status = cairo_region_subtract_rectangle (&clear_region, &dst_rectangle);
2627
    if (unlikely (status))
2628
        goto CLEANUP_REGIONS;
2629
 
2630
  EMPTY:
2631
    status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
2632
                                         CAIRO_COLOR_TRANSPARENT,
2633
                                         &clear_region);
2634
 
2635
  CLEANUP_REGIONS:
2636
    _cairo_region_fini (&clear_region);
2637
 
2638
    return _cairo_surface_set_error (dst, status);
2639
}
2640
 
2641
/**
2642
 * _cairo_surface_composite_fixup_unbounded:
2643
 * @dst: the destination surface
2644
 * @src_attr: source surface attributes (from _cairo_pattern_acquire_surface())
2645
 * @src_width: width of source surface
2646
 * @src_height: height of source surface
2647
 * @mask_attr: mask surface attributes or %NULL if no mask
2648
 * @mask_width: width of mask surface
2649
 * @mask_height: height of mask surface
2650
 * @src_x: @src_x from _cairo_surface_composite()
2651
 * @src_y: @src_y from _cairo_surface_composite()
2652
 * @mask_x: @mask_x from _cairo_surface_composite()
2653
 * @mask_y: @mask_y from _cairo_surface_composite()
2654
 * @dst_x: @dst_x from _cairo_surface_composite()
2655
 * @dst_y: @dst_y from _cairo_surface_composite()
2656
 * @width: @width from _cairo_surface_composite()
2657
 * @height: @height_x from _cairo_surface_composite()
2658
 *
2659
 * Eeek! Too many parameters! This is a helper function to take care of fixing
2660
 * up for bugs in libpixman and RENDER where, when asked to composite an
2661
 * untransformed surface with an unbounded operator (like CLEAR or SOURCE)
2662
 * only the region inside both the source and the mask is affected.
2663
 * This function clears the region that should have been drawn but was wasn't.
2664
 **/
2665
cairo_status_t
2666
_cairo_surface_composite_fixup_unbounded (cairo_surface_t            *dst,
2667
                                          cairo_surface_attributes_t *src_attr,
2668
                                          int                         src_width,
2669
                                          int                         src_height,
2670
                                          cairo_surface_attributes_t *mask_attr,
2671
                                          int                         mask_width,
2672
                                          int                         mask_height,
2673
                                          int                         src_x,
2674
                                          int                         src_y,
2675
                                          int                         mask_x,
2676
                                          int                         mask_y,
2677
                                          int                         dst_x,
2678
                                          int                         dst_y,
2679
                                          unsigned int                width,
2680
                                          unsigned int                height,
2681
                                          cairo_region_t             *clip_region)
2682
{
2683
    cairo_rectangle_int_t src_tmp, mask_tmp;
2684
    cairo_rectangle_int_t *src_rectangle = NULL;
2685
    cairo_rectangle_int_t *mask_rectangle = NULL;
2686
 
2687
    if (unlikely (dst->status))
2688
        return dst->status;
2689
 
2690
    assert (_cairo_surface_is_writable (dst));
2691
 
2692
    /* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
2693
     * non-repeating sources and masks. Other sources and masks can be ignored.
2694
     */
2695
    if (_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) &&
2696
        src_attr->extend == CAIRO_EXTEND_NONE)
2697
    {
2698
        src_tmp.x = (dst_x - (src_x + src_attr->x_offset));
2699
        src_tmp.y = (dst_y - (src_y + src_attr->y_offset));
2700
        src_tmp.width = src_width;
2701
        src_tmp.height = src_height;
2702
 
2703
        src_rectangle = &src_tmp;
2704
    }
2705
 
2706
    if (mask_attr &&
2707
        _cairo_matrix_is_integer_translation (&mask_attr->matrix, NULL, NULL) &&
2708
        mask_attr->extend == CAIRO_EXTEND_NONE)
2709
    {
2710
        mask_tmp.x = (dst_x - (mask_x + mask_attr->x_offset));
2711
        mask_tmp.y = (dst_y - (mask_y + mask_attr->y_offset));
2712
        mask_tmp.width = mask_width;
2713
        mask_tmp.height = mask_height;
2714
 
2715
        mask_rectangle = &mask_tmp;
2716
    }
2717
 
2718
    return _cairo_surface_composite_fixup_unbounded_internal (dst, src_rectangle, mask_rectangle,
2719
                                                              dst_x, dst_y, width, height,
2720
                                                              clip_region);
2721
}
2722
 
2723
/**
2724
 * _cairo_surface_composite_shape_fixup_unbounded:
2725
 * @dst: the destination surface
2726
 * @src_attr: source surface attributes (from _cairo_pattern_acquire_surface())
2727
 * @src_width: width of source surface
2728
 * @src_height: height of source surface
2729
 * @mask_width: width of mask surface
2730
 * @mask_height: height of mask surface
2731
 * @src_x: @src_x from _cairo_surface_composite()
2732
 * @src_y: @src_y from _cairo_surface_composite()
2733
 * @mask_x: @mask_x from _cairo_surface_composite()
2734
 * @mask_y: @mask_y from _cairo_surface_composite()
2735
 * @dst_x: @dst_x from _cairo_surface_composite()
2736
 * @dst_y: @dst_y from _cairo_surface_composite()
2737
 * @width: @width from _cairo_surface_composite()
2738
 * @height: @height_x from _cairo_surface_composite()
2739
 *
2740
 * Like _cairo_surface_composite_fixup_unbounded(), but instead of
2741
 * handling the case where we have a source pattern and a mask
2742
 * pattern, handle the case where we are compositing a source pattern
2743
 * using a mask we create ourselves, as in
2744
 * _cairo_surface_composite_glyphs() or _cairo_surface_composite_trapezoids()
2745
 **/
2746
cairo_status_t
2747
_cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t            *dst,
2748
                                                cairo_surface_attributes_t *src_attr,
2749
                                                int                         src_width,
2750
                                                int                         src_height,
2751
                                                int                         mask_width,
2752
                                                int                         mask_height,
2753
                                                int                         src_x,
2754
                                                int                         src_y,
2755
                                                int                         mask_x,
2756
                                                int                         mask_y,
2757
                                                int                         dst_x,
2758
                                                int                         dst_y,
2759
                                                unsigned int                width,
2760
                                                unsigned int                height,
2761
                                                cairo_region_t      *clip_region)
2762
{
2763
    cairo_rectangle_int_t src_tmp, mask_tmp;
2764
    cairo_rectangle_int_t *src_rectangle = NULL;
2765
    cairo_rectangle_int_t *mask_rectangle = NULL;
2766
 
2767
    if (dst->status)
2768
        return dst->status;
2769
 
2770
    assert (_cairo_surface_is_writable (dst));
2771
 
2772
    /* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
2773
     * non-repeating sources and masks. Other sources and masks can be ignored.
2774
     */
2775
    if (_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) &&
2776
        src_attr->extend == CAIRO_EXTEND_NONE)
2777
    {
2778
        src_tmp.x = (dst_x - (src_x + src_attr->x_offset));
2779
        src_tmp.y = (dst_y - (src_y + src_attr->y_offset));
2780
        src_tmp.width = src_width;
2781
        src_tmp.height = src_height;
2782
 
2783
        src_rectangle = &src_tmp;
2784
    }
2785
 
2786
    mask_tmp.x = dst_x - mask_x;
2787
    mask_tmp.y = dst_y - mask_y;
2788
    mask_tmp.width = mask_width;
2789
    mask_tmp.height = mask_height;
2790
 
2791
    mask_rectangle = &mask_tmp;
2792
 
2793
    return _cairo_surface_composite_fixup_unbounded_internal (dst, src_rectangle, mask_rectangle,
2794
                                                              dst_x, dst_y, width, height,
2795
                                                              clip_region);
2796
}
2797
 
2798
/**
2799
 * _cairo_surface_copy_pattern_for_destination
2800
 * @pattern: the pattern to copy
2801
 * @destination: the destination surface for which the pattern is being copied
2802
 * @pattern_copy: the location to hold the copy
2803
 *
2804
 * Copies the given pattern, taking into account device scale and offsets
2805
 * of the destination surface.
2806
 */
2807
static void
2808
_cairo_surface_copy_pattern_for_destination (const cairo_pattern_t **pattern,
2809
                                             cairo_surface_t *destination,
2810
                                             cairo_pattern_t *pattern_copy)
2811
{
2812
    if (! _cairo_surface_has_device_transform (destination))
2813
        return;
2814
 
2815
    _cairo_pattern_init_static_copy (pattern_copy, *pattern);
2816
    _cairo_pattern_transform (pattern_copy,
2817
                              &destination->device_transform_inverse);
2818
 
2819
    *pattern = pattern_copy;
2820
}
2821
 
2822
/**
2823
 * _cairo_surface_set_resolution
2824
 * @surface: the surface
2825
 * @x_res: x resolution, in dpi
2826
 * @y_res: y resolution, in dpi
2827
 *
2828
 * Set the actual surface resolution of @surface to the given x and y DPI.
2829
 * Mainly used for correctly computing the scale factor when fallback
2830
 * rendering needs to take place in the paginated surface.
2831
 */
2832
void
2833
_cairo_surface_set_resolution (cairo_surface_t *surface,
2834
                               double x_res,
2835
                               double y_res)
2836
{
2837
    if (surface->status)
2838
        return;
2839
 
2840
    surface->x_resolution = x_res;
2841
    surface->y_resolution = y_res;
2842
}
2843
 
2844
/* Generic methods for determining operation extents. */
2845
 
2846
static void
2847
_rectangle_intersect_clip (cairo_rectangle_int_t *extents, cairo_clip_t *clip)
2848
{
2849
    const cairo_rectangle_int_t *clip_extents;
2850
    cairo_bool_t is_empty;
2851
 
2852
    clip_extents = NULL;
2853
    if (clip != NULL)
2854
        clip_extents = _cairo_clip_get_extents (clip);
2855
 
2856
    if (clip_extents != NULL)
2857
        is_empty = _cairo_rectangle_intersect (extents, clip_extents);
2858
}
2859
 
2860
static void
2861
_cairo_surface_operation_extents (cairo_surface_t *surface,
2862
                                  cairo_operator_t op,
2863
                                  const cairo_pattern_t *source,
2864
                                  cairo_clip_t *clip,
2865
                                  cairo_rectangle_int_t *extents)
2866
{
2867
    cairo_bool_t is_empty;
2868
 
2869
    is_empty = _cairo_surface_get_extents (surface, extents);
2870
 
2871
    if (_cairo_operator_bounded_by_source (op)) {
2872
        cairo_rectangle_int_t source_extents;
2873
 
2874
        _cairo_pattern_get_extents (source, &source_extents);
2875
        is_empty = _cairo_rectangle_intersect (extents, &source_extents);
2876
    }
2877
 
2878
    _rectangle_intersect_clip (extents, clip);
2879
}
2880
 
2881
cairo_status_t
2882
_cairo_surface_paint_extents (cairo_surface_t *surface,
2883
                              cairo_operator_t          op,
2884
                              const cairo_pattern_t     *source,
2885
                              cairo_clip_t              *clip,
2886
                              cairo_rectangle_int_t     *extents)
2887
{
2888
    _cairo_surface_operation_extents (surface, op, source, clip, extents);
2889
    return CAIRO_STATUS_SUCCESS;
2890
}
2891
 
2892
cairo_status_t
2893
_cairo_surface_mask_extents (cairo_surface_t *surface,
2894
                             cairo_operator_t            op,
2895
                             const cairo_pattern_t      *source,
2896
                             const cairo_pattern_t      *mask,
2897
                             cairo_clip_t               *clip,
2898
                             cairo_rectangle_int_t      *extents)
2899
{
2900
    cairo_bool_t is_empty;
2901
 
2902
    _cairo_surface_operation_extents (surface, op, source, clip, extents);
2903
 
2904
    if (_cairo_operator_bounded_by_mask (op)) {
2905
        cairo_rectangle_int_t mask_extents;
2906
 
2907
        _cairo_pattern_get_extents (mask, &mask_extents);
2908
        is_empty = _cairo_rectangle_intersect (extents, &mask_extents);
2909
    }
2910
 
2911
    return CAIRO_STATUS_SUCCESS;
2912
}
2913
 
2914
cairo_status_t
2915
_cairo_surface_stroke_extents (cairo_surface_t *surface,
2916
                               cairo_operator_t op,
2917
                               const cairo_pattern_t *source,
2918
                               cairo_path_fixed_t       *path,
2919
                               cairo_stroke_style_t *style,
2920
                               const cairo_matrix_t *ctm,
2921
                               const cairo_matrix_t *ctm_inverse,
2922
                               double tolerance,
2923
                               cairo_antialias_t         antialias,
2924
                               cairo_clip_t *clip,
2925
                               cairo_rectangle_int_t *extents)
2926
{
2927
    cairo_status_t status;
2928
    cairo_bool_t is_empty;
2929
 
2930
    _cairo_surface_operation_extents (surface, op, source, clip, extents);
2931
 
2932
    if (_cairo_operator_bounded_by_mask (op)) {
2933
        cairo_rectangle_int_t mask_extents;
2934
 
2935
        status = _cairo_path_fixed_stroke_extents (path, style,
2936
                                                   ctm, ctm_inverse,
2937
                                                   tolerance,
2938
                                                   &mask_extents);
2939
        if (unlikely (status))
2940
            return status;
2941
 
2942
        is_empty = _cairo_rectangle_intersect (extents, &mask_extents);
2943
    }
2944
 
2945
    return CAIRO_STATUS_SUCCESS;
2946
}
2947
 
2948
cairo_status_t
2949
_cairo_surface_fill_extents (cairo_surface_t            *surface,
2950
                             cairo_operator_t            op,
2951
                             const cairo_pattern_t      *source,
2952
                             cairo_path_fixed_t         *path,
2953
                             cairo_fill_rule_t           fill_rule,
2954
                             double                      tolerance,
2955
                             cairo_antialias_t           antialias,
2956
                             cairo_clip_t               *clip,
2957
                             cairo_rectangle_int_t      *extents)
2958
{
2959
    cairo_bool_t is_empty;
2960
 
2961
    _cairo_surface_operation_extents (surface, op, source, clip, extents);
2962
 
2963
    if (_cairo_operator_bounded_by_mask (op)) {
2964
        cairo_rectangle_int_t mask_extents;
2965
 
2966
        _cairo_path_fixed_fill_extents (path, fill_rule, tolerance,
2967
                                        &mask_extents);
2968
        is_empty = _cairo_rectangle_intersect (extents, &mask_extents);
2969
    }
2970
 
2971
    return CAIRO_STATUS_SUCCESS;
2972
}
2973
 
2974
cairo_status_t
2975
_cairo_surface_glyphs_extents (cairo_surface_t *surface,
2976
                               cairo_operator_t    op,
2977
                               const cairo_pattern_t *source,
2978
                               cairo_glyph_t      *glyphs,
2979
                               int                 num_glyphs,
2980
                               cairo_scaled_font_t  *scaled_font,
2981
                               cairo_clip_t         *clip,
2982
                               cairo_rectangle_int_t *extents)
2983
{
2984
    cairo_status_t           status;
2985
    cairo_bool_t             is_empty;
2986
 
2987
    _cairo_surface_operation_extents (surface, op, source, clip, extents);
2988
 
2989
    if (_cairo_operator_bounded_by_mask (op)) {
2990
        cairo_rectangle_int_t glyph_extents;
2991
 
2992
        status = _cairo_scaled_font_glyph_device_extents (scaled_font,
2993
                                                          glyphs,
2994
                                                          num_glyphs,
2995
                                                          &glyph_extents,
2996
                                                          NULL);
2997
        if (unlikely (status))
2998
            return status;
2999
 
3000
        is_empty = _cairo_rectangle_intersect (extents, &glyph_extents);
3001
    }
3002
 
3003
    return CAIRO_STATUS_SUCCESS;
3004
}
3005
 
3006
cairo_surface_t *
3007
_cairo_surface_create_in_error (cairo_status_t status)
3008
{
3009
    switch (status) {
3010
    case CAIRO_STATUS_NO_MEMORY:
3011
        return (cairo_surface_t *) &_cairo_surface_nil;
3012
    case CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
3013
        return (cairo_surface_t *) &_cairo_surface_nil_surface_type_mismatch;
3014
    case CAIRO_STATUS_INVALID_STATUS:
3015
        return (cairo_surface_t *) &_cairo_surface_nil_invalid_status;
3016
    case CAIRO_STATUS_INVALID_CONTENT:
3017
        return (cairo_surface_t *) &_cairo_surface_nil_invalid_content;
3018
    case CAIRO_STATUS_INVALID_FORMAT:
3019
        return (cairo_surface_t *) &_cairo_surface_nil_invalid_format;
3020
    case CAIRO_STATUS_INVALID_VISUAL:
3021
        return (cairo_surface_t *) &_cairo_surface_nil_invalid_visual;
3022
    case CAIRO_STATUS_READ_ERROR:
3023
        return (cairo_surface_t *) &_cairo_surface_nil_read_error;
3024
    case CAIRO_STATUS_WRITE_ERROR:
3025
        return (cairo_surface_t *) &_cairo_surface_nil_write_error;
3026
    case CAIRO_STATUS_FILE_NOT_FOUND:
3027
        return (cairo_surface_t *) &_cairo_surface_nil_file_not_found;
3028
    case CAIRO_STATUS_TEMP_FILE_ERROR:
3029
        return (cairo_surface_t *) &_cairo_surface_nil_temp_file_error;
3030
    case CAIRO_STATUS_INVALID_STRIDE:
3031
        return (cairo_surface_t *) &_cairo_surface_nil_invalid_stride;
3032
    case CAIRO_STATUS_INVALID_SIZE:
3033
        return (cairo_surface_t *) &_cairo_surface_nil_invalid_size;
3034
    case CAIRO_STATUS_SUCCESS:
3035
    case CAIRO_STATUS_LAST_STATUS:
3036
        ASSERT_NOT_REACHED;
3037
        /* fall-through */
3038
    case CAIRO_STATUS_INVALID_RESTORE:
3039
    case CAIRO_STATUS_INVALID_POP_GROUP:
3040
    case CAIRO_STATUS_NO_CURRENT_POINT:
3041
    case CAIRO_STATUS_INVALID_MATRIX:
3042
    case CAIRO_STATUS_NULL_POINTER:
3043
    case CAIRO_STATUS_INVALID_STRING:
3044
    case CAIRO_STATUS_INVALID_PATH_DATA:
3045
    case CAIRO_STATUS_SURFACE_FINISHED:
3046
    case CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
3047
    case CAIRO_STATUS_INVALID_DASH:
3048
    case CAIRO_STATUS_INVALID_DSC_COMMENT:
3049
    case CAIRO_STATUS_INVALID_INDEX:
3050
    case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
3051
    case CAIRO_STATUS_FONT_TYPE_MISMATCH:
3052
    case CAIRO_STATUS_USER_FONT_IMMUTABLE:
3053
    case CAIRO_STATUS_USER_FONT_ERROR:
3054
    case CAIRO_STATUS_NEGATIVE_COUNT:
3055
    case CAIRO_STATUS_INVALID_CLUSTERS:
3056
    case CAIRO_STATUS_INVALID_SLANT:
3057
    case CAIRO_STATUS_INVALID_WEIGHT:
3058
    case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
3059
    default:
3060
        _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
3061
        return (cairo_surface_t *) &_cairo_surface_nil;
3062
    }
3063
}
3064
 
3065
/*  LocalWords:  rasterized
3066
 */