w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

cairo-device.c
Go to the documentation of this file.
1 /* Cairo - a vector graphics library with display and print output
2  *
3  * Copyright © 2009 Intel Corporation
4  *
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.
12  *
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
18  *
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/
23  *
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.
27  *
28  * The Original Code is the cairo graphics library.
29  *
30  * The Initial Developer of the Original Code is Intel Corporation.
31  *
32  * Contributors(s):
33  * Chris Wilson <chris@chris-wilson.co.uk>
34  */
35 
36 #include "cairoint.h"
37 #include "cairo-device-private.h"
38 #include "cairo-error-private.h"
39 
40 /**
41  * SECTION:cairo-device
42  * @Title: cairo_device_t
43  * @Short_Description: interface to underlying rendering system
44  * @See_Also: #cairo_surface_t
45  *
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().
49  *
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.
53  *
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.
59  *
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.
64  *
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;
72  *
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  * }
81  *
82  * // Do the custom operations on the device here.
83  * // But do not call any Cairo functions that might acquire devices.
84  *
85  * // Release the device when done.
86  * cairo_device_release (device);
87  * }
88  * </programlisting></informalexample>
89  *
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  **/
96 
97 static const cairo_device_t _nil_device = {
100 };
101 
105 };
106 
110 };
111 
114 {
115  switch (status) {
117  return (cairo_device_t *) &_nil_device;
119  return (cairo_device_t *) &_invalid_device;
121  return (cairo_device_t *) &_mismatch_device;
122 
126  /* fall-through */
166  default:
168  return (cairo_device_t *) &_nil_device;
169  }
170 }
171 
172 void
175 {
177  device->status = CAIRO_STATUS_SUCCESS;
178 
179  device->backend = backend;
180 
182  device->mutex_depth = 0;
183 
184  device->finished = FALSE;
185 
187 }
188 
189 /**
190  * cairo_device_reference:
191  * @device: a #cairo_device_t
192  *
193  * Increases the reference count on @device by one. This prevents
194  * @device from being destroyed until a matching call to
195  * cairo_device_destroy() is made.
196  *
197  * Use cairo_device_get_reference_count() to get the number of references
198  * to a #cairo_device_t.
199  *
200  * Return value: the referenced #cairo_device_t.
201  *
202  * Since: 1.10
203  **/
206 {
207  if (device == NULL ||
209  {
210  return device;
211  }
212 
215 
216  return device;
217 }
219 
220 /**
221  * cairo_device_status:
222  * @device: a #cairo_device_t
223  *
224  * Checks whether an error has previously occurred for this
225  * device.
226  *
227  * Return value: %CAIRO_STATUS_SUCCESS on success or an error code if
228  * the device is in an error state.
229  *
230  * Since: 1.10
231  **/
234 {
235  if (device == NULL)
237 
238  return device->status;
239 }
240 
241 /**
242  * cairo_device_flush:
243  * @device: a #cairo_device_t
244  *
245  * Finish any pending operations for the device and also restore any
246  * temporary modifications cairo has made to the device's state.
247  * This function must be called before switching from using the
248  * device with Cairo to operating on it directly with native APIs.
249  * If the device doesn't support direct access, then this function
250  * does nothing.
251  *
252  * This function may acquire devices.
253  *
254  * Since: 1.10
255  **/
256 void
258 {
260 
261  if (device == NULL || device->status)
262  return;
263 
264  if (device->finished)
265  return;
266 
267  if (device->backend->flush != NULL) {
268  status = device->backend->flush (device);
269  if (unlikely (status))
271  }
272 }
274 
275 /**
276  * cairo_device_finish:
277  * @device: the #cairo_device_t to finish
278  *
279  * This function finishes the device and drops all references to
280  * external resources. All surfaces, fonts and other objects created
281  * for this @device will be finished, too.
282  * Further operations on the @device will not affect the @device but
283  * will instead trigger a %CAIRO_STATUS_DEVICE_FINISHED error.
284  *
285  * When the last call to cairo_device_destroy() decreases the
286  * reference count to zero, cairo will call cairo_device_finish() if
287  * it hasn't been called already, before freeing the resources
288  * associated with the device.
289  *
290  * This function may acquire devices.
291  *
292  * Since: 1.10
293  **/
294 void
296 {
297  if (device == NULL ||
299  {
300  return;
301  }
302 
303  if (device->finished)
304  return;
305 
306  cairo_device_flush (device);
307 
308  if (device->backend->finish != NULL)
309  device->backend->finish (device);
310 
311  /* We only finish the device after the backend's callback returns because
312  * the device might still be needed during the callback
313  * (e.g. for cairo_device_acquire ()).
314  */
315  device->finished = TRUE;
316 }
318 
319 /**
320  * cairo_device_destroy:
321  * @device: a #cairo_device_t
322  *
323  * Decreases the reference count on @device by one. If the result is
324  * zero, then @device and all associated resources are freed. See
325  * cairo_device_reference().
326  *
327  * This function may acquire devices if the last reference was dropped.
328  *
329  * Since: 1.10
330  **/
331 void
333 {
334  cairo_user_data_array_t user_data;
335 
336  if (device == NULL ||
338  {
339  return;
340  }
341 
344  return;
345 
346  cairo_device_finish (device);
347 
348  assert (device->mutex_depth == 0);
349  CAIRO_MUTEX_FINI (device->mutex);
350 
351  user_data = device->user_data;
352 
353  device->backend->destroy (device);
354 
355  _cairo_user_data_array_fini (&user_data);
356 
357 }
359 
360 /**
361  * cairo_device_get_type:
362  * @device: a #cairo_device_t
363  *
364  * This function returns the type of the device. See #cairo_device_type_t
365  * for available types.
366  *
367  * Return value: The type of @device.
368  *
369  * Since: 1.10
370  **/
373 {
374  if (device == NULL ||
376  {
378  }
379 
380  return device->backend->type;
381 }
382 
383 /**
384  * cairo_device_acquire:
385  * @device: a #cairo_device_t
386  *
387  * Acquires the @device for the current thread. This function will block
388  * until no other thread has acquired the device.
389  *
390  * If the return value is %CAIRO_STATUS_SUCCESS, you successfully acquired the
391  * device. From now on your thread owns the device and no other thread will be
392  * able to acquire it until a matching call to cairo_device_release(). It is
393  * allowed to recursively acquire the device multiple times from the same
394  * thread.
395  *
396  * <note><para>You must never acquire two different devices at the same time
397  * unless this is explicitly allowed. Otherwise the possibility of deadlocks
398  * exist.
399  *
400  * As various Cairo functions can acquire devices when called, these functions
401  * may also cause deadlocks when you call them with an acquired device. So you
402  * must not have a device acquired when calling them. These functions are
403  * marked in the documentation.
404  * </para></note>
405  *
406  * Return value: %CAIRO_STATUS_SUCCESS on success or an error code if
407  * the device is in an error state and could not be
408  * acquired. After a successful call to cairo_device_acquire(),
409  * a matching call to cairo_device_release() is required.
410  *
411  * Since: 1.10
412  **/
415 {
416  if (device == NULL)
417  return CAIRO_STATUS_SUCCESS;
418 
419  if (unlikely (device->status))
420  return device->status;
421 
422  if (unlikely (device->finished))
424 
425  CAIRO_MUTEX_LOCK (device->mutex);
426  if (device->mutex_depth++ == 0) {
427  if (device->backend->lock != NULL)
428  device->backend->lock (device);
429  }
430 
431  return CAIRO_STATUS_SUCCESS;
432 }
434 
435 /**
436  * cairo_device_release:
437  * @device: a #cairo_device_t
438  *
439  * Releases a @device previously acquired using cairo_device_acquire(). See
440  * that function for details.
441  *
442  * Since: 1.10
443  **/
444 void
446 {
447  if (device == NULL)
448  return;
449 
450  assert (device->mutex_depth > 0);
451 
452  if (--device->mutex_depth == 0) {
453  if (device->backend->unlock != NULL)
454  device->backend->unlock (device);
455  }
456 
457  CAIRO_MUTEX_UNLOCK (device->mutex);
458 }
460 
464 {
466  return CAIRO_STATUS_SUCCESS;
467 
469 
470  return _cairo_error (status);
471 }
472 
473 /**
474  * cairo_device_get_reference_count:
475  * @device: a #cairo_device_t
476  *
477  * Returns the current reference count of @device.
478  *
479  * Return value: the current reference count of @device. If the
480  * object is a nil object, 0 will be returned.
481  *
482  * Since: 1.10
483  **/
484 unsigned int
486 {
487  if (device == NULL ||
489  return 0;
490 
491  return CAIRO_REFERENCE_COUNT_GET_VALUE (&device->ref_count);
492 }
493 
494 /**
495  * cairo_device_get_user_data:
496  * @device: a #cairo_device_t
497  * @key: the address of the #cairo_user_data_key_t the user data was
498  * attached to
499  *
500  * Return user data previously attached to @device using the
501  * specified key. If no user data has been attached with the given
502  * key this function returns %NULL.
503  *
504  * Return value: the user data previously attached or %NULL.
505  *
506  * Since: 1.10
507  **/
508 void *
510  const cairo_user_data_key_t *key)
511 {
513  key);
514 }
515 
516 /**
517  * cairo_device_set_user_data:
518  * @device: a #cairo_device_t
519  * @key: the address of a #cairo_user_data_key_t to attach the user data to
520  * @user_data: the user data to attach to the #cairo_device_t
521  * @destroy: a #cairo_destroy_func_t which will be called when the
522  * #cairo_t is destroyed or when new user data is attached using the
523  * same key.
524  *
525  * Attach user data to @device. To remove user data from a surface,
526  * call this function with the key that was used to set it and %NULL
527  * for @data.
528  *
529  * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
530  * slot could not be allocated for the user data.
531  *
532  * Since: 1.10
533  **/
536  const cairo_user_data_key_t *key,
537  void *user_data,
538  cairo_destroy_func_t destroy)
539 {
541  return device->status;
542 
544  key, user_data, destroy);
545 }
void * _cairo_user_data_array_get_data(cairo_user_data_array_t *array, const cairo_user_data_key_t *key)
Definition: cairo-array.c:412
void _cairo_user_data_array_init(cairo_user_data_array_t *array)
Definition: cairo-array.c:367
cairo_status_t _cairo_user_data_array_set_data(cairo_user_data_array_t *array, const cairo_user_data_key_t *key, void *user_data, cairo_destroy_func_t destroy)
Definition: cairo-array.c:449
void _cairo_user_data_array_fini(cairo_user_data_array_t *array)
Definition: cairo-array.c:380
#define _cairo_status_set_error(status, err)
#define slim_hidden_def(name)
void cairo_device_release(cairo_device_t *device)
Definition: cairo-device.c:445
static const cairo_device_t _invalid_device
Definition: cairo-device.c:107
cairo_status_t cairo_device_acquire(cairo_device_t *device)
Definition: cairo-device.c:414
cairo_status_t _cairo_device_set_error(cairo_device_t *device, cairo_status_t status)
Definition: cairo-device.c:462
cairo_status_t cairo_device_set_user_data(cairo_device_t *device, const cairo_user_data_key_t *key, void *user_data, cairo_destroy_func_t destroy)
Definition: cairo-device.c:535
void _cairo_device_init(cairo_device_t *device, const cairo_device_backend_t *backend)
Definition: cairo-device.c:173
void cairo_device_finish(cairo_device_t *device)
Definition: cairo-device.c:295
cairo_device_t * _cairo_device_create_in_error(cairo_status_t status)
Definition: cairo-device.c:113
unsigned int cairo_device_get_reference_count(cairo_device_t *device)
Definition: cairo-device.c:485
cairo_device_t * cairo_device_reference(cairo_device_t *device)
Definition: cairo-device.c:205
void * cairo_device_get_user_data(cairo_device_t *device, const cairo_user_data_key_t *key)
Definition: cairo-device.c:509
void cairo_device_destroy(cairo_device_t *device)
Definition: cairo-device.c:332
void cairo_device_flush(cairo_device_t *device)
Definition: cairo-device.c:257
cairo_status_t cairo_device_status(cairo_device_t *device)
Definition: cairo-device.c:233
static const cairo_device_t _nil_device
Definition: cairo-device.c:97
cairo_device_type_t cairo_device_get_type(cairo_device_t *device)
Definition: cairo-device.c:372
static const cairo_device_t _mismatch_device
Definition: cairo-device.c:102
cairo_status_t _cairo_error(cairo_status_t status)
Definition: cairo-error.c:65
#define _cairo_error_throw(status)
#define CAIRO_MUTEX_FINI
#define CAIRO_MUTEX_UNLOCK
#define CAIRO_MUTEX_LOCK
#define CAIRO_RECURSIVE_MUTEX_INIT
#define CAIRO_REFERENCE_COUNT_HAS_REFERENCE(RC)
#define CAIRO_REFERENCE_COUNT_GET_VALUE(RC)
#define CAIRO_REFERENCE_COUNT_IS_INVALID(RC)
#define _cairo_reference_count_inc(RC)
#define _cairo_reference_count_dec_and_test(RC)
#define CAIRO_REFERENCE_COUNT_INVALID
#define CAIRO_REFERENCE_COUNT_INIT(RC, VALUE)
@ CAIRO_STATUS_NO_CURRENT_POINT
Definition: cairo.h:320
@ CAIRO_STATUS_INVALID_CLUSTERS
Definition: cairo.h:345
@ CAIRO_STATUS_SUCCESS
Definition: cairo.h:315
@ CAIRO_STATUS_TEMP_FILE_ERROR
Definition: cairo.h:339
@ CAIRO_STATUS_NULL_POINTER
Definition: cairo.h:323
@ CAIRO_STATUS_INVALID_MESH_CONSTRUCTION
Definition: cairo.h:352
@ CAIRO_STATUS_INVALID_CONTENT
Definition: cairo.h:331
@ CAIRO_STATUS_INVALID_SIZE
Definition: cairo.h:348
@ CAIRO_STATUS_SURFACE_TYPE_MISMATCH
Definition: cairo.h:329
@ CAIRO_STATUS_INVALID_FORMAT
Definition: cairo.h:332
@ CAIRO_STATUS_DEVICE_FINISHED
Definition: cairo.h:353
@ CAIRO_STATUS_FILE_NOT_FOUND
Definition: cairo.h:334
@ CAIRO_STATUS_PNG_ERROR
Definition: cairo.h:355
@ CAIRO_STATUS_INVALID_SLANT
Definition: cairo.h:346
@ CAIRO_STATUS_INVALID_INDEX
Definition: cairo.h:337
@ CAIRO_STATUS_JBIG2_GLOBAL_MISSING
Definition: cairo.h:354
@ CAIRO_STATUS_INVALID_STATUS
Definition: cairo.h:322
@ CAIRO_STATUS_INVALID_DASH
Definition: cairo.h:335
@ CAIRO_STATUS_WRITE_ERROR
Definition: cairo.h:327
@ CAIRO_STATUS_SURFACE_FINISHED
Definition: cairo.h:328
@ CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED
Definition: cairo.h:349
@ CAIRO_STATUS_FREETYPE_ERROR
Definition: cairo.h:356
@ CAIRO_STATUS_USER_FONT_ERROR
Definition: cairo.h:343
@ CAIRO_STATUS_DEVICE_ERROR
Definition: cairo.h:351
@ CAIRO_STATUS_INVALID_POP_GROUP
Definition: cairo.h:319
@ CAIRO_STATUS_DEVICE_TYPE_MISMATCH
Definition: cairo.h:350
@ CAIRO_STATUS_NO_MEMORY
Definition: cairo.h:317
@ CAIRO_STATUS_LAST_STATUS
Definition: cairo.h:360
@ CAIRO_STATUS_CLIP_NOT_REPRESENTABLE
Definition: cairo.h:338
@ CAIRO_STATUS_INVALID_RESTORE
Definition: cairo.h:318
@ CAIRO_STATUS_PATTERN_TYPE_MISMATCH
Definition: cairo.h:330
@ CAIRO_STATUS_INVALID_DSC_COMMENT
Definition: cairo.h:336
@ CAIRO_STATUS_NEGATIVE_COUNT
Definition: cairo.h:344
@ CAIRO_STATUS_INVALID_WEIGHT
Definition: cairo.h:347
@ CAIRO_STATUS_READ_ERROR
Definition: cairo.h:326
@ CAIRO_STATUS_WIN32_GDI_ERROR
Definition: cairo.h:357
@ CAIRO_STATUS_TAG_ERROR
Definition: cairo.h:358
@ CAIRO_STATUS_FONT_TYPE_MISMATCH
Definition: cairo.h:341
@ CAIRO_STATUS_INVALID_VISUAL
Definition: cairo.h:333
@ CAIRO_STATUS_INVALID_STRING
Definition: cairo.h:324
@ CAIRO_STATUS_INVALID_PATH_DATA
Definition: cairo.h:325
@ CAIRO_STATUS_USER_FONT_IMMUTABLE
Definition: cairo.h:342
@ CAIRO_STATUS_INVALID_STRIDE
Definition: cairo.h:340
@ CAIRO_STATUS_INVALID_MATRIX
Definition: cairo.h:321
enum _cairo_status cairo_status_t
void(* cairo_destroy_func_t)(void *data)
Definition: cairo.h:232
@ CAIRO_DEVICE_TYPE_INVALID
Definition: cairo.h:2173
enum _cairo_device_type cairo_device_type_t
#define ASSERT_NOT_REACHED
Definition: cairoint.h:155
@ FALSE
Definition: dd.h:101
@ TRUE
Definition: dd.h:102
assert(pcxLoadImage24((char *)((void *) 0), fp, pinfo, hdr))
#define unlikely(x)
Definition: jbig2arith.cc:116
#define NULL
Definition: ftobjs.h:61
#define status
static backend_t backend[]
Definition: main.c:103
cairo_status_t(* flush)(void *device)
void(* finish)(void *device)
cairo_device_type_t type
void(* destroy)(void *device)
void(* lock)(void *device)
void(* unlock)(void *device)
cairo_recursive_mutex_t mutex
cairo_reference_count_t ref_count
cairo_bool_t finished
cairo_status_t status
const cairo_device_backend_t * backend
cairo_user_data_array_t user_data
#define key
Definition: tex2xindy.c:753