2 * $RCSId: xc/lib/fontconfig/src/fcfreetype.c,v 1.11 2002/08/31 22:17:32 keithp Exp $
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
52 #include FT_FREETYPE_H
53 #include FT_TRUETYPE_TABLES_H
54 #include FT_SFNT_NAMES_H
55 #include FT_TRUETYPE_IDS_H
56 #include FT_TYPE1_TABLES_H
57 #if HAVE_FT_GET_X11_FONT_FORMAT
60 #if HAVE_FT_GET_BDF_PROPERTY
67 #if HAVE_WARNING_CPP_DIRECTIVE
68 #if !HAVE_FT_GET_BDF_PROPERTY
69 #warning "No FT_Get_BDF_Property: Please install freetype 2.1.4 or later"
72 #if !HAVE_FT_GET_PS_FONT_INFO
73 #warning "No FT_Get_PS_Font_Info: Please install freetype 2.1.1 or later"
78 * Keep Han languages separated by eliminating languages
79 * that the codePageRange bits says aren't supported
85 } FcCodePageRange
[] = {
86 { 17, (const FcChar8
*) "ja" },
87 { 18, (const FcChar8
*) "zh-cn" },
88 { 19, (const FcChar8
*) "ko" },
89 { 20, (const FcChar8
*) "zh-tw" },
92 #define NUM_CODE_PAGE_RANGE (int) (sizeof FcCodePageRange / sizeof FcCodePageRange[0])
95 FcFreeTypeIsExclusiveLang (const FcChar8
*lang
)
99 for (i
= 0; i
< NUM_CODE_PAGE_RANGE
; i
++)
101 if (FcLangCompare (lang
, FcCodePageRange
[i
].lang
) == FcLangEqual
)
108 const FT_UShort platform_id
;
109 const FT_UShort encoding_id
;
110 const char fromcode
[12];
113 #define TT_ENCODING_DONT_CARE 0xffff
114 #define FC_ENCODING_MAC_ROMAN "MACINTOSH"
116 static const FcFtEncoding fcFtEncoding
[] = {
117 { TT_PLATFORM_APPLE_UNICODE
, TT_ENCODING_DONT_CARE
, "UCS-2BE" },
118 { TT_PLATFORM_MACINTOSH
, TT_MAC_ID_ROMAN
, "MACINTOSH" },
119 { TT_PLATFORM_MACINTOSH
, TT_MAC_ID_JAPANESE
, "SJIS" },
120 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_UNICODE_CS
, "UTF-16BE" },
121 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_SJIS
, "SJIS-WIN" },
122 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_GB2312
, "GB3212" },
123 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_BIG_5
, "BIG-5" },
124 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_WANSUNG
, "Wansung" },
125 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_JOHAB
, "Johab" },
126 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_UCS_4
, "UCS4" },
127 { TT_PLATFORM_ISO
, TT_ISO_ID_7BIT_ASCII
, "ASCII" },
128 { TT_PLATFORM_ISO
, TT_ISO_ID_10646
, "UCS-2BE" },
129 { TT_PLATFORM_ISO
, TT_ISO_ID_8859_1
, "ISO-8859-1" },
132 #define NUM_FC_FT_ENCODING (int) (sizeof (fcFtEncoding) / sizeof (fcFtEncoding[0]))
135 const FT_UShort platform_id
;
136 const FT_UShort language_id
;
140 #define TT_LANGUAGE_DONT_CARE 0xffff
142 static const FcFtLanguage fcFtLanguage
[] = {
143 { TT_PLATFORM_APPLE_UNICODE
, TT_LANGUAGE_DONT_CARE
, "" },
144 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ENGLISH
, "en" },
145 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_FRENCH
, "fr" },
146 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GERMAN
, "de" },
147 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ITALIAN
, "it" },
148 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_DUTCH
, "nl" },
149 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SWEDISH
, "sv" },
150 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SPANISH
, "es" },
151 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_DANISH
, "da" },
152 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_PORTUGUESE
, "pt" },
153 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_NORWEGIAN
, "no" },
154 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_HEBREW
, "he" },
155 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_JAPANESE
, "ja" },
156 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ARABIC
, "ar" },
157 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_FINNISH
, "fi" },
158 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GREEK
, "el" },
159 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ICELANDIC
, "is" },
160 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MALTESE
, "mt" },
161 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TURKISH
, "tr" },
162 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CROATIAN
, "hr" },
163 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CHINESE_TRADITIONAL
, "zh-tw" },
164 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_URDU
, "ur" },
165 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_HINDI
, "hi" },
166 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_THAI
, "th" },
167 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KOREAN
, "ko" },
168 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_LITHUANIAN
, "lt" },
169 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_POLISH
, "pl" },
170 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_HUNGARIAN
, "hu" },
171 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ESTONIAN
, "et" },
172 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_LETTISH
, "lv" },
173 /* { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SAAMISK, ??? */
174 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_FAEROESE
, "fo" },
175 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_FARSI
, "fa" },
176 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_RUSSIAN
, "ru" },
177 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CHINESE_SIMPLIFIED
, "zh-cn" },
178 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_FLEMISH
, "nl" },
179 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_IRISH
, "ga" },
180 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ALBANIAN
, "sq" },
181 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ROMANIAN
, "ro" },
182 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CZECH
, "cs" },
183 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SLOVAK
, "sk" },
184 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SLOVENIAN
, "sl" },
185 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_YIDDISH
, "yi" },
186 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SERBIAN
, "sr" },
187 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MACEDONIAN
, "mk" },
188 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BULGARIAN
, "bg" },
189 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_UKRAINIAN
, "uk" },
190 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BYELORUSSIAN
, "be" },
191 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_UZBEK
, "uz" },
192 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KAZAKH
, "kk" },
193 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AZERBAIJANI
, "az" },
194 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT
, "az" },
195 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT
, "ar" },
196 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ARMENIAN
, "hy" },
197 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GEORGIAN
, "ka" },
198 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MOLDAVIAN
, "mo" },
199 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KIRGHIZ
, "ky" },
200 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TAJIKI
, "tg" },
201 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TURKMEN
, "tk" },
202 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MONGOLIAN
, "mo" },
203 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT
,"mo" },
204 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT
, "mo" },
205 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_PASHTO
, "ps" },
206 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KURDISH
, "ku" },
207 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KASHMIRI
, "ks" },
208 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SINDHI
, "sd" },
209 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TIBETAN
, "bo" },
210 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_NEPALI
, "ne" },
211 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SANSKRIT
, "sa" },
212 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MARATHI
, "mr" },
213 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BENGALI
, "bn" },
214 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ASSAMESE
, "as" },
215 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GUJARATI
, "gu" },
216 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_PUNJABI
, "pa" },
217 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ORIYA
, "or" },
218 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MALAYALAM
, "ml" },
219 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KANNADA
, "kn" },
220 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TAMIL
, "ta" },
221 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TELUGU
, "te" },
222 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SINHALESE
, "si" },
223 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BURMESE
, "my" },
224 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KHMER
, "km" },
225 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_LAO
, "lo" },
226 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_VIETNAMESE
, "vi" },
227 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_INDONESIAN
, "id" },
228 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TAGALOG
, "tl" },
229 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MALAY_ROMAN_SCRIPT
, "ms" },
230 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MALAY_ARABIC_SCRIPT
, "ms" },
231 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AMHARIC
, "am" },
232 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TIGRINYA
, "ti" },
233 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GALLA
, "om" },
234 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SOMALI
, "so" },
235 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SWAHILI
, "sw" },
236 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_RUANDA
, "rw" },
237 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_RUNDI
, "rn" },
238 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CHEWA
, "ny" },
239 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MALAGASY
, "mg" },
240 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ESPERANTO
, "eo" },
241 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_WELSH
, "cy" },
242 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BASQUE
, "eu" },
243 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CATALAN
, "ca" },
244 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_LATIN
, "la" },
245 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_QUECHUA
, "qu" },
246 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GUARANI
, "gn" },
247 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AYMARA
, "ay" },
248 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TATAR
, "tt" },
249 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_UIGHUR
, "ug" },
250 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_DZONGKHA
, "dz" },
251 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_JAVANESE
, "jw" },
252 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SUNDANESE
, "su" },
254 #if 0 /* these seem to be errors that have been dropped */
256 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SCOTTISH_GAELIC
},
257 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_IRISH_GAELIC
},
261 /* The following codes are new as of 2000-03-10 */
262 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GALICIAN
, "gl" },
263 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AFRIKAANS
, "af" },
264 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BRETON
, "br" },
265 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_INUKTITUT
, "iu" },
266 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SCOTTISH_GAELIC
, "gd" },
267 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MANX_GAELIC
, "gv" },
268 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_IRISH_GAELIC
, "ga" },
269 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TONGAN
, "to" },
270 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GREEK_POLYTONIC
, "el" },
271 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GREELANDIC
, "ik" },
272 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT
,"az" },
274 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_SAUDI_ARABIA
, "ar" },
275 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_IRAQ
, "ar" },
276 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_EGYPT
, "ar" },
277 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_LIBYA
, "ar" },
278 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_ALGERIA
, "ar" },
279 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_MOROCCO
, "ar" },
280 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_TUNISIA
, "ar" },
281 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_OMAN
, "ar" },
282 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_YEMEN
, "ar" },
283 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_SYRIA
, "ar" },
284 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_JORDAN
, "ar" },
285 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_LEBANON
, "ar" },
286 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_KUWAIT
, "ar" },
287 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_UAE
, "ar" },
288 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_BAHRAIN
, "ar" },
289 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_QATAR
, "ar" },
290 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BULGARIAN_BULGARIA
, "bg" },
291 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CATALAN_SPAIN
, "ca" },
292 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_TAIWAN
, "zh-tw" },
293 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_PRC
, "zh-cn" },
294 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_HONG_KONG
, "zh-hk" },
295 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_SINGAPORE
, "zh-sg" },
297 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_MACAU
, "zh-mo" },
299 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CZECH_CZECH_REPUBLIC
, "cs" },
300 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_DANISH_DENMARK
, "da" },
301 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GERMAN_GERMANY
, "de" },
302 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GERMAN_SWITZERLAND
, "de" },
303 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GERMAN_AUSTRIA
, "de" },
304 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GERMAN_LUXEMBOURG
, "de" },
305 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GERMAN_LIECHTENSTEI
, "de" },
306 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GREEK_GREECE
, "el" },
307 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_UNITED_STATES
, "en" },
308 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_UNITED_KINGDOM
, "en" },
309 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_AUSTRALIA
, "en" },
310 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_CANADA
, "en" },
311 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_NEW_ZEALAND
, "en" },
312 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_IRELAND
, "en" },
313 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_SOUTH_AFRICA
, "en" },
314 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_JAMAICA
, "en" },
315 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_CARIBBEAN
, "en" },
316 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_BELIZE
, "en" },
317 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_TRINIDAD
, "en" },
318 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_ZIMBABWE
, "en" },
319 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_PHILIPPINES
, "en" },
320 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT
,"es" },
321 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_MEXICO
, "es" },
322 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT
,"es" },
323 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_GUATEMALA
, "es" },
324 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_COSTA_RICA
, "es" },
325 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_PANAMA
, "es" },
326 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC
,"es" },
327 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_VENEZUELA
, "es" },
328 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_COLOMBIA
, "es" },
329 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_PERU
, "es" },
330 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_ARGENTINA
, "es" },
331 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_ECUADOR
, "es" },
332 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_CHILE
, "es" },
333 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_URUGUAY
, "es" },
334 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_PARAGUAY
, "es" },
335 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_BOLIVIA
, "es" },
336 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_EL_SALVADOR
, "es" },
337 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_HONDURAS
, "es" },
338 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_NICARAGUA
, "es" },
339 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_PUERTO_RICO
, "es" },
340 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FINNISH_FINLAND
, "fi" },
341 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_FRANCE
, "fr" },
342 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_BELGIUM
, "fr" },
343 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_CANADA
, "fr" },
344 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_SWITZERLAND
, "fr" },
345 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_LUXEMBOURG
, "fr" },
346 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_MONACO
, "fr" },
347 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_HEBREW_ISRAEL
, "he" },
348 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_HUNGARIAN_HUNGARY
, "hu" },
349 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ICELANDIC_ICELAND
, "is" },
350 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ITALIAN_ITALY
, "it" },
351 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ITALIAN_SWITZERLAND
, "it" },
352 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_JAPANESE_JAPAN
, "ja" },
353 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA
,"ko" },
354 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KOREAN_JOHAB_KOREA
, "ko" },
355 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_DUTCH_NETHERLANDS
, "nl" },
356 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_DUTCH_BELGIUM
, "nl" },
357 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL
, "no" },
358 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK
, "nn" },
359 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_POLISH_POLAND
, "pl" },
360 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PORTUGUESE_BRAZIL
, "pt" },
361 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PORTUGUESE_PORTUGAL
, "pt" },
362 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND
,"rm" },
363 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ROMANIAN_ROMANIA
, "ro" },
364 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MOLDAVIAN_MOLDAVIA
, "mo" },
365 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_RUSSIAN_RUSSIA
, "ru" },
366 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_RUSSIAN_MOLDAVIA
, "ru" },
367 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CROATIAN_CROATIA
, "hr" },
368 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SERBIAN_SERBIA_LATIN
, "sr" },
369 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC
, "sr" },
370 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SLOVAK_SLOVAKIA
, "sk" },
371 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ALBANIAN_ALBANIA
, "sq" },
372 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SWEDISH_SWEDEN
, "sv" },
373 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SWEDISH_FINLAND
, "sv" },
374 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_THAI_THAILAND
, "th" },
375 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TURKISH_TURKEY
, "tr" },
376 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_URDU_PAKISTAN
, "ur" },
377 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_INDONESIAN_INDONESIA
, "id" },
378 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_UKRAINIAN_UKRAINE
, "uk" },
379 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BELARUSIAN_BELARUS
, "be" },
380 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SLOVENE_SLOVENIA
, "sl" },
381 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ESTONIAN_ESTONIA
, "et" },
382 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_LATVIAN_LATVIA
, "lv" },
383 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_LITHUANIAN_LITHUANIA
, "lt" },
384 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA
,"lt" },
386 #ifdef TT_MS_LANGID_MAORI_NEW_ZELAND
387 /* this seems to be an error that have been dropped */
388 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MAORI_NEW_ZEALAND
, "mi" },
391 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FARSI_IRAN
, "fa" },
392 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_VIETNAMESE_VIET_NAM
, "vi" },
393 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARMENIAN_ARMENIA
, "hy" },
394 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN
, "az" },
395 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC
, "az" },
396 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BASQUE_SPAIN
, "eu" },
397 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SORBIAN_GERMANY
, "wen" },
398 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MACEDONIAN_MACEDONIA
, "mk" },
399 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SUTU_SOUTH_AFRICA
, "st" },
400 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TSONGA_SOUTH_AFRICA
, "ts" },
401 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TSWANA_SOUTH_AFRICA
, "tn" },
402 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_VENDA_SOUTH_AFRICA
, "ven" },
403 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_XHOSA_SOUTH_AFRICA
, "xh" },
404 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ZULU_SOUTH_AFRICA
, "zu" },
405 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA
, "af" },
406 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GEORGIAN_GEORGIA
, "ka" },
407 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS
, "fo" },
408 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_HINDI_INDIA
, "hi" },
409 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MALTESE_MALTA
, "mt" },
410 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SAAMI_LAPONIA
, "se" },
412 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM
,"gd" },
413 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_IRISH_GAELIC_IRELAND
, "ga" },
415 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MALAY_MALAYSIA
, "ms" },
416 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM
, "ms" },
417 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KAZAK_KAZAKSTAN
, "kk" },
418 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SWAHILI_KENYA
, "sw" },
419 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN
, "uz" },
420 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC
, "uz" },
421 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TATAR_TATARSTAN
, "tt" },
422 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BENGALI_INDIA
, "bn" },
423 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PUNJABI_INDIA
, "pa" },
424 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GUJARATI_INDIA
, "gu" },
425 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ORIYA_INDIA
, "or" },
426 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TAMIL_INDIA
, "ta" },
427 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TELUGU_INDIA
, "te" },
428 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KANNADA_INDIA
, "kn" },
429 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MALAYALAM_INDIA
, "ml" },
430 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ASSAMESE_INDIA
, "as" },
431 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MARATHI_INDIA
, "mr" },
432 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SANSKRIT_INDIA
, "sa" },
433 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KONKANI_INDIA
, "kok" },
435 /* new as of 2001-01-01 */
436 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_GENERAL
, "ar" },
437 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_GENERAL
, "zh" },
438 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_GENERAL
, "en" },
439 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_WEST_INDIES
, "fr" },
440 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_REUNION
, "fr" },
441 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_CONGO
, "fr" },
443 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_SENEGAL
, "fr" },
444 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_CAMEROON
, "fr" },
445 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_COTE_D_IVOIRE
, "fr" },
446 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_MALI
, "fr" },
447 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA
,"bs" },
448 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_URDU_INDIA
, "ur" },
449 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TAJIK_TAJIKISTAN
, "tg" },
450 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_YIDDISH_GERMANY
, "yi" },
451 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN
, "ky" },
453 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TURKMEN_TURKMENISTAN
, "tk" },
454 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MONGOLIAN_MONGOLIA
, "mn" },
456 /* the following seems to be inconsistent;
457 here is the current "official" way: */
458 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TIBETAN_BHUTAN
, "bo" },
459 /* and here is what is used by Passport SDK */
460 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TIBETAN_CHINA
, "bo" },
461 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_DZONGHKA_BHUTAN
, "dz" },
462 /* end of inconsistency */
464 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_WELSH_WALES
, "cy" },
465 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KHMER_CAMBODIA
, "km" },
466 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_LAO_LAOS
, "lo" },
467 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BURMESE_MYANMAR
, "my" },
468 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GALICIAN_SPAIN
, "gl" },
469 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MANIPURI_INDIA
, "mni" },
470 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SINDHI_INDIA
, "sd" },
471 /* the following one is only encountered in Microsoft RTF specification */
472 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KASHMIRI_PAKISTAN
, "ks" },
473 /* the following one is not in the Passport list, looks like an omission */
474 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KASHMIRI_INDIA
, "ks" },
475 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_NEPALI_NEPAL
, "ne" },
476 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_NEPALI_INDIA
, "ne" },
477 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRISIAN_NETHERLANDS
, "fy" },
479 /* new as of 2001-03-01 (from Office Xp) */
480 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_HONG_KONG
, "en" },
481 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_INDIA
, "en" },
482 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_MALAYSIA
, "en" },
483 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_SINGAPORE
, "en" },
484 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SYRIAC_SYRIA
, "syr" },
485 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SINHALESE_SRI_LANKA
, "si" },
486 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHEROKEE_UNITED_STATES
, "chr" },
487 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_INUKTITUT_CANADA
, "iu" },
488 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_AMHARIC_ETHIOPIA
, "am" },
490 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TAMAZIGHT_MOROCCO
},
491 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN
},
493 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PASHTO_AFGHANISTAN
, "ps" },
494 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FILIPINO_PHILIPPINES
, "phi" },
495 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_DHIVEHI_MALDIVES
, "div" },
497 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_OROMO_ETHIOPIA
, "om" },
498 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TIGRIGNA_ETHIOPIA
, "ti" },
499 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TIGRIGNA_ERYTHREA
, "ti" },
501 /* New additions from Windows Xp/Passport SDK 2001-11-10. */
503 /* don't ask what this one means... It is commented out currently. */
505 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GREEK_GREECE2
},
508 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_UNITED_STATES
, "es" },
509 /* The following two IDs blatantly violate MS specs by using a */
510 /* sublanguage >,. */
511 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_LATIN_AMERICA
, "es" },
512 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_NORTH_AFRICA
, "fr" },
514 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_MOROCCO
, "fr" },
515 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_HAITI
, "fr" },
516 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BENGALI_BANGLADESH
, "bn" },
517 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN
, "ar" },
518 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN
,"mn" },
520 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_EDO_NIGERIA
},
521 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FULFULDE_NIGERIA
},
522 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_IBIBIO_NIGERIA
},
524 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_HAUSA_NIGERIA
, "ha" },
525 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_YORUBA_NIGERIA
, "yo" },
526 /* language codes from, to, are (still) unknown. */
527 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_IGBO_NIGERIA
, "ibo" },
528 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KANURI_NIGERIA
, "kau" },
529 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GUARANI_PARAGUAY
, "gn" },
530 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_HAWAIIAN_UNITED_STATES
, "haw" },
531 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_LATIN
, "la" },
532 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SOMALI_SOMALIA
, "so" },
534 /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */
535 /* not written (but OTOH the peculiar writing system is worth */
537 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_YI_CHINA
},
539 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES
,"pap" },
542 #define NUM_FC_FT_LANGUAGE (int) (sizeof (fcFtLanguage) / sizeof (fcFtLanguage[0]))
545 FT_UShort language_id
;
549 static const FcMacRomanFake fcMacRomanFake
[] = {
550 { TT_MS_LANGID_JAPANESE_JAPAN
, "SJIS-WIN" },
551 { TT_MS_LANGID_ENGLISH_UNITED_STATES
, "ASCII" },
555 FcFontCapabilities(FT_Face face
);
557 #define NUM_FC_MAC_ROMAN_FAKE (int) (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0]))
564 * A shift-JIS will have many high bits turned on
567 FcLooksLikeSJIS (FcChar8
*string
, int len
)
569 int nhigh
= 0, nlow
= 0;
573 if (*string
++ & 0x80) nhigh
++;
577 * Heuristic -- if more than 1/3 of the bytes have the high-bit set,
578 * this is likely to be SJIS and not ROMAN
580 if (nhigh
* 2 > nlow
)
586 FcSfntNameTranscode (FT_SfntName
*sname
)
589 const char *fromcode
;
595 for (i
= 0; i
< NUM_FC_FT_ENCODING
; i
++)
596 if (fcFtEncoding
[i
].platform_id
== sname
->platform_id
&&
597 (fcFtEncoding
[i
].encoding_id
== TT_ENCODING_DONT_CARE
||
598 fcFtEncoding
[i
].encoding_id
== sname
->encoding_id
))
600 if (i
== NUM_FC_FT_ENCODING
)
602 fromcode
= fcFtEncoding
[i
].fromcode
;
605 * Many names encoded for TT_PLATFORM_MACINTOSH are broken
606 * in various ways. Kludge around them.
608 if (!strcmp (fromcode
, FC_ENCODING_MAC_ROMAN
))
610 if (sname
->language_id
== TT_MAC_LANGID_ENGLISH
&&
611 FcLooksLikeSJIS (sname
->string
, sname
->string_len
))
615 else if (sname
->language_id
>= 0x100)
618 * "real" Mac language IDs are all less than 150.
619 * Names using one of the MS language IDs are assumed
620 * to use an associated encoding (Yes, this is a kludge)
625 for (f
= 0; f
< NUM_FC_MAC_ROMAN_FAKE
; f
++)
626 if (fcMacRomanFake
[f
].language_id
== sname
->language_id
)
628 fromcode
= fcMacRomanFake
[f
].fromcode
;
635 if (!strcmp (fromcode
, "UCS-2BE") || !strcmp (fromcode
, "UTF-16BE"))
637 FcChar8
*src
= sname
->string
;
638 int src_len
= sname
->string_len
;
646 * Convert Utf16 to Utf8
649 if (!FcUtf16Len (src
, FcEndianBig
, src_len
, &len
, &wchar
))
653 * Allocate plenty of space. Freed below
655 utf8
= malloc (len
* FC_UTF8_MAX_LEN
+ 1);
661 while ((ilen
= FcUtf16ToUcs4 (src
, FcEndianBig
, &ucs4
, src_len
)) > 0)
665 olen
= FcUcs4ToUtf8 (ucs4
, u8
);
671 if (!strcmp (fromcode
, "ASCII") || !strcmp (fromcode
, "ISO-8859-1"))
673 FcChar8
*src
= sname
->string
;
674 int src_len
= sname
->string_len
;
680 * Convert Latin1 to Utf8. Freed below
682 utf8
= malloc (src_len
* 2 + 1);
691 olen
= FcUcs4ToUtf8 (ucs4
, u8
);
697 if (!strcmp (fromcode
, FC_ENCODING_MAC_ROMAN
))
700 const FcCharMap
*map
= FcFreeTypeGetPrivateMap (ft_encoding_apple_roman
);
701 FcChar8
*src
= (FcChar8
*) sname
->string
;
702 int src_len
= sname
->string_len
;
705 * Convert AppleRoman to Utf8
710 utf8
= malloc (sname
->string_len
* 3 + 1);
717 FcChar32 ucs4
= FcFreeTypePrivateToUcs4 (*src
++, map
);
718 int olen
= FcUcs4ToUtf8 (ucs4
, u8
);
726 cd
= iconv_open ("UTF-8", fromcode
);
727 if (cd
&& cd
!= (iconv_t
) (-1))
729 size_t in_bytes_left
= sname
->string_len
;
730 size_t out_bytes_left
= sname
->string_len
* FC_UTF8_MAX_LEN
;
731 char *inbuf
, *outbuf
;
733 utf8
= malloc (out_bytes_left
+ 1);
740 outbuf
= (char *) utf8
;
741 inbuf
= (char *) sname
->string
;
743 while (in_bytes_left
)
745 size_t did
= iconv (cd
,
746 &inbuf
, &in_bytes_left
,
747 &outbuf
, &out_bytes_left
);
748 if (did
== (size_t) (-1))
762 if (FcStrCmpIgnoreBlanksAndCase (utf8
, (FcChar8
*) "") == 0)
770 static const FcChar8
*
771 FcSfntNameLanguage (FT_SfntName
*sname
)
774 FT_UShort platform_id
= sname
->platform_id
;
775 FT_UShort language_id
= sname
->language_id
;
778 * Many names encoded for TT_PLATFORM_MACINTOSH are broken
779 * in various ways. Kludge around them.
781 if (platform_id
== TT_PLATFORM_MACINTOSH
&&
782 sname
->encoding_id
== TT_MAC_ID_ROMAN
&&
783 FcLooksLikeSJIS (sname
->string
, sname
->string_len
))
785 language_id
= TT_MAC_LANGID_JAPANESE
;
788 for (i
= 0; i
< NUM_FC_FT_LANGUAGE
; i
++)
789 if (fcFtLanguage
[i
].platform_id
== platform_id
&&
790 (fcFtLanguage
[i
].language_id
== TT_LANGUAGE_DONT_CARE
||
791 fcFtLanguage
[i
].language_id
== language_id
))
793 if (fcFtLanguage
[i
].lang
[0] == '\0')
796 return (FcChar8
*) fcFtLanguage
[i
].lang
;
801 /* Order is significant. For example, some B&H fonts are hinted by
802 URW++, and both strings appear in the notice. */
804 static const struct {
805 const FT_String
*notice
;
806 const FcChar8
*foundry
;
807 } FcNoticeFoundries
[] = {
808 { (const FT_String
*) "Bigelow", (const FcChar8
*) "b&h" },
809 { (const FT_String
*) "Adobe", (const FcChar8
*) "adobe" },
810 { (const FT_String
*) "Bitstream", (const FcChar8
*) "bitstream" },
811 { (const FT_String
*) "Monotype", (const FcChar8
*) "monotype" },
812 { (const FT_String
*) "Linotype", (const FcChar8
*) "linotype" },
813 { (const FT_String
*) "LINOTYPE-HELL",
814 (const FcChar8
*) "linotype" },
815 { (const FT_String
*) "IBM", (const FcChar8
*) "ibm" },
816 { (const FT_String
*) "URW", (const FcChar8
*) "urw" },
817 { (const FT_String
*) "International Typeface Corporation",
818 (const FcChar8
*) "itc" },
819 { (const FT_String
*) "Tiro Typeworks",
820 (const FcChar8
*) "tiro" },
821 { (const FT_String
*) "XFree86", (const FcChar8
*) "xfree86" },
822 { (const FT_String
*) "Microsoft", (const FcChar8
*) "microsoft" },
823 { (const FT_String
*) "Omega", (const FcChar8
*) "omega" },
824 { (const FT_String
*) "Font21", (const FcChar8
*) "hwan" },
825 { (const FT_String
*) "HanYang System",
826 (const FcChar8
*) "hanyang" }
829 #define NUM_NOTICE_FOUNDRIES (int) (sizeof (FcNoticeFoundries) / sizeof (FcNoticeFoundries[0]))
831 static const FcChar8
*
832 FcNoticeFoundry(const FT_String
*notice
)
837 for(i
= 0; i
< NUM_NOTICE_FOUNDRIES
; i
++)
838 if (strstr ((const char *) notice
, (const char *) FcNoticeFoundries
[i
].notice
))
839 return FcNoticeFoundries
[i
].foundry
;
844 FcVendorMatch(const FT_Char vendor
[4], const FT_Char
*vendor_string
)
846 /* vendor is not necessarily NUL-terminated. */
849 len
= strlen((char *) vendor_string
);
850 if (memcmp(vendor
, vendor_string
, len
) != 0)
852 for (i
= len
; i
< 4; i
++)
853 if (vendor
[i
] != ' ' && vendor
[i
] != '\0')
858 /* This table is partly taken from ttmkfdir by Joerg Pommnitz. */
860 /* It should not contain useless entries (such as UNKN) nor duplicate
861 entries for padding both with spaces and NULs. */
863 static const struct {
864 const FT_Char
*vendor
;
865 const FcChar8
*foundry
;
866 } FcVendorFoundries
[] = {
867 { (const FT_Char
*) "ADBE", (const FcChar8
*) "adobe"},
868 { (const FT_Char
*) "AGFA", (const FcChar8
*) "agfa"},
869 { (const FT_Char
*) "ALTS", (const FcChar8
*) "altsys"},
870 { (const FT_Char
*) "APPL", (const FcChar8
*) "apple"},
871 { (const FT_Char
*) "ARPH", (const FcChar8
*) "arphic"},
872 { (const FT_Char
*) "ATEC", (const FcChar8
*) "alltype"},
873 { (const FT_Char
*) "B&H", (const FcChar8
*) "b&h"},
874 { (const FT_Char
*) "BITS", (const FcChar8
*) "bitstream"},
875 { (const FT_Char
*) "CANO", (const FcChar8
*) "cannon"},
876 { (const FT_Char
*) "DYNA", (const FcChar8
*) "dynalab"},
877 { (const FT_Char
*) "EPSN", (const FcChar8
*) "epson"},
878 { (const FT_Char
*) "FJ", (const FcChar8
*) "fujitsu"},
879 { (const FT_Char
*) "IBM", (const FcChar8
*) "ibm"},
880 { (const FT_Char
*) "ITC", (const FcChar8
*) "itc"},
881 { (const FT_Char
*) "IMPR", (const FcChar8
*) "impress"},
882 { (const FT_Char
*) "LARA", (const FcChar8
*) "larabiefonts"},
883 { (const FT_Char
*) "LEAF", (const FcChar8
*) "interleaf"},
884 { (const FT_Char
*) "LETR", (const FcChar8
*) "letraset"},
885 { (const FT_Char
*) "LINO", (const FcChar8
*) "linotype"},
886 { (const FT_Char
*) "MACR", (const FcChar8
*) "macromedia"},
887 { (const FT_Char
*) "MONO", (const FcChar8
*) "monotype"},
888 { (const FT_Char
*) "MS", (const FcChar8
*) "microsoft"},
889 { (const FT_Char
*) "MT", (const FcChar8
*) "monotype"},
890 { (const FT_Char
*) "NEC", (const FcChar8
*) "nec"},
891 { (const FT_Char
*) "PARA", (const FcChar8
*) "paratype"},
892 { (const FT_Char
*) "QMSI", (const FcChar8
*) "qms"},
893 { (const FT_Char
*) "RICO", (const FcChar8
*) "ricoh"},
894 { (const FT_Char
*) "URW", (const FcChar8
*) "urw"},
895 { (const FT_Char
*) "Y&Y", (const FcChar8
*) "y&y"}
898 #define NUM_VENDOR_FOUNDRIES (int) (sizeof (FcVendorFoundries) / sizeof (FcVendorFoundries[0]))
900 static const FcChar8
*
901 FcVendorFoundry(const FT_Char vendor
[4])
906 for(i
= 0; i
< NUM_VENDOR_FOUNDRIES
; i
++)
907 if (FcVendorMatch (vendor
, FcVendorFoundries
[i
].vendor
))
908 return FcVendorFoundries
[i
].foundry
;
912 typedef struct _FcStringConst
{
918 FcStringIsConst (const FcChar8
*string
,
919 const FcStringConst
*c
,
924 for (i
= 0; i
< nc
; i
++)
925 if (FcStrCmpIgnoreBlanksAndCase (string
, c
[i
].name
) == 0)
931 FcStringContainsConst (const FcChar8
*string
,
932 const FcStringConst
*c
,
937 for (i
= 0; i
< nc
; i
++)
938 if (FcStrContainsIgnoreBlanksAndCase (string
, c
[i
].name
))
943 typedef FcChar8
*FC8
;
945 static const FcStringConst weightConsts
[] = {
946 { (FC8
) "thin", FC_WEIGHT_THIN
},
947 { (FC8
) "extralight", FC_WEIGHT_EXTRALIGHT
},
948 { (FC8
) "ultralight", FC_WEIGHT_ULTRALIGHT
},
949 { (FC8
) "light", FC_WEIGHT_LIGHT
},
950 { (FC8
) "book", FC_WEIGHT_BOOK
},
951 { (FC8
) "regular", FC_WEIGHT_REGULAR
},
952 { (FC8
) "normal", FC_WEIGHT_NORMAL
},
953 { (FC8
) "medium", FC_WEIGHT_MEDIUM
},
954 { (FC8
) "demibold", FC_WEIGHT_DEMIBOLD
},
955 { (FC8
) "demi", FC_WEIGHT_DEMIBOLD
},
956 { (FC8
) "semibold", FC_WEIGHT_SEMIBOLD
},
957 { (FC8
) "extrabold", FC_WEIGHT_EXTRABOLD
},
958 { (FC8
) "superbold", FC_WEIGHT_EXTRABOLD
},
959 { (FC8
) "ultrabold", FC_WEIGHT_ULTRABOLD
},
960 { (FC8
) "bold", FC_WEIGHT_BOLD
},
961 { (FC8
) "black", FC_WEIGHT_BLACK
},
962 { (FC8
) "heavy", FC_WEIGHT_HEAVY
},
965 #define NUM_WEIGHT_CONSTS (int) (sizeof (weightConsts) / sizeof (weightConsts[0]))
967 #define FcIsWeight(s) FcStringIsConst(s,weightConsts,NUM_WEIGHT_CONSTS)
968 #define FcContainsWeight(s) FcStringContainsConst (s,weightConsts,NUM_WEIGHT_CONSTS)
970 static const FcStringConst widthConsts
[] = {
971 { (FC8
) "ultracondensed", FC_WIDTH_ULTRACONDENSED
},
972 { (FC8
) "extracondensed", FC_WIDTH_EXTRACONDENSED
},
973 { (FC8
) "semicondensed", FC_WIDTH_SEMICONDENSED
},
974 { (FC8
) "condensed", FC_WIDTH_CONDENSED
}, /* must be after *condensed */
975 { (FC8
) "normal", FC_WIDTH_NORMAL
},
976 { (FC8
) "semiexpanded", FC_WIDTH_SEMIEXPANDED
},
977 { (FC8
) "extraexpanded", FC_WIDTH_EXTRAEXPANDED
},
978 { (FC8
) "ultraexpanded", FC_WIDTH_ULTRAEXPANDED
},
979 { (FC8
) "expanded", FC_WIDTH_EXPANDED
}, /* must be after *expanded */
982 #define NUM_WIDTH_CONSTS (int) (sizeof (widthConsts) / sizeof (widthConsts[0]))
984 #define FcIsWidth(s) FcStringIsConst(s,widthConsts,NUM_WIDTH_CONSTS)
985 #define FcContainsWidth(s) FcStringContainsConst (s,widthConsts,NUM_WIDTH_CONSTS)
987 static const FcStringConst slantConsts
[] = {
988 { (FC8
) "italic", FC_SLANT_ITALIC
},
989 { (FC8
) "kursiv", FC_SLANT_ITALIC
},
990 { (FC8
) "oblique", FC_SLANT_OBLIQUE
},
993 #define NUM_SLANT_CONSTS (int) (sizeof (slantConsts) / sizeof (slantConsts[0]))
995 #define FcIsSlant(s) FcStringIsConst(s,slantConsts,NUM_SLANT_CONSTS)
996 #define FcContainsSlant(s) FcStringContainsConst (s,slantConsts,NUM_SLANT_CONSTS)
998 static const FcStringConst decorativeConsts
[] = {
999 { (FC8
) "shadow", FcTrue
},
1000 { (FC8
) "smallcaps", FcTrue
},
1001 { (FC8
) "antiqua", FcTrue
},
1002 { (FC8
) "romansc", FcTrue
},
1003 { (FC8
) "embosed", FcTrue
},
1004 { (FC8
) "romansmallcaps", FcTrue
},
1007 #define NUM_DECORATIVE_CONSTS (int) (sizeof (decorativeConsts) / sizeof (decorativeConsts[0]))
1009 #define FcIsDecorative(s) FcStringIsConst(s,decorativeConsts,NUM_DECORATIVE_CONSTS)
1010 #define FcContainsDecorative(s) FcStringContainsConst (s,decorativeConsts,NUM_DECORATIVE_CONSTS)
1013 FcGetPixelSize (FT_Face face
, int i
)
1015 #if HAVE_FT_GET_BDF_PROPERTY
1016 if (face
->num_fixed_sizes
== 1)
1018 BDF_PropertyRec prop
;
1021 rc
= FT_Get_BDF_Property (face
, "PIXEL_SIZE", &prop
);
1022 if (rc
== 0 && prop
.type
== BDF_PROPERTY_TYPE_INTEGER
)
1023 return (double) prop
.u
.integer
;
1026 #if HAVE_FT_BITMAP_SIZE_Y_PPEM
1027 return (double) face
->available_sizes
[i
].y_ppem
/ 64.0;
1029 return (double) face
->available_sizes
[i
].height
;
1034 FcStringInPatternElement (FcPattern
*pat
, const char *elt
, FcChar8
*string
)
1038 for (e
= 0; FcPatternGetString (pat
, elt
, e
, &old
) == FcResultMatch
; e
++)
1039 if (!FcStrCmpIgnoreBlanksAndCase (old
, string
))
1047 FcFreeTypeQuery (const FcChar8
*file
,
1057 FcBool decorative
= FcFalse
;
1061 FT_Library ftLibrary
;
1063 FcChar8
*family
= 0;
1066 const FcChar8
*foundry
= 0;
1069 #if HAVE_FT_GET_PS_FONT_INFO
1070 PS_FontInfoRec psfontinfo
;
1072 #if HAVE_FT_GET_BDF_PROPERTY
1073 BDF_PropertyRec prop
;
1076 const FcChar8
*exclusiveLang
= 0;
1078 FT_UInt snamei
, snamec
;
1081 int nfamily_lang
= 0;
1083 int nstyle_lang
= 0;
1085 int nfullname_lang
= 0;
1090 if (FT_Init_FreeType (&ftLibrary
))
1093 if (FT_New_Face (ftLibrary
, (char *) file
, id
, &face
))
1096 *count
= face
->num_faces
;
1098 pat
= FcPatternCreate ();
1102 if (!FcPatternAddBool (pat
, FC_OUTLINE
,
1103 (face
->face_flags
& FT_FACE_FLAG_SCALABLE
) != 0))
1106 if (!FcPatternAddBool (pat
, FC_SCALABLE
,
1107 (face
->face_flags
& FT_FACE_FLAG_SCALABLE
) != 0))
1112 * Get the OS/2 table
1114 os2
= (TT_OS2
*) FT_Get_Sfnt_Table (face
, ft_sfnt_os2
);
1117 * Look first in the OS/2 table for the foundry, if
1118 * not found here, the various notices will be searched for
1119 * that information, either from the sfnt name tables or
1120 * the Postscript FontInfo dictionary. Finally, the
1121 * BDF properties will queried.
1124 if (os2
&& os2
->version
>= 0x0001 && os2
->version
!= 0xffff)
1125 foundry
= FcVendorFoundry(os2
->achVendID
);
1127 if (FcDebug () & FC_DBG_SCANV
)
1130 * Grub through the name table looking for family
1131 * and style names. FreeType makes quite a hash
1134 snamec
= FT_Get_Sfnt_Name_Count (face
);
1135 for (snamei
= 0; snamei
< snamec
; snamei
++)
1138 const FcChar8
*lang
;
1139 const char *elt
= 0, *eltlang
= 0;
1140 int *np
= 0, *nlangp
= 0;
1142 if (FT_Get_Sfnt_Name (face
, snamei
, &sname
) != 0)
1145 utf8
= FcSfntNameTranscode (&sname
);
1146 lang
= FcSfntNameLanguage (&sname
);
1151 switch (sname
.name_id
) {
1152 case TT_NAME_ID_FONT_FAMILY
:
1154 case TT_NAME_ID_PS_NAME
:
1155 case TT_NAME_ID_UNIQUE_ID
:
1157 if (FcDebug () & FC_DBG_SCANV
)
1158 printf ("found family (n %2d p %d e %d l 0x%04x) %s\n",
1159 sname
.name_id
, sname
.platform_id
,
1160 sname
.encoding_id
, sname
.language_id
,
1164 eltlang
= FC_FAMILYLANG
;
1166 nlangp
= &nfamily_lang
;
1168 case TT_NAME_ID_FULL_NAME
:
1169 case TT_NAME_ID_MAC_FULL_NAME
:
1170 if (FcDebug () & FC_DBG_SCANV
)
1171 printf ("found full (n %2d p %d e %d l 0x%04x) %s\n",
1172 sname
.name_id
, sname
.platform_id
,
1173 sname
.encoding_id
, sname
.language_id
,
1177 eltlang
= FC_FULLNAMELANG
;
1179 nlangp
= &nfullname_lang
;
1181 case TT_NAME_ID_FONT_SUBFAMILY
:
1182 if (FcDebug () & FC_DBG_SCANV
)
1183 printf ("found style (n %2d p %d e %d l 0x%04x) %s\n",
1184 sname
.name_id
, sname
.platform_id
,
1185 sname
.encoding_id
, sname
.language_id
,
1189 eltlang
= FC_STYLELANG
;
1191 nlangp
= &nstyle_lang
;
1193 case TT_NAME_ID_TRADEMARK
:
1194 case TT_NAME_ID_MANUFACTURER
:
1195 /* If the foundry wasn't found in the OS/2 table, look here */
1197 foundry
= FcNoticeFoundry((FT_String
*) utf8
);
1202 if (FcStringInPatternElement (pat
, elt
, utf8
))
1208 /* add new element */
1209 if (!FcPatternAddString (pat
, elt
, utf8
))
1217 /* pad lang list with 'xx' to line up with elt */
1218 while (*nlangp
< *np
)
1220 if (!FcPatternAddString (pat
, eltlang
, (FcChar8
*) "xx"))
1224 if (!FcPatternAddString (pat
, eltlang
, lang
))
1234 if (!nfamily
&& face
->family_name
&&
1235 FcStrCmpIgnoreBlanksAndCase ((FcChar8
*) face
->family_name
, (FcChar8
*) "") != 0)
1237 if (FcDebug () & FC_DBG_SCANV
)
1238 printf ("using FreeType family \"%s\"\n", face
->family_name
);
1239 if (!FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) face
->family_name
))
1244 if (!nstyle
&& face
->style_name
&&
1245 FcStrCmpIgnoreBlanksAndCase ((FcChar8
*) face
->style_name
, (FcChar8
*) "") != 0)
1247 if (FcDebug () & FC_DBG_SCANV
)
1248 printf ("using FreeType style \"%s\"\n", face
->style_name
);
1249 if (!FcPatternAddString (pat
, FC_STYLE
, (FcChar8
*) face
->style_name
))
1256 FcChar8
*start
, *end
;
1259 start
= (FcChar8
*) strrchr ((char *) file
, '/');
1263 start
= (FcChar8
*) file
;
1264 end
= (FcChar8
*) strrchr ((char *) start
, '.');
1266 end
= start
+ strlen ((char *) start
);
1268 family
= malloc (end
- start
+ 1);
1269 strncpy ((char *) family
, (char *) start
, end
- start
);
1270 family
[end
- start
] = '\0';
1271 if (FcDebug () & FC_DBG_SCANV
)
1272 printf ("using filename for family %s\n", family
);
1273 if (!FcPatternAddString (pat
, FC_FAMILY
, family
))
1283 * Walk through FC_FULLNAME entries eliding those in FC_FAMILY
1284 * or which are simply a FC_FAMILY and FC_STYLE glued together
1292 for (fn
= 0; FcPatternGetString (pat
, FC_FULLNAME
, fn
, &full
) == FcResultMatch
; fn
++)
1294 FcBool remove
= FcFalse
;
1298 for (fa
= 0; !remove
&&
1299 FcPatternGetString (pat
, FC_FAMILY
,
1300 fa
, &fam
) == FcResultMatch
;
1306 if (!FcStrCmpIgnoreBlanksAndCase (full
, fam
))
1312 * If the family is in the full name, check the
1313 * combination of this family with every style
1315 if (!FcStrContainsIgnoreBlanksAndCase (full
, fam
))
1317 for (st
= 0; !remove
&&
1318 FcPatternGetString (pat
, FC_STYLE
,
1319 st
, &style
) == FcResultMatch
;
1322 FcChar8
*both
= FcStrPlus (fam
, style
);
1326 if (FcStrCmpIgnoreBlanksAndCase (full
, both
) == 0)
1334 FcPatternRemove (pat
, FC_FULLNAME
, fn
);
1335 FcPatternRemove (pat
, FC_FULLNAMELANG
, fn
);
1341 if (FcDebug () & FC_DBG_SCANV
)
1342 for (fn
= 0; FcPatternGetString (pat
, FC_FULLNAME
, fn
, &full
) == FcResultMatch
; fn
++)
1343 printf ("Saving unique fullname %s\n", full
);
1346 if (!FcPatternAddString (pat
, FC_FILE
, file
))
1349 if (!FcPatternAddInteger (pat
, FC_INDEX
, id
))
1354 * don't even try this -- CJK 'monospace' fonts are really
1355 * dual width, and most other fonts don't bother to set
1356 * the attribute. Sigh.
1358 if ((face
->face_flags
& FT_FACE_FLAG_FIXED_WIDTH
) != 0)
1359 if (!FcPatternAddInteger (pat
, FC_SPACING
, FC_MONO
))
1364 * Find the font revision (if available)
1366 head
= (TT_Header
*) FT_Get_Sfnt_Table (face
, ft_sfnt_head
);
1369 if (!FcPatternAddInteger (pat
, FC_FONTVERSION
, head
->Font_Revision
))
1374 if (!FcPatternAddInteger (pat
, FC_FONTVERSION
, 0))
1378 if (os2
&& os2
->version
>= 0x0001 && os2
->version
!= 0xffff)
1380 for (i
= 0; i
< NUM_CODE_PAGE_RANGE
; i
++)
1384 if (FcCodePageRange
[i
].bit
< 32)
1386 bits
= os2
->ulCodePageRange1
;
1387 bit
= FcCodePageRange
[i
].bit
;
1391 bits
= os2
->ulCodePageRange2
;
1392 bit
= FcCodePageRange
[i
].bit
- 32;
1394 if (bits
& (1 << bit
))
1397 * If the font advertises support for multiple
1398 * "exclusive" languages, then include support
1399 * for any language found to have coverage
1406 exclusiveLang
= FcCodePageRange
[i
].lang
;
1411 if (os2
&& os2
->version
!= 0xffff)
1413 if (os2
->usWeightClass
== 0)
1415 else if (os2
->usWeightClass
< 150)
1416 weight
= FC_WEIGHT_THIN
;
1417 else if (os2
->usWeightClass
< 250)
1418 weight
= FC_WEIGHT_EXTRALIGHT
;
1419 else if (os2
->usWeightClass
< 350)
1420 weight
= FC_WEIGHT_LIGHT
;
1421 else if (os2
->usWeightClass
< 450)
1422 weight
= FC_WEIGHT_REGULAR
;
1423 else if (os2
->usWeightClass
< 550)
1424 weight
= FC_WEIGHT_MEDIUM
;
1425 else if (os2
->usWeightClass
< 650)
1426 weight
= FC_WEIGHT_SEMIBOLD
;
1427 else if (os2
->usWeightClass
< 750)
1428 weight
= FC_WEIGHT_BOLD
;
1429 else if (os2
->usWeightClass
< 850)
1430 weight
= FC_WEIGHT_EXTRABOLD
;
1431 else if (os2
->usWeightClass
< 950)
1432 weight
= FC_WEIGHT_BLACK
;
1433 if ((FcDebug() & FC_DBG_SCANV
) && weight
!= -1)
1434 printf ("\tos2 weight class %d maps to weight %d\n",
1435 os2
->usWeightClass
, weight
);
1437 switch (os2
->usWidthClass
) {
1438 case 1: width
= FC_WIDTH_ULTRACONDENSED
; break;
1439 case 2: width
= FC_WIDTH_EXTRACONDENSED
; break;
1440 case 3: width
= FC_WIDTH_CONDENSED
; break;
1441 case 4: width
= FC_WIDTH_SEMICONDENSED
; break;
1442 case 5: width
= FC_WIDTH_NORMAL
; break;
1443 case 6: width
= FC_WIDTH_SEMIEXPANDED
; break;
1444 case 7: width
= FC_WIDTH_EXPANDED
; break;
1445 case 8: width
= FC_WIDTH_EXTRAEXPANDED
; break;
1446 case 9: width
= FC_WIDTH_ULTRAEXPANDED
; break;
1448 if ((FcDebug() & FC_DBG_SCANV
) && width
!= -1)
1449 printf ("\tos2 width class %d maps to width %d\n",
1450 os2
->usWidthClass
, width
);
1452 if (os2
&& (complex = FcFontCapabilities(face
)))
1454 if (!FcPatternAddString (pat
, FC_CAPABILITY
, complex))
1463 * Type 1: Check for FontInfo dictionary information
1464 * Code from g2@magestudios.net (Gerard Escalante)
1467 #if HAVE_FT_GET_PS_FONT_INFO
1468 if (FT_Get_PS_Font_Info(face
, &psfontinfo
) == 0)
1470 if (weight
== -1 && psfontinfo
.weight
)
1472 weight
= FcIsWeight ((FcChar8
*) psfontinfo
.weight
);
1473 if (FcDebug() & FC_DBG_SCANV
)
1474 printf ("\tType1 weight %s maps to %d\n",
1475 psfontinfo
.weight
, weight
);
1480 * Don't bother with italic_angle; FreeType already extracts that
1481 * information for us and sticks it into style_flags
1483 if (psfontinfo
.italic_angle
)
1484 slant
= FC_SLANT_ITALIC
;
1486 slant
= FC_SLANT_ROMAN
;
1490 foundry
= FcNoticeFoundry(psfontinfo
.notice
);
1492 #endif /* HAVE_FT_GET_PS_FONT_INFO */
1494 #if HAVE_FT_GET_BDF_PROPERTY
1496 * Finally, look for a FOUNDRY BDF property if no other
1497 * mechanism has managed to locate a foundry
1503 rc
= FT_Get_BDF_Property(face
, "FOUNDRY", &prop
);
1504 if(rc
== 0 && prop
.type
== BDF_PROPERTY_TYPE_ATOM
)
1505 foundry
= (FcChar8
*) prop
.u
.atom
;
1510 if (FT_Get_BDF_Property(face
, "RELATIVE_SETWIDTH", &prop
) == 0 &&
1511 (prop
.type
== BDF_PROPERTY_TYPE_INTEGER
||
1512 prop
.type
== BDF_PROPERTY_TYPE_CARDINAL
))
1516 if (prop
.type
== BDF_PROPERTY_TYPE_INTEGER
)
1517 value
= prop
.u
.integer
;
1519 value
= (FT_Int32
) prop
.u
.cardinal
;
1520 switch ((value
+ 5) / 10) {
1521 case 1: width
= FC_WIDTH_ULTRACONDENSED
; break;
1522 case 2: width
= FC_WIDTH_EXTRACONDENSED
; break;
1523 case 3: width
= FC_WIDTH_CONDENSED
; break;
1524 case 4: width
= FC_WIDTH_SEMICONDENSED
; break;
1525 case 5: width
= FC_WIDTH_NORMAL
; break;
1526 case 6: width
= FC_WIDTH_SEMIEXPANDED
; break;
1527 case 7: width
= FC_WIDTH_EXPANDED
; break;
1528 case 8: width
= FC_WIDTH_EXTRAEXPANDED
; break;
1529 case 9: width
= FC_WIDTH_ULTRAEXPANDED
; break;
1533 FT_Get_BDF_Property (face
, "SETWIDTH_NAME", &prop
) == 0 &&
1534 prop
.type
== BDF_PROPERTY_TYPE_ATOM
)
1536 width
= FcIsWidth ((FcChar8
*) prop
.u
.atom
);
1537 if (FcDebug () & FC_DBG_SCANV
)
1538 printf ("\tsetwidth %s maps to %d\n", prop
.u
.atom
, width
);
1544 * Look for weight, width and slant names in the style value
1546 for (st
= 0; FcPatternGetString (pat
, FC_STYLE
, st
, &style
) == FcResultMatch
; st
++)
1550 weight
= FcContainsWeight (style
);
1551 if (FcDebug() & FC_DBG_SCANV
)
1552 printf ("\tStyle %s maps to weight %d\n", style
, weight
);
1556 width
= FcContainsWidth (style
);
1557 if (FcDebug() & FC_DBG_SCANV
)
1558 printf ("\tStyle %s maps to width %d\n", style
, width
);
1562 slant
= FcContainsSlant (style
);
1563 if (FcDebug() & FC_DBG_SCANV
)
1564 printf ("\tStyle %s maps to slant %d\n", style
, slant
);
1566 if (decorative
== FcFalse
)
1568 decorative
= FcContainsDecorative (style
) > 0;
1569 if (FcDebug() & FC_DBG_SCANV
)
1570 printf ("\tStyle %s maps to decorative %d\n", style
, decorative
);
1574 * Pull default values from the FreeType flags if more
1575 * specific values not found above
1579 slant
= FC_SLANT_ROMAN
;
1580 if (face
->style_flags
& FT_STYLE_FLAG_ITALIC
)
1581 slant
= FC_SLANT_ITALIC
;
1586 weight
= FC_WEIGHT_MEDIUM
;
1587 if (face
->style_flags
& FT_STYLE_FLAG_BOLD
)
1588 weight
= FC_WEIGHT_BOLD
;
1592 width
= FC_WIDTH_NORMAL
;
1595 foundry
= (FcChar8
*) "unknown";
1597 if (!FcPatternAddInteger (pat
, FC_SLANT
, slant
))
1600 if (!FcPatternAddInteger (pat
, FC_WEIGHT
, weight
))
1603 if (!FcPatternAddInteger (pat
, FC_WIDTH
, width
))
1606 if (!FcPatternAddString (pat
, FC_FOUNDRY
, foundry
))
1609 if (!FcPatternAddBool (pat
, FC_DECORATIVE
, decorative
))
1613 * Compute the unicode coverage for the font
1615 cs
= FcFreeTypeCharSetAndSpacing (face
, blanks
, &spacing
);
1619 #if HAVE_FT_GET_BDF_PROPERTY
1620 /* For PCF fonts, override the computed spacing with the one from
1622 if(FT_Get_BDF_Property(face
, "SPACING", &prop
) == 0 &&
1623 prop
.type
== BDF_PROPERTY_TYPE_ATOM
) {
1624 if(!strcmp(prop
.u
.atom
, "c") || !strcmp(prop
.u
.atom
, "C"))
1625 spacing
= FC_CHARCELL
;
1626 else if(!strcmp(prop
.u
.atom
, "m") || !strcmp(prop
.u
.atom
, "M"))
1628 else if(!strcmp(prop
.u
.atom
, "p") || !strcmp(prop
.u
.atom
, "P"))
1629 spacing
= FC_PROPORTIONAL
;
1634 * Skip over PCF fonts that have no encoded characters; they're
1635 * usually just Unicode fonts transcoded to some legacy encoding
1636 * ftglue.c forces us to approximate whether a font is a PCF font
1637 * or not by whether it has any BDF properties. Try PIXEL_SIZE;
1638 * I don't know how to get a list of BDF properties on the font. -PL
1640 if (FcCharSetCount (cs
) == 0)
1642 #if HAVE_FT_GET_BDF_PROPERTY
1643 if(FT_Get_BDF_Property(face
, "PIXEL_SIZE", &prop
) == 0)
1648 if (!FcPatternAddCharSet (pat
, FC_CHARSET
, cs
))
1651 ls
= FcFreeTypeLangSet (cs
, exclusiveLang
);
1655 if (!FcPatternAddLangSet (pat
, FC_LANG
, ls
))
1657 FcLangSetDestroy (ls
);
1661 FcLangSetDestroy (ls
);
1663 if (spacing
!= FC_PROPORTIONAL
)
1664 if (!FcPatternAddInteger (pat
, FC_SPACING
, spacing
))
1667 if (!(face
->face_flags
& FT_FACE_FLAG_SCALABLE
))
1669 for (i
= 0; i
< face
->num_fixed_sizes
; i
++)
1670 if (!FcPatternAddDouble (pat
, FC_PIXEL_SIZE
,
1671 FcGetPixelSize (face
, i
)))
1673 if (!FcPatternAddBool (pat
, FC_ANTIALIAS
, FcFalse
))
1675 #if HAVE_FT_GET_BDF_PROPERTY
1676 if(face
->num_fixed_sizes
== 1) {
1680 /* skip bitmap fonts which do not even have a family name */
1681 rc
= FT_Get_BDF_Property(face
, "FAMILY_NAME", &prop
);
1682 if (rc
!= 0 || prop
.type
!= BDF_PROPERTY_TYPE_ATOM
)
1685 rc
= FT_Get_BDF_Property(face
, "POINT_SIZE", &prop
);
1686 if(rc
== 0 && prop
.type
== BDF_PROPERTY_TYPE_INTEGER
)
1687 value
= prop
.u
.integer
;
1688 else if(rc
== 0 && prop
.type
== BDF_PROPERTY_TYPE_CARDINAL
)
1689 value
= prop
.u
.cardinal
;
1692 if(!FcPatternAddDouble(pat
, FC_SIZE
, value
/ 10.0))
1695 rc
= FT_Get_BDF_Property(face
, "RESOLUTION_Y", &prop
);
1696 if(rc
== 0 && prop
.type
== BDF_PROPERTY_TYPE_INTEGER
)
1697 value
= prop
.u
.integer
;
1698 else if(rc
== 0 && prop
.type
== BDF_PROPERTY_TYPE_CARDINAL
)
1699 value
= prop
.u
.cardinal
;
1702 if(!FcPatternAddDouble(pat
, FC_DPI
, (double)value
))
1710 #if HAVE_FT_GET_X11_FONT_FORMAT
1712 * Use the (not well documented or supported) X-specific function
1713 * from FreeType to figure out the font format
1716 const char *font_format
= FT_Get_X11_Font_Format (face
);
1718 FcPatternAddString (pat
, FC_FONTFORMAT
, (FcChar8
*) font_format
);
1723 * Drop our reference to the charset
1725 FcCharSetDestroy (cs
);
1728 * Deallocate family/style values
1731 FT_Done_Face (face
);
1732 FT_Done_FreeType (ftLibrary
);
1736 FcCharSetDestroy (cs
);
1738 FcPatternDestroy (pat
);
1740 FT_Done_Face (face
);
1742 FT_Done_FreeType (ftLibrary
);
1748 * For our purposes, this approximation is sufficient
1750 #if !HAVE_FT_GET_NEXT_CHAR
1751 #define FT_Get_Next_Char(face, ucs4, gi) ((ucs4) >= 0xffffff ? \
1753 (*(gi) = 1), (ucs4) + 1)
1754 #warning "No FT_Get_Next_Char: Please install freetype version 2.1.0 or newer"
1757 typedef struct _FcCharEnt
{
1759 unsigned char encode
;
1763 const FcCharEnt
*ent
;
1767 typedef struct _FcFontDecode
{
1768 FT_Encoding encoding
;
1769 const FcCharMap
*map
;
1773 static const FcCharEnt AppleRomanEnt
[] = {
1774 { 0x0020, 0x20 }, /* SPACE */
1775 { 0x0021, 0x21 }, /* EXCLAMATION MARK */
1776 { 0x0022, 0x22 }, /* QUOTATION MARK */
1777 { 0x0023, 0x23 }, /* NUMBER SIGN */
1778 { 0x0024, 0x24 }, /* DOLLAR SIGN */
1779 { 0x0025, 0x25 }, /* PERCENT SIGN */
1780 { 0x0026, 0x26 }, /* AMPERSAND */
1781 { 0x0027, 0x27 }, /* APOSTROPHE */
1782 { 0x0028, 0x28 }, /* LEFT PARENTHESIS */
1783 { 0x0029, 0x29 }, /* RIGHT PARENTHESIS */
1784 { 0x002A, 0x2A }, /* ASTERISK */
1785 { 0x002B, 0x2B }, /* PLUS SIGN */
1786 { 0x002C, 0x2C }, /* COMMA */
1787 { 0x002D, 0x2D }, /* HYPHEN-MINUS */
1788 { 0x002E, 0x2E }, /* FULL STOP */
1789 { 0x002F, 0x2F }, /* SOLIDUS */
1790 { 0x0030, 0x30 }, /* DIGIT ZERO */
1791 { 0x0031, 0x31 }, /* DIGIT ONE */
1792 { 0x0032, 0x32 }, /* DIGIT TWO */
1793 { 0x0033, 0x33 }, /* DIGIT THREE */
1794 { 0x0034, 0x34 }, /* DIGIT FOUR */
1795 { 0x0035, 0x35 }, /* DIGIT FIVE */
1796 { 0x0036, 0x36 }, /* DIGIT SIX */
1797 { 0x0037, 0x37 }, /* DIGIT SEVEN */
1798 { 0x0038, 0x38 }, /* DIGIT EIGHT */
1799 { 0x0039, 0x39 }, /* DIGIT NINE */
1800 { 0x003A, 0x3A }, /* COLON */
1801 { 0x003B, 0x3B }, /* SEMICOLON */
1802 { 0x003C, 0x3C }, /* LESS-THAN SIGN */
1803 { 0x003D, 0x3D }, /* EQUALS SIGN */
1804 { 0x003E, 0x3E }, /* GREATER-THAN SIGN */
1805 { 0x003F, 0x3F }, /* QUESTION MARK */
1806 { 0x0040, 0x40 }, /* COMMERCIAL AT */
1807 { 0x0041, 0x41 }, /* LATIN CAPITAL LETTER A */
1808 { 0x0042, 0x42 }, /* LATIN CAPITAL LETTER B */
1809 { 0x0043, 0x43 }, /* LATIN CAPITAL LETTER C */
1810 { 0x0044, 0x44 }, /* LATIN CAPITAL LETTER D */
1811 { 0x0045, 0x45 }, /* LATIN CAPITAL LETTER E */
1812 { 0x0046, 0x46 }, /* LATIN CAPITAL LETTER F */
1813 { 0x0047, 0x47 }, /* LATIN CAPITAL LETTER G */
1814 { 0x0048, 0x48 }, /* LATIN CAPITAL LETTER H */
1815 { 0x0049, 0x49 }, /* LATIN CAPITAL LETTER I */
1816 { 0x004A, 0x4A }, /* LATIN CAPITAL LETTER J */
1817 { 0x004B, 0x4B }, /* LATIN CAPITAL LETTER K */
1818 { 0x004C, 0x4C }, /* LATIN CAPITAL LETTER L */
1819 { 0x004D, 0x4D }, /* LATIN CAPITAL LETTER M */
1820 { 0x004E, 0x4E }, /* LATIN CAPITAL LETTER N */
1821 { 0x004F, 0x4F }, /* LATIN CAPITAL LETTER O */
1822 { 0x0050, 0x50 }, /* LATIN CAPITAL LETTER P */
1823 { 0x0051, 0x51 }, /* LATIN CAPITAL LETTER Q */
1824 { 0x0052, 0x52 }, /* LATIN CAPITAL LETTER R */
1825 { 0x0053, 0x53 }, /* LATIN CAPITAL LETTER S */
1826 { 0x0054, 0x54 }, /* LATIN CAPITAL LETTER T */
1827 { 0x0055, 0x55 }, /* LATIN CAPITAL LETTER U */
1828 { 0x0056, 0x56 }, /* LATIN CAPITAL LETTER V */
1829 { 0x0057, 0x57 }, /* LATIN CAPITAL LETTER W */
1830 { 0x0058, 0x58 }, /* LATIN CAPITAL LETTER X */
1831 { 0x0059, 0x59 }, /* LATIN CAPITAL LETTER Y */
1832 { 0x005A, 0x5A }, /* LATIN CAPITAL LETTER Z */
1833 { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET */
1834 { 0x005C, 0x5C }, /* REVERSE SOLIDUS */
1835 { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET */
1836 { 0x005E, 0x5E }, /* CIRCUMFLEX ACCENT */
1837 { 0x005F, 0x5F }, /* LOW LINE */
1838 { 0x0060, 0x60 }, /* GRAVE ACCENT */
1839 { 0x0061, 0x61 }, /* LATIN SMALL LETTER A */
1840 { 0x0062, 0x62 }, /* LATIN SMALL LETTER B */
1841 { 0x0063, 0x63 }, /* LATIN SMALL LETTER C */
1842 { 0x0064, 0x64 }, /* LATIN SMALL LETTER D */
1843 { 0x0065, 0x65 }, /* LATIN SMALL LETTER E */
1844 { 0x0066, 0x66 }, /* LATIN SMALL LETTER F */
1845 { 0x0067, 0x67 }, /* LATIN SMALL LETTER G */
1846 { 0x0068, 0x68 }, /* LATIN SMALL LETTER H */
1847 { 0x0069, 0x69 }, /* LATIN SMALL LETTER I */
1848 { 0x006A, 0x6A }, /* LATIN SMALL LETTER J */
1849 { 0x006B, 0x6B }, /* LATIN SMALL LETTER K */
1850 { 0x006C, 0x6C }, /* LATIN SMALL LETTER L */
1851 { 0x006D, 0x6D }, /* LATIN SMALL LETTER M */
1852 { 0x006E, 0x6E }, /* LATIN SMALL LETTER N */
1853 { 0x006F, 0x6F }, /* LATIN SMALL LETTER O */
1854 { 0x0070, 0x70 }, /* LATIN SMALL LETTER P */
1855 { 0x0071, 0x71 }, /* LATIN SMALL LETTER Q */
1856 { 0x0072, 0x72 }, /* LATIN SMALL LETTER R */
1857 { 0x0073, 0x73 }, /* LATIN SMALL LETTER S */
1858 { 0x0074, 0x74 }, /* LATIN SMALL LETTER T */
1859 { 0x0075, 0x75 }, /* LATIN SMALL LETTER U */
1860 { 0x0076, 0x76 }, /* LATIN SMALL LETTER V */
1861 { 0x0077, 0x77 }, /* LATIN SMALL LETTER W */
1862 { 0x0078, 0x78 }, /* LATIN SMALL LETTER X */
1863 { 0x0079, 0x79 }, /* LATIN SMALL LETTER Y */
1864 { 0x007A, 0x7A }, /* LATIN SMALL LETTER Z */
1865 { 0x007B, 0x7B }, /* LEFT CURLY BRACKET */
1866 { 0x007C, 0x7C }, /* VERTICAL LINE */
1867 { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET */
1868 { 0x007E, 0x7E }, /* TILDE */
1869 { 0x00A0, 0xCA }, /* NO-BREAK SPACE */
1870 { 0x00A1, 0xC1 }, /* INVERTED EXCLAMATION MARK */
1871 { 0x00A2, 0xA2 }, /* CENT SIGN */
1872 { 0x00A3, 0xA3 }, /* POUND SIGN */
1873 { 0x00A5, 0xB4 }, /* YEN SIGN */
1874 { 0x00A7, 0xA4 }, /* SECTION SIGN */
1875 { 0x00A8, 0xAC }, /* DIAERESIS */
1876 { 0x00A9, 0xA9 }, /* COPYRIGHT SIGN */
1877 { 0x00AA, 0xBB }, /* FEMININE ORDINAL INDICATOR */
1878 { 0x00AB, 0xC7 }, /* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
1879 { 0x00AC, 0xC2 }, /* NOT SIGN */
1880 { 0x00AE, 0xA8 }, /* REGISTERED SIGN */
1881 { 0x00AF, 0xF8 }, /* MACRON */
1882 { 0x00B0, 0xA1 }, /* DEGREE SIGN */
1883 { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN */
1884 { 0x00B4, 0xAB }, /* ACUTE ACCENT */
1885 { 0x00B5, 0xB5 }, /* MICRO SIGN */
1886 { 0x00B6, 0xA6 }, /* PILCROW SIGN */
1887 { 0x00B7, 0xE1 }, /* MIDDLE DOT */
1888 { 0x00B8, 0xFC }, /* CEDILLA */
1889 { 0x00BA, 0xBC }, /* MASCULINE ORDINAL INDICATOR */
1890 { 0x00BB, 0xC8 }, /* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
1891 { 0x00BF, 0xC0 }, /* INVERTED QUESTION MARK */
1892 { 0x00C0, 0xCB }, /* LATIN CAPITAL LETTER A WITH GRAVE */
1893 { 0x00C1, 0xE7 }, /* LATIN CAPITAL LETTER A WITH ACUTE */
1894 { 0x00C2, 0xE5 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
1895 { 0x00C3, 0xCC }, /* LATIN CAPITAL LETTER A WITH TILDE */
1896 { 0x00C4, 0x80 }, /* LATIN CAPITAL LETTER A WITH DIAERESIS */
1897 { 0x00C5, 0x81 }, /* LATIN CAPITAL LETTER A WITH RING ABOVE */
1898 { 0x00C6, 0xAE }, /* LATIN CAPITAL LETTER AE */
1899 { 0x00C7, 0x82 }, /* LATIN CAPITAL LETTER C WITH CEDILLA */
1900 { 0x00C8, 0xE9 }, /* LATIN CAPITAL LETTER E WITH GRAVE */
1901 { 0x00C9, 0x83 }, /* LATIN CAPITAL LETTER E WITH ACUTE */
1902 { 0x00CA, 0xE6 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
1903 { 0x00CB, 0xE8 }, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
1904 { 0x00CC, 0xED }, /* LATIN CAPITAL LETTER I WITH GRAVE */
1905 { 0x00CD, 0xEA }, /* LATIN CAPITAL LETTER I WITH ACUTE */
1906 { 0x00CE, 0xEB }, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
1907 { 0x00CF, 0xEC }, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
1908 { 0x00D1, 0x84 }, /* LATIN CAPITAL LETTER N WITH TILDE */
1909 { 0x00D2, 0xF1 }, /* LATIN CAPITAL LETTER O WITH GRAVE */
1910 { 0x00D3, 0xEE }, /* LATIN CAPITAL LETTER O WITH ACUTE */
1911 { 0x00D4, 0xEF }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
1912 { 0x00D5, 0xCD }, /* LATIN CAPITAL LETTER O WITH TILDE */
1913 { 0x00D6, 0x85 }, /* LATIN CAPITAL LETTER O WITH DIAERESIS */
1914 { 0x00D8, 0xAF }, /* LATIN CAPITAL LETTER O WITH STROKE */
1915 { 0x00D9, 0xF4 }, /* LATIN CAPITAL LETTER U WITH GRAVE */
1916 { 0x00DA, 0xF2 }, /* LATIN CAPITAL LETTER U WITH ACUTE */
1917 { 0x00DB, 0xF3 }, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
1918 { 0x00DC, 0x86 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS */
1919 { 0x00DF, 0xA7 }, /* LATIN SMALL LETTER SHARP S */
1920 { 0x00E0, 0x88 }, /* LATIN SMALL LETTER A WITH GRAVE */
1921 { 0x00E1, 0x87 }, /* LATIN SMALL LETTER A WITH ACUTE */
1922 { 0x00E2, 0x89 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
1923 { 0x00E3, 0x8B }, /* LATIN SMALL LETTER A WITH TILDE */
1924 { 0x00E4, 0x8A }, /* LATIN SMALL LETTER A WITH DIAERESIS */
1925 { 0x00E5, 0x8C }, /* LATIN SMALL LETTER A WITH RING ABOVE */
1926 { 0x00E6, 0xBE }, /* LATIN SMALL LETTER AE */
1927 { 0x00E7, 0x8D }, /* LATIN SMALL LETTER C WITH CEDILLA */
1928 { 0x00E8, 0x8F }, /* LATIN SMALL LETTER E WITH GRAVE */
1929 { 0x00E9, 0x8E }, /* LATIN SMALL LETTER E WITH ACUTE */
1930 { 0x00EA, 0x90 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */
1931 { 0x00EB, 0x91 }, /* LATIN SMALL LETTER E WITH DIAERESIS */
1932 { 0x00EC, 0x93 }, /* LATIN SMALL LETTER I WITH GRAVE */
1933 { 0x00ED, 0x92 }, /* LATIN SMALL LETTER I WITH ACUTE */
1934 { 0x00EE, 0x94 }, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
1935 { 0x00EF, 0x95 }, /* LATIN SMALL LETTER I WITH DIAERESIS */
1936 { 0x00F1, 0x96 }, /* LATIN SMALL LETTER N WITH TILDE */
1937 { 0x00F2, 0x98 }, /* LATIN SMALL LETTER O WITH GRAVE */
1938 { 0x00F3, 0x97 }, /* LATIN SMALL LETTER O WITH ACUTE */
1939 { 0x00F4, 0x99 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
1940 { 0x00F5, 0x9B }, /* LATIN SMALL LETTER O WITH TILDE */
1941 { 0x00F6, 0x9A }, /* LATIN SMALL LETTER O WITH DIAERESIS */
1942 { 0x00F7, 0xD6 }, /* DIVISION SIGN */
1943 { 0x00F8, 0xBF }, /* LATIN SMALL LETTER O WITH STROKE */
1944 { 0x00F9, 0x9D }, /* LATIN SMALL LETTER U WITH GRAVE */
1945 { 0x00FA, 0x9C }, /* LATIN SMALL LETTER U WITH ACUTE */
1946 { 0x00FB, 0x9E }, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
1947 { 0x00FC, 0x9F }, /* LATIN SMALL LETTER U WITH DIAERESIS */
1948 { 0x00FF, 0xD8 }, /* LATIN SMALL LETTER Y WITH DIAERESIS */
1949 { 0x0131, 0xF5 }, /* LATIN SMALL LETTER DOTLESS I */
1950 { 0x0152, 0xCE }, /* LATIN CAPITAL LIGATURE OE */
1951 { 0x0153, 0xCF }, /* LATIN SMALL LIGATURE OE */
1952 { 0x0178, 0xD9 }, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
1953 { 0x0192, 0xC4 }, /* LATIN SMALL LETTER F WITH HOOK */
1954 { 0x02C6, 0xF6 }, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
1955 { 0x02C7, 0xFF }, /* CARON */
1956 { 0x02D8, 0xF9 }, /* BREVE */
1957 { 0x02D9, 0xFA }, /* DOT ABOVE */
1958 { 0x02DA, 0xFB }, /* RING ABOVE */
1959 { 0x02DB, 0xFE }, /* OGONEK */
1960 { 0x02DC, 0xF7 }, /* SMALL TILDE */
1961 { 0x02DD, 0xFD }, /* DOUBLE ACUTE ACCENT */
1962 { 0x03A9, 0xBD }, /* GREEK CAPITAL LETTER OMEGA */
1963 { 0x03C0, 0xB9 }, /* GREEK SMALL LETTER PI */
1964 { 0x2013, 0xD0 }, /* EN DASH */
1965 { 0x2014, 0xD1 }, /* EM DASH */
1966 { 0x2018, 0xD4 }, /* LEFT SINGLE QUOTATION MARK */
1967 { 0x2019, 0xD5 }, /* RIGHT SINGLE QUOTATION MARK */
1968 { 0x201A, 0xE2 }, /* SINGLE LOW-9 QUOTATION MARK */
1969 { 0x201C, 0xD2 }, /* LEFT DOUBLE QUOTATION MARK */
1970 { 0x201D, 0xD3 }, /* RIGHT DOUBLE QUOTATION MARK */
1971 { 0x201E, 0xE3 }, /* DOUBLE LOW-9 QUOTATION MARK */
1972 { 0x2020, 0xA0 }, /* DAGGER */
1973 { 0x2021, 0xE0 }, /* DOUBLE DAGGER */
1974 { 0x2022, 0xA5 }, /* BULLET */
1975 { 0x2026, 0xC9 }, /* HORIZONTAL ELLIPSIS */
1976 { 0x2030, 0xE4 }, /* PER MILLE SIGN */
1977 { 0x2039, 0xDC }, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
1978 { 0x203A, 0xDD }, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
1979 { 0x2044, 0xDA }, /* FRACTION SLASH */
1980 { 0x20AC, 0xDB }, /* EURO SIGN */
1981 { 0x2122, 0xAA }, /* TRADE MARK SIGN */
1982 { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL */
1983 { 0x2206, 0xC6 }, /* INCREMENT */
1984 { 0x220F, 0xB8 }, /* N-ARY PRODUCT */
1985 { 0x2211, 0xB7 }, /* N-ARY SUMMATION */
1986 { 0x221A, 0xC3 }, /* SQUARE ROOT */
1987 { 0x221E, 0xB0 }, /* INFINITY */
1988 { 0x222B, 0xBA }, /* INTEGRAL */
1989 { 0x2248, 0xC5 }, /* ALMOST EQUAL TO */
1990 { 0x2260, 0xAD }, /* NOT EQUAL TO */
1991 { 0x2264, 0xB2 }, /* LESS-THAN OR EQUAL TO */
1992 { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO */
1993 { 0x25CA, 0xD7 }, /* LOZENGE */
1994 { 0xF8FF, 0xF0 }, /* Apple logo */
1995 { 0xFB01, 0xDE }, /* LATIN SMALL LIGATURE FI */
1996 { 0xFB02, 0xDF }, /* LATIN SMALL LIGATURE FL */
1999 static const FcCharMap AppleRoman
= {
2001 sizeof (AppleRomanEnt
) / sizeof (AppleRomanEnt
[0])
2004 static const FcCharEnt AdobeSymbolEnt
[] = {
2005 { 0x0020, 0x20 }, /* SPACE # space */
2006 { 0x0021, 0x21 }, /* EXCLAMATION MARK # exclam */
2007 { 0x0023, 0x23 }, /* NUMBER SIGN # numbersign */
2008 { 0x0025, 0x25 }, /* PERCENT SIGN # percent */
2009 { 0x0026, 0x26 }, /* AMPERSAND # ampersand */
2010 { 0x0028, 0x28 }, /* LEFT PARENTHESIS # parenleft */
2011 { 0x0029, 0x29 }, /* RIGHT PARENTHESIS # parenright */
2012 { 0x002B, 0x2B }, /* PLUS SIGN # plus */
2013 { 0x002C, 0x2C }, /* COMMA # comma */
2014 { 0x002E, 0x2E }, /* FULL STOP # period */
2015 { 0x002F, 0x2F }, /* SOLIDUS # slash */
2016 { 0x0030, 0x30 }, /* DIGIT ZERO # zero */
2017 { 0x0031, 0x31 }, /* DIGIT ONE # one */
2018 { 0x0032, 0x32 }, /* DIGIT TWO # two */
2019 { 0x0033, 0x33 }, /* DIGIT THREE # three */
2020 { 0x0034, 0x34 }, /* DIGIT FOUR # four */
2021 { 0x0035, 0x35 }, /* DIGIT FIVE # five */
2022 { 0x0036, 0x36 }, /* DIGIT SIX # six */
2023 { 0x0037, 0x37 }, /* DIGIT SEVEN # seven */
2024 { 0x0038, 0x38 }, /* DIGIT EIGHT # eight */
2025 { 0x0039, 0x39 }, /* DIGIT NINE # nine */
2026 { 0x003A, 0x3A }, /* COLON # colon */
2027 { 0x003B, 0x3B }, /* SEMICOLON # semicolon */
2028 { 0x003C, 0x3C }, /* LESS-THAN SIGN # less */
2029 { 0x003D, 0x3D }, /* EQUALS SIGN # equal */
2030 { 0x003E, 0x3E }, /* GREATER-THAN SIGN # greater */
2031 { 0x003F, 0x3F }, /* QUESTION MARK # question */
2032 { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET # bracketleft */
2033 { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET # bracketright */
2034 { 0x005F, 0x5F }, /* LOW LINE # underscore */
2035 { 0x007B, 0x7B }, /* LEFT CURLY BRACKET # braceleft */
2036 { 0x007C, 0x7C }, /* VERTICAL LINE # bar */
2037 { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET # braceright */
2038 { 0x00A0, 0x20 }, /* NO-BREAK SPACE # space */
2039 { 0x00AC, 0xD8 }, /* NOT SIGN # logicalnot */
2040 { 0x00B0, 0xB0 }, /* DEGREE SIGN # degree */
2041 { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN # plusminus */
2042 { 0x00B5, 0x6D }, /* MICRO SIGN # mu */
2043 { 0x00D7, 0xB4 }, /* MULTIPLICATION SIGN # multiply */
2044 { 0x00F7, 0xB8 }, /* DIVISION SIGN # divide */
2045 { 0x0192, 0xA6 }, /* LATIN SMALL LETTER F WITH HOOK # florin */
2046 { 0x0391, 0x41 }, /* GREEK CAPITAL LETTER ALPHA # Alpha */
2047 { 0x0392, 0x42 }, /* GREEK CAPITAL LETTER BETA # Beta */
2048 { 0x0393, 0x47 }, /* GREEK CAPITAL LETTER GAMMA # Gamma */
2049 { 0x0394, 0x44 }, /* GREEK CAPITAL LETTER DELTA # Delta */
2050 { 0x0395, 0x45 }, /* GREEK CAPITAL LETTER EPSILON # Epsilon */
2051 { 0x0396, 0x5A }, /* GREEK CAPITAL LETTER ZETA # Zeta */
2052 { 0x0397, 0x48 }, /* GREEK CAPITAL LETTER ETA # Eta */
2053 { 0x0398, 0x51 }, /* GREEK CAPITAL LETTER THETA # Theta */
2054 { 0x0399, 0x49 }, /* GREEK CAPITAL LETTER IOTA # Iota */
2055 { 0x039A, 0x4B }, /* GREEK CAPITAL LETTER KAPPA # Kappa */
2056 { 0x039B, 0x4C }, /* GREEK CAPITAL LETTER LAMDA # Lambda */
2057 { 0x039C, 0x4D }, /* GREEK CAPITAL LETTER MU # Mu */
2058 { 0x039D, 0x4E }, /* GREEK CAPITAL LETTER NU # Nu */
2059 { 0x039E, 0x58 }, /* GREEK CAPITAL LETTER XI # Xi */
2060 { 0x039F, 0x4F }, /* GREEK CAPITAL LETTER OMICRON # Omicron */
2061 { 0x03A0, 0x50 }, /* GREEK CAPITAL LETTER PI # Pi */
2062 { 0x03A1, 0x52 }, /* GREEK CAPITAL LETTER RHO # Rho */
2063 { 0x03A3, 0x53 }, /* GREEK CAPITAL LETTER SIGMA # Sigma */
2064 { 0x03A4, 0x54 }, /* GREEK CAPITAL LETTER TAU # Tau */
2065 { 0x03A5, 0x55 }, /* GREEK CAPITAL LETTER UPSILON # Upsilon */
2066 { 0x03A6, 0x46 }, /* GREEK CAPITAL LETTER PHI # Phi */
2067 { 0x03A7, 0x43 }, /* GREEK CAPITAL LETTER CHI # Chi */
2068 { 0x03A8, 0x59 }, /* GREEK CAPITAL LETTER PSI # Psi */
2069 { 0x03A9, 0x57 }, /* GREEK CAPITAL LETTER OMEGA # Omega */
2070 { 0x03B1, 0x61 }, /* GREEK SMALL LETTER ALPHA # alpha */
2071 { 0x03B2, 0x62 }, /* GREEK SMALL LETTER BETA # beta */
2072 { 0x03B3, 0x67 }, /* GREEK SMALL LETTER GAMMA # gamma */
2073 { 0x03B4, 0x64 }, /* GREEK SMALL LETTER DELTA # delta */
2074 { 0x03B5, 0x65 }, /* GREEK SMALL LETTER EPSILON # epsilon */
2075 { 0x03B6, 0x7A }, /* GREEK SMALL LETTER ZETA # zeta */
2076 { 0x03B7, 0x68 }, /* GREEK SMALL LETTER ETA # eta */
2077 { 0x03B8, 0x71 }, /* GREEK SMALL LETTER THETA # theta */
2078 { 0x03B9, 0x69 }, /* GREEK SMALL LETTER IOTA # iota */
2079 { 0x03BA, 0x6B }, /* GREEK SMALL LETTER KAPPA # kappa */
2080 { 0x03BB, 0x6C }, /* GREEK SMALL LETTER LAMDA # lambda */
2081 { 0x03BC, 0x6D }, /* GREEK SMALL LETTER MU # mu */
2082 { 0x03BD, 0x6E }, /* GREEK SMALL LETTER NU # nu */
2083 { 0x03BE, 0x78 }, /* GREEK SMALL LETTER XI # xi */
2084 { 0x03BF, 0x6F }, /* GREEK SMALL LETTER OMICRON # omicron */
2085 { 0x03C0, 0x70 }, /* GREEK SMALL LETTER PI # pi */
2086 { 0x03C1, 0x72 }, /* GREEK SMALL LETTER RHO # rho */
2087 { 0x03C2, 0x56 }, /* GREEK SMALL LETTER FINAL SIGMA # sigma1 */
2088 { 0x03C3, 0x73 }, /* GREEK SMALL LETTER SIGMA # sigma */
2089 { 0x03C4, 0x74 }, /* GREEK SMALL LETTER TAU # tau */
2090 { 0x03C5, 0x75 }, /* GREEK SMALL LETTER UPSILON # upsilon */
2091 { 0x03C6, 0x66 }, /* GREEK SMALL LETTER PHI # phi */
2092 { 0x03C7, 0x63 }, /* GREEK SMALL LETTER CHI # chi */
2093 { 0x03C8, 0x79 }, /* GREEK SMALL LETTER PSI # psi */
2094 { 0x03C9, 0x77 }, /* GREEK SMALL LETTER OMEGA # omega */
2095 { 0x03D1, 0x4A }, /* GREEK THETA SYMBOL # theta1 */
2096 { 0x03D2, 0xA1 }, /* GREEK UPSILON WITH HOOK SYMBOL # Upsilon1 */
2097 { 0x03D5, 0x6A }, /* GREEK PHI SYMBOL # phi1 */
2098 { 0x03D6, 0x76 }, /* GREEK PI SYMBOL # omega1 */
2099 { 0x2022, 0xB7 }, /* BULLET # bullet */
2100 { 0x2026, 0xBC }, /* HORIZONTAL ELLIPSIS # ellipsis */
2101 { 0x2032, 0xA2 }, /* PRIME # minute */
2102 { 0x2033, 0xB2 }, /* DOUBLE PRIME # second */
2103 { 0x2044, 0xA4 }, /* FRACTION SLASH # fraction */
2104 { 0x20AC, 0xA0 }, /* EURO SIGN # Euro */
2105 { 0x2111, 0xC1 }, /* BLACK-LETTER CAPITAL I # Ifraktur */
2106 { 0x2118, 0xC3 }, /* SCRIPT CAPITAL P # weierstrass */
2107 { 0x211C, 0xC2 }, /* BLACK-LETTER CAPITAL R # Rfraktur */
2108 { 0x2126, 0x57 }, /* OHM SIGN # Omega */
2109 { 0x2135, 0xC0 }, /* ALEF SYMBOL # aleph */
2110 { 0x2190, 0xAC }, /* LEFTWARDS ARROW # arrowleft */
2111 { 0x2191, 0xAD }, /* UPWARDS ARROW # arrowup */
2112 { 0x2192, 0xAE }, /* RIGHTWARDS ARROW # arrowright */
2113 { 0x2193, 0xAF }, /* DOWNWARDS ARROW # arrowdown */
2114 { 0x2194, 0xAB }, /* LEFT RIGHT ARROW # arrowboth */
2115 { 0x21B5, 0xBF }, /* DOWNWARDS ARROW WITH CORNER LEFTWARDS # carriagereturn */
2116 { 0x21D0, 0xDC }, /* LEFTWARDS DOUBLE ARROW # arrowdblleft */
2117 { 0x21D1, 0xDD }, /* UPWARDS DOUBLE ARROW # arrowdblup */
2118 { 0x21D2, 0xDE }, /* RIGHTWARDS DOUBLE ARROW # arrowdblright */
2119 { 0x21D3, 0xDF }, /* DOWNWARDS DOUBLE ARROW # arrowdbldown */
2120 { 0x21D4, 0xDB }, /* LEFT RIGHT DOUBLE ARROW # arrowdblboth */
2121 { 0x2200, 0x22 }, /* FOR ALL # universal */
2122 { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL # partialdiff */
2123 { 0x2203, 0x24 }, /* THERE EXISTS # existential */
2124 { 0x2205, 0xC6 }, /* EMPTY SET # emptyset */
2125 { 0x2206, 0x44 }, /* INCREMENT # Delta */
2126 { 0x2207, 0xD1 }, /* NABLA # gradient */
2127 { 0x2208, 0xCE }, /* ELEMENT OF # element */
2128 { 0x2209, 0xCF }, /* NOT AN ELEMENT OF # notelement */
2129 { 0x220B, 0x27 }, /* CONTAINS AS MEMBER # suchthat */
2130 { 0x220F, 0xD5 }, /* N-ARY PRODUCT # product */
2131 { 0x2211, 0xE5 }, /* N-ARY SUMMATION # summation */
2132 { 0x2212, 0x2D }, /* MINUS SIGN # minus */
2133 { 0x2215, 0xA4 }, /* DIVISION SLASH # fraction */
2134 { 0x2217, 0x2A }, /* ASTERISK OPERATOR # asteriskmath */
2135 { 0x221A, 0xD6 }, /* SQUARE ROOT # radical */
2136 { 0x221D, 0xB5 }, /* PROPORTIONAL TO # proportional */
2137 { 0x221E, 0xA5 }, /* INFINITY # infinity */
2138 { 0x2220, 0xD0 }, /* ANGLE # angle */
2139 { 0x2227, 0xD9 }, /* LOGICAL AND # logicaland */
2140 { 0x2228, 0xDA }, /* LOGICAL OR # logicalor */
2141 { 0x2229, 0xC7 }, /* INTERSECTION # intersection */
2142 { 0x222A, 0xC8 }, /* UNION # union */
2143 { 0x222B, 0xF2 }, /* INTEGRAL # integral */
2144 { 0x2234, 0x5C }, /* THEREFORE # therefore */
2145 { 0x223C, 0x7E }, /* TILDE OPERATOR # similar */
2146 { 0x2245, 0x40 }, /* APPROXIMATELY EQUAL TO # congruent */
2147 { 0x2248, 0xBB }, /* ALMOST EQUAL TO # approxequal */
2148 { 0x2260, 0xB9 }, /* NOT EQUAL TO # notequal */
2149 { 0x2261, 0xBA }, /* IDENTICAL TO # equivalence */
2150 { 0x2264, 0xA3 }, /* LESS-THAN OR EQUAL TO # lessequal */
2151 { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO # greaterequal */
2152 { 0x2282, 0xCC }, /* SUBSET OF # propersubset */
2153 { 0x2283, 0xC9 }, /* SUPERSET OF # propersuperset */
2154 { 0x2284, 0xCB }, /* NOT A SUBSET OF # notsubset */
2155 { 0x2286, 0xCD }, /* SUBSET OF OR EQUAL TO # reflexsubset */
2156 { 0x2287, 0xCA }, /* SUPERSET OF OR EQUAL TO # reflexsuperset */
2157 { 0x2295, 0xC5 }, /* CIRCLED PLUS # circleplus */
2158 { 0x2297, 0xC4 }, /* CIRCLED TIMES # circlemultiply */
2159 { 0x22A5, 0x5E }, /* UP TACK # perpendicular */
2160 { 0x22C5, 0xD7 }, /* DOT OPERATOR # dotmath */
2161 { 0x2320, 0xF3 }, /* TOP HALF INTEGRAL # integraltp */
2162 { 0x2321, 0xF5 }, /* BOTTOM HALF INTEGRAL # integralbt */
2163 { 0x2329, 0xE1 }, /* LEFT-POINTING ANGLE BRACKET # angleleft */
2164 { 0x232A, 0xF1 }, /* RIGHT-POINTING ANGLE BRACKET # angleright */
2165 { 0x25CA, 0xE0 }, /* LOZENGE # lozenge */
2166 { 0x2660, 0xAA }, /* BLACK SPADE SUIT # spade */
2167 { 0x2663, 0xA7 }, /* BLACK CLUB SUIT # club */
2168 { 0x2665, 0xA9 }, /* BLACK HEART SUIT # heart */
2169 { 0x2666, 0xA8 }, /* BLACK DIAMOND SUIT # diamond */
2170 { 0xF6D9, 0xD3 }, /* COPYRIGHT SIGN SERIF # copyrightserif (CUS) */
2171 { 0xF6DA, 0xD2 }, /* REGISTERED SIGN SERIF # registerserif (CUS) */
2172 { 0xF6DB, 0xD4 }, /* TRADE MARK SIGN SERIF # trademarkserif (CUS) */
2173 { 0xF8E5, 0x60 }, /* RADICAL EXTENDER # radicalex (CUS) */
2174 { 0xF8E6, 0xBD }, /* VERTICAL ARROW EXTENDER # arrowvertex (CUS) */
2175 { 0xF8E7, 0xBE }, /* HORIZONTAL ARROW EXTENDER # arrowhorizex (CUS) */
2176 { 0xF8E8, 0xE2 }, /* REGISTERED SIGN SANS SERIF # registersans (CUS) */
2177 { 0xF8E9, 0xE3 }, /* COPYRIGHT SIGN SANS SERIF # copyrightsans (CUS) */
2178 { 0xF8EA, 0xE4 }, /* TRADE MARK SIGN SANS SERIF # trademarksans (CUS) */
2179 { 0xF8EB, 0xE6 }, /* LEFT PAREN TOP # parenlefttp (CUS) */
2180 { 0xF8EC, 0xE7 }, /* LEFT PAREN EXTENDER # parenleftex (CUS) */
2181 { 0xF8ED, 0xE8 }, /* LEFT PAREN BOTTOM # parenleftbt (CUS) */
2182 { 0xF8EE, 0xE9 }, /* LEFT SQUARE BRACKET TOP # bracketlefttp (CUS) */
2183 { 0xF8EF, 0xEA }, /* LEFT SQUARE BRACKET EXTENDER # bracketleftex (CUS) */
2184 { 0xF8F0, 0xEB }, /* LEFT SQUARE BRACKET BOTTOM # bracketleftbt (CUS) */
2185 { 0xF8F1, 0xEC }, /* LEFT CURLY BRACKET TOP # bracelefttp (CUS) */
2186 { 0xF8F2, 0xED }, /* LEFT CURLY BRACKET MID # braceleftmid (CUS) */
2187 { 0xF8F3, 0xEE }, /* LEFT CURLY BRACKET BOTTOM # braceleftbt (CUS) */
2188 { 0xF8F4, 0xEF }, /* CURLY BRACKET EXTENDER # braceex (CUS) */
2189 { 0xF8F5, 0xF4 }, /* INTEGRAL EXTENDER # integralex (CUS) */
2190 { 0xF8F6, 0xF6 }, /* RIGHT PAREN TOP # parenrighttp (CUS) */
2191 { 0xF8F7, 0xF7 }, /* RIGHT PAREN EXTENDER # parenrightex (CUS) */
2192 { 0xF8F8, 0xF8 }, /* RIGHT PAREN BOTTOM # parenrightbt (CUS) */
2193 { 0xF8F9, 0xF9 }, /* RIGHT SQUARE BRACKET TOP # bracketrighttp (CUS) */
2194 { 0xF8FA, 0xFA }, /* RIGHT SQUARE BRACKET EXTENDER # bracketrightex (CUS) */
2195 { 0xF8FB, 0xFB }, /* RIGHT SQUARE BRACKET BOTTOM # bracketrightbt (CUS) */
2196 { 0xF8FC, 0xFC }, /* RIGHT CURLY BRACKET TOP # bracerighttp (CUS) */
2197 { 0xF8FD, 0xFD }, /* RIGHT CURLY BRACKET MID # bracerightmid (CUS) */
2198 { 0xF8FE, 0xFE }, /* RIGHT CURLY BRACKET BOTTOM # bracerightbt (CUS) */
2201 static const FcCharMap AdobeSymbol
= {
2203 sizeof (AdobeSymbolEnt
) / sizeof (AdobeSymbolEnt
[0]),
2206 static const FcFontDecode fcFontDecoders
[] = {
2207 { ft_encoding_unicode
, 0, (1 << 21) - 1 },
2208 { ft_encoding_symbol
, &AdobeSymbol
, (1 << 16) - 1 },
2209 { ft_encoding_apple_roman
, &AppleRoman
, (1 << 16) - 1 },
2212 #define NUM_DECODE (int) (sizeof (fcFontDecoders) / sizeof (fcFontDecoders[0]))
2214 static const FcChar32 prefer_unicode
[] = {
2215 0x20ac, /* EURO SIGN */
2218 #define NUM_PREFER_UNICODE (int) (sizeof (prefer_unicode) / sizeof (prefer_unicode[0]))
2221 FcFreeTypeUcs4ToPrivate (FcChar32 ucs4
, const FcCharMap
*map
)
2227 high
= map
->nent
- 1;
2228 if (ucs4
< map
->ent
[low
].bmp
|| map
->ent
[high
].bmp
< ucs4
)
2232 mid
= (high
+ low
) >> 1;
2233 bmp
= map
->ent
[mid
].bmp
;
2235 return (FT_ULong
) map
->ent
[mid
].encode
;
2245 FcFreeTypePrivateToUcs4 (FcChar32
private, const FcCharMap
*map
)
2249 for (i
= 0; i
< map
->nent
; i
++)
2250 if (map
->ent
[i
].encode
== private)
2251 return (FcChar32
) map
->ent
[i
].bmp
;
2256 FcFreeTypeGetPrivateMap (FT_Encoding encoding
)
2260 for (i
= 0; i
< NUM_DECODE
; i
++)
2261 if (fcFontDecoders
[i
].encoding
== encoding
)
2262 return fcFontDecoders
[i
].map
;
2266 #include "../fc-glyphname/fcglyphname.h"
2269 FcHashGlyphName (const FcChar8
*name
)
2274 while ((c
= *name
++))
2276 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
2281 #if HAVE_FT_HAS_PS_GLYPH_NAMES
2283 * Use Type1 glyph names for fonts which have reliable names
2284 * and which export an Adobe Custom mapping
2287 FcFreeTypeUseNames (FT_Face face
)
2291 if (!FT_Has_PS_Glyph_Names (face
))
2293 for (map
= 0; map
< face
->num_charmaps
; map
++)
2294 if (face
->charmaps
[map
]->encoding
== ft_encoding_adobe_custom
)
2299 static const FcChar8
*
2300 FcUcs4ToGlyphName (FcChar32 ucs4
)
2302 int i
= (int) (ucs4
% FC_GLYPHNAME_HASH
);
2304 const FcGlyphName
*gn
;
2306 while ((gn
= ucs_to_name
[i
]))
2308 if (gn
->ucs
== ucs4
)
2312 r
= (int) (ucs4
% FC_GLYPHNAME_REHASH
);
2317 if (i
>= FC_GLYPHNAME_HASH
)
2318 i
-= FC_GLYPHNAME_HASH
;
2324 FcGlyphNameToUcs4 (FcChar8
*name
)
2326 FcChar32 h
= FcHashGlyphName (name
);
2327 int i
= (int) (h
% FC_GLYPHNAME_HASH
);
2329 const FcGlyphName
*gn
;
2331 while ((gn
= name_to_ucs
[i
]))
2333 if (!strcmp ((char *) name
, (char *) gn
->name
))
2337 r
= (int) (h
% FC_GLYPHNAME_REHASH
);
2342 if (i
>= FC_GLYPHNAME_HASH
)
2343 i
-= FC_GLYPHNAME_HASH
;
2349 * Search through a font for a glyph by name. This is
2350 * currently a linear search as there doesn't appear to be
2351 * any defined order within the font
2354 FcFreeTypeGlyphNameIndex (FT_Face face
, const FcChar8
*name
)
2357 FcChar8 name_buf
[FC_GLYPHNAME_MAXLEN
+ 2];
2359 for (gindex
= 0; gindex
< (FT_UInt
) face
->num_glyphs
; gindex
++)
2361 if (FT_Get_Glyph_Name (face
, gindex
, name_buf
, FC_GLYPHNAME_MAXLEN
+1) == 0)
2362 if (!strcmp ((char *) name
, (char *) name_buf
))
2370 * Map a UCS4 glyph to a glyph index. Use all available encoding
2371 * tables to try and find one that works. This information is expected
2372 * to be cached by higher levels, so performance isn't critical
2376 FcFreeTypeCharIndex (FT_Face face
, FcChar32 ucs4
)
2378 int initial
, offset
, decode
;
2389 * Find the current encoding
2393 for (; initial
< NUM_DECODE
; initial
++)
2394 if (fcFontDecoders
[initial
].encoding
== face
->charmap
->encoding
)
2396 if (initial
== NUM_DECODE
)
2399 for (p
= 0; p
< NUM_PREFER_UNICODE
; p
++)
2400 if (ucs4
== prefer_unicode
[p
])
2406 * Check each encoding for the glyph, starting with the current one
2408 for (offset
= 0; offset
< NUM_DECODE
; offset
++)
2410 decode
= (initial
+ offset
) % NUM_DECODE
;
2411 if (!face
->charmap
|| face
->charmap
->encoding
!= fcFontDecoders
[decode
].encoding
)
2412 if (FT_Select_Charmap (face
, fcFontDecoders
[decode
].encoding
) != 0)
2414 if (fcFontDecoders
[decode
].map
)
2416 charcode
= FcFreeTypeUcs4ToPrivate (ucs4
, fcFontDecoders
[decode
].map
);
2417 if (charcode
== ~0U)
2422 glyphindex
= FT_Get_Char_Index (face
, (FT_ULong
) charcode
);
2426 #if HAVE_FT_HAS_PS_GLYPH_NAMES
2428 * Check postscript name table if present
2430 if (FcFreeTypeUseNames (face
))
2432 const FcChar8
*name
= FcUcs4ToGlyphName (ucs4
);
2435 glyphindex
= FcFreeTypeGlyphNameIndex (face
, name
);
2445 FcFreeTypeCheckGlyph (FT_Face face
, FcChar32 ucs4
,
2446 FT_UInt glyph
, FcBlanks
*blanks
,
2449 FT_Int load_flags
= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
| FT_LOAD_NO_SCALE
| FT_LOAD_NO_HINTING
;
2453 * When using scalable fonts, only report those glyphs
2454 * which can be scaled; otherwise those fonts will
2455 * only be available at some sizes, and never when
2456 * transformed. Avoid this by simply reporting bitmap-only
2459 if (face
->face_flags
& FT_FACE_FLAG_SCALABLE
)
2460 load_flags
|= FT_LOAD_NO_BITMAP
;
2462 if (FT_Load_Glyph (face
, glyph
, load_flags
))
2469 *advance
= slot
->metrics
.horiAdvance
;
2471 switch (slot
->format
) {
2472 case ft_glyph_format_bitmap
:
2474 * Bitmaps are assumed to be reasonable; if
2475 * this proves to be a rash assumption, this
2476 * code can be easily modified
2479 case ft_glyph_format_outline
:
2481 * Glyphs with contours are always OK
2483 if (slot
->outline
.n_contours
!= 0)
2486 * Glyphs with no contours are only OK if
2487 * they're members of the Blanks set specified
2488 * in the configuration. If blanks isn't set,
2489 * then allow any glyph to be blank
2491 if (!blanks
|| FcBlanksIsMember (blanks
, ucs4
))
2493 /* fall through ... */
2500 #define FC_MIN(a,b) ((a) < (b) ? (a) : (b))
2501 #define FC_MAX(a,b) ((a) > (b) ? (a) : (b))
2502 #define FC_ABS(a) ((a) < 0 ? -(a) : (a))
2503 #define APPROXIMATELY_EQUAL(x,y) (FC_ABS ((x) - (y)) <= FC_MAX (FC_ABS (x), FC_ABS (y)) / 33)
2506 FcFreeTypeCharSetAndSpacing (FT_Face face
, FcBlanks
*blanks
, int *spacing
)
2508 FcChar32 page
, off
, ucs4
;
2510 FcChar32 font_max
= 0;
2514 const FcCharMap
*map
;
2518 FT_Pos advance
, advance_one
= 0, advance_two
= 0;
2519 FcBool has_advance
= FcFalse
, fixed_advance
= FcTrue
, dual_advance
= FcFalse
;
2521 fcs
= FcCharSetCreate ();
2526 printf ("Family %s style %s\n", face
->family_name
, face
->style_name
);
2528 for (o
= 0; o
< NUM_DECODE
; o
++)
2530 if (FT_Select_Charmap (face
, fcFontDecoders
[o
].encoding
) != 0)
2532 map
= fcFontDecoders
[o
].map
;
2536 * Non-Unicode tables are easy; there's a list of all possible
2539 for (i
= 0; i
< map
->nent
; i
++)
2541 ucs4
= map
->ent
[i
].bmp
;
2542 glyph
= FT_Get_Char_Index (face
, map
->ent
[i
].encode
);
2544 FcFreeTypeCheckGlyph (face
, ucs4
, glyph
, blanks
, &advance
))
2547 * ignore glyphs with zero advance. They’re
2548 * combining characters, and while their behaviour
2549 * isn’t well defined for monospaced applications in
2550 * Unicode, there are many fonts which include
2551 * zero-width combining characters in otherwise
2558 has_advance
= FcTrue
;
2559 advance_one
= advance
;
2561 else if (!APPROXIMATELY_EQUAL (advance
, advance_one
))
2565 dual_advance
= FcTrue
;
2566 fixed_advance
= FcFalse
;
2567 advance_two
= advance
;
2569 else if (!APPROXIMATELY_EQUAL (advance
, advance_two
))
2570 dual_advance
= FcFalse
;
2574 leaf
= FcCharSetFindLeafCreate (fcs
, ucs4
);
2577 leaf
->map
[(ucs4
& 0xff) >> 5] |= (1 << (ucs4
& 0x1f));
2579 if (ucs4
> font_max
)
2590 * Find the first encoded character in the font
2592 if (FT_Get_Char_Index (face
, 0))
2599 ucs4
= FT_Get_Next_Char (face
, 0, &gindex
);
2608 while ((ucs4
>> 8) == page
)
2610 glyph
= FT_Get_Char_Index (face
, ucs4
);
2611 if (glyph
&& FcFreeTypeCheckGlyph (face
, ucs4
,
2612 glyph
, blanks
, &advance
))
2618 has_advance
= FcTrue
;
2619 advance_one
= advance
;
2621 else if (!APPROXIMATELY_EQUAL (advance
, advance_one
))
2625 dual_advance
= FcTrue
;
2626 fixed_advance
= FcFalse
;
2627 advance_two
= advance
;
2629 else if (!APPROXIMATELY_EQUAL (advance
, advance_two
))
2630 dual_advance
= FcFalse
;
2636 leaf
= FcCharSetFindLeafCreate (fcs
, ucs4
);
2641 leaf
->map
[off
>> 5] |= (1 << (off
& 0x1f));
2643 if (ucs4
> font_max
)
2649 ucs4
= FT_Get_Next_Char (face
, ucs4
- 1, &gindex
);
2654 for (ucs4
= 0; ucs4
< 0x10000; ucs4
++)
2656 FcBool FT_Has
, FC_Has
;
2658 FT_Has
= FT_Get_Char_Index (face
, ucs4
) != 0;
2659 FC_Has
= FcCharSetHasChar (fcs
, ucs4
);
2660 if (FT_Has
!= FC_Has
)
2662 printf ("0x%08x FT says %d FC says %d\n", ucs4
, FT_Has
, FC_Has
);
2668 #if HAVE_FT_HAS_PS_GLYPH_NAMES
2670 * Add mapping from PS glyph names if available
2672 if (FcFreeTypeUseNames (face
))
2674 FcChar8 name_buf
[FC_GLYPHNAME_MAXLEN
+ 2];
2676 for (glyph
= 0; glyph
< (FT_UInt
) face
->num_glyphs
; glyph
++)
2678 if (FT_Get_Glyph_Name (face
, glyph
, name_buf
, FC_GLYPHNAME_MAXLEN
+1) == 0)
2680 ucs4
= FcGlyphNameToUcs4 (name_buf
);
2681 if (ucs4
!= 0xffff &&
2682 FcFreeTypeCheckGlyph (face
, ucs4
, glyph
, blanks
, &advance
))
2688 has_advance
= FcTrue
;
2689 advance_one
= advance
;
2691 else if (!APPROXIMATELY_EQUAL (advance
, advance_one
))
2695 dual_advance
= FcTrue
;
2696 fixed_advance
= FcFalse
;
2697 advance_two
= advance
;
2699 else if (!APPROXIMATELY_EQUAL (advance
, advance_two
))
2700 dual_advance
= FcFalse
;
2703 leaf
= FcCharSetFindLeafCreate (fcs
, ucs4
);
2706 leaf
->map
[(ucs4
& 0xff) >> 5] |= (1 << (ucs4
& 0x1f));
2708 if (ucs4
> font_max
)
2717 printf ("%d glyphs %d encoded\n", (int) face
->num_glyphs
, FcCharSetCount (fcs
));
2718 for (ucs4
= 0; ucs4
<= font_max
; ucs4
++)
2720 FcBool has_char
= (glyph
= FcFreeTypeCharIndex (face
, ucs4
)) != 0;
2721 FcBool has_bit
= FcCharSetHasChar (fcs
, ucs4
);
2723 if (has_char
&& !has_bit
)
2725 if (!FcFreeTypeCheckGlyph (face
, ucs4
, glyph
, blanks
, &advance
))
2726 printf ("Bitmap missing broken char 0x%x\n", ucs4
);
2728 printf ("Bitmap missing char 0x%x\n", ucs4
);
2730 else if (!has_char
&& has_bit
)
2731 printf ("Bitmap extra char 0x%x\n", ucs4
);
2736 else if (dual_advance
&& APPROXIMATELY_EQUAL (2 * FC_MIN (advance_one
, advance_two
), FC_MAX (advance_one
, advance_two
)))
2739 *spacing
= FC_PROPORTIONAL
;
2742 FcCharSetDestroy (fcs
);
2748 FcFreeTypeCharSet (FT_Face face
, FcBlanks
*blanks
)
2752 return FcFreeTypeCharSetAndSpacing (face
, blanks
, &spacing
);
2756 #define TTAG_GPOS FT_MAKE_TAG( 'G', 'P', 'O', 'S' )
2757 #define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' )
2758 #define TTAG_SILF FT_MAKE_TAG( 'S', 'i', 'l', 'f')
2759 #define TT_Err_Ok FT_Err_Ok
2760 #define TT_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle
2761 #define TTO_Err_Empty_Script 0x1005
2762 #define TTO_Err_Invalid_SubTable 0x1001
2764 #define OTLAYOUT_HEAD "otlayout:"
2765 #define OTLAYOUT_HEAD_LEN 9
2766 #define OTLAYOUT_ID_LEN 4
2767 /* space + head + id */
2768 #define OTLAYOUT_LEN (1 + OTLAYOUT_HEAD_LEN + OTLAYOUT_ID_LEN)
2771 * This is a bit generous; the registry has only lower case and space
2772 * except for 'DFLT'.
2774 #define FcIsSpace(x) (040 == (x))
2775 #define FcIsValidScript(x) (FcIsLower(x) || FcIsUpper (x) || FcIsSpace(x))
2778 addtag(FcChar8
*complex, FT_ULong tag
)
2780 FcChar8 tagstring
[OTLAYOUT_ID_LEN
+ 1];
2782 tagstring
[0] = (FcChar8
)(tag
>> 24),
2783 tagstring
[1] = (FcChar8
)(tag
>> 16),
2784 tagstring
[2] = (FcChar8
)(tag
>> 8),
2785 tagstring
[3] = (FcChar8
)(tag
);
2786 tagstring
[4] = '\0';
2788 /* skip tags which aren't alphabetic, under the assumption that
2789 * they're probably broken
2791 if (!FcIsValidScript(tagstring
[0]) ||
2792 !FcIsValidScript(tagstring
[1]) ||
2793 !FcIsValidScript(tagstring
[2]) ||
2794 !FcIsValidScript(tagstring
[3]))
2797 if (*complex != '\0')
2798 strcat ((char *) complex, " ");
2799 strcat ((char *) complex, "otlayout:");
2800 strcat ((char *) complex, (char *) tagstring
);
2804 compareulong (const void *a
, const void *b
)
2806 const FT_ULong
*ua
= (const FT_ULong
*) a
;
2807 const FT_ULong
*ub
= (const FT_ULong
*) b
;
2813 GetScriptTags(FT_Face face
, FT_ULong tabletag
, FT_ULong
**stags
, FT_UShort
*script_count
)
2815 FT_ULong cur_offset
, new_offset
, base_offset
;
2816 FT_Stream stream
= face
->stream
;
2822 return TT_Err_Invalid_Face_Handle
;
2824 memory
= stream
->memory
;
2826 if (( error
= ftglue_face_goto_table( face
, tabletag
, stream
) ))
2829 base_offset
= ftglue_stream_pos ( stream
);
2833 if ( ftglue_stream_seek ( stream
, base_offset
+ 4L ) || ftglue_stream_frame_enter( stream
, 2L ) )
2836 new_offset
= GET_UShort() + base_offset
;
2838 ftglue_stream_frame_exit( stream
);
2840 cur_offset
= ftglue_stream_pos( stream
);
2842 if ( ftglue_stream_seek( stream
, new_offset
) != TT_Err_Ok
)
2845 base_offset
= ftglue_stream_pos( stream
);
2847 if ( ftglue_stream_frame_enter( stream
, 2L ) )
2850 *script_count
= GET_UShort ();
2852 ftglue_stream_frame_exit( stream
);
2854 *stags
= ftglue_alloc(memory
, *script_count
* sizeof( FT_ULong
), &error
);
2860 for ( n
= 0; n
< *script_count
; n
++ )
2862 if ( ftglue_stream_frame_enter( stream
, 6L ) )
2865 (*stags
)[p
] = GET_ULong ();
2866 new_offset
= GET_UShort () + base_offset
;
2868 ftglue_stream_frame_exit( stream
);
2870 cur_offset
= ftglue_stream_pos( stream
);
2872 error
= ftglue_stream_seek( stream
, new_offset
);
2874 if ( error
== TT_Err_Ok
)
2877 (void)ftglue_stream_seek( stream
, cur_offset
);
2882 error
= TTO_Err_Invalid_SubTable
;
2886 /* sort the tag list before returning it */
2887 qsort(*stags
, *script_count
, sizeof(FT_ULong
), compareulong
);
2893 ftglue_free( memory
, *stags
);
2899 FcFontCapabilities(FT_Face face
)
2901 FcBool issilgraphitefont
= 0;
2904 FT_ULong
*gsubtags
=NULL
, *gpostags
=NULL
;
2905 FT_UShort gsub_count
=0, gpos_count
=0;
2907 FT_Memory memory
= face
->stream
->memory
;
2908 FcChar8
*complex = NULL
;
2909 int indx1
= 0, indx2
= 0;
2911 err
= FT_Load_Sfnt_Table(face
, TTAG_SILF
, 0, 0, &len
);
2912 issilgraphitefont
= ( err
== FT_Err_Ok
);
2914 if (GetScriptTags(face
, TTAG_GPOS
, &gpostags
, &gpos_count
) != FT_Err_Ok
)
2916 if (GetScriptTags(face
, TTAG_GSUB
, &gsubtags
, &gsub_count
) != FT_Err_Ok
)
2919 if (!issilgraphitefont
&& !gsub_count
&& !gpos_count
)
2922 maxsize
= (((FT_ULong
) gpos_count
+ (FT_ULong
) gsub_count
) * OTLAYOUT_LEN
+
2923 (issilgraphitefont
? 13 : 0));
2924 complex = malloc (sizeof (FcChar8
) * maxsize
);
2929 if (issilgraphitefont
)
2930 strcpy((char *) complex, "ttable:Silf ");
2932 while ((indx1
< gsub_count
) || (indx2
< gpos_count
)) {
2933 if (indx1
== gsub_count
) {
2934 addtag(complex, gpostags
[indx2
]);
2936 } else if ((indx2
== gpos_count
) || (gsubtags
[indx1
] < gpostags
[indx2
])) {
2937 addtag(complex, gsubtags
[indx1
]);
2939 } else if (gsubtags
[indx1
] == gpostags
[indx2
]) {
2940 addtag(complex, gsubtags
[indx1
]);
2944 addtag(complex, gpostags
[indx2
]);
2948 if (FcDebug () & FC_DBG_SCANV
)
2949 printf("complex features in this font: %s\n", complex);
2951 ftglue_free(memory
, gsubtags
);
2952 ftglue_free(memory
, gpostags
);