2 * fontconfig/src/fcfreetype.c
4 * Copyright © 2001 Keith Packard
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.
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.
26 Copyright © 2002-2003 by Juliusz Chroboczek
28 Permission is hereby granted, free of charge, to any person obtaining a copy
29 of this software and associated documentation files (the "Software"), to deal
30 in the Software without restriction, including without limitation the rights
31 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
32 copies of the Software, and to permit persons to whom the Software is
33 furnished to do so, subject to the following conditions:
35 The above copyright notice and this permission notice shall be included in
36 all copies or substantial portions of the Software.
38 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
41 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
53 #include FT_FREETYPE_H
54 #include FT_ADVANCES_H
55 #include FT_TRUETYPE_TABLES_H
56 #include FT_SFNT_NAMES_H
57 #include FT_TRUETYPE_IDS_H
58 #include FT_TYPE1_TABLES_H
59 #if HAVE_FT_GET_X11_FONT_FORMAT
62 #if HAVE_FT_GET_BDF_PROPERTY
66 #include FT_MULTIPLE_MASTERS_H
71 * Keep Han languages separated by eliminating languages
72 * that the codePageRange bits says aren't supported
77 const FcChar8 lang[6];
78 } FcCodePageRange[] = {
85 #define NUM_CODE_PAGE_RANGE (int) (sizeof FcCodePageRange / sizeof FcCodePageRange[0])
88 FcFreeTypeIsExclusiveLang (const FcChar8 *lang)
92 for (i = 0; i < NUM_CODE_PAGE_RANGE; i++)
94 if (FcLangCompare (lang, FcCodePageRange[i].lang) == FcLangEqual)
101 const FT_UShort platform_id;
102 const FT_UShort encoding_id;
103 const char fromcode[12];
106 #define TT_ENCODING_DONT_CARE 0xffff
107 #define FC_ENCODING_MAC_ROMAN "MACINTOSH"
109 static const FcFtEncoding fcFtEncoding[] = {
110 { TT_PLATFORM_APPLE_UNICODE, TT_ENCODING_DONT_CARE, "UTF-16BE" },
111 { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, "MACINTOSH" },
112 { TT_PLATFORM_MACINTOSH, TT_MAC_ID_JAPANESE, "SJIS" },
113 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS, "UTF-16BE" },
114 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, "UTF-16BE" },
115 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, "SJIS-WIN" },
116 { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, "GB2312" },
117 { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, "BIG-5" },
118 { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, "Wansung" },
119 { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, "Johab" },
120 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, "UTF-16BE" },
121 { TT_PLATFORM_ISO, TT_ISO_ID_7BIT_ASCII, "ASCII" },
122 { TT_PLATFORM_ISO, TT_ISO_ID_10646, "UTF-16BE" },
123 { TT_PLATFORM_ISO, TT_ISO_ID_8859_1, "ISO-8859-1" },
126 #define NUM_FC_FT_ENCODING (int) (sizeof (fcFtEncoding) / sizeof (fcFtEncoding[0]))
129 const FT_UShort platform_id;
130 const FT_UShort language_id;
134 #define TT_LANGUAGE_DONT_CARE 0xffff
136 static const FcFtLanguage fcFtLanguage[] = {
137 { TT_PLATFORM_APPLE_UNICODE, TT_LANGUAGE_DONT_CARE, "" },
138 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ENGLISH, "en" },
139 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FRENCH, "fr" },
140 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GERMAN, "de" },
141 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ITALIAN, "it" },
142 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_DUTCH, "nl" },
143 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SWEDISH, "sv" },
144 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SPANISH, "es" },
145 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_DANISH, "da" },
146 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_PORTUGUESE, "pt" },
147 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_NORWEGIAN, "no" },
148 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_HEBREW, "he" },
149 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_JAPANESE, "ja" },
150 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ARABIC, "ar" },
151 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FINNISH, "fi" },
152 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GREEK, "el" },
153 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ICELANDIC, "is" },
154 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALTESE, "mt" },
155 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TURKISH, "tr" },
156 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CROATIAN, "hr" },
157 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CHINESE_TRADITIONAL, "zh-tw" },
158 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_URDU, "ur" },
159 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_HINDI, "hi" },
160 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_THAI, "th" },
161 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KOREAN, "ko" },
162 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_LITHUANIAN, "lt" },
163 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_POLISH, "pl" },
164 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_HUNGARIAN, "hu" },
165 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ESTONIAN, "et" },
166 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_LETTISH, "lv" },
167 /* { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SAAMISK, ??? */
168 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FAEROESE, "fo" },
169 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FARSI, "fa" },
170 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_RUSSIAN, "ru" },
171 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CHINESE_SIMPLIFIED, "zh-cn" },
172 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FLEMISH, "nl" },
173 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_IRISH, "ga" },
174 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ALBANIAN, "sq" },
175 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ROMANIAN, "ro" },
176 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CZECH, "cs" },
177 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SLOVAK, "sk" },
178 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SLOVENIAN, "sl" },
179 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_YIDDISH, "yi" },
180 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SERBIAN, "sr" },
181 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MACEDONIAN, "mk" },
182 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BULGARIAN, "bg" },
183 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_UKRAINIAN, "uk" },
184 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BYELORUSSIAN, "be" },
185 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_UZBEK, "uz" },
186 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KAZAKH, "kk" },
187 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AZERBAIJANI, "az" },
188 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT, "az" },
189 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT, "ar" },
190 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ARMENIAN, "hy" },
191 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GEORGIAN, "ka" },
192 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MOLDAVIAN, "mo" },
193 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KIRGHIZ, "ky" },
194 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TAJIKI, "tg" },
195 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TURKMEN, "tk" },
196 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MONGOLIAN, "mo" },
197 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT,"mo" },
198 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT, "mo" },
199 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_PASHTO, "ps" },
200 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KURDISH, "ku" },
201 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KASHMIRI, "ks" },
202 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SINDHI, "sd" },
203 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TIBETAN, "bo" },
204 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_NEPALI, "ne" },
205 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SANSKRIT, "sa" },
206 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MARATHI, "mr" },
207 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BENGALI, "bn" },
208 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ASSAMESE, "as" },
209 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GUJARATI, "gu" },
210 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_PUNJABI, "pa" },
211 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ORIYA, "or" },
212 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALAYALAM, "ml" },
213 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KANNADA, "kn" },
214 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TAMIL, "ta" },
215 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TELUGU, "te" },
216 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SINHALESE, "si" },
217 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BURMESE, "my" },
218 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KHMER, "km" },
219 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_LAO, "lo" },
220 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_VIETNAMESE, "vi" },
221 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_INDONESIAN, "id" },
222 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TAGALOG, "tl" },
223 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALAY_ROMAN_SCRIPT, "ms" },
224 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALAY_ARABIC_SCRIPT, "ms" },
225 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AMHARIC, "am" },
226 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TIGRINYA, "ti" },
227 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GALLA, "om" },
228 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SOMALI, "so" },
229 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SWAHILI, "sw" },
230 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_RUANDA, "rw" },
231 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_RUNDI, "rn" },
232 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CHEWA, "ny" },
233 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALAGASY, "mg" },
234 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ESPERANTO, "eo" },
235 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_WELSH, "cy" },
236 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BASQUE, "eu" },
237 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CATALAN, "ca" },
238 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_LATIN, "la" },
239 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_QUECHUA, "qu" },
240 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GUARANI, "gn" },
241 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AYMARA, "ay" },
242 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TATAR, "tt" },
243 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_UIGHUR, "ug" },
244 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_DZONGKHA, "dz" },
245 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_JAVANESE, "jw" },
246 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SUNDANESE, "su" },
248 #if 0 /* these seem to be errors that have been dropped */
250 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SCOTTISH_GAELIC },
251 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_IRISH_GAELIC },
255 /* The following codes are new as of 2000-03-10 */
256 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GALICIAN, "gl" },
257 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AFRIKAANS, "af" },
258 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BRETON, "br" },
259 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_INUKTITUT, "iu" },
260 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SCOTTISH_GAELIC, "gd" },
261 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MANX_GAELIC, "gv" },
262 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_IRISH_GAELIC, "ga" },
263 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TONGAN, "to" },
264 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GREEK_POLYTONIC, "el" },
265 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GREELANDIC, "ik" },
266 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT,"az" },
268 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_SAUDI_ARABIA, "ar" },
269 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_IRAQ, "ar" },
270 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_EGYPT, "ar" },
271 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_LIBYA, "ar" },
272 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_ALGERIA, "ar" },
273 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_MOROCCO, "ar" },
274 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_TUNISIA, "ar" },
275 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_OMAN, "ar" },
276 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_YEMEN, "ar" },
277 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_SYRIA, "ar" },
278 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_JORDAN, "ar" },
279 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_LEBANON, "ar" },
280 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_KUWAIT, "ar" },
281 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_UAE, "ar" },
282 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_BAHRAIN, "ar" },
283 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_QATAR, "ar" },
284 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BULGARIAN_BULGARIA, "bg" },
285 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CATALAN_SPAIN, "ca" },
286 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_TAIWAN, "zh-tw" },
287 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_PRC, "zh-cn" },
288 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_HONG_KONG, "zh-hk" },
289 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_SINGAPORE, "zh-sg" },
291 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_MACAU, "zh-mo" },
293 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CZECH_CZECH_REPUBLIC, "cs" },
294 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DANISH_DENMARK, "da" },
295 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_GERMANY, "de" },
296 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_SWITZERLAND, "de" },
297 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_AUSTRIA, "de" },
298 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_LUXEMBOURG, "de" },
299 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_LIECHTENSTEI, "de" },
300 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GREEK_GREECE, "el" },
301 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_UNITED_STATES, "en" },
302 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_UNITED_KINGDOM, "en" },
303 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_AUSTRALIA, "en" },
304 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_CANADA, "en" },
305 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_NEW_ZEALAND, "en" },
306 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_IRELAND, "en" },
307 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_SOUTH_AFRICA, "en" },
308 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_JAMAICA, "en" },
309 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_CARIBBEAN, "en" },
310 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_BELIZE, "en" },
311 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_TRINIDAD, "en" },
312 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_ZIMBABWE, "en" },
313 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_PHILIPPINES, "en" },
314 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT,"es" },
315 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_MEXICO, "es" },
316 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT,"es" },
317 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_GUATEMALA, "es" },
318 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_COSTA_RICA, "es" },
319 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_PANAMA, "es" },
320 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC,"es" },
321 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_VENEZUELA, "es" },
322 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_COLOMBIA, "es" },
323 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_PERU, "es" },
324 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_ARGENTINA, "es" },
325 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_ECUADOR, "es" },
326 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_CHILE, "es" },
327 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_URUGUAY, "es" },
328 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_PARAGUAY, "es" },
329 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_BOLIVIA, "es" },
330 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_EL_SALVADOR, "es" },
331 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_HONDURAS, "es" },
332 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_NICARAGUA, "es" },
333 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_PUERTO_RICO, "es" },
334 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FINNISH_FINLAND, "fi" },
335 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_FRANCE, "fr" },
336 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_BELGIUM, "fr" },
337 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_CANADA, "fr" },
338 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_SWITZERLAND, "fr" },
339 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_LUXEMBOURG, "fr" },
340 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_MONACO, "fr" },
341 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HEBREW_ISRAEL, "he" },
342 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HUNGARIAN_HUNGARY, "hu" },
343 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ICELANDIC_ICELAND, "is" },
344 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ITALIAN_ITALY, "it" },
345 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ITALIAN_SWITZERLAND, "it" },
346 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_JAPANESE_JAPAN, "ja" },
347 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA,"ko" },
348 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KOREAN_JOHAB_KOREA, "ko" },
349 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DUTCH_NETHERLANDS, "nl" },
350 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DUTCH_BELGIUM, "nl" },
351 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL, "no" },
352 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK, "nn" },
353 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_POLISH_POLAND, "pl" },
354 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PORTUGUESE_BRAZIL, "pt" },
355 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PORTUGUESE_PORTUGAL, "pt" },
356 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND,"rm" },
357 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ROMANIAN_ROMANIA, "ro" },
358 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MOLDAVIAN_MOLDAVIA, "mo" },
359 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_RUSSIAN_RUSSIA, "ru" },
360 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_RUSSIAN_MOLDAVIA, "ru" },
361 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CROATIAN_CROATIA, "hr" },
362 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SERBIAN_SERBIA_LATIN, "sr" },
363 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC, "sr" },
364 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SLOVAK_SLOVAKIA, "sk" },
365 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ALBANIAN_ALBANIA, "sq" },
366 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SWEDISH_SWEDEN, "sv" },
367 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SWEDISH_FINLAND, "sv" },
368 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_THAI_THAILAND, "th" },
369 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TURKISH_TURKEY, "tr" },
370 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_URDU_PAKISTAN, "ur" },
371 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_INDONESIAN_INDONESIA, "id" },
372 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_UKRAINIAN_UKRAINE, "uk" },
373 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BELARUSIAN_BELARUS, "be" },
374 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SLOVENE_SLOVENIA, "sl" },
375 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ESTONIAN_ESTONIA, "et" },
376 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_LATVIAN_LATVIA, "lv" },
377 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_LITHUANIAN_LITHUANIA, "lt" },
378 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA,"lt" },
379 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MAORI_NEW_ZEALAND, "mi" },
380 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FARSI_IRAN, "fa" },
381 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_VIETNAMESE_VIET_NAM, "vi" },
382 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARMENIAN_ARMENIA, "hy" },
383 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN, "az" },
384 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC, "az" },
385 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BASQUE_SPAIN, "eu" },
386 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SORBIAN_GERMANY, "wen" },
387 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MACEDONIAN_MACEDONIA, "mk" },
388 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SUTU_SOUTH_AFRICA, "st" },
389 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TSONGA_SOUTH_AFRICA, "ts" },
390 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TSWANA_SOUTH_AFRICA, "tn" },
391 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_VENDA_SOUTH_AFRICA, "ven" },
392 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_XHOSA_SOUTH_AFRICA, "xh" },
393 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ZULU_SOUTH_AFRICA, "zu" },
394 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA, "af" },
395 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GEORGIAN_GEORGIA, "ka" },
396 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS, "fo" },
397 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HINDI_INDIA, "hi" },
398 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MALTESE_MALTA, "mt" },
399 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SAAMI_LAPONIA, "se" },
401 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM,"gd" },
402 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_IRISH_GAELIC_IRELAND, "ga" },
404 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MALAY_MALAYSIA, "ms" },
405 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM, "ms" },
406 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KAZAK_KAZAKSTAN, "kk" },
407 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SWAHILI_KENYA, "sw" },
408 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN, "uz" },
409 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC, "uz" },
410 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TATAR_TATARSTAN, "tt" },
411 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BENGALI_INDIA, "bn" },
412 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PUNJABI_INDIA, "pa" },
413 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GUJARATI_INDIA, "gu" },
414 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ORIYA_INDIA, "or" },
415 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TAMIL_INDIA, "ta" },
416 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TELUGU_INDIA, "te" },
417 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KANNADA_INDIA, "kn" },
418 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MALAYALAM_INDIA, "ml" },
419 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ASSAMESE_INDIA, "as" },
420 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MARATHI_INDIA, "mr" },
421 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SANSKRIT_INDIA, "sa" },
422 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KONKANI_INDIA, "kok" },
424 /* new as of 2001-01-01 */
425 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_GENERAL, "ar" },
426 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_GENERAL, "zh" },
427 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_GENERAL, "en" },
428 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_WEST_INDIES, "fr" },
429 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_REUNION, "fr" },
430 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_CONGO, "fr" },
432 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_SENEGAL, "fr" },
433 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_CAMEROON, "fr" },
434 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_COTE_D_IVOIRE, "fr" },
435 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_MALI, "fr" },
436 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA,"bs" },
437 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_URDU_INDIA, "ur" },
438 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TAJIK_TAJIKISTAN, "tg" },
439 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_YIDDISH_GERMANY, "yi" },
440 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN, "ky" },
442 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TURKMEN_TURKMENISTAN, "tk" },
443 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MONGOLIAN_MONGOLIA, "mn" },
445 /* the following seems to be inconsistent;
446 here is the current "official" way: */
447 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TIBETAN_BHUTAN, "bo" },
448 /* and here is what is used by Passport SDK */
449 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TIBETAN_CHINA, "bo" },
450 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DZONGHKA_BHUTAN, "dz" },
451 /* end of inconsistency */
453 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_WELSH_WALES, "cy" },
454 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KHMER_CAMBODIA, "km" },
455 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_LAO_LAOS, "lo" },
456 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BURMESE_MYANMAR, "my" },
457 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GALICIAN_SPAIN, "gl" },
458 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MANIPURI_INDIA, "mni" },
459 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SINDHI_INDIA, "sd" },
460 /* the following one is only encountered in Microsoft RTF specification */
461 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KASHMIRI_PAKISTAN, "ks" },
462 /* the following one is not in the Passport list, looks like an omission */
463 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KASHMIRI_INDIA, "ks" },
464 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_NEPALI_NEPAL, "ne" },
465 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_NEPALI_INDIA, "ne" },
466 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRISIAN_NETHERLANDS, "fy" },
468 /* new as of 2001-03-01 (from Office Xp) */
469 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_HONG_KONG, "en" },
470 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_INDIA, "en" },
471 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_MALAYSIA, "en" },
472 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_SINGAPORE, "en" },
473 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SYRIAC_SYRIA, "syr" },
474 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SINHALESE_SRI_LANKA, "si" },
475 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHEROKEE_UNITED_STATES, "chr" },
476 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_INUKTITUT_CANADA, "iu" },
477 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_AMHARIC_ETHIOPIA, "am" },
479 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TAMAZIGHT_MOROCCO },
480 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN },
482 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PASHTO_AFGHANISTAN, "ps" },
483 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FILIPINO_PHILIPPINES, "phi" },
484 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DHIVEHI_MALDIVES, "div" },
486 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_OROMO_ETHIOPIA, "om" },
487 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TIGRIGNA_ETHIOPIA, "ti" },
488 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TIGRIGNA_ERYTHREA, "ti" },
490 /* New additions from Windows Xp/Passport SDK 2001-11-10. */
492 /* don't ask what this one means... It is commented out currently. */
494 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GREEK_GREECE2 },
497 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_UNITED_STATES, "es" },
498 /* The following two IDs blatantly violate MS specs by using a */
499 /* sublanguage >,. */
500 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_LATIN_AMERICA, "es" },
501 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_NORTH_AFRICA, "fr" },
503 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_MOROCCO, "fr" },
504 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_HAITI, "fr" },
505 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BENGALI_BANGLADESH, "bn" },
506 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN, "ar" },
507 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN,"mn" },
509 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_EDO_NIGERIA },
510 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FULFULDE_NIGERIA },
511 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_IBIBIO_NIGERIA },
513 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HAUSA_NIGERIA, "ha" },
514 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_YORUBA_NIGERIA, "yo" },
515 /* language codes from, to, are (still) unknown. */
516 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_IGBO_NIGERIA, "ibo" },
517 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KANURI_NIGERIA, "kau" },
518 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GUARANI_PARAGUAY, "gn" },
519 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HAWAIIAN_UNITED_STATES, "haw" },
520 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_LATIN, "la" },
521 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SOMALI_SOMALIA, "so" },
523 /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */
524 /* not written (but OTOH the peculiar writing system is worth */
526 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_YI_CHINA },
528 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES,"pap" },
531 #define NUM_FC_FT_LANGUAGE (int) (sizeof (fcFtLanguage) / sizeof (fcFtLanguage[0]))
534 FT_UShort language_id;
538 static const FcMacRomanFake fcMacRomanFake[] = {
539 { TT_MS_LANGID_JAPANESE_JAPAN, "SJIS-WIN" },
540 { TT_MS_LANGID_ENGLISH_UNITED_STATES, "ASCII" },
544 FcFontCapabilities(FT_Face face);
547 FcFreeTypeSpacing (FT_Face face);
549 #define NUM_FC_MAC_ROMAN_FAKE (int) (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0]))
552 /* From http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/ROMAN.TXT */
553 static const FcChar16 fcMacRomanNonASCIIToUnicode[128] = {
554 /*0x80*/ 0x00C4, /* LATIN CAPITAL LETTER A WITH DIAERESIS */
555 /*0x81*/ 0x00C5, /* LATIN CAPITAL LETTER A WITH RING ABOVE */
556 /*0x82*/ 0x00C7, /* LATIN CAPITAL LETTER C WITH CEDILLA */
557 /*0x83*/ 0x00C9, /* LATIN CAPITAL LETTER E WITH ACUTE */
558 /*0x84*/ 0x00D1, /* LATIN CAPITAL LETTER N WITH TILDE */
559 /*0x85*/ 0x00D6, /* LATIN CAPITAL LETTER O WITH DIAERESIS */
560 /*0x86*/ 0x00DC, /* LATIN CAPITAL LETTER U WITH DIAERESIS */
561 /*0x87*/ 0x00E1, /* LATIN SMALL LETTER A WITH ACUTE */
562 /*0x88*/ 0x00E0, /* LATIN SMALL LETTER A WITH GRAVE */
563 /*0x89*/ 0x00E2, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
564 /*0x8A*/ 0x00E4, /* LATIN SMALL LETTER A WITH DIAERESIS */
565 /*0x8B*/ 0x00E3, /* LATIN SMALL LETTER A WITH TILDE */
566 /*0x8C*/ 0x00E5, /* LATIN SMALL LETTER A WITH RING ABOVE */
567 /*0x8D*/ 0x00E7, /* LATIN SMALL LETTER C WITH CEDILLA */
568 /*0x8E*/ 0x00E9, /* LATIN SMALL LETTER E WITH ACUTE */
569 /*0x8F*/ 0x00E8, /* LATIN SMALL LETTER E WITH GRAVE */
570 /*0x90*/ 0x00EA, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */
571 /*0x91*/ 0x00EB, /* LATIN SMALL LETTER E WITH DIAERESIS */
572 /*0x92*/ 0x00ED, /* LATIN SMALL LETTER I WITH ACUTE */
573 /*0x93*/ 0x00EC, /* LATIN SMALL LETTER I WITH GRAVE */
574 /*0x94*/ 0x00EE, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
575 /*0x95*/ 0x00EF, /* LATIN SMALL LETTER I WITH DIAERESIS */
576 /*0x96*/ 0x00F1, /* LATIN SMALL LETTER N WITH TILDE */
577 /*0x97*/ 0x00F3, /* LATIN SMALL LETTER O WITH ACUTE */
578 /*0x98*/ 0x00F2, /* LATIN SMALL LETTER O WITH GRAVE */
579 /*0x99*/ 0x00F4, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
580 /*0x9A*/ 0x00F6, /* LATIN SMALL LETTER O WITH DIAERESIS */
581 /*0x9B*/ 0x00F5, /* LATIN SMALL LETTER O WITH TILDE */
582 /*0x9C*/ 0x00FA, /* LATIN SMALL LETTER U WITH ACUTE */
583 /*0x9D*/ 0x00F9, /* LATIN SMALL LETTER U WITH GRAVE */
584 /*0x9E*/ 0x00FB, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
585 /*0x9F*/ 0x00FC, /* LATIN SMALL LETTER U WITH DIAERESIS */
586 /*0xA0*/ 0x2020, /* DAGGER */
587 /*0xA1*/ 0x00B0, /* DEGREE SIGN */
588 /*0xA2*/ 0x00A2, /* CENT SIGN */
589 /*0xA3*/ 0x00A3, /* POUND SIGN */
590 /*0xA4*/ 0x00A7, /* SECTION SIGN */
591 /*0xA5*/ 0x2022, /* BULLET */
592 /*0xA6*/ 0x00B6, /* PILCROW SIGN */
593 /*0xA7*/ 0x00DF, /* LATIN SMALL LETTER SHARP S */
594 /*0xA8*/ 0x00AE, /* REGISTERED SIGN */
595 /*0xA9*/ 0x00A9, /* COPYRIGHT SIGN */
596 /*0xAA*/ 0x2122, /* TRADE MARK SIGN */
597 /*0xAB*/ 0x00B4, /* ACUTE ACCENT */
598 /*0xAC*/ 0x00A8, /* DIAERESIS */
599 /*0xAD*/ 0x2260, /* NOT EQUAL TO */
600 /*0xAE*/ 0x00C6, /* LATIN CAPITAL LETTER AE */
601 /*0xAF*/ 0x00D8, /* LATIN CAPITAL LETTER O WITH STROKE */
602 /*0xB0*/ 0x221E, /* INFINITY */
603 /*0xB1*/ 0x00B1, /* PLUS-MINUS SIGN */
604 /*0xB2*/ 0x2264, /* LESS-THAN OR EQUAL TO */
605 /*0xB3*/ 0x2265, /* GREATER-THAN OR EQUAL TO */
606 /*0xB4*/ 0x00A5, /* YEN SIGN */
607 /*0xB5*/ 0x00B5, /* MICRO SIGN */
608 /*0xB6*/ 0x2202, /* PARTIAL DIFFERENTIAL */
609 /*0xB7*/ 0x2211, /* N-ARY SUMMATION */
610 /*0xB8*/ 0x220F, /* N-ARY PRODUCT */
611 /*0xB9*/ 0x03C0, /* GREEK SMALL LETTER PI */
612 /*0xBA*/ 0x222B, /* INTEGRAL */
613 /*0xBB*/ 0x00AA, /* FEMININE ORDINAL INDICATOR */
614 /*0xBC*/ 0x00BA, /* MASCULINE ORDINAL INDICATOR */
615 /*0xBD*/ 0x03A9, /* GREEK CAPITAL LETTER OMEGA */
616 /*0xBE*/ 0x00E6, /* LATIN SMALL LETTER AE */
617 /*0xBF*/ 0x00F8, /* LATIN SMALL LETTER O WITH STROKE */
618 /*0xC0*/ 0x00BF, /* INVERTED QUESTION MARK */
619 /*0xC1*/ 0x00A1, /* INVERTED EXCLAMATION MARK */
620 /*0xC2*/ 0x00AC, /* NOT SIGN */
621 /*0xC3*/ 0x221A, /* SQUARE ROOT */
622 /*0xC4*/ 0x0192, /* LATIN SMALL LETTER F WITH HOOK */
623 /*0xC5*/ 0x2248, /* ALMOST EQUAL TO */
624 /*0xC6*/ 0x2206, /* INCREMENT */
625 /*0xC7*/ 0x00AB, /* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
626 /*0xC8*/ 0x00BB, /* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
627 /*0xC9*/ 0x2026, /* HORIZONTAL ELLIPSIS */
628 /*0xCA*/ 0x00A0, /* NO-BREAK SPACE */
629 /*0xCB*/ 0x00C0, /* LATIN CAPITAL LETTER A WITH GRAVE */
630 /*0xCC*/ 0x00C3, /* LATIN CAPITAL LETTER A WITH TILDE */
631 /*0xCD*/ 0x00D5, /* LATIN CAPITAL LETTER O WITH TILDE */
632 /*0xCE*/ 0x0152, /* LATIN CAPITAL LIGATURE OE */
633 /*0xCF*/ 0x0153, /* LATIN SMALL LIGATURE OE */
634 /*0xD0*/ 0x2013, /* EN DASH */
635 /*0xD1*/ 0x2014, /* EM DASH */
636 /*0xD2*/ 0x201C, /* LEFT DOUBLE QUOTATION MARK */
637 /*0xD3*/ 0x201D, /* RIGHT DOUBLE QUOTATION MARK */
638 /*0xD4*/ 0x2018, /* LEFT SINGLE QUOTATION MARK */
639 /*0xD5*/ 0x2019, /* RIGHT SINGLE QUOTATION MARK */
640 /*0xD6*/ 0x00F7, /* DIVISION SIGN */
641 /*0xD7*/ 0x25CA, /* LOZENGE */
642 /*0xD8*/ 0x00FF, /* LATIN SMALL LETTER Y WITH DIAERESIS */
643 /*0xD9*/ 0x0178, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
644 /*0xDA*/ 0x2044, /* FRACTION SLASH */
645 /*0xDB*/ 0x20AC, /* EURO SIGN */
646 /*0xDC*/ 0x2039, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
647 /*0xDD*/ 0x203A, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
648 /*0xDE*/ 0xFB01, /* LATIN SMALL LIGATURE FI */
649 /*0xDF*/ 0xFB02, /* LATIN SMALL LIGATURE FL */
650 /*0xE0*/ 0x2021, /* DOUBLE DAGGER */
651 /*0xE1*/ 0x00B7, /* MIDDLE DOT */
652 /*0xE2*/ 0x201A, /* SINGLE LOW-9 QUOTATION MARK */
653 /*0xE3*/ 0x201E, /* DOUBLE LOW-9 QUOTATION MARK */
654 /*0xE4*/ 0x2030, /* PER MILLE SIGN */
655 /*0xE5*/ 0x00C2, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
656 /*0xE6*/ 0x00CA, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
657 /*0xE7*/ 0x00C1, /* LATIN CAPITAL LETTER A WITH ACUTE */
658 /*0xE8*/ 0x00CB, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
659 /*0xE9*/ 0x00C8, /* LATIN CAPITAL LETTER E WITH GRAVE */
660 /*0xEA*/ 0x00CD, /* LATIN CAPITAL LETTER I WITH ACUTE */
661 /*0xEB*/ 0x00CE, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
662 /*0xEC*/ 0x00CF, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
663 /*0xED*/ 0x00CC, /* LATIN CAPITAL LETTER I WITH GRAVE */
664 /*0xEE*/ 0x00D3, /* LATIN CAPITAL LETTER O WITH ACUTE */
665 /*0xEF*/ 0x00D4, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
666 /*0xF0*/ 0xF8FF, /* Apple logo */
667 /*0xF1*/ 0x00D2, /* LATIN CAPITAL LETTER O WITH GRAVE */
668 /*0xF2*/ 0x00DA, /* LATIN CAPITAL LETTER U WITH ACUTE */
669 /*0xF3*/ 0x00DB, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
670 /*0xF4*/ 0x00D9, /* LATIN CAPITAL LETTER U WITH GRAVE */
671 /*0xF5*/ 0x0131, /* LATIN SMALL LETTER DOTLESS I */
672 /*0xF6*/ 0x02C6, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
673 /*0xF7*/ 0x02DC, /* SMALL TILDE */
674 /*0xF8*/ 0x00AF, /* MACRON */
675 /*0xF9*/ 0x02D8, /* BREVE */
676 /*0xFA*/ 0x02D9, /* DOT ABOVE */
677 /*0xFB*/ 0x02DA, /* RING ABOVE */
678 /*0xFC*/ 0x00B8, /* CEDILLA */
679 /*0xFD*/ 0x02DD, /* DOUBLE ACUTE ACCENT */
680 /*0xFE*/ 0x02DB, /* OGONEK */
681 /*0xFF*/ 0x02C7, /* CARON */
689 * A shift-JIS will have many high bits turned on
692 FcLooksLikeSJIS (FcChar8 *string, int len)
694 int nhigh = 0, nlow = 0;
698 if (*string++ & 0x80) nhigh++;
702 * Heuristic -- if more than 1/3 of the bytes have the high-bit set,
703 * this is likely to be SJIS and not ROMAN
705 if (nhigh * 2 > nlow)
711 FcSfntNameTranscode (FT_SfntName *sname)
714 const char *fromcode;
720 for (i = 0; i < NUM_FC_FT_ENCODING; i++)
721 if (fcFtEncoding[i].platform_id == sname->platform_id &&
722 (fcFtEncoding[i].encoding_id == TT_ENCODING_DONT_CARE ||
723 fcFtEncoding[i].encoding_id == sname->encoding_id))
725 if (i == NUM_FC_FT_ENCODING)
727 fromcode = fcFtEncoding[i].fromcode;
730 * Many names encoded for TT_PLATFORM_MACINTOSH are broken
731 * in various ways. Kludge around them.
733 if (!strcmp (fromcode, FC_ENCODING_MAC_ROMAN))
735 if (sname->language_id == TT_MAC_LANGID_ENGLISH &&
736 FcLooksLikeSJIS (sname->string, sname->string_len))
740 else if (sname->language_id >= 0x100)
743 * "real" Mac language IDs are all less than 150.
744 * Names using one of the MS language IDs are assumed
745 * to use an associated encoding (Yes, this is a kludge)
750 for (f = 0; f < NUM_FC_MAC_ROMAN_FAKE; f++)
751 if (fcMacRomanFake[f].language_id == sname->language_id)
753 fromcode = fcMacRomanFake[f].fromcode;
760 if (!strcmp (fromcode, "UCS-2BE") || !strcmp (fromcode, "UTF-16BE"))
762 FcChar8 *src = sname->string;
763 int src_len = sname->string_len;
771 * Convert Utf16 to Utf8
774 if (!FcUtf16Len (src, FcEndianBig, src_len, &len, &wchar))
778 * Allocate plenty of space. Freed below
780 utf8 = malloc (len * FC_UTF8_MAX_LEN + 1);
786 while ((ilen = FcUtf16ToUcs4 (src, FcEndianBig, &ucs4, src_len)) > 0)
790 olen = FcUcs4ToUtf8 (ucs4, u8);
796 if (!strcmp (fromcode, "ASCII") || !strcmp (fromcode, "ISO-8859-1"))
798 FcChar8 *src = sname->string;
799 int src_len = sname->string_len;
805 * Convert Latin1 to Utf8. Freed below
807 utf8 = malloc (src_len * 2 + 1);
816 olen = FcUcs4ToUtf8 (ucs4, u8);
822 if (!strcmp (fromcode, FC_ENCODING_MAC_ROMAN))
824 FcChar8 *src = sname->string;
825 int src_len = sname->string_len;
831 * Convert Latin1 to Utf8. Freed below
833 utf8 = malloc (src_len * 3 + 1);
842 ucs4 = fcMacRomanNonASCIIToUnicode[ucs4 - 128];
844 olen = FcUcs4ToUtf8 (ucs4, u8);
852 cd = iconv_open ("UTF-8", fromcode);
853 if (cd && cd != (iconv_t) (-1))
855 size_t in_bytes_left = sname->string_len;
856 size_t out_bytes_left = sname->string_len * FC_UTF8_MAX_LEN;
857 char *inbuf, *outbuf;
859 utf8 = malloc (out_bytes_left + 1);
866 outbuf = (char *) utf8;
867 inbuf = (char *) sname->string;
869 while (in_bytes_left)
871 size_t did = iconv (cd,
872 &inbuf, &in_bytes_left,
873 &outbuf, &out_bytes_left);
874 if (did == (size_t) (-1))
888 if (FcStrCmpIgnoreBlanksAndCase (utf8, (FcChar8 *) "") == 0)
896 static const FcChar8 *
897 FcSfntNameLanguage (FT_SfntName *sname)
900 FT_UShort platform_id = sname->platform_id;
901 FT_UShort language_id = sname->language_id;
904 * Many names encoded for TT_PLATFORM_MACINTOSH are broken
905 * in various ways. Kludge around them.
907 if (platform_id == TT_PLATFORM_MACINTOSH &&
908 sname->encoding_id == TT_MAC_ID_ROMAN &&
909 FcLooksLikeSJIS (sname->string, sname->string_len))
911 language_id = TT_MAC_LANGID_JAPANESE;
914 for (i = 0; i < NUM_FC_FT_LANGUAGE; i++)
915 if (fcFtLanguage[i].platform_id == platform_id &&
916 (fcFtLanguage[i].language_id == TT_LANGUAGE_DONT_CARE ||
917 fcFtLanguage[i].language_id == language_id))
919 if (fcFtLanguage[i].lang[0] == '\0')
922 return (FcChar8 *) fcFtLanguage[i].lang;
927 /* Order is significant. For example, some B&H fonts are hinted by
928 URW++, and both strings appear in the notice. */
930 static const char *FcNoticeFoundries[][2] =
934 {"Bitstream", "bitstream"},
937 {"HanYang System", "hanyang"},
940 {"International Typeface Corporation", "itc"},
941 {"Linotype", "linotype"},
942 {"LINOTYPE-HELL", "linotype"},
943 {"Microsoft", "microsoft"},
944 {"Monotype", "monotype"},
946 {"Tiro Typeworks", "tiro"},
948 {"XFree86", "xfree86"},
952 #define NUM_NOTICE_FOUNDRIES (int) (sizeof (FcNoticeFoundries) / sizeof (FcNoticeFoundries[0]))
954 static const FcChar8 *
955 FcNoticeFoundry(const FT_String *notice)
960 for(i = 0; i < NUM_NOTICE_FOUNDRIES; i++)
962 const char *n = FcNoticeFoundries[i][0];
963 const char *f = FcNoticeFoundries[i][1];
965 if (strstr ((const char *) notice, n))
966 return (const FcChar8 *) f;
971 typedef struct _FcStringConst {
977 FcStringIsConst (const FcChar8 *string,
978 const FcStringConst *c,
983 for (i = 0; i < nc; i++)
984 if (FcStrCmpIgnoreBlanksAndCase (string, c[i].name) == 0)
990 FcStringContainsConst (const FcChar8 *string,
991 const FcStringConst *c,
996 for (i = 0; i < nc; i++)
998 if (c[i].name[0] == '<')
1000 if (FcStrContainsWord (string, c[i].name + 1))
1005 if (FcStrContainsIgnoreBlanksAndCase (string, c[i].name))
1012 typedef FcChar8 *FC8;
1014 static const FcStringConst weightConsts[] = {
1015 { (FC8) "thin", FC_WEIGHT_THIN },
1016 { (FC8) "extralight", FC_WEIGHT_EXTRALIGHT },
1017 { (FC8) "ultralight", FC_WEIGHT_ULTRALIGHT },
1018 { (FC8) "demilight", FC_WEIGHT_DEMILIGHT },
1019 { (FC8) "semilight", FC_WEIGHT_SEMILIGHT },
1020 { (FC8) "light", FC_WEIGHT_LIGHT },
1021 { (FC8) "book", FC_WEIGHT_BOOK },
1022 { (FC8) "regular", FC_WEIGHT_REGULAR },
1023 { (FC8) "normal", FC_WEIGHT_NORMAL },
1024 { (FC8) "medium", FC_WEIGHT_MEDIUM },
1025 { (FC8) "demibold", FC_WEIGHT_DEMIBOLD },
1026 { (FC8) "demi", FC_WEIGHT_DEMIBOLD },
1027 { (FC8) "semibold", FC_WEIGHT_SEMIBOLD },
1028 { (FC8) "extrabold", FC_WEIGHT_EXTRABOLD },
1029 { (FC8) "superbold", FC_WEIGHT_EXTRABOLD },
1030 { (FC8) "ultrabold", FC_WEIGHT_ULTRABOLD },
1031 { (FC8) "bold", FC_WEIGHT_BOLD },
1032 { (FC8) "ultrablack", FC_WEIGHT_ULTRABLACK },
1033 { (FC8) "superblack", FC_WEIGHT_EXTRABLACK },
1034 { (FC8) "extrablack", FC_WEIGHT_EXTRABLACK },
1035 { (FC8) "<ultra", FC_WEIGHT_ULTRABOLD }, /* only if a word */
1036 { (FC8) "black", FC_WEIGHT_BLACK },
1037 { (FC8) "heavy", FC_WEIGHT_HEAVY },
1040 #define NUM_WEIGHT_CONSTS (int) (sizeof (weightConsts) / sizeof (weightConsts[0]))
1042 #define FcIsWeight(s) FcStringIsConst(s,weightConsts,NUM_WEIGHT_CONSTS)
1043 #define FcContainsWeight(s) FcStringContainsConst (s,weightConsts,NUM_WEIGHT_CONSTS)
1045 static const FcStringConst widthConsts[] = {
1046 { (FC8) "ultracondensed", FC_WIDTH_ULTRACONDENSED },
1047 { (FC8) "extracondensed", FC_WIDTH_EXTRACONDENSED },
1048 { (FC8) "semicondensed", FC_WIDTH_SEMICONDENSED },
1049 { (FC8) "condensed", FC_WIDTH_CONDENSED }, /* must be after *condensed */
1050 { (FC8) "normal", FC_WIDTH_NORMAL },
1051 { (FC8) "semiexpanded", FC_WIDTH_SEMIEXPANDED },
1052 { (FC8) "extraexpanded", FC_WIDTH_EXTRAEXPANDED },
1053 { (FC8) "ultraexpanded", FC_WIDTH_ULTRAEXPANDED },
1054 { (FC8) "expanded", FC_WIDTH_EXPANDED }, /* must be after *expanded */
1055 { (FC8) "extended", FC_WIDTH_EXPANDED },
1058 #define NUM_WIDTH_CONSTS (int) (sizeof (widthConsts) / sizeof (widthConsts[0]))
1060 #define FcIsWidth(s) FcStringIsConst(s,widthConsts,NUM_WIDTH_CONSTS)
1061 #define FcContainsWidth(s) FcStringContainsConst (s,widthConsts,NUM_WIDTH_CONSTS)
1063 static const FcStringConst slantConsts[] = {
1064 { (FC8) "italic", FC_SLANT_ITALIC },
1065 { (FC8) "kursiv", FC_SLANT_ITALIC },
1066 { (FC8) "oblique", FC_SLANT_OBLIQUE },
1069 #define NUM_SLANT_CONSTS (int) (sizeof (slantConsts) / sizeof (slantConsts[0]))
1071 #define FcContainsSlant(s) FcStringContainsConst (s,slantConsts,NUM_SLANT_CONSTS)
1073 static const FcStringConst decorativeConsts[] = {
1074 { (FC8) "shadow", FcTrue },
1075 { (FC8) "caps", FcTrue },
1076 { (FC8) "antiqua", FcTrue },
1077 { (FC8) "romansc", FcTrue },
1078 { (FC8) "embosed", FcTrue },
1079 { (FC8) "dunhill", FcTrue },
1082 #define NUM_DECORATIVE_CONSTS (int) (sizeof (decorativeConsts) / sizeof (decorativeConsts[0]))
1084 #define FcContainsDecorative(s) FcStringContainsConst (s,decorativeConsts,NUM_DECORATIVE_CONSTS)
1087 FcGetPixelSize (FT_Face face, int i)
1089 #if HAVE_FT_GET_BDF_PROPERTY
1090 if (face->num_fixed_sizes == 1)
1092 BDF_PropertyRec prop;
1095 rc = FT_Get_BDF_Property (face, "PIXEL_SIZE", &prop);
1096 if (rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
1097 return (double) prop.u.integer;
1100 return (double) face->available_sizes[i].y_ppem / 64.0;
1104 FcStringInPatternElement (FcPattern *pat, const char *elt, FcChar8 *string)
1108 for (e = 0; FcPatternGetString (pat, elt, e, &old) == FcResultMatch; e++)
1109 if (!FcStrCmpIgnoreBlanksAndCase (old, string))
1116 static const FT_UShort platform_order[] = {
1117 TT_PLATFORM_MICROSOFT,
1118 TT_PLATFORM_APPLE_UNICODE,
1119 TT_PLATFORM_MACINTOSH,
1122 #define NUM_PLATFORM_ORDER (sizeof (platform_order) / sizeof (platform_order[0]))
1124 static const FT_UShort nameid_order[] = {
1125 TT_NAME_ID_WWS_FAMILY,
1126 TT_NAME_ID_PREFERRED_FAMILY,
1127 TT_NAME_ID_FONT_FAMILY,
1128 TT_NAME_ID_MAC_FULL_NAME,
1129 TT_NAME_ID_FULL_NAME,
1130 TT_NAME_ID_WWS_SUBFAMILY,
1131 TT_NAME_ID_PREFERRED_SUBFAMILY,
1132 TT_NAME_ID_FONT_SUBFAMILY,
1133 TT_NAME_ID_TRADEMARK,
1134 TT_NAME_ID_MANUFACTURER,
1137 #define NUM_NAMEID_ORDER (sizeof (nameid_order) / sizeof (nameid_order[0]))
1140 FcFreeTypeGetName (const FT_Face face,
1141 unsigned int platform,
1142 unsigned int nameid,
1145 int min = 0, max = (int) FT_Get_Sfnt_Name_Count (face) - 1;
1149 int mid = (min + max) / 2;
1151 if (FT_Get_Sfnt_Name (face, mid, sname) != 0)
1154 if (platform < sname->platform_id || (platform == sname->platform_id && nameid < sname->name_id))
1156 else if (platform > sname->platform_id || (platform == sname->platform_id && nameid > sname->name_id))
1166 FcFreeTypeQueryFaceInternal (const FT_Face face,
1167 const FcChar8 *file,
1169 FcCharSet **cs_share,
1170 FcLangSet **ls_share)
1176 FcBool decorative = FcFalse;
1177 FcBool variable = FcFalse;
1178 FcBool variable_weight = FcFalse;
1179 FcBool variable_width = FcFalse;
1180 FcBool variable_size = FcFalse;
1184 FcChar8 *family = 0;
1186 FcChar8 *complex_, *foundry_ = NULL;
1187 const FcChar8 *foundry = 0;
1190 /* Support for glyph-variation named-instances. */
1191 FT_MM_Var *master = NULL;
1192 FT_Var_Named_Style *instance = NULL;
1193 double weight_mult = 1.0;
1194 double width_mult = 1.0;
1197 #if HAVE_FT_GET_PS_FONT_INFO
1198 PS_FontInfoRec psfontinfo;
1200 #if HAVE_FT_GET_BDF_PROPERTY
1201 BDF_PropertyRec prop;
1204 const FcChar8 *exclusiveLang = 0;
1207 int nfamily_lang = 0;
1209 int nstyle_lang = 0;
1211 int nfullname_lang = 0;
1217 FcBool symbol = FcFalse;
1219 FcInitDebug (); /* We might be called with no initizalization whatsoever. */
1221 pat = FcPatternCreate ();
1226 int has_outline = !!(face->face_flags & FT_FACE_FLAG_SCALABLE);
1229 if (!FcPatternAddBool (pat, FC_OUTLINE, has_outline))
1232 has_color = !!(face->face_flags & FT_FACE_FLAG_COLOR);
1233 if (!FcPatternAddBool (pat, FC_COLOR, has_color))
1236 /* All color fonts are designed to be scaled, even if they only have
1237 * bitmap strikes. Client is responsible to scale the bitmaps. This
1238 * is in constrast to non-color strikes... */
1239 if (!FcPatternAddBool (pat, FC_SCALABLE, has_outline || has_color))
1245 if (FT_Get_MM_Var (face, &master))
1248 if (id >> 16 == 0x8000)
1250 /* Query variable font itself. */
1253 for (i = 0; i < master->num_axis; i++)
1255 double min_value = master->axis[i].minimum / (double) (1 << 16);
1256 double def_value = master->axis[i].def / (double) (1 << 16);
1257 double max_value = master->axis[i].maximum / (double) (1 << 16);
1258 const char *elt = NULL;
1260 if (min_value > def_value || def_value > max_value || min_value == max_value)
1263 switch (master->axis[i].tag)
1265 case FT_MAKE_TAG ('w','g','h','t'):
1267 min_value = FcWeightFromOpenTypeDouble (min_value);
1268 max_value = FcWeightFromOpenTypeDouble (max_value);
1269 variable_weight = FcTrue;
1270 weight = 0; /* To stop looking for weight. */
1273 case FT_MAKE_TAG ('w','d','t','h'):
1275 /* Values in 'wdth' match Fontconfig FC_WIDTH_* scheme directly. */
1276 variable_width = FcTrue;
1277 width = 0; /* To stop looking for width. */
1280 case FT_MAKE_TAG ('o','p','s','z'):
1282 /* Values in 'opsz' match Fontconfig FC_SIZE, both are in points. */
1283 variable_size = FcTrue;
1289 FcRange *r = FcRangeCreateDouble (min_value, max_value);
1290 if (!FcPatternAddRange (pat, elt, r))
1305 else if ((id >> 16) - 1 < master->num_namedstyles)
1307 /* Pull out weight and width from named-instance. */
1310 instance = &master->namedstyle[(id >> 16) - 1];
1312 for (i = 0; i < master->num_axis; i++)
1314 double value = instance->coords[i] / (double) (1 << 16);
1315 double default_value = master->axis[i].def / (double) (1 << 16);
1316 double mult = default_value ? value / default_value : 1;
1317 //printf ("named-instance, axis %d tag %lx value %g\n", i, master->axis[i].tag, value);
1318 switch (master->axis[i].tag)
1320 case FT_MAKE_TAG ('w','g','h','t'):
1324 case FT_MAKE_TAG ('w','d','t','h'):
1328 case FT_MAKE_TAG ('o','p','s','z'):
1329 if (!FcPatternAddDouble (pat, FC_SIZE, value))
1338 if (!FcPatternAddBool (pat, FC_VARIABLE, variable))
1342 * Get the OS/2 table
1344 os2 = (TT_OS2 *) FT_Get_Sfnt_Table (face, FT_SFNT_OS2);
1347 * Look first in the OS/2 table for the foundry, if
1348 * not found here, the various notices will be searched for
1349 * that information, either from the sfnt name tables or
1350 * the Postscript FontInfo dictionary. Finally, the
1351 * BDF properties will queried.
1354 if (os2 && os2->version >= 0x0001 && os2->version != 0xffff)
1356 if (os2->achVendID && os2->achVendID[0] != 0)
1358 foundry_ = (FcChar8 *) malloc (sizeof (os2->achVendID) + 1);
1359 memcpy ((void *)foundry_, os2->achVendID, sizeof (os2->achVendID));
1360 foundry_[sizeof (os2->achVendID)] = 0;
1365 if (FcDebug () & FC_DBG_SCANV)
1368 * Grub through the name table looking for family
1369 * and style names. FreeType makes quite a hash
1372 for (p = 0; p < NUM_PLATFORM_ORDER; p++)
1374 int platform = platform_order[p];
1377 * Order nameids so preferred names appear first
1378 * in the resulting list
1380 for (n = 0; n < NUM_NAMEID_ORDER; n++)
1383 const FcChar8 *lang;
1384 const char *elt = 0, *eltlang = 0;
1385 int *np = 0, *nlangp = 0;
1387 int nameid, lookupid;
1389 nameid = lookupid = nameid_order[n];
1393 /* For named-instances, we skip regular style nameIDs,
1394 * and treat the instance's nameid as FONT_SUBFAMILY.
1395 * Postscript name is automatically handled by FreeType. */
1396 if (nameid == TT_NAME_ID_WWS_SUBFAMILY ||
1397 nameid == TT_NAME_ID_PREFERRED_SUBFAMILY)
1400 if (nameid == TT_NAME_ID_FONT_SUBFAMILY)
1401 lookupid = instance->strid;
1404 if (!FcFreeTypeGetName (face, platform, lookupid, &sname))
1408 case TT_NAME_ID_WWS_FAMILY:
1409 case TT_NAME_ID_PREFERRED_FAMILY:
1410 case TT_NAME_ID_FONT_FAMILY:
1412 case TT_NAME_ID_UNIQUE_ID:
1414 if (FcDebug () & FC_DBG_SCANV)
1415 printf ("found family (n %2d p %d e %d l 0x%04x)",
1416 sname.name_id, sname.platform_id,
1417 sname.encoding_id, sname.language_id);
1420 eltlang = FC_FAMILYLANG;
1422 nlangp = &nfamily_lang;
1424 case TT_NAME_ID_MAC_FULL_NAME:
1425 case TT_NAME_ID_FULL_NAME:
1426 if (FcDebug () & FC_DBG_SCANV)
1427 printf ("found full (n %2d p %d e %d l 0x%04x)",
1428 sname.name_id, sname.platform_id,
1429 sname.encoding_id, sname.language_id);
1432 eltlang = FC_FULLNAMELANG;
1434 nlangp = &nfullname_lang;
1436 case TT_NAME_ID_WWS_SUBFAMILY:
1437 case TT_NAME_ID_PREFERRED_SUBFAMILY:
1438 case TT_NAME_ID_FONT_SUBFAMILY:
1441 if (FcDebug () & FC_DBG_SCANV)
1442 printf ("found style (n %2d p %d e %d l 0x%04x) ",
1443 sname.name_id, sname.platform_id,
1444 sname.encoding_id, sname.language_id);
1447 eltlang = FC_STYLELANG;
1449 nlangp = &nstyle_lang;
1451 case TT_NAME_ID_TRADEMARK:
1452 case TT_NAME_ID_MANUFACTURER:
1453 /* If the foundry wasn't found in the OS/2 table, look here */
1457 utf8 = FcSfntNameTranscode (&sname);
1458 foundry = FcNoticeFoundry((FT_String *) utf8);
1467 utf8 = FcSfntNameTranscode (&sname);
1468 lang = FcSfntNameLanguage (&sname);
1470 if (FcDebug () & FC_DBG_SCANV)
1471 printf ("%s\n", utf8);
1476 /* Trim surrounding whitespace. */
1480 len = strlen ((const char *) pp);
1481 memmove (utf8, pp, len + 1);
1483 while (pp > utf8 && *(pp - 1) == ' ')
1487 if (FcStringInPatternElement (pat, elt, utf8))
1493 /* add new element */
1494 if (!FcPatternAddString (pat, elt, utf8))
1502 /* pad lang list with 'und' to line up with elt */
1503 while (*nlangp < *np)
1505 if (!FcPatternAddString (pat, eltlang, (FcChar8 *) "und"))
1509 if (!FcPatternAddString (pat, eltlang, lang))
1518 if (!nfamily && face->family_name &&
1519 FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->family_name, (FcChar8 *) "") != 0)
1521 if (FcDebug () & FC_DBG_SCANV)
1522 printf ("using FreeType family \"%s\"\n", face->family_name);
1523 if (!FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) face->family_name))
1525 if (!FcPatternAddString (pat, FC_STYLELANG, (FcChar8 *) "en"))
1530 if (!variable && !nstyle && face->style_name &&
1531 FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->style_name, (FcChar8 *) "") != 0)
1533 if (FcDebug () & FC_DBG_SCANV)
1534 printf ("using FreeType style \"%s\"\n", face->style_name);
1536 if (!FcPatternAddString (pat, FC_STYLE, (FcChar8 *) face->style_name))
1538 if (!FcPatternAddString (pat, FC_STYLELANG, (FcChar8 *) "en"))
1543 if (!nfamily && file && *file)
1545 FcChar8 *start, *end;
1548 start = (FcChar8 *) strrchr ((char *) file, '/');
1552 start = (FcChar8 *) file;
1553 end = (FcChar8 *) strrchr ((char *) start, '.');
1555 end = start + strlen ((char *) start);
1557 family = malloc (end - start + 1);
1558 strncpy ((char *) family, (char *) start, end - start);
1559 family[end - start] = '\0';
1560 if (FcDebug () & FC_DBG_SCANV)
1561 printf ("using filename for family %s\n", family);
1562 if (!FcPatternAddString (pat, FC_FAMILY, family))
1571 /* Add the PostScript name into the cache */
1576 tmp = FT_Get_Postscript_Name (face);
1580 FcChar8 *family, *familylang = NULL;
1584 /* Workaround when FT_Get_Postscript_Name didn't give any name.
1585 * try to find out the English family name and convert.
1587 while (FcPatternObjectGetString (pat, FC_FAMILYLANG_OBJECT, n, &familylang) == FcResultMatch)
1589 if (FcStrCmp (familylang, (const FcChar8 *)"en") == 0)
1597 if (FcPatternObjectGetString (pat, FC_FAMILY_OBJECT, n, &family) != FcResultMatch)
1599 len = strlen ((const char *)family);
1600 /* the literal name in PostScript Language is limited to 127 characters though,
1601 * It is the architectural limit. so assuming 255 characters may works enough.
1603 for (i = 0; i < len && i < 255; i++)
1605 /* those characters are not allowed to be the literal name in PostScript */
1606 static const char exclusive_chars[] = "\x04()/<>[]{}\t\f\r\n ";
1608 if (strchr(exclusive_chars, family[i]) != NULL)
1611 psname[i] = family[i];
1617 strncpy (psname, tmp, 255);
1620 if (!FcPatternAddString (pat, FC_POSTSCRIPT_NAME, (const FcChar8 *)psname))
1624 if (file && *file && !FcPatternAddString (pat, FC_FILE, file))
1627 if (!FcPatternAddInteger (pat, FC_INDEX, id))
1632 * don't even try this -- CJK 'monospace' fonts are really
1633 * dual width, and most other fonts don't bother to set
1634 * the attribute. Sigh.
1636 if ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0)
1637 if (!FcPatternAddInteger (pat, FC_SPACING, FC_MONO))
1642 * Find the font revision (if available)
1644 head = (TT_Header *) FT_Get_Sfnt_Table (face, ft_sfnt_head);
1647 if (!FcPatternAddInteger (pat, FC_FONTVERSION, head->Font_Revision))
1652 if (!FcPatternAddInteger (pat, FC_FONTVERSION, 0))
1656 if (os2 && os2->version >= 0x0001 && os2->version != 0xffff)
1659 for (i = 0; i < NUM_CODE_PAGE_RANGE; i++)
1663 if (FcCodePageRange[i].bit < 32)
1665 bits = os2->ulCodePageRange1;
1666 bit = FcCodePageRange[i].bit;
1670 bits = os2->ulCodePageRange2;
1671 bit = FcCodePageRange[i].bit - 32;
1673 if (bits & (1U << bit))
1676 * If the font advertises support for multiple
1677 * "exclusive" languages, then include support
1678 * for any language found to have coverage
1685 exclusiveLang = FcCodePageRange[i].lang;
1690 if (os2 && os2->version != 0xffff)
1692 weight = os2->usWeightClass;
1693 weight = FcWeightFromOpenTypeDouble (weight * weight_mult);
1694 if ((FcDebug() & FC_DBG_SCANV) && weight != -1)
1695 printf ("\tos2 weight class %d multiplier %g maps to weight %g\n",
1696 os2->usWeightClass, weight_mult, weight);
1698 switch (os2->usWidthClass) {
1699 case 1: width = FC_WIDTH_ULTRACONDENSED; break;
1700 case 2: width = FC_WIDTH_EXTRACONDENSED; break;
1701 case 3: width = FC_WIDTH_CONDENSED; break;
1702 case 4: width = FC_WIDTH_SEMICONDENSED; break;
1703 case 5: width = FC_WIDTH_NORMAL; break;
1704 case 6: width = FC_WIDTH_SEMIEXPANDED; break;
1705 case 7: width = FC_WIDTH_EXPANDED; break;
1706 case 8: width = FC_WIDTH_EXTRAEXPANDED; break;
1707 case 9: width = FC_WIDTH_ULTRAEXPANDED; break;
1709 width *= width_mult;
1710 if ((FcDebug() & FC_DBG_SCANV) && width != -1)
1711 printf ("\tos2 width class %d multiplier %g maps to width %g\n",
1712 os2->usWidthClass, width_mult, width);
1714 if (os2 && (complex_ = FcFontCapabilities(face)))
1716 if (!FcPatternAddString (pat, FC_CAPABILITY, complex_))
1724 if (!variable_size && os2 && os2->version >= 0x0005 && os2->version != 0xffff)
1726 double lower_size, upper_size;
1729 /* usLowerPointSize and usUpperPointSize is actually twips */
1730 lower_size = os2->usLowerOpticalPointSize / 20.0L;
1731 upper_size = os2->usUpperOpticalPointSize / 20.0L;
1733 if (lower_size == upper_size)
1735 if (!FcPatternAddDouble (pat, FC_SIZE, lower_size))
1740 r = FcRangeCreateDouble (lower_size, upper_size);
1741 if (!FcPatternAddRange (pat, FC_SIZE, r))
1751 * Type 1: Check for FontInfo dictionary information
1752 * Code from g2@magestudios.net (Gerard Escalante)
1755 #if HAVE_FT_GET_PS_FONT_INFO
1756 if (FT_Get_PS_Font_Info(face, &psfontinfo) == 0)
1758 if (weight == -1 && psfontinfo.weight)
1760 weight = FcIsWeight ((FcChar8 *) psfontinfo.weight);
1761 if (FcDebug() & FC_DBG_SCANV)
1762 printf ("\tType1 weight %s maps to %g\n",
1763 psfontinfo.weight, weight);
1768 * Don't bother with italic_angle; FreeType already extracts that
1769 * information for us and sticks it into style_flags
1771 if (psfontinfo.italic_angle)
1772 slant = FC_SLANT_ITALIC;
1774 slant = FC_SLANT_ROMAN;
1778 foundry = FcNoticeFoundry(psfontinfo.notice);
1780 #endif /* HAVE_FT_GET_PS_FONT_INFO */
1782 #if HAVE_FT_GET_BDF_PROPERTY
1784 * Finally, look for a FOUNDRY BDF property if no other
1785 * mechanism has managed to locate a foundry
1791 rc = FT_Get_BDF_Property(face, "FOUNDRY", &prop);
1792 if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM)
1793 foundry = (FcChar8 *) prop.u.atom;
1798 if (FT_Get_BDF_Property(face, "RELATIVE_SETWIDTH", &prop) == 0 &&
1799 (prop.type == BDF_PROPERTY_TYPE_INTEGER ||
1800 prop.type == BDF_PROPERTY_TYPE_CARDINAL))
1804 if (prop.type == BDF_PROPERTY_TYPE_INTEGER)
1805 value = prop.u.integer;
1807 value = (FT_Int32) prop.u.cardinal;
1808 switch ((value + 5) / 10) {
1809 case 1: width = FC_WIDTH_ULTRACONDENSED; break;
1810 case 2: width = FC_WIDTH_EXTRACONDENSED; break;
1811 case 3: width = FC_WIDTH_CONDENSED; break;
1812 case 4: width = FC_WIDTH_SEMICONDENSED; break;
1813 case 5: width = FC_WIDTH_NORMAL; break;
1814 case 6: width = FC_WIDTH_SEMIEXPANDED; break;
1815 case 7: width = FC_WIDTH_EXPANDED; break;
1816 case 8: width = FC_WIDTH_EXTRAEXPANDED; break;
1817 case 9: width = FC_WIDTH_ULTRAEXPANDED; break;
1821 FT_Get_BDF_Property (face, "SETWIDTH_NAME", &prop) == 0 &&
1822 prop.type == BDF_PROPERTY_TYPE_ATOM && prop.u.atom != NULL)
1824 width = FcIsWidth ((FcChar8 *) prop.u.atom);
1825 if (FcDebug () & FC_DBG_SCANV)
1826 printf ("\tsetwidth %s maps to %g\n", prop.u.atom, width);
1832 * Look for weight, width and slant names in the style value
1834 for (st = 0; FcPatternGetString (pat, FC_STYLE, st, &style) == FcResultMatch; st++)
1838 weight = FcContainsWeight (style);
1839 if (FcDebug() & FC_DBG_SCANV)
1840 printf ("\tStyle %s maps to weight %g\n", style, weight);
1844 width = FcContainsWidth (style);
1845 if (FcDebug() & FC_DBG_SCANV)
1846 printf ("\tStyle %s maps to width %g\n", style, width);
1850 slant = FcContainsSlant (style);
1851 if (FcDebug() & FC_DBG_SCANV)
1852 printf ("\tStyle %s maps to slant %d\n", style, slant);
1854 if (decorative == FcFalse)
1856 decorative = FcContainsDecorative (style) > 0;
1857 if (FcDebug() & FC_DBG_SCANV)
1858 printf ("\tStyle %s maps to decorative %d\n", style, decorative);
1862 * Pull default values from the FreeType flags if more
1863 * specific values not found above
1867 slant = FC_SLANT_ROMAN;
1868 if (face->style_flags & FT_STYLE_FLAG_ITALIC)
1869 slant = FC_SLANT_ITALIC;
1874 weight = FC_WEIGHT_MEDIUM;
1875 if (face->style_flags & FT_STYLE_FLAG_BOLD)
1876 weight = FC_WEIGHT_BOLD;
1880 width = FC_WIDTH_NORMAL;
1883 foundry = (FcChar8 *) "unknown";
1885 if (!FcPatternAddInteger (pat, FC_SLANT, slant))
1888 if (!variable_weight && !FcPatternAddDouble (pat, FC_WEIGHT, weight))
1891 if (!variable_width && !FcPatternAddDouble (pat, FC_WIDTH, width))
1894 if (!FcPatternAddString (pat, FC_FOUNDRY, foundry))
1897 if (!FcPatternAddBool (pat, FC_DECORATIVE, decorative))
1902 * Compute the unicode coverage for the font
1904 if (cs_share && *cs_share)
1905 cs = FcCharSetCopy (*cs_share);
1908 cs = FcFreeTypeCharSet (face, NULL);
1910 *cs_share = FcCharSetCopy (cs);
1915 /* The FcFreeTypeCharSet() chose the encoding; test it for symbol. */
1916 symbol = face->charmap && face->charmap->encoding == FT_ENCODING_MS_SYMBOL;
1917 if (!FcPatternAddBool (pat, FC_SYMBOL, symbol))
1920 spacing = FcFreeTypeSpacing (face);
1921 #if HAVE_FT_GET_BDF_PROPERTY
1922 /* For PCF fonts, override the computed spacing with the one from
1924 if(FT_Get_BDF_Property(face, "SPACING", &prop) == 0 &&
1925 prop.type == BDF_PROPERTY_TYPE_ATOM && prop.u.atom != NULL) {
1926 if(!strcmp(prop.u.atom, "c") || !strcmp(prop.u.atom, "C"))
1927 spacing = FC_CHARCELL;
1928 else if(!strcmp(prop.u.atom, "m") || !strcmp(prop.u.atom, "M"))
1930 else if(!strcmp(prop.u.atom, "p") || !strcmp(prop.u.atom, "P"))
1931 spacing = FC_PROPORTIONAL;
1936 * Skip over PCF fonts that have no encoded characters; they're
1937 * usually just Unicode fonts transcoded to some legacy encoding
1938 * FT forces us to approximate whether a font is a PCF font
1939 * or not by whether it has any BDF properties. Try PIXEL_SIZE;
1940 * I don't know how to get a list of BDF properties on the font. -PL
1942 if (FcCharSetCount (cs) == 0)
1944 #if HAVE_FT_GET_BDF_PROPERTY
1945 if(FT_Get_BDF_Property(face, "PIXEL_SIZE", &prop) == 0)
1950 if (!FcPatternAddCharSet (pat, FC_CHARSET, cs))
1955 if (ls_share && *ls_share)
1956 ls = FcLangSetCopy (*ls_share);
1959 ls = FcFreeTypeLangSet (cs, exclusiveLang);
1961 *ls_share = FcLangSetCopy (ls);
1968 /* Symbol fonts don't cover any language, even though they
1969 * claim to support Latin1 range. */
1970 ls = FcLangSetCreate ();
1973 if (!FcPatternAddLangSet (pat, FC_LANG, ls))
1975 FcLangSetDestroy (ls);
1979 FcLangSetDestroy (ls);
1981 if (spacing != FC_PROPORTIONAL)
1982 if (!FcPatternAddInteger (pat, FC_SPACING, spacing))
1985 if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
1988 for (i = 0; i < face->num_fixed_sizes; i++)
1989 if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE,
1990 FcGetPixelSize (face, i)))
1992 if (!FcPatternAddBool (pat, FC_ANTIALIAS, FcFalse))
1995 #if HAVE_FT_GET_X11_FONT_FORMAT
1997 * Use the (not well documented or supported) X-specific function
1998 * from FreeType to figure out the font format
2001 const char *font_format = FT_Get_X11_Font_Format (face);
2003 if (!FcPatternAddString (pat, FC_FONTFORMAT, (FcChar8 *) font_format))
2009 * Drop our reference to the charset
2011 FcCharSetDestroy (cs);
2017 /* TODO: How to free master?! */
2023 FcCharSetDestroy (cs);
2025 FcPatternDestroy (pat);
2033 FcFreeTypeQueryFace (const FT_Face face,
2034 const FcChar8 *file,
2036 FcBlanks *blanks FC_UNUSED)
2038 return FcFreeTypeQueryFaceInternal (face, file, id, NULL, NULL);
2042 FcFreeTypeQuery(const FcChar8 *file,
2044 FcBlanks *blanks FC_UNUSED,
2048 FT_Library ftLibrary;
2049 FcPattern *pat = NULL;
2051 if (FT_Init_FreeType (&ftLibrary))
2054 if (FT_New_Face (ftLibrary, (char *) file, id & 0x7FFFFFFFF, &face))
2058 *count = face->num_faces;
2060 pat = FcFreeTypeQueryFaceInternal (face, file, id, NULL, NULL);
2062 FT_Done_Face (face);
2064 FT_Done_FreeType (ftLibrary);
2069 FcFreeTypeQueryAll(const FcChar8 *file,
2075 FT_Face face = NULL;
2076 FT_Library ftLibrary = NULL;
2077 FcCharSet *cs = NULL;
2078 FcLangSet *ls = NULL;
2079 FT_MM_Var *mm_var = NULL;
2080 FcBool index_set = id != (unsigned int) -1;
2081 unsigned int set_face_num = index_set ? id & 0xFFFF : 0;
2082 unsigned int set_instance_num = index_set ? id >> 16 : 0;
2083 unsigned int face_num = set_face_num;
2084 unsigned int instance_num = set_instance_num;
2085 unsigned int num_faces = 0;
2086 unsigned int num_instances = 0;
2087 unsigned int ret = 0;
2093 if (FT_Init_FreeType (&ftLibrary))
2096 if (FT_New_Face (ftLibrary, (const char *) file, face_num, &face))
2099 num_faces = face->num_faces;
2100 num_instances = face->style_flags >> 16;
2101 if (num_instances && (!index_set || instance_num))
2103 FT_Get_MM_Var (face, &mm_var);
2112 FcPattern *pat = NULL;
2114 if (instance_num == 0x8000 || instance_num > num_instances)
2115 FT_Set_Var_Design_Coordinates (face, 0, NULL); /* Reset variations. */
2116 else if (instance_num)
2118 FT_Var_Named_Style *instance = &mm_var->namedstyle[instance_num - 1];
2119 FT_Fixed *coords = instance->coords;
2123 /* Skip named-instance that coincides with base instance. */
2125 for (i = 0; i < mm_var->num_axis; i++)
2126 if (coords[i] != mm_var->axis[i].def)
2134 FT_Set_Var_Design_Coordinates (face, mm_var->num_axis, coords);
2137 id = ((instance_num << 16) + face_num);
2138 pat = FcFreeTypeQueryFaceInternal (face, (const FcChar8 *) file, id, &cs, &ls);
2144 if (!set || ! FcFontSetAdd (set, pat))
2145 FcPatternDestroy (pat);
2147 else if (instance_num != 0x8000)
2151 if (!index_set && instance_num < num_instances)
2153 else if (!index_set && instance_num == num_instances)
2154 instance_num = 0x8000; /* variable font */
2157 FcLangSetDestroy (ls);
2159 FcCharSetDestroy (cs);
2161 FT_Done_Face (face);
2165 instance_num = set_instance_num;
2167 if (FT_New_Face (ftLibrary, (const char *) file, face_num, &face))
2170 } while (!err && (!index_set || face_num == set_face_num) && face_num < num_faces);
2173 #ifdef HAVE_FT_DONE_MM_VAR
2174 FT_Done_MM_Var (ftLibrary, mm_var);
2178 FcLangSetDestroy (ls);
2179 FcCharSetDestroy (cs);
2181 FT_Done_Face (face);
2182 FT_Done_FreeType (ftLibrary);
2188 static const FT_Encoding fcFontEncodings[] = {
2189 FT_ENCODING_UNICODE,
2190 FT_ENCODING_MS_SYMBOL
2193 #define NUM_DECODE (int) (sizeof (fcFontEncodings) / sizeof (fcFontEncodings[0]))
2196 * Map a UCS4 glyph to a glyph index. Use all available encoding
2197 * tables to try and find one that works. This information is expected
2198 * to be cached by higher levels, so performance isn't critical
2202 FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
2204 int initial, offset, decode;
2213 * Find the current encoding
2217 for (; initial < NUM_DECODE; initial++)
2218 if (fcFontEncodings[initial] == face->charmap->encoding)
2220 if (initial == NUM_DECODE)
2224 * Check each encoding for the glyph, starting with the current one
2226 for (offset = 0; offset < NUM_DECODE; offset++)
2228 decode = (initial + offset) % NUM_DECODE;
2229 if (!face->charmap || face->charmap->encoding != fcFontEncodings[decode])
2230 if (FT_Select_Charmap (face, fcFontEncodings[decode]) != 0)
2232 glyphindex = FT_Get_Char_Index (face, (FT_ULong) ucs4);
2235 if (ucs4 < 0x100 && face->charmap &&
2236 face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
2238 /* For symbol-encoded OpenType fonts, we duplicate the
2239 * U+F000..F0FF range at U+0000..U+00FF. That's what
2240 * Windows seems to do, and that's hinted about at:
2241 * http://www.microsoft.com/typography/otspec/recom.htm
2242 * under "Non-Standard (Symbol) Fonts".
2244 * See thread with subject "Webdings and other MS symbol
2245 * fonts don't display" on mailing list from May 2015.
2247 glyphindex = FT_Get_Char_Index (face, (FT_ULong) ucs4 + 0xF000);
2255 static inline int fc_min (int a, int b) { return a <= b ? a : b; }
2256 static inline int fc_max (int a, int b) { return a >= b ? a : b; }
2257 static inline FcBool fc_approximately_equal (int x, int y)
2258 { return abs (x - y) * 33 <= fc_max (abs (x), abs (y)); }
2261 FcFreeTypeSpacing (FT_Face face)
2263 FT_Int load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
2264 FT_Pos advances[3] = {0};
2265 unsigned int num_advances = 0;
2268 /* When using scalable fonts, only report those glyphs
2269 * which can be scaled; otherwise those fonts will
2270 * only be available at some sizes, and never when
2271 * transformed. Avoid this by simply reporting bitmap-only
2274 if (face->face_flags & FT_FACE_FLAG_SCALABLE)
2275 load_flags |= FT_LOAD_NO_BITMAP;
2277 if (!(face->face_flags & FT_FACE_FLAG_SCALABLE) &&
2278 face->num_fixed_sizes > 0 &&
2279 FT_Get_Sfnt_Table (face, ft_sfnt_head))
2281 FT_Int strike_index = 0, i;
2282 /* Select the face closest to 16 pixels tall */
2283 for (i = 1; i < face->num_fixed_sizes; i++)
2285 if (abs (face->available_sizes[i].height - 16) <
2286 abs (face->available_sizes[strike_index].height - 16))
2290 FT_Select_Size (face, strike_index);
2293 for (o = 0; o < NUM_DECODE; o++)
2298 if (FT_Select_Charmap (face, fcFontEncodings[o]) != 0)
2301 ucs4 = FT_Get_First_Char (face, &glyph);
2302 while (glyph != 0 && num_advances < 3)
2305 if (!FT_Get_Advance (face, glyph, load_flags, &advance) && advance)
2308 for (j = 0; j < num_advances; j++)
2309 if (fc_approximately_equal (advance, advances[j]))
2311 if (j == num_advances)
2312 advances[num_advances++] = advance;
2315 ucs4 = FT_Get_Next_Char (face, ucs4, &glyph);
2320 if (num_advances <= 1)
2322 else if (num_advances == 2 &&
2323 fc_approximately_equal (fc_min (advances[0], advances[1]) * 2,
2324 fc_max (advances[0], advances[1])))
2327 return FC_PROPORTIONAL;
2331 FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks FC_UNUSED)
2333 const FT_Int load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
2337 fcs = FcCharSetCreate ();
2342 printf ("Family %s style %s\n", face->family_name, face->style_name);
2344 for (o = 0; o < NUM_DECODE; o++)
2346 FcChar32 page, off, ucs4;
2350 if (FT_Select_Charmap (face, fcFontEncodings[o]) != 0)
2355 ucs4 = FT_Get_First_Char (face, &glyph);
2358 FcBool good = FcTrue;
2360 /* CID fonts built by Adobe used to make ASCII control chars to cid1
2361 * (space glyph). As such, always check contour for those characters. */
2364 if (FT_Load_Glyph (face, glyph, load_flags) ||
2365 (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE &&
2366 face->glyph->outline.n_contours == 0))
2372 FcCharSetAddChar (fcs, ucs4);
2373 if ((ucs4 >> 8) != page)
2376 leaf = FcCharSetFindLeafCreate (fcs, ucs4);
2381 leaf->map[off >> 5] |= (1U << (off & 0x1f));
2384 ucs4 = FT_Get_Next_Char (face, ucs4, &glyph);
2386 if (fcFontEncodings[o] == FT_ENCODING_MS_SYMBOL)
2388 /* For symbol-encoded OpenType fonts, we duplicate the
2389 * U+F000..F0FF range at U+0000..U+00FF. That's what
2390 * Windows seems to do, and that's hinted about at:
2391 * http://www.microsoft.com/typography/otspec/recom.htm
2392 * under "Non-Standard (Symbol) Fonts".
2394 * See thread with subject "Webdings and other MS symbol
2395 * fonts don't display" on mailing list from May 2015.
2397 for (ucs4 = 0xF000; ucs4 < 0xF100; ucs4++)
2399 if (FcCharSetHasChar (fcs, ucs4))
2400 FcCharSetAddChar (fcs, ucs4 - 0xF000);
2404 for (ucs4 = 0x0020; ucs4 < 0x10000; ucs4++)
2406 FcBool FT_Has, FC_Has;
2408 FT_Has = FT_Get_Char_Index (face, ucs4) != 0;
2409 FC_Has = FcCharSetHasChar (fcs, ucs4);
2410 if (FT_Has != FC_Has)
2412 printf ("0x%08x FT says %d FC says %d\n", ucs4, FT_Has, FC_Has);
2421 FcCharSetDestroy (fcs);
2426 FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks FC_UNUSED, int *spacing)
2430 *spacing = FcFreeTypeSpacing (face);
2432 return FcFreeTypeCharSet (face, blanks);
2436 #define TTAG_GPOS FT_MAKE_TAG( 'G', 'P', 'O', 'S' )
2437 #define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' )
2438 #define TTAG_SILF FT_MAKE_TAG( 'S', 'i', 'l', 'f')
2440 #define OTLAYOUT_HEAD "otlayout:"
2441 #define OTLAYOUT_HEAD_LEN 9
2442 #define OTLAYOUT_ID_LEN 4
2443 /* space + head + id */
2444 #define OTLAYOUT_LEN (1 + OTLAYOUT_HEAD_LEN + OTLAYOUT_ID_LEN)
2447 * This is a bit generous; the registry has only lower case and space
2448 * except for 'DFLT'.
2450 #define FcIsSpace(x) (040 == (x))
2451 #define FcIsDigit(c) (('0' <= (c) && (c) <= '9'))
2452 #define FcIsValidScript(x) (FcIsLower(x) || FcIsUpper (x) || FcIsDigit(x) || FcIsSpace(x))
2455 addtag(FcChar8 *complex_, FT_ULong tag)
2457 FcChar8 tagstring[OTLAYOUT_ID_LEN + 1];
2459 tagstring[0] = (FcChar8)(tag >> 24),
2460 tagstring[1] = (FcChar8)(tag >> 16),
2461 tagstring[2] = (FcChar8)(tag >> 8),
2462 tagstring[3] = (FcChar8)(tag);
2463 tagstring[4] = '\0';
2465 /* skip tags which aren't alphanumeric, under the assumption that
2466 * they're probably broken
2468 if (!FcIsValidScript(tagstring[0]) ||
2469 !FcIsValidScript(tagstring[1]) ||
2470 !FcIsValidScript(tagstring[2]) ||
2471 !FcIsValidScript(tagstring[3]))
2474 if (*complex_ != '\0')
2475 strcat ((char *) complex_, " ");
2476 strcat ((char *) complex_, OTLAYOUT_HEAD);
2477 strcat ((char *) complex_, (char *) tagstring);
2481 compareulong (const void *a, const void *b)
2483 const FT_ULong *ua = (const FT_ULong *) a;
2484 const FT_ULong *ub = (const FT_ULong *) b;
2490 GetScriptTags(FT_Face face, FT_ULong tabletag, FT_ULong **stags)
2492 FT_ULong cur_offset, new_offset, base_offset;
2493 FT_Stream stream = face->stream;
2501 if (( error = ftglue_face_goto_table( face, tabletag, stream ) ))
2504 base_offset = ftglue_stream_pos ( stream );
2508 if ( ftglue_stream_seek ( stream, base_offset + 4L ) || ftglue_stream_frame_enter( stream, 2L ) )
2511 new_offset = GET_UShort() + base_offset;
2513 ftglue_stream_frame_exit( stream );
2515 cur_offset = ftglue_stream_pos( stream );
2517 if ( ftglue_stream_seek( stream, new_offset ) != FT_Err_Ok )
2520 base_offset = ftglue_stream_pos( stream );
2522 if ( ftglue_stream_frame_enter( stream, 2L ) )
2525 script_count = GET_UShort ();
2527 ftglue_stream_frame_exit( stream );
2529 *stags = malloc(script_count * sizeof (FT_ULong));
2534 for ( n = 0; n < script_count; n++ )
2536 if ( ftglue_stream_frame_enter( stream, 6L ) )
2539 (*stags)[p] = GET_ULong ();
2540 new_offset = GET_UShort () + base_offset;
2542 ftglue_stream_frame_exit( stream );
2544 cur_offset = ftglue_stream_pos( stream );
2546 error = ftglue_stream_seek( stream, new_offset );
2548 if ( error == FT_Err_Ok )
2551 (void)ftglue_stream_seek( stream, cur_offset );
2557 /* sort the tag list before returning it */
2558 qsort(*stags, script_count, sizeof(FT_ULong), compareulong);
2560 return script_count;
2569 FcFontCapabilities(FT_Face face)
2571 FcBool issilgraphitefont = 0;
2574 FT_ULong *gsubtags=NULL, *gpostags=NULL;
2575 FT_UShort gsub_count=0, gpos_count=0;
2577 FcChar8 *complex_ = NULL;
2578 int indx1 = 0, indx2 = 0;
2580 err = FT_Load_Sfnt_Table(face, TTAG_SILF, 0, 0, &len);
2581 issilgraphitefont = ( err == FT_Err_Ok);
2583 gpos_count = GetScriptTags(face, TTAG_GPOS, &gpostags);
2584 gsub_count = GetScriptTags(face, TTAG_GSUB, &gsubtags);
2586 if (!issilgraphitefont && !gsub_count && !gpos_count)
2589 maxsize = (((FT_ULong) gpos_count + (FT_ULong) gsub_count) * OTLAYOUT_LEN +
2590 (issilgraphitefont ? 13 : 0));
2591 complex_ = malloc (sizeof (FcChar8) * maxsize);
2596 if (issilgraphitefont)
2597 strcpy((char *) complex_, "ttable:Silf ");
2599 while ((indx1 < gsub_count) || (indx2 < gpos_count)) {
2600 if (indx1 == gsub_count) {
2601 addtag(complex_, gpostags[indx2]);
2603 } else if ((indx2 == gpos_count) || (gsubtags[indx1] < gpostags[indx2])) {
2604 addtag(complex_, gsubtags[indx1]);
2606 } else if (gsubtags[indx1] == gpostags[indx2]) {
2607 addtag(complex_, gsubtags[indx1]);
2611 addtag(complex_, gpostags[indx2]);
2615 if (FcDebug () & FC_DBG_SCANV)
2616 printf("complex_ features in this font: %s\n", complex_);
2623 #define __fcfreetype__
2624 #include "fcaliastail.h"
2625 #include "fcftaliastail.h"
2626 #undef __fcfreetype__