Coverage Report

Created: 2025-07-07 10:01

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