~ubuntu-branches/ubuntu/maverick/cairo/maverick

« back to all changes in this revision

Viewing changes to .pc/90_git_surface_crash.patch/src/cairo-surface.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2010-07-06 11:39:41 UTC
  • Revision ID: james.westby@ubuntu.com-20100706113941-tk6nfdk83uoi80ce
Tags: 1.9.10-1ubuntu2
* debian/patches/90_git_surface_crash.patch:
  - git change to fix an assertion error crashing i.e inkscape (lp: #600622)

Show diffs side-by-side

added added

removed removed

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