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 Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
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_TRUETYPE_TABLES_H
55 #include FT_SFNT_NAMES_H
56 #include FT_TRUETYPE_IDS_H
57 #include FT_TYPE1_TABLES_H
58 #if HAVE_FT_GET_X11_FONT_FORMAT
61 #if HAVE_FT_GET_BDF_PROPERTY
68 #if HAVE_WARNING_CPP_DIRECTIVE
69 #if !HAVE_FT_GET_BDF_PROPERTY
70 #warning "No FT_Get_BDF_Property: Please install freetype 2.1.4 or later"
73 #if !HAVE_FT_GET_PS_FONT_INFO
74 #warning "No FT_Get_PS_Font_Info: Please install freetype 2.1.1 or later"
79 * Keep Han languages separated by eliminating languages
80 * that the codePageRange bits says aren't supported
85 const FcChar8 lang
[6];
86 } FcCodePageRange
[] = {
93 #define NUM_CODE_PAGE_RANGE (int) (sizeof FcCodePageRange / sizeof FcCodePageRange[0])
96 FcFreeTypeIsExclusiveLang (const FcChar8
*lang
)
100 for (i
= 0; i
< NUM_CODE_PAGE_RANGE
; i
++)
102 if (FcLangCompare (lang
, FcCodePageRange
[i
].lang
) == FcLangEqual
)
109 const FT_UShort platform_id
;
110 const FT_UShort encoding_id
;
111 const char fromcode
[12];
114 #define TT_ENCODING_DONT_CARE 0xffff
115 #define FC_ENCODING_MAC_ROMAN "MACINTOSH"
117 static const FcFtEncoding fcFtEncoding
[] = {
118 { TT_PLATFORM_APPLE_UNICODE
, TT_ENCODING_DONT_CARE
, "UCS-2BE" },
119 { TT_PLATFORM_MACINTOSH
, TT_MAC_ID_ROMAN
, "MACINTOSH" },
120 { TT_PLATFORM_MACINTOSH
, TT_MAC_ID_JAPANESE
, "SJIS" },
121 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_UNICODE_CS
, "UTF-16BE" },
122 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_SJIS
, "SJIS-WIN" },
123 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_GB2312
, "GB3212" },
124 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_BIG_5
, "BIG-5" },
125 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_WANSUNG
, "Wansung" },
126 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_JOHAB
, "Johab" },
127 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_UCS_4
, "UCS4" },
128 { TT_PLATFORM_ISO
, TT_ISO_ID_7BIT_ASCII
, "ASCII" },
129 { TT_PLATFORM_ISO
, TT_ISO_ID_10646
, "UCS-2BE" },
130 { TT_PLATFORM_ISO
, TT_ISO_ID_8859_1
, "ISO-8859-1" },
133 #define NUM_FC_FT_ENCODING (int) (sizeof (fcFtEncoding) / sizeof (fcFtEncoding[0]))
136 const FT_UShort platform_id
;
137 const FT_UShort language_id
;
141 #define TT_LANGUAGE_DONT_CARE 0xffff
143 static const FcFtLanguage fcFtLanguage
[] = {
144 { TT_PLATFORM_APPLE_UNICODE
, TT_LANGUAGE_DONT_CARE
, "" },
145 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ENGLISH
, "en" },
146 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_FRENCH
, "fr" },
147 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GERMAN
, "de" },
148 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ITALIAN
, "it" },
149 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_DUTCH
, "nl" },
150 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SWEDISH
, "sv" },
151 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SPANISH
, "es" },
152 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_DANISH
, "da" },
153 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_PORTUGUESE
, "pt" },
154 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_NORWEGIAN
, "no" },
155 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_HEBREW
, "he" },
156 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_JAPANESE
, "ja" },
157 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ARABIC
, "ar" },
158 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_FINNISH
, "fi" },
159 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GREEK
, "el" },
160 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ICELANDIC
, "is" },
161 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MALTESE
, "mt" },
162 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TURKISH
, "tr" },
163 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CROATIAN
, "hr" },
164 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CHINESE_TRADITIONAL
, "zh-tw" },
165 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_URDU
, "ur" },
166 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_HINDI
, "hi" },
167 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_THAI
, "th" },
168 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KOREAN
, "ko" },
169 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_LITHUANIAN
, "lt" },
170 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_POLISH
, "pl" },
171 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_HUNGARIAN
, "hu" },
172 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ESTONIAN
, "et" },
173 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_LETTISH
, "lv" },
174 /* { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SAAMISK, ??? */
175 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_FAEROESE
, "fo" },
176 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_FARSI
, "fa" },
177 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_RUSSIAN
, "ru" },
178 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CHINESE_SIMPLIFIED
, "zh-cn" },
179 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_FLEMISH
, "nl" },
180 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_IRISH
, "ga" },
181 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ALBANIAN
, "sq" },
182 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ROMANIAN
, "ro" },
183 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CZECH
, "cs" },
184 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SLOVAK
, "sk" },
185 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SLOVENIAN
, "sl" },
186 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_YIDDISH
, "yi" },
187 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SERBIAN
, "sr" },
188 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MACEDONIAN
, "mk" },
189 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BULGARIAN
, "bg" },
190 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_UKRAINIAN
, "uk" },
191 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BYELORUSSIAN
, "be" },
192 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_UZBEK
, "uz" },
193 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KAZAKH
, "kk" },
194 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AZERBAIJANI
, "az" },
195 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT
, "az" },
196 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT
, "ar" },
197 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ARMENIAN
, "hy" },
198 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GEORGIAN
, "ka" },
199 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MOLDAVIAN
, "mo" },
200 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KIRGHIZ
, "ky" },
201 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TAJIKI
, "tg" },
202 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TURKMEN
, "tk" },
203 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MONGOLIAN
, "mo" },
204 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT
,"mo" },
205 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT
, "mo" },
206 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_PASHTO
, "ps" },
207 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KURDISH
, "ku" },
208 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KASHMIRI
, "ks" },
209 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SINDHI
, "sd" },
210 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TIBETAN
, "bo" },
211 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_NEPALI
, "ne" },
212 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SANSKRIT
, "sa" },
213 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MARATHI
, "mr" },
214 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BENGALI
, "bn" },
215 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ASSAMESE
, "as" },
216 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GUJARATI
, "gu" },
217 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_PUNJABI
, "pa" },
218 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ORIYA
, "or" },
219 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MALAYALAM
, "ml" },
220 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KANNADA
, "kn" },
221 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TAMIL
, "ta" },
222 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TELUGU
, "te" },
223 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SINHALESE
, "si" },
224 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BURMESE
, "my" },
225 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KHMER
, "km" },
226 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_LAO
, "lo" },
227 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_VIETNAMESE
, "vi" },
228 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_INDONESIAN
, "id" },
229 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TAGALOG
, "tl" },
230 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MALAY_ROMAN_SCRIPT
, "ms" },
231 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MALAY_ARABIC_SCRIPT
, "ms" },
232 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AMHARIC
, "am" },
233 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TIGRINYA
, "ti" },
234 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GALLA
, "om" },
235 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SOMALI
, "so" },
236 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SWAHILI
, "sw" },
237 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_RUANDA
, "rw" },
238 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_RUNDI
, "rn" },
239 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CHEWA
, "ny" },
240 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MALAGASY
, "mg" },
241 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ESPERANTO
, "eo" },
242 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_WELSH
, "cy" },
243 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BASQUE
, "eu" },
244 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CATALAN
, "ca" },
245 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_LATIN
, "la" },
246 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_QUECHUA
, "qu" },
247 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GUARANI
, "gn" },
248 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AYMARA
, "ay" },
249 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TATAR
, "tt" },
250 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_UIGHUR
, "ug" },
251 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_DZONGKHA
, "dz" },
252 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_JAVANESE
, "jw" },
253 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SUNDANESE
, "su" },
255 #if 0 /* these seem to be errors that have been dropped */
257 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SCOTTISH_GAELIC
},
258 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_IRISH_GAELIC
},
262 /* The following codes are new as of 2000-03-10 */
263 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GALICIAN
, "gl" },
264 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AFRIKAANS
, "af" },
265 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BRETON
, "br" },
266 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_INUKTITUT
, "iu" },
267 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SCOTTISH_GAELIC
, "gd" },
268 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MANX_GAELIC
, "gv" },
269 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_IRISH_GAELIC
, "ga" },
270 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TONGAN
, "to" },
271 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GREEK_POLYTONIC
, "el" },
272 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GREELANDIC
, "ik" },
273 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT
,"az" },
275 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_SAUDI_ARABIA
, "ar" },
276 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_IRAQ
, "ar" },
277 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_EGYPT
, "ar" },
278 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_LIBYA
, "ar" },
279 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_ALGERIA
, "ar" },
280 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_MOROCCO
, "ar" },
281 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_TUNISIA
, "ar" },
282 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_OMAN
, "ar" },
283 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_YEMEN
, "ar" },
284 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_SYRIA
, "ar" },
285 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_JORDAN
, "ar" },
286 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_LEBANON
, "ar" },
287 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_KUWAIT
, "ar" },
288 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_UAE
, "ar" },
289 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_BAHRAIN
, "ar" },
290 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_QATAR
, "ar" },
291 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BULGARIAN_BULGARIA
, "bg" },
292 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CATALAN_SPAIN
, "ca" },
293 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_TAIWAN
, "zh-tw" },
294 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_PRC
, "zh-cn" },
295 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_HONG_KONG
, "zh-hk" },
296 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_SINGAPORE
, "zh-sg" },
298 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_MACAU
, "zh-mo" },
300 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CZECH_CZECH_REPUBLIC
, "cs" },
301 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_DANISH_DENMARK
, "da" },
302 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GERMAN_GERMANY
, "de" },
303 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GERMAN_SWITZERLAND
, "de" },
304 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GERMAN_AUSTRIA
, "de" },
305 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GERMAN_LUXEMBOURG
, "de" },
306 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GERMAN_LIECHTENSTEI
, "de" },
307 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GREEK_GREECE
, "el" },
308 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_UNITED_STATES
, "en" },
309 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_UNITED_KINGDOM
, "en" },
310 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_AUSTRALIA
, "en" },
311 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_CANADA
, "en" },
312 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_NEW_ZEALAND
, "en" },
313 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_IRELAND
, "en" },
314 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_SOUTH_AFRICA
, "en" },
315 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_JAMAICA
, "en" },
316 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_CARIBBEAN
, "en" },
317 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_BELIZE
, "en" },
318 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_TRINIDAD
, "en" },
319 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_ZIMBABWE
, "en" },
320 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_PHILIPPINES
, "en" },
321 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT
,"es" },
322 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_MEXICO
, "es" },
323 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT
,"es" },
324 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_GUATEMALA
, "es" },
325 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_COSTA_RICA
, "es" },
326 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_PANAMA
, "es" },
327 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC
,"es" },
328 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_VENEZUELA
, "es" },
329 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_COLOMBIA
, "es" },
330 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_PERU
, "es" },
331 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_ARGENTINA
, "es" },
332 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_ECUADOR
, "es" },
333 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_CHILE
, "es" },
334 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_URUGUAY
, "es" },
335 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_PARAGUAY
, "es" },
336 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_BOLIVIA
, "es" },
337 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_EL_SALVADOR
, "es" },
338 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_HONDURAS
, "es" },
339 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_NICARAGUA
, "es" },
340 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_PUERTO_RICO
, "es" },
341 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FINNISH_FINLAND
, "fi" },
342 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_FRANCE
, "fr" },
343 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_BELGIUM
, "fr" },
344 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_CANADA
, "fr" },
345 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_SWITZERLAND
, "fr" },
346 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_LUXEMBOURG
, "fr" },
347 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_MONACO
, "fr" },
348 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_HEBREW_ISRAEL
, "he" },
349 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_HUNGARIAN_HUNGARY
, "hu" },
350 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ICELANDIC_ICELAND
, "is" },
351 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ITALIAN_ITALY
, "it" },
352 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ITALIAN_SWITZERLAND
, "it" },
353 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_JAPANESE_JAPAN
, "ja" },
354 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA
,"ko" },
355 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KOREAN_JOHAB_KOREA
, "ko" },
356 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_DUTCH_NETHERLANDS
, "nl" },
357 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_DUTCH_BELGIUM
, "nl" },
358 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL
, "no" },
359 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK
, "nn" },
360 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_POLISH_POLAND
, "pl" },
361 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PORTUGUESE_BRAZIL
, "pt" },
362 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PORTUGUESE_PORTUGAL
, "pt" },
363 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND
,"rm" },
364 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ROMANIAN_ROMANIA
, "ro" },
365 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MOLDAVIAN_MOLDAVIA
, "mo" },
366 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_RUSSIAN_RUSSIA
, "ru" },
367 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_RUSSIAN_MOLDAVIA
, "ru" },
368 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CROATIAN_CROATIA
, "hr" },
369 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SERBIAN_SERBIA_LATIN
, "sr" },
370 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC
, "sr" },
371 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SLOVAK_SLOVAKIA
, "sk" },
372 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ALBANIAN_ALBANIA
, "sq" },
373 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SWEDISH_SWEDEN
, "sv" },
374 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SWEDISH_FINLAND
, "sv" },
375 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_THAI_THAILAND
, "th" },
376 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TURKISH_TURKEY
, "tr" },
377 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_URDU_PAKISTAN
, "ur" },
378 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_INDONESIAN_INDONESIA
, "id" },
379 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_UKRAINIAN_UKRAINE
, "uk" },
380 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BELARUSIAN_BELARUS
, "be" },
381 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SLOVENE_SLOVENIA
, "sl" },
382 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ESTONIAN_ESTONIA
, "et" },
383 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_LATVIAN_LATVIA
, "lv" },
384 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_LITHUANIAN_LITHUANIA
, "lt" },
385 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA
,"lt" },
387 #ifdef TT_MS_LANGID_MAORI_NEW_ZELAND
388 /* this seems to be an error that have been dropped */
389 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MAORI_NEW_ZEALAND
, "mi" },
392 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FARSI_IRAN
, "fa" },
393 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_VIETNAMESE_VIET_NAM
, "vi" },
394 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARMENIAN_ARMENIA
, "hy" },
395 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN
, "az" },
396 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC
, "az" },
397 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BASQUE_SPAIN
, "eu" },
398 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SORBIAN_GERMANY
, "wen" },
399 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MACEDONIAN_MACEDONIA
, "mk" },
400 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SUTU_SOUTH_AFRICA
, "st" },
401 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TSONGA_SOUTH_AFRICA
, "ts" },
402 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TSWANA_SOUTH_AFRICA
, "tn" },
403 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_VENDA_SOUTH_AFRICA
, "ven" },
404 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_XHOSA_SOUTH_AFRICA
, "xh" },
405 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ZULU_SOUTH_AFRICA
, "zu" },
406 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA
, "af" },
407 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GEORGIAN_GEORGIA
, "ka" },
408 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS
, "fo" },
409 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_HINDI_INDIA
, "hi" },
410 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MALTESE_MALTA
, "mt" },
411 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SAAMI_LAPONIA
, "se" },
413 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM
,"gd" },
414 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_IRISH_GAELIC_IRELAND
, "ga" },
416 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MALAY_MALAYSIA
, "ms" },
417 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM
, "ms" },
418 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KAZAK_KAZAKSTAN
, "kk" },
419 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SWAHILI_KENYA
, "sw" },
420 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN
, "uz" },
421 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC
, "uz" },
422 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TATAR_TATARSTAN
, "tt" },
423 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BENGALI_INDIA
, "bn" },
424 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PUNJABI_INDIA
, "pa" },
425 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GUJARATI_INDIA
, "gu" },
426 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ORIYA_INDIA
, "or" },
427 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TAMIL_INDIA
, "ta" },
428 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TELUGU_INDIA
, "te" },
429 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KANNADA_INDIA
, "kn" },
430 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MALAYALAM_INDIA
, "ml" },
431 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ASSAMESE_INDIA
, "as" },
432 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MARATHI_INDIA
, "mr" },
433 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SANSKRIT_INDIA
, "sa" },
434 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KONKANI_INDIA
, "kok" },
436 /* new as of 2001-01-01 */
437 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_GENERAL
, "ar" },
438 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_GENERAL
, "zh" },
439 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_GENERAL
, "en" },
440 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_WEST_INDIES
, "fr" },
441 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_REUNION
, "fr" },
442 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_CONGO
, "fr" },
444 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_SENEGAL
, "fr" },
445 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_CAMEROON
, "fr" },
446 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_COTE_D_IVOIRE
, "fr" },
447 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_MALI
, "fr" },
448 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA
,"bs" },
449 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_URDU_INDIA
, "ur" },
450 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TAJIK_TAJIKISTAN
, "tg" },
451 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_YIDDISH_GERMANY
, "yi" },
452 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN
, "ky" },
454 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TURKMEN_TURKMENISTAN
, "tk" },
455 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MONGOLIAN_MONGOLIA
, "mn" },
457 /* the following seems to be inconsistent;
458 here is the current "official" way: */
459 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TIBETAN_BHUTAN
, "bo" },
460 /* and here is what is used by Passport SDK */
461 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TIBETAN_CHINA
, "bo" },
462 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_DZONGHKA_BHUTAN
, "dz" },
463 /* end of inconsistency */
465 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_WELSH_WALES
, "cy" },
466 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KHMER_CAMBODIA
, "km" },
467 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_LAO_LAOS
, "lo" },
468 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BURMESE_MYANMAR
, "my" },
469 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GALICIAN_SPAIN
, "gl" },
470 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MANIPURI_INDIA
, "mni" },
471 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SINDHI_INDIA
, "sd" },
472 /* the following one is only encountered in Microsoft RTF specification */
473 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KASHMIRI_PAKISTAN
, "ks" },
474 /* the following one is not in the Passport list, looks like an omission */
475 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KASHMIRI_INDIA
, "ks" },
476 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_NEPALI_NEPAL
, "ne" },
477 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_NEPALI_INDIA
, "ne" },
478 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRISIAN_NETHERLANDS
, "fy" },
480 /* new as of 2001-03-01 (from Office Xp) */
481 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_HONG_KONG
, "en" },
482 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_INDIA
, "en" },
483 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_MALAYSIA
, "en" },
484 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_SINGAPORE
, "en" },
485 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SYRIAC_SYRIA
, "syr" },
486 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SINHALESE_SRI_LANKA
, "si" },
487 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHEROKEE_UNITED_STATES
, "chr" },
488 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_INUKTITUT_CANADA
, "iu" },
489 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_AMHARIC_ETHIOPIA
, "am" },
491 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TAMAZIGHT_MOROCCO
},
492 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN
},
494 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PASHTO_AFGHANISTAN
, "ps" },
495 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FILIPINO_PHILIPPINES
, "phi" },
496 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_DHIVEHI_MALDIVES
, "div" },
498 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_OROMO_ETHIOPIA
, "om" },
499 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TIGRIGNA_ETHIOPIA
, "ti" },
500 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TIGRIGNA_ERYTHREA
, "ti" },
502 /* New additions from Windows Xp/Passport SDK 2001-11-10. */
504 /* don't ask what this one means... It is commented out currently. */
506 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GREEK_GREECE2
},
509 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_UNITED_STATES
, "es" },
510 /* The following two IDs blatantly violate MS specs by using a */
511 /* sublanguage >,. */
512 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_LATIN_AMERICA
, "es" },
513 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_NORTH_AFRICA
, "fr" },
515 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_MOROCCO
, "fr" },
516 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_HAITI
, "fr" },
517 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BENGALI_BANGLADESH
, "bn" },
518 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN
, "ar" },
519 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN
,"mn" },
521 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_EDO_NIGERIA
},
522 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FULFULDE_NIGERIA
},
523 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_IBIBIO_NIGERIA
},
525 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_HAUSA_NIGERIA
, "ha" },
526 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_YORUBA_NIGERIA
, "yo" },
527 /* language codes from, to, are (still) unknown. */
528 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_IGBO_NIGERIA
, "ibo" },
529 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KANURI_NIGERIA
, "kau" },
530 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GUARANI_PARAGUAY
, "gn" },
531 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_HAWAIIAN_UNITED_STATES
, "haw" },
532 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_LATIN
, "la" },
533 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SOMALI_SOMALIA
, "so" },
535 /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */
536 /* not written (but OTOH the peculiar writing system is worth */
538 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_YI_CHINA
},
540 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES
,"pap" },
543 #define NUM_FC_FT_LANGUAGE (int) (sizeof (fcFtLanguage) / sizeof (fcFtLanguage[0]))
546 FT_UShort language_id
;
550 static const FcMacRomanFake fcMacRomanFake
[] = {
551 { TT_MS_LANGID_JAPANESE_JAPAN
, "SJIS-WIN" },
552 { TT_MS_LANGID_ENGLISH_UNITED_STATES
, "ASCII" },
556 FcFontCapabilities(FT_Face face
);
558 #define NUM_FC_MAC_ROMAN_FAKE (int) (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0]))
565 * A shift-JIS will have many high bits turned on
568 FcLooksLikeSJIS (FcChar8
*string
, int len
)
570 int nhigh
= 0, nlow
= 0;
574 if (*string
++ & 0x80) nhigh
++;
578 * Heuristic -- if more than 1/3 of the bytes have the high-bit set,
579 * this is likely to be SJIS and not ROMAN
581 if (nhigh
* 2 > nlow
)
587 FcSfntNameTranscode (FT_SfntName
*sname
)
590 const char *fromcode
;
596 for (i
= 0; i
< NUM_FC_FT_ENCODING
; i
++)
597 if (fcFtEncoding
[i
].platform_id
== sname
->platform_id
&&
598 (fcFtEncoding
[i
].encoding_id
== TT_ENCODING_DONT_CARE
||
599 fcFtEncoding
[i
].encoding_id
== sname
->encoding_id
))
601 if (i
== NUM_FC_FT_ENCODING
)
603 fromcode
= fcFtEncoding
[i
].fromcode
;
606 * Many names encoded for TT_PLATFORM_MACINTOSH are broken
607 * in various ways. Kludge around them.
609 if (!strcmp (fromcode
, FC_ENCODING_MAC_ROMAN
))
611 if (sname
->language_id
== TT_MAC_LANGID_ENGLISH
&&
612 FcLooksLikeSJIS (sname
->string
, sname
->string_len
))
616 else if (sname
->language_id
>= 0x100)
619 * "real" Mac language IDs are all less than 150.
620 * Names using one of the MS language IDs are assumed
621 * to use an associated encoding (Yes, this is a kludge)
626 for (f
= 0; f
< NUM_FC_MAC_ROMAN_FAKE
; f
++)
627 if (fcMacRomanFake
[f
].language_id
== sname
->language_id
)
629 fromcode
= fcMacRomanFake
[f
].fromcode
;
636 if (!strcmp (fromcode
, "UCS-2BE") || !strcmp (fromcode
, "UTF-16BE"))
638 FcChar8
*src
= sname
->string
;
639 int src_len
= sname
->string_len
;
647 * Convert Utf16 to Utf8
650 if (!FcUtf16Len (src
, FcEndianBig
, src_len
, &len
, &wchar
))
654 * Allocate plenty of space. Freed below
656 utf8
= malloc (len
* FC_UTF8_MAX_LEN
+ 1);
662 while ((ilen
= FcUtf16ToUcs4 (src
, FcEndianBig
, &ucs4
, src_len
)) > 0)
666 olen
= FcUcs4ToUtf8 (ucs4
, u8
);
672 if (!strcmp (fromcode
, "ASCII") || !strcmp (fromcode
, "ISO-8859-1"))
674 FcChar8
*src
= sname
->string
;
675 int src_len
= sname
->string_len
;
681 * Convert Latin1 to Utf8. Freed below
683 utf8
= malloc (src_len
* 2 + 1);
692 olen
= FcUcs4ToUtf8 (ucs4
, u8
);
698 if (!strcmp (fromcode
, FC_ENCODING_MAC_ROMAN
))
701 const FcCharMap
*map
= FcFreeTypeGetPrivateMap (ft_encoding_apple_roman
);
702 FcChar8
*src
= (FcChar8
*) sname
->string
;
703 int src_len
= sname
->string_len
;
706 * Convert AppleRoman to Utf8
711 utf8
= malloc (sname
->string_len
* 3 + 1);
718 FcChar32 ucs4
= FcFreeTypePrivateToUcs4 (*src
++, map
);
719 int olen
= FcUcs4ToUtf8 (ucs4
, u8
);
727 cd
= iconv_open ("UTF-8", fromcode
);
728 if (cd
&& cd
!= (iconv_t
) (-1))
730 size_t in_bytes_left
= sname
->string_len
;
731 size_t out_bytes_left
= sname
->string_len
* FC_UTF8_MAX_LEN
;
732 char *inbuf
, *outbuf
;
734 utf8
= malloc (out_bytes_left
+ 1);
741 outbuf
= (char *) utf8
;
742 inbuf
= (char *) sname
->string
;
744 while (in_bytes_left
)
746 size_t did
= iconv (cd
,
747 &inbuf
, &in_bytes_left
,
748 &outbuf
, &out_bytes_left
);
749 if (did
== (size_t) (-1))
763 if (FcStrCmpIgnoreBlanksAndCase (utf8
, (FcChar8
*) "") == 0)
771 static const FcChar8
*
772 FcSfntNameLanguage (FT_SfntName
*sname
)
775 FT_UShort platform_id
= sname
->platform_id
;
776 FT_UShort language_id
= sname
->language_id
;
779 * Many names encoded for TT_PLATFORM_MACINTOSH are broken
780 * in various ways. Kludge around them.
782 if (platform_id
== TT_PLATFORM_MACINTOSH
&&
783 sname
->encoding_id
== TT_MAC_ID_ROMAN
&&
784 FcLooksLikeSJIS (sname
->string
, sname
->string_len
))
786 language_id
= TT_MAC_LANGID_JAPANESE
;
789 for (i
= 0; i
< NUM_FC_FT_LANGUAGE
; i
++)
790 if (fcFtLanguage
[i
].platform_id
== platform_id
&&
791 (fcFtLanguage
[i
].language_id
== TT_LANGUAGE_DONT_CARE
||
792 fcFtLanguage
[i
].language_id
== language_id
))
794 if (fcFtLanguage
[i
].lang
[0] == '\0')
797 return (FcChar8
*) fcFtLanguage
[i
].lang
;
802 /* Order is significant. For example, some B&H fonts are hinted by
803 URW++, and both strings appear in the notice. */
805 static const char notice_foundry_data
[] =
808 "Bitstream\0bitstream\0"
809 "Monotype\0monotype\0"
810 "Linotype\0linotype\0"
811 "LINOTYPE-HELL\0linotype\0"
814 "International Typeface Corporation\0itc\0"
815 "Tiro Typeworks\0tiro\0"
817 "Microsoft\0microsoft\0"
820 "HanYang System\0hanyang";
822 struct _notice_foundry
{
823 /* these are the offsets into the
824 * notice_foundry_data array.
826 unsigned char notice_offset
;
827 unsigned char foundry_offset
;
830 static const struct _notice_foundry FcNoticeFoundries
[] = {
848 #define NUM_NOTICE_FOUNDRIES (int) (sizeof (FcNoticeFoundries) / sizeof (FcNoticeFoundries[0]))
850 static const FcChar8
*
851 FcNoticeFoundry(const FT_String
*notice
)
856 for(i
= 0; i
< NUM_NOTICE_FOUNDRIES
; i
++)
858 const struct _notice_foundry
*nf
= &FcNoticeFoundries
[i
];
859 const char *n
= notice_foundry_data
+ nf
->notice_offset
;
860 const char *f
= notice_foundry_data
+ nf
->foundry_offset
;
862 if (strstr ((const char *) notice
, n
))
863 return (const FcChar8
*) f
;
869 FcVendorMatch(const FT_Char vendor
[4], const FT_Char
*vendor_string
)
871 /* vendor is not necessarily NUL-terminated. */
874 len
= strlen((char *) vendor_string
);
875 if (memcmp(vendor
, vendor_string
, len
) != 0)
877 for (i
= len
; i
< 4; i
++)
878 if (vendor
[i
] != ' ' && vendor
[i
] != '\0')
883 /* This table is partly taken from ttmkfdir by Joerg Pommnitz. */
885 /* It should not contain useless entries (such as UNKN) nor duplicate
886 entries for padding both with spaces and NULs. */
888 static const struct {
889 const FT_Char vendor
[5];
890 const FcChar8 foundry
[13];
891 } FcVendorFoundries
[] = {
897 { "ATEC", "alltype"},
899 { "BITS", "bitstream"},
901 { "DYNA", "dynalab"},
906 { "IMPR", "impress"},
907 { "LARA", "larabiefonts"},
908 { "LEAF", "interleaf"},
909 { "LETR", "letraset"},
910 { "LINO", "linotype"},
911 { "MACR", "macromedia"},
912 { "MONO", "monotype"},
913 { "MS", "microsoft"},
916 { "PARA", "paratype"},
923 #define NUM_VENDOR_FOUNDRIES (int) (sizeof (FcVendorFoundries) / sizeof (FcVendorFoundries[0]))
925 static const FcChar8
*
926 FcVendorFoundry(const FT_Char vendor
[4])
931 for(i
= 0; i
< NUM_VENDOR_FOUNDRIES
; i
++)
932 if (FcVendorMatch (vendor
, FcVendorFoundries
[i
].vendor
))
933 return FcVendorFoundries
[i
].foundry
;
937 typedef struct _FcStringConst
{
943 FcStringIsConst (const FcChar8
*string
,
944 const FcStringConst
*c
,
949 for (i
= 0; i
< nc
; i
++)
950 if (FcStrCmpIgnoreBlanksAndCase (string
, c
[i
].name
) == 0)
956 FcStringContainsConst (const FcChar8
*string
,
957 const FcStringConst
*c
,
962 for (i
= 0; i
< nc
; i
++)
964 if (c
[i
].name
[0] == '<')
966 if (FcStrContainsWord (string
, c
[i
].name
+ 1))
971 if (FcStrContainsIgnoreBlanksAndCase (string
, c
[i
].name
))
978 typedef FcChar8
*FC8
;
980 static const FcStringConst weightConsts
[] = {
981 { (FC8
) "thin", FC_WEIGHT_THIN
},
982 { (FC8
) "extralight", FC_WEIGHT_EXTRALIGHT
},
983 { (FC8
) "ultralight", FC_WEIGHT_ULTRALIGHT
},
984 { (FC8
) "light", FC_WEIGHT_LIGHT
},
985 { (FC8
) "book", FC_WEIGHT_BOOK
},
986 { (FC8
) "regular", FC_WEIGHT_REGULAR
},
987 { (FC8
) "normal", FC_WEIGHT_NORMAL
},
988 { (FC8
) "medium", FC_WEIGHT_MEDIUM
},
989 { (FC8
) "demibold", FC_WEIGHT_DEMIBOLD
},
990 { (FC8
) "demi", FC_WEIGHT_DEMIBOLD
},
991 { (FC8
) "semibold", FC_WEIGHT_SEMIBOLD
},
992 { (FC8
) "extrabold", FC_WEIGHT_EXTRABOLD
},
993 { (FC8
) "superbold", FC_WEIGHT_EXTRABOLD
},
994 { (FC8
) "ultrabold", FC_WEIGHT_ULTRABOLD
},
995 { (FC8
) "bold", FC_WEIGHT_BOLD
},
996 { (FC8
) "ultrablack", FC_WEIGHT_ULTRABLACK
},
997 { (FC8
) "superblack", FC_WEIGHT_EXTRABLACK
},
998 { (FC8
) "extrablack", FC_WEIGHT_EXTRABLACK
},
999 { (FC8
) "<ultra", FC_WEIGHT_ULTRABOLD
}, /* only if a word */
1000 { (FC8
) "black", FC_WEIGHT_BLACK
},
1001 { (FC8
) "heavy", FC_WEIGHT_HEAVY
},
1004 #define NUM_WEIGHT_CONSTS (int) (sizeof (weightConsts) / sizeof (weightConsts[0]))
1006 #define FcIsWeight(s) FcStringIsConst(s,weightConsts,NUM_WEIGHT_CONSTS)
1007 #define FcContainsWeight(s) FcStringContainsConst (s,weightConsts,NUM_WEIGHT_CONSTS)
1009 static const FcStringConst widthConsts
[] = {
1010 { (FC8
) "ultracondensed", FC_WIDTH_ULTRACONDENSED
},
1011 { (FC8
) "extracondensed", FC_WIDTH_EXTRACONDENSED
},
1012 { (FC8
) "semicondensed", FC_WIDTH_SEMICONDENSED
},
1013 { (FC8
) "condensed", FC_WIDTH_CONDENSED
}, /* must be after *condensed */
1014 { (FC8
) "normal", FC_WIDTH_NORMAL
},
1015 { (FC8
) "semiexpanded", FC_WIDTH_SEMIEXPANDED
},
1016 { (FC8
) "extraexpanded", FC_WIDTH_EXTRAEXPANDED
},
1017 { (FC8
) "ultraexpanded", FC_WIDTH_ULTRAEXPANDED
},
1018 { (FC8
) "expanded", FC_WIDTH_EXPANDED
}, /* must be after *expanded */
1019 { (FC8
) "extended", FC_WIDTH_EXPANDED
},
1022 #define NUM_WIDTH_CONSTS (int) (sizeof (widthConsts) / sizeof (widthConsts[0]))
1024 #define FcIsWidth(s) FcStringIsConst(s,widthConsts,NUM_WIDTH_CONSTS)
1025 #define FcContainsWidth(s) FcStringContainsConst (s,widthConsts,NUM_WIDTH_CONSTS)
1027 static const FcStringConst slantConsts
[] = {
1028 { (FC8
) "italic", FC_SLANT_ITALIC
},
1029 { (FC8
) "kursiv", FC_SLANT_ITALIC
},
1030 { (FC8
) "oblique", FC_SLANT_OBLIQUE
},
1033 #define NUM_SLANT_CONSTS (int) (sizeof (slantConsts) / sizeof (slantConsts[0]))
1035 #define FcIsSlant(s) FcStringIsConst(s,slantConsts,NUM_SLANT_CONSTS)
1036 #define FcContainsSlant(s) FcStringContainsConst (s,slantConsts,NUM_SLANT_CONSTS)
1038 static const FcStringConst decorativeConsts
[] = {
1039 { (FC8
) "shadow", FcTrue
},
1040 { (FC8
) "caps", FcTrue
},
1041 { (FC8
) "antiqua", FcTrue
},
1042 { (FC8
) "romansc", FcTrue
},
1043 { (FC8
) "embosed", FcTrue
},
1044 { (FC8
) "dunhill", FcTrue
},
1047 #define NUM_DECORATIVE_CONSTS (int) (sizeof (decorativeConsts) / sizeof (decorativeConsts[0]))
1049 #define FcIsDecorative(s) FcStringIsConst(s,decorativeConsts,NUM_DECORATIVE_CONSTS)
1050 #define FcContainsDecorative(s) FcStringContainsConst (s,decorativeConsts,NUM_DECORATIVE_CONSTS)
1053 FcGetPixelSize (FT_Face face
, int i
)
1055 #if HAVE_FT_GET_BDF_PROPERTY
1056 if (face
->num_fixed_sizes
== 1)
1058 BDF_PropertyRec prop
;
1061 rc
= FT_Get_BDF_Property (face
, "PIXEL_SIZE", &prop
);
1062 if (rc
== 0 && prop
.type
== BDF_PROPERTY_TYPE_INTEGER
)
1063 return (double) prop
.u
.integer
;
1066 #if HAVE_FT_BITMAP_SIZE_Y_PPEM
1067 return (double) face
->available_sizes
[i
].y_ppem
/ 64.0;
1069 return (double) face
->available_sizes
[i
].height
;
1074 FcStringInPatternElement (FcPattern
*pat
, const char *elt
, FcChar8
*string
)
1078 for (e
= 0; FcPatternGetString (pat
, elt
, e
, &old
) == FcResultMatch
; e
++)
1079 if (!FcStrCmpIgnoreBlanksAndCase (old
, string
))
1086 static const FT_UShort platform_order
[] = {
1087 TT_PLATFORM_MICROSOFT
,
1088 TT_PLATFORM_APPLE_UNICODE
,
1089 TT_PLATFORM_MACINTOSH
,
1091 #define NUM_PLATFORM_ORDER (sizeof (platform_order) / sizeof (platform_order[0]))
1093 static const FT_UShort nameid_order
[] = {
1094 TT_NAME_ID_PREFERRED_FAMILY
,
1095 TT_NAME_ID_FONT_FAMILY
,
1096 TT_NAME_ID_MAC_FULL_NAME
,
1097 TT_NAME_ID_FULL_NAME
,
1098 TT_NAME_ID_PREFERRED_SUBFAMILY
,
1099 TT_NAME_ID_FONT_SUBFAMILY
,
1100 TT_NAME_ID_TRADEMARK
,
1101 TT_NAME_ID_MANUFACTURER
,
1104 #define NUM_NAMEID_ORDER (sizeof (nameid_order) / sizeof (nameid_order[0]))
1106 FcFreeTypeQueryFace (const FT_Face face
,
1107 const FcChar8
*file
,
1115 FcBool decorative
= FcFalse
;
1120 FcChar8
*family
= 0;
1123 const FcChar8
*foundry
= 0;
1126 #if HAVE_FT_GET_PS_FONT_INFO
1127 PS_FontInfoRec psfontinfo
;
1129 #if HAVE_FT_GET_BDF_PROPERTY
1130 BDF_PropertyRec prop
;
1133 const FcChar8
*exclusiveLang
= 0;
1135 FT_UInt snamei
, snamec
;
1138 int nfamily_lang
= 0;
1140 int nstyle_lang
= 0;
1142 int nfullname_lang
= 0;
1149 pat
= FcPatternCreate ();
1153 if (!FcPatternAddBool (pat
, FC_OUTLINE
,
1154 (face
->face_flags
& FT_FACE_FLAG_SCALABLE
) != 0))
1157 if (!FcPatternAddBool (pat
, FC_SCALABLE
,
1158 (face
->face_flags
& FT_FACE_FLAG_SCALABLE
) != 0))
1163 * Get the OS/2 table
1165 os2
= (TT_OS2
*) FT_Get_Sfnt_Table (face
, ft_sfnt_os2
);
1168 * Look first in the OS/2 table for the foundry, if
1169 * not found here, the various notices will be searched for
1170 * that information, either from the sfnt name tables or
1171 * the Postscript FontInfo dictionary. Finally, the
1172 * BDF properties will queried.
1175 if (os2
&& os2
->version
>= 0x0001 && os2
->version
!= 0xffff)
1176 foundry
= FcVendorFoundry(os2
->achVendID
);
1178 if (FcDebug () & FC_DBG_SCANV
)
1181 * Grub through the name table looking for family
1182 * and style names. FreeType makes quite a hash
1185 snamec
= FT_Get_Sfnt_Name_Count (face
);
1186 for (p
= 0; p
<= NUM_PLATFORM_ORDER
; p
++)
1188 if (p
< NUM_PLATFORM_ORDER
)
1189 platform
= platform_order
[p
];
1194 * Order nameids so preferred names appear first
1195 * in the resulting list
1197 for (n
= 0; n
< NUM_NAMEID_ORDER
; n
++)
1199 nameid
= nameid_order
[n
];
1201 for (snamei
= 0; snamei
< snamec
; snamei
++)
1204 const FcChar8
*lang
;
1205 const char *elt
= 0, *eltlang
= 0;
1206 int *np
= 0, *nlangp
= 0;
1208 if (FT_Get_Sfnt_Name (face
, snamei
, &sname
) != 0)
1210 if (sname
.name_id
!= nameid
)
1214 * Sort platforms in preference order, accepting
1215 * all other platforms last
1217 if (p
< NUM_PLATFORM_ORDER
)
1219 if (sname
.platform_id
!= platform
)
1226 for (sp
= 0; sp
< NUM_PLATFORM_ORDER
; sp
++)
1227 if (sname
.platform_id
== platform_order
[sp
])
1229 if (sp
!= NUM_PLATFORM_ORDER
)
1232 utf8
= FcSfntNameTranscode (&sname
);
1233 lang
= FcSfntNameLanguage (&sname
);
1238 switch (sname
.name_id
) {
1239 case TT_NAME_ID_PREFERRED_FAMILY
:
1240 case TT_NAME_ID_FONT_FAMILY
:
1242 case TT_NAME_ID_PS_NAME
:
1243 case TT_NAME_ID_UNIQUE_ID
:
1245 if (FcDebug () & FC_DBG_SCANV
)
1246 printf ("found family (n %2d p %d e %d l 0x%04x) %s\n",
1247 sname
.name_id
, sname
.platform_id
,
1248 sname
.encoding_id
, sname
.language_id
,
1252 eltlang
= FC_FAMILYLANG
;
1254 nlangp
= &nfamily_lang
;
1256 case TT_NAME_ID_MAC_FULL_NAME
:
1257 case TT_NAME_ID_FULL_NAME
:
1258 if (FcDebug () & FC_DBG_SCANV
)
1259 printf ("found full (n %2d p %d e %d l 0x%04x) %s\n",
1260 sname
.name_id
, sname
.platform_id
,
1261 sname
.encoding_id
, sname
.language_id
,
1265 eltlang
= FC_FULLNAMELANG
;
1267 nlangp
= &nfullname_lang
;
1269 case TT_NAME_ID_PREFERRED_SUBFAMILY
:
1270 case TT_NAME_ID_FONT_SUBFAMILY
:
1271 if (FcDebug () & FC_DBG_SCANV
)
1272 printf ("found style (n %2d p %d e %d l 0x%04x) %s\n",
1273 sname
.name_id
, sname
.platform_id
,
1274 sname
.encoding_id
, sname
.language_id
,
1278 eltlang
= FC_STYLELANG
;
1280 nlangp
= &nstyle_lang
;
1282 case TT_NAME_ID_TRADEMARK
:
1283 case TT_NAME_ID_MANUFACTURER
:
1284 /* If the foundry wasn't found in the OS/2 table, look here */
1286 foundry
= FcNoticeFoundry((FT_String
*) utf8
);
1291 if (FcStringInPatternElement (pat
, elt
, utf8
))
1297 /* add new element */
1298 if (!FcPatternAddString (pat
, elt
, utf8
))
1306 /* pad lang list with 'xx' to line up with elt */
1307 while (*nlangp
< *np
)
1309 if (!FcPatternAddString (pat
, eltlang
, (FcChar8
*) "xx"))
1313 if (!FcPatternAddString (pat
, eltlang
, lang
))
1325 if (!nfamily
&& face
->family_name
&&
1326 FcStrCmpIgnoreBlanksAndCase ((FcChar8
*) face
->family_name
, (FcChar8
*) "") != 0)
1328 if (FcDebug () & FC_DBG_SCANV
)
1329 printf ("using FreeType family \"%s\"\n", face
->family_name
);
1330 if (!FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) face
->family_name
))
1335 if (!nstyle
&& face
->style_name
&&
1336 FcStrCmpIgnoreBlanksAndCase ((FcChar8
*) face
->style_name
, (FcChar8
*) "") != 0)
1338 if (FcDebug () & FC_DBG_SCANV
)
1339 printf ("using FreeType style \"%s\"\n", face
->style_name
);
1340 if (!FcPatternAddString (pat
, FC_STYLE
, (FcChar8
*) face
->style_name
))
1347 FcChar8
*start
, *end
;
1350 start
= (FcChar8
*) strrchr ((char *) file
, '/');
1354 start
= (FcChar8
*) file
;
1355 end
= (FcChar8
*) strrchr ((char *) start
, '.');
1357 end
= start
+ strlen ((char *) start
);
1359 family
= malloc (end
- start
+ 1);
1360 strncpy ((char *) family
, (char *) start
, end
- start
);
1361 family
[end
- start
] = '\0';
1362 if (FcDebug () & FC_DBG_SCANV
)
1363 printf ("using filename for family %s\n", family
);
1364 if (!FcPatternAddString (pat
, FC_FAMILY
, family
))
1373 if (!FcPatternAddString (pat
, FC_FILE
, file
))
1376 if (!FcPatternAddInteger (pat
, FC_INDEX
, id
))
1381 * don't even try this -- CJK 'monospace' fonts are really
1382 * dual width, and most other fonts don't bother to set
1383 * the attribute. Sigh.
1385 if ((face
->face_flags
& FT_FACE_FLAG_FIXED_WIDTH
) != 0)
1386 if (!FcPatternAddInteger (pat
, FC_SPACING
, FC_MONO
))
1391 * Find the font revision (if available)
1393 head
= (TT_Header
*) FT_Get_Sfnt_Table (face
, ft_sfnt_head
);
1396 if (!FcPatternAddInteger (pat
, FC_FONTVERSION
, head
->Font_Revision
))
1401 if (!FcPatternAddInteger (pat
, FC_FONTVERSION
, 0))
1405 if (os2
&& os2
->version
>= 0x0001 && os2
->version
!= 0xffff)
1407 for (i
= 0; i
< NUM_CODE_PAGE_RANGE
; i
++)
1411 if (FcCodePageRange
[i
].bit
< 32)
1413 bits
= os2
->ulCodePageRange1
;
1414 bit
= FcCodePageRange
[i
].bit
;
1418 bits
= os2
->ulCodePageRange2
;
1419 bit
= FcCodePageRange
[i
].bit
- 32;
1421 if (bits
& (1 << bit
))
1424 * If the font advertises support for multiple
1425 * "exclusive" languages, then include support
1426 * for any language found to have coverage
1433 exclusiveLang
= FcCodePageRange
[i
].lang
;
1438 if (os2
&& os2
->version
!= 0xffff)
1440 if (os2
->usWeightClass
== 0)
1442 else if (os2
->usWeightClass
< 150)
1443 weight
= FC_WEIGHT_THIN
;
1444 else if (os2
->usWeightClass
< 250)
1445 weight
= FC_WEIGHT_EXTRALIGHT
;
1446 else if (os2
->usWeightClass
< 350)
1447 weight
= FC_WEIGHT_LIGHT
;
1448 else if (os2
->usWeightClass
< 450)
1449 weight
= FC_WEIGHT_REGULAR
;
1450 else if (os2
->usWeightClass
< 550)
1451 weight
= FC_WEIGHT_MEDIUM
;
1452 else if (os2
->usWeightClass
< 650)
1453 weight
= FC_WEIGHT_SEMIBOLD
;
1454 else if (os2
->usWeightClass
< 750)
1455 weight
= FC_WEIGHT_BOLD
;
1456 else if (os2
->usWeightClass
< 850)
1457 weight
= FC_WEIGHT_EXTRABOLD
;
1458 else if (os2
->usWeightClass
< 925)
1459 weight
= FC_WEIGHT_BLACK
;
1460 else if (os2
->usWeightClass
< 1000)
1461 weight
= FC_WEIGHT_EXTRABLACK
;
1462 if ((FcDebug() & FC_DBG_SCANV
) && weight
!= -1)
1463 printf ("\tos2 weight class %d maps to weight %d\n",
1464 os2
->usWeightClass
, weight
);
1466 switch (os2
->usWidthClass
) {
1467 case 1: width
= FC_WIDTH_ULTRACONDENSED
; break;
1468 case 2: width
= FC_WIDTH_EXTRACONDENSED
; break;
1469 case 3: width
= FC_WIDTH_CONDENSED
; break;
1470 case 4: width
= FC_WIDTH_SEMICONDENSED
; break;
1471 case 5: width
= FC_WIDTH_NORMAL
; break;
1472 case 6: width
= FC_WIDTH_SEMIEXPANDED
; break;
1473 case 7: width
= FC_WIDTH_EXPANDED
; break;
1474 case 8: width
= FC_WIDTH_EXTRAEXPANDED
; break;
1475 case 9: width
= FC_WIDTH_ULTRAEXPANDED
; break;
1477 if ((FcDebug() & FC_DBG_SCANV
) && width
!= -1)
1478 printf ("\tos2 width class %d maps to width %d\n",
1479 os2
->usWidthClass
, width
);
1481 if (os2
&& (complex = FcFontCapabilities(face
)))
1483 if (!FcPatternAddString (pat
, FC_CAPABILITY
, complex))
1492 * Type 1: Check for FontInfo dictionary information
1493 * Code from g2@magestudios.net (Gerard Escalante)
1496 #if HAVE_FT_GET_PS_FONT_INFO
1497 if (FT_Get_PS_Font_Info(face
, &psfontinfo
) == 0)
1499 if (weight
== -1 && psfontinfo
.weight
)
1501 weight
= FcIsWeight ((FcChar8
*) psfontinfo
.weight
);
1502 if (FcDebug() & FC_DBG_SCANV
)
1503 printf ("\tType1 weight %s maps to %d\n",
1504 psfontinfo
.weight
, weight
);
1509 * Don't bother with italic_angle; FreeType already extracts that
1510 * information for us and sticks it into style_flags
1512 if (psfontinfo
.italic_angle
)
1513 slant
= FC_SLANT_ITALIC
;
1515 slant
= FC_SLANT_ROMAN
;
1519 foundry
= FcNoticeFoundry(psfontinfo
.notice
);
1521 #endif /* HAVE_FT_GET_PS_FONT_INFO */
1523 #if HAVE_FT_GET_BDF_PROPERTY
1525 * Finally, look for a FOUNDRY BDF property if no other
1526 * mechanism has managed to locate a foundry
1532 rc
= FT_Get_BDF_Property(face
, "FOUNDRY", &prop
);
1533 if(rc
== 0 && prop
.type
== BDF_PROPERTY_TYPE_ATOM
)
1534 foundry
= (FcChar8
*) prop
.u
.atom
;
1539 if (FT_Get_BDF_Property(face
, "RELATIVE_SETWIDTH", &prop
) == 0 &&
1540 (prop
.type
== BDF_PROPERTY_TYPE_INTEGER
||
1541 prop
.type
== BDF_PROPERTY_TYPE_CARDINAL
))
1545 if (prop
.type
== BDF_PROPERTY_TYPE_INTEGER
)
1546 value
= prop
.u
.integer
;
1548 value
= (FT_Int32
) prop
.u
.cardinal
;
1549 switch ((value
+ 5) / 10) {
1550 case 1: width
= FC_WIDTH_ULTRACONDENSED
; break;
1551 case 2: width
= FC_WIDTH_EXTRACONDENSED
; break;
1552 case 3: width
= FC_WIDTH_CONDENSED
; break;
1553 case 4: width
= FC_WIDTH_SEMICONDENSED
; break;
1554 case 5: width
= FC_WIDTH_NORMAL
; break;
1555 case 6: width
= FC_WIDTH_SEMIEXPANDED
; break;
1556 case 7: width
= FC_WIDTH_EXPANDED
; break;
1557 case 8: width
= FC_WIDTH_EXTRAEXPANDED
; break;
1558 case 9: width
= FC_WIDTH_ULTRAEXPANDED
; break;
1562 FT_Get_BDF_Property (face
, "SETWIDTH_NAME", &prop
) == 0 &&
1563 prop
.type
== BDF_PROPERTY_TYPE_ATOM
)
1565 width
= FcIsWidth ((FcChar8
*) prop
.u
.atom
);
1566 if (FcDebug () & FC_DBG_SCANV
)
1567 printf ("\tsetwidth %s maps to %d\n", prop
.u
.atom
, width
);
1573 * Look for weight, width and slant names in the style value
1575 for (st
= 0; FcPatternGetString (pat
, FC_STYLE
, st
, &style
) == FcResultMatch
; st
++)
1579 weight
= FcContainsWeight (style
);
1580 if (FcDebug() & FC_DBG_SCANV
)
1581 printf ("\tStyle %s maps to weight %d\n", style
, weight
);
1585 width
= FcContainsWidth (style
);
1586 if (FcDebug() & FC_DBG_SCANV
)
1587 printf ("\tStyle %s maps to width %d\n", style
, width
);
1591 slant
= FcContainsSlant (style
);
1592 if (FcDebug() & FC_DBG_SCANV
)
1593 printf ("\tStyle %s maps to slant %d\n", style
, slant
);
1595 if (decorative
== FcFalse
)
1597 decorative
= FcContainsDecorative (style
) > 0;
1598 if (FcDebug() & FC_DBG_SCANV
)
1599 printf ("\tStyle %s maps to decorative %d\n", style
, decorative
);
1603 * Pull default values from the FreeType flags if more
1604 * specific values not found above
1608 slant
= FC_SLANT_ROMAN
;
1609 if (face
->style_flags
& FT_STYLE_FLAG_ITALIC
)
1610 slant
= FC_SLANT_ITALIC
;
1615 weight
= FC_WEIGHT_MEDIUM
;
1616 if (face
->style_flags
& FT_STYLE_FLAG_BOLD
)
1617 weight
= FC_WEIGHT_BOLD
;
1621 width
= FC_WIDTH_NORMAL
;
1624 foundry
= (FcChar8
*) "unknown";
1626 if (!FcPatternAddInteger (pat
, FC_SLANT
, slant
))
1629 if (!FcPatternAddInteger (pat
, FC_WEIGHT
, weight
))
1632 if (!FcPatternAddInteger (pat
, FC_WIDTH
, width
))
1635 if (!FcPatternAddString (pat
, FC_FOUNDRY
, foundry
))
1638 if (!FcPatternAddBool (pat
, FC_DECORATIVE
, decorative
))
1642 * Compute the unicode coverage for the font
1644 cs
= FcFreeTypeCharSetAndSpacing (face
, blanks
, &spacing
);
1648 #if HAVE_FT_GET_BDF_PROPERTY
1649 /* For PCF fonts, override the computed spacing with the one from
1651 if(FT_Get_BDF_Property(face
, "SPACING", &prop
) == 0 &&
1652 prop
.type
== BDF_PROPERTY_TYPE_ATOM
) {
1653 if(!strcmp(prop
.u
.atom
, "c") || !strcmp(prop
.u
.atom
, "C"))
1654 spacing
= FC_CHARCELL
;
1655 else if(!strcmp(prop
.u
.atom
, "m") || !strcmp(prop
.u
.atom
, "M"))
1657 else if(!strcmp(prop
.u
.atom
, "p") || !strcmp(prop
.u
.atom
, "P"))
1658 spacing
= FC_PROPORTIONAL
;
1663 * Skip over PCF fonts that have no encoded characters; they're
1664 * usually just Unicode fonts transcoded to some legacy encoding
1665 * ftglue.c forces us to approximate whether a font is a PCF font
1666 * or not by whether it has any BDF properties. Try PIXEL_SIZE;
1667 * I don't know how to get a list of BDF properties on the font. -PL
1669 if (FcCharSetCount (cs
) == 0)
1671 #if HAVE_FT_GET_BDF_PROPERTY
1672 if(FT_Get_BDF_Property(face
, "PIXEL_SIZE", &prop
) == 0)
1677 if (!FcPatternAddCharSet (pat
, FC_CHARSET
, cs
))
1680 ls
= FcFreeTypeLangSet (cs
, exclusiveLang
);
1684 if (!FcPatternAddLangSet (pat
, FC_LANG
, ls
))
1686 FcLangSetDestroy (ls
);
1690 FcLangSetDestroy (ls
);
1692 if (spacing
!= FC_PROPORTIONAL
)
1693 if (!FcPatternAddInteger (pat
, FC_SPACING
, spacing
))
1696 if (!(face
->face_flags
& FT_FACE_FLAG_SCALABLE
))
1698 for (i
= 0; i
< face
->num_fixed_sizes
; i
++)
1699 if (!FcPatternAddDouble (pat
, FC_PIXEL_SIZE
,
1700 FcGetPixelSize (face
, i
)))
1702 if (!FcPatternAddBool (pat
, FC_ANTIALIAS
, FcFalse
))
1705 #if HAVE_FT_GET_X11_FONT_FORMAT
1707 * Use the (not well documented or supported) X-specific function
1708 * from FreeType to figure out the font format
1711 const char *font_format
= FT_Get_X11_Font_Format (face
);
1713 FcPatternAddString (pat
, FC_FONTFORMAT
, (FcChar8
*) font_format
);
1718 * Drop our reference to the charset
1720 FcCharSetDestroy (cs
);
1725 FcCharSetDestroy (cs
);
1727 FcPatternDestroy (pat
);
1733 FcFreeTypeQuery(const FcChar8
*file
,
1739 FT_Library ftLibrary
;
1740 FcPattern
*pat
= NULL
;
1742 if (FT_Init_FreeType (&ftLibrary
))
1745 if (FT_New_Face (ftLibrary
, (char *) file
, id
, &face
))
1748 *count
= face
->num_faces
;
1750 pat
= FcFreeTypeQueryFace (face
, file
, id
, blanks
);
1752 FT_Done_Face (face
);
1754 FT_Done_FreeType (ftLibrary
);
1759 * For our purposes, this approximation is sufficient
1761 #if !HAVE_FT_GET_NEXT_CHAR
1762 #define FT_Get_Next_Char(face, ucs4, gi) ((ucs4) >= 0xffffff ? \
1764 (*(gi) = 1), (ucs4) + 1)
1765 #warning "No FT_Get_Next_Char: Please install freetype version 2.1.0 or newer"
1768 typedef struct _FcCharEnt
{
1770 unsigned char encode
;
1774 const FcCharEnt
*ent
;
1778 typedef struct _FcFontDecode
{
1779 FT_Encoding encoding
;
1780 const FcCharMap
*map
;
1784 static const FcCharEnt AppleRomanEnt
[] = {
1785 { 0x0020, 0x20 }, /* SPACE */
1786 { 0x0021, 0x21 }, /* EXCLAMATION MARK */
1787 { 0x0022, 0x22 }, /* QUOTATION MARK */
1788 { 0x0023, 0x23 }, /* NUMBER SIGN */
1789 { 0x0024, 0x24 }, /* DOLLAR SIGN */
1790 { 0x0025, 0x25 }, /* PERCENT SIGN */
1791 { 0x0026, 0x26 }, /* AMPERSAND */
1792 { 0x0027, 0x27 }, /* APOSTROPHE */
1793 { 0x0028, 0x28 }, /* LEFT PARENTHESIS */
1794 { 0x0029, 0x29 }, /* RIGHT PARENTHESIS */
1795 { 0x002A, 0x2A }, /* ASTERISK */
1796 { 0x002B, 0x2B }, /* PLUS SIGN */
1797 { 0x002C, 0x2C }, /* COMMA */
1798 { 0x002D, 0x2D }, /* HYPHEN-MINUS */
1799 { 0x002E, 0x2E }, /* FULL STOP */
1800 { 0x002F, 0x2F }, /* SOLIDUS */
1801 { 0x0030, 0x30 }, /* DIGIT ZERO */
1802 { 0x0031, 0x31 }, /* DIGIT ONE */
1803 { 0x0032, 0x32 }, /* DIGIT TWO */
1804 { 0x0033, 0x33 }, /* DIGIT THREE */
1805 { 0x0034, 0x34 }, /* DIGIT FOUR */
1806 { 0x0035, 0x35 }, /* DIGIT FIVE */
1807 { 0x0036, 0x36 }, /* DIGIT SIX */
1808 { 0x0037, 0x37 }, /* DIGIT SEVEN */
1809 { 0x0038, 0x38 }, /* DIGIT EIGHT */
1810 { 0x0039, 0x39 }, /* DIGIT NINE */
1811 { 0x003A, 0x3A }, /* COLON */
1812 { 0x003B, 0x3B }, /* SEMICOLON */
1813 { 0x003C, 0x3C }, /* LESS-THAN SIGN */
1814 { 0x003D, 0x3D }, /* EQUALS SIGN */
1815 { 0x003E, 0x3E }, /* GREATER-THAN SIGN */
1816 { 0x003F, 0x3F }, /* QUESTION MARK */
1817 { 0x0040, 0x40 }, /* COMMERCIAL AT */
1818 { 0x0041, 0x41 }, /* LATIN CAPITAL LETTER A */
1819 { 0x0042, 0x42 }, /* LATIN CAPITAL LETTER B */
1820 { 0x0043, 0x43 }, /* LATIN CAPITAL LETTER C */
1821 { 0x0044, 0x44 }, /* LATIN CAPITAL LETTER D */
1822 { 0x0045, 0x45 }, /* LATIN CAPITAL LETTER E */
1823 { 0x0046, 0x46 }, /* LATIN CAPITAL LETTER F */
1824 { 0x0047, 0x47 }, /* LATIN CAPITAL LETTER G */
1825 { 0x0048, 0x48 }, /* LATIN CAPITAL LETTER H */
1826 { 0x0049, 0x49 }, /* LATIN CAPITAL LETTER I */
1827 { 0x004A, 0x4A }, /* LATIN CAPITAL LETTER J */
1828 { 0x004B, 0x4B }, /* LATIN CAPITAL LETTER K */
1829 { 0x004C, 0x4C }, /* LATIN CAPITAL LETTER L */
1830 { 0x004D, 0x4D }, /* LATIN CAPITAL LETTER M */
1831 { 0x004E, 0x4E }, /* LATIN CAPITAL LETTER N */
1832 { 0x004F, 0x4F }, /* LATIN CAPITAL LETTER O */
1833 { 0x0050, 0x50 }, /* LATIN CAPITAL LETTER P */
1834 { 0x0051, 0x51 }, /* LATIN CAPITAL LETTER Q */
1835 { 0x0052, 0x52 }, /* LATIN CAPITAL LETTER R */
1836 { 0x0053, 0x53 }, /* LATIN CAPITAL LETTER S */
1837 { 0x0054, 0x54 }, /* LATIN CAPITAL LETTER T */
1838 { 0x0055, 0x55 }, /* LATIN CAPITAL LETTER U */
1839 { 0x0056, 0x56 }, /* LATIN CAPITAL LETTER V */
1840 { 0x0057, 0x57 }, /* LATIN CAPITAL LETTER W */
1841 { 0x0058, 0x58 }, /* LATIN CAPITAL LETTER X */
1842 { 0x0059, 0x59 }, /* LATIN CAPITAL LETTER Y */
1843 { 0x005A, 0x5A }, /* LATIN CAPITAL LETTER Z */
1844 { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET */
1845 { 0x005C, 0x5C }, /* REVERSE SOLIDUS */
1846 { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET */
1847 { 0x005E, 0x5E }, /* CIRCUMFLEX ACCENT */
1848 { 0x005F, 0x5F }, /* LOW LINE */
1849 { 0x0060, 0x60 }, /* GRAVE ACCENT */
1850 { 0x0061, 0x61 }, /* LATIN SMALL LETTER A */
1851 { 0x0062, 0x62 }, /* LATIN SMALL LETTER B */
1852 { 0x0063, 0x63 }, /* LATIN SMALL LETTER C */
1853 { 0x0064, 0x64 }, /* LATIN SMALL LETTER D */
1854 { 0x0065, 0x65 }, /* LATIN SMALL LETTER E */
1855 { 0x0066, 0x66 }, /* LATIN SMALL LETTER F */
1856 { 0x0067, 0x67 }, /* LATIN SMALL LETTER G */
1857 { 0x0068, 0x68 }, /* LATIN SMALL LETTER H */
1858 { 0x0069, 0x69 }, /* LATIN SMALL LETTER I */
1859 { 0x006A, 0x6A }, /* LATIN SMALL LETTER J */
1860 { 0x006B, 0x6B }, /* LATIN SMALL LETTER K */
1861 { 0x006C, 0x6C }, /* LATIN SMALL LETTER L */
1862 { 0x006D, 0x6D }, /* LATIN SMALL LETTER M */
1863 { 0x006E, 0x6E }, /* LATIN SMALL LETTER N */
1864 { 0x006F, 0x6F }, /* LATIN SMALL LETTER O */
1865 { 0x0070, 0x70 }, /* LATIN SMALL LETTER P */
1866 { 0x0071, 0x71 }, /* LATIN SMALL LETTER Q */
1867 { 0x0072, 0x72 }, /* LATIN SMALL LETTER R */
1868 { 0x0073, 0x73 }, /* LATIN SMALL LETTER S */
1869 { 0x0074, 0x74 }, /* LATIN SMALL LETTER T */
1870 { 0x0075, 0x75 }, /* LATIN SMALL LETTER U */
1871 { 0x0076, 0x76 }, /* LATIN SMALL LETTER V */
1872 { 0x0077, 0x77 }, /* LATIN SMALL LETTER W */
1873 { 0x0078, 0x78 }, /* LATIN SMALL LETTER X */
1874 { 0x0079, 0x79 }, /* LATIN SMALL LETTER Y */
1875 { 0x007A, 0x7A }, /* LATIN SMALL LETTER Z */
1876 { 0x007B, 0x7B }, /* LEFT CURLY BRACKET */
1877 { 0x007C, 0x7C }, /* VERTICAL LINE */
1878 { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET */
1879 { 0x007E, 0x7E }, /* TILDE */
1880 { 0x00A0, 0xCA }, /* NO-BREAK SPACE */
1881 { 0x00A1, 0xC1 }, /* INVERTED EXCLAMATION MARK */
1882 { 0x00A2, 0xA2 }, /* CENT SIGN */
1883 { 0x00A3, 0xA3 }, /* POUND SIGN */
1884 { 0x00A5, 0xB4 }, /* YEN SIGN */
1885 { 0x00A7, 0xA4 }, /* SECTION SIGN */
1886 { 0x00A8, 0xAC }, /* DIAERESIS */
1887 { 0x00A9, 0xA9 }, /* COPYRIGHT SIGN */
1888 { 0x00AA, 0xBB }, /* FEMININE ORDINAL INDICATOR */
1889 { 0x00AB, 0xC7 }, /* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
1890 { 0x00AC, 0xC2 }, /* NOT SIGN */
1891 { 0x00AE, 0xA8 }, /* REGISTERED SIGN */
1892 { 0x00AF, 0xF8 }, /* MACRON */
1893 { 0x00B0, 0xA1 }, /* DEGREE SIGN */
1894 { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN */
1895 { 0x00B4, 0xAB }, /* ACUTE ACCENT */
1896 { 0x00B5, 0xB5 }, /* MICRO SIGN */
1897 { 0x00B6, 0xA6 }, /* PILCROW SIGN */
1898 { 0x00B7, 0xE1 }, /* MIDDLE DOT */
1899 { 0x00B8, 0xFC }, /* CEDILLA */
1900 { 0x00BA, 0xBC }, /* MASCULINE ORDINAL INDICATOR */
1901 { 0x00BB, 0xC8 }, /* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
1902 { 0x00BF, 0xC0 }, /* INVERTED QUESTION MARK */
1903 { 0x00C0, 0xCB }, /* LATIN CAPITAL LETTER A WITH GRAVE */
1904 { 0x00C1, 0xE7 }, /* LATIN CAPITAL LETTER A WITH ACUTE */
1905 { 0x00C2, 0xE5 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
1906 { 0x00C3, 0xCC }, /* LATIN CAPITAL LETTER A WITH TILDE */
1907 { 0x00C4, 0x80 }, /* LATIN CAPITAL LETTER A WITH DIAERESIS */
1908 { 0x00C5, 0x81 }, /* LATIN CAPITAL LETTER A WITH RING ABOVE */
1909 { 0x00C6, 0xAE }, /* LATIN CAPITAL LETTER AE */
1910 { 0x00C7, 0x82 }, /* LATIN CAPITAL LETTER C WITH CEDILLA */
1911 { 0x00C8, 0xE9 }, /* LATIN CAPITAL LETTER E WITH GRAVE */
1912 { 0x00C9, 0x83 }, /* LATIN CAPITAL LETTER E WITH ACUTE */
1913 { 0x00CA, 0xE6 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
1914 { 0x00CB, 0xE8 }, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
1915 { 0x00CC, 0xED }, /* LATIN CAPITAL LETTER I WITH GRAVE */
1916 { 0x00CD, 0xEA }, /* LATIN CAPITAL LETTER I WITH ACUTE */
1917 { 0x00CE, 0xEB }, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
1918 { 0x00CF, 0xEC }, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
1919 { 0x00D1, 0x84 }, /* LATIN CAPITAL LETTER N WITH TILDE */
1920 { 0x00D2, 0xF1 }, /* LATIN CAPITAL LETTER O WITH GRAVE */
1921 { 0x00D3, 0xEE }, /* LATIN CAPITAL LETTER O WITH ACUTE */
1922 { 0x00D4, 0xEF }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
1923 { 0x00D5, 0xCD }, /* LATIN CAPITAL LETTER O WITH TILDE */
1924 { 0x00D6, 0x85 }, /* LATIN CAPITAL LETTER O WITH DIAERESIS */
1925 { 0x00D8, 0xAF }, /* LATIN CAPITAL LETTER O WITH STROKE */
1926 { 0x00D9, 0xF4 }, /* LATIN CAPITAL LETTER U WITH GRAVE */
1927 { 0x00DA, 0xF2 }, /* LATIN CAPITAL LETTER U WITH ACUTE */
1928 { 0x00DB, 0xF3 }, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
1929 { 0x00DC, 0x86 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS */
1930 { 0x00DF, 0xA7 }, /* LATIN SMALL LETTER SHARP S */
1931 { 0x00E0, 0x88 }, /* LATIN SMALL LETTER A WITH GRAVE */
1932 { 0x00E1, 0x87 }, /* LATIN SMALL LETTER A WITH ACUTE */
1933 { 0x00E2, 0x89 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
1934 { 0x00E3, 0x8B }, /* LATIN SMALL LETTER A WITH TILDE */
1935 { 0x00E4, 0x8A }, /* LATIN SMALL LETTER A WITH DIAERESIS */
1936 { 0x00E5, 0x8C }, /* LATIN SMALL LETTER A WITH RING ABOVE */
1937 { 0x00E6, 0xBE }, /* LATIN SMALL LETTER AE */
1938 { 0x00E7, 0x8D }, /* LATIN SMALL LETTER C WITH CEDILLA */
1939 { 0x00E8, 0x8F }, /* LATIN SMALL LETTER E WITH GRAVE */
1940 { 0x00E9, 0x8E }, /* LATIN SMALL LETTER E WITH ACUTE */
1941 { 0x00EA, 0x90 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */
1942 { 0x00EB, 0x91 }, /* LATIN SMALL LETTER E WITH DIAERESIS */
1943 { 0x00EC, 0x93 }, /* LATIN SMALL LETTER I WITH GRAVE */
1944 { 0x00ED, 0x92 }, /* LATIN SMALL LETTER I WITH ACUTE */
1945 { 0x00EE, 0x94 }, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
1946 { 0x00EF, 0x95 }, /* LATIN SMALL LETTER I WITH DIAERESIS */
1947 { 0x00F1, 0x96 }, /* LATIN SMALL LETTER N WITH TILDE */
1948 { 0x00F2, 0x98 }, /* LATIN SMALL LETTER O WITH GRAVE */
1949 { 0x00F3, 0x97 }, /* LATIN SMALL LETTER O WITH ACUTE */
1950 { 0x00F4, 0x99 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
1951 { 0x00F5, 0x9B }, /* LATIN SMALL LETTER O WITH TILDE */
1952 { 0x00F6, 0x9A }, /* LATIN SMALL LETTER O WITH DIAERESIS */
1953 { 0x00F7, 0xD6 }, /* DIVISION SIGN */
1954 { 0x00F8, 0xBF }, /* LATIN SMALL LETTER O WITH STROKE */
1955 { 0x00F9, 0x9D }, /* LATIN SMALL LETTER U WITH GRAVE */
1956 { 0x00FA, 0x9C }, /* LATIN SMALL LETTER U WITH ACUTE */
1957 { 0x00FB, 0x9E }, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
1958 { 0x00FC, 0x9F }, /* LATIN SMALL LETTER U WITH DIAERESIS */
1959 { 0x00FF, 0xD8 }, /* LATIN SMALL LETTER Y WITH DIAERESIS */
1960 { 0x0131, 0xF5 }, /* LATIN SMALL LETTER DOTLESS I */
1961 { 0x0152, 0xCE }, /* LATIN CAPITAL LIGATURE OE */
1962 { 0x0153, 0xCF }, /* LATIN SMALL LIGATURE OE */
1963 { 0x0178, 0xD9 }, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
1964 { 0x0192, 0xC4 }, /* LATIN SMALL LETTER F WITH HOOK */
1965 { 0x02C6, 0xF6 }, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
1966 { 0x02C7, 0xFF }, /* CARON */
1967 { 0x02D8, 0xF9 }, /* BREVE */
1968 { 0x02D9, 0xFA }, /* DOT ABOVE */
1969 { 0x02DA, 0xFB }, /* RING ABOVE */
1970 { 0x02DB, 0xFE }, /* OGONEK */
1971 { 0x02DC, 0xF7 }, /* SMALL TILDE */
1972 { 0x02DD, 0xFD }, /* DOUBLE ACUTE ACCENT */
1973 { 0x03A9, 0xBD }, /* GREEK CAPITAL LETTER OMEGA */
1974 { 0x03C0, 0xB9 }, /* GREEK SMALL LETTER PI */
1975 { 0x2013, 0xD0 }, /* EN DASH */
1976 { 0x2014, 0xD1 }, /* EM DASH */
1977 { 0x2018, 0xD4 }, /* LEFT SINGLE QUOTATION MARK */
1978 { 0x2019, 0xD5 }, /* RIGHT SINGLE QUOTATION MARK */
1979 { 0x201A, 0xE2 }, /* SINGLE LOW-9 QUOTATION MARK */
1980 { 0x201C, 0xD2 }, /* LEFT DOUBLE QUOTATION MARK */
1981 { 0x201D, 0xD3 }, /* RIGHT DOUBLE QUOTATION MARK */
1982 { 0x201E, 0xE3 }, /* DOUBLE LOW-9 QUOTATION MARK */
1983 { 0x2020, 0xA0 }, /* DAGGER */
1984 { 0x2021, 0xE0 }, /* DOUBLE DAGGER */
1985 { 0x2022, 0xA5 }, /* BULLET */
1986 { 0x2026, 0xC9 }, /* HORIZONTAL ELLIPSIS */
1987 { 0x2030, 0xE4 }, /* PER MILLE SIGN */
1988 { 0x2039, 0xDC }, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
1989 { 0x203A, 0xDD }, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
1990 { 0x2044, 0xDA }, /* FRACTION SLASH */
1991 { 0x20AC, 0xDB }, /* EURO SIGN */
1992 { 0x2122, 0xAA }, /* TRADE MARK SIGN */
1993 { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL */
1994 { 0x2206, 0xC6 }, /* INCREMENT */
1995 { 0x220F, 0xB8 }, /* N-ARY PRODUCT */
1996 { 0x2211, 0xB7 }, /* N-ARY SUMMATION */
1997 { 0x221A, 0xC3 }, /* SQUARE ROOT */
1998 { 0x221E, 0xB0 }, /* INFINITY */
1999 { 0x222B, 0xBA }, /* INTEGRAL */
2000 { 0x2248, 0xC5 }, /* ALMOST EQUAL TO */
2001 { 0x2260, 0xAD }, /* NOT EQUAL TO */
2002 { 0x2264, 0xB2 }, /* LESS-THAN OR EQUAL TO */
2003 { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO */
2004 { 0x25CA, 0xD7 }, /* LOZENGE */
2005 { 0xF8FF, 0xF0 }, /* Apple logo */
2006 { 0xFB01, 0xDE }, /* LATIN SMALL LIGATURE FI */
2007 { 0xFB02, 0xDF }, /* LATIN SMALL LIGATURE FL */
2010 static const FcCharMap AppleRoman
= {
2012 sizeof (AppleRomanEnt
) / sizeof (AppleRomanEnt
[0])
2015 static const FcCharEnt AdobeSymbolEnt
[] = {
2016 { 0x0020, 0x20 }, /* SPACE # space */
2017 { 0x0021, 0x21 }, /* EXCLAMATION MARK # exclam */
2018 { 0x0023, 0x23 }, /* NUMBER SIGN # numbersign */
2019 { 0x0025, 0x25 }, /* PERCENT SIGN # percent */
2020 { 0x0026, 0x26 }, /* AMPERSAND # ampersand */
2021 { 0x0028, 0x28 }, /* LEFT PARENTHESIS # parenleft */
2022 { 0x0029, 0x29 }, /* RIGHT PARENTHESIS # parenright */
2023 { 0x002B, 0x2B }, /* PLUS SIGN # plus */
2024 { 0x002C, 0x2C }, /* COMMA # comma */
2025 { 0x002E, 0x2E }, /* FULL STOP # period */
2026 { 0x002F, 0x2F }, /* SOLIDUS # slash */
2027 { 0x0030, 0x30 }, /* DIGIT ZERO # zero */
2028 { 0x0031, 0x31 }, /* DIGIT ONE # one */
2029 { 0x0032, 0x32 }, /* DIGIT TWO # two */
2030 { 0x0033, 0x33 }, /* DIGIT THREE # three */
2031 { 0x0034, 0x34 }, /* DIGIT FOUR # four */
2032 { 0x0035, 0x35 }, /* DIGIT FIVE # five */
2033 { 0x0036, 0x36 }, /* DIGIT SIX # six */
2034 { 0x0037, 0x37 }, /* DIGIT SEVEN # seven */
2035 { 0x0038, 0x38 }, /* DIGIT EIGHT # eight */
2036 { 0x0039, 0x39 }, /* DIGIT NINE # nine */
2037 { 0x003A, 0x3A }, /* COLON # colon */
2038 { 0x003B, 0x3B }, /* SEMICOLON # semicolon */
2039 { 0x003C, 0x3C }, /* LESS-THAN SIGN # less */
2040 { 0x003D, 0x3D }, /* EQUALS SIGN # equal */
2041 { 0x003E, 0x3E }, /* GREATER-THAN SIGN # greater */
2042 { 0x003F, 0x3F }, /* QUESTION MARK # question */
2043 { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET # bracketleft */
2044 { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET # bracketright */
2045 { 0x005F, 0x5F }, /* LOW LINE # underscore */
2046 { 0x007B, 0x7B }, /* LEFT CURLY BRACKET # braceleft */
2047 { 0x007C, 0x7C }, /* VERTICAL LINE # bar */
2048 { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET # braceright */
2049 { 0x00A0, 0x20 }, /* NO-BREAK SPACE # space */
2050 { 0x00AC, 0xD8 }, /* NOT SIGN # logicalnot */
2051 { 0x00B0, 0xB0 }, /* DEGREE SIGN # degree */
2052 { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN # plusminus */
2053 { 0x00B5, 0x6D }, /* MICRO SIGN # mu */
2054 { 0x00D7, 0xB4 }, /* MULTIPLICATION SIGN # multiply */
2055 { 0x00F7, 0xB8 }, /* DIVISION SIGN # divide */
2056 { 0x0192, 0xA6 }, /* LATIN SMALL LETTER F WITH HOOK # florin */
2057 { 0x0391, 0x41 }, /* GREEK CAPITAL LETTER ALPHA # Alpha */
2058 { 0x0392, 0x42 }, /* GREEK CAPITAL LETTER BETA # Beta */
2059 { 0x0393, 0x47 }, /* GREEK CAPITAL LETTER GAMMA # Gamma */
2060 { 0x0394, 0x44 }, /* GREEK CAPITAL LETTER DELTA # Delta */
2061 { 0x0395, 0x45 }, /* GREEK CAPITAL LETTER EPSILON # Epsilon */
2062 { 0x0396, 0x5A }, /* GREEK CAPITAL LETTER ZETA # Zeta */
2063 { 0x0397, 0x48 }, /* GREEK CAPITAL LETTER ETA # Eta */
2064 { 0x0398, 0x51 }, /* GREEK CAPITAL LETTER THETA # Theta */
2065 { 0x0399, 0x49 }, /* GREEK CAPITAL LETTER IOTA # Iota */
2066 { 0x039A, 0x4B }, /* GREEK CAPITAL LETTER KAPPA # Kappa */
2067 { 0x039B, 0x4C }, /* GREEK CAPITAL LETTER LAMDA # Lambda */
2068 { 0x039C, 0x4D }, /* GREEK CAPITAL LETTER MU # Mu */
2069 { 0x039D, 0x4E }, /* GREEK CAPITAL LETTER NU # Nu */
2070 { 0x039E, 0x58 }, /* GREEK CAPITAL LETTER XI # Xi */
2071 { 0x039F, 0x4F }, /* GREEK CAPITAL LETTER OMICRON # Omicron */
2072 { 0x03A0, 0x50 }, /* GREEK CAPITAL LETTER PI # Pi */
2073 { 0x03A1, 0x52 }, /* GREEK CAPITAL LETTER RHO # Rho */
2074 { 0x03A3, 0x53 }, /* GREEK CAPITAL LETTER SIGMA # Sigma */
2075 { 0x03A4, 0x54 }, /* GREEK CAPITAL LETTER TAU # Tau */
2076 { 0x03A5, 0x55 }, /* GREEK CAPITAL LETTER UPSILON # Upsilon */
2077 { 0x03A6, 0x46 }, /* GREEK CAPITAL LETTER PHI # Phi */
2078 { 0x03A7, 0x43 }, /* GREEK CAPITAL LETTER CHI # Chi */
2079 { 0x03A8, 0x59 }, /* GREEK CAPITAL LETTER PSI # Psi */
2080 { 0x03A9, 0x57 }, /* GREEK CAPITAL LETTER OMEGA # Omega */
2081 { 0x03B1, 0x61 }, /* GREEK SMALL LETTER ALPHA # alpha */
2082 { 0x03B2, 0x62 }, /* GREEK SMALL LETTER BETA # beta */
2083 { 0x03B3, 0x67 }, /* GREEK SMALL LETTER GAMMA # gamma */
2084 { 0x03B4, 0x64 }, /* GREEK SMALL LETTER DELTA # delta */
2085 { 0x03B5, 0x65 }, /* GREEK SMALL LETTER EPSILON # epsilon */
2086 { 0x03B6, 0x7A }, /* GREEK SMALL LETTER ZETA # zeta */
2087 { 0x03B7, 0x68 }, /* GREEK SMALL LETTER ETA # eta */
2088 { 0x03B8, 0x71 }, /* GREEK SMALL LETTER THETA # theta */
2089 { 0x03B9, 0x69 }, /* GREEK SMALL LETTER IOTA # iota */
2090 { 0x03BA, 0x6B }, /* GREEK SMALL LETTER KAPPA # kappa */
2091 { 0x03BB, 0x6C }, /* GREEK SMALL LETTER LAMDA # lambda */
2092 { 0x03BC, 0x6D }, /* GREEK SMALL LETTER MU # mu */
2093 { 0x03BD, 0x6E }, /* GREEK SMALL LETTER NU # nu */
2094 { 0x03BE, 0x78 }, /* GREEK SMALL LETTER XI # xi */
2095 { 0x03BF, 0x6F }, /* GREEK SMALL LETTER OMICRON # omicron */
2096 { 0x03C0, 0x70 }, /* GREEK SMALL LETTER PI # pi */
2097 { 0x03C1, 0x72 }, /* GREEK SMALL LETTER RHO # rho */
2098 { 0x03C2, 0x56 }, /* GREEK SMALL LETTER FINAL SIGMA # sigma1 */
2099 { 0x03C3, 0x73 }, /* GREEK SMALL LETTER SIGMA # sigma */
2100 { 0x03C4, 0x74 }, /* GREEK SMALL LETTER TAU # tau */
2101 { 0x03C5, 0x75 }, /* GREEK SMALL LETTER UPSILON # upsilon */
2102 { 0x03C6, 0x66 }, /* GREEK SMALL LETTER PHI # phi */
2103 { 0x03C7, 0x63 }, /* GREEK SMALL LETTER CHI # chi */
2104 { 0x03C8, 0x79 }, /* GREEK SMALL LETTER PSI # psi */
2105 { 0x03C9, 0x77 }, /* GREEK SMALL LETTER OMEGA # omega */
2106 { 0x03D1, 0x4A }, /* GREEK THETA SYMBOL # theta1 */
2107 { 0x03D2, 0xA1 }, /* GREEK UPSILON WITH HOOK SYMBOL # Upsilon1 */
2108 { 0x03D5, 0x6A }, /* GREEK PHI SYMBOL # phi1 */
2109 { 0x03D6, 0x76 }, /* GREEK PI SYMBOL # omega1 */
2110 { 0x2022, 0xB7 }, /* BULLET # bullet */
2111 { 0x2026, 0xBC }, /* HORIZONTAL ELLIPSIS # ellipsis */
2112 { 0x2032, 0xA2 }, /* PRIME # minute */
2113 { 0x2033, 0xB2 }, /* DOUBLE PRIME # second */
2114 { 0x2044, 0xA4 }, /* FRACTION SLASH # fraction */
2115 { 0x20AC, 0xA0 }, /* EURO SIGN # Euro */
2116 { 0x2111, 0xC1 }, /* BLACK-LETTER CAPITAL I # Ifraktur */
2117 { 0x2118, 0xC3 }, /* SCRIPT CAPITAL P # weierstrass */
2118 { 0x211C, 0xC2 }, /* BLACK-LETTER CAPITAL R # Rfraktur */
2119 { 0x2126, 0x57 }, /* OHM SIGN # Omega */
2120 { 0x2135, 0xC0 }, /* ALEF SYMBOL # aleph */
2121 { 0x2190, 0xAC }, /* LEFTWARDS ARROW # arrowleft */
2122 { 0x2191, 0xAD }, /* UPWARDS ARROW # arrowup */
2123 { 0x2192, 0xAE }, /* RIGHTWARDS ARROW # arrowright */
2124 { 0x2193, 0xAF }, /* DOWNWARDS ARROW # arrowdown */
2125 { 0x2194, 0xAB }, /* LEFT RIGHT ARROW # arrowboth */
2126 { 0x21B5, 0xBF }, /* DOWNWARDS ARROW WITH CORNER LEFTWARDS # carriagereturn */
2127 { 0x21D0, 0xDC }, /* LEFTWARDS DOUBLE ARROW # arrowdblleft */
2128 { 0x21D1, 0xDD }, /* UPWARDS DOUBLE ARROW # arrowdblup */
2129 { 0x21D2, 0xDE }, /* RIGHTWARDS DOUBLE ARROW # arrowdblright */
2130 { 0x21D3, 0xDF }, /* DOWNWARDS DOUBLE ARROW # arrowdbldown */
2131 { 0x21D4, 0xDB }, /* LEFT RIGHT DOUBLE ARROW # arrowdblboth */
2132 { 0x2200, 0x22 }, /* FOR ALL # universal */
2133 { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL # partialdiff */
2134 { 0x2203, 0x24 }, /* THERE EXISTS # existential */
2135 { 0x2205, 0xC6 }, /* EMPTY SET # emptyset */
2136 { 0x2206, 0x44 }, /* INCREMENT # Delta */
2137 { 0x2207, 0xD1 }, /* NABLA # gradient */
2138 { 0x2208, 0xCE }, /* ELEMENT OF # element */
2139 { 0x2209, 0xCF }, /* NOT AN ELEMENT OF # notelement */
2140 { 0x220B, 0x27 }, /* CONTAINS AS MEMBER # suchthat */
2141 { 0x220F, 0xD5 }, /* N-ARY PRODUCT # product */
2142 { 0x2211, 0xE5 }, /* N-ARY SUMMATION # summation */
2143 { 0x2212, 0x2D }, /* MINUS SIGN # minus */
2144 { 0x2215, 0xA4 }, /* DIVISION SLASH # fraction */
2145 { 0x2217, 0x2A }, /* ASTERISK OPERATOR # asteriskmath */
2146 { 0x221A, 0xD6 }, /* SQUARE ROOT # radical */
2147 { 0x221D, 0xB5 }, /* PROPORTIONAL TO # proportional */
2148 { 0x221E, 0xA5 }, /* INFINITY # infinity */
2149 { 0x2220, 0xD0 }, /* ANGLE # angle */
2150 { 0x2227, 0xD9 }, /* LOGICAL AND # logicaland */
2151 { 0x2228, 0xDA }, /* LOGICAL OR # logicalor */
2152 { 0x2229, 0xC7 }, /* INTERSECTION # intersection */
2153 { 0x222A, 0xC8 }, /* UNION # union */
2154 { 0x222B, 0xF2 }, /* INTEGRAL # integral */
2155 { 0x2234, 0x5C }, /* THEREFORE # therefore */
2156 { 0x223C, 0x7E }, /* TILDE OPERATOR # similar */
2157 { 0x2245, 0x40 }, /* APPROXIMATELY EQUAL TO # congruent */
2158 { 0x2248, 0xBB }, /* ALMOST EQUAL TO # approxequal */
2159 { 0x2260, 0xB9 }, /* NOT EQUAL TO # notequal */
2160 { 0x2261, 0xBA }, /* IDENTICAL TO # equivalence */
2161 { 0x2264, 0xA3 }, /* LESS-THAN OR EQUAL TO # lessequal */
2162 { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO # greaterequal */
2163 { 0x2282, 0xCC }, /* SUBSET OF # propersubset */
2164 { 0x2283, 0xC9 }, /* SUPERSET OF # propersuperset */
2165 { 0x2284, 0xCB }, /* NOT A SUBSET OF # notsubset */
2166 { 0x2286, 0xCD }, /* SUBSET OF OR EQUAL TO # reflexsubset */
2167 { 0x2287, 0xCA }, /* SUPERSET OF OR EQUAL TO # reflexsuperset */
2168 { 0x2295, 0xC5 }, /* CIRCLED PLUS # circleplus */
2169 { 0x2297, 0xC4 }, /* CIRCLED TIMES # circlemultiply */
2170 { 0x22A5, 0x5E }, /* UP TACK # perpendicular */
2171 { 0x22C5, 0xD7 }, /* DOT OPERATOR # dotmath */
2172 { 0x2320, 0xF3 }, /* TOP HALF INTEGRAL # integraltp */
2173 { 0x2321, 0xF5 }, /* BOTTOM HALF INTEGRAL # integralbt */
2174 { 0x2329, 0xE1 }, /* LEFT-POINTING ANGLE BRACKET # angleleft */
2175 { 0x232A, 0xF1 }, /* RIGHT-POINTING ANGLE BRACKET # angleright */
2176 { 0x25CA, 0xE0 }, /* LOZENGE # lozenge */
2177 { 0x2660, 0xAA }, /* BLACK SPADE SUIT # spade */
2178 { 0x2663, 0xA7 }, /* BLACK CLUB SUIT # club */
2179 { 0x2665, 0xA9 }, /* BLACK HEART SUIT # heart */
2180 { 0x2666, 0xA8 }, /* BLACK DIAMOND SUIT # diamond */
2181 { 0xF6D9, 0xD3 }, /* COPYRIGHT SIGN SERIF # copyrightserif (CUS) */
2182 { 0xF6DA, 0xD2 }, /* REGISTERED SIGN SERIF # registerserif (CUS) */
2183 { 0xF6DB, 0xD4 }, /* TRADE MARK SIGN SERIF # trademarkserif (CUS) */
2184 { 0xF8E5, 0x60 }, /* RADICAL EXTENDER # radicalex (CUS) */
2185 { 0xF8E6, 0xBD }, /* VERTICAL ARROW EXTENDER # arrowvertex (CUS) */
2186 { 0xF8E7, 0xBE }, /* HORIZONTAL ARROW EXTENDER # arrowhorizex (CUS) */
2187 { 0xF8E8, 0xE2 }, /* REGISTERED SIGN SANS SERIF # registersans (CUS) */
2188 { 0xF8E9, 0xE3 }, /* COPYRIGHT SIGN SANS SERIF # copyrightsans (CUS) */
2189 { 0xF8EA, 0xE4 }, /* TRADE MARK SIGN SANS SERIF # trademarksans (CUS) */
2190 { 0xF8EB, 0xE6 }, /* LEFT PAREN TOP # parenlefttp (CUS) */
2191 { 0xF8EC, 0xE7 }, /* LEFT PAREN EXTENDER # parenleftex (CUS) */
2192 { 0xF8ED, 0xE8 }, /* LEFT PAREN BOTTOM # parenleftbt (CUS) */
2193 { 0xF8EE, 0xE9 }, /* LEFT SQUARE BRACKET TOP # bracketlefttp (CUS) */
2194 { 0xF8EF, 0xEA }, /* LEFT SQUARE BRACKET EXTENDER # bracketleftex (CUS) */
2195 { 0xF8F0, 0xEB }, /* LEFT SQUARE BRACKET BOTTOM # bracketleftbt (CUS) */
2196 { 0xF8F1, 0xEC }, /* LEFT CURLY BRACKET TOP # bracelefttp (CUS) */
2197 { 0xF8F2, 0xED }, /* LEFT CURLY BRACKET MID # braceleftmid (CUS) */
2198 { 0xF8F3, 0xEE }, /* LEFT CURLY BRACKET BOTTOM # braceleftbt (CUS) */
2199 { 0xF8F4, 0xEF }, /* CURLY BRACKET EXTENDER # braceex (CUS) */
2200 { 0xF8F5, 0xF4 }, /* INTEGRAL EXTENDER # integralex (CUS) */
2201 { 0xF8F6, 0xF6 }, /* RIGHT PAREN TOP # parenrighttp (CUS) */
2202 { 0xF8F7, 0xF7 }, /* RIGHT PAREN EXTENDER # parenrightex (CUS) */
2203 { 0xF8F8, 0xF8 }, /* RIGHT PAREN BOTTOM # parenrightbt (CUS) */
2204 { 0xF8F9, 0xF9 }, /* RIGHT SQUARE BRACKET TOP # bracketrighttp (CUS) */
2205 { 0xF8FA, 0xFA }, /* RIGHT SQUARE BRACKET EXTENDER # bracketrightex (CUS) */
2206 { 0xF8FB, 0xFB }, /* RIGHT SQUARE BRACKET BOTTOM # bracketrightbt (CUS) */
2207 { 0xF8FC, 0xFC }, /* RIGHT CURLY BRACKET TOP # bracerighttp (CUS) */
2208 { 0xF8FD, 0xFD }, /* RIGHT CURLY BRACKET MID # bracerightmid (CUS) */
2209 { 0xF8FE, 0xFE }, /* RIGHT CURLY BRACKET BOTTOM # bracerightbt (CUS) */
2212 static const FcCharMap AdobeSymbol
= {
2214 sizeof (AdobeSymbolEnt
) / sizeof (AdobeSymbolEnt
[0]),
2217 static const FcFontDecode fcFontDecoders
[] = {
2218 { ft_encoding_unicode
, 0, (1 << 21) - 1 },
2219 { ft_encoding_symbol
, &AdobeSymbol
, (1 << 16) - 1 },
2220 { ft_encoding_apple_roman
, &AppleRoman
, (1 << 16) - 1 },
2223 #define NUM_DECODE (int) (sizeof (fcFontDecoders) / sizeof (fcFontDecoders[0]))
2225 static const FcChar32 prefer_unicode
[] = {
2226 0x20ac, /* EURO SIGN */
2229 #define NUM_PREFER_UNICODE (int) (sizeof (prefer_unicode) / sizeof (prefer_unicode[0]))
2232 FcFreeTypeUcs4ToPrivate (FcChar32 ucs4
, const FcCharMap
*map
)
2238 high
= map
->nent
- 1;
2239 if (ucs4
< map
->ent
[low
].bmp
|| map
->ent
[high
].bmp
< ucs4
)
2243 mid
= (high
+ low
) >> 1;
2244 bmp
= map
->ent
[mid
].bmp
;
2246 return (FT_ULong
) map
->ent
[mid
].encode
;
2256 FcFreeTypePrivateToUcs4 (FcChar32
private, const FcCharMap
*map
)
2260 for (i
= 0; i
< map
->nent
; i
++)
2261 if (map
->ent
[i
].encode
== private)
2262 return (FcChar32
) map
->ent
[i
].bmp
;
2267 FcFreeTypeGetPrivateMap (FT_Encoding encoding
)
2271 for (i
= 0; i
< NUM_DECODE
; i
++)
2272 if (fcFontDecoders
[i
].encoding
== encoding
)
2273 return fcFontDecoders
[i
].map
;
2277 #include "../fc-glyphname/fcglyphname.h"
2280 FcHashGlyphName (const FcChar8
*name
)
2285 while ((c
= *name
++))
2287 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
2292 #if HAVE_FT_HAS_PS_GLYPH_NAMES
2294 * Use Type1 glyph names for fonts which have reliable names
2295 * and which export an Adobe Custom mapping
2298 FcFreeTypeUseNames (FT_Face face
)
2302 if (!FT_Has_PS_Glyph_Names (face
))
2304 for (map
= 0; map
< face
->num_charmaps
; map
++)
2305 if (face
->charmaps
[map
]->encoding
== ft_encoding_adobe_custom
)
2310 static const FcChar8
*
2311 FcUcs4ToGlyphName (FcChar32 ucs4
)
2313 int i
= (int) (ucs4
% FC_GLYPHNAME_HASH
);
2317 while ((gn
= ucs_to_name
[i
]) != -1)
2319 if (glyphs
[gn
].ucs
== ucs4
)
2320 return glyphs
[gn
].name
;
2323 r
= (int) (ucs4
% FC_GLYPHNAME_REHASH
);
2328 if (i
>= FC_GLYPHNAME_HASH
)
2329 i
-= FC_GLYPHNAME_HASH
;
2335 FcGlyphNameToUcs4 (FcChar8
*name
)
2337 FcChar32 h
= FcHashGlyphName (name
);
2338 int i
= (int) (h
% FC_GLYPHNAME_HASH
);
2342 while ((gn
= name_to_ucs
[i
]) != -1)
2344 if (!strcmp ((char *) name
, (char *) glyphs
[gn
].name
))
2345 return glyphs
[gn
].ucs
;
2348 r
= (int) (h
% FC_GLYPHNAME_REHASH
);
2353 if (i
>= FC_GLYPHNAME_HASH
)
2354 i
-= FC_GLYPHNAME_HASH
;
2360 * Work around a bug in some FreeType versions which fail
2361 * to correctly bounds check glyph name buffers and overwrite
2362 * the stack. As Postscript names have a limit of 127 characters,
2363 * this should be sufficient.
2366 #if FC_GLYPHNAME_MAXLEN < 127
2367 # define FC_GLYPHNAME_BUFLEN 127
2369 # define FC_GLYPHNAME_BUFLEN FC_GLYPHNAME_MAXLEN
2373 * Search through a font for a glyph by name. This is
2374 * currently a linear search as there doesn't appear to be
2375 * any defined order within the font
2378 FcFreeTypeGlyphNameIndex (FT_Face face
, const FcChar8
*name
)
2381 FcChar8 name_buf
[FC_GLYPHNAME_BUFLEN
+ 2];
2383 for (gindex
= 0; gindex
< (FT_UInt
) face
->num_glyphs
; gindex
++)
2385 if (FT_Get_Glyph_Name (face
, gindex
, name_buf
, FC_GLYPHNAME_BUFLEN
+1) == 0)
2386 if (!strcmp ((char *) name
, (char *) name_buf
))
2394 * Map a UCS4 glyph to a glyph index. Use all available encoding
2395 * tables to try and find one that works. This information is expected
2396 * to be cached by higher levels, so performance isn't critical
2400 FcFreeTypeCharIndex (FT_Face face
, FcChar32 ucs4
)
2402 int initial
, offset
, decode
;
2413 * Find the current encoding
2417 for (; initial
< NUM_DECODE
; initial
++)
2418 if (fcFontDecoders
[initial
].encoding
== face
->charmap
->encoding
)
2420 if (initial
== NUM_DECODE
)
2423 for (p
= 0; p
< NUM_PREFER_UNICODE
; p
++)
2424 if (ucs4
== prefer_unicode
[p
])
2430 * Check each encoding for the glyph, starting with the current one
2432 for (offset
= 0; offset
< NUM_DECODE
; offset
++)
2434 decode
= (initial
+ offset
) % NUM_DECODE
;
2435 if (!face
->charmap
|| face
->charmap
->encoding
!= fcFontDecoders
[decode
].encoding
)
2436 if (FT_Select_Charmap (face
, fcFontDecoders
[decode
].encoding
) != 0)
2438 if (fcFontDecoders
[decode
].map
)
2440 charcode
= FcFreeTypeUcs4ToPrivate (ucs4
, fcFontDecoders
[decode
].map
);
2441 if (charcode
== ~0U)
2446 glyphindex
= FT_Get_Char_Index (face
, (FT_ULong
) charcode
);
2450 #if HAVE_FT_HAS_PS_GLYPH_NAMES
2452 * Check postscript name table if present
2454 if (FcFreeTypeUseNames (face
))
2456 const FcChar8
*name
= FcUcs4ToGlyphName (ucs4
);
2459 glyphindex
= FcFreeTypeGlyphNameIndex (face
, name
);
2469 FcFreeTypeCheckGlyph (FT_Face face
, FcChar32 ucs4
,
2470 FT_UInt glyph
, FcBlanks
*blanks
,
2472 FcBool using_strike
)
2474 FT_Int load_flags
= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
| FT_LOAD_NO_SCALE
| FT_LOAD_NO_HINTING
;
2478 load_flags
&= ~FT_LOAD_NO_SCALE
;
2481 * When using scalable fonts, only report those glyphs
2482 * which can be scaled; otherwise those fonts will
2483 * only be available at some sizes, and never when
2484 * transformed. Avoid this by simply reporting bitmap-only
2487 if (face
->face_flags
& FT_FACE_FLAG_SCALABLE
)
2488 load_flags
|= FT_LOAD_NO_BITMAP
;
2490 if (FT_Load_Glyph (face
, glyph
, load_flags
))
2497 *advance
= slot
->metrics
.horiAdvance
;
2499 switch (slot
->format
) {
2500 case ft_glyph_format_bitmap
:
2502 * Bitmaps are assumed to be reasonable; if
2503 * this proves to be a rash assumption, this
2504 * code can be easily modified
2507 case ft_glyph_format_outline
:
2509 * Glyphs with contours are always OK
2511 if (slot
->outline
.n_contours
!= 0)
2514 * Glyphs with no contours are only OK if
2515 * they're members of the Blanks set specified
2516 * in the configuration. If blanks isn't set,
2517 * then allow any glyph to be blank
2519 if (!blanks
|| FcBlanksIsMember (blanks
, ucs4
))
2521 /* fall through ... */
2528 #define FC_MIN(a,b) ((a) < (b) ? (a) : (b))
2529 #define FC_MAX(a,b) ((a) > (b) ? (a) : (b))
2530 #define FC_ABS(a) ((a) < 0 ? -(a) : (a))
2531 #define APPROXIMATELY_EQUAL(x,y) (FC_ABS ((x) - (y)) <= FC_MAX (FC_ABS (x), FC_ABS (y)) / 33)
2534 FcFreeTypeCharSetAndSpacingForSize (FT_Face face
, FcBlanks
*blanks
, int *spacing
, FT_Int strike_index
)
2536 FcChar32 page
, off
, ucs4
;
2538 FcChar32 font_max
= 0;
2542 const FcCharMap
*map
;
2546 FT_Pos advance
, advance_one
= 0, advance_two
= 0;
2547 FcBool has_advance
= FcFalse
, fixed_advance
= FcTrue
, dual_advance
= FcFalse
;
2548 FcBool using_strike
= FcFalse
;
2550 fcs
= FcCharSetCreate ();
2554 #if HAVE_FT_SELECT_SIZE
2555 if (strike_index
>= 0) {
2556 if (FT_Select_Size (face
, strike_index
) != FT_Err_Ok
)
2558 using_strike
= FcTrue
;
2563 printf ("Family %s style %s\n", face
->family_name
, face
->style_name
);
2565 for (o
= 0; o
< NUM_DECODE
; o
++)
2567 if (FT_Select_Charmap (face
, fcFontDecoders
[o
].encoding
) != 0)
2569 map
= fcFontDecoders
[o
].map
;
2573 * Non-Unicode tables are easy; there's a list of all possible
2576 for (i
= 0; i
< map
->nent
; i
++)
2578 ucs4
= map
->ent
[i
].bmp
;
2579 glyph
= FT_Get_Char_Index (face
, map
->ent
[i
].encode
);
2581 FcFreeTypeCheckGlyph (face
, ucs4
, glyph
, blanks
, &advance
, using_strike
))
2584 * ignore glyphs with zero advance. They’re
2585 * combining characters, and while their behaviour
2586 * isn’t well defined for monospaced applications in
2587 * Unicode, there are many fonts which include
2588 * zero-width combining characters in otherwise
2595 has_advance
= FcTrue
;
2596 advance_one
= advance
;
2598 else if (!APPROXIMATELY_EQUAL (advance
, advance_one
))
2602 dual_advance
= FcTrue
;
2603 fixed_advance
= FcFalse
;
2604 advance_two
= advance
;
2606 else if (!APPROXIMATELY_EQUAL (advance
, advance_two
))
2607 dual_advance
= FcFalse
;
2611 leaf
= FcCharSetFindLeafCreate (fcs
, ucs4
);
2614 leaf
->map
[(ucs4
& 0xff) >> 5] |= (1 << (ucs4
& 0x1f));
2616 if (ucs4
> font_max
)
2626 ucs4
= FT_Get_First_Char (face
, &glyph
);
2629 if (FcFreeTypeCheckGlyph (face
, ucs4
, glyph
, blanks
, &advance
, using_strike
))
2635 has_advance
= FcTrue
;
2636 advance_one
= advance
;
2638 else if (!APPROXIMATELY_EQUAL (advance
, advance_one
))
2642 dual_advance
= FcTrue
;
2643 fixed_advance
= FcFalse
;
2644 advance_two
= advance
;
2646 else if (!APPROXIMATELY_EQUAL (advance
, advance_two
))
2647 dual_advance
= FcFalse
;
2651 if ((ucs4
>> 8) != page
)
2654 leaf
= FcCharSetFindLeafCreate (fcs
, ucs4
);
2659 leaf
->map
[off
>> 5] |= (1 << (off
& 0x1f));
2661 if (ucs4
> font_max
)
2665 ucs4
= FT_Get_Next_Char (face
, ucs4
, &glyph
);
2668 for (ucs4
= 0; ucs4
< 0x10000; ucs4
++)
2670 FcBool FT_Has
, FC_Has
;
2672 FT_Has
= FT_Get_Char_Index (face
, ucs4
) != 0;
2673 FC_Has
= FcCharSetHasChar (fcs
, ucs4
);
2674 if (FT_Has
!= FC_Has
)
2676 printf ("0x%08x FT says %d FC says %d\n", ucs4
, FT_Has
, FC_Has
);
2682 #if HAVE_FT_HAS_PS_GLYPH_NAMES
2684 * Add mapping from PS glyph names if available
2686 if (FcFreeTypeUseNames (face
))
2688 FcChar8 name_buf
[FC_GLYPHNAME_BUFLEN
+ 2];
2690 for (glyph
= 0; glyph
< (FT_UInt
) face
->num_glyphs
; glyph
++)
2692 if (FT_Get_Glyph_Name (face
, glyph
, name_buf
, FC_GLYPHNAME_BUFLEN
+1) == 0)
2694 ucs4
= FcGlyphNameToUcs4 (name_buf
);
2695 if (ucs4
!= 0xffff &&
2696 FcFreeTypeCheckGlyph (face
, ucs4
, glyph
, blanks
, &advance
, using_strike
))
2702 has_advance
= FcTrue
;
2703 advance_one
= advance
;
2705 else if (!APPROXIMATELY_EQUAL (advance
, advance_one
))
2709 dual_advance
= FcTrue
;
2710 fixed_advance
= FcFalse
;
2711 advance_two
= advance
;
2713 else if (!APPROXIMATELY_EQUAL (advance
, advance_two
))
2714 dual_advance
= FcFalse
;
2717 leaf
= FcCharSetFindLeafCreate (fcs
, ucs4
);
2720 leaf
->map
[(ucs4
& 0xff) >> 5] |= (1 << (ucs4
& 0x1f));
2722 if (ucs4
> font_max
)
2731 printf ("%d glyphs %d encoded\n", (int) face
->num_glyphs
, FcCharSetCount (fcs
));
2732 for (ucs4
= 0; ucs4
<= font_max
; ucs4
++)
2734 FcBool has_char
= (glyph
= FcFreeTypeCharIndex (face
, ucs4
)) != 0;
2735 FcBool has_bit
= FcCharSetHasChar (fcs
, ucs4
);
2737 if (has_char
&& !has_bit
)
2739 if (!FcFreeTypeCheckGlyph (face
, ucs4
, glyph
, blanks
, &advance
, using_strike
))
2740 printf ("Bitmap missing broken char 0x%x\n", ucs4
);
2742 printf ("Bitmap missing char 0x%x\n", ucs4
);
2744 else if (!has_char
&& has_bit
)
2745 printf ("Bitmap extra char 0x%x\n", ucs4
);
2750 else if (dual_advance
&& APPROXIMATELY_EQUAL (2 * FC_MIN (advance_one
, advance_two
), FC_MAX (advance_one
, advance_two
)))
2753 *spacing
= FC_PROPORTIONAL
;
2756 FcCharSetDestroy (fcs
);
2762 FcFreeTypeCharSetAndSpacing (FT_Face face
, FcBlanks
*blanks
, int *spacing
)
2766 cs
= FcFreeTypeCharSetAndSpacingForSize (face
, blanks
, spacing
, -1);
2768 * Check for bitmap-only ttf fonts that are missing the glyf table.
2769 * In that case, pick a size and look for glyphs in that size instead
2771 if (FcCharSetCount (cs
) == 0)
2773 /* Check for non-scalable TT fonts */
2774 if (!(face
->face_flags
& FT_FACE_FLAG_SCALABLE
) &&
2775 face
->num_fixed_sizes
> 0 &&
2776 FT_Get_Sfnt_Table (face
, ft_sfnt_head
))
2778 FT_Int strike_index
= 0;
2781 /* Select the face closest to 16 pixels tall */
2782 for (i
= 1; i
< face
->num_fixed_sizes
; i
++) {
2783 if (abs (face
->available_sizes
[i
].height
- 16) <
2784 abs (face
->available_sizes
[strike_index
].height
- 16))
2787 FcCharSetDestroy (cs
);
2788 cs
= FcFreeTypeCharSetAndSpacingForSize (face
, blanks
, spacing
, strike_index
);
2795 FcFreeTypeCharSet (FT_Face face
, FcBlanks
*blanks
)
2799 return FcFreeTypeCharSetAndSpacing (face
, blanks
, &spacing
);
2803 #define TTAG_GPOS FT_MAKE_TAG( 'G', 'P', 'O', 'S' )
2804 #define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' )
2805 #define TTAG_SILF FT_MAKE_TAG( 'S', 'i', 'l', 'f')
2806 #define TT_Err_Ok FT_Err_Ok
2807 #define TT_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle
2808 #define TTO_Err_Empty_Script 0x1005
2809 #define TTO_Err_Invalid_SubTable 0x1001
2811 #define OTLAYOUT_HEAD "otlayout:"
2812 #define OTLAYOUT_HEAD_LEN 9
2813 #define OTLAYOUT_ID_LEN 4
2814 /* space + head + id */
2815 #define OTLAYOUT_LEN (1 + OTLAYOUT_HEAD_LEN + OTLAYOUT_ID_LEN)
2818 * This is a bit generous; the registry has only lower case and space
2819 * except for 'DFLT'.
2821 #define FcIsSpace(x) (040 == (x))
2822 #define FcIsValidScript(x) (FcIsLower(x) || FcIsUpper (x) || FcIsSpace(x))
2825 addtag(FcChar8
*complex, FT_ULong tag
)
2827 FcChar8 tagstring
[OTLAYOUT_ID_LEN
+ 1];
2829 tagstring
[0] = (FcChar8
)(tag
>> 24),
2830 tagstring
[1] = (FcChar8
)(tag
>> 16),
2831 tagstring
[2] = (FcChar8
)(tag
>> 8),
2832 tagstring
[3] = (FcChar8
)(tag
);
2833 tagstring
[4] = '\0';
2835 /* skip tags which aren't alphabetic, under the assumption that
2836 * they're probably broken
2838 if (!FcIsValidScript(tagstring
[0]) ||
2839 !FcIsValidScript(tagstring
[1]) ||
2840 !FcIsValidScript(tagstring
[2]) ||
2841 !FcIsValidScript(tagstring
[3]))
2844 if (*complex != '\0')
2845 strcat ((char *) complex, " ");
2846 strcat ((char *) complex, "otlayout:");
2847 strcat ((char *) complex, (char *) tagstring
);
2851 compareulong (const void *a
, const void *b
)
2853 const FT_ULong
*ua
= (const FT_ULong
*) a
;
2854 const FT_ULong
*ub
= (const FT_ULong
*) b
;
2860 GetScriptTags(FT_Face face
, FT_ULong tabletag
, FT_ULong
**stags
, FT_UShort
*script_count
)
2862 FT_ULong cur_offset
, new_offset
, base_offset
;
2863 FT_Stream stream
= face
->stream
;
2869 return TT_Err_Invalid_Face_Handle
;
2871 memory
= stream
->memory
;
2873 if (( error
= ftglue_face_goto_table( face
, tabletag
, stream
) ))
2876 base_offset
= ftglue_stream_pos ( stream
);
2880 if ( ftglue_stream_seek ( stream
, base_offset
+ 4L ) || ftglue_stream_frame_enter( stream
, 2L ) )
2883 new_offset
= GET_UShort() + base_offset
;
2885 ftglue_stream_frame_exit( stream
);
2887 cur_offset
= ftglue_stream_pos( stream
);
2889 if ( ftglue_stream_seek( stream
, new_offset
) != TT_Err_Ok
)
2892 base_offset
= ftglue_stream_pos( stream
);
2894 if ( ftglue_stream_frame_enter( stream
, 2L ) )
2897 *script_count
= GET_UShort ();
2899 ftglue_stream_frame_exit( stream
);
2901 *stags
= ftglue_alloc(memory
, *script_count
* sizeof( FT_ULong
), &error
);
2907 for ( n
= 0; n
< *script_count
; n
++ )
2909 if ( ftglue_stream_frame_enter( stream
, 6L ) )
2912 (*stags
)[p
] = GET_ULong ();
2913 new_offset
= GET_UShort () + base_offset
;
2915 ftglue_stream_frame_exit( stream
);
2917 cur_offset
= ftglue_stream_pos( stream
);
2919 error
= ftglue_stream_seek( stream
, new_offset
);
2921 if ( error
== TT_Err_Ok
)
2924 (void)ftglue_stream_seek( stream
, cur_offset
);
2929 error
= TTO_Err_Invalid_SubTable
;
2933 /* sort the tag list before returning it */
2934 qsort(*stags
, *script_count
, sizeof(FT_ULong
), compareulong
);
2940 ftglue_free( memory
, *stags
);
2946 FcFontCapabilities(FT_Face face
)
2948 FcBool issilgraphitefont
= 0;
2951 FT_ULong
*gsubtags
=NULL
, *gpostags
=NULL
;
2952 FT_UShort gsub_count
=0, gpos_count
=0;
2954 FT_Memory memory
= face
->stream
->memory
;
2955 FcChar8
*complex = NULL
;
2956 int indx1
= 0, indx2
= 0;
2958 err
= FT_Load_Sfnt_Table(face
, TTAG_SILF
, 0, 0, &len
);
2959 issilgraphitefont
= ( err
== FT_Err_Ok
);
2961 if (GetScriptTags(face
, TTAG_GPOS
, &gpostags
, &gpos_count
) != FT_Err_Ok
)
2963 if (GetScriptTags(face
, TTAG_GSUB
, &gsubtags
, &gsub_count
) != FT_Err_Ok
)
2966 if (!issilgraphitefont
&& !gsub_count
&& !gpos_count
)
2969 maxsize
= (((FT_ULong
) gpos_count
+ (FT_ULong
) gsub_count
) * OTLAYOUT_LEN
+
2970 (issilgraphitefont
? 13 : 0));
2971 complex = malloc (sizeof (FcChar8
) * maxsize
);
2976 if (issilgraphitefont
)
2977 strcpy((char *) complex, "ttable:Silf ");
2979 while ((indx1
< gsub_count
) || (indx2
< gpos_count
)) {
2980 if (indx1
== gsub_count
) {
2981 addtag(complex, gpostags
[indx2
]);
2983 } else if ((indx2
== gpos_count
) || (gsubtags
[indx1
] < gpostags
[indx2
])) {
2984 addtag(complex, gsubtags
[indx1
]);
2986 } else if (gsubtags
[indx1
] == gpostags
[indx2
]) {
2987 addtag(complex, gsubtags
[indx1
]);
2991 addtag(complex, gpostags
[indx2
]);
2995 if (FcDebug () & FC_DBG_SCANV
)
2996 printf("complex features in this font: %s\n", complex);
2998 ftglue_free(memory
, gsubtags
);
2999 ftglue_free(memory
, gpostags
);
3003 #define __fcfreetype__
3004 #include "fcaliastail.h"
3005 #include "fcftaliastail.h"
3006 #undef __fcfreetype__