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
{
82
    if (status == CAIRO_STATUS_SUCCESS)
83
	return status;
84

            
85
    /* Don't overwrite an existing error. This preserves the first
86
     * error, which is the most significant. */
87
    _cairo_status_set_error (&font_face->status, status);
88

            
89
    return _cairo_error (status);
90
}
91

            
92
void
93
4060
_cairo_font_face_init (cairo_font_face_t               *font_face,
94
		       const cairo_font_face_backend_t *backend)
95
{
96
    CAIRO_MUTEX_INITIALIZE ();
97

            
98
4060
    font_face->status = CAIRO_STATUS_SUCCESS;
99
4060
    CAIRO_REFERENCE_COUNT_INIT (&font_face->ref_count, 1);
100
4060
    font_face->backend = backend;
101

            
102
4060
    _cairo_user_data_array_init (&font_face->user_data);
103
4060
}
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
275634
cairo_font_face_reference (cairo_font_face_t *font_face)
123
{
124
275634
    if (font_face == NULL ||
125
517136
	CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
126
17066
	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
258568
    _cairo_reference_count_inc (&font_face->ref_count);
133

            
134
258568
    return font_face;
135
}
136

            
137
static inline cairo_bool_t
138
371030
__put(cairo_reference_count_t *v)
139
{
140
    int c, old;
141

            
142
371030
    c = CAIRO_REFERENCE_COUNT_GET_VALUE(v);
143
738924
    while (c != 1 && (old = _cairo_atomic_int_cmpxchg_return_old(&v->ref_count, c, c - 1)) != c)
144
2
	c = old;
145

            
146
371030
    return c != 1;
147
}
148

            
149
cairo_bool_t
150
_cairo_font_face_destroy (void *abstract_face)
151
{
152
#if 0 /* Nothing needs to be done, we can just drop the last reference */
153
    cairo_font_face_t *font_face = abstract_face;
154
    return _cairo_reference_count_dec_and_test (&font_face->ref_count);
155
#endif
156
    return TRUE;
157
}
158

            
159
/**
160
 * cairo_font_face_destroy:
161
 * @font_face: a #cairo_font_face_t
162
 *
163
 * Decreases the reference count on @font_face by one. If the result
164
 * is zero, then @font_face and all associated resources are freed.
165
 * See cairo_font_face_reference().
166
 *
167
 * Since: 1.0
168
 **/
169
void
170
313548
cairo_font_face_destroy (cairo_font_face_t *font_face)
171
{
172
313548
    if (font_face == NULL ||
173
519998
	CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
174
53553
	return;
175

            
176
519990
    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&font_face->ref_count));
177

            
178
    /* We allow resurrection to deal with some memory management for the
179
     * FreeType backend where cairo_ft_font_face_t and cairo_ft_unscaled_font_t
180
     * need to effectively mutually reference each other
181
     */
182
259995
    if (__put (&font_face->ref_count))
183
256861
	return;
184

            
185
3134
    if (! font_face->backend->destroy (font_face))
186
	return;
187

            
188
3134
    _cairo_user_data_array_fini (&font_face->user_data);
189

            
190
3134
    free (font_face);
191
}
192

            
193
/**
194
 * cairo_font_face_get_type:
195
 * @font_face: a font face
196
 *
197
 * This function returns the type of the backend used to create
198
 * a font face. See #cairo_font_type_t for available types.
199
 *
200
 * Return value: The type of @font_face.
201
 *
202
 * Since: 1.2
203
 **/
204
cairo_font_type_t
205
14
cairo_font_face_get_type (cairo_font_face_t *font_face)
206
{
207
28
    if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
208
4
	return CAIRO_FONT_TYPE_TOY;
209

            
210
10
    return font_face->backend->type;
211
}
212

            
213
/**
214
 * cairo_font_face_get_reference_count:
215
 * @font_face: a #cairo_font_face_t
216
 *
217
 * Returns the current reference count of @font_face.
218
 *
219
 * Return value: the current reference count of @font_face.  If the
220
 * object is a nil object, 0 will be returned.
221
 *
222
 * Since: 1.4
223
 **/
224
unsigned int
225
cairo_font_face_get_reference_count (cairo_font_face_t *font_face)
226
{
227
    if (font_face == NULL ||
228
	CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
229
	return 0;
230

            
231
    return CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->ref_count);
232
}
233

            
234
/**
235
 * cairo_font_face_status:
236
 * @font_face: a #cairo_font_face_t
237
 *
238
 * Checks whether an error has previously occurred for this
239
 * font face
240
 *
241
 * Return value: %CAIRO_STATUS_SUCCESS or another error such as
242
 *   %CAIRO_STATUS_NO_MEMORY.
243
 *
244
 * Since: 1.0
245
 **/
246
cairo_status_t
247
41
cairo_font_face_status (cairo_font_face_t *font_face)
248
{
249
41
    return font_face->status;
250
}
251

            
252
/**
253
 * cairo_font_face_get_user_data:
254
 * @font_face: a #cairo_font_face_t
255
 * @key: the address of the #cairo_user_data_key_t the user data was
256
 * attached to
257
 *
258
 * Return user data previously attached to @font_face using the specified
259
 * key.  If no user data has been attached with the given key this
260
 * function returns %NULL.
261
 *
262
 * Return value: the user data previously attached or %NULL.
263
 *
264
 * Since: 1.0
265
 **/
266
void *
267
615
cairo_font_face_get_user_data (cairo_font_face_t	   *font_face,
268
			       const cairo_user_data_key_t *key)
269
{
270
615
    return _cairo_user_data_array_get_data (&font_face->user_data,
271
					    key);
272
}
273

            
274
/**
275
 * cairo_font_face_set_user_data:
276
 * @font_face: a #cairo_font_face_t
277
 * @key: the address of a #cairo_user_data_key_t to attach the user data to
278
 * @user_data: the user data to attach to the font face
279
 * @destroy: a #cairo_destroy_func_t which will be called when the
280
 * font face is destroyed or when new user data is attached using the
281
 * same key.
282
 *
283
 * Attach user data to @font_face.  To remove user data from a font face,
284
 * call this function with the key that was used to set it and %NULL
285
 * for @data.
286
 *
287
 * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
288
 * slot could not be allocated for the user data.
289
 *
290
 * Since: 1.0
291
 **/
292
cairo_status_t
293
72
cairo_font_face_set_user_data (cairo_font_face_t	   *font_face,
294
			       const cairo_user_data_key_t *key,
295
			       void			   *user_data,
296
			       cairo_destroy_func_t	    destroy)
297
{
298
144
    if (CAIRO_REFERENCE_COUNT_IS_INVALID (&font_face->ref_count))
299
	return font_face->status;
300

            
301
72
    return _cairo_user_data_array_set_data (&font_face->user_data,
302
					    key, user_data, destroy);
303
}
304

            
305
void
306
320
_cairo_unscaled_font_init (cairo_unscaled_font_t               *unscaled_font,
307
			   const cairo_unscaled_font_backend_t *backend)
308
{
309
320
    CAIRO_REFERENCE_COUNT_INIT (&unscaled_font->ref_count, 1);
310
320
    unscaled_font->backend = backend;
311
320
}
312

            
313
cairo_unscaled_font_t *
314
111991
_cairo_unscaled_font_reference (cairo_unscaled_font_t *unscaled_font)
315
{
316
111991
    if (unscaled_font == NULL)
317
	return NULL;
318

            
319
223982
    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled_font->ref_count));
320

            
321
111991
    _cairo_reference_count_inc (&unscaled_font->ref_count);
322

            
323
111991
    return unscaled_font;
324
}
325

            
326
void
327
111035
_cairo_unscaled_font_destroy (cairo_unscaled_font_t *unscaled_font)
328
{
329
111035
    if (unscaled_font == NULL)
330
	return;
331

            
332
222070
    assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled_font->ref_count));
333

            
334
111035
    if (__put (&unscaled_font->ref_count))
335
111029
	return;
336

            
337
6
    if (! unscaled_font->backend->destroy (unscaled_font))
338
	return;
339

            
340
6
    free (unscaled_font);
341
}