Tizen 2.0 Release
[framework/graphics/cairo.git] / src / cairo-font-face.c
1 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
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  *      Graydon Hoare <graydon@redhat.com>
38  *      Owen Taylor <otaylor@redhat.com>
39  */
40
41 #include "cairoint.h"
42 #include "cairo-error-private.h"
43
44 /**
45  * SECTION:cairo-font-face
46  * @Title: cairo_font_face_t
47  * @Short_Description: Base class for font faces
48  * @See_Also: #cairo_scaled_font_t
49  *
50  * #cairo_font_face_t represents a particular font at a particular weight,
51  * slant, and other characteristic but no size, transformation, or size.
52  *
53  * Font faces are created using <firstterm>font-backend</firstterm>-specific
54  * constructors, typically of the form
55  * <function>cairo_<emphasis>backend</emphasis>_font_face_create(<!-- -->)</function>,
56  * or implicitly using the <firstterm>toy</firstterm> text API by way of
57  * cairo_select_font_face().  The resulting face can be accessed using
58  * cairo_get_font_face().
59  **/
60
61 /* #cairo_font_face_t */
62
63 const cairo_font_face_t _cairo_font_face_nil = {
64     { 0 },                              /* hash_entry */
65     CAIRO_STATUS_NO_MEMORY,             /* status */
66     CAIRO_REFERENCE_COUNT_INVALID,      /* ref_count */
67     { 0, 0, 0, NULL },                  /* user_data */
68     NULL
69 };
70
71 cairo_status_t
72 _cairo_font_face_set_error (cairo_font_face_t *font_face,
73                             cairo_status_t     status)
74 {
75     if (status == CAIRO_STATUS_SUCCESS)
76         return status;
77
78     /* Don't overwrite an existing error. This preserves the first
79      * error, which is the most significant. */
80     _cairo_status_set_error (&font_face->status, status);
81
82     return _cairo_error (status);
83 }
84
85 void
86 _cairo_font_face_init (cairo_font_face_t               *font_face,
87                        const cairo_font_face_backend_t *backend)
88 {
89     CAIRO_MUTEX_INITIALIZE ();
90
91     font_face->status = CAIRO_STATUS_SUCCESS;
92     CAIRO_REFERENCE_COUNT_INIT (&font_face->ref_count, 1);
93     font_face->backend = backend;
94
95     _cairo_user_data_array_init (&font_face->user_data);
96 }
97
98 /**
99  * cairo_font_face_reference:
100  * @font_face: a #cairo_font_face_t, (may be %NULL in which case this
101  * function does nothing).
102  *
103  * Increases the reference count on @font_face by one. This prevents
104  * @font_face from being destroyed until a matching call to
105  * cairo_font_face_destroy() is made.
106  *
107  * The number of references to a #cairo_font_face_t can be get using
108  * cairo_font_face_get_reference_count().
109  *
110  * Return value: the referenced #cairo_font_face_t.
111  *
112  * Since: 1.0
113  **/
114 cairo_font_face_t *
115 cairo_font_face_reference (cairo_font_face_t *font_face)
116 {
117     if (font_face == NULL ||
118             CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
119         return font_face;
120
121     /* We would normally assert that we have a reference here but we
122      * can't get away with that due to the zombie case as documented
123      * in _cairo_ft_font_face_destroy. */
124
125     _cairo_reference_count_inc (&font_face->ref_count);
126
127     return font_face;
128 }
129 slim_hidden_def (cairo_font_face_reference);
130
131 /**
132  * cairo_font_face_destroy:
133  * @font_face: a #cairo_font_face_t
134  *
135  * Decreases the reference count on @font_face by one. If the result
136  * is zero, then @font_face and all associated resources are freed.
137  * See cairo_font_face_reference().
138  *
139  * Since: 1.0
140  **/
141 void
142 cairo_font_face_destroy (cairo_font_face_t *font_face)
143 {
144     if (font_face == NULL ||
145             CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
146         return;
147
148     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->ref_count));
149
150     if (! _cairo_reference_count_dec_and_test (&font_face->ref_count))
151         return;
152
153     if (font_face->backend->destroy)
154         font_face->backend->destroy (font_face);
155
156     /* We allow resurrection to deal with some memory management for the
157      * FreeType backend where cairo_ft_font_face_t and cairo_ft_unscaled_font_t
158      * need to effectively mutually reference each other
159      */
160     if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->ref_count))
161         return;
162
163     _cairo_user_data_array_fini (&font_face->user_data);
164
165     free (font_face);
166 }
167 slim_hidden_def (cairo_font_face_destroy);
168
169 /**
170  * cairo_font_face_get_type:
171  * @font_face: a font face
172  *
173  * This function returns the type of the backend used to create
174  * a font face. See #cairo_font_type_t for available types.
175  *
176  * Return value: The type of @font_face.
177  *
178  * Since: 1.2
179  **/
180 cairo_font_type_t
181 cairo_font_face_get_type (cairo_font_face_t *font_face)
182 {
183     if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
184         return CAIRO_FONT_TYPE_TOY;
185
186     return font_face->backend->type;
187 }
188
189 /**
190  * cairo_font_face_get_reference_count:
191  * @font_face: a #cairo_font_face_t
192  *
193  * Returns the current reference count of @font_face.
194  *
195  * Return value: the current reference count of @font_face.  If the
196  * object is a nil object, 0 will be returned.
197  *
198  * Since: 1.4
199  **/
200 unsigned int
201 cairo_font_face_get_reference_count (cairo_font_face_t *font_face)
202 {
203     if (font_face == NULL ||
204             CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
205         return 0;
206
207     return CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->ref_count);
208 }
209
210 /**
211  * cairo_font_face_status:
212  * @font_face: a #cairo_font_face_t
213  *
214  * Checks whether an error has previously occurred for this
215  * font face
216  *
217  * Return value: %CAIRO_STATUS_SUCCESS or another error such as
218  *   %CAIRO_STATUS_NO_MEMORY.
219  *
220  * Since: 1.0
221  **/
222 cairo_status_t
223 cairo_font_face_status (cairo_font_face_t *font_face)
224 {
225     return font_face->status;
226 }
227
228 /**
229  * cairo_font_face_get_user_data:
230  * @font_face: a #cairo_font_face_t
231  * @key: the address of the #cairo_user_data_key_t the user data was
232  * attached to
233  *
234  * Return user data previously attached to @font_face using the specified
235  * key.  If no user data has been attached with the given key this
236  * function returns %NULL.
237  *
238  * Return value: the user data previously attached or %NULL.
239  *
240  * Since: 1.0
241  **/
242 void *
243 cairo_font_face_get_user_data (cairo_font_face_t           *font_face,
244                                const cairo_user_data_key_t *key)
245 {
246     return _cairo_user_data_array_get_data (&font_face->user_data,
247                                             key);
248 }
249 slim_hidden_def (cairo_font_face_get_user_data);
250
251 /**
252  * cairo_font_face_set_user_data:
253  * @font_face: a #cairo_font_face_t
254  * @key: the address of a #cairo_user_data_key_t to attach the user data to
255  * @user_data: the user data to attach to the font face
256  * @destroy: a #cairo_destroy_func_t which will be called when the
257  * font face is destroyed or when new user data is attached using the
258  * same key.
259  *
260  * Attach user data to @font_face.  To remove user data from a font face,
261  * call this function with the key that was used to set it and %NULL
262  * for @data.
263  *
264  * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
265  * slot could not be allocated for the user data.
266  *
267  * Since: 1.0
268  **/
269 cairo_status_t
270 cairo_font_face_set_user_data (cairo_font_face_t           *font_face,
271                                const cairo_user_data_key_t *key,
272                                void                        *user_data,
273                                cairo_destroy_func_t         destroy)
274 {
275     if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
276         return font_face->status;
277
278     return _cairo_user_data_array_set_data (&font_face->user_data,
279                                             key, user_data, destroy);
280 }
281 slim_hidden_def (cairo_font_face_set_user_data);
282
283 void
284 _cairo_unscaled_font_init (cairo_unscaled_font_t               *unscaled_font,
285                            const cairo_unscaled_font_backend_t *backend)
286 {
287     CAIRO_REFERENCE_COUNT_INIT (&unscaled_font->ref_count, 1);
288     unscaled_font->backend = backend;
289 }
290
291 cairo_unscaled_font_t *
292 _cairo_unscaled_font_reference (cairo_unscaled_font_t *unscaled_font)
293 {
294     if (unscaled_font == NULL)
295         return NULL;
296
297     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled_font->ref_count));
298
299     _cairo_reference_count_inc (&unscaled_font->ref_count);
300
301     return unscaled_font;
302 }
303
304 void
305 _cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
306 {
307     if (unscaled_font == NULL)
308         return;
309
310     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled_font->ref_count));
311
312     if (! _cairo_reference_count_dec_and_test (&unscaled_font->ref_count))
313         return;
314
315     unscaled_font->backend->destroy (unscaled_font);
316
317     free (unscaled_font);
318 }