Line data Source code
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 : * cairo_<emphasis>backend</emphasis>_font_face_create(), or implicitly
56 : * 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 0 : _cairo_font_face_set_error (cairo_font_face_t *font_face,
73 : cairo_status_t status)
74 : {
75 0 : if (status == CAIRO_STATUS_SUCCESS)
76 0 : return status;
77 :
78 : /* Don't overwrite an existing error. This preserves the first
79 : * error, which is the most significant. */
80 0 : _cairo_status_set_error (&font_face->status, status);
81 :
82 0 : return _cairo_error (status);
83 : }
84 :
85 : void
86 6 : _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 6 : font_face->status = CAIRO_STATUS_SUCCESS;
92 6 : CAIRO_REFERENCE_COUNT_INIT (&font_face->ref_count, 1);
93 6 : font_face->backend = backend;
94 :
95 6 : _cairo_user_data_array_init (&font_face->user_data);
96 6 : }
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 : cairo_font_face_t *
113 28 : cairo_font_face_reference (cairo_font_face_t *font_face)
114 : {
115 56 : if (font_face == NULL ||
116 56 : CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
117 0 : return font_face;
118 :
119 : /* We would normally assert that we have a reference here but we
120 : * can't get away with that due to the zombie case as documented
121 : * in _cairo_ft_font_face_destroy. */
122 :
123 28 : _cairo_reference_count_inc (&font_face->ref_count);
124 :
125 28 : return font_face;
126 : }
127 : slim_hidden_def (cairo_font_face_reference);
128 :
129 : /**
130 : * cairo_font_face_destroy:
131 : * @font_face: a #cairo_font_face_t
132 : *
133 : * Decreases the reference count on @font_face by one. If the result
134 : * is zero, then @font_face and all associated resources are freed.
135 : * See cairo_font_face_reference().
136 : **/
137 : void
138 10 : cairo_font_face_destroy (cairo_font_face_t *font_face)
139 : {
140 18 : if (font_face == NULL ||
141 16 : CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
142 2 : return;
143 :
144 16 : assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->ref_count));
145 :
146 8 : if (! _cairo_reference_count_dec_and_test (&font_face->ref_count))
147 8 : return;
148 :
149 0 : if (font_face->backend->destroy)
150 0 : font_face->backend->destroy (font_face);
151 :
152 : /* We allow resurrection to deal with some memory management for the
153 : * FreeType backend where cairo_ft_font_face_t and cairo_ft_unscaled_font_t
154 : * need to effectively mutually reference each other
155 : */
156 0 : if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->ref_count))
157 0 : return;
158 :
159 0 : _cairo_user_data_array_fini (&font_face->user_data);
160 :
161 0 : free (font_face);
162 : }
163 : slim_hidden_def (cairo_font_face_destroy);
164 :
165 : /**
166 : * cairo_font_face_get_type:
167 : * @font_face: a font face
168 : *
169 : * This function returns the type of the backend used to create
170 : * a font face. See #cairo_font_type_t for available types.
171 : *
172 : * Return value: The type of @font_face.
173 : *
174 : * Since: 1.2
175 : **/
176 : cairo_font_type_t
177 2 : cairo_font_face_get_type (cairo_font_face_t *font_face)
178 : {
179 4 : if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
180 0 : return CAIRO_FONT_TYPE_TOY;
181 :
182 2 : return font_face->backend->type;
183 : }
184 :
185 : /**
186 : * cairo_font_face_get_reference_count:
187 : * @font_face: a #cairo_font_face_t
188 : *
189 : * Returns the current reference count of @font_face.
190 : *
191 : * Return value: the current reference count of @font_face. If the
192 : * object is a nil object, 0 will be returned.
193 : *
194 : * Since: 1.4
195 : **/
196 : unsigned int
197 0 : cairo_font_face_get_reference_count (cairo_font_face_t *font_face)
198 : {
199 0 : if (font_face == NULL ||
200 0 : CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
201 0 : return 0;
202 :
203 0 : return CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->ref_count);
204 : }
205 :
206 : /**
207 : * cairo_font_face_status:
208 : * @font_face: a #cairo_font_face_t
209 : *
210 : * Checks whether an error has previously occurred for this
211 : * font face
212 : *
213 : * Return value: %CAIRO_STATUS_SUCCESS or another error such as
214 : * %CAIRO_STATUS_NO_MEMORY.
215 : **/
216 : cairo_status_t
217 306 : cairo_font_face_status (cairo_font_face_t *font_face)
218 : {
219 306 : return font_face->status;
220 : }
221 :
222 : /**
223 : * cairo_font_face_get_user_data:
224 : * @font_face: a #cairo_font_face_t
225 : * @key: the address of the #cairo_user_data_key_t the user data was
226 : * attached to
227 : *
228 : * Return user data previously attached to @font_face using the specified
229 : * key. If no user data has been attached with the given key this
230 : * function returns %NULL.
231 : *
232 : * Return value: the user data previously attached or %NULL.
233 : **/
234 : void *
235 306 : cairo_font_face_get_user_data (cairo_font_face_t *font_face,
236 : const cairo_user_data_key_t *key)
237 : {
238 306 : return _cairo_user_data_array_get_data (&font_face->user_data,
239 : key);
240 : }
241 : slim_hidden_def (cairo_font_face_get_user_data);
242 :
243 : /**
244 : * cairo_font_face_set_user_data:
245 : * @font_face: a #cairo_font_face_t
246 : * @key: the address of a #cairo_user_data_key_t to attach the user data to
247 : * @user_data: the user data to attach to the font face
248 : * @destroy: a #cairo_destroy_func_t which will be called when the
249 : * font face is destroyed or when new user data is attached using the
250 : * same key.
251 : *
252 : * Attach user data to @font_face. To remove user data from a font face,
253 : * call this function with the key that was used to set it and %NULL
254 : * for @data.
255 : *
256 : * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
257 : * slot could not be allocated for the user data.
258 : **/
259 : cairo_status_t
260 5 : cairo_font_face_set_user_data (cairo_font_face_t *font_face,
261 : const cairo_user_data_key_t *key,
262 : void *user_data,
263 : cairo_destroy_func_t destroy)
264 : {
265 10 : if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
266 0 : return font_face->status;
267 :
268 5 : return _cairo_user_data_array_set_data (&font_face->user_data,
269 : key, user_data, destroy);
270 : }
271 : slim_hidden_def (cairo_font_face_set_user_data);
272 :
273 : void
274 6 : _cairo_unscaled_font_init (cairo_unscaled_font_t *unscaled_font,
275 : const cairo_unscaled_font_backend_t *backend)
276 : {
277 6 : CAIRO_REFERENCE_COUNT_INIT (&unscaled_font->ref_count, 1);
278 6 : unscaled_font->backend = backend;
279 6 : }
280 :
281 : cairo_unscaled_font_t *
282 19 : _cairo_unscaled_font_reference (cairo_unscaled_font_t *unscaled_font)
283 : {
284 19 : if (unscaled_font == NULL)
285 0 : return NULL;
286 :
287 38 : assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled_font->ref_count));
288 :
289 19 : _cairo_reference_count_inc (&unscaled_font->ref_count);
290 :
291 19 : return unscaled_font;
292 : }
293 :
294 : void
295 8 : _cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
296 : {
297 8 : if (unscaled_font == NULL)
298 0 : return;
299 :
300 16 : assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled_font->ref_count));
301 :
302 8 : if (! _cairo_reference_count_dec_and_test (&unscaled_font->ref_count))
303 8 : return;
304 :
305 0 : unscaled_font->backend->destroy (unscaled_font);
306 :
307 0 : free (unscaled_font);
308 : }
|