beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-device.c
blob585a9c1c41f98f76caee56eebb8ccd072fe0b80a
1 /* Cairo - a vector graphics library with display and print output
3 * Copyright © 2009 Intel Corporation
5 * This library is free software; you can redistribute it and/or
6 * modify it either under the terms of the GNU Lesser General Public
7 * License version 2.1 as published by the Free Software Foundation
8 * (the "LGPL") or, at your option, under the terms of the Mozilla
9 * Public License Version 1.1 (the "MPL"). If you do not alter this
10 * notice, a recipient may use your version of this file under either
11 * the MPL or the LGPL.
13 * You should have received a copy of the LGPL along with this library
14 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
19 * The contents of this file are subject to the Mozilla Public License
20 * Version 1.1 (the "License"); you may not use this file except in
21 * compliance with the License. You may obtain a copy of the License at
22 * http://www.mozilla.org/MPL/
24 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 * the specific language governing rights and limitations.
28 * The Original Code is the cairo graphics library.
30 * The Initial Developer of the Original Code is Intel Corporation.
32 * Contributors(s):
33 * Chris Wilson <chris@chris-wilson.co.uk>
36 #include "cairoint.h"
37 #include "cairo-device-private.h"
38 #include "cairo-error-private.h"
40 /**
41 * SECTION:cairo-device
42 * @Title: cairo_device_t
43 * @Short_Description: interface to underlying rendering system
44 * @See_Also: #cairo_surface_t
46 * Devices are the abstraction Cairo employs for the rendering system
47 * used by a #cairo_surface_t. You can get the device of a surface using
48 * cairo_surface_get_device().
50 * Devices are created using custom functions specific to the rendering
51 * system you want to use. See the documentation for the surface types
52 * for those functions.
54 * An important function that devices fulfill is sharing access to the
55 * rendering system between Cairo and your application. If you want to
56 * access a device directly that you used to draw to with Cairo, you must
57 * first call cairo_device_flush() to ensure that Cairo finishes all
58 * operations on the device and resets it to a clean state.
60 * Cairo also provides the functions cairo_device_acquire() and
61 * cairo_device_release() to synchronize access to the rendering system
62 * in a multithreaded environment. This is done internally, but can also
63 * be used by applications.
65 * Putting this all together, a function that works with devices should
66 * look something like this:
67 * <informalexample><programlisting>
68 * void
69 * my_device_modifying_function (cairo_device_t *device)
70 * {
71 * cairo_status_t status;
73 * // Ensure the device is properly reset
74 * cairo_device_flush (device);
75 * // Try to acquire the device
76 * status = cairo_device_acquire (device);
77 * if (status != CAIRO_STATUS_SUCCESS) {
78 * printf ("Failed to acquire the device: %s\n", cairo_status_to_string (status));
79 * return;
80 * }
82 * // Do the custom operations on the device here.
83 * // But do not call any Cairo functions that might acquire devices.
85 * // Release the device when done.
86 * cairo_device_release (device);
87 * }
88 * </programlisting></informalexample>
90 * <note><para>Please refer to the documentation of each backend for
91 * additional usage requirements, guarantees provided, and
92 * interactions with existing surface API of the device functions for
93 * surfaces of that type.
94 * </para></note>
95 **/
97 static const cairo_device_t _nil_device = {
98 CAIRO_REFERENCE_COUNT_INVALID,
99 CAIRO_STATUS_NO_MEMORY,
102 static const cairo_device_t _mismatch_device = {
103 CAIRO_REFERENCE_COUNT_INVALID,
104 CAIRO_STATUS_DEVICE_TYPE_MISMATCH,
107 static const cairo_device_t _invalid_device = {
108 CAIRO_REFERENCE_COUNT_INVALID,
109 CAIRO_STATUS_DEVICE_ERROR,
112 cairo_device_t *
113 _cairo_device_create_in_error (cairo_status_t status)
115 switch (status) {
116 case CAIRO_STATUS_NO_MEMORY:
117 return (cairo_device_t *) &_nil_device;
118 case CAIRO_STATUS_DEVICE_ERROR:
119 return (cairo_device_t *) &_invalid_device;
120 case CAIRO_STATUS_DEVICE_TYPE_MISMATCH:
121 return (cairo_device_t *) &_mismatch_device;
123 case CAIRO_STATUS_SUCCESS:
124 case CAIRO_STATUS_LAST_STATUS:
125 ASSERT_NOT_REACHED;
126 /* fall-through */
127 case CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
128 case CAIRO_STATUS_INVALID_STATUS:
129 case CAIRO_STATUS_INVALID_FORMAT:
130 case CAIRO_STATUS_INVALID_VISUAL:
131 case CAIRO_STATUS_READ_ERROR:
132 case CAIRO_STATUS_WRITE_ERROR:
133 case CAIRO_STATUS_FILE_NOT_FOUND:
134 case CAIRO_STATUS_TEMP_FILE_ERROR:
135 case CAIRO_STATUS_INVALID_STRIDE:
136 case CAIRO_STATUS_INVALID_SIZE:
137 case CAIRO_STATUS_INVALID_RESTORE:
138 case CAIRO_STATUS_INVALID_POP_GROUP:
139 case CAIRO_STATUS_NO_CURRENT_POINT:
140 case CAIRO_STATUS_INVALID_MATRIX:
141 case CAIRO_STATUS_NULL_POINTER:
142 case CAIRO_STATUS_INVALID_STRING:
143 case CAIRO_STATUS_INVALID_PATH_DATA:
144 case CAIRO_STATUS_SURFACE_FINISHED:
145 case CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
146 case CAIRO_STATUS_INVALID_DASH:
147 case CAIRO_STATUS_INVALID_DSC_COMMENT:
148 case CAIRO_STATUS_INVALID_INDEX:
149 case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
150 case CAIRO_STATUS_FONT_TYPE_MISMATCH:
151 case CAIRO_STATUS_USER_FONT_IMMUTABLE:
152 case CAIRO_STATUS_USER_FONT_ERROR:
153 case CAIRO_STATUS_NEGATIVE_COUNT:
154 case CAIRO_STATUS_INVALID_CLUSTERS:
155 case CAIRO_STATUS_INVALID_SLANT:
156 case CAIRO_STATUS_INVALID_WEIGHT:
157 case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
158 case CAIRO_STATUS_INVALID_CONTENT:
159 case CAIRO_STATUS_INVALID_MESH_CONSTRUCTION:
160 case CAIRO_STATUS_DEVICE_FINISHED:
161 case CAIRO_STATUS_JBIG2_GLOBAL_MISSING:
162 default:
163 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
164 return (cairo_device_t *) &_nil_device;
168 void
169 _cairo_device_init (cairo_device_t *device,
170 const cairo_device_backend_t *backend)
172 CAIRO_REFERENCE_COUNT_INIT (&device->ref_count, 1);
173 device->status = CAIRO_STATUS_SUCCESS;
175 device->backend = backend;
177 CAIRO_RECURSIVE_MUTEX_INIT (device->mutex);
178 device->mutex_depth = 0;
180 device->finished = FALSE;
182 _cairo_user_data_array_init (&device->user_data);
186 * cairo_device_reference:
187 * @device: a #cairo_device_t
189 * Increases the reference count on @device by one. This prevents
190 * @device from being destroyed until a matching call to
191 * cairo_device_destroy() is made.
193 * The number of references to a #cairo_device_t can be get using
194 * cairo_device_get_reference_count().
196 * Return value: the referenced #cairo_device_t.
198 * Since: 1.10
200 cairo_device_t *
201 cairo_device_reference (cairo_device_t *device)
203 if (device == NULL ||
204 CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
206 return device;
209 assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&device->ref_count));
210 _cairo_reference_count_inc (&device->ref_count);
212 return device;
214 slim_hidden_def (cairo_device_reference);
217 * cairo_device_status:
218 * @device: a #cairo_device_t
220 * Checks whether an error has previously occurred for this
221 * device.
223 * Return value: %CAIRO_STATUS_SUCCESS on success or an error code if
224 * the device is in an error state.
226 * Since: 1.10
228 cairo_status_t
229 cairo_device_status (cairo_device_t *device)
231 if (device == NULL)
232 return CAIRO_STATUS_NULL_POINTER;
234 return device->status;
238 * cairo_device_flush:
239 * @device: a #cairo_device_t
241 * Finish any pending operations for the device and also restore any
242 * temporary modifications cairo has made to the device's state.
243 * This function must be called before switching from using the
244 * device with Cairo to operating on it directly with native APIs.
245 * If the device doesn't support direct access, then this function
246 * does nothing.
248 * This function may acquire devices.
250 * Since: 1.10
252 void
253 cairo_device_flush (cairo_device_t *device)
255 cairo_status_t status;
257 if (device == NULL || device->status)
258 return;
260 if (device->finished)
261 return;
263 if (device->backend->flush != NULL) {
264 status = device->backend->flush (device);
265 if (unlikely (status))
266 status = _cairo_device_set_error (device, status);
269 slim_hidden_def (cairo_device_flush);
272 * cairo_device_finish:
273 * @device: the #cairo_device_t to finish
275 * This function finishes the device and drops all references to
276 * external resources. All surfaces, fonts and other objects created
277 * for this @device will be finished, too.
278 * Further operations on the @device will not affect the @device but
279 * will instead trigger a %CAIRO_STATUS_DEVICE_FINISHED error.
281 * When the last call to cairo_device_destroy() decreases the
282 * reference count to zero, cairo will call cairo_device_finish() if
283 * it hasn't been called already, before freeing the resources
284 * associated with the device.
286 * This function may acquire devices.
288 * Since: 1.10
290 void
291 cairo_device_finish (cairo_device_t *device)
293 if (device == NULL ||
294 CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
296 return;
299 if (device->finished)
300 return;
302 cairo_device_flush (device);
304 if (device->backend->finish != NULL)
305 device->backend->finish (device);
307 /* We only finish the device after the backend's callback returns because
308 * the device might still be needed during the callback
309 * (e.g. for cairo_device_acquire ()).
311 device->finished = TRUE;
313 slim_hidden_def (cairo_device_finish);
316 * cairo_device_destroy:
317 * @device: a #cairo_device_t
319 * Decreases the reference count on @device by one. If the result is
320 * zero, then @device and all associated resources are freed. See
321 * cairo_device_reference().
323 * This function may acquire devices if the last reference was dropped.
325 * Since: 1.10
327 void
328 cairo_device_destroy (cairo_device_t *device)
330 cairo_user_data_array_t user_data;
332 if (device == NULL ||
333 CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
335 return;
338 assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&device->ref_count));
339 if (! _cairo_reference_count_dec_and_test (&device->ref_count))
340 return;
342 cairo_device_finish (device);
344 assert (device->mutex_depth == 0);
345 CAIRO_MUTEX_FINI (device->mutex);
347 user_data = device->user_data;
349 device->backend->destroy (device);
351 _cairo_user_data_array_fini (&user_data);
354 slim_hidden_def (cairo_device_destroy);
357 * cairo_device_get_type:
358 * @device: a #cairo_device_t
360 * This function returns the type of the device. See #cairo_device_type_t
361 * for available types.
363 * Return value: The type of @device.
365 * Since: 1.10
367 cairo_device_type_t
368 cairo_device_get_type (cairo_device_t *device)
370 if (device == NULL ||
371 CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
373 return CAIRO_DEVICE_TYPE_INVALID;
376 return device->backend->type;
380 * cairo_device_acquire:
381 * @device: a #cairo_device_t
383 * Acquires the @device for the current thread. This function will block
384 * until no other thread has acquired the device.
386 * If the return value is %CAIRO_STATUS_SUCCESS, you successfully acquired the
387 * device. From now on your thread owns the device and no other thread will be
388 * able to acquire it until a matching call to cairo_device_release(). It is
389 * allowed to recursively acquire the device multiple times from the same
390 * thread.
392 * <note><para>You must never acquire two different devices at the same time
393 * unless this is explicitly allowed. Otherwise the possibility of deadlocks
394 * exist.
396 * As various Cairo functions can acquire devices when called, these functions
397 * may also cause deadlocks when you call them with an acquired device. So you
398 * must not have a device acquired when calling them. These functions are
399 * marked in the documentation.
400 * </para></note>
402 * Return value: %CAIRO_STATUS_SUCCESS on success or an error code if
403 * the device is in an error state and could not be
404 * acquired. After a successful call to cairo_device_acquire(),
405 * a matching call to cairo_device_release() is required.
407 * Since: 1.10
409 cairo_status_t
410 cairo_device_acquire (cairo_device_t *device)
412 if (device == NULL)
413 return CAIRO_STATUS_SUCCESS;
415 if (unlikely (device->status))
416 return device->status;
418 if (unlikely (device->finished))
419 return _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_FINISHED);
421 CAIRO_MUTEX_LOCK (device->mutex);
422 if (device->mutex_depth++ == 0) {
423 if (device->backend->lock != NULL)
424 device->backend->lock (device);
427 return CAIRO_STATUS_SUCCESS;
429 slim_hidden_def (cairo_device_acquire);
432 * cairo_device_release:
433 * @device: a #cairo_device_t
435 * Releases a @device previously acquired using cairo_device_acquire(). See
436 * that function for details.
438 * Since: 1.10
440 void
441 cairo_device_release (cairo_device_t *device)
443 if (device == NULL)
444 return;
446 assert (device->mutex_depth > 0);
448 if (--device->mutex_depth == 0) {
449 if (device->backend->unlock != NULL)
450 device->backend->unlock (device);
453 CAIRO_MUTEX_UNLOCK (device->mutex);
455 slim_hidden_def (cairo_device_release);
457 cairo_status_t
458 _cairo_device_set_error (cairo_device_t *device,
459 cairo_status_t status)
461 if (status == CAIRO_STATUS_SUCCESS)
462 return CAIRO_STATUS_SUCCESS;
464 _cairo_status_set_error (&device->status, status);
466 return _cairo_error (status);
470 * cairo_device_get_reference_count:
471 * @device: a #cairo_device_t
473 * Returns the current reference count of @device.
475 * Return value: the current reference count of @device. If the
476 * object is a nil object, 0 will be returned.
478 * Since: 1.10
480 unsigned int
481 cairo_device_get_reference_count (cairo_device_t *device)
483 if (device == NULL ||
484 CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
485 return 0;
487 return CAIRO_REFERENCE_COUNT_GET_VALUE (&device->ref_count);
491 * cairo_device_get_user_data:
492 * @device: a #cairo_device_t
493 * @key: the address of the #cairo_user_data_key_t the user data was
494 * attached to
496 * Return user data previously attached to @device using the
497 * specified key. If no user data has been attached with the given
498 * key this function returns %NULL.
500 * Return value: the user data previously attached or %NULL.
502 * Since: 1.10
504 void *
505 cairo_device_get_user_data (cairo_device_t *device,
506 const cairo_user_data_key_t *key)
508 return _cairo_user_data_array_get_data (&device->user_data,
509 key);
513 * cairo_device_set_user_data:
514 * @device: a #cairo_device_t
515 * @key: the address of a #cairo_user_data_key_t to attach the user data to
516 * @user_data: the user data to attach to the #cairo_device_t
517 * @destroy: a #cairo_destroy_func_t which will be called when the
518 * #cairo_t is destroyed or when new user data is attached using the
519 * same key.
521 * Attach user data to @device. To remove user data from a surface,
522 * call this function with the key that was used to set it and %NULL
523 * for @data.
525 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
526 * slot could not be allocated for the user data.
528 * Since: 1.10
530 cairo_status_t
531 cairo_device_set_user_data (cairo_device_t *device,
532 const cairo_user_data_key_t *key,
533 void *user_data,
534 cairo_destroy_func_t destroy)
536 if (CAIRO_REFERENCE_COUNT_IS_INVALID (&device->ref_count))
537 return device->status;
539 return _cairo_user_data_array_set_data (&device->user_data,
540 key, user_data, destroy);