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