Mercurial > mplayer.hg
annotate libass/ass_fontconfig.c @ 36560:67e2b2a5ce42
tcp: fix socket/descriptor leak on error.
author | reimar |
---|---|
date | Sun, 19 Jan 2014 22:24:53 +0000 |
parents | c3aaaf17c721 |
children |
rev | line source |
---|---|
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19902
diff
changeset
|
1 /* |
26723 | 2 * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> |
3 * | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
4 * This file is part of libass. |
26723 | 5 * |
34011 | 6 * Permission to use, copy, modify, and distribute this software for any |
7 * purpose with or without fee is hereby granted, provided that the above | |
8 * copyright notice and this permission notice appear in all copies. | |
26723 | 9 * |
34011 | 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | |
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | |
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | |
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | |
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | |
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
26723 | 17 */ |
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19902
diff
changeset
|
18 |
18937 | 19 #include "config.h" |
20 | |
21 #include <stdlib.h> | |
22 #include <stdio.h> | |
23 #include <assert.h> | |
24 #include <string.h> | |
31875 | 25 #include <strings.h> |
18937 | 26 #include <sys/types.h> |
27 #include <sys/stat.h> | |
22292 | 28 #include <inttypes.h> |
29 #include <ft2build.h> | |
30 #include FT_FREETYPE_H | |
18937 | 31 |
30200 | 32 #include "ass_utils.h" |
21458
7af6c25a0cfc
Keep embedded fonts in ass_library_t and perform actual disk write
eugeni
parents:
21351
diff
changeset
|
33 #include "ass.h" |
7af6c25a0cfc
Keep embedded fonts in ass_library_t and perform actual disk write
eugeni
parents:
21351
diff
changeset
|
34 #include "ass_library.h" |
18937 | 35 #include "ass_fontconfig.h" |
36 | |
27393 | 37 #ifdef CONFIG_FONTCONFIG |
18937 | 38 #include <fontconfig/fontconfig.h> |
21460 | 39 #include <fontconfig/fcfreetype.h> |
18937 | 40 #endif |
41 | |
30200 | 42 struct fc_instance { |
27393 | 43 #ifdef CONFIG_FONTCONFIG |
30200 | 44 FcConfig *config; |
18937 | 45 #endif |
30200 | 46 char *family_default; |
47 char *path_default; | |
48 int index_default; | |
18937 | 49 }; |
50 | |
27393 | 51 #ifdef CONFIG_FONTCONFIG |
26660
ab5729095d68
Define FC_FULLNAME and FC_EMBOLDEN to fix compilation with ancient fontconfig.
eugeni
parents:
26659
diff
changeset
|
52 |
18937 | 53 /** |
31853 | 54 * \brief Case-insensitive match ASS/SSA font family against full name. (also |
55 * known as "name for humans") | |
56 * | |
57 * \param lib library instance | |
58 * \param priv fontconfig instance | |
59 * \param family font fullname | |
60 * \param bold weight attribute | |
61 * \param italic italic attribute | |
62 * \return font set | |
63 */ | |
64 static FcFontSet * | |
65 match_fullname(ASS_Library *lib, FCInstance *priv, const char *family, | |
66 unsigned bold, unsigned italic) | |
67 { | |
68 FcFontSet *sets[2]; | |
69 FcFontSet *result = FcFontSetCreate(); | |
70 int nsets = 0; | |
71 int i, fi; | |
72 | |
73 if ((sets[nsets] = FcConfigGetFonts(priv->config, FcSetSystem))) | |
74 nsets++; | |
75 if ((sets[nsets] = FcConfigGetFonts(priv->config, FcSetApplication))) | |
76 nsets++; | |
77 | |
78 // Run over font sets and patterns and try to match against full name | |
79 for (i = 0; i < nsets; i++) { | |
80 FcFontSet *set = sets[i]; | |
81 for (fi = 0; fi < set->nfont; fi++) { | |
82 FcPattern *pat = set->fonts[fi]; | |
83 char *fullname; | |
84 int pi = 0, at; | |
85 FcBool ol; | |
86 while (FcPatternGetString(pat, FC_FULLNAME, pi++, | |
87 (FcChar8 **) &fullname) == FcResultMatch) { | |
88 if (FcPatternGetBool(pat, FC_OUTLINE, 0, &ol) != FcResultMatch | |
89 || ol != FcTrue) | |
90 continue; | |
91 if (FcPatternGetInteger(pat, FC_SLANT, 0, &at) != FcResultMatch | |
92 || at < italic) | |
93 continue; | |
94 if (FcPatternGetInteger(pat, FC_WEIGHT, 0, &at) != FcResultMatch | |
95 || at < bold) | |
96 continue; | |
97 if (strcasecmp(fullname, family) == 0) { | |
98 FcFontSetAdd(result, FcPatternDuplicate(pat)); | |
99 break; | |
100 } | |
101 } | |
102 } | |
103 } | |
104 | |
105 return result; | |
106 } | |
107 | |
108 /** | |
18937 | 109 * \brief Low-level font selection. |
110 * \param priv private data | |
111 * \param family font family | |
28860
7fcc0bf5b27a
Treat -font/-subfont as Fontconfig pattern in libass.
eugeni
parents:
27842
diff
changeset
|
112 * \param treat_family_as_pattern treat family as fontconfig pattern |
18937 | 113 * \param bold font weight value |
114 * \param italic font slant value | |
115 * \param index out: font index inside a file | |
23980 | 116 * \param code: the character that should be present in the font, can be 0 |
18937 | 117 * \return font file path |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28942
diff
changeset
|
118 */ |
31853 | 119 static char *select_font(ASS_Library *library, FCInstance *priv, |
30200 | 120 const char *family, int treat_family_as_pattern, |
121 unsigned bold, unsigned italic, int *index, | |
122 uint32_t code) | |
18937 | 123 { |
30200 | 124 FcBool rc; |
125 FcResult result; | |
126 FcPattern *pat = NULL, *rpat = NULL; | |
127 int r_index, r_slant, r_weight; | |
128 FcChar8 *r_family, *r_style, *r_file, *r_fullname; | |
129 FcBool r_outline, r_embolden; | |
130 FcCharSet *r_charset; | |
31853 | 131 FcFontSet *ffullname = NULL, *fsorted = NULL, *fset = NULL; |
30200 | 132 int curf; |
133 char *retval = NULL; | |
134 int family_cnt = 0; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28942
diff
changeset
|
135 |
30200 | 136 *index = 0; |
18937 | 137 |
30200 | 138 if (treat_family_as_pattern) |
139 pat = FcNameParse((const FcChar8 *) family); | |
140 else | |
141 pat = FcPatternCreate(); | |
28860
7fcc0bf5b27a
Treat -font/-subfont as Fontconfig pattern in libass.
eugeni
parents:
27842
diff
changeset
|
142 |
30200 | 143 if (!pat) |
144 goto error; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28942
diff
changeset
|
145 |
30200 | 146 if (!treat_family_as_pattern) { |
147 FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *) family); | |
26591 | 148 |
30200 | 149 // In SSA/ASS fonts are sometimes referenced by their "full name", |
150 // which is usually a concatenation of family name and font | |
151 // style (ex. Ottawa Bold). Full name is available from | |
152 // FontConfig pattern element FC_FULLNAME, but it is never | |
153 // used for font matching. | |
154 // Therefore, I'm removing words from the end of the name one | |
155 // by one, and adding shortened names to the pattern. It seems | |
156 // that the first value (full name in this case) has | |
157 // precedence in matching. | |
158 // An alternative approach could be to reimplement FcFontSort | |
159 // using FC_FULLNAME instead of FC_FAMILY. | |
160 family_cnt = 1; | |
161 { | |
162 char *s = strdup(family); | |
163 char *p = s + strlen(s); | |
164 while (--p > s) | |
165 if (*p == ' ' || *p == '-') { | |
166 *p = '\0'; | |
167 FcPatternAddString(pat, FC_FAMILY, (const FcChar8 *) s); | |
168 ++family_cnt; | |
169 } | |
170 free(s); | |
171 } | |
172 } | |
173 FcPatternAddBool(pat, FC_OUTLINE, FcTrue); | |
174 FcPatternAddInteger(pat, FC_SLANT, italic); | |
175 FcPatternAddInteger(pat, FC_WEIGHT, bold); | |
19063
5525af2ee4c7
Use FcPatternAdd-Type instead of FcNameParse. The latter, as it turns out, requires escaping of some characters ('-', maybe more).
eugeni
parents:
19001
diff
changeset
|
176 |
30200 | 177 FcDefaultSubstitute(pat); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28942
diff
changeset
|
178 |
30200 | 179 rc = FcConfigSubstitute(priv->config, pat, FcMatchPattern); |
180 if (!rc) | |
181 goto error; | |
36363 | 182 /* Fontconfig defaults include a language setting, which it sets based on |
183 * some environment variables or defaults to "en". Unset this as we don't | |
184 * know the real language, and because some some attached fonts lack | |
185 * non-ascii characters included in fontconfig's list of characters | |
186 * required for English support and therefore don't match the lang=en | |
187 * criterion. | |
188 */ | |
189 FcPatternDel(pat, "lang"); | |
21351
c611dfc4cb85
If a glyph is not found in the current font, switch to another one.
eugeni
parents:
21279
diff
changeset
|
190 |
31853 | 191 fsorted = FcFontSort(priv->config, pat, FcTrue, NULL, &result); |
192 ffullname = match_fullname(library, priv, family, bold, italic); | |
193 if (!fsorted || !ffullname) | |
30200 | 194 goto error; |
21351
c611dfc4cb85
If a glyph is not found in the current font, switch to another one.
eugeni
parents:
21279
diff
changeset
|
195 |
31853 | 196 fset = FcFontSetCreate(); |
197 for (curf = 0; curf < ffullname->nfont; ++curf) { | |
198 FcPattern *curp = ffullname->fonts[curf]; | |
199 FcPatternReference(curp); | |
200 FcFontSetAdd(fset, curp); | |
201 } | |
202 for (curf = 0; curf < fsorted->nfont; ++curf) { | |
203 FcPattern *curp = fsorted->fonts[curf]; | |
204 FcPatternReference(curp); | |
205 FcFontSetAdd(fset, curp); | |
206 } | |
207 | |
30200 | 208 for (curf = 0; curf < fset->nfont; ++curf) { |
209 FcPattern *curp = fset->fonts[curf]; | |
26658
1e1ebebc8f5b
Remove extra family names from the search pattern after FcFontSort and
eugeni
parents:
26620
diff
changeset
|
210 |
30200 | 211 result = FcPatternGetBool(curp, FC_OUTLINE, 0, &r_outline); |
212 if (result != FcResultMatch) | |
213 continue; | |
214 if (r_outline != FcTrue) | |
215 continue; | |
216 if (!code) | |
217 break; | |
218 result = FcPatternGetCharSet(curp, FC_CHARSET, 0, &r_charset); | |
219 if (result != FcResultMatch) | |
220 continue; | |
221 if (FcCharSetHasChar(r_charset, code)) | |
222 break; | |
223 } | |
21351
c611dfc4cb85
If a glyph is not found in the current font, switch to another one.
eugeni
parents:
21279
diff
changeset
|
224 |
30200 | 225 if (curf >= fset->nfont) |
226 goto error; | |
21351
c611dfc4cb85
If a glyph is not found in the current font, switch to another one.
eugeni
parents:
21279
diff
changeset
|
227 |
30200 | 228 if (!treat_family_as_pattern) { |
229 // Remove all extra family names from original pattern. | |
230 // After this, FcFontRenderPrepare will select the most relevant family | |
231 // name in case there are more than one of them. | |
232 for (; family_cnt > 1; --family_cnt) | |
233 FcPatternRemove(pat, FC_FAMILY, family_cnt - 1); | |
234 } | |
235 | |
236 rpat = FcFontRenderPrepare(priv->config, pat, fset->fonts[curf]); | |
237 if (!rpat) | |
238 goto error; | |
26658
1e1ebebc8f5b
Remove extra family names from the search pattern after FcFontSort and
eugeni
parents:
26620
diff
changeset
|
239 |
30200 | 240 result = FcPatternGetInteger(rpat, FC_INDEX, 0, &r_index); |
241 if (result != FcResultMatch) | |
242 goto error; | |
243 *index = r_index; | |
26658
1e1ebebc8f5b
Remove extra family names from the search pattern after FcFontSort and
eugeni
parents:
26620
diff
changeset
|
244 |
30200 | 245 result = FcPatternGetString(rpat, FC_FILE, 0, &r_file); |
246 if (result != FcResultMatch) | |
247 goto error; | |
248 retval = strdup((const char *) r_file); | |
18937 | 249 |
30200 | 250 result = FcPatternGetString(rpat, FC_FAMILY, 0, &r_family); |
251 if (result != FcResultMatch) | |
252 r_family = NULL; | |
26614 | 253 |
30200 | 254 result = FcPatternGetString(rpat, FC_FULLNAME, 0, &r_fullname); |
255 if (result != FcResultMatch) | |
256 r_fullname = NULL; | |
18937 | 257 |
30200 | 258 if (!treat_family_as_pattern && |
259 !(r_family && strcasecmp((const char *) r_family, family) == 0) && | |
260 !(r_fullname && strcasecmp((const char *) r_fullname, family) == 0)) | |
261 ass_msg(library, MSGL_WARN, | |
262 "fontconfig: Selected font is not the requested one: " | |
263 "'%s' != '%s'", | |
264 (const char *) (r_fullname ? r_fullname : r_family), family); | |
26616 | 265 |
30200 | 266 result = FcPatternGetString(rpat, FC_STYLE, 0, &r_style); |
267 if (result != FcResultMatch) | |
268 r_style = NULL; | |
269 | |
270 result = FcPatternGetInteger(rpat, FC_SLANT, 0, &r_slant); | |
271 if (result != FcResultMatch) | |
272 r_slant = 0; | |
26616 | 273 |
30200 | 274 result = FcPatternGetInteger(rpat, FC_WEIGHT, 0, &r_weight); |
275 if (result != FcResultMatch) | |
276 r_weight = 0; | |
26616 | 277 |
30200 | 278 result = FcPatternGetBool(rpat, FC_EMBOLDEN, 0, &r_embolden); |
279 if (result != FcResultMatch) | |
280 r_embolden = 0; | |
26616 | 281 |
30200 | 282 ass_msg(library, MSGL_V, |
283 "Font info: family '%s', style '%s', fullname '%s'," | |
284 " slant %d, weight %d%s", (const char *) r_family, | |
285 (const char *) r_style, (const char *) r_fullname, r_slant, | |
286 r_weight, r_embolden ? ", embolden" : ""); | |
26616 | 287 |
30200 | 288 error: |
289 if (pat) | |
290 FcPatternDestroy(pat); | |
291 if (rpat) | |
292 FcPatternDestroy(rpat); | |
31853 | 293 if (fsorted) |
294 FcFontSetDestroy(fsorted); | |
295 if (ffullname) | |
296 FcFontSetDestroy(ffullname); | |
30200 | 297 if (fset) |
298 FcFontSetDestroy(fset); | |
299 return retval; | |
18937 | 300 } |
301 | |
302 /** | |
303 * \brief Find a font. Use default family or path if necessary. | |
304 * \param priv_ private data | |
305 * \param family font family | |
28860
7fcc0bf5b27a
Treat -font/-subfont as Fontconfig pattern in libass.
eugeni
parents:
27842
diff
changeset
|
306 * \param treat_family_as_pattern treat family as fontconfig pattern |
18937 | 307 * \param bold font weight value |
308 * \param italic font slant value | |
309 * \param index out: font index inside a file | |
23980 | 310 * \param code: the character that should be present in the font, can be 0 |
18937 | 311 * \return font file path |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28942
diff
changeset
|
312 */ |
30200 | 313 char *fontconfig_select(ASS_Library *library, FCInstance *priv, |
314 const char *family, int treat_family_as_pattern, | |
315 unsigned bold, unsigned italic, int *index, | |
316 uint32_t code) | |
18937 | 317 { |
30200 | 318 char *res = 0; |
319 if (!priv->config) { | |
320 *index = priv->index_default; | |
321 res = priv->path_default ? strdup(priv->path_default) : 0; | |
322 return res; | |
323 } | |
324 if (family && *family) | |
325 res = | |
31853 | 326 select_font(library, priv, family, treat_family_as_pattern, |
30200 | 327 bold, italic, index, code); |
328 if (!res && priv->family_default) { | |
329 res = | |
31853 | 330 select_font(library, priv, priv->family_default, 0, bold, |
30200 | 331 italic, index, code); |
332 if (res) | |
333 ass_msg(library, MSGL_WARN, "fontconfig_select: Using default " | |
334 "font family: (%s, %d, %d) -> %s, %d", | |
335 family, bold, italic, res, *index); | |
336 } | |
337 if (!res && priv->path_default) { | |
338 res = strdup(priv->path_default); | |
339 *index = priv->index_default; | |
340 ass_msg(library, MSGL_WARN, "fontconfig_select: Using default font: " | |
341 "(%s, %d, %d) -> %s, %d", family, bold, italic, | |
342 res, *index); | |
343 } | |
344 if (!res) { | |
31853 | 345 res = select_font(library, priv, "Arial", 0, bold, italic, |
30200 | 346 index, code); |
347 if (res) | |
348 ass_msg(library, MSGL_WARN, "fontconfig_select: Using 'Arial' " | |
349 "font family: (%s, %d, %d) -> %s, %d", family, bold, | |
350 italic, res, *index); | |
351 } | |
352 if (res) | |
353 ass_msg(library, MSGL_V, | |
354 "fontconfig_select: (%s, %d, %d) -> %s, %d", family, bold, | |
355 italic, res, *index); | |
356 return res; | |
18937 | 357 } |
358 | |
21458
7af6c25a0cfc
Keep embedded fonts in ass_library_t and perform actual disk write
eugeni
parents:
21351
diff
changeset
|
359 /** |
21630 | 360 * \brief Process memory font. |
361 * \param priv private data | |
362 * \param library library object | |
363 * \param ftlibrary freetype library object | |
364 * \param idx index of the processed font in library->fontdata | |
31853 | 365 * |
366 * Builds a font pattern in memory via FT_New_Memory_Face/FcFreeTypeQueryFace. | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28942
diff
changeset
|
367 */ |
30200 | 368 static void process_fontdata(FCInstance *priv, ASS_Library *library, |
369 FT_Library ftlibrary, int idx) | |
21458
7af6c25a0cfc
Keep embedded fonts in ass_library_t and perform actual disk write
eugeni
parents:
21351
diff
changeset
|
370 { |
30200 | 371 int rc; |
372 const char *name = library->fontdata[idx].name; | |
373 const char *data = library->fontdata[idx].data; | |
374 int data_size = library->fontdata[idx].size; | |
23216
b863ed752149
Move variables and a function under #ifdef FC_VERSION to avoid warnings.
eugeni
parents:
23215
diff
changeset
|
375 |
30200 | 376 FT_Face face; |
377 FcPattern *pattern; | |
378 FcFontSet *fset; | |
379 FcBool res; | |
380 int face_index, num_faces = 1; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28942
diff
changeset
|
381 |
30200 | 382 for (face_index = 0; face_index < num_faces; ++face_index) { |
383 rc = FT_New_Memory_Face(ftlibrary, (unsigned char *) data, | |
384 data_size, face_index, &face); | |
385 if (rc) { | |
386 ass_msg(library, MSGL_WARN, "Error opening memory font: %s", | |
387 name); | |
388 return; | |
389 } | |
390 num_faces = face->num_faces; | |
21458
7af6c25a0cfc
Keep embedded fonts in ass_library_t and perform actual disk write
eugeni
parents:
21351
diff
changeset
|
391 |
30200 | 392 pattern = |
31853 | 393 FcFreeTypeQueryFace(face, (unsigned char *) name, face_index, |
30200 | 394 FcConfigGetBlanks(priv->config)); |
395 if (!pattern) { | |
396 ass_msg(library, MSGL_WARN, "%s failed", "FcFreeTypeQueryFace"); | |
397 FT_Done_Face(face); | |
398 return; | |
399 } | |
21460 | 400 |
30200 | 401 fset = FcConfigGetFonts(priv->config, FcSetSystem); // somehow it failes when asked for FcSetApplication |
402 if (!fset) { | |
403 ass_msg(library, MSGL_WARN, "%s failed", "FcConfigGetFonts"); | |
404 FT_Done_Face(face); | |
405 return; | |
406 } | |
21460 | 407 |
30200 | 408 res = FcFontSetAdd(fset, pattern); |
409 if (!res) { | |
410 ass_msg(library, MSGL_WARN, "%s failed", "FcFontSetAdd"); | |
411 FT_Done_Face(face); | |
412 return; | |
413 } | |
21460 | 414 |
30200 | 415 FT_Done_Face(face); |
416 } | |
21458
7af6c25a0cfc
Keep embedded fonts in ass_library_t and perform actual disk write
eugeni
parents:
21351
diff
changeset
|
417 } |
7af6c25a0cfc
Keep embedded fonts in ass_library_t and perform actual disk write
eugeni
parents:
21351
diff
changeset
|
418 |
18937 | 419 /** |
420 * \brief Init fontconfig. | |
21630 | 421 * \param library libass library object |
422 * \param ftlibrary freetype library object | |
18937 | 423 * \param family default font family |
424 * \param path default font path | |
30200 | 425 * \param fc whether fontconfig should be used |
426 * \param config path to a fontconfig configuration file, or NULL | |
427 * \param update whether the fontconfig cache should be built/updated | |
18937 | 428 * \return pointer to fontconfig private data |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28942
diff
changeset
|
429 */ |
30200 | 430 FCInstance *fontconfig_init(ASS_Library *library, |
431 FT_Library ftlibrary, const char *family, | |
432 const char *path, int fc, const char *config, | |
433 int update) | |
18937 | 434 { |
30200 | 435 int rc; |
436 FCInstance *priv = calloc(1, sizeof(FCInstance)); | |
437 const char *dir = library->fonts_dir; | |
438 int i; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28942
diff
changeset
|
439 |
30200 | 440 if (!fc) { |
441 ass_msg(library, MSGL_WARN, | |
442 "Fontconfig disabled, only default font will be used."); | |
443 goto exit; | |
444 } | |
21458
7af6c25a0cfc
Keep embedded fonts in ass_library_t and perform actual disk write
eugeni
parents:
21351
diff
changeset
|
445 |
30200 | 446 priv->config = FcConfigCreate(); |
447 rc = FcConfigParseAndLoad(priv->config, (unsigned char *) config, FcTrue); | |
448 if (!rc) { | |
449 ass_msg(library, MSGL_WARN, "No usable fontconfig configuration " | |
450 "file found, using fallback."); | |
451 FcConfigDestroy(priv->config); | |
452 priv->config = FcInitLoadConfig(); | |
453 rc++; | |
454 } | |
455 if (rc && update) { | |
456 FcConfigBuildFonts(priv->config); | |
457 } | |
27095 | 458 |
30200 | 459 if (!rc || !priv->config) { |
460 ass_msg(library, MSGL_FATAL, | |
461 "No valid fontconfig configuration found!"); | |
462 FcConfigDestroy(priv->config); | |
463 goto exit; | |
464 } | |
465 | |
466 for (i = 0; i < library->num_fontdata; ++i) | |
467 process_fontdata(priv, library, ftlibrary, i); | |
468 | |
469 if (dir) { | |
31853 | 470 ass_msg(library, MSGL_V, "Updating font cache"); |
27095 | 471 |
30200 | 472 rc = FcConfigAppFontAddDir(priv->config, (const FcChar8 *) dir); |
473 if (!rc) { | |
474 ass_msg(library, MSGL_WARN, "%s failed", "FcConfigAppFontAddDir"); | |
475 } | |
476 } | |
19340 | 477 |
30200 | 478 priv->family_default = family ? strdup(family) : NULL; |
479 exit: | |
480 priv->path_default = path ? strdup(path) : NULL; | |
481 priv->index_default = 0; | |
19340 | 482 |
30200 | 483 return priv; |
18937 | 484 } |
485 | |
30200 | 486 int fontconfig_update(FCInstance *priv) |
487 { | |
488 return FcConfigBuildFonts(priv->config); | |
489 } | |
490 | |
491 #else /* CONFIG_FONTCONFIG */ | |
18937 | 492 |
30200 | 493 char *fontconfig_select(ASS_Library *library, FCInstance *priv, |
494 const char *family, int treat_family_as_pattern, | |
495 unsigned bold, unsigned italic, int *index, | |
496 uint32_t code) | |
18937 | 497 { |
30200 | 498 *index = priv->index_default; |
499 char* res = priv->path_default ? strdup(priv->path_default) : 0; | |
500 return res; | |
18937 | 501 } |
502 | |
30200 | 503 FCInstance *fontconfig_init(ASS_Library *library, |
504 FT_Library ftlibrary, const char *family, | |
505 const char *path, int fc, const char *config, | |
506 int update) | |
18937 | 507 { |
30200 | 508 FCInstance *priv; |
19481 | 509 |
30200 | 510 ass_msg(library, MSGL_WARN, |
511 "Fontconfig disabled, only default font will be used."); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28942
diff
changeset
|
512 |
30200 | 513 priv = calloc(1, sizeof(FCInstance)); |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28942
diff
changeset
|
514 |
30200 | 515 priv->path_default = path ? strdup(path) : 0; |
516 priv->index_default = 0; | |
517 return priv; | |
518 } | |
519 | |
520 int fontconfig_update(FCInstance *priv) | |
521 { | |
522 // Do nothing | |
523 return 1; | |
18937 | 524 } |
525 | |
526 #endif | |
527 | |
30200 | 528 void fontconfig_done(FCInstance *priv) |
18937 | 529 { |
31875 | 530 |
531 if (priv) { | |
30200 | 532 #ifdef CONFIG_FONTCONFIG |
34011 | 533 if (priv->config) |
534 FcConfigDestroy(priv->config); | |
30200 | 535 #endif |
536 free(priv->path_default); | |
537 free(priv->family_default); | |
31875 | 538 } |
539 free(priv); | |
18937 | 540 } |