comparison libass/ass_fontconfig.c @ 18937:9e95ac641e77

Initial libass release (without mencoder support).
author eugeni
date Fri, 07 Jul 2006 18:26:51 +0000
parents
children 31b7033c573e
comparison
equal deleted inserted replaced
18936:b80b0c115a24 18937:9e95ac641e77
1 #include "config.h"
2
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <assert.h>
6 #include <string.h>
7 #include <sys/types.h>
8 #include <sys/stat.h>
9
10 #include "mp_msg.h"
11 #include "ass_fontconfig.h"
12
13 #ifdef HAVE_FONTCONFIG
14 #include <fontconfig/fontconfig.h>
15 #endif
16
17 struct fc_instance_s {
18 #ifdef HAVE_FONTCONFIG
19 FcConfig* config;
20 #endif
21 char* family_default;
22 char* path_default;
23 int index_default;
24 };
25
26 extern int no_more_font_messages;
27
28 #ifdef HAVE_FONTCONFIG
29 /**
30 * \brief Low-level font selection.
31 * \param priv private data
32 * \param family font family
33 * \param bold font weight value
34 * \param italic font slant value
35 * \param index out: font index inside a file
36 * \return font file path
37 */
38 static char* _select_font(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index)
39 {
40 FcBool rc;
41 FcResult result;
42 FcPattern *pat, *rpat;
43 int val_i;
44 FcChar8* val_s;
45 char buf[2000];
46
47 *index = 0;
48
49 snprintf(buf, 2000, "%s:outline=True:slant=%u:weight=%u", family, italic, bold);
50
51 pat = FcNameParse((const FcChar8*)buf);
52 if (!pat)
53 return 0;
54
55 FcDefaultSubstitute(pat);
56
57 rc = FcConfigSubstitute(priv->config, pat, FcMatchPattern);
58 if (!rc)
59 return 0;
60
61 rpat = FcFontMatch(priv->config, pat, &result);
62 if (!rpat)
63 return 0;
64
65 result = FcPatternGetInteger(rpat, FC_INDEX, 0, &val_i);
66 if (result != FcResultMatch)
67 return 0;
68 *index = val_i;
69
70 result = FcPatternGetString(rpat, FC_FAMILY, 0, &val_s);
71 if (result != FcResultMatch)
72 return 0;
73
74 if (strcasecmp((const char*)val_s, family) != 0)
75 mp_msg(MSGT_GLOBAL, MSGL_WARN, "fontconfig: selected font family is not the requested one: '%s' != '%s'\n",
76 (const char*)val_s, family);
77
78 result = FcPatternGetString(rpat, FC_FILE, 0, &val_s);
79 if (result != FcResultMatch)
80 return 0;
81
82 return strdup((const char*)val_s);
83 }
84
85 /**
86 * \brief Find a font. Use default family or path if necessary.
87 * \param priv_ private data
88 * \param family font family
89 * \param bold font weight value
90 * \param italic font slant value
91 * \param index out: font index inside a file
92 * \return font file path
93 */
94 char* fontconfig_select(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index)
95 {
96 char* res = 0;
97 if (family && *family)
98 res = _select_font(priv, family, bold, italic, index);
99 if (!res && priv->family_default) {
100 res = _select_font(priv, priv->family_default, bold, italic, index);
101 if (res && !no_more_font_messages)
102 mp_msg(MSGT_GLOBAL, MSGL_WARN, "fontconfig_select: using default font family: (%s, %d, %d) -> %s, %d\n",
103 family, bold, italic, res, *index);
104 }
105 if (!res && priv->path_default) {
106 res = priv->path_default;
107 *index = priv->index_default;
108 if (!no_more_font_messages)
109 mp_msg(MSGT_GLOBAL, MSGL_WARN, "fontconfig_select: using default font: (%s, %d, %d) -> %s, %d\n",
110 family, bold, italic, res, *index);
111 }
112 if (!res) {
113 res = _select_font(priv, "Arial", bold, italic, index);
114 if (res && !no_more_font_messages)
115 mp_msg(MSGT_GLOBAL, MSGL_WARN, "fontconfig_select: using 'Arial' font family: (%s, %d, %d) -> %s, %d\n",
116 family, bold, italic, res, *index);
117 }
118 if (res)
119 mp_msg(MSGT_GLOBAL, MSGL_V, "fontconfig_select: (%s, %d, %d) -> %s, %d\n",
120 family, bold, italic, res, *index);
121 return res;
122 }
123
124 /**
125 * \brief Init fontconfig.
126 * \param dir additional directoryu for fonts
127 * \param family default font family
128 * \param path default font path
129 * \return pointer to fontconfig private data
130 */
131 fc_instance_t* fontconfig_init(const char* dir, const char* family, const char* path)
132 {
133 int rc;
134 struct stat st;
135 fc_instance_t* priv = calloc(1, sizeof(fc_instance_t));
136
137 rc = FcInit();
138 assert(rc);
139
140 priv->config = FcConfigGetCurrent();
141 if (!priv->config) {
142 mp_msg(MSGT_GLOBAL, MSGL_FATAL, "FcInitLoadConfigAndFonts failed\n");
143 return 0;
144 }
145
146 rc = FcConfigAppFontAddDir(priv->config, (const FcChar8*)dir);
147 if (!rc) {
148 mp_msg(MSGT_GLOBAL, MSGL_WARN, "FcConfigAppFontAddDir failed\n");
149 }
150
151 priv->family_default = family ? strdup(family) : 0;
152 priv->index_default = 0;
153
154 rc = stat(path, &st);
155 if (!rc && S_ISREG(st.st_mode))
156 priv->path_default = path ? strdup(path) : 0;
157 else
158 priv->path_default = 0;
159
160 return priv;
161 }
162
163 #else
164
165 char* fontconfig_select(fc_instance_t* priv, const char* family, unsigned bold, unsigned italic, int* index)
166 {
167 *index = priv->index_default;
168 return priv->path_default;
169 }
170
171 fc_instance_t* fontconfig_init(const char* dir, const char* family, const char* path)
172 {
173 mp_msg(MSGT_GLOBAL, MSGL_WARN, "Fontconfig disabled, only default font will be used\n");
174
175 fc_instance_t* priv = calloc(1, sizeof(fc_instance_t));
176
177 priv->path_default = strdup(path);
178 priv->index_default = 0;
179 return priv;
180 }
181
182 #endif
183
184 void fontconfig_done(fc_instance_t* priv)
185 {
186 // don't call FcFini() here, library can still be used by some code
187 if (priv && priv->path_default) free(priv->path_default);
188 if (priv && priv->family_default) free(priv->family_default);
189 if (priv) free(priv);
190 }
191
192