/work/workdir/UnpackedTarball/cairo/src/cairo-font-face.c
Line | Count | Source (jump to first uncovered line) |
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 | | const cairo_font_face_t _cairo_font_face_nil_file_not_found = { |
71 | | { 0 }, /* hash_entry */ |
72 | | CAIRO_STATUS_FILE_NOT_FOUND, /* status */ |
73 | | CAIRO_REFERENCE_COUNT_INVALID, /* ref_count */ |
74 | | { 0, 0, 0, NULL }, /* user_data */ |
75 | | NULL |
76 | | }; |
77 | | |
78 | | cairo_status_t |
79 | | _cairo_font_face_set_error (cairo_font_face_t *font_face, |
80 | | cairo_status_t status) |
81 | 0 | { |
82 | 0 | if (status == CAIRO_STATUS_SUCCESS) |
83 | 0 | return status; |
84 | | |
85 | | /* Don't overwrite an existing error. This preserves the first |
86 | | * error, which is the most significant. */ |
87 | 0 | _cairo_status_set_error (&font_face->status, status); |
88 | | |
89 | 0 | return _cairo_error (status); |
90 | 0 | } |
91 | | |
92 | | void |
93 | | _cairo_font_face_init (cairo_font_face_t *font_face, |
94 | | const cairo_font_face_backend_t *backend) |
95 | 5 | { |
96 | 5 | CAIRO_MUTEX_INITIALIZE (); |
97 | | |
98 | 5 | font_face->status = CAIRO_STATUS_SUCCESS; |
99 | 5 | CAIRO_REFERENCE_COUNT_INIT (&font_face->ref_count, 1); |
100 | 5 | font_face->backend = backend; |
101 | | |
102 | 5 | _cairo_user_data_array_init (&font_face->user_data); |
103 | 5 | } |
104 | | |
105 | | /** |
106 | | * cairo_font_face_reference: |
107 | | * @font_face: a #cairo_font_face_t, (may be %NULL in which case this |
108 | | * function does nothing). |
109 | | * |
110 | | * Increases the reference count on @font_face by one. This prevents |
111 | | * @font_face from being destroyed until a matching call to |
112 | | * cairo_font_face_destroy() is made. |
113 | | * |
114 | | * Use cairo_font_face_get_reference_count() to get the number of |
115 | | * references to a #cairo_font_face_t. |
116 | | * |
117 | | * Return value: the referenced #cairo_font_face_t. |
118 | | * |
119 | | * Since: 1.0 |
120 | | **/ |
121 | | cairo_font_face_t * |
122 | | cairo_font_face_reference (cairo_font_face_t *font_face) |
123 | 44.0k | { |
124 | 44.0k | if (font_face == NULL || |
125 | 44.0k | CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count)) |
126 | 19.4k | return font_face; |
127 | | |
128 | | /* We would normally assert that we have a reference here but we |
129 | | * can't get away with that due to the zombie case as documented |
130 | | * in _cairo_ft_font_face_destroy. */ |
131 | | |
132 | 24.6k | _cairo_reference_count_inc (&font_face->ref_count); |
133 | | |
134 | 24.6k | return font_face; |
135 | 44.0k | } |
136 | | slim_hidden_def (cairo_font_face_reference); |
137 | | |
138 | | static inline cairo_bool_t |
139 | | __put(cairo_reference_count_t *v) |
140 | 25.0k | { |
141 | 25.0k | int c, old; |
142 | | |
143 | 25.0k | c = CAIRO_REFERENCE_COUNT_GET_VALUE(v); |
144 | 25.0k | while (c != 1 && (old = _cairo_atomic_int_cmpxchg_return_old(&v->ref_count, c, c - 1)) != c) |
145 | 0 | c = old; |
146 | | |
147 | 25.0k | return c != 1; |
148 | 25.0k | } |
149 | | |
150 | | cairo_bool_t |
151 | | _cairo_font_face_destroy (void *abstract_face) |
152 | 0 | { |
153 | | #if 0 /* Nothing needs to be done, we can just drop the last reference */ |
154 | | cairo_font_face_t *font_face = abstract_face; |
155 | | return _cairo_reference_count_dec_and_test (&font_face->ref_count); |
156 | | #endif |
157 | 0 | return TRUE; |
158 | 0 | } |
159 | | |
160 | | /** |
161 | | * cairo_font_face_destroy: |
162 | | * @font_face: a #cairo_font_face_t |
163 | | * |
164 | | * Decreases the reference count on @font_face by one. If the result |
165 | | * is zero, then @font_face and all associated resources are freed. |
166 | | * See cairo_font_face_reference(). |
167 | | * |
168 | | * Since: 1.0 |
169 | | **/ |
170 | | void |
171 | | cairo_font_face_destroy (cairo_font_face_t *font_face) |
172 | 8.18M | { |
173 | 8.18M | if (font_face == NULL || |
174 | 8.18M | CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count)) |
175 | 8.15M | return; |
176 | | |
177 | 24.2k | assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->ref_count)); |
178 | | |
179 | | /* We allow resurrection to deal with some memory management for the |
180 | | * FreeType backend where cairo_ft_font_face_t and cairo_ft_unscaled_font_t |
181 | | * need to effectively mutually reference each other |
182 | | */ |
183 | 24.2k | if (__put (&font_face->ref_count)) |
184 | 24.2k | return; |
185 | | |
186 | 0 | if (! font_face->backend->destroy (font_face)) |
187 | 0 | return; |
188 | | |
189 | 0 | _cairo_user_data_array_fini (&font_face->user_data); |
190 | |
|
191 | 0 | free (font_face); |
192 | 0 | } |
193 | | slim_hidden_def (cairo_font_face_destroy); |
194 | | |
195 | | /** |
196 | | * cairo_font_face_get_type: |
197 | | * @font_face: a font face |
198 | | * |
199 | | * This function returns the type of the backend used to create |
200 | | * a font face. See #cairo_font_type_t for available types. |
201 | | * |
202 | | * Return value: The type of @font_face. |
203 | | * |
204 | | * Since: 1.2 |
205 | | **/ |
206 | | cairo_font_type_t |
207 | | cairo_font_face_get_type (cairo_font_face_t *font_face) |
208 | 0 | { |
209 | 0 | if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count)) |
210 | 0 | return CAIRO_FONT_TYPE_TOY; |
211 | | |
212 | 0 | return font_face->backend->type; |
213 | 0 | } |
214 | | |
215 | | /** |
216 | | * cairo_font_face_get_reference_count: |
217 | | * @font_face: a #cairo_font_face_t |
218 | | * |
219 | | * Returns the current reference count of @font_face. |
220 | | * |
221 | | * Return value: the current reference count of @font_face. If the |
222 | | * object is a nil object, 0 will be returned. |
223 | | * |
224 | | * Since: 1.4 |
225 | | **/ |
226 | | unsigned int |
227 | | cairo_font_face_get_reference_count (cairo_font_face_t *font_face) |
228 | 0 | { |
229 | 0 | if (font_face == NULL || |
230 | 0 | CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count)) |
231 | 0 | return 0; |
232 | | |
233 | 0 | return CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->ref_count); |
234 | 0 | } |
235 | | |
236 | | /** |
237 | | * cairo_font_face_status: |
238 | | * @font_face: a #cairo_font_face_t |
239 | | * |
240 | | * Checks whether an error has previously occurred for this |
241 | | * font face |
242 | | * |
243 | | * Return value: %CAIRO_STATUS_SUCCESS or another error such as |
244 | | * %CAIRO_STATUS_NO_MEMORY. |
245 | | * |
246 | | * Since: 1.0 |
247 | | **/ |
248 | | cairo_status_t |
249 | | cairo_font_face_status (cairo_font_face_t *font_face) |
250 | 0 | { |
251 | 0 | return font_face->status; |
252 | 0 | } |
253 | | |
254 | | /** |
255 | | * cairo_font_face_get_user_data: |
256 | | * @font_face: a #cairo_font_face_t |
257 | | * @key: the address of the #cairo_user_data_key_t the user data was |
258 | | * attached to |
259 | | * |
260 | | * Return user data previously attached to @font_face using the specified |
261 | | * key. If no user data has been attached with the given key this |
262 | | * function returns %NULL. |
263 | | * |
264 | | * Return value: the user data previously attached or %NULL. |
265 | | * |
266 | | * Since: 1.0 |
267 | | **/ |
268 | | void * |
269 | | cairo_font_face_get_user_data (cairo_font_face_t *font_face, |
270 | | const cairo_user_data_key_t *key) |
271 | 0 | { |
272 | 0 | return _cairo_user_data_array_get_data (&font_face->user_data, |
273 | 0 | key); |
274 | 0 | } |
275 | | slim_hidden_def (cairo_font_face_get_user_data); |
276 | | |
277 | | /** |
278 | | * cairo_font_face_set_user_data: |
279 | | * @font_face: a #cairo_font_face_t |
280 | | * @key: the address of a #cairo_user_data_key_t to attach the user data to |
281 | | * @user_data: the user data to attach to the font face |
282 | | * @destroy: a #cairo_destroy_func_t which will be called when the |
283 | | * font face is destroyed or when new user data is attached using the |
284 | | * same key. |
285 | | * |
286 | | * Attach user data to @font_face. To remove user data from a font face, |
287 | | * call this function with the key that was used to set it and %NULL |
288 | | * for @data. |
289 | | * |
290 | | * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a |
291 | | * slot could not be allocated for the user data. |
292 | | * |
293 | | * Since: 1.0 |
294 | | **/ |
295 | | cairo_status_t |
296 | | cairo_font_face_set_user_data (cairo_font_face_t *font_face, |
297 | | const cairo_user_data_key_t *key, |
298 | | void *user_data, |
299 | | cairo_destroy_func_t destroy) |
300 | 0 | { |
301 | 0 | if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count)) |
302 | 0 | return font_face->status; |
303 | | |
304 | 0 | return _cairo_user_data_array_set_data (&font_face->user_data, |
305 | 0 | key, user_data, destroy); |
306 | 0 | } |
307 | | slim_hidden_def (cairo_font_face_set_user_data); |
308 | | |
309 | | void |
310 | | _cairo_unscaled_font_init (cairo_unscaled_font_t *unscaled_font, |
311 | | const cairo_unscaled_font_backend_t *backend) |
312 | 5 | { |
313 | 5 | CAIRO_REFERENCE_COUNT_INIT (&unscaled_font->ref_count, 1); |
314 | 5 | unscaled_font->backend = backend; |
315 | 5 | } |
316 | | |
317 | | cairo_unscaled_font_t * |
318 | | _cairo_unscaled_font_reference (cairo_unscaled_font_t *unscaled_font) |
319 | 996 | { |
320 | 996 | if (unscaled_font == NULL) |
321 | 0 | return NULL; |
322 | | |
323 | 996 | assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled_font->ref_count)); |
324 | | |
325 | 996 | _cairo_reference_count_inc (&unscaled_font->ref_count); |
326 | | |
327 | 996 | return unscaled_font; |
328 | 996 | } |
329 | | |
330 | | void |
331 | | _cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font) |
332 | 802 | { |
333 | 802 | if (unscaled_font == NULL) |
334 | 0 | return; |
335 | | |
336 | 802 | assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled_font->ref_count)); |
337 | | |
338 | 802 | if (__put (&unscaled_font->ref_count)) |
339 | 802 | return; |
340 | | |
341 | 0 | if (! unscaled_font->backend->destroy (unscaled_font)) |
342 | 0 | return; |
343 | | |
344 | 0 | free (unscaled_font); |
345 | 0 | } |