2 * $XFree86: xc/lib/fontconfig/src/fcfreetype.c,v 1.5 2002/06/29 20:31:02 keithp Exp $
4 * Copyright © 2001 Keith Packard, member of The XFree86 Project, Inc.
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 Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD 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.
29 #include <freetype/freetype.h>
30 #include <freetype/internal/ftobjs.h>
31 #include <freetype/tttables.h>
33 static const FcChar8 *fcLangLatin1[] = {
34 (FcChar8 *) "br", /* Breton */
35 (FcChar8 *) "ca", /* Catalan */
36 (FcChar8 *) "da", /* Danish */
37 (FcChar8 *) "de", /* German */
38 (FcChar8 *) "en", /* English */
39 (FcChar8 *) "es", /* Spanish */
40 (FcChar8 *) "eu", /* Basque */
41 (FcChar8 *) "fi", /* Finnish */
42 (FcChar8 *) "fo", /* Faroese */
43 (FcChar8 *) "fr", /* French */
44 (FcChar8 *) "ga", /* Irish */
45 (FcChar8 *) "gd", /* Scottish */
46 (FcChar8 *) "gl", /* Galician */
47 (FcChar8 *) "is", /* Islandic */
48 (FcChar8 *) "it", /* Italian */
49 (FcChar8 *) "kl", /* Greenlandic */
50 (FcChar8 *) "la", /* Latin */
51 (FcChar8 *) "nl", /* Dutch */
52 (FcChar8 *) "no", /* Norwegian */
53 (FcChar8 *) "pt", /* Portuguese */
54 (FcChar8 *) "rm", /* Rhaeto-Romanic */
55 (FcChar8 *) "sq", /* Albanian */
56 (FcChar8 *) "sv", /* Swedish */
60 static const FcChar8 *fcLangLatin2[] = {
61 (FcChar8 *) "cs", /* Czech */
62 (FcChar8 *) "de", /* German */
63 (FcChar8 *) "en", /* English */
64 (FcChar8 *) "fi", /* Finnish */
65 (FcChar8 *) "hr", /* Croatian */
66 (FcChar8 *) "hu", /* Hungarian */
67 (FcChar8 *) "la", /* Latin */
68 (FcChar8 *) "pl", /* Polish */
69 (FcChar8 *) "ro", /* Romanian */
70 (FcChar8 *) "sk", /* Slovak */
71 (FcChar8 *) "sl", /* Slovenian */
72 (FcChar8 *) "sq", /* Albanian */
76 static const FcChar8 *fcLangCyrillic[] = {
77 (FcChar8 *) "az", /* Azerbaijani */
78 (FcChar8 *) "ba", /* Bashkir */
79 (FcChar8 *) "bg", /* Bulgarian */
80 (FcChar8 *) "be", /* Byelorussian */
81 (FcChar8 *) "kk", /* Kazakh */
82 (FcChar8 *) "ky", /* Kirghiz */
83 (FcChar8 *) "mk", /* Macedonian */
84 (FcChar8 *) "mo", /* Moldavian */
85 (FcChar8 *) "mn", /* Mongolian */
86 (FcChar8 *) "ru", /* Russian */
87 (FcChar8 *) "sr", /* Serbian */
88 (FcChar8 *) "tg", /* Tadzhik */
89 (FcChar8 *) "tt", /* Tatar */
90 (FcChar8 *) "tk", /* Turkmen */
91 (FcChar8 *) "uz", /* Uzbek */
92 (FcChar8 *) "uk", /* Ukrainian */
96 static const FcChar8 *fcLangGreek[] = {
97 (FcChar8 *) "el", /* Greek */
101 static const FcChar8 *fcLangTurkish[] = {
102 (FcChar8 *) "tr", /* Turkish */
106 static const FcChar8 *fcLangHebrew[] = {
107 (FcChar8 *) "he", /* Hebrew */
108 (FcChar8 *) "yi", /* Yiddish */
112 static const FcChar8 *fcLangArabic[] = {
113 (FcChar8 *) "ar", /* arabic */
117 static const FcChar8 *fcLangWindowsBaltic[] = {
118 (FcChar8 *) "da", /* Danish */
119 (FcChar8 *) "de", /* German */
120 (FcChar8 *) "en", /* English */
121 (FcChar8 *) "et", /* Estonian */
122 (FcChar8 *) "fi", /* Finnish */
123 (FcChar8 *) "la", /* Latin */
124 (FcChar8 *) "lt", /* Lithuanian */
125 (FcChar8 *) "lv", /* Latvian */
126 (FcChar8 *) "no", /* Norwegian */
127 (FcChar8 *) "pl", /* Polish */
128 (FcChar8 *) "sl", /* Slovenian */
129 (FcChar8 *) "sv", /* Swedish */
133 static const FcChar8 *fcLangVietnamese[] = {
134 (FcChar8 *) "vi", /* Vietnamese */
138 static const FcChar8 *fcLangThai[] = {
139 (FcChar8 *) "th", /* Thai */
143 static const FcChar8 *fcLangJapanese[] = {
144 (FcChar8 *) "ja", /* Japanese */
148 static const FcChar8 *fcLangSimplifiedChinese[] = {
149 (FcChar8 *) "zh-cn", /* Chinese-China */
153 static const FcChar8 *fcLangKorean[] = {
154 (FcChar8 *) "ko", /* Korean */
158 static const FcChar8 *fcLangTraditionalChinese[] = {
159 (FcChar8 *) "zh-tw", /* Chinese-Taiwan */
163 static const FcChar8 *fcLangEnglish[] = {
164 (FcChar8 *) "en", /* English */
169 * Elide some of the less useful bits
171 static const struct {
173 const FcChar8 **lang;
174 } FcCodePageRange[] = {
177 { 2, fcLangCyrillic },
179 { 4, fcLangTurkish },
182 { 7, fcLangWindowsBaltic },
183 { 8, fcLangVietnamese },
184 /* 9-15 reserved for Alternate ANSI */
186 { 17, fcLangJapanese },
187 { 18, fcLangSimplifiedChinese },
188 { 19, fcLangKorean },
189 { 20, fcLangTraditionalChinese },
190 { 21, fcLangKorean },
191 /* 22-28 reserved for Alternate ANSI & OEM */
192 /* { 29, fcLangMacintosh }, */
193 /* { 30, fcLangOem }, */
194 /* { 31, fcLangSymbol },*/
195 /* 32-47 reserved for OEM */
197 { 49, fcLangCyrillic },
198 /* { 50, fcLangMsdosNordic }, */
199 { 51, fcLangArabic },
200 /* { 52, fcLangMSDOS_CANADIAN_FRENCH }, */
201 { 53, fcLangHebrew },
202 /* { 54, fcLangMSDOS_ICELANDIC }, */
203 /* { 55, fcLangMSDOS_PORTUGUESE }, */
204 { 56, fcLangTurkish },
205 { 57, fcLangCyrillic },
206 { 58, fcLangLatin2 },
207 { 59, fcLangWindowsBaltic },
209 { 61, fcLangArabic },
210 { 62, fcLangLatin1 },
211 { 63, fcLangEnglish },
214 #define NUM_CODE_PAGE_RANGE (sizeof FcCodePageRange / sizeof FcCodePageRange[0])
217 FcFreeTypeHasLang (FcPattern *pattern, const FcChar8 *lang)
222 for (i = 0; FcPatternGetString (pattern, FC_LANG, i, &old) == FcResultMatch; i++)
223 if (!FcStrCmp (lang, old))
229 FcFreeTypeQuery (const FcChar8 *file,
240 FT_Library ftLibrary;
241 const FcChar8 *family;
245 FcBool hasLang = FcFalse;
248 if (FT_Init_FreeType (&ftLibrary))
251 if (FT_New_Face (ftLibrary, (char *) file, id, &face))
254 *count = face->num_faces;
256 pat = FcPatternCreate ();
260 if (!FcPatternAddBool (pat, FC_OUTLINE,
261 (face->face_flags & FT_FACE_FLAG_SCALABLE) != 0))
264 if (!FcPatternAddBool (pat, FC_SCALABLE,
265 (face->face_flags & FT_FACE_FLAG_SCALABLE) != 0))
269 slant = FC_SLANT_ROMAN;
270 if (face->style_flags & FT_STYLE_FLAG_ITALIC)
271 slant = FC_SLANT_ITALIC;
273 if (!FcPatternAddInteger (pat, FC_SLANT, slant))
276 weight = FC_WEIGHT_MEDIUM;
277 if (face->style_flags & FT_STYLE_FLAG_BOLD)
278 weight = FC_WEIGHT_BOLD;
280 if (!FcPatternAddInteger (pat, FC_WEIGHT, weight))
283 family = (FcChar8 *) face->family_name;
286 family = (FcChar8 *) strrchr ((char *) file, '/');
292 if (!FcPatternAddString (pat, FC_FAMILY, family))
295 if (face->style_name)
297 if (!FcPatternAddString (pat, FC_STYLE, (FcChar8 *) face->style_name))
301 if (!FcPatternAddString (pat, FC_FILE, file))
304 if (!FcPatternAddInteger (pat, FC_INDEX, id))
307 if (!FcPatternAddString (pat, FC_SOURCE, (FcChar8 *) "FreeType"))
311 if ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0)
312 if (!FcPatternAddInteger (pat, FC_SPACING, FC_MONO))
317 * Get the OS/2 table and poke about
319 os2 = (TT_OS2 *) FT_Get_Sfnt_Table (face, ft_sfnt_os2);
320 if (os2 && os2->version >= 0x0001 && os2->version != 0xffff)
322 for (i = 0; i < NUM_CODE_PAGE_RANGE; i++)
326 if (FcCodePageRange[i].bit < 32)
328 bits = os2->ulCodePageRange1;
329 bit = FcCodePageRange[i].bit;
333 bits = os2->ulCodePageRange2;
334 bit = FcCodePageRange[i].bit - 32;
336 if (bits & (1 << bit))
341 for (j = 0; (lang = FcCodePageRange[i].lang[j]); j++)
342 if (!FcFreeTypeHasLang (pat, lang))
344 if (!FcPatternAddString (pat, FC_LANG, lang))
353 * Compute the unicode coverage for the font
355 cs = FcFreeTypeCharSet (face, blanks);
359 codepoints = FcCharSetCount (cs);
361 * Skip over PCF fonts that have no encoded characters; they're
362 * usually just Unicode fonts transcoded to some legacy encoding
366 if (!strcmp(FT_MODULE_CLASS(&face->driver->root)->module_name, "pcf"))
370 if (!FcPatternAddCharSet (pat, FC_CHARSET, cs))
375 if (!FcFreeTypeSetLang (pat, cs))
379 * Make sure it has a lang entry
381 if (FcPatternGetString (pat, FC_LANG, 0, &lang) != FcResultMatch)
382 if (!FcPatternAddString (pat, FC_LANG, (FcChar8 *) "x-unknown"))
387 * Drop our reference to the charset
389 FcCharSetDestroy (cs);
391 if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
393 for (i = 0; i < face->num_fixed_sizes; i++)
394 if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE,
395 (double) face->available_sizes[i].height))
397 if (!FcPatternAddBool (pat, FC_ANTIALIAS, FcFalse))
402 FT_Done_FreeType (ftLibrary);
406 FcCharSetDestroy (cs);
408 FcPatternDestroy (pat);
412 FT_Done_FreeType (ftLibrary);