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]))
1141 unsigned int platform_id;
1142 unsigned int name_id;
1143 unsigned int encoding_id;
1144 unsigned int language_id;
1149 name_mapping_cmp (const void *pa, const void *pb)
1151 const FcNameMapping *a = (const FcNameMapping *) pa;
1152 const FcNameMapping *b = (const FcNameMapping *) pb;
1154 if (a->platform_id != b->platform_id) return (int) a->platform_id - (int) b->platform_id;
1155 if (a->name_id != b->name_id) return (int) a->name_id - (int) b->name_id;
1156 if (a->encoding_id != b->encoding_id) return (int) a->encoding_id - (int) b->encoding_id;
1157 if (a->language_id != b->language_id) return (int) a->language_id - (int) b->language_id;
1158 if (a->idx != b->idx) return (int) a->idx - (int) b->idx;
1164 FcFreeTypeGetFirstName (const FT_Face face,
1165 unsigned int platform,
1166 unsigned int nameid,
1167 FcNameMapping *mapping,
1171 int min = 0, max = (int) count - 1;
1175 int mid = (min + max) / 2;
1177 if (FT_Get_Sfnt_Name (face, mapping[mid].idx, sname) != 0)
1180 if (platform < sname->platform_id ||
1181 (platform == sname->platform_id &&
1182 (nameid < sname->name_id ||
1183 (nameid == sname->name_id &&
1185 platform == mapping[mid - 1].platform_id &&
1186 nameid == mapping[mid - 1].name_id
1189 else if (platform > sname->platform_id ||
1190 (platform == sname->platform_id &&
1191 nameid > sname->name_id))
1201 FcFreeTypeQueryFaceInternal (const FT_Face face,
1202 const FcChar8 *file,
1204 FcCharSet **cs_share,
1205 FcLangSet **ls_share,
1206 FcNameMapping **nm_share)
1212 FcBool decorative = FcFalse;
1213 FcBool variable = FcFalse;
1214 FcBool variable_weight = FcFalse;
1215 FcBool variable_width = FcFalse;
1216 FcBool variable_size = FcFalse;
1219 FcNameMapping *name_mapping = NULL;
1221 FcChar8 *family = 0;
1223 FcChar8 *complex_, *foundry_ = NULL;
1224 const FcChar8 *foundry = 0;
1227 /* Support for glyph-variation named-instances. */
1228 FT_MM_Var *master = NULL;
1229 FT_Var_Named_Style *instance = NULL;
1230 double weight_mult = 1.0;
1231 double width_mult = 1.0;
1234 #if HAVE_FT_GET_PS_FONT_INFO
1235 PS_FontInfoRec psfontinfo;
1237 #if HAVE_FT_GET_BDF_PROPERTY
1238 BDF_PropertyRec prop;
1241 const FcChar8 *exclusiveLang = 0;
1245 int nfamily_lang = 0;
1247 int nstyle_lang = 0;
1249 int nfullname_lang = 0;
1255 FcBool symbol = FcFalse;
1257 FcInitDebug (); /* We might be called with no initizalization whatsoever. */
1259 pat = FcPatternCreate ();
1264 int has_outline = !!(face->face_flags & FT_FACE_FLAG_SCALABLE);
1267 if (!FcPatternAddBool (pat, FC_OUTLINE, has_outline))
1270 has_color = FT_HAS_COLOR (face);
1271 if (!FcPatternAddBool (pat, FC_COLOR, has_color))
1274 /* All color fonts are designed to be scaled, even if they only have
1275 * bitmap strikes. Client is responsible to scale the bitmaps. This
1276 * is in constrast to non-color strikes... */
1277 if (!FcPatternAddBool (pat, FC_SCALABLE, has_outline || has_color))
1283 if (FT_Get_MM_Var (face, &master))
1286 if (id >> 16 == 0x8000)
1288 /* Query variable font itself. */
1291 for (i = 0; i < master->num_axis; i++)
1293 double min_value = master->axis[i].minimum / (double) (1U << 16);
1294 double def_value = master->axis[i].def / (double) (1U << 16);
1295 double max_value = master->axis[i].maximum / (double) (1U << 16);
1296 const char *elt = NULL;
1298 if (min_value > def_value || def_value > max_value || min_value == max_value)
1301 switch (master->axis[i].tag)
1303 case FT_MAKE_TAG ('w','g','h','t'):
1305 min_value = FcWeightFromOpenTypeDouble (min_value);
1306 max_value = FcWeightFromOpenTypeDouble (max_value);
1307 variable_weight = FcTrue;
1308 weight = 0; /* To stop looking for weight. */
1311 case FT_MAKE_TAG ('w','d','t','h'):
1313 /* Values in 'wdth' match Fontconfig FC_WIDTH_* scheme directly. */
1314 variable_width = FcTrue;
1315 width = 0; /* To stop looking for width. */
1318 case FT_MAKE_TAG ('o','p','s','z'):
1320 /* Values in 'opsz' match Fontconfig FC_SIZE, both are in points. */
1321 variable_size = FcTrue;
1327 FcRange *r = FcRangeCreateDouble (min_value, max_value);
1328 if (!FcPatternAddRange (pat, elt, r))
1343 else if ((id >> 16) - 1 < master->num_namedstyles)
1345 /* Pull out weight and width from named-instance. */
1348 instance = &master->namedstyle[(id >> 16) - 1];
1350 for (i = 0; i < master->num_axis; i++)
1352 double value = instance->coords[i] / (double) (1U << 16);
1353 double default_value = master->axis[i].def / (double) (1U << 16);
1354 double mult = default_value ? value / default_value : 1;
1355 //printf ("named-instance, axis %d tag %lx value %g\n", i, master->axis[i].tag, value);
1356 switch (master->axis[i].tag)
1358 case FT_MAKE_TAG ('w','g','h','t'):
1362 case FT_MAKE_TAG ('w','d','t','h'):
1366 case FT_MAKE_TAG ('o','p','s','z'):
1367 if (!FcPatternAddDouble (pat, FC_SIZE, value))
1376 if (!FcPatternAddBool (pat, FC_VARIABLE, variable))
1380 * Get the OS/2 table
1382 os2 = (TT_OS2 *) FT_Get_Sfnt_Table (face, FT_SFNT_OS2);
1385 * Look first in the OS/2 table for the foundry, if
1386 * not found here, the various notices will be searched for
1387 * that information, either from the sfnt name tables or
1388 * the Postscript FontInfo dictionary. Finally, the
1389 * BDF properties will queried.
1392 if (os2 && os2->version >= 0x0001 && os2->version != 0xffff)
1394 if (os2->achVendID && os2->achVendID[0] != 0)
1396 foundry_ = (FcChar8 *) malloc (sizeof (os2->achVendID) + 1);
1397 memcpy ((void *)foundry_, os2->achVendID, sizeof (os2->achVendID));
1398 foundry_[sizeof (os2->achVendID)] = 0;
1403 if (FcDebug () & FC_DBG_SCANV)
1406 * Grub through the name table looking for family
1407 * and style names. FreeType makes quite a hash
1410 name_count = FT_Get_Sfnt_Name_Count (face);
1412 name_mapping = *nm_share;
1416 name_mapping = malloc (name_count * sizeof (FcNameMapping));
1419 for (i = 0; i < name_count; i++)
1421 FcNameMapping *p = &name_mapping[i];
1423 if (FT_Get_Sfnt_Name (face, i, &sname) == 0)
1425 p->platform_id = sname.platform_id;
1426 p->name_id = sname.name_id;
1427 p->encoding_id = sname.encoding_id;
1428 p->language_id = sname.language_id;
1437 p->idx = (unsigned int) -1;
1440 qsort (name_mapping, name_count, sizeof(FcNameMapping), name_mapping_cmp);
1443 *nm_share = name_mapping;
1445 for (p = 0; p < NUM_PLATFORM_ORDER; p++)
1447 int platform = platform_order[p];
1450 * Order nameids so preferred names appear first
1451 * in the resulting list
1453 for (n = 0; n < NUM_NAMEID_ORDER; n++)
1457 const FcChar8 *lang;
1458 const char *elt = 0, *eltlang = 0;
1459 int *np = 0, *nlangp = 0;
1461 int nameid, lookupid;
1463 nameid = lookupid = nameid_order[n];
1467 /* For named-instances, we skip regular style nameIDs,
1468 * and treat the instance's nameid as FONT_SUBFAMILY.
1469 * Postscript name is automatically handled by FreeType. */
1470 if (nameid == TT_NAME_ID_WWS_SUBFAMILY ||
1471 nameid == TT_NAME_ID_PREFERRED_SUBFAMILY)
1474 if (nameid == TT_NAME_ID_FONT_SUBFAMILY)
1475 lookupid = instance->strid;
1478 nameidx = FcFreeTypeGetFirstName (face, platform, lookupid,
1479 name_mapping, name_count,
1486 case TT_NAME_ID_WWS_FAMILY:
1487 case TT_NAME_ID_PREFERRED_FAMILY:
1488 case TT_NAME_ID_FONT_FAMILY:
1490 case TT_NAME_ID_UNIQUE_ID:
1492 if (FcDebug () & FC_DBG_SCANV)
1493 printf ("found family (n %2d p %d e %d l 0x%04x)",
1494 sname.name_id, sname.platform_id,
1495 sname.encoding_id, sname.language_id);
1498 eltlang = FC_FAMILYLANG;
1500 nlangp = &nfamily_lang;
1502 case TT_NAME_ID_MAC_FULL_NAME:
1503 case TT_NAME_ID_FULL_NAME:
1504 if (FcDebug () & FC_DBG_SCANV)
1505 printf ("found full (n %2d p %d e %d l 0x%04x)",
1506 sname.name_id, sname.platform_id,
1507 sname.encoding_id, sname.language_id);
1510 eltlang = FC_FULLNAMELANG;
1512 nlangp = &nfullname_lang;
1514 case TT_NAME_ID_WWS_SUBFAMILY:
1515 case TT_NAME_ID_PREFERRED_SUBFAMILY:
1516 case TT_NAME_ID_FONT_SUBFAMILY:
1519 if (FcDebug () & FC_DBG_SCANV)
1520 printf ("found style (n %2d p %d e %d l 0x%04x) ",
1521 sname.name_id, sname.platform_id,
1522 sname.encoding_id, sname.language_id);
1525 eltlang = FC_STYLELANG;
1527 nlangp = &nstyle_lang;
1529 case TT_NAME_ID_TRADEMARK:
1530 case TT_NAME_ID_MANUFACTURER:
1531 /* If the foundry wasn't found in the OS/2 table, look here */
1535 utf8 = FcSfntNameTranscode (&sname);
1536 foundry = FcNoticeFoundry((FT_String *) utf8);
1545 utf8 = FcSfntNameTranscode (&sname);
1546 lang = FcSfntNameLanguage (&sname);
1548 if (FcDebug () & FC_DBG_SCANV)
1549 printf ("%s\n", utf8);
1554 /* Trim surrounding whitespace. */
1558 len = strlen ((const char *) pp);
1559 memmove (utf8, pp, len + 1);
1561 while (pp > utf8 && *(pp - 1) == ' ')
1565 if (FcStringInPatternElement (pat, elt, utf8))
1571 /* add new element */
1572 if (!FcPatternAddString (pat, elt, utf8))
1580 /* pad lang list with 'und' to line up with elt */
1581 while (*nlangp < *np)
1583 if (!FcPatternAddString (pat, eltlang, (FcChar8 *) "und"))
1587 if (!FcPatternAddString (pat, eltlang, lang))
1594 while (++nameidx < name_count &&
1595 FT_Get_Sfnt_Name (face, name_mapping[nameidx].idx, &sname) == 0 &&
1596 platform == sname.platform_id && lookupid == sname.name_id);
1600 free (name_mapping);
1602 if (!nfamily && face->family_name &&
1603 FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->family_name, (FcChar8 *) "") != 0)
1605 if (FcDebug () & FC_DBG_SCANV)
1606 printf ("using FreeType family \"%s\"\n", face->family_name);
1607 if (!FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) face->family_name))
1609 if (!FcPatternAddString (pat, FC_STYLELANG, (FcChar8 *) "en"))
1614 if (!variable && !nstyle && face->style_name &&
1615 FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->style_name, (FcChar8 *) "") != 0)
1617 if (FcDebug () & FC_DBG_SCANV)
1618 printf ("using FreeType style \"%s\"\n", face->style_name);
1620 if (!FcPatternAddString (pat, FC_STYLE, (FcChar8 *) face->style_name))
1622 if (!FcPatternAddString (pat, FC_STYLELANG, (FcChar8 *) "en"))
1627 if (!nfamily && file && *file)
1629 FcChar8 *start, *end;
1632 start = (FcChar8 *) strrchr ((char *) file, '/');
1636 start = (FcChar8 *) file;
1637 end = (FcChar8 *) strrchr ((char *) start, '.');
1639 end = start + strlen ((char *) start);
1641 family = malloc (end - start + 1);
1642 strncpy ((char *) family, (char *) start, end - start);
1643 family[end - start] = '\0';
1644 if (FcDebug () & FC_DBG_SCANV)
1645 printf ("using filename for family %s\n", family);
1646 if (!FcPatternAddString (pat, FC_FAMILY, family))
1655 /* Add the PostScript name into the cache */
1660 tmp = FT_Get_Postscript_Name (face);
1664 FcChar8 *family, *familylang = NULL;
1668 /* Workaround when FT_Get_Postscript_Name didn't give any name.
1669 * try to find out the English family name and convert.
1671 while (FcPatternObjectGetString (pat, FC_FAMILYLANG_OBJECT, n, &familylang) == FcResultMatch)
1673 if (FcStrCmp (familylang, (const FcChar8 *)"en") == 0)
1681 if (FcPatternObjectGetString (pat, FC_FAMILY_OBJECT, n, &family) != FcResultMatch)
1683 len = strlen ((const char *)family);
1684 /* the literal name in PostScript Language is limited to 127 characters though,
1685 * It is the architectural limit. so assuming 255 characters may works enough.
1687 for (i = 0; i < len && i < 255; i++)
1689 /* those characters are not allowed to be the literal name in PostScript */
1690 static const char exclusive_chars[] = "\x04()/<>[]{}\t\f\r\n ";
1692 if (strchr(exclusive_chars, family[i]) != NULL)
1695 psname[i] = family[i];
1701 strncpy (psname, tmp, 255);
1704 if (!FcPatternAddString (pat, FC_POSTSCRIPT_NAME, (const FcChar8 *)psname))
1708 if (file && *file && !FcPatternAddString (pat, FC_FILE, file))
1711 if (!FcPatternAddInteger (pat, FC_INDEX, id))
1716 * don't even try this -- CJK 'monospace' fonts are really
1717 * dual width, and most other fonts don't bother to set
1718 * the attribute. Sigh.
1720 if ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0)
1721 if (!FcPatternAddInteger (pat, FC_SPACING, FC_MONO))
1726 * Find the font revision (if available)
1728 head = (TT_Header *) FT_Get_Sfnt_Table (face, ft_sfnt_head);
1731 if (!FcPatternAddInteger (pat, FC_FONTVERSION, head->Font_Revision))
1736 if (!FcPatternAddInteger (pat, FC_FONTVERSION, 0))
1740 if (os2 && os2->version >= 0x0001 && os2->version != 0xffff)
1743 for (i = 0; i < NUM_CODE_PAGE_RANGE; i++)
1747 if (FcCodePageRange[i].bit < 32)
1749 bits = os2->ulCodePageRange1;
1750 bit = FcCodePageRange[i].bit;
1754 bits = os2->ulCodePageRange2;
1755 bit = FcCodePageRange[i].bit - 32;
1757 if (bits & (1U << bit))
1760 * If the font advertises support for multiple
1761 * "exclusive" languages, then include support
1762 * for any language found to have coverage
1769 exclusiveLang = FcCodePageRange[i].lang;
1774 if (os2 && os2->version != 0xffff)
1776 weight = os2->usWeightClass;
1777 weight = FcWeightFromOpenTypeDouble (weight * weight_mult);
1778 if ((FcDebug() & FC_DBG_SCANV) && weight != -1)
1779 printf ("\tos2 weight class %d multiplier %g maps to weight %g\n",
1780 os2->usWeightClass, weight_mult, weight);
1782 switch (os2->usWidthClass) {
1783 case 1: width = FC_WIDTH_ULTRACONDENSED; break;
1784 case 2: width = FC_WIDTH_EXTRACONDENSED; break;
1785 case 3: width = FC_WIDTH_CONDENSED; break;
1786 case 4: width = FC_WIDTH_SEMICONDENSED; break;
1787 case 5: width = FC_WIDTH_NORMAL; break;
1788 case 6: width = FC_WIDTH_SEMIEXPANDED; break;
1789 case 7: width = FC_WIDTH_EXPANDED; break;
1790 case 8: width = FC_WIDTH_EXTRAEXPANDED; break;
1791 case 9: width = FC_WIDTH_ULTRAEXPANDED; break;
1793 width *= width_mult;
1794 if ((FcDebug() & FC_DBG_SCANV) && width != -1)
1795 printf ("\tos2 width class %d multiplier %g maps to width %g\n",
1796 os2->usWidthClass, width_mult, width);
1798 if (os2 && (complex_ = FcFontCapabilities(face)))
1800 if (!FcPatternAddString (pat, FC_CAPABILITY, complex_))
1808 if (!variable_size && os2 && os2->version >= 0x0005 && os2->version != 0xffff)
1810 double lower_size, upper_size;
1813 /* usLowerPointSize and usUpperPointSize is actually twips */
1814 lower_size = os2->usLowerOpticalPointSize / 20.0L;
1815 upper_size = os2->usUpperOpticalPointSize / 20.0L;
1817 if (lower_size == upper_size)
1819 if (!FcPatternAddDouble (pat, FC_SIZE, lower_size))
1824 r = FcRangeCreateDouble (lower_size, upper_size);
1825 if (!FcPatternAddRange (pat, FC_SIZE, r))
1835 * Type 1: Check for FontInfo dictionary information
1836 * Code from g2@magestudios.net (Gerard Escalante)
1839 #if HAVE_FT_GET_PS_FONT_INFO
1840 if (FT_Get_PS_Font_Info(face, &psfontinfo) == 0)
1842 if (weight == -1 && psfontinfo.weight)
1844 weight = FcIsWeight ((FcChar8 *) psfontinfo.weight);
1845 if (FcDebug() & FC_DBG_SCANV)
1846 printf ("\tType1 weight %s maps to %g\n",
1847 psfontinfo.weight, weight);
1852 * Don't bother with italic_angle; FreeType already extracts that
1853 * information for us and sticks it into style_flags
1855 if (psfontinfo.italic_angle)
1856 slant = FC_SLANT_ITALIC;
1858 slant = FC_SLANT_ROMAN;
1862 foundry = FcNoticeFoundry(psfontinfo.notice);
1864 #endif /* HAVE_FT_GET_PS_FONT_INFO */
1866 #if HAVE_FT_GET_BDF_PROPERTY
1868 * Finally, look for a FOUNDRY BDF property if no other
1869 * mechanism has managed to locate a foundry
1875 rc = FT_Get_BDF_Property(face, "FOUNDRY", &prop);
1876 if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM)
1877 foundry = (FcChar8 *) prop.u.atom;
1882 if (FT_Get_BDF_Property(face, "RELATIVE_SETWIDTH", &prop) == 0 &&
1883 (prop.type == BDF_PROPERTY_TYPE_INTEGER ||
1884 prop.type == BDF_PROPERTY_TYPE_CARDINAL))
1888 if (prop.type == BDF_PROPERTY_TYPE_INTEGER)
1889 value = prop.u.integer;
1891 value = (FT_Int32) prop.u.cardinal;
1892 switch ((value + 5) / 10) {
1893 case 1: width = FC_WIDTH_ULTRACONDENSED; break;
1894 case 2: width = FC_WIDTH_EXTRACONDENSED; break;
1895 case 3: width = FC_WIDTH_CONDENSED; break;
1896 case 4: width = FC_WIDTH_SEMICONDENSED; break;
1897 case 5: width = FC_WIDTH_NORMAL; break;
1898 case 6: width = FC_WIDTH_SEMIEXPANDED; break;
1899 case 7: width = FC_WIDTH_EXPANDED; break;
1900 case 8: width = FC_WIDTH_EXTRAEXPANDED; break;
1901 case 9: width = FC_WIDTH_ULTRAEXPANDED; break;
1905 FT_Get_BDF_Property (face, "SETWIDTH_NAME", &prop) == 0 &&
1906 prop.type == BDF_PROPERTY_TYPE_ATOM && prop.u.atom != NULL)
1908 width = FcIsWidth ((FcChar8 *) prop.u.atom);
1909 if (FcDebug () & FC_DBG_SCANV)
1910 printf ("\tsetwidth %s maps to %g\n", prop.u.atom, width);
1916 * Look for weight, width and slant names in the style value
1918 for (st = 0; FcPatternGetString (pat, FC_STYLE, st, &style) == FcResultMatch; st++)
1922 weight = FcContainsWeight (style);
1923 if (FcDebug() & FC_DBG_SCANV)
1924 printf ("\tStyle %s maps to weight %g\n", style, weight);
1928 width = FcContainsWidth (style);
1929 if (FcDebug() & FC_DBG_SCANV)
1930 printf ("\tStyle %s maps to width %g\n", style, width);
1934 slant = FcContainsSlant (style);
1935 if (FcDebug() & FC_DBG_SCANV)
1936 printf ("\tStyle %s maps to slant %d\n", style, slant);
1938 if (decorative == FcFalse)
1940 decorative = FcContainsDecorative (style) > 0;
1941 if (FcDebug() & FC_DBG_SCANV)
1942 printf ("\tStyle %s maps to decorative %d\n", style, decorative);
1946 * Pull default values from the FreeType flags if more
1947 * specific values not found above
1951 slant = FC_SLANT_ROMAN;
1952 if (face->style_flags & FT_STYLE_FLAG_ITALIC)
1953 slant = FC_SLANT_ITALIC;
1958 weight = FC_WEIGHT_MEDIUM;
1959 if (face->style_flags & FT_STYLE_FLAG_BOLD)
1960 weight = FC_WEIGHT_BOLD;
1964 width = FC_WIDTH_NORMAL;
1967 foundry = (FcChar8 *) "unknown";
1969 if (!FcPatternAddInteger (pat, FC_SLANT, slant))
1972 if (!variable_weight && !FcPatternAddDouble (pat, FC_WEIGHT, weight))
1975 if (!variable_width && !FcPatternAddDouble (pat, FC_WIDTH, width))
1978 if (!FcPatternAddString (pat, FC_FOUNDRY, foundry))
1981 if (!FcPatternAddBool (pat, FC_DECORATIVE, decorative))
1986 * Compute the unicode coverage for the font
1988 if (cs_share && *cs_share)
1989 cs = FcCharSetCopy (*cs_share);
1992 cs = FcFreeTypeCharSet (face, NULL);
1994 *cs_share = FcCharSetCopy (cs);
1999 /* The FcFreeTypeCharSet() chose the encoding; test it for symbol. */
2000 symbol = face->charmap && face->charmap->encoding == FT_ENCODING_MS_SYMBOL;
2001 if (!FcPatternAddBool (pat, FC_SYMBOL, symbol))
2004 spacing = FcFreeTypeSpacing (face);
2005 #if HAVE_FT_GET_BDF_PROPERTY
2006 /* For PCF fonts, override the computed spacing with the one from
2008 if(FT_Get_BDF_Property(face, "SPACING", &prop) == 0 &&
2009 prop.type == BDF_PROPERTY_TYPE_ATOM && prop.u.atom != NULL) {
2010 if(!strcmp(prop.u.atom, "c") || !strcmp(prop.u.atom, "C"))
2011 spacing = FC_CHARCELL;
2012 else if(!strcmp(prop.u.atom, "m") || !strcmp(prop.u.atom, "M"))
2014 else if(!strcmp(prop.u.atom, "p") || !strcmp(prop.u.atom, "P"))
2015 spacing = FC_PROPORTIONAL;
2020 * Skip over PCF fonts that have no encoded characters; they're
2021 * usually just Unicode fonts transcoded to some legacy encoding
2022 * FT forces us to approximate whether a font is a PCF font
2023 * or not by whether it has any BDF properties. Try PIXEL_SIZE;
2024 * I don't know how to get a list of BDF properties on the font. -PL
2026 if (FcCharSetCount (cs) == 0)
2028 #if HAVE_FT_GET_BDF_PROPERTY
2029 if(FT_Get_BDF_Property(face, "PIXEL_SIZE", &prop) == 0)
2034 if (!FcPatternAddCharSet (pat, FC_CHARSET, cs))
2039 if (ls_share && *ls_share)
2040 ls = FcLangSetCopy (*ls_share);
2043 ls = FcFreeTypeLangSet (cs, exclusiveLang);
2045 *ls_share = FcLangSetCopy (ls);
2052 /* Symbol fonts don't cover any language, even though they
2053 * claim to support Latin1 range. */
2054 ls = FcLangSetCreate ();
2057 if (!FcPatternAddLangSet (pat, FC_LANG, ls))
2059 FcLangSetDestroy (ls);
2063 FcLangSetDestroy (ls);
2065 if (spacing != FC_PROPORTIONAL)
2066 if (!FcPatternAddInteger (pat, FC_SPACING, spacing))
2069 if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
2072 for (i = 0; i < face->num_fixed_sizes; i++)
2073 if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE,
2074 FcGetPixelSize (face, i)))
2076 if (!FcPatternAddBool (pat, FC_ANTIALIAS, FcFalse))
2079 #if HAVE_FT_GET_X11_FONT_FORMAT
2081 * Use the (not well documented or supported) X-specific function
2082 * from FreeType to figure out the font format
2085 const char *font_format = FT_Get_X11_Font_Format (face);
2087 if (!FcPatternAddString (pat, FC_FONTFORMAT, (FcChar8 *) font_format))
2093 * Drop our reference to the charset
2095 FcCharSetDestroy (cs);
2101 /* TODO: How to free master?! */
2107 FcCharSetDestroy (cs);
2109 FcPatternDestroy (pat);
2117 FcFreeTypeQueryFace (const FT_Face face,
2118 const FcChar8 *file,
2120 FcBlanks *blanks FC_UNUSED)
2122 return FcFreeTypeQueryFaceInternal (face, file, id, NULL, NULL, NULL);
2126 FcFreeTypeQuery(const FcChar8 *file,
2128 FcBlanks *blanks FC_UNUSED,
2132 FT_Library ftLibrary;
2133 FcPattern *pat = NULL;
2135 if (FT_Init_FreeType (&ftLibrary))
2138 if (FT_New_Face (ftLibrary, (char *) file, id & 0x7FFFFFFFF, &face))
2142 *count = face->num_faces;
2144 pat = FcFreeTypeQueryFaceInternal (face, file, id, NULL, NULL, NULL);
2146 FT_Done_Face (face);
2148 FT_Done_FreeType (ftLibrary);
2153 FcFreeTypeQueryAll(const FcChar8 *file,
2159 FT_Face face = NULL;
2160 FT_Library ftLibrary = NULL;
2161 FcCharSet *cs = NULL;
2162 FcLangSet *ls = NULL;
2163 FcNameMapping *nm = NULL;
2164 FT_MM_Var *mm_var = NULL;
2165 FcBool index_set = id != (unsigned int) -1;
2166 unsigned int set_face_num = index_set ? id & 0xFFFF : 0;
2167 unsigned int set_instance_num = index_set ? id >> 16 : 0;
2168 unsigned int face_num = set_face_num;
2169 unsigned int instance_num = set_instance_num;
2170 unsigned int num_faces = 0;
2171 unsigned int num_instances = 0;
2172 unsigned int ret = 0;
2178 if (FT_Init_FreeType (&ftLibrary))
2181 if (FT_New_Face (ftLibrary, (const char *) file, face_num, &face))
2184 num_faces = face->num_faces;
2185 num_instances = face->style_flags >> 16;
2186 if (num_instances && (!index_set || instance_num))
2188 FT_Get_MM_Var (face, &mm_var);
2197 FcPattern *pat = NULL;
2199 if (instance_num == 0x8000 || instance_num > num_instances)
2200 FT_Set_Var_Design_Coordinates (face, 0, NULL); /* Reset variations. */
2201 else if (instance_num)
2203 FT_Var_Named_Style *instance = &mm_var->namedstyle[instance_num - 1];
2204 FT_Fixed *coords = instance->coords;
2208 /* Skip named-instance that coincides with base instance. */
2210 for (i = 0; i < mm_var->num_axis; i++)
2211 if (coords[i] != mm_var->axis[i].def)
2219 FT_Set_Var_Design_Coordinates (face, mm_var->num_axis, coords);
2222 id = ((instance_num << 16) + face_num);
2223 pat = FcFreeTypeQueryFaceInternal (face, (const FcChar8 *) file, id, &cs, &ls, &nm);
2229 if (!set || ! FcFontSetAdd (set, pat))
2230 FcPatternDestroy (pat);
2232 else if (instance_num != 0x8000)
2236 if (!index_set && instance_num < num_instances)
2238 else if (!index_set && instance_num == num_instances)
2239 instance_num = 0x8000; /* variable font */
2244 FcLangSetDestroy (ls);
2246 FcCharSetDestroy (cs);
2248 FT_Done_Face (face);
2252 instance_num = set_instance_num;
2254 if (FT_New_Face (ftLibrary, (const char *) file, face_num, &face))
2257 } while (!err && (!index_set || face_num == set_face_num) && face_num < num_faces);
2260 #ifdef HAVE_FT_DONE_MM_VAR
2261 FT_Done_MM_Var (ftLibrary, mm_var);
2265 FcLangSetDestroy (ls);
2266 FcCharSetDestroy (cs);
2268 FT_Done_Face (face);
2269 FT_Done_FreeType (ftLibrary);
2275 static const FT_Encoding fcFontEncodings[] = {
2276 FT_ENCODING_UNICODE,
2277 FT_ENCODING_MS_SYMBOL
2280 #define NUM_DECODE (int) (sizeof (fcFontEncodings) / sizeof (fcFontEncodings[0]))
2283 * Map a UCS4 glyph to a glyph index. Use all available encoding
2284 * tables to try and find one that works. This information is expected
2285 * to be cached by higher levels, so performance isn't critical
2289 FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
2291 int initial, offset, decode;
2300 * Find the current encoding
2304 for (; initial < NUM_DECODE; initial++)
2305 if (fcFontEncodings[initial] == face->charmap->encoding)
2307 if (initial == NUM_DECODE)
2311 * Check each encoding for the glyph, starting with the current one
2313 for (offset = 0; offset < NUM_DECODE; offset++)
2315 decode = (initial + offset) % NUM_DECODE;
2316 if (!face->charmap || face->charmap->encoding != fcFontEncodings[decode])
2317 if (FT_Select_Charmap (face, fcFontEncodings[decode]) != 0)
2319 glyphindex = FT_Get_Char_Index (face, (FT_ULong) ucs4);
2322 if (ucs4 < 0x100 && face->charmap &&
2323 face->charmap->encoding == FT_ENCODING_MS_SYMBOL)
2325 /* For symbol-encoded OpenType fonts, we duplicate the
2326 * U+F000..F0FF range at U+0000..U+00FF. That's what
2327 * Windows seems to do, and that's hinted about at:
2328 * http://www.microsoft.com/typography/otspec/recom.htm
2329 * under "Non-Standard (Symbol) Fonts".
2331 * See thread with subject "Webdings and other MS symbol
2332 * fonts don't display" on mailing list from May 2015.
2334 glyphindex = FT_Get_Char_Index (face, (FT_ULong) ucs4 + 0xF000);
2342 static inline int fc_min (int a, int b) { return a <= b ? a : b; }
2343 static inline int fc_max (int a, int b) { return a >= b ? a : b; }
2344 static inline FcBool fc_approximately_equal (int x, int y)
2345 { return abs (x - y) * 33 <= fc_max (abs (x), abs (y)); }
2348 FcFreeTypeSpacing (FT_Face face)
2350 FT_Int load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
2351 FT_Pos advances[3] = {0};
2352 unsigned int num_advances = 0;
2355 /* When using scalable fonts, only report those glyphs
2356 * which can be scaled; otherwise those fonts will
2357 * only be available at some sizes, and never when
2358 * transformed. Avoid this by simply reporting bitmap-only
2361 if (face->face_flags & FT_FACE_FLAG_SCALABLE)
2362 load_flags |= FT_LOAD_NO_BITMAP;
2364 if (!(face->face_flags & FT_FACE_FLAG_SCALABLE) &&
2365 face->num_fixed_sizes > 0 &&
2366 FT_Get_Sfnt_Table (face, ft_sfnt_head))
2368 FT_Int strike_index = 0, i;
2369 /* Select the face closest to 16 pixels tall */
2370 for (i = 1; i < face->num_fixed_sizes; i++)
2372 if (abs (face->available_sizes[i].height - 16) <
2373 abs (face->available_sizes[strike_index].height - 16))
2377 FT_Select_Size (face, strike_index);
2380 for (o = 0; o < NUM_DECODE; o++)
2385 if (FT_Select_Charmap (face, fcFontEncodings[o]) != 0)
2388 ucs4 = FT_Get_First_Char (face, &glyph);
2389 while (glyph != 0 && num_advances < 3)
2392 if (!FT_Get_Advance (face, glyph, load_flags, &advance) && advance)
2395 for (j = 0; j < num_advances; j++)
2396 if (fc_approximately_equal (advance, advances[j]))
2398 if (j == num_advances)
2399 advances[num_advances++] = advance;
2402 ucs4 = FT_Get_Next_Char (face, ucs4, &glyph);
2407 if (num_advances <= 1)
2409 else if (num_advances == 2 &&
2410 fc_approximately_equal (fc_min (advances[0], advances[1]) * 2,
2411 fc_max (advances[0], advances[1])))
2414 return FC_PROPORTIONAL;
2418 FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks FC_UNUSED)
2420 const FT_Int load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
2424 fcs = FcCharSetCreate ();
2429 printf ("Family %s style %s\n", face->family_name, face->style_name);
2431 for (o = 0; o < NUM_DECODE; o++)
2433 FcChar32 page, off, ucs4;
2437 if (FT_Select_Charmap (face, fcFontEncodings[o]) != 0)
2442 ucs4 = FT_Get_First_Char (face, &glyph);
2445 FcBool good = FcTrue;
2447 /* CID fonts built by Adobe used to make ASCII control chars to cid1
2448 * (space glyph). As such, always check contour for those characters. */
2451 if (FT_Load_Glyph (face, glyph, load_flags) ||
2452 (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE &&
2453 face->glyph->outline.n_contours == 0))
2459 FcCharSetAddChar (fcs, ucs4);
2460 if ((ucs4 >> 8) != page)
2463 leaf = FcCharSetFindLeafCreate (fcs, ucs4);
2468 leaf->map[off >> 5] |= (1U << (off & 0x1f));
2471 ucs4 = FT_Get_Next_Char (face, ucs4, &glyph);
2473 if (fcFontEncodings[o] == FT_ENCODING_MS_SYMBOL)
2475 /* For symbol-encoded OpenType fonts, we duplicate the
2476 * U+F000..F0FF range at U+0000..U+00FF. That's what
2477 * Windows seems to do, and that's hinted about at:
2478 * http://www.microsoft.com/typography/otspec/recom.htm
2479 * under "Non-Standard (Symbol) Fonts".
2481 * See thread with subject "Webdings and other MS symbol
2482 * fonts don't display" on mailing list from May 2015.
2484 for (ucs4 = 0xF000; ucs4 < 0xF100; ucs4++)
2486 if (FcCharSetHasChar (fcs, ucs4))
2487 FcCharSetAddChar (fcs, ucs4 - 0xF000);
2491 for (ucs4 = 0x0020; ucs4 < 0x10000; ucs4++)
2493 FcBool FT_Has, FC_Has;
2495 FT_Has = FT_Get_Char_Index (face, ucs4) != 0;
2496 FC_Has = FcCharSetHasChar (fcs, ucs4);
2497 if (FT_Has != FC_Has)
2499 printf ("0x%08x FT says %d FC says %d\n", ucs4, FT_Has, FC_Has);
2508 FcCharSetDestroy (fcs);
2513 FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks FC_UNUSED, int *spacing)
2517 *spacing = FcFreeTypeSpacing (face);
2519 return FcFreeTypeCharSet (face, blanks);
2523 #define TTAG_GPOS FT_MAKE_TAG( 'G', 'P', 'O', 'S' )
2524 #define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' )
2525 #define TTAG_SILF FT_MAKE_TAG( 'S', 'i', 'l', 'f')
2527 #define OTLAYOUT_HEAD "otlayout:"
2528 #define OTLAYOUT_HEAD_LEN 9
2529 #define OTLAYOUT_ID_LEN 4
2530 /* space + head + id */
2531 #define OTLAYOUT_LEN (1 + OTLAYOUT_HEAD_LEN + OTLAYOUT_ID_LEN)
2534 * This is a bit generous; the registry has only lower case and space
2535 * except for 'DFLT'.
2537 #define FcIsSpace(x) (040 == (x))
2538 #define FcIsDigit(c) (('0' <= (c) && (c) <= '9'))
2539 #define FcIsValidScript(x) (FcIsLower(x) || FcIsUpper (x) || FcIsDigit(x) || FcIsSpace(x))
2542 addtag(FcChar8 *complex_, FT_ULong tag)
2544 FcChar8 tagstring[OTLAYOUT_ID_LEN + 1];
2546 tagstring[0] = (FcChar8)(tag >> 24),
2547 tagstring[1] = (FcChar8)(tag >> 16),
2548 tagstring[2] = (FcChar8)(tag >> 8),
2549 tagstring[3] = (FcChar8)(tag);
2550 tagstring[4] = '\0';
2552 /* skip tags which aren't alphanumeric, under the assumption that
2553 * they're probably broken
2555 if (!FcIsValidScript(tagstring[0]) ||
2556 !FcIsValidScript(tagstring[1]) ||
2557 !FcIsValidScript(tagstring[2]) ||
2558 !FcIsValidScript(tagstring[3]))
2561 if (*complex_ != '\0')
2562 strcat ((char *) complex_, " ");
2563 strcat ((char *) complex_, OTLAYOUT_HEAD);
2564 strcat ((char *) complex_, (char *) tagstring);
2568 compareulong (const void *a, const void *b)
2570 const FT_ULong *ua = (const FT_ULong *) a;
2571 const FT_ULong *ub = (const FT_ULong *) b;
2577 GetScriptTags(FT_Face face, FT_ULong tabletag, FT_ULong **stags)
2579 FT_ULong cur_offset, new_offset, base_offset;
2580 FT_Stream stream = face->stream;
2588 if (( error = ftglue_face_goto_table( face, tabletag, stream ) ))
2591 base_offset = ftglue_stream_pos ( stream );
2595 if ( ftglue_stream_seek ( stream, base_offset + 4L ) || ftglue_stream_frame_enter( stream, 2L ) )
2598 new_offset = GET_UShort() + base_offset;
2600 ftglue_stream_frame_exit( stream );
2602 cur_offset = ftglue_stream_pos( stream );
2604 if ( ftglue_stream_seek( stream, new_offset ) != FT_Err_Ok )
2607 base_offset = ftglue_stream_pos( stream );
2609 if ( ftglue_stream_frame_enter( stream, 2L ) )
2612 script_count = GET_UShort ();
2614 ftglue_stream_frame_exit( stream );
2616 *stags = malloc(script_count * sizeof (FT_ULong));
2621 for ( n = 0; n < script_count; n++ )
2623 if ( ftglue_stream_frame_enter( stream, 6L ) )
2626 (*stags)[p] = GET_ULong ();
2627 new_offset = GET_UShort () + base_offset;
2629 ftglue_stream_frame_exit( stream );
2631 cur_offset = ftglue_stream_pos( stream );
2633 error = ftglue_stream_seek( stream, new_offset );
2635 if ( error == FT_Err_Ok )
2638 (void)ftglue_stream_seek( stream, cur_offset );
2644 /* sort the tag list before returning it */
2645 qsort(*stags, script_count, sizeof(FT_ULong), compareulong);
2647 return script_count;
2656 FcFontCapabilities(FT_Face face)
2658 FcBool issilgraphitefont = 0;
2661 FT_ULong *gsubtags=NULL, *gpostags=NULL;
2662 FT_UShort gsub_count=0, gpos_count=0;
2664 FcChar8 *complex_ = NULL;
2665 int indx1 = 0, indx2 = 0;
2667 err = FT_Load_Sfnt_Table(face, TTAG_SILF, 0, 0, &len);
2668 issilgraphitefont = ( err == FT_Err_Ok);
2670 gpos_count = GetScriptTags(face, TTAG_GPOS, &gpostags);
2671 gsub_count = GetScriptTags(face, TTAG_GSUB, &gsubtags);
2673 if (!issilgraphitefont && !gsub_count && !gpos_count)
2676 maxsize = (((FT_ULong) gpos_count + (FT_ULong) gsub_count) * OTLAYOUT_LEN +
2677 (issilgraphitefont ? 13 : 0));
2678 complex_ = malloc (sizeof (FcChar8) * maxsize);
2683 if (issilgraphitefont)
2684 strcpy((char *) complex_, "ttable:Silf ");
2686 while ((indx1 < gsub_count) || (indx2 < gpos_count)) {
2687 if (indx1 == gsub_count) {
2688 addtag(complex_, gpostags[indx2]);
2690 } else if ((indx2 == gpos_count) || (gsubtags[indx1] < gpostags[indx2])) {
2691 addtag(complex_, gsubtags[indx1]);
2693 } else if (gsubtags[indx1] == gpostags[indx2]) {
2694 addtag(complex_, gsubtags[indx1]);
2698 addtag(complex_, gpostags[indx2]);
2702 if (FcDebug () & FC_DBG_SCANV)
2703 printf("complex_ features in this font: %s\n", complex_);
2710 #define __fcfreetype__
2711 #include "fcaliastail.h"
2712 #include "fcftaliastail.h"
2713 #undef __fcfreetype__