Coverage Report

Created: 2025-07-07 10:01

/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
}