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_FT_GET_BDF_PROPERTY
68 #warning "No FT_Get_BDF_Property: Please install freetype 2.1.4 or later"
71 #if !HAVE_FT_GET_PS_FONT_INFO
72 #warning "No FT_Get_PS_Font_Info: Please install freetype 2.1.1 or later"
76 * Keep Han languages separated by eliminating languages
77 * that the codePageRange bits says aren't supported
83 } FcCodePageRange
[] = {
84 { 17, (const FcChar8
*) "ja" },
85 { 18, (const FcChar8
*) "zh-cn" },
86 { 19, (const FcChar8
*) "ko" },
87 { 20, (const FcChar8
*) "zh-tw" },
90 #define NUM_CODE_PAGE_RANGE (int) (sizeof FcCodePageRange / sizeof FcCodePageRange[0])
93 FcFreeTypeIsExclusiveLang (const FcChar8
*lang
)
97 for (i
= 0; i
< NUM_CODE_PAGE_RANGE
; i
++)
99 if (FcLangCompare (lang
, FcCodePageRange
[i
].lang
) == FcLangEqual
)
106 const FT_UShort platform_id
;
107 const FT_UShort encoding_id
;
108 const char fromcode
[12];
111 #define TT_ENCODING_DONT_CARE 0xffff
112 #define FC_ENCODING_MAC_ROMAN "MACINTOSH"
114 static const FcFtEncoding fcFtEncoding
[] = {
115 { TT_PLATFORM_APPLE_UNICODE
, TT_ENCODING_DONT_CARE
, "UCS-2BE" },
116 { TT_PLATFORM_MACINTOSH
, TT_MAC_ID_ROMAN
, "MACINTOSH" },
117 { TT_PLATFORM_MACINTOSH
, TT_MAC_ID_JAPANESE
, "SJIS" },
118 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_UNICODE_CS
, "UTF-16BE" },
119 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_SJIS
, "SJIS-WIN" },
120 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_GB2312
, "GB3212" },
121 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_BIG_5
, "BIG-5" },
122 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_WANSUNG
, "Wansung" },
123 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_JOHAB
, "Johab" },
124 { TT_PLATFORM_MICROSOFT
, TT_MS_ID_UCS_4
, "UCS4" },
125 { TT_PLATFORM_ISO
, TT_ISO_ID_7BIT_ASCII
, "ASCII" },
126 { TT_PLATFORM_ISO
, TT_ISO_ID_10646
, "UCS-2BE" },
127 { TT_PLATFORM_ISO
, TT_ISO_ID_8859_1
, "ISO-8859-1" },
130 #define NUM_FC_FT_ENCODING (int) (sizeof (fcFtEncoding) / sizeof (fcFtEncoding[0]))
133 const FT_UShort platform_id
;
134 const FT_UShort language_id
;
138 #define TT_LANGUAGE_DONT_CARE 0xffff
140 static const FcFtLanguage fcFtLanguage
[] = {
141 { TT_PLATFORM_APPLE_UNICODE
, TT_LANGUAGE_DONT_CARE
, "" },
142 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ENGLISH
, "en" },
143 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_FRENCH
, "fr" },
144 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GERMAN
, "de" },
145 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ITALIAN
, "it" },
146 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_DUTCH
, "nl" },
147 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SWEDISH
, "sv" },
148 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SPANISH
, "es" },
149 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_DANISH
, "da" },
150 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_PORTUGUESE
, "pt" },
151 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_NORWEGIAN
, "no" },
152 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_HEBREW
, "he" },
153 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_JAPANESE
, "ja" },
154 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ARABIC
, "ar" },
155 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_FINNISH
, "fi" },
156 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GREEK
, "el" },
157 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ICELANDIC
, "is" },
158 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MALTESE
, "mt" },
159 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TURKISH
, "tr" },
160 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CROATIAN
, "hr" },
161 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CHINESE_TRADITIONAL
, "zh-tw" },
162 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_URDU
, "ur" },
163 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_HINDI
, "hi" },
164 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_THAI
, "th" },
165 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KOREAN
, "ko" },
166 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_LITHUANIAN
, "lt" },
167 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_POLISH
, "pl" },
168 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_HUNGARIAN
, "hu" },
169 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ESTONIAN
, "et" },
170 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_LETTISH
, "lv" },
171 /* { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SAAMISK, ??? */
172 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_FAEROESE
, "fo" },
173 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_FARSI
, "fa" },
174 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_RUSSIAN
, "ru" },
175 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CHINESE_SIMPLIFIED
, "zh-cn" },
176 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_FLEMISH
, "nl" },
177 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_IRISH
, "ga" },
178 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ALBANIAN
, "sq" },
179 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ROMANIAN
, "ro" },
180 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CZECH
, "cs" },
181 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SLOVAK
, "sk" },
182 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SLOVENIAN
, "sl" },
183 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_YIDDISH
, "yi" },
184 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SERBIAN
, "sr" },
185 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MACEDONIAN
, "mk" },
186 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BULGARIAN
, "bg" },
187 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_UKRAINIAN
, "uk" },
188 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BYELORUSSIAN
, "be" },
189 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_UZBEK
, "uz" },
190 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KAZAKH
, "kk" },
191 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AZERBAIJANI
, "az" },
192 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT
, "az" },
193 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT
, "ar" },
194 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ARMENIAN
, "hy" },
195 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GEORGIAN
, "ka" },
196 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MOLDAVIAN
, "mo" },
197 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KIRGHIZ
, "ky" },
198 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TAJIKI
, "tg" },
199 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TURKMEN
, "tk" },
200 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MONGOLIAN
, "mo" },
201 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT
,"mo" },
202 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT
, "mo" },
203 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_PASHTO
, "ps" },
204 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KURDISH
, "ku" },
205 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KASHMIRI
, "ks" },
206 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SINDHI
, "sd" },
207 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TIBETAN
, "bo" },
208 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_NEPALI
, "ne" },
209 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SANSKRIT
, "sa" },
210 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MARATHI
, "mr" },
211 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BENGALI
, "bn" },
212 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ASSAMESE
, "as" },
213 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GUJARATI
, "gu" },
214 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_PUNJABI
, "pa" },
215 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ORIYA
, "or" },
216 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MALAYALAM
, "ml" },
217 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KANNADA
, "kn" },
218 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TAMIL
, "ta" },
219 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TELUGU
, "te" },
220 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SINHALESE
, "si" },
221 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BURMESE
, "my" },
222 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_KHMER
, "km" },
223 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_LAO
, "lo" },
224 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_VIETNAMESE
, "vi" },
225 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_INDONESIAN
, "id" },
226 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TAGALOG
, "tl" },
227 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MALAY_ROMAN_SCRIPT
, "ms" },
228 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MALAY_ARABIC_SCRIPT
, "ms" },
229 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AMHARIC
, "am" },
230 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TIGRINYA
, "ti" },
231 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GALLA
, "om" },
232 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SOMALI
, "so" },
233 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SWAHILI
, "sw" },
234 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_RUANDA
, "rw" },
235 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_RUNDI
, "rn" },
236 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CHEWA
, "ny" },
237 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MALAGASY
, "mg" },
238 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_ESPERANTO
, "eo" },
239 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_WELSH
, "cy" },
240 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BASQUE
, "eu" },
241 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_CATALAN
, "ca" },
242 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_LATIN
, "la" },
243 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_QUECHUA
, "qu" },
244 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GUARANI
, "gn" },
245 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AYMARA
, "ay" },
246 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TATAR
, "tt" },
247 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_UIGHUR
, "ug" },
248 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_DZONGKHA
, "dz" },
249 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_JAVANESE
, "jw" },
250 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SUNDANESE
, "su" },
252 #if 0 /* these seem to be errors that have been dropped */
254 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SCOTTISH_GAELIC
},
255 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_IRISH_GAELIC
},
259 /* The following codes are new as of 2000-03-10 */
260 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GALICIAN
, "gl" },
261 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AFRIKAANS
, "af" },
262 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_BRETON
, "br" },
263 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_INUKTITUT
, "iu" },
264 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_SCOTTISH_GAELIC
, "gd" },
265 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_MANX_GAELIC
, "gv" },
266 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_IRISH_GAELIC
, "ga" },
267 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_TONGAN
, "to" },
268 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GREEK_POLYTONIC
, "el" },
269 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_GREELANDIC
, "ik" },
270 { TT_PLATFORM_MACINTOSH
, TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT
,"az" },
272 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_SAUDI_ARABIA
, "ar" },
273 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_IRAQ
, "ar" },
274 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_EGYPT
, "ar" },
275 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_LIBYA
, "ar" },
276 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_ALGERIA
, "ar" },
277 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_MOROCCO
, "ar" },
278 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_TUNISIA
, "ar" },
279 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_OMAN
, "ar" },
280 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_YEMEN
, "ar" },
281 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_SYRIA
, "ar" },
282 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_JORDAN
, "ar" },
283 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_LEBANON
, "ar" },
284 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_KUWAIT
, "ar" },
285 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_UAE
, "ar" },
286 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_BAHRAIN
, "ar" },
287 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_QATAR
, "ar" },
288 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BULGARIAN_BULGARIA
, "bg" },
289 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CATALAN_SPAIN
, "ca" },
290 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_TAIWAN
, "zh-tw" },
291 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_PRC
, "zh-cn" },
292 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_HONG_KONG
, "zh-hk" },
293 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_SINGAPORE
, "zh-sg" },
295 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_MACAU
, "zh-mo" },
297 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CZECH_CZECH_REPUBLIC
, "cs" },
298 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_DANISH_DENMARK
, "da" },
299 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GERMAN_GERMANY
, "de" },
300 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GERMAN_SWITZERLAND
, "de" },
301 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GERMAN_AUSTRIA
, "de" },
302 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GERMAN_LUXEMBOURG
, "de" },
303 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GERMAN_LIECHTENSTEI
, "de" },
304 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GREEK_GREECE
, "el" },
305 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_UNITED_STATES
, "en" },
306 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_UNITED_KINGDOM
, "en" },
307 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_AUSTRALIA
, "en" },
308 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_CANADA
, "en" },
309 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_NEW_ZEALAND
, "en" },
310 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_IRELAND
, "en" },
311 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_SOUTH_AFRICA
, "en" },
312 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_JAMAICA
, "en" },
313 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_CARIBBEAN
, "en" },
314 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_BELIZE
, "en" },
315 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_TRINIDAD
, "en" },
316 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_ZIMBABWE
, "en" },
317 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_PHILIPPINES
, "en" },
318 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT
,"es" },
319 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_MEXICO
, "es" },
320 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT
,"es" },
321 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_GUATEMALA
, "es" },
322 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_COSTA_RICA
, "es" },
323 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_PANAMA
, "es" },
324 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC
,"es" },
325 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_VENEZUELA
, "es" },
326 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_COLOMBIA
, "es" },
327 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_PERU
, "es" },
328 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_ARGENTINA
, "es" },
329 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_ECUADOR
, "es" },
330 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_CHILE
, "es" },
331 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_URUGUAY
, "es" },
332 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_PARAGUAY
, "es" },
333 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_BOLIVIA
, "es" },
334 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_EL_SALVADOR
, "es" },
335 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_HONDURAS
, "es" },
336 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_NICARAGUA
, "es" },
337 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_PUERTO_RICO
, "es" },
338 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FINNISH_FINLAND
, "fi" },
339 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_FRANCE
, "fr" },
340 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_BELGIUM
, "fr" },
341 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_CANADA
, "fr" },
342 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_SWITZERLAND
, "fr" },
343 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_LUXEMBOURG
, "fr" },
344 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_MONACO
, "fr" },
345 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_HEBREW_ISRAEL
, "he" },
346 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_HUNGARIAN_HUNGARY
, "hu" },
347 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ICELANDIC_ICELAND
, "is" },
348 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ITALIAN_ITALY
, "it" },
349 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ITALIAN_SWITZERLAND
, "it" },
350 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_JAPANESE_JAPAN
, "ja" },
351 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA
,"ko" },
352 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KOREAN_JOHAB_KOREA
, "ko" },
353 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_DUTCH_NETHERLANDS
, "nl" },
354 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_DUTCH_BELGIUM
, "nl" },
355 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL
, "no" },
356 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK
, "nn" },
357 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_POLISH_POLAND
, "pl" },
358 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PORTUGUESE_BRAZIL
, "pt" },
359 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PORTUGUESE_PORTUGAL
, "pt" },
360 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND
,"rm" },
361 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ROMANIAN_ROMANIA
, "ro" },
362 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MOLDAVIAN_MOLDAVIA
, "mo" },
363 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_RUSSIAN_RUSSIA
, "ru" },
364 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_RUSSIAN_MOLDAVIA
, "ru" },
365 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CROATIAN_CROATIA
, "hr" },
366 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SERBIAN_SERBIA_LATIN
, "sr" },
367 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC
, "sr" },
368 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SLOVAK_SLOVAKIA
, "sk" },
369 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ALBANIAN_ALBANIA
, "sq" },
370 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SWEDISH_SWEDEN
, "sv" },
371 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SWEDISH_FINLAND
, "sv" },
372 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_THAI_THAILAND
, "th" },
373 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TURKISH_TURKEY
, "tr" },
374 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_URDU_PAKISTAN
, "ur" },
375 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_INDONESIAN_INDONESIA
, "id" },
376 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_UKRAINIAN_UKRAINE
, "uk" },
377 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BELARUSIAN_BELARUS
, "be" },
378 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SLOVENE_SLOVENIA
, "sl" },
379 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ESTONIAN_ESTONIA
, "et" },
380 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_LATVIAN_LATVIA
, "lv" },
381 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_LITHUANIAN_LITHUANIA
, "lt" },
382 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA
,"lt" },
384 #ifdef TT_MS_LANGID_MAORI_NEW_ZELAND
385 /* this seems to be an error that have been dropped */
386 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MAORI_NEW_ZEALAND
, "mi" },
389 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FARSI_IRAN
, "fa" },
390 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_VIETNAMESE_VIET_NAM
, "vi" },
391 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARMENIAN_ARMENIA
, "hy" },
392 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN
, "az" },
393 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC
, "az" },
394 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BASQUE_SPAIN
, "eu" },
395 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SORBIAN_GERMANY
, "wen" },
396 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MACEDONIAN_MACEDONIA
, "mk" },
397 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SUTU_SOUTH_AFRICA
, "st" },
398 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TSONGA_SOUTH_AFRICA
, "ts" },
399 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TSWANA_SOUTH_AFRICA
, "tn" },
400 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_VENDA_SOUTH_AFRICA
, "ven" },
401 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_XHOSA_SOUTH_AFRICA
, "xh" },
402 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ZULU_SOUTH_AFRICA
, "zu" },
403 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA
, "af" },
404 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GEORGIAN_GEORGIA
, "ka" },
405 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS
, "fo" },
406 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_HINDI_INDIA
, "hi" },
407 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MALTESE_MALTA
, "mt" },
408 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SAAMI_LAPONIA
, "se" },
410 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM
,"gd" },
411 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_IRISH_GAELIC_IRELAND
, "ga" },
413 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MALAY_MALAYSIA
, "ms" },
414 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM
, "ms" },
415 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KAZAK_KAZAKSTAN
, "kk" },
416 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SWAHILI_KENYA
, "sw" },
417 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN
, "uz" },
418 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC
, "uz" },
419 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TATAR_TATARSTAN
, "tt" },
420 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BENGALI_INDIA
, "bn" },
421 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PUNJABI_INDIA
, "pa" },
422 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GUJARATI_INDIA
, "gu" },
423 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ORIYA_INDIA
, "or" },
424 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TAMIL_INDIA
, "ta" },
425 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TELUGU_INDIA
, "te" },
426 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KANNADA_INDIA
, "kn" },
427 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MALAYALAM_INDIA
, "ml" },
428 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ASSAMESE_INDIA
, "as" },
429 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MARATHI_INDIA
, "mr" },
430 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SANSKRIT_INDIA
, "sa" },
431 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KONKANI_INDIA
, "kok" },
433 /* new as of 2001-01-01 */
434 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ARABIC_GENERAL
, "ar" },
435 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHINESE_GENERAL
, "zh" },
436 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_GENERAL
, "en" },
437 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_WEST_INDIES
, "fr" },
438 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_REUNION
, "fr" },
439 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_CONGO
, "fr" },
441 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_SENEGAL
, "fr" },
442 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_CAMEROON
, "fr" },
443 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_COTE_D_IVOIRE
, "fr" },
444 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_MALI
, "fr" },
445 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA
,"bs" },
446 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_URDU_INDIA
, "ur" },
447 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TAJIK_TAJIKISTAN
, "tg" },
448 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_YIDDISH_GERMANY
, "yi" },
449 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN
, "ky" },
451 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TURKMEN_TURKMENISTAN
, "tk" },
452 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MONGOLIAN_MONGOLIA
, "mn" },
454 /* the following seems to be inconsistent;
455 here is the current "official" way: */
456 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TIBETAN_BHUTAN
, "bo" },
457 /* and here is what is used by Passport SDK */
458 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TIBETAN_CHINA
, "bo" },
459 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_DZONGHKA_BHUTAN
, "dz" },
460 /* end of inconsistency */
462 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_WELSH_WALES
, "cy" },
463 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KHMER_CAMBODIA
, "km" },
464 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_LAO_LAOS
, "lo" },
465 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BURMESE_MYANMAR
, "my" },
466 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GALICIAN_SPAIN
, "gl" },
467 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MANIPURI_INDIA
, "mni" },
468 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SINDHI_INDIA
, "sd" },
469 /* the following one is only encountered in Microsoft RTF specification */
470 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KASHMIRI_PAKISTAN
, "ks" },
471 /* the following one is not in the Passport list, looks like an omission */
472 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KASHMIRI_INDIA
, "ks" },
473 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_NEPALI_NEPAL
, "ne" },
474 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_NEPALI_INDIA
, "ne" },
475 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRISIAN_NETHERLANDS
, "fy" },
477 /* new as of 2001-03-01 (from Office Xp) */
478 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_HONG_KONG
, "en" },
479 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_INDIA
, "en" },
480 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_MALAYSIA
, "en" },
481 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_ENGLISH_SINGAPORE
, "en" },
482 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SYRIAC_SYRIA
, "syr" },
483 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SINHALESE_SRI_LANKA
, "si" },
484 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_CHEROKEE_UNITED_STATES
, "chr" },
485 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_INUKTITUT_CANADA
, "iu" },
486 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_AMHARIC_ETHIOPIA
, "am" },
488 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TAMAZIGHT_MOROCCO
},
489 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN
},
491 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PASHTO_AFGHANISTAN
, "ps" },
492 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FILIPINO_PHILIPPINES
, "phi" },
493 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_DHIVEHI_MALDIVES
, "div" },
495 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_OROMO_ETHIOPIA
, "om" },
496 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TIGRIGNA_ETHIOPIA
, "ti" },
497 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_TIGRIGNA_ERYTHREA
, "ti" },
499 /* New additions from Windows Xp/Passport SDK 2001-11-10. */
501 /* don't ask what this one means... It is commented out currently. */
503 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GREEK_GREECE2
},
506 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_UNITED_STATES
, "es" },
507 /* The following two IDs blatantly violate MS specs by using a */
508 /* sublanguage >,. */
509 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SPANISH_LATIN_AMERICA
, "es" },
510 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_NORTH_AFRICA
, "fr" },
512 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_MOROCCO
, "fr" },
513 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FRENCH_HAITI
, "fr" },
514 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_BENGALI_BANGLADESH
, "bn" },
515 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN
, "ar" },
516 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN
,"mn" },
518 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_EDO_NIGERIA
},
519 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_FULFULDE_NIGERIA
},
520 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_IBIBIO_NIGERIA
},
522 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_HAUSA_NIGERIA
, "ha" },
523 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_YORUBA_NIGERIA
, "yo" },
524 /* language codes from, to, are (still) unknown. */
525 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_IGBO_NIGERIA
, "ibo" },
526 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_KANURI_NIGERIA
, "kau" },
527 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_GUARANI_PARAGUAY
, "gn" },
528 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_HAWAIIAN_UNITED_STATES
, "haw" },
529 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_LATIN
, "la" },
530 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_SOMALI_SOMALIA
, "so" },
532 /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */
533 /* not written (but OTOH the peculiar writing system is worth */
535 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_YI_CHINA
},
537 { TT_PLATFORM_MICROSOFT
, TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES
,"pap" },
540 #define NUM_FC_FT_LANGUAGE (int) (sizeof (fcFtLanguage) / sizeof (fcFtLanguage[0]))
543 FT_UShort language_id
;
547 static const FcMacRomanFake fcMacRomanFake
[] = {
548 { TT_MS_LANGID_JAPANESE_JAPAN
, "SJIS-WIN" },
549 { TT_MS_LANGID_ENGLISH_UNITED_STATES
, "ASCII" },
553 FcFontCapabilities(FT_Face face
);
555 #define NUM_FC_MAC_ROMAN_FAKE (int) (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0]))
562 FcSfntNameTranscode (FT_SfntName
*sname
)
565 const char *fromcode
;
571 for (i
= 0; i
< NUM_FC_FT_ENCODING
; i
++)
572 if (fcFtEncoding
[i
].platform_id
== sname
->platform_id
&&
573 (fcFtEncoding
[i
].encoding_id
== TT_ENCODING_DONT_CARE
||
574 fcFtEncoding
[i
].encoding_id
== sname
->encoding_id
))
576 if (i
== NUM_FC_FT_ENCODING
)
578 fromcode
= fcFtEncoding
[i
].fromcode
;
581 * "real" Mac language IDs are all less than 150.
582 * Names using one of the MS language IDs are assumed
583 * to use an associated encoding (Yes, this is a kludge)
585 if (!strcmp (fromcode
, FC_ENCODING_MAC_ROMAN
) &&
586 sname
->language_id
>= 0x100)
591 for (f
= 0; f
< NUM_FC_MAC_ROMAN_FAKE
; f
++)
592 if (fcMacRomanFake
[f
].language_id
== sname
->language_id
)
594 fromcode
= fcMacRomanFake
[f
].fromcode
;
600 if (!strcmp (fromcode
, "UCS-2BE") || !strcmp (fromcode
, "UTF-16BE"))
602 FcChar8
*src
= sname
->string
;
603 int src_len
= sname
->string_len
;
611 * Convert Utf16 to Utf8
614 if (!FcUtf16Len (src
, FcEndianBig
, src_len
, &len
, &wchar
))
618 * Allocate plenty of space. Freed below
620 utf8
= malloc (len
* FC_UTF8_MAX_LEN
+ 1);
626 while ((ilen
= FcUtf16ToUcs4 (src
, FcEndianBig
, &ucs4
, src_len
)) > 0)
630 olen
= FcUcs4ToUtf8 (ucs4
, u8
);
636 if (!strcmp (fromcode
, "ASCII") || !strcmp (fromcode
, "ISO-8859-1"))
638 FcChar8
*src
= sname
->string
;
639 int src_len
= sname
->string_len
;
645 * Convert Latin1 to Utf8. Freed below
647 utf8
= malloc (src_len
* 2 + 1);
656 olen
= FcUcs4ToUtf8 (ucs4
, u8
);
662 if (!strcmp (fromcode
, FC_ENCODING_MAC_ROMAN
))
665 const FcCharMap
*map
= FcFreeTypeGetPrivateMap (ft_encoding_apple_roman
);
666 FcChar8
*src
= (FcChar8
*) sname
->string
;
667 int src_len
= sname
->string_len
;
670 * Convert AppleRoman to Utf8
675 utf8
= malloc (sname
->string_len
* 3 + 1);
682 FcChar32 ucs4
= FcFreeTypePrivateToUcs4 (*src
++, map
);
683 int olen
= FcUcs4ToUtf8 (ucs4
, u8
);
691 cd
= iconv_open ("UTF-8", fromcode
);
692 if (cd
&& cd
!= (iconv_t
) (-1))
694 size_t in_bytes_left
= sname
->string_len
;
695 size_t out_bytes_left
= sname
->string_len
* FC_UTF8_MAX_LEN
;
696 char *inbuf
, *outbuf
;
698 utf8
= malloc (out_bytes_left
+ 1);
705 outbuf
= (char *) utf8
;
706 inbuf
= (char *) sname
->string
;
708 while (in_bytes_left
)
710 size_t did
= iconv (cd
,
711 &inbuf
, &in_bytes_left
,
712 &outbuf
, &out_bytes_left
);
713 if (did
== (size_t) (-1))
727 if (FcStrCmpIgnoreBlanksAndCase (utf8
, (FcChar8
*) "") == 0)
735 static const FcChar8
*
736 FcSfntNameLanguage (FT_SfntName
*sname
)
739 for (i
= 0; i
< NUM_FC_FT_LANGUAGE
; i
++)
740 if (fcFtLanguage
[i
].platform_id
== sname
->platform_id
&&
741 (fcFtLanguage
[i
].language_id
== TT_LANGUAGE_DONT_CARE
||
742 fcFtLanguage
[i
].language_id
== sname
->language_id
))
744 if (fcFtLanguage
[i
].lang
[0] == '\0')
747 return (FcChar8
*) fcFtLanguage
[i
].lang
;
752 /* Order is significant. For example, some B&H fonts are hinted by
753 URW++, and both strings appear in the notice. */
755 static const struct {
756 const FT_String
*notice
;
757 const FcChar8
*foundry
;
758 } FcNoticeFoundries
[] = {
759 { (const FT_String
*) "Bigelow", (const FcChar8
*) "b&h" },
760 { (const FT_String
*) "Adobe", (const FcChar8
*) "adobe" },
761 { (const FT_String
*) "Bitstream", (const FcChar8
*) "bitstream" },
762 { (const FT_String
*) "Monotype", (const FcChar8
*) "monotype" },
763 { (const FT_String
*) "Linotype", (const FcChar8
*) "linotype" },
764 { (const FT_String
*) "LINOTYPE-HELL",
765 (const FcChar8
*) "linotype" },
766 { (const FT_String
*) "IBM", (const FcChar8
*) "ibm" },
767 { (const FT_String
*) "URW", (const FcChar8
*) "urw" },
768 { (const FT_String
*) "International Typeface Corporation",
769 (const FcChar8
*) "itc" },
770 { (const FT_String
*) "Tiro Typeworks",
771 (const FcChar8
*) "tiro" },
772 { (const FT_String
*) "XFree86", (const FcChar8
*) "xfree86" },
773 { (const FT_String
*) "Microsoft", (const FcChar8
*) "microsoft" },
774 { (const FT_String
*) "Omega", (const FcChar8
*) "omega" },
775 { (const FT_String
*) "Font21", (const FcChar8
*) "hwan" },
776 { (const FT_String
*) "HanYang System",
777 (const FcChar8
*) "hanyang" }
780 #define NUM_NOTICE_FOUNDRIES (int) (sizeof (FcNoticeFoundries) / sizeof (FcNoticeFoundries[0]))
782 static const FcChar8
*
783 FcNoticeFoundry(const FT_String
*notice
)
788 for(i
= 0; i
< NUM_NOTICE_FOUNDRIES
; i
++)
789 if (strstr ((const char *) notice
, (const char *) FcNoticeFoundries
[i
].notice
))
790 return FcNoticeFoundries
[i
].foundry
;
795 FcVendorMatch(const FT_Char vendor
[4], const FT_Char
*vendor_string
)
797 /* vendor is not necessarily NUL-terminated. */
800 len
= strlen((char *) vendor_string
);
801 if (memcmp(vendor
, vendor_string
, len
) != 0)
803 for (i
= len
; i
< 4; i
++)
804 if (vendor
[i
] != ' ' && vendor
[i
] != '\0')
809 /* This table is partly taken from ttmkfdir by Joerg Pommnitz. */
811 /* It should not contain useless entries (such as UNKN) nor duplicate
812 entries for padding both with spaces and NULs. */
814 static const struct {
815 const FT_Char
*vendor
;
816 const FcChar8
*foundry
;
817 } FcVendorFoundries
[] = {
818 { (const FT_Char
*) "ADBE", (const FcChar8
*) "adobe"},
819 { (const FT_Char
*) "AGFA", (const FcChar8
*) "agfa"},
820 { (const FT_Char
*) "ALTS", (const FcChar8
*) "altsys"},
821 { (const FT_Char
*) "APPL", (const FcChar8
*) "apple"},
822 { (const FT_Char
*) "ARPH", (const FcChar8
*) "arphic"},
823 { (const FT_Char
*) "ATEC", (const FcChar8
*) "alltype"},
824 { (const FT_Char
*) "B&H", (const FcChar8
*) "b&h"},
825 { (const FT_Char
*) "BITS", (const FcChar8
*) "bitstream"},
826 { (const FT_Char
*) "CANO", (const FcChar8
*) "cannon"},
827 { (const FT_Char
*) "DYNA", (const FcChar8
*) "dynalab"},
828 { (const FT_Char
*) "EPSN", (const FcChar8
*) "epson"},
829 { (const FT_Char
*) "FJ", (const FcChar8
*) "fujitsu"},
830 { (const FT_Char
*) "IBM", (const FcChar8
*) "ibm"},
831 { (const FT_Char
*) "ITC", (const FcChar8
*) "itc"},
832 { (const FT_Char
*) "IMPR", (const FcChar8
*) "impress"},
833 { (const FT_Char
*) "LARA", (const FcChar8
*) "larabiefonts"},
834 { (const FT_Char
*) "LEAF", (const FcChar8
*) "interleaf"},
835 { (const FT_Char
*) "LETR", (const FcChar8
*) "letraset"},
836 { (const FT_Char
*) "LINO", (const FcChar8
*) "linotype"},
837 { (const FT_Char
*) "MACR", (const FcChar8
*) "macromedia"},
838 { (const FT_Char
*) "MONO", (const FcChar8
*) "monotype"},
839 { (const FT_Char
*) "MS", (const FcChar8
*) "microsoft"},
840 { (const FT_Char
*) "MT", (const FcChar8
*) "monotype"},
841 { (const FT_Char
*) "NEC", (const FcChar8
*) "nec"},
842 { (const FT_Char
*) "PARA", (const FcChar8
*) "paratype"},
843 { (const FT_Char
*) "QMSI", (const FcChar8
*) "qms"},
844 { (const FT_Char
*) "RICO", (const FcChar8
*) "ricoh"},
845 { (const FT_Char
*) "URW", (const FcChar8
*) "urw"},
846 { (const FT_Char
*) "Y&Y", (const FcChar8
*) "y&y"}
849 #define NUM_VENDOR_FOUNDRIES (int) (sizeof (FcVendorFoundries) / sizeof (FcVendorFoundries[0]))
851 static const FcChar8
*
852 FcVendorFoundry(const FT_Char vendor
[4])
857 for(i
= 0; i
< NUM_VENDOR_FOUNDRIES
; i
++)
858 if (FcVendorMatch (vendor
, FcVendorFoundries
[i
].vendor
))
859 return FcVendorFoundries
[i
].foundry
;
863 typedef struct _FcStringConst
{
869 FcStringIsConst (const FcChar8
*string
,
870 const FcStringConst
*c
,
875 for (i
= 0; i
< nc
; i
++)
876 if (FcStrCmpIgnoreBlanksAndCase (string
, c
[i
].name
) == 0)
882 FcStringContainsConst (const FcChar8
*string
,
883 const FcStringConst
*c
,
888 for (i
= 0; i
< nc
; i
++)
889 if (FcStrContainsIgnoreBlanksAndCase (string
, c
[i
].name
))
894 typedef FcChar8
*FC8
;
896 static const FcStringConst weightConsts
[] = {
897 { (FC8
) "thin", FC_WEIGHT_THIN
},
898 { (FC8
) "extralight", FC_WEIGHT_EXTRALIGHT
},
899 { (FC8
) "ultralight", FC_WEIGHT_ULTRALIGHT
},
900 { (FC8
) "light", FC_WEIGHT_LIGHT
},
901 { (FC8
) "book", FC_WEIGHT_BOOK
},
902 { (FC8
) "regular", FC_WEIGHT_REGULAR
},
903 { (FC8
) "normal", FC_WEIGHT_NORMAL
},
904 { (FC8
) "medium", FC_WEIGHT_MEDIUM
},
905 { (FC8
) "demibold", FC_WEIGHT_DEMIBOLD
},
906 { (FC8
) "demi", FC_WEIGHT_DEMIBOLD
},
907 { (FC8
) "semibold", FC_WEIGHT_SEMIBOLD
},
908 { (FC8
) "bold", FC_WEIGHT_BOLD
},
909 { (FC8
) "extrabold", FC_WEIGHT_EXTRABOLD
},
910 { (FC8
) "ultrabold", FC_WEIGHT_ULTRABOLD
},
911 { (FC8
) "black", FC_WEIGHT_BLACK
},
912 { (FC8
) "heavy", FC_WEIGHT_HEAVY
},
915 #define NUM_WEIGHT_CONSTS (int) (sizeof (weightConsts) / sizeof (weightConsts[0]))
917 #define FcIsWeight(s) FcStringIsConst(s,weightConsts,NUM_WEIGHT_CONSTS)
918 #define FcContainsWeight(s) FcStringContainsConst (s,weightConsts,NUM_WEIGHT_CONSTS)
920 static const FcStringConst widthConsts
[] = {
921 { (FC8
) "ultracondensed", FC_WIDTH_ULTRACONDENSED
},
922 { (FC8
) "extracondensed", FC_WIDTH_EXTRACONDENSED
},
923 { (FC8
) "semicondensed", FC_WIDTH_SEMICONDENSED
},
924 { (FC8
) "condensed", FC_WIDTH_CONDENSED
}, /* must be after *condensed */
925 { (FC8
) "normal", FC_WIDTH_NORMAL
},
926 { (FC8
) "semiexpanded", FC_WIDTH_SEMIEXPANDED
},
927 { (FC8
) "extraexpanded", FC_WIDTH_EXTRAEXPANDED
},
928 { (FC8
) "ultraexpanded", FC_WIDTH_ULTRAEXPANDED
},
929 { (FC8
) "expanded", FC_WIDTH_EXPANDED
}, /* must be after *expanded */
932 #define NUM_WIDTH_CONSTS (int) (sizeof (widthConsts) / sizeof (widthConsts[0]))
934 #define FcIsWidth(s) FcStringIsConst(s,widthConsts,NUM_WIDTH_CONSTS)
935 #define FcContainsWidth(s) FcStringContainsConst (s,widthConsts,NUM_WIDTH_CONSTS)
937 static const FcStringConst slantConsts
[] = {
938 { (FC8
) "italic", FC_SLANT_ITALIC
},
939 { (FC8
) "oblique", FC_SLANT_OBLIQUE
},
942 #define NUM_SLANT_CONSTS (int) (sizeof (slantConsts) / sizeof (slantConsts[0]))
944 #define FcIsSlant(s) FcStringIsConst(s,slantConsts,NUM_SLANT_CONSTS)
945 #define FcContainsSlant(s) FcStringContainsConst (s,slantConsts,NUM_SLANT_CONSTS)
948 FcGetPixelSize (FT_Face face
, int i
)
950 #if HAVE_FT_GET_BDF_PROPERTY
951 if (face
->num_fixed_sizes
== 1)
953 BDF_PropertyRec prop
;
956 rc
= FT_Get_BDF_Property (face
, "PIXEL_SIZE", &prop
);
957 if (rc
== 0 && prop
.type
== BDF_PROPERTY_TYPE_INTEGER
)
958 return (double) prop
.u
.integer
;
961 #if HAVE_FT_BITMAP_SIZE_Y_PPEM
962 return (double) face
->available_sizes
[i
].y_ppem
/ 64.0;
964 return (double) face
->available_sizes
[i
].height
;
969 FcStringInPatternElement (FcPattern
*pat
, const char *elt
, FcChar8
*string
)
973 for (e
= 0; FcPatternGetString (pat
, elt
, e
, &old
) == FcResultMatch
; e
++)
974 if (!FcStrCmpIgnoreBlanksAndCase (old
, string
))
982 FcFreeTypeQuery (const FcChar8
*file
,
995 FT_Library ftLibrary
;
1000 const FcChar8
*foundry
= 0;
1003 #if HAVE_FT_GET_PS_FONT_INFO
1004 PS_FontInfoRec psfontinfo
;
1006 #if HAVE_FT_GET_BDF_PROPERTY
1007 BDF_PropertyRec prop
;
1010 const FcChar8
*exclusiveLang
= 0;
1012 FT_UInt snamei
, snamec
;
1015 int nfamily_lang
= 0;
1017 int nstyle_lang
= 0;
1019 int nfullname_lang
= 0;
1024 if (FT_Init_FreeType (&ftLibrary
))
1027 if (FT_New_Face (ftLibrary
, (char *) file
, id
, &face
))
1030 *count
= face
->num_faces
;
1032 pat
= FcPatternCreate ();
1036 if (!FcPatternAddBool (pat
, FC_OUTLINE
,
1037 (face
->face_flags
& FT_FACE_FLAG_SCALABLE
) != 0))
1040 if (!FcPatternAddBool (pat
, FC_SCALABLE
,
1041 (face
->face_flags
& FT_FACE_FLAG_SCALABLE
) != 0))
1046 * Get the OS/2 table
1048 os2
= (TT_OS2
*) FT_Get_Sfnt_Table (face
, ft_sfnt_os2
);
1051 * Look first in the OS/2 table for the foundry, if
1052 * not found here, the various notices will be searched for
1053 * that information, either from the sfnt name tables or
1054 * the Postscript FontInfo dictionary. Finally, the
1055 * BDF properties will queried.
1058 if (os2
&& os2
->version
>= 0x0001 && os2
->version
!= 0xffff)
1059 foundry
= FcVendorFoundry(os2
->achVendID
);
1061 if (FcDebug () & FC_DBG_SCANV
)
1064 * Grub through the name table looking for family
1065 * and style names. FreeType makes quite a hash
1068 snamec
= FT_Get_Sfnt_Name_Count (face
);
1069 for (snamei
= 0; snamei
< snamec
; snamei
++)
1072 const FcChar8
*lang
;
1073 const char *elt
= 0, *eltlang
= 0;
1074 int *np
= 0, *nlangp
= 0;
1076 if (FT_Get_Sfnt_Name (face
, snamei
, &sname
) != 0)
1079 utf8
= FcSfntNameTranscode (&sname
);
1080 lang
= FcSfntNameLanguage (&sname
);
1085 switch (sname
.name_id
) {
1086 case TT_NAME_ID_FONT_FAMILY
:
1088 case TT_NAME_ID_PS_NAME
:
1089 case TT_NAME_ID_UNIQUE_ID
:
1091 if (FcDebug () & FC_DBG_SCANV
)
1092 printf ("found family (n %2d p %d e %d l 0x%04x) %s\n",
1093 sname
.name_id
, sname
.platform_id
,
1094 sname
.encoding_id
, sname
.language_id
,
1098 eltlang
= FC_FAMILYLANG
;
1100 nlangp
= &nfamily_lang
;
1102 case TT_NAME_ID_FULL_NAME
:
1103 case TT_NAME_ID_MAC_FULL_NAME
:
1104 if (FcDebug () & FC_DBG_SCANV
)
1105 printf ("found full (n %2d p %d e %d l 0x%04x) %s\n",
1106 sname
.name_id
, sname
.platform_id
,
1107 sname
.encoding_id
, sname
.language_id
,
1111 eltlang
= FC_FULLNAMELANG
;
1113 nlangp
= &nfullname_lang
;
1115 case TT_NAME_ID_FONT_SUBFAMILY
:
1116 if (FcDebug () & FC_DBG_SCANV
)
1117 printf ("found style (n %2d p %d e %d l 0x%04x) %s\n",
1118 sname
.name_id
, sname
.platform_id
,
1119 sname
.encoding_id
, sname
.language_id
,
1123 eltlang
= FC_STYLELANG
;
1125 nlangp
= &nstyle_lang
;
1127 case TT_NAME_ID_TRADEMARK
:
1128 case TT_NAME_ID_MANUFACTURER
:
1129 /* If the foundry wasn't found in the OS/2 table, look here */
1131 foundry
= FcNoticeFoundry((FT_String
*) utf8
);
1136 if (FcStringInPatternElement (pat
, elt
, utf8
))
1142 /* add new element */
1143 if (!FcPatternAddString (pat
, elt
, utf8
))
1151 /* pad lang list with 'xx' to line up with elt */
1152 while (*nlangp
< *np
)
1154 if (!FcPatternAddString (pat
, eltlang
, (FcChar8
*) "xx"))
1158 if (!FcPatternAddString (pat
, eltlang
, lang
))
1168 if (!nfamily
&& face
->family_name
&&
1169 FcStrCmpIgnoreBlanksAndCase ((FcChar8
*) face
->family_name
, (FcChar8
*) "") != 0)
1171 if (FcDebug () & FC_DBG_SCANV
)
1172 printf ("using FreeType family \"%s\"\n", face
->family_name
);
1173 if (!FcPatternAddString (pat
, FC_FAMILY
, (FcChar8
*) face
->family_name
))
1178 if (!nstyle
&& face
->style_name
&&
1179 FcStrCmpIgnoreBlanksAndCase ((FcChar8
*) face
->style_name
, (FcChar8
*) "") != 0)
1181 if (FcDebug () & FC_DBG_SCANV
)
1182 printf ("using FreeType style \"%s\"\n", face
->style_name
);
1183 if (!FcPatternAddString (pat
, FC_STYLE
, (FcChar8
*) face
->style_name
))
1190 FcChar8
*start
, *end
;
1193 start
= (FcChar8
*) strrchr ((char *) file
, '/');
1197 start
= (FcChar8
*) file
;
1198 end
= (FcChar8
*) strrchr ((char *) start
, '.');
1200 end
= start
+ strlen ((char *) start
);
1202 family
= malloc (end
- start
+ 1);
1203 strncpy ((char *) family
, (char *) start
, end
- start
);
1204 family
[end
- start
] = '\0';
1205 if (FcDebug () & FC_DBG_SCANV
)
1206 printf ("using filename for family %s\n", family
);
1207 if (!FcPatternAddString (pat
, FC_FAMILY
, family
))
1217 * Walk through FC_FULLNAME entries eliding those in FC_FAMILY
1218 * or which are simply a FC_FAMILY and FC_STYLE glued together
1226 for (fn
= 0; FcPatternGetString (pat
, FC_FULLNAME
, fn
, &full
) == FcResultMatch
; fn
++)
1228 FcBool remove
= FcFalse
;
1232 for (fa
= 0; !remove
&&
1233 FcPatternGetString (pat
, FC_FAMILY
,
1234 fa
, &fam
) == FcResultMatch
;
1240 if (!FcStrCmpIgnoreBlanksAndCase (full
, fam
))
1246 * If the family is in the full name, check the
1247 * combination of this family with every style
1249 if (!FcStrContainsIgnoreBlanksAndCase (full
, fam
))
1251 for (st
= 0; !remove
&&
1252 FcPatternGetString (pat
, FC_STYLE
,
1253 st
, &style
) == FcResultMatch
;
1256 FcChar8
*both
= FcStrPlus (fam
, style
);
1260 if (FcStrCmpIgnoreBlanksAndCase (full
, both
) == 0)
1268 FcPatternRemove (pat
, FC_FULLNAME
, fn
);
1269 FcPatternRemove (pat
, FC_FULLNAMELANG
, fn
);
1275 if (FcDebug () & FC_DBG_SCANV
)
1276 for (fn
= 0; FcPatternGetString (pat
, FC_FULLNAME
, fn
, &full
) == FcResultMatch
; fn
++)
1277 printf ("Saving unique fullname %s\n", full
);
1280 if (!FcPatternAddString (pat
, FC_FILE
, file
))
1283 if (!FcPatternAddInteger (pat
, FC_INDEX
, id
))
1288 * don't even try this -- CJK 'monospace' fonts are really
1289 * dual width, and most other fonts don't bother to set
1290 * the attribute. Sigh.
1292 if ((face
->face_flags
& FT_FACE_FLAG_FIXED_WIDTH
) != 0)
1293 if (!FcPatternAddInteger (pat
, FC_SPACING
, FC_MONO
))
1298 * Find the font revision (if available)
1300 head
= (TT_Header
*) FT_Get_Sfnt_Table (face
, ft_sfnt_head
);
1303 if (!FcPatternAddInteger (pat
, FC_FONTVERSION
, head
->Font_Revision
))
1308 if (!FcPatternAddInteger (pat
, FC_FONTVERSION
, 0))
1312 if (os2
&& os2
->version
>= 0x0001 && os2
->version
!= 0xffff)
1314 for (i
= 0; i
< NUM_CODE_PAGE_RANGE
; i
++)
1318 if (FcCodePageRange
[i
].bit
< 32)
1320 bits
= os2
->ulCodePageRange1
;
1321 bit
= FcCodePageRange
[i
].bit
;
1325 bits
= os2
->ulCodePageRange2
;
1326 bit
= FcCodePageRange
[i
].bit
- 32;
1328 if (bits
& (1 << bit
))
1331 * If the font advertises support for multiple
1332 * "exclusive" languages, then include support
1333 * for any language found to have coverage
1340 exclusiveLang
= FcCodePageRange
[i
].lang
;
1345 if (os2
&& os2
->version
!= 0xffff)
1347 if (os2
->usWeightClass
== 0)
1349 else if (os2
->usWeightClass
< 150)
1350 weight
= FC_WEIGHT_THIN
;
1351 else if (os2
->usWeightClass
< 250)
1352 weight
= FC_WEIGHT_EXTRALIGHT
;
1353 else if (os2
->usWeightClass
< 350)
1354 weight
= FC_WEIGHT_LIGHT
;
1355 else if (os2
->usWeightClass
< 450)
1356 weight
= FC_WEIGHT_REGULAR
;
1357 else if (os2
->usWeightClass
< 550)
1358 weight
= FC_WEIGHT_MEDIUM
;
1359 else if (os2
->usWeightClass
< 650)
1360 weight
= FC_WEIGHT_SEMIBOLD
;
1361 else if (os2
->usWeightClass
< 750)
1362 weight
= FC_WEIGHT_BOLD
;
1363 else if (os2
->usWeightClass
< 850)
1364 weight
= FC_WEIGHT_EXTRABOLD
;
1365 else if (os2
->usWeightClass
< 950)
1366 weight
= FC_WEIGHT_BLACK
;
1368 switch (os2
->usWidthClass
) {
1369 case 1: width
= FC_WIDTH_ULTRACONDENSED
; break;
1370 case 2: width
= FC_WIDTH_EXTRACONDENSED
; break;
1371 case 3: width
= FC_WIDTH_CONDENSED
; break;
1372 case 4: width
= FC_WIDTH_SEMICONDENSED
; break;
1373 case 5: width
= FC_WIDTH_NORMAL
; break;
1374 case 6: width
= FC_WIDTH_SEMIEXPANDED
; break;
1375 case 7: width
= FC_WIDTH_EXPANDED
; break;
1376 case 8: width
= FC_WIDTH_EXTRAEXPANDED
; break;
1377 case 9: width
= FC_WIDTH_ULTRAEXPANDED
; break;
1380 if (os2
&& (complex = FcFontCapabilities(face
)))
1382 if (!FcPatternAddString (pat
, FC_CAPABILITY
, complex))
1391 * Type 1: Check for FontInfo dictionary information
1392 * Code from g2@magestudios.net (Gerard Escalante)
1395 #if HAVE_FT_GET_PS_FONT_INFO
1396 if (FT_Get_PS_Font_Info(face
, &psfontinfo
) == 0)
1398 if (weight
== -1 && psfontinfo
.weight
)
1400 weight
= FcIsWeight ((FcChar8
*) psfontinfo
.weight
);
1401 if (FcDebug() & FC_DBG_SCANV
)
1402 printf ("\tType1 weight %s maps to %d\n",
1403 psfontinfo
.weight
, weight
);
1408 * Don't bother with italic_angle; FreeType already extracts that
1409 * information for us and sticks it into style_flags
1411 if (psfontinfo
.italic_angle
)
1412 slant
= FC_SLANT_ITALIC
;
1414 slant
= FC_SLANT_ROMAN
;
1418 foundry
= FcNoticeFoundry(psfontinfo
.notice
);
1420 #endif /* HAVE_FT_GET_PS_FONT_INFO */
1422 #if HAVE_FT_GET_BDF_PROPERTY
1424 * Finally, look for a FOUNDRY BDF property if no other
1425 * mechanism has managed to locate a foundry
1431 rc
= FT_Get_BDF_Property(face
, "FOUNDRY", &prop
);
1432 if(rc
== 0 && prop
.type
== BDF_PROPERTY_TYPE_ATOM
)
1433 foundry
= (FcChar8
*) prop
.u
.atom
;
1438 if (FT_Get_BDF_Property(face
, "RELATIVE_SETWIDTH", &prop
) == 0 &&
1439 (prop
.type
== BDF_PROPERTY_TYPE_INTEGER
||
1440 prop
.type
== BDF_PROPERTY_TYPE_CARDINAL
))
1444 if (prop
.type
== BDF_PROPERTY_TYPE_INTEGER
)
1445 value
= prop
.u
.integer
;
1447 value
= (FT_Int32
) prop
.u
.cardinal
;
1448 switch ((value
+ 5) / 10) {
1449 case 1: width
= FC_WIDTH_ULTRACONDENSED
; break;
1450 case 2: width
= FC_WIDTH_EXTRACONDENSED
; break;
1451 case 3: width
= FC_WIDTH_CONDENSED
; break;
1452 case 4: width
= FC_WIDTH_SEMICONDENSED
; break;
1453 case 5: width
= FC_WIDTH_NORMAL
; break;
1454 case 6: width
= FC_WIDTH_SEMIEXPANDED
; break;
1455 case 7: width
= FC_WIDTH_EXPANDED
; break;
1456 case 8: width
= FC_WIDTH_EXTRAEXPANDED
; break;
1457 case 9: width
= FC_WIDTH_ULTRAEXPANDED
; break;
1461 FT_Get_BDF_Property (face
, "SETWIDTH_NAME", &prop
) == 0 &&
1462 prop
.type
== BDF_PROPERTY_TYPE_ATOM
)
1464 width
= FcIsWidth ((FcChar8
*) prop
.u
.atom
);
1465 if (FcDebug () & FC_DBG_SCANV
)
1466 printf ("\tsetwidth %s maps to %d\n", prop
.u
.atom
, width
);
1472 * Look for weight, width and slant names in the style value
1474 for (st
= 0; FcPatternGetString (pat
, FC_STYLE
, st
, &style
) == FcResultMatch
; st
++)
1478 weight
= FcContainsWeight (style
);
1479 if (FcDebug() & FC_DBG_SCANV
)
1480 printf ("\tStyle %s maps to weight %d\n", style
, weight
);
1484 width
= FcContainsWidth (style
);
1485 if (FcDebug() & FC_DBG_SCANV
)
1486 printf ("\tStyle %s maps to width %d\n", style
, width
);
1490 slant
= FcContainsSlant (style
);
1491 if (FcDebug() & FC_DBG_SCANV
)
1492 printf ("\tStyle %s maps to slant %d\n", style
, slant
);
1496 * Pull default values from the FreeType flags if more
1497 * specific values not found above
1501 slant
= FC_SLANT_ROMAN
;
1502 if (face
->style_flags
& FT_STYLE_FLAG_ITALIC
)
1503 slant
= FC_SLANT_ITALIC
;
1508 weight
= FC_WEIGHT_MEDIUM
;
1509 if (face
->style_flags
& FT_STYLE_FLAG_BOLD
)
1510 weight
= FC_WEIGHT_BOLD
;
1514 width
= FC_WIDTH_NORMAL
;
1517 foundry
= (FcChar8
*) "unknown";
1519 if (!FcPatternAddInteger (pat
, FC_SLANT
, slant
))
1522 if (!FcPatternAddInteger (pat
, FC_WEIGHT
, weight
))
1525 if (!FcPatternAddInteger (pat
, FC_WIDTH
, width
))
1528 if (!FcPatternAddString (pat
, FC_FOUNDRY
, foundry
))
1532 * Compute the unicode coverage for the font
1534 cs
= FcFreeTypeCharSetAndSpacing (face
, blanks
, &spacing
);
1538 #if HAVE_FT_GET_BDF_PROPERTY
1539 /* For PCF fonts, override the computed spacing with the one from
1541 if(FT_Get_BDF_Property(face
, "SPACING", &prop
) == 0 &&
1542 prop
.type
== BDF_PROPERTY_TYPE_ATOM
) {
1543 if(!strcmp(prop
.u
.atom
, "c") || !strcmp(prop
.u
.atom
, "C"))
1544 spacing
= FC_CHARCELL
;
1545 else if(!strcmp(prop
.u
.atom
, "m") || !strcmp(prop
.u
.atom
, "M"))
1547 else if(!strcmp(prop
.u
.atom
, "p") || !strcmp(prop
.u
.atom
, "P"))
1548 spacing
= FC_PROPORTIONAL
;
1553 * Skip over PCF fonts that have no encoded characters; they're
1554 * usually just Unicode fonts transcoded to some legacy encoding
1555 * ftglue.c forces us to approximate whether a font is a PCF font
1556 * or not by whether it has any BDF properties. Try PIXEL_SIZE;
1557 * I don't know how to get a list of BDF properties on the font. -PL
1559 if (FcCharSetCount (cs
) == 0)
1561 #if HAVE_FT_GET_BDF_PROPERTY
1562 if(FT_Get_BDF_Property(face
, "PIXEL_SIZE", &prop
) == 0)
1567 if (!FcPatternAddCharSet (pat
, FC_CHARSET
, cs
))
1570 ls
= FcFreeTypeLangSet (cs
, exclusiveLang
);
1574 if (!FcPatternAddLangSet (pat
, FC_LANG
, ls
))
1576 FcLangSetDestroy (ls
);
1580 FcLangSetDestroy (ls
);
1582 if (spacing
!= FC_PROPORTIONAL
)
1583 if (!FcPatternAddInteger (pat
, FC_SPACING
, spacing
))
1586 if (!(face
->face_flags
& FT_FACE_FLAG_SCALABLE
))
1588 for (i
= 0; i
< face
->num_fixed_sizes
; i
++)
1589 if (!FcPatternAddDouble (pat
, FC_PIXEL_SIZE
,
1590 FcGetPixelSize (face
, i
)))
1592 if (!FcPatternAddBool (pat
, FC_ANTIALIAS
, FcFalse
))
1594 #if HAVE_FT_GET_BDF_PROPERTY
1595 if(face
->num_fixed_sizes
== 1) {
1599 /* skip bitmap fonts which do not even have a family name */
1600 rc
= FT_Get_BDF_Property(face
, "FAMILY_NAME", &prop
);
1601 if (rc
!= 0 || prop
.type
!= BDF_PROPERTY_TYPE_ATOM
)
1604 rc
= FT_Get_BDF_Property(face
, "POINT_SIZE", &prop
);
1605 if(rc
== 0 && prop
.type
== BDF_PROPERTY_TYPE_INTEGER
)
1606 value
= prop
.u
.integer
;
1607 else if(rc
== 0 && prop
.type
== BDF_PROPERTY_TYPE_CARDINAL
)
1608 value
= prop
.u
.cardinal
;
1611 if(!FcPatternAddDouble(pat
, FC_SIZE
, value
/ 10.0))
1614 rc
= FT_Get_BDF_Property(face
, "RESOLUTION_Y", &prop
);
1615 if(rc
== 0 && prop
.type
== BDF_PROPERTY_TYPE_INTEGER
)
1616 value
= prop
.u
.integer
;
1617 else if(rc
== 0 && prop
.type
== BDF_PROPERTY_TYPE_CARDINAL
)
1618 value
= prop
.u
.cardinal
;
1621 if(!FcPatternAddDouble(pat
, FC_DPI
, (double)value
))
1629 #if HAVE_FT_GET_X11_FONT_FORMAT
1631 * Use the (not well documented or supported) X-specific function
1632 * from FreeType to figure out the font format
1635 const char *font_format
= FT_Get_X11_Font_Format (face
);
1637 FcPatternAddString (pat
, FC_FONTFORMAT
, (FcChar8
*) font_format
);
1642 * Drop our reference to the charset
1644 FcCharSetDestroy (cs
);
1647 * Deallocate family/style values
1650 FT_Done_Face (face
);
1651 FT_Done_FreeType (ftLibrary
);
1655 FcCharSetDestroy (cs
);
1657 FcPatternDestroy (pat
);
1659 FT_Done_Face (face
);
1661 FT_Done_FreeType (ftLibrary
);
1667 * For our purposes, this approximation is sufficient
1669 #if !HAVE_FT_GET_NEXT_CHAR
1670 #define FT_Get_Next_Char(face, ucs4, gi) ((ucs4) >= 0xffffff ? \
1672 (*(gi) = 1), (ucs4) + 1)
1673 #warning "No FT_Get_Next_Char: Please install freetype version 2.1.0 or newer"
1676 typedef struct _FcCharEnt
{
1678 unsigned char encode
;
1682 const FcCharEnt
*ent
;
1686 typedef struct _FcFontDecode
{
1687 FT_Encoding encoding
;
1688 const FcCharMap
*map
;
1692 static const FcCharEnt AppleRomanEnt
[] = {
1693 { 0x0020, 0x20 }, /* SPACE */
1694 { 0x0021, 0x21 }, /* EXCLAMATION MARK */
1695 { 0x0022, 0x22 }, /* QUOTATION MARK */
1696 { 0x0023, 0x23 }, /* NUMBER SIGN */
1697 { 0x0024, 0x24 }, /* DOLLAR SIGN */
1698 { 0x0025, 0x25 }, /* PERCENT SIGN */
1699 { 0x0026, 0x26 }, /* AMPERSAND */
1700 { 0x0027, 0x27 }, /* APOSTROPHE */
1701 { 0x0028, 0x28 }, /* LEFT PARENTHESIS */
1702 { 0x0029, 0x29 }, /* RIGHT PARENTHESIS */
1703 { 0x002A, 0x2A }, /* ASTERISK */
1704 { 0x002B, 0x2B }, /* PLUS SIGN */
1705 { 0x002C, 0x2C }, /* COMMA */
1706 { 0x002D, 0x2D }, /* HYPHEN-MINUS */
1707 { 0x002E, 0x2E }, /* FULL STOP */
1708 { 0x002F, 0x2F }, /* SOLIDUS */
1709 { 0x0030, 0x30 }, /* DIGIT ZERO */
1710 { 0x0031, 0x31 }, /* DIGIT ONE */
1711 { 0x0032, 0x32 }, /* DIGIT TWO */
1712 { 0x0033, 0x33 }, /* DIGIT THREE */
1713 { 0x0034, 0x34 }, /* DIGIT FOUR */
1714 { 0x0035, 0x35 }, /* DIGIT FIVE */
1715 { 0x0036, 0x36 }, /* DIGIT SIX */
1716 { 0x0037, 0x37 }, /* DIGIT SEVEN */
1717 { 0x0038, 0x38 }, /* DIGIT EIGHT */
1718 { 0x0039, 0x39 }, /* DIGIT NINE */
1719 { 0x003A, 0x3A }, /* COLON */
1720 { 0x003B, 0x3B }, /* SEMICOLON */
1721 { 0x003C, 0x3C }, /* LESS-THAN SIGN */
1722 { 0x003D, 0x3D }, /* EQUALS SIGN */
1723 { 0x003E, 0x3E }, /* GREATER-THAN SIGN */
1724 { 0x003F, 0x3F }, /* QUESTION MARK */
1725 { 0x0040, 0x40 }, /* COMMERCIAL AT */
1726 { 0x0041, 0x41 }, /* LATIN CAPITAL LETTER A */
1727 { 0x0042, 0x42 }, /* LATIN CAPITAL LETTER B */
1728 { 0x0043, 0x43 }, /* LATIN CAPITAL LETTER C */
1729 { 0x0044, 0x44 }, /* LATIN CAPITAL LETTER D */
1730 { 0x0045, 0x45 }, /* LATIN CAPITAL LETTER E */
1731 { 0x0046, 0x46 }, /* LATIN CAPITAL LETTER F */
1732 { 0x0047, 0x47 }, /* LATIN CAPITAL LETTER G */
1733 { 0x0048, 0x48 }, /* LATIN CAPITAL LETTER H */
1734 { 0x0049, 0x49 }, /* LATIN CAPITAL LETTER I */
1735 { 0x004A, 0x4A }, /* LATIN CAPITAL LETTER J */
1736 { 0x004B, 0x4B }, /* LATIN CAPITAL LETTER K */
1737 { 0x004C, 0x4C }, /* LATIN CAPITAL LETTER L */
1738 { 0x004D, 0x4D }, /* LATIN CAPITAL LETTER M */
1739 { 0x004E, 0x4E }, /* LATIN CAPITAL LETTER N */
1740 { 0x004F, 0x4F }, /* LATIN CAPITAL LETTER O */
1741 { 0x0050, 0x50 }, /* LATIN CAPITAL LETTER P */
1742 { 0x0051, 0x51 }, /* LATIN CAPITAL LETTER Q */
1743 { 0x0052, 0x52 }, /* LATIN CAPITAL LETTER R */
1744 { 0x0053, 0x53 }, /* LATIN CAPITAL LETTER S */
1745 { 0x0054, 0x54 }, /* LATIN CAPITAL LETTER T */
1746 { 0x0055, 0x55 }, /* LATIN CAPITAL LETTER U */
1747 { 0x0056, 0x56 }, /* LATIN CAPITAL LETTER V */
1748 { 0x0057, 0x57 }, /* LATIN CAPITAL LETTER W */
1749 { 0x0058, 0x58 }, /* LATIN CAPITAL LETTER X */
1750 { 0x0059, 0x59 }, /* LATIN CAPITAL LETTER Y */
1751 { 0x005A, 0x5A }, /* LATIN CAPITAL LETTER Z */
1752 { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET */
1753 { 0x005C, 0x5C }, /* REVERSE SOLIDUS */
1754 { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET */
1755 { 0x005E, 0x5E }, /* CIRCUMFLEX ACCENT */
1756 { 0x005F, 0x5F }, /* LOW LINE */
1757 { 0x0060, 0x60 }, /* GRAVE ACCENT */
1758 { 0x0061, 0x61 }, /* LATIN SMALL LETTER A */
1759 { 0x0062, 0x62 }, /* LATIN SMALL LETTER B */
1760 { 0x0063, 0x63 }, /* LATIN SMALL LETTER C */
1761 { 0x0064, 0x64 }, /* LATIN SMALL LETTER D */
1762 { 0x0065, 0x65 }, /* LATIN SMALL LETTER E */
1763 { 0x0066, 0x66 }, /* LATIN SMALL LETTER F */
1764 { 0x0067, 0x67 }, /* LATIN SMALL LETTER G */
1765 { 0x0068, 0x68 }, /* LATIN SMALL LETTER H */
1766 { 0x0069, 0x69 }, /* LATIN SMALL LETTER I */
1767 { 0x006A, 0x6A }, /* LATIN SMALL LETTER J */
1768 { 0x006B, 0x6B }, /* LATIN SMALL LETTER K */
1769 { 0x006C, 0x6C }, /* LATIN SMALL LETTER L */
1770 { 0x006D, 0x6D }, /* LATIN SMALL LETTER M */
1771 { 0x006E, 0x6E }, /* LATIN SMALL LETTER N */
1772 { 0x006F, 0x6F }, /* LATIN SMALL LETTER O */
1773 { 0x0070, 0x70 }, /* LATIN SMALL LETTER P */
1774 { 0x0071, 0x71 }, /* LATIN SMALL LETTER Q */
1775 { 0x0072, 0x72 }, /* LATIN SMALL LETTER R */
1776 { 0x0073, 0x73 }, /* LATIN SMALL LETTER S */
1777 { 0x0074, 0x74 }, /* LATIN SMALL LETTER T */
1778 { 0x0075, 0x75 }, /* LATIN SMALL LETTER U */
1779 { 0x0076, 0x76 }, /* LATIN SMALL LETTER V */
1780 { 0x0077, 0x77 }, /* LATIN SMALL LETTER W */
1781 { 0x0078, 0x78 }, /* LATIN SMALL LETTER X */
1782 { 0x0079, 0x79 }, /* LATIN SMALL LETTER Y */
1783 { 0x007A, 0x7A }, /* LATIN SMALL LETTER Z */
1784 { 0x007B, 0x7B }, /* LEFT CURLY BRACKET */
1785 { 0x007C, 0x7C }, /* VERTICAL LINE */
1786 { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET */
1787 { 0x007E, 0x7E }, /* TILDE */
1788 { 0x00A0, 0xCA }, /* NO-BREAK SPACE */
1789 { 0x00A1, 0xC1 }, /* INVERTED EXCLAMATION MARK */
1790 { 0x00A2, 0xA2 }, /* CENT SIGN */
1791 { 0x00A3, 0xA3 }, /* POUND SIGN */
1792 { 0x00A5, 0xB4 }, /* YEN SIGN */
1793 { 0x00A7, 0xA4 }, /* SECTION SIGN */
1794 { 0x00A8, 0xAC }, /* DIAERESIS */
1795 { 0x00A9, 0xA9 }, /* COPYRIGHT SIGN */
1796 { 0x00AA, 0xBB }, /* FEMININE ORDINAL INDICATOR */
1797 { 0x00AB, 0xC7 }, /* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
1798 { 0x00AC, 0xC2 }, /* NOT SIGN */
1799 { 0x00AE, 0xA8 }, /* REGISTERED SIGN */
1800 { 0x00AF, 0xF8 }, /* MACRON */
1801 { 0x00B0, 0xA1 }, /* DEGREE SIGN */
1802 { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN */
1803 { 0x00B4, 0xAB }, /* ACUTE ACCENT */
1804 { 0x00B5, 0xB5 }, /* MICRO SIGN */
1805 { 0x00B6, 0xA6 }, /* PILCROW SIGN */
1806 { 0x00B7, 0xE1 }, /* MIDDLE DOT */
1807 { 0x00B8, 0xFC }, /* CEDILLA */
1808 { 0x00BA, 0xBC }, /* MASCULINE ORDINAL INDICATOR */
1809 { 0x00BB, 0xC8 }, /* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
1810 { 0x00BF, 0xC0 }, /* INVERTED QUESTION MARK */
1811 { 0x00C0, 0xCB }, /* LATIN CAPITAL LETTER A WITH GRAVE */
1812 { 0x00C1, 0xE7 }, /* LATIN CAPITAL LETTER A WITH ACUTE */
1813 { 0x00C2, 0xE5 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
1814 { 0x00C3, 0xCC }, /* LATIN CAPITAL LETTER A WITH TILDE */
1815 { 0x00C4, 0x80 }, /* LATIN CAPITAL LETTER A WITH DIAERESIS */
1816 { 0x00C5, 0x81 }, /* LATIN CAPITAL LETTER A WITH RING ABOVE */
1817 { 0x00C6, 0xAE }, /* LATIN CAPITAL LETTER AE */
1818 { 0x00C7, 0x82 }, /* LATIN CAPITAL LETTER C WITH CEDILLA */
1819 { 0x00C8, 0xE9 }, /* LATIN CAPITAL LETTER E WITH GRAVE */
1820 { 0x00C9, 0x83 }, /* LATIN CAPITAL LETTER E WITH ACUTE */
1821 { 0x00CA, 0xE6 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
1822 { 0x00CB, 0xE8 }, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
1823 { 0x00CC, 0xED }, /* LATIN CAPITAL LETTER I WITH GRAVE */
1824 { 0x00CD, 0xEA }, /* LATIN CAPITAL LETTER I WITH ACUTE */
1825 { 0x00CE, 0xEB }, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
1826 { 0x00CF, 0xEC }, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
1827 { 0x00D1, 0x84 }, /* LATIN CAPITAL LETTER N WITH TILDE */
1828 { 0x00D2, 0xF1 }, /* LATIN CAPITAL LETTER O WITH GRAVE */
1829 { 0x00D3, 0xEE }, /* LATIN CAPITAL LETTER O WITH ACUTE */
1830 { 0x00D4, 0xEF }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
1831 { 0x00D5, 0xCD }, /* LATIN CAPITAL LETTER O WITH TILDE */
1832 { 0x00D6, 0x85 }, /* LATIN CAPITAL LETTER O WITH DIAERESIS */
1833 { 0x00D8, 0xAF }, /* LATIN CAPITAL LETTER O WITH STROKE */
1834 { 0x00D9, 0xF4 }, /* LATIN CAPITAL LETTER U WITH GRAVE */
1835 { 0x00DA, 0xF2 }, /* LATIN CAPITAL LETTER U WITH ACUTE */
1836 { 0x00DB, 0xF3 }, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
1837 { 0x00DC, 0x86 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS */
1838 { 0x00DF, 0xA7 }, /* LATIN SMALL LETTER SHARP S */
1839 { 0x00E0, 0x88 }, /* LATIN SMALL LETTER A WITH GRAVE */
1840 { 0x00E1, 0x87 }, /* LATIN SMALL LETTER A WITH ACUTE */
1841 { 0x00E2, 0x89 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
1842 { 0x00E3, 0x8B }, /* LATIN SMALL LETTER A WITH TILDE */
1843 { 0x00E4, 0x8A }, /* LATIN SMALL LETTER A WITH DIAERESIS */
1844 { 0x00E5, 0x8C }, /* LATIN SMALL LETTER A WITH RING ABOVE */
1845 { 0x00E6, 0xBE }, /* LATIN SMALL LETTER AE */
1846 { 0x00E7, 0x8D }, /* LATIN SMALL LETTER C WITH CEDILLA */
1847 { 0x00E8, 0x8F }, /* LATIN SMALL LETTER E WITH GRAVE */
1848 { 0x00E9, 0x8E }, /* LATIN SMALL LETTER E WITH ACUTE */
1849 { 0x00EA, 0x90 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */
1850 { 0x00EB, 0x91 }, /* LATIN SMALL LETTER E WITH DIAERESIS */
1851 { 0x00EC, 0x93 }, /* LATIN SMALL LETTER I WITH GRAVE */
1852 { 0x00ED, 0x92 }, /* LATIN SMALL LETTER I WITH ACUTE */
1853 { 0x00EE, 0x94 }, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
1854 { 0x00EF, 0x95 }, /* LATIN SMALL LETTER I WITH DIAERESIS */
1855 { 0x00F1, 0x96 }, /* LATIN SMALL LETTER N WITH TILDE */
1856 { 0x00F2, 0x98 }, /* LATIN SMALL LETTER O WITH GRAVE */
1857 { 0x00F3, 0x97 }, /* LATIN SMALL LETTER O WITH ACUTE */
1858 { 0x00F4, 0x99 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
1859 { 0x00F5, 0x9B }, /* LATIN SMALL LETTER O WITH TILDE */
1860 { 0x00F6, 0x9A }, /* LATIN SMALL LETTER O WITH DIAERESIS */
1861 { 0x00F7, 0xD6 }, /* DIVISION SIGN */
1862 { 0x00F8, 0xBF }, /* LATIN SMALL LETTER O WITH STROKE */
1863 { 0x00F9, 0x9D }, /* LATIN SMALL LETTER U WITH GRAVE */
1864 { 0x00FA, 0x9C }, /* LATIN SMALL LETTER U WITH ACUTE */
1865 { 0x00FB, 0x9E }, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
1866 { 0x00FC, 0x9F }, /* LATIN SMALL LETTER U WITH DIAERESIS */
1867 { 0x00FF, 0xD8 }, /* LATIN SMALL LETTER Y WITH DIAERESIS */
1868 { 0x0131, 0xF5 }, /* LATIN SMALL LETTER DOTLESS I */
1869 { 0x0152, 0xCE }, /* LATIN CAPITAL LIGATURE OE */
1870 { 0x0153, 0xCF }, /* LATIN SMALL LIGATURE OE */
1871 { 0x0178, 0xD9 }, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
1872 { 0x0192, 0xC4 }, /* LATIN SMALL LETTER F WITH HOOK */
1873 { 0x02C6, 0xF6 }, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
1874 { 0x02C7, 0xFF }, /* CARON */
1875 { 0x02D8, 0xF9 }, /* BREVE */
1876 { 0x02D9, 0xFA }, /* DOT ABOVE */
1877 { 0x02DA, 0xFB }, /* RING ABOVE */
1878 { 0x02DB, 0xFE }, /* OGONEK */
1879 { 0x02DC, 0xF7 }, /* SMALL TILDE */
1880 { 0x02DD, 0xFD }, /* DOUBLE ACUTE ACCENT */
1881 { 0x03A9, 0xBD }, /* GREEK CAPITAL LETTER OMEGA */
1882 { 0x03C0, 0xB9 }, /* GREEK SMALL LETTER PI */
1883 { 0x2013, 0xD0 }, /* EN DASH */
1884 { 0x2014, 0xD1 }, /* EM DASH */
1885 { 0x2018, 0xD4 }, /* LEFT SINGLE QUOTATION MARK */
1886 { 0x2019, 0xD5 }, /* RIGHT SINGLE QUOTATION MARK */
1887 { 0x201A, 0xE2 }, /* SINGLE LOW-9 QUOTATION MARK */
1888 { 0x201C, 0xD2 }, /* LEFT DOUBLE QUOTATION MARK */
1889 { 0x201D, 0xD3 }, /* RIGHT DOUBLE QUOTATION MARK */
1890 { 0x201E, 0xE3 }, /* DOUBLE LOW-9 QUOTATION MARK */
1891 { 0x2020, 0xA0 }, /* DAGGER */
1892 { 0x2021, 0xE0 }, /* DOUBLE DAGGER */
1893 { 0x2022, 0xA5 }, /* BULLET */
1894 { 0x2026, 0xC9 }, /* HORIZONTAL ELLIPSIS */
1895 { 0x2030, 0xE4 }, /* PER MILLE SIGN */
1896 { 0x2039, 0xDC }, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
1897 { 0x203A, 0xDD }, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
1898 { 0x2044, 0xDA }, /* FRACTION SLASH */
1899 { 0x20AC, 0xDB }, /* EURO SIGN */
1900 { 0x2122, 0xAA }, /* TRADE MARK SIGN */
1901 { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL */
1902 { 0x2206, 0xC6 }, /* INCREMENT */
1903 { 0x220F, 0xB8 }, /* N-ARY PRODUCT */
1904 { 0x2211, 0xB7 }, /* N-ARY SUMMATION */
1905 { 0x221A, 0xC3 }, /* SQUARE ROOT */
1906 { 0x221E, 0xB0 }, /* INFINITY */
1907 { 0x222B, 0xBA }, /* INTEGRAL */
1908 { 0x2248, 0xC5 }, /* ALMOST EQUAL TO */
1909 { 0x2260, 0xAD }, /* NOT EQUAL TO */
1910 { 0x2264, 0xB2 }, /* LESS-THAN OR EQUAL TO */
1911 { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO */
1912 { 0x25CA, 0xD7 }, /* LOZENGE */
1913 { 0xF8FF, 0xF0 }, /* Apple logo */
1914 { 0xFB01, 0xDE }, /* LATIN SMALL LIGATURE FI */
1915 { 0xFB02, 0xDF }, /* LATIN SMALL LIGATURE FL */
1918 static const FcCharMap AppleRoman
= {
1920 sizeof (AppleRomanEnt
) / sizeof (AppleRomanEnt
[0])
1923 static const FcCharEnt AdobeSymbolEnt
[] = {
1924 { 0x0020, 0x20 }, /* SPACE # space */
1925 { 0x0021, 0x21 }, /* EXCLAMATION MARK # exclam */
1926 { 0x0023, 0x23 }, /* NUMBER SIGN # numbersign */
1927 { 0x0025, 0x25 }, /* PERCENT SIGN # percent */
1928 { 0x0026, 0x26 }, /* AMPERSAND # ampersand */
1929 { 0x0028, 0x28 }, /* LEFT PARENTHESIS # parenleft */
1930 { 0x0029, 0x29 }, /* RIGHT PARENTHESIS # parenright */
1931 { 0x002B, 0x2B }, /* PLUS SIGN # plus */
1932 { 0x002C, 0x2C }, /* COMMA # comma */
1933 { 0x002E, 0x2E }, /* FULL STOP # period */
1934 { 0x002F, 0x2F }, /* SOLIDUS # slash */
1935 { 0x0030, 0x30 }, /* DIGIT ZERO # zero */
1936 { 0x0031, 0x31 }, /* DIGIT ONE # one */
1937 { 0x0032, 0x32 }, /* DIGIT TWO # two */
1938 { 0x0033, 0x33 }, /* DIGIT THREE # three */
1939 { 0x0034, 0x34 }, /* DIGIT FOUR # four */
1940 { 0x0035, 0x35 }, /* DIGIT FIVE # five */
1941 { 0x0036, 0x36 }, /* DIGIT SIX # six */
1942 { 0x0037, 0x37 }, /* DIGIT SEVEN # seven */
1943 { 0x0038, 0x38 }, /* DIGIT EIGHT # eight */
1944 { 0x0039, 0x39 }, /* DIGIT NINE # nine */
1945 { 0x003A, 0x3A }, /* COLON # colon */
1946 { 0x003B, 0x3B }, /* SEMICOLON # semicolon */
1947 { 0x003C, 0x3C }, /* LESS-THAN SIGN # less */
1948 { 0x003D, 0x3D }, /* EQUALS SIGN # equal */
1949 { 0x003E, 0x3E }, /* GREATER-THAN SIGN # greater */
1950 { 0x003F, 0x3F }, /* QUESTION MARK # question */
1951 { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET # bracketleft */
1952 { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET # bracketright */
1953 { 0x005F, 0x5F }, /* LOW LINE # underscore */
1954 { 0x007B, 0x7B }, /* LEFT CURLY BRACKET # braceleft */
1955 { 0x007C, 0x7C }, /* VERTICAL LINE # bar */
1956 { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET # braceright */
1957 { 0x00A0, 0x20 }, /* NO-BREAK SPACE # space */
1958 { 0x00AC, 0xD8 }, /* NOT SIGN # logicalnot */
1959 { 0x00B0, 0xB0 }, /* DEGREE SIGN # degree */
1960 { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN # plusminus */
1961 { 0x00B5, 0x6D }, /* MICRO SIGN # mu */
1962 { 0x00D7, 0xB4 }, /* MULTIPLICATION SIGN # multiply */
1963 { 0x00F7, 0xB8 }, /* DIVISION SIGN # divide */
1964 { 0x0192, 0xA6 }, /* LATIN SMALL LETTER F WITH HOOK # florin */
1965 { 0x0391, 0x41 }, /* GREEK CAPITAL LETTER ALPHA # Alpha */
1966 { 0x0392, 0x42 }, /* GREEK CAPITAL LETTER BETA # Beta */
1967 { 0x0393, 0x47 }, /* GREEK CAPITAL LETTER GAMMA # Gamma */
1968 { 0x0394, 0x44 }, /* GREEK CAPITAL LETTER DELTA # Delta */
1969 { 0x0395, 0x45 }, /* GREEK CAPITAL LETTER EPSILON # Epsilon */
1970 { 0x0396, 0x5A }, /* GREEK CAPITAL LETTER ZETA # Zeta */
1971 { 0x0397, 0x48 }, /* GREEK CAPITAL LETTER ETA # Eta */
1972 { 0x0398, 0x51 }, /* GREEK CAPITAL LETTER THETA # Theta */
1973 { 0x0399, 0x49 }, /* GREEK CAPITAL LETTER IOTA # Iota */
1974 { 0x039A, 0x4B }, /* GREEK CAPITAL LETTER KAPPA # Kappa */
1975 { 0x039B, 0x4C }, /* GREEK CAPITAL LETTER LAMDA # Lambda */
1976 { 0x039C, 0x4D }, /* GREEK CAPITAL LETTER MU # Mu */
1977 { 0x039D, 0x4E }, /* GREEK CAPITAL LETTER NU # Nu */
1978 { 0x039E, 0x58 }, /* GREEK CAPITAL LETTER XI # Xi */
1979 { 0x039F, 0x4F }, /* GREEK CAPITAL LETTER OMICRON # Omicron */
1980 { 0x03A0, 0x50 }, /* GREEK CAPITAL LETTER PI # Pi */
1981 { 0x03A1, 0x52 }, /* GREEK CAPITAL LETTER RHO # Rho */
1982 { 0x03A3, 0x53 }, /* GREEK CAPITAL LETTER SIGMA # Sigma */
1983 { 0x03A4, 0x54 }, /* GREEK CAPITAL LETTER TAU # Tau */
1984 { 0x03A5, 0x55 }, /* GREEK CAPITAL LETTER UPSILON # Upsilon */
1985 { 0x03A6, 0x46 }, /* GREEK CAPITAL LETTER PHI # Phi */
1986 { 0x03A7, 0x43 }, /* GREEK CAPITAL LETTER CHI # Chi */
1987 { 0x03A8, 0x59 }, /* GREEK CAPITAL LETTER PSI # Psi */
1988 { 0x03A9, 0x57 }, /* GREEK CAPITAL LETTER OMEGA # Omega */
1989 { 0x03B1, 0x61 }, /* GREEK SMALL LETTER ALPHA # alpha */
1990 { 0x03B2, 0x62 }, /* GREEK SMALL LETTER BETA # beta */
1991 { 0x03B3, 0x67 }, /* GREEK SMALL LETTER GAMMA # gamma */
1992 { 0x03B4, 0x64 }, /* GREEK SMALL LETTER DELTA # delta */
1993 { 0x03B5, 0x65 }, /* GREEK SMALL LETTER EPSILON # epsilon */
1994 { 0x03B6, 0x7A }, /* GREEK SMALL LETTER ZETA # zeta */
1995 { 0x03B7, 0x68 }, /* GREEK SMALL LETTER ETA # eta */
1996 { 0x03B8, 0x71 }, /* GREEK SMALL LETTER THETA # theta */
1997 { 0x03B9, 0x69 }, /* GREEK SMALL LETTER IOTA # iota */
1998 { 0x03BA, 0x6B }, /* GREEK SMALL LETTER KAPPA # kappa */
1999 { 0x03BB, 0x6C }, /* GREEK SMALL LETTER LAMDA # lambda */
2000 { 0x03BC, 0x6D }, /* GREEK SMALL LETTER MU # mu */
2001 { 0x03BD, 0x6E }, /* GREEK SMALL LETTER NU # nu */
2002 { 0x03BE, 0x78 }, /* GREEK SMALL LETTER XI # xi */
2003 { 0x03BF, 0x6F }, /* GREEK SMALL LETTER OMICRON # omicron */
2004 { 0x03C0, 0x70 }, /* GREEK SMALL LETTER PI # pi */
2005 { 0x03C1, 0x72 }, /* GREEK SMALL LETTER RHO # rho */
2006 { 0x03C2, 0x56 }, /* GREEK SMALL LETTER FINAL SIGMA # sigma1 */
2007 { 0x03C3, 0x73 }, /* GREEK SMALL LETTER SIGMA # sigma */
2008 { 0x03C4, 0x74 }, /* GREEK SMALL LETTER TAU # tau */
2009 { 0x03C5, 0x75 }, /* GREEK SMALL LETTER UPSILON # upsilon */
2010 { 0x03C6, 0x66 }, /* GREEK SMALL LETTER PHI # phi */
2011 { 0x03C7, 0x63 }, /* GREEK SMALL LETTER CHI # chi */
2012 { 0x03C8, 0x79 }, /* GREEK SMALL LETTER PSI # psi */
2013 { 0x03C9, 0x77 }, /* GREEK SMALL LETTER OMEGA # omega */
2014 { 0x03D1, 0x4A }, /* GREEK THETA SYMBOL # theta1 */
2015 { 0x03D2, 0xA1 }, /* GREEK UPSILON WITH HOOK SYMBOL # Upsilon1 */
2016 { 0x03D5, 0x6A }, /* GREEK PHI SYMBOL # phi1 */
2017 { 0x03D6, 0x76 }, /* GREEK PI SYMBOL # omega1 */
2018 { 0x2022, 0xB7 }, /* BULLET # bullet */
2019 { 0x2026, 0xBC }, /* HORIZONTAL ELLIPSIS # ellipsis */
2020 { 0x2032, 0xA2 }, /* PRIME # minute */
2021 { 0x2033, 0xB2 }, /* DOUBLE PRIME # second */
2022 { 0x2044, 0xA4 }, /* FRACTION SLASH # fraction */
2023 { 0x20AC, 0xA0 }, /* EURO SIGN # Euro */
2024 { 0x2111, 0xC1 }, /* BLACK-LETTER CAPITAL I # Ifraktur */
2025 { 0x2118, 0xC3 }, /* SCRIPT CAPITAL P # weierstrass */
2026 { 0x211C, 0xC2 }, /* BLACK-LETTER CAPITAL R # Rfraktur */
2027 { 0x2126, 0x57 }, /* OHM SIGN # Omega */
2028 { 0x2135, 0xC0 }, /* ALEF SYMBOL # aleph */
2029 { 0x2190, 0xAC }, /* LEFTWARDS ARROW # arrowleft */
2030 { 0x2191, 0xAD }, /* UPWARDS ARROW # arrowup */
2031 { 0x2192, 0xAE }, /* RIGHTWARDS ARROW # arrowright */
2032 { 0x2193, 0xAF }, /* DOWNWARDS ARROW # arrowdown */
2033 { 0x2194, 0xAB }, /* LEFT RIGHT ARROW # arrowboth */
2034 { 0x21B5, 0xBF }, /* DOWNWARDS ARROW WITH CORNER LEFTWARDS # carriagereturn */
2035 { 0x21D0, 0xDC }, /* LEFTWARDS DOUBLE ARROW # arrowdblleft */
2036 { 0x21D1, 0xDD }, /* UPWARDS DOUBLE ARROW # arrowdblup */
2037 { 0x21D2, 0xDE }, /* RIGHTWARDS DOUBLE ARROW # arrowdblright */
2038 { 0x21D3, 0xDF }, /* DOWNWARDS DOUBLE ARROW # arrowdbldown */
2039 { 0x21D4, 0xDB }, /* LEFT RIGHT DOUBLE ARROW # arrowdblboth */
2040 { 0x2200, 0x22 }, /* FOR ALL # universal */
2041 { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL # partialdiff */
2042 { 0x2203, 0x24 }, /* THERE EXISTS # existential */
2043 { 0x2205, 0xC6 }, /* EMPTY SET # emptyset */
2044 { 0x2206, 0x44 }, /* INCREMENT # Delta */
2045 { 0x2207, 0xD1 }, /* NABLA # gradient */
2046 { 0x2208, 0xCE }, /* ELEMENT OF # element */
2047 { 0x2209, 0xCF }, /* NOT AN ELEMENT OF # notelement */
2048 { 0x220B, 0x27 }, /* CONTAINS AS MEMBER # suchthat */
2049 { 0x220F, 0xD5 }, /* N-ARY PRODUCT # product */
2050 { 0x2211, 0xE5 }, /* N-ARY SUMMATION # summation */
2051 { 0x2212, 0x2D }, /* MINUS SIGN # minus */
2052 { 0x2215, 0xA4 }, /* DIVISION SLASH # fraction */
2053 { 0x2217, 0x2A }, /* ASTERISK OPERATOR # asteriskmath */
2054 { 0x221A, 0xD6 }, /* SQUARE ROOT # radical */
2055 { 0x221D, 0xB5 }, /* PROPORTIONAL TO # proportional */
2056 { 0x221E, 0xA5 }, /* INFINITY # infinity */
2057 { 0x2220, 0xD0 }, /* ANGLE # angle */
2058 { 0x2227, 0xD9 }, /* LOGICAL AND # logicaland */
2059 { 0x2228, 0xDA }, /* LOGICAL OR # logicalor */
2060 { 0x2229, 0xC7 }, /* INTERSECTION # intersection */
2061 { 0x222A, 0xC8 }, /* UNION # union */
2062 { 0x222B, 0xF2 }, /* INTEGRAL # integral */
2063 { 0x2234, 0x5C }, /* THEREFORE # therefore */
2064 { 0x223C, 0x7E }, /* TILDE OPERATOR # similar */
2065 { 0x2245, 0x40 }, /* APPROXIMATELY EQUAL TO # congruent */
2066 { 0x2248, 0xBB }, /* ALMOST EQUAL TO # approxequal */
2067 { 0x2260, 0xB9 }, /* NOT EQUAL TO # notequal */
2068 { 0x2261, 0xBA }, /* IDENTICAL TO # equivalence */
2069 { 0x2264, 0xA3 }, /* LESS-THAN OR EQUAL TO # lessequal */
2070 { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO # greaterequal */
2071 { 0x2282, 0xCC }, /* SUBSET OF # propersubset */
2072 { 0x2283, 0xC9 }, /* SUPERSET OF # propersuperset */
2073 { 0x2284, 0xCB }, /* NOT A SUBSET OF # notsubset */
2074 { 0x2286, 0xCD }, /* SUBSET OF OR EQUAL TO # reflexsubset */
2075 { 0x2287, 0xCA }, /* SUPERSET OF OR EQUAL TO # reflexsuperset */
2076 { 0x2295, 0xC5 }, /* CIRCLED PLUS # circleplus */
2077 { 0x2297, 0xC4 }, /* CIRCLED TIMES # circlemultiply */
2078 { 0x22A5, 0x5E }, /* UP TACK # perpendicular */
2079 { 0x22C5, 0xD7 }, /* DOT OPERATOR # dotmath */
2080 { 0x2320, 0xF3 }, /* TOP HALF INTEGRAL # integraltp */
2081 { 0x2321, 0xF5 }, /* BOTTOM HALF INTEGRAL # integralbt */
2082 { 0x2329, 0xE1 }, /* LEFT-POINTING ANGLE BRACKET # angleleft */
2083 { 0x232A, 0xF1 }, /* RIGHT-POINTING ANGLE BRACKET # angleright */
2084 { 0x25CA, 0xE0 }, /* LOZENGE # lozenge */
2085 { 0x2660, 0xAA }, /* BLACK SPADE SUIT # spade */
2086 { 0x2663, 0xA7 }, /* BLACK CLUB SUIT # club */
2087 { 0x2665, 0xA9 }, /* BLACK HEART SUIT # heart */
2088 { 0x2666, 0xA8 }, /* BLACK DIAMOND SUIT # diamond */
2089 { 0xF6D9, 0xD3 }, /* COPYRIGHT SIGN SERIF # copyrightserif (CUS) */
2090 { 0xF6DA, 0xD2 }, /* REGISTERED SIGN SERIF # registerserif (CUS) */
2091 { 0xF6DB, 0xD4 }, /* TRADE MARK SIGN SERIF # trademarkserif (CUS) */
2092 { 0xF8E5, 0x60 }, /* RADICAL EXTENDER # radicalex (CUS) */
2093 { 0xF8E6, 0xBD }, /* VERTICAL ARROW EXTENDER # arrowvertex (CUS) */
2094 { 0xF8E7, 0xBE }, /* HORIZONTAL ARROW EXTENDER # arrowhorizex (CUS) */
2095 { 0xF8E8, 0xE2 }, /* REGISTERED SIGN SANS SERIF # registersans (CUS) */
2096 { 0xF8E9, 0xE3 }, /* COPYRIGHT SIGN SANS SERIF # copyrightsans (CUS) */
2097 { 0xF8EA, 0xE4 }, /* TRADE MARK SIGN SANS SERIF # trademarksans (CUS) */
2098 { 0xF8EB, 0xE6 }, /* LEFT PAREN TOP # parenlefttp (CUS) */
2099 { 0xF8EC, 0xE7 }, /* LEFT PAREN EXTENDER # parenleftex (CUS) */
2100 { 0xF8ED, 0xE8 }, /* LEFT PAREN BOTTOM # parenleftbt (CUS) */
2101 { 0xF8EE, 0xE9 }, /* LEFT SQUARE BRACKET TOP # bracketlefttp (CUS) */
2102 { 0xF8EF, 0xEA }, /* LEFT SQUARE BRACKET EXTENDER # bracketleftex (CUS) */
2103 { 0xF8F0, 0xEB }, /* LEFT SQUARE BRACKET BOTTOM # bracketleftbt (CUS) */
2104 { 0xF8F1, 0xEC }, /* LEFT CURLY BRACKET TOP # bracelefttp (CUS) */
2105 { 0xF8F2, 0xED }, /* LEFT CURLY BRACKET MID # braceleftmid (CUS) */
2106 { 0xF8F3, 0xEE }, /* LEFT CURLY BRACKET BOTTOM # braceleftbt (CUS) */
2107 { 0xF8F4, 0xEF }, /* CURLY BRACKET EXTENDER # braceex (CUS) */
2108 { 0xF8F5, 0xF4 }, /* INTEGRAL EXTENDER # integralex (CUS) */
2109 { 0xF8F6, 0xF6 }, /* RIGHT PAREN TOP # parenrighttp (CUS) */
2110 { 0xF8F7, 0xF7 }, /* RIGHT PAREN EXTENDER # parenrightex (CUS) */
2111 { 0xF8F8, 0xF8 }, /* RIGHT PAREN BOTTOM # parenrightbt (CUS) */
2112 { 0xF8F9, 0xF9 }, /* RIGHT SQUARE BRACKET TOP # bracketrighttp (CUS) */
2113 { 0xF8FA, 0xFA }, /* RIGHT SQUARE BRACKET EXTENDER # bracketrightex (CUS) */
2114 { 0xF8FB, 0xFB }, /* RIGHT SQUARE BRACKET BOTTOM # bracketrightbt (CUS) */
2115 { 0xF8FC, 0xFC }, /* RIGHT CURLY BRACKET TOP # bracerighttp (CUS) */
2116 { 0xF8FD, 0xFD }, /* RIGHT CURLY BRACKET MID # bracerightmid (CUS) */
2117 { 0xF8FE, 0xFE }, /* RIGHT CURLY BRACKET BOTTOM # bracerightbt (CUS) */
2120 static const FcCharMap AdobeSymbol
= {
2122 sizeof (AdobeSymbolEnt
) / sizeof (AdobeSymbolEnt
[0]),
2125 static const FcFontDecode fcFontDecoders
[] = {
2126 { ft_encoding_unicode
, 0, (1 << 21) - 1 },
2127 { ft_encoding_symbol
, &AdobeSymbol
, (1 << 16) - 1 },
2128 { ft_encoding_apple_roman
, &AppleRoman
, (1 << 16) - 1 },
2131 #define NUM_DECODE (int) (sizeof (fcFontDecoders) / sizeof (fcFontDecoders[0]))
2133 static const FcChar32 prefer_unicode
[] = {
2134 0x20ac, /* EURO SIGN */
2137 #define NUM_PREFER_UNICODE (int) (sizeof (prefer_unicode) / sizeof (prefer_unicode[0]))
2140 FcFreeTypeUcs4ToPrivate (FcChar32 ucs4
, const FcCharMap
*map
)
2146 high
= map
->nent
- 1;
2147 if (ucs4
< map
->ent
[low
].bmp
|| map
->ent
[high
].bmp
< ucs4
)
2151 mid
= (high
+ low
) >> 1;
2152 bmp
= map
->ent
[mid
].bmp
;
2154 return (FT_ULong
) map
->ent
[mid
].encode
;
2164 FcFreeTypePrivateToUcs4 (FcChar32
private, const FcCharMap
*map
)
2168 for (i
= 0; i
< map
->nent
; i
++)
2169 if (map
->ent
[i
].encode
== private)
2170 return (FcChar32
) map
->ent
[i
].bmp
;
2175 FcFreeTypeGetPrivateMap (FT_Encoding encoding
)
2179 for (i
= 0; i
< NUM_DECODE
; i
++)
2180 if (fcFontDecoders
[i
].encoding
== encoding
)
2181 return fcFontDecoders
[i
].map
;
2185 #include "../fc-glyphname/fcglyphname.h"
2188 FcHashGlyphName (const FcChar8
*name
)
2193 while ((c
= *name
++))
2195 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
2200 #if HAVE_FT_HAS_PS_GLYPH_NAMES
2202 * Use Type1 glyph names for fonts which have reliable names
2203 * and which export an Adobe Custom mapping
2206 FcFreeTypeUseNames (FT_Face face
)
2210 if (!FT_Has_PS_Glyph_Names (face
))
2212 for (map
= 0; map
< face
->num_charmaps
; map
++)
2213 if (face
->charmaps
[map
]->encoding
== ft_encoding_adobe_custom
)
2218 static const FcChar8
*
2219 FcUcs4ToGlyphName (FcChar32 ucs4
)
2221 int i
= (int) (ucs4
% FC_GLYPHNAME_HASH
);
2223 const FcGlyphName
*gn
;
2225 while ((gn
= ucs_to_name
[i
]))
2227 if (gn
->ucs
== ucs4
)
2231 r
= (int) (ucs4
% FC_GLYPHNAME_REHASH
);
2236 if (i
>= FC_GLYPHNAME_HASH
)
2237 i
-= FC_GLYPHNAME_HASH
;
2243 FcGlyphNameToUcs4 (FcChar8
*name
)
2245 FcChar32 h
= FcHashGlyphName (name
);
2246 int i
= (int) (h
% FC_GLYPHNAME_HASH
);
2248 const FcGlyphName
*gn
;
2250 while ((gn
= name_to_ucs
[i
]))
2252 if (!strcmp ((char *) name
, (char *) gn
->name
))
2256 r
= (int) (h
% FC_GLYPHNAME_REHASH
);
2261 if (i
>= FC_GLYPHNAME_HASH
)
2262 i
-= FC_GLYPHNAME_HASH
;
2268 * Search through a font for a glyph by name. This is
2269 * currently a linear search as there doesn't appear to be
2270 * any defined order within the font
2273 FcFreeTypeGlyphNameIndex (FT_Face face
, const FcChar8
*name
)
2276 FcChar8 name_buf
[FC_GLYPHNAME_MAXLEN
+ 2];
2278 for (gindex
= 0; gindex
< (FT_UInt
) face
->num_glyphs
; gindex
++)
2280 if (FT_Get_Glyph_Name (face
, gindex
, name_buf
, FC_GLYPHNAME_MAXLEN
+1) == 0)
2281 if (!strcmp ((char *) name
, (char *) name_buf
))
2289 * Map a UCS4 glyph to a glyph index. Use all available encoding
2290 * tables to try and find one that works. This information is expected
2291 * to be cached by higher levels, so performance isn't critical
2295 FcFreeTypeCharIndex (FT_Face face
, FcChar32 ucs4
)
2297 int initial
, offset
, decode
;
2308 * Find the current encoding
2312 for (; initial
< NUM_DECODE
; initial
++)
2313 if (fcFontDecoders
[initial
].encoding
== face
->charmap
->encoding
)
2315 if (initial
== NUM_DECODE
)
2318 for (p
= 0; p
< NUM_PREFER_UNICODE
; p
++)
2319 if (ucs4
== prefer_unicode
[p
])
2325 * Check each encoding for the glyph, starting with the current one
2327 for (offset
= 0; offset
< NUM_DECODE
; offset
++)
2329 decode
= (initial
+ offset
) % NUM_DECODE
;
2330 if (!face
->charmap
|| face
->charmap
->encoding
!= fcFontDecoders
[decode
].encoding
)
2331 if (FT_Select_Charmap (face
, fcFontDecoders
[decode
].encoding
) != 0)
2333 if (fcFontDecoders
[decode
].map
)
2335 charcode
= FcFreeTypeUcs4ToPrivate (ucs4
, fcFontDecoders
[decode
].map
);
2336 if (charcode
== ~0U)
2341 glyphindex
= FT_Get_Char_Index (face
, (FT_ULong
) charcode
);
2345 #if HAVE_FT_HAS_PS_GLYPH_NAMES
2347 * Check postscript name table if present
2349 if (FcFreeTypeUseNames (face
))
2351 const FcChar8
*name
= FcUcs4ToGlyphName (ucs4
);
2354 glyphindex
= FcFreeTypeGlyphNameIndex (face
, name
);
2364 FcFreeTypeCheckGlyph (FT_Face face
, FcChar32 ucs4
,
2365 FT_UInt glyph
, FcBlanks
*blanks
,
2368 FT_Int load_flags
= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
| FT_LOAD_NO_SCALE
| FT_LOAD_NO_HINTING
;
2372 * When using scalable fonts, only report those glyphs
2373 * which can be scaled; otherwise those fonts will
2374 * only be available at some sizes, and never when
2375 * transformed. Avoid this by simply reporting bitmap-only
2378 if (face
->face_flags
& FT_FACE_FLAG_SCALABLE
)
2379 load_flags
|= FT_LOAD_NO_BITMAP
;
2381 if (FT_Load_Glyph (face
, glyph
, load_flags
))
2388 *advance
= slot
->metrics
.horiAdvance
;
2390 switch (slot
->format
) {
2391 case ft_glyph_format_bitmap
:
2393 * Bitmaps are assumed to be reasonable; if
2394 * this proves to be a rash assumption, this
2395 * code can be easily modified
2398 case ft_glyph_format_outline
:
2400 * Glyphs with contours are always OK
2402 if (slot
->outline
.n_contours
!= 0)
2405 * Glyphs with no contours are only OK if
2406 * they're members of the Blanks set specified
2407 * in the configuration. If blanks isn't set,
2408 * then allow any glyph to be blank
2410 if (!blanks
|| FcBlanksIsMember (blanks
, ucs4
))
2412 /* fall through ... */
2419 #define FC_MIN(a,b) ((a) < (b) ? (a) : (b))
2420 #define FC_MAX(a,b) ((a) > (b) ? (a) : (b))
2421 #define FC_ABS(a) ((a) < 0 ? -(a) : (a))
2422 #define APPROXIMATELY_EQUAL(x,y) (FC_ABS ((x) - (y)) <= FC_MAX (FC_ABS (x), FC_ABS (y)) / 33)
2425 FcFreeTypeCharSetAndSpacing (FT_Face face
, FcBlanks
*blanks
, int *spacing
)
2427 FcChar32 page
, off
, ucs4
;
2429 FcChar32 font_max
= 0;
2433 const FcCharMap
*map
;
2437 FT_Pos advance
, advance_one
= 0, advance_two
= 0;
2438 FcBool has_advance
= FcFalse
, fixed_advance
= FcTrue
, dual_advance
= FcFalse
;
2440 fcs
= FcCharSetCreate ();
2445 printf ("Family %s style %s\n", face
->family_name
, face
->style_name
);
2447 for (o
= 0; o
< NUM_DECODE
; o
++)
2449 if (FT_Select_Charmap (face
, fcFontDecoders
[o
].encoding
) != 0)
2451 map
= fcFontDecoders
[o
].map
;
2455 * Non-Unicode tables are easy; there's a list of all possible
2458 for (i
= 0; i
< map
->nent
; i
++)
2460 ucs4
= map
->ent
[i
].bmp
;
2461 glyph
= FT_Get_Char_Index (face
, map
->ent
[i
].encode
);
2463 FcFreeTypeCheckGlyph (face
, ucs4
, glyph
, blanks
, &advance
))
2466 * ignore glyphs with zero advance. They’re
2467 * combining characters, and while their behaviour
2468 * isn’t well defined for monospaced applications in
2469 * Unicode, there are many fonts which include
2470 * zero-width combining characters in otherwise
2477 has_advance
= FcTrue
;
2478 advance_one
= advance
;
2480 else if (!APPROXIMATELY_EQUAL (advance
, advance_one
))
2484 dual_advance
= FcTrue
;
2485 fixed_advance
= FcFalse
;
2486 advance_two
= advance
;
2488 else if (!APPROXIMATELY_EQUAL (advance
, advance_two
))
2489 dual_advance
= FcFalse
;
2493 leaf
= FcCharSetFindLeafCreate (fcs
, ucs4
);
2496 leaf
->map
[(ucs4
& 0xff) >> 5] |= (1 << (ucs4
& 0x1f));
2498 if (ucs4
> font_max
)
2509 * Find the first encoded character in the font
2511 if (FT_Get_Char_Index (face
, 0))
2518 ucs4
= FT_Get_Next_Char (face
, 0, &gindex
);
2527 while ((ucs4
>> 8) == page
)
2529 glyph
= FT_Get_Char_Index (face
, ucs4
);
2530 if (glyph
&& FcFreeTypeCheckGlyph (face
, ucs4
,
2531 glyph
, blanks
, &advance
))
2537 has_advance
= FcTrue
;
2538 advance_one
= advance
;
2540 else if (!APPROXIMATELY_EQUAL (advance
, advance_one
))
2544 dual_advance
= FcTrue
;
2545 fixed_advance
= FcFalse
;
2546 advance_two
= advance
;
2548 else if (!APPROXIMATELY_EQUAL (advance
, advance_two
))
2549 dual_advance
= FcFalse
;
2555 leaf
= FcCharSetFindLeafCreate (fcs
, ucs4
);
2560 leaf
->map
[off
>> 5] |= (1 << (off
& 0x1f));
2562 if (ucs4
> font_max
)
2568 ucs4
= FT_Get_Next_Char (face
, ucs4
- 1, &gindex
);
2573 for (ucs4
= 0; ucs4
< 0x10000; ucs4
++)
2575 FcBool FT_Has
, FC_Has
;
2577 FT_Has
= FT_Get_Char_Index (face
, ucs4
) != 0;
2578 FC_Has
= FcCharSetHasChar (fcs
, ucs4
);
2579 if (FT_Has
!= FC_Has
)
2581 printf ("0x%08x FT says %d FC says %d\n", ucs4
, FT_Has
, FC_Has
);
2587 #if HAVE_FT_HAS_PS_GLYPH_NAMES
2589 * Add mapping from PS glyph names if available
2591 if (FcFreeTypeUseNames (face
))
2593 FcChar8 name_buf
[FC_GLYPHNAME_MAXLEN
+ 2];
2595 for (glyph
= 0; glyph
< (FT_UInt
) face
->num_glyphs
; glyph
++)
2597 if (FT_Get_Glyph_Name (face
, glyph
, name_buf
, FC_GLYPHNAME_MAXLEN
+1) == 0)
2599 ucs4
= FcGlyphNameToUcs4 (name_buf
);
2600 if (ucs4
!= 0xffff &&
2601 FcFreeTypeCheckGlyph (face
, ucs4
, glyph
, blanks
, &advance
))
2607 has_advance
= FcTrue
;
2608 advance_one
= advance
;
2610 else if (!APPROXIMATELY_EQUAL (advance
, advance_one
))
2614 dual_advance
= FcTrue
;
2615 fixed_advance
= FcFalse
;
2616 advance_two
= advance
;
2618 else if (!APPROXIMATELY_EQUAL (advance
, advance_two
))
2619 dual_advance
= FcFalse
;
2622 leaf
= FcCharSetFindLeafCreate (fcs
, ucs4
);
2625 leaf
->map
[(ucs4
& 0xff) >> 5] |= (1 << (ucs4
& 0x1f));
2627 if (ucs4
> font_max
)
2636 printf ("%d glyphs %d encoded\n", (int) face
->num_glyphs
, FcCharSetCount (fcs
));
2637 for (ucs4
= 0; ucs4
<= font_max
; ucs4
++)
2639 FcBool has_char
= (glyph
= FcFreeTypeCharIndex (face
, ucs4
)) != 0;
2640 FcBool has_bit
= FcCharSetHasChar (fcs
, ucs4
);
2642 if (has_char
&& !has_bit
)
2644 if (!FcFreeTypeCheckGlyph (face
, ucs4
, glyph
, blanks
, &advance
))
2645 printf ("Bitmap missing broken char 0x%x\n", ucs4
);
2647 printf ("Bitmap missing char 0x%x\n", ucs4
);
2649 else if (!has_char
&& has_bit
)
2650 printf ("Bitmap extra char 0x%x\n", ucs4
);
2655 else if (dual_advance
&& APPROXIMATELY_EQUAL (2 * FC_MIN (advance_one
, advance_two
), FC_MAX (advance_one
, advance_two
)))
2658 *spacing
= FC_PROPORTIONAL
;
2661 FcCharSetDestroy (fcs
);
2667 FcFreeTypeCharSet (FT_Face face
, FcBlanks
*blanks
)
2671 return FcFreeTypeCharSetAndSpacing (face
, blanks
, &spacing
);
2675 #define TTAG_GPOS FT_MAKE_TAG( 'G', 'P', 'O', 'S' )
2676 #define TTAG_GSUB FT_MAKE_TAG( 'G', 'S', 'U', 'B' )
2677 #define TTAG_SILF FT_MAKE_TAG( 'S', 'i', 'l', 'f')
2678 #define TT_Err_Ok FT_Err_Ok
2679 #define TT_Err_Invalid_Face_Handle FT_Err_Invalid_Face_Handle
2680 #define TTO_Err_Empty_Script 0x1005
2681 #define TTO_Err_Invalid_SubTable 0x1001
2683 #define OTLAYOUT_HEAD "otlayout:"
2684 #define OTLAYOUT_HEAD_LEN 9
2685 #define OTLAYOUT_ID_LEN 4
2686 /* space + head + id */
2687 #define OTLAYOUT_LEN (1 + OTLAYOUT_HEAD_LEN + OTLAYOUT_ID_LEN)
2690 * This is a bit generous; the registry has only lower case and space
2691 * except for 'DFLT'.
2693 #define FcIsSpace(x) (040 == (x))
2694 #define FcIsValidScript(x) (FcIsLower(x) || FcIsUpper (x) || FcIsSpace(x))
2697 addtag(FcChar8
*complex, FT_ULong tag
)
2699 FcChar8 tagstring
[OTLAYOUT_ID_LEN
+ 1];
2701 tagstring
[0] = (FcChar8
)(tag
>> 24),
2702 tagstring
[1] = (FcChar8
)(tag
>> 16),
2703 tagstring
[2] = (FcChar8
)(tag
>> 8),
2704 tagstring
[3] = (FcChar8
)(tag
);
2705 tagstring
[4] = '\0';
2707 /* skip tags which aren't alphabetic, under the assumption that
2708 * they're probably broken
2710 if (!FcIsValidScript(tagstring
[0]) ||
2711 !FcIsValidScript(tagstring
[1]) ||
2712 !FcIsValidScript(tagstring
[2]) ||
2713 !FcIsValidScript(tagstring
[3]))
2716 if (*complex != '\0')
2717 strcat ((char *) complex, " ");
2718 strcat ((char *) complex, "otlayout:");
2719 strcat ((char *) complex, (char *) tagstring
);
2723 compareulong (const void *a
, const void *b
)
2725 const FT_ULong
*ua
= (const FT_ULong
*) a
;
2726 const FT_ULong
*ub
= (const FT_ULong
*) b
;
2732 GetScriptTags(FT_Face face
, FT_ULong tabletag
, FT_ULong
**stags
, FT_UShort
*script_count
)
2734 FT_ULong cur_offset
, new_offset
, base_offset
;
2735 FT_Stream stream
= face
->stream
;
2741 return TT_Err_Invalid_Face_Handle
;
2743 memory
= stream
->memory
;
2745 if (( error
= ftglue_face_goto_table( face
, tabletag
, stream
) ))
2748 base_offset
= ftglue_stream_pos ( stream
);
2752 if ( ftglue_stream_seek ( stream
, base_offset
+ 4L ) || ftglue_stream_frame_enter( stream
, 2L ) )
2755 new_offset
= GET_UShort() + base_offset
;
2757 ftglue_stream_frame_exit( stream
);
2759 cur_offset
= ftglue_stream_pos( stream
);
2761 if ( ftglue_stream_seek( stream
, new_offset
) != TT_Err_Ok
)
2764 base_offset
= ftglue_stream_pos( stream
);
2766 if ( ftglue_stream_frame_enter( stream
, 2L ) )
2769 *script_count
= GET_UShort ();
2771 ftglue_stream_frame_exit( stream
);
2773 *stags
= ftglue_alloc(memory
, *script_count
* sizeof( FT_ULong
), &error
);
2779 for ( n
= 0; n
< *script_count
; n
++ )
2781 if ( ftglue_stream_frame_enter( stream
, 6L ) )
2784 (*stags
)[p
] = GET_ULong ();
2785 new_offset
= GET_UShort () + base_offset
;
2787 ftglue_stream_frame_exit( stream
);
2789 cur_offset
= ftglue_stream_pos( stream
);
2791 error
= ftglue_stream_seek( stream
, new_offset
);
2793 if ( error
== TT_Err_Ok
)
2796 (void)ftglue_stream_seek( stream
, cur_offset
);
2801 error
= TTO_Err_Invalid_SubTable
;
2805 /* sort the tag list before returning it */
2806 qsort(*stags
, *script_count
, sizeof(FT_ULong
), compareulong
);
2812 ftglue_free( memory
, *stags
);
2818 FcFontCapabilities(FT_Face face
)
2820 FcBool issilgraphitefont
= 0;
2823 FT_ULong
*gsubtags
=NULL
, *gpostags
=NULL
;
2824 FT_UShort gsub_count
=0, gpos_count
=0;
2826 FT_Memory memory
= face
->stream
->memory
;
2827 FcChar8
*complex = NULL
;
2828 int indx1
= 0, indx2
= 0;
2830 err
= FT_Load_Sfnt_Table(face
, TTAG_SILF
, 0, 0, &len
);
2831 issilgraphitefont
= ( err
== FT_Err_Ok
);
2833 if (GetScriptTags(face
, TTAG_GPOS
, &gpostags
, &gpos_count
) != FT_Err_Ok
)
2835 if (GetScriptTags(face
, TTAG_GSUB
, &gsubtags
, &gsub_count
) != FT_Err_Ok
)
2838 if (!issilgraphitefont
&& !gsub_count
&& !gpos_count
)
2841 maxsize
= (((FT_ULong
) gpos_count
+ (FT_ULong
) gsub_count
) * OTLAYOUT_LEN
+
2842 (issilgraphitefont
? 13 : 0));
2843 complex = malloc (sizeof (FcChar8
) * maxsize
);
2848 if (issilgraphitefont
)
2849 strcpy((char *) complex, "ttable:Silf ");
2851 while ((indx1
< gsub_count
) || (indx2
< gpos_count
)) {
2852 if (indx1
== gsub_count
) {
2853 addtag(complex, gpostags
[indx2
]);
2855 } else if ((indx2
== gpos_count
) || (gsubtags
[indx1
] < gpostags
[indx2
])) {
2856 addtag(complex, gsubtags
[indx1
]);
2858 } else if (gsubtags
[indx1
] == gpostags
[indx2
]) {
2859 addtag(complex, gsubtags
[indx1
]);
2863 addtag(complex, gpostags
[indx2
]);
2867 if (FcDebug () & FC_DBG_SCANV
)
2868 printf("complex features in this font: %s\n", complex);
2870 ftglue_free(memory
, gsubtags
);
2871 ftglue_free(memory
, gpostags
);