Coverage Report

Created: 2026-11-10 07:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fontconfig/src/fcinit.c
Line
Count
Source
1
/*
2
 * fontconfig/src/fcinit.c
3
 *
4
 * Copyright © 2001 Keith Packard
5
 *
6
 * Permission to use, copy, modify, distribute, and sell this software and its
7
 * documentation for any purpose is hereby granted without fee, provided that
8
 * the above copyright notice appear in all copies and that both that
9
 * copyright notice and this permission notice appear in supporting
10
 * documentation, and that the name of the author(s) not be used in
11
 * advertising or publicity pertaining to distribution of the software without
12
 * specific, written prior permission.  The authors make no
13
 * representations about the suitability of this software for any purpose.  It
14
 * is provided "as is" without express or implied warranty.
15
 *
16
 * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18
 * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22
 * PERFORMANCE OF THIS SOFTWARE.
23
 */
24
25
#include "fcint.h"
26
27
#include <stdlib.h>
28
29
#if defined(FC_ATOMIC_INT_NIL)
30
#  pragma message("Could not find any system to define atomic_int macros, library may NOT be thread-safe.")
31
#endif
32
#if defined(FC_MUTEX_IMPL_NIL)
33
#  pragma message("Could not find any system to define mutex macros, library may NOT be thread-safe.")
34
#endif
35
#if defined(FC_ATOMIC_INT_NIL) || defined(FC_MUTEX_IMPL_NIL)
36
#  pragma message("To suppress these warnings, define FC_NO_MT.")
37
#endif
38
39
static FcConfig *
40
FcInitFallbackConfig (const FcChar8 *sysroot)
41
11
{
42
11
    FcConfig      *config;
43
11
    const FcChar8 *fallback = (const FcChar8 *)
44
11
  ""
45
11
  "<fontconfig>" FC_DEFAULT_FONTS
46
11
  "  <dir prefix=\"xdg\">fonts</dir>"
47
11
  "  <cachedir>" FC_CACHEDIR
48
11
  "</cachedir>"
49
11
  "  <cachedir prefix=\"xdg\">fontconfig</cachedir>"
50
11
  "  <include ignore_missing=\"yes\">" CONFIGDIR
51
11
  "</include>"
52
11
  "  <include ignore_missing=\"yes\" prefix=\"xdg\">fontconfig/conf.d</include>"
53
11
  "  <include ignore_missing=\"yes\" prefix=\"xdg\">fontconfig/fonts.conf</include>"
54
11
  "</fontconfig>";
55
56
11
    config = FcConfigCreate();
57
11
    if (!config)
58
0
  goto bail0;
59
11
    FcConfigSetSysRoot (config, sysroot);
60
11
    if (!FcConfigParseAndLoadFromMemory (config, fallback, FcFalse))
61
0
  goto bail1;
62
63
11
    return config;
64
65
0
bail1:
66
0
    FcConfigDestroy (config);
67
0
bail0:
68
0
    return 0;
69
0
}
70
71
static FcConfig *
72
FcInitFallbackConfigWithFilter (FcConfig *config, const FcChar8 *sysroot)
73
11
{
74
11
    FcConfig *fallback = FcInitFallbackConfig (sysroot);
75
76
11
    if (!fallback) {
77
0
  FcConfigDestroy (config);
78
0
  return NULL;
79
0
    }
80
    /* Copy filter data */
81
11
    fallback->filter_func = config->filter_func;
82
11
    fallback->filter_data = config->filter_data;
83
11
    fallback->destroy_data_func = config->destroy_data_func;
84
11
    config->filter_func = NULL;
85
11
    config->filter_data = NULL;
86
11
    config->destroy_data_func = NULL;
87
    /* Rebuild fontset */
88
11
    FcConfigBuildFonts (fallback);
89
90
11
    FcConfigDestroy (config);
91
92
11
    return fallback;
93
11
}
94
95
int
96
FcGetVersion (void)
97
0
{
98
0
    return FC_VERSION;
99
0
}
100
101
/*
102
 * Load the configuration files
103
 */
104
FcConfig *
105
FcInitLoadOwnConfig (FcConfig *config)
106
11
{
107
11
    if (!config) {
108
11
  config = FcConfigCreate();
109
11
  if (!config)
110
0
      return NULL;
111
11
    }
112
113
11
    FcInitDebug();
114
115
11
    if (!FcConfigParseAndLoad (config, 0, FcTrue)) {
116
11
  const FcChar8 *sysroot = FcConfigGetSysRoot (config);
117
11
  FcConfig      *fallback = FcInitFallbackConfigWithFilter (config, sysroot);
118
119
11
  return fallback;
120
11
    }
121
0
    (void)FcConfigParseOnly (config, (const FcChar8 *)FC_TEMPLATEDIR, FcFalse);
122
123
0
    if (config->cacheDirs && config->cacheDirs->num == 0) {
124
0
  FcChar8 *prefix, *p;
125
0
  size_t   plen;
126
0
  FcBool   have_own = FcFalse;
127
0
  char    *env_file, *env_path;
128
129
0
  env_file = getenv ("FONTCONFIG_FILE");
130
0
  env_path = getenv ("FONTCONFIG_PATH");
131
0
  if ((env_file != NULL && env_file[0] != 0) ||
132
0
      (env_path != NULL && env_path[0] != 0))
133
0
      have_own = FcTrue;
134
135
0
  if (!have_own) {
136
0
      fprintf (stderr,
137
0
               "Fontconfig warning: no <cachedir> elements found. Check configuration.\n");
138
0
      fprintf (stderr,
139
0
               "Fontconfig warning: adding <cachedir>%s</cachedir>\n",
140
0
               FC_CACHEDIR);
141
0
  }
142
0
  prefix = FcConfigXdgCacheHome();
143
0
  if (!prefix)
144
0
      goto bail;
145
0
  plen = strlen ((const char *)prefix);
146
0
  p = realloc (prefix, plen + 12);
147
0
  if (!p)
148
0
      goto bail;
149
0
  prefix = p;
150
0
  memcpy (&prefix[plen], FC_DIR_SEPARATOR_S "fontconfig", 11);
151
0
  prefix[plen + 11] = 0;
152
0
  if (!have_own)
153
0
      fprintf (stderr,
154
0
               "Fontconfig warning: adding <cachedir prefix=\"xdg\">fontconfig</cachedir>\n");
155
156
0
  if (!FcConfigAddCacheDir (config, (FcChar8 *)FC_CACHEDIR) ||
157
0
      !FcConfigAddCacheDir (config, (FcChar8 *)prefix)) {
158
0
      FcConfig      *fallback;
159
0
      const FcChar8 *sysroot;
160
161
0
  bail:
162
0
      sysroot = FcConfigGetSysRoot (config);
163
0
      fprintf (stderr,
164
0
               "Fontconfig error: out of memory");
165
0
      if (prefix)
166
0
    FcStrFree (prefix);
167
0
      fallback = FcInitFallbackConfigWithFilter (config, sysroot);
168
169
0
      return fallback;
170
0
  }
171
0
  FcStrFree (prefix);
172
0
    }
173
174
0
    return config;
175
0
}
176
177
FcConfig *
178
FcInitLoadConfig (void)
179
0
{
180
0
    return FcInitLoadOwnConfig (NULL);
181
0
}
182
183
/*
184
 * Load the configuration files and scan for available fonts
185
 */
186
FcConfig *
187
FcInitLoadOwnConfigAndFonts (FcConfig *config)
188
11
{
189
11
    config = FcInitLoadOwnConfig (config);
190
11
    if (!config)
191
0
  return 0;
192
11
    if (!FcConfigBuildFonts (config)) {
193
0
  FcConfigDestroy (config);
194
0
  return 0;
195
0
    }
196
11
    return config;
197
11
}
198
199
#ifdef ENABLE_TEST_HOOKS
200
/* Counts how many times the default configuration has been fully built.
201
 * Test-only hook (see test-mt-fcinit) to assert that concurrent lazy
202
 * initialization builds the default config exactly once. Not compiled
203
 * into production builds. */
204
fc_atomic_int_t FcConfigInitCount;
205
#endif
206
207
FcConfig *
208
FcInitLoadConfigAndFonts (void)
209
11
{
210
#ifdef ENABLE_TEST_HOOKS
211
    fc_atomic_int_add (FcConfigInitCount, 1);
212
#endif
213
11
    return FcInitLoadOwnConfigAndFonts (NULL);
214
11
}
215
216
/*
217
 * Initialize the default library configuration
218
 */
219
FcBool
220
FcInit (void)
221
0
{
222
0
    return FcConfigInit();
223
0
}
224
225
/*
226
 * Free all library-allocated data structures.
227
 */
228
void
229
FcFini (void)
230
0
{
231
0
    FcConfigFini();
232
0
    FcCacheFini();
233
0
}
234
235
/*
236
 * Reread the configuration and available font lists
237
 */
238
FcBool
239
FcInitReinitialize (void)
240
0
{
241
0
    FcConfig *config, *old_config;
242
0
    FcBool    ret;
243
244
0
    old_config = FcConfigReference (NULL);
245
0
    if (!old_config)
246
0
  return FcFalse;
247
0
    config = FcInitReinitializeWith (old_config);
248
0
    FcConfigDestroy (old_config);
249
0
    if (!config)
250
0
  return FcFalse;
251
0
    ret = FcConfigSetCurrent (config);
252
    /* FcConfigSetCurrent() increases the refcount.
253
     * decrease it here to avoid the memory leak.
254
     */
255
0
    FcConfigDestroy (config);
256
257
0
    return ret;
258
0
}
259
260
FcConfig *
261
FcInitReinitializeWith (FcConfig *config)
262
0
{
263
0
    FcConfig      *ret;
264
0
    FcStrList     *l;
265
0
    const FcChar8 *s;
266
267
0
    ret = FcInitLoadOwnConfig (NULL);
268
0
    if (!ret)
269
0
  return NULL;
270
0
    if (!FcConfigBuildFonts (ret)) {
271
0
  FcConfigDestroy (ret);
272
0
  return NULL;
273
0
    }
274
    /* inherit application specific fonts only */
275
0
    l = FcStrListCreate (config->appFonts);
276
0
    if (!l) {
277
0
  FcConfigDestroy (ret);
278
0
  return NULL;
279
0
    }
280
0
    while ((s = FcStrListNext (l))) {
281
0
  if (FcFileIsFile (s)) {
282
0
      if (!FcConfigAppFontAddFile (ret, s)) {
283
0
    fprintf (stderr, "Fontconfig warning: failed to re-add an application font: %s\n",
284
0
             (const char *)s);
285
0
      }
286
0
  } else if (FcFileIsDir (s)) {
287
0
      if (!FcConfigAppFontAddDir (ret, s)) {
288
0
    FcStrListDone (l);
289
0
    FcConfigDestroy (ret);
290
0
    return NULL;
291
0
      }
292
0
  } else {
293
0
      fprintf (stderr, "Fontconfig warning: failed to re-add an application font: %s\n",
294
0
               (const char *)s);
295
0
  }
296
0
    }
297
0
    FcStrListDone (l);
298
299
0
    return ret;
300
0
}
301
302
FcBool
303
FcInitBringUptoDate (void)
304
253
{
305
253
    FcConfig *config = FcConfigReference (NULL);
306
253
    FcBool    ret = FcTrue;
307
253
    time_t    now;
308
309
253
    if (!config)
310
0
  return FcFalse;
311
    /*
312
     * rescanInterval == 0 disables automatic up to date
313
     */
314
253
    if (config->rescanInterval == 0)
315
0
  goto bail;
316
    /*
317
     * Check no more often than rescanInterval seconds
318
     */
319
253
    now = time (0);
320
253
    if (config->rescanTime + config->rescanInterval - now > 0)
321
252
  goto bail;
322
    /*
323
     * If up to date, don't reload configuration
324
     */
325
1
    if (FcConfigUptoDate (0))
326
1
  goto bail;
327
0
    ret = FcInitReinitialize();
328
253
bail:
329
253
    FcConfigDestroy (config);
330
331
253
    return ret;
332
0
}
333
334
#define __fcinit__
335
#include "fcaliastail.h"
336
#undef __fcinit__