forgotten commit. disabled until egl is adapted.
[AROS-Contrib.git] / vpdf / fontcache.c
blob9584e4da9ef330886740d93fa68a3b0c8c47a3d2
2 #define SYSTEM_PRIVATE
3 #define AROS_ALMOST_COMPATIBLE
4 #include <exec/lists.h>
5 #include <proto/alib.h>
6 #include <private/vapor/vapor.h>
8 #include <stdlib.h>
9 #include <assert.h>
10 #include <stdio.h>
12 #include <proto/dos.h>
13 #include <ft2build.h>
14 #include FT_FREETYPE_H
15 #include FT_TRUETYPE_TABLES_H
16 #include FT_SFNT_NAMES_H
17 #include "system/directory.h"
18 #include "system/functions.h"
19 #include "freetype/ttnameid.h"
21 #include "fcstr.c"
23 #include "fontcache.h"
25 #define FC_DBG_SCANV 1
27 static FT_Library ftLibrary;
29 void kprintf(char *fmt,...);
32 #define D(x) x
33 //#define FcDebug() 0xffffffffUL
34 #define FcDebug() 0
35 #define FcResultMatch TRUE
38 struct fontlangset
42 struct fontcharset
46 /* return an id for next insertion. if not found returns 0 */
48 static int fcPatternCheckEntry(struct fontpattern *pat, int element)
50 struct patternentry *pe;
52 ITERATELIST(pe, &pat->entries)
54 if (pe->element == element)
55 return pe->id + 1; /* elements with high ids are at the begining of the list */
58 return 0;
62 static int fcPatternAddEntry(struct fontpattern *pat, int element, int type, union patternvalue *value, int excluding)
64 struct patternentry *pe = calloc(1, sizeof(*pe));
65 if (pe == NULL)
66 return FALSE;
68 pe->element = element;
69 pe->type = type;
70 pe->id = fcPatternCheckEntry(pat, element);
71 pe->excluding = excluding;
73 if (type == FC_ETYPE_STRING)
75 if (FcDebug () & FC_DBG_SCANV)
76 kprintf("adding string entry to pattern. elt:%d. value:%s, id:%d, excluding:%d\n", element, value->s, pe->id, excluding);
77 pe->value.s = value->s != NULL ? strdup(value->s) : NULL;
79 else
81 if (FcDebug () & FC_DBG_SCANV)
82 kprintf("adding int entry to pattern. elt:%d. value:%d, id:%d, excluding:%d\n", element, value->i, pe->id, excluding);
83 pe->value.p = value->p;
86 ADDHEAD(&pat->entries, pe); /* add to head so elements with high ids are first. this is 'normal' mode */
88 return TRUE;
91 static int fcPatternAddEntryRaw(struct fontpattern *pat, int element, int type, union patternvalue *value, int id)
93 struct patternentry *pe = calloc(1, sizeof(*pe));
94 if (pe == NULL)
95 return FALSE;
97 pe->element = element;
98 pe->type = type;
99 pe->id = id;
100 pe->value.p = value->p; /* no duplication. string is preallocated */
102 ADDTAIL(&pat->entries, pe); /* when loading from cache we put entries in the order they were written in */
104 return TRUE;
109 int fcPatternAddString(struct fontpattern *pat, int element, char *value)
111 union patternvalue v;
112 v.s = value;
113 return fcPatternAddEntry(pat, element, FC_ETYPE_STRING, &v, FALSE); /* value is copied */
116 int fcPatternAddInteger(struct fontpattern *pat, int element, int value)
118 union patternvalue v;
119 v.i = value;
120 return fcPatternAddEntry(pat, element, FC_ETYPE_INTEGER, &v, FALSE);
123 int fcPatternAddExcludingInteger(struct fontpattern *pat, int element, int value)
125 union patternvalue v;
126 v.i = value;
127 return fcPatternAddEntry(pat, element, FC_ETYPE_INTEGER, &v, TRUE);
131 /* if elt is found but is not string then return NULL! */
133 char *fcPatternGetString(struct fontpattern *pat, int element, int id)
135 struct patternentry *pe;
137 ITERATELIST(pe, &pat->entries)
139 if (pe->element == element && pe->id == id)
141 if (pe->type != FC_ETYPE_STRING)
142 kprintf("***ERROR*** Getting element %d as string!\n", element);
144 return pe->value.s;
148 return NULL;
151 int fcPatternGetInteger(struct fontpattern *pat, int element, int id)
153 struct patternentry *pe;
155 ITERATELIST(pe, &pat->entries)
157 if (pe->element == element && pe->id == id)
159 if (pe->type != FC_ETYPE_INTEGER)
160 kprintf("***ERROR*** Getting element %d as integer!\n", element);
162 return pe->value.i;
166 return 0;
169 struct patternentry *fcPatternGetEntry(struct fontpattern *pat, int element, int id)
171 struct patternentry *pe;
173 ITERATELIST(pe, &pat->entries)
175 if (pe->element == element && pe->id == id)
177 return pe;
181 return NULL;
185 /* */
187 typedef struct {
188 const unsigned short platform_id;
189 const unsigned short encoding_id;
190 const char fromcode[12];
191 } FcFtEncoding;
193 typedef struct _FcCharEnt {
194 unsigned short bmp;
195 unsigned char encode;
196 } FcCharEnt;
198 typedef struct _FcCharMap {
199 const FcCharEnt *ent;
200 int nent;
201 } FcCharMap;
203 typedef struct _FcFontDecode {
204 FT_Encoding encoding;
205 const FcCharMap *map;
206 FcChar32 max;
207 } FcFontDecode;
209 /* Keep Han languages separated by eliminating languages that the codePageRange bits says aren't supported */
211 static const struct {
212 char bit;
213 const FcChar8 lang[6];
214 } FcCodePageRange[] = {
215 { 17, "ja" },
216 { 18, "zh-cn" },
217 { 19, "ko" },
218 { 20, "zh-tw" },
221 #define NUM_CODE_PAGE_RANGE (int) (sizeof FcCodePageRange / sizeof FcCodePageRange[0])
223 #if 0
224 FcBool FcFreeTypeIsExclusiveLang (const FcChar8 *lang)
226 int i;
228 for (i = 0; i < NUM_CODE_PAGE_RANGE; i++)
230 if (FcLangCompare (lang, FcCodePageRange[i].lang) == FcLangEqual)
231 return FcTrue;
233 return FcFalse;
235 #endif
237 #define TT_ENCODING_DONT_CARE 0xffff
238 #define FC_ENCODING_MAC_ROMAN "MACINTOSH"
240 static const FcFtEncoding fcFtEncoding[] = {
241 { TT_PLATFORM_APPLE_UNICODE, TT_ENCODING_DONT_CARE, "UCS-2BE" },
242 { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, "MACINTOSH" },
243 { TT_PLATFORM_MACINTOSH, TT_MAC_ID_JAPANESE, "SJIS" },
244 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, "UTF-16BE" },
245 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, "SJIS-WIN" },
246 { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, "GB2312" },
247 { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, "BIG-5" },
248 { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, "Wansung" },
249 { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, "Johab" },
250 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, "UCS-2BE" },
251 { TT_PLATFORM_ISO, TT_ISO_ID_7BIT_ASCII, "ASCII" },
252 { TT_PLATFORM_ISO, TT_ISO_ID_10646, "UCS-2BE" },
253 { TT_PLATFORM_ISO, TT_ISO_ID_8859_1, "ISO-8859-1" },
256 #define NUM_FC_FT_ENCODING (int) (sizeof (fcFtEncoding) / sizeof (fcFtEncoding[0]))
258 typedef struct {
259 const FT_UShort platform_id;
260 const FT_UShort language_id;
261 const char lang[8];
262 } FcFtLanguage;
264 #define TT_LANGUAGE_DONT_CARE 0xffff
266 static const FcFtLanguage fcFtLanguage[] = {
267 { TT_PLATFORM_APPLE_UNICODE, TT_LANGUAGE_DONT_CARE, "" },
268 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ENGLISH, "en" },
269 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FRENCH, "fr" },
270 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GERMAN, "de" },
271 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ITALIAN, "it" },
272 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_DUTCH, "nl" },
273 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SWEDISH, "sv" },
274 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SPANISH, "es" },
275 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_DANISH, "da" },
276 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_PORTUGUESE, "pt" },
277 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_NORWEGIAN, "no" },
278 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_HEBREW, "he" },
279 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_JAPANESE, "ja" },
280 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ARABIC, "ar" },
281 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FINNISH, "fi" },
282 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GREEK, "el" },
283 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ICELANDIC, "is" },
284 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALTESE, "mt" },
285 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TURKISH, "tr" },
286 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CROATIAN, "hr" },
287 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CHINESE_TRADITIONAL, "zh-tw" },
288 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_URDU, "ur" },
289 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_HINDI, "hi" },
290 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_THAI, "th" },
291 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KOREAN, "ko" },
292 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_LITHUANIAN, "lt" },
293 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_POLISH, "pl" },
294 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_HUNGARIAN, "hu" },
295 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ESTONIAN, "et" },
296 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_LETTISH, "lv" },
297 /* { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SAAMISK, ??? */
298 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FAEROESE, "fo" },
299 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FARSI, "fa" },
300 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_RUSSIAN, "ru" },
301 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CHINESE_SIMPLIFIED, "zh-cn" },
302 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_FLEMISH, "nl" },
303 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_IRISH, "ga" },
304 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ALBANIAN, "sq" },
305 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ROMANIAN, "ro" },
306 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CZECH, "cs" },
307 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SLOVAK, "sk" },
308 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SLOVENIAN, "sl" },
309 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_YIDDISH, "yi" },
310 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SERBIAN, "sr" },
311 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MACEDONIAN, "mk" },
312 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BULGARIAN, "bg" },
313 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_UKRAINIAN, "uk" },
314 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BYELORUSSIAN, "be" },
315 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_UZBEK, "uz" },
316 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KAZAKH, "kk" },
317 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AZERBAIJANI, "az" },
318 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT, "az" },
319 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT, "ar" },
320 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ARMENIAN, "hy" },
321 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GEORGIAN, "ka" },
322 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MOLDAVIAN, "mo" },
323 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KIRGHIZ, "ky" },
324 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TAJIKI, "tg" },
325 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TURKMEN, "tk" },
326 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MONGOLIAN, "mo" },
327 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT,"mo" },
328 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT, "mo" },
329 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_PASHTO, "ps" },
330 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KURDISH, "ku" },
331 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KASHMIRI, "ks" },
332 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SINDHI, "sd" },
333 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TIBETAN, "bo" },
334 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_NEPALI, "ne" },
335 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SANSKRIT, "sa" },
336 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MARATHI, "mr" },
337 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BENGALI, "bn" },
338 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ASSAMESE, "as" },
339 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GUJARATI, "gu" },
340 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_PUNJABI, "pa" },
341 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ORIYA, "or" },
342 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALAYALAM, "ml" },
343 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KANNADA, "kn" },
344 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TAMIL, "ta" },
345 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TELUGU, "te" },
346 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SINHALESE, "si" },
347 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BURMESE, "my" },
348 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_KHMER, "km" },
349 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_LAO, "lo" },
350 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_VIETNAMESE, "vi" },
351 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_INDONESIAN, "id" },
352 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TAGALOG, "tl" },
353 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALAY_ROMAN_SCRIPT, "ms" },
354 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALAY_ARABIC_SCRIPT, "ms" },
355 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AMHARIC, "am" },
356 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TIGRINYA, "ti" },
357 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GALLA, "om" },
358 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SOMALI, "so" },
359 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SWAHILI, "sw" },
360 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_RUANDA, "rw" },
361 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_RUNDI, "rn" },
362 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CHEWA, "ny" },
363 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MALAGASY, "mg" },
364 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_ESPERANTO, "eo" },
365 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_WELSH, "cy" },
366 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BASQUE, "eu" },
367 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_CATALAN, "ca" },
368 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_LATIN, "la" },
369 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_QUECHUA, "qu" },
370 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GUARANI, "gn" },
371 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AYMARA, "ay" },
372 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TATAR, "tt" },
373 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_UIGHUR, "ug" },
374 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_DZONGKHA, "dz" },
375 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_JAVANESE, "jw" },
376 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SUNDANESE, "su" },
378 #if 0 /* these seem to be errors that have been dropped */
380 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SCOTTISH_GAELIC },
381 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_IRISH_GAELIC },
383 #endif
385 /* The following codes are new as of 2000-03-10 */
386 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GALICIAN, "gl" },
387 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AFRIKAANS, "af" },
388 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_BRETON, "br" },
389 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_INUKTITUT, "iu" },
390 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_SCOTTISH_GAELIC, "gd" },
391 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_MANX_GAELIC, "gv" },
392 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_IRISH_GAELIC, "ga" },
393 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_TONGAN, "to" },
394 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GREEK_POLYTONIC, "el" },
395 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_GREELANDIC, "ik" },
396 { TT_PLATFORM_MACINTOSH, TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT,"az" },
398 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_SAUDI_ARABIA, "ar" },
399 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_IRAQ, "ar" },
400 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_EGYPT, "ar" },
401 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_LIBYA, "ar" },
402 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_ALGERIA, "ar" },
403 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_MOROCCO, "ar" },
404 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_TUNISIA, "ar" },
405 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_OMAN, "ar" },
406 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_YEMEN, "ar" },
407 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_SYRIA, "ar" },
408 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_JORDAN, "ar" },
409 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_LEBANON, "ar" },
410 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_KUWAIT, "ar" },
411 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_UAE, "ar" },
412 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_BAHRAIN, "ar" },
413 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_QATAR, "ar" },
414 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BULGARIAN_BULGARIA, "bg" },
415 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CATALAN_SPAIN, "ca" },
416 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_TAIWAN, "zh-tw" },
417 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_PRC, "zh-cn" },
418 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_HONG_KONG, "zh-hk" },
419 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_SINGAPORE, "zh-sg" },
421 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_MACAU, "zh-mo" },
423 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CZECH_CZECH_REPUBLIC, "cs" },
424 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DANISH_DENMARK, "da" },
425 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_GERMANY, "de" },
426 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_SWITZERLAND, "de" },
427 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_AUSTRIA, "de" },
428 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_LUXEMBOURG, "de" },
429 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GERMAN_LIECHTENSTEI, "de" },
430 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GREEK_GREECE, "el" },
431 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_UNITED_STATES, "en" },
432 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_UNITED_KINGDOM, "en" },
433 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_AUSTRALIA, "en" },
434 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_CANADA, "en" },
435 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_NEW_ZEALAND, "en" },
436 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_IRELAND, "en" },
437 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_SOUTH_AFRICA, "en" },
438 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_JAMAICA, "en" },
439 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_CARIBBEAN, "en" },
440 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_BELIZE, "en" },
441 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_TRINIDAD, "en" },
442 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_ZIMBABWE, "en" },
443 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_PHILIPPINES, "en" },
444 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT,"es" },
445 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_MEXICO, "es" },
446 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT,"es" },
447 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_GUATEMALA, "es" },
448 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_COSTA_RICA, "es" },
449 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_PANAMA, "es" },
450 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC,"es" },
451 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_VENEZUELA, "es" },
452 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_COLOMBIA, "es" },
453 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_PERU, "es" },
454 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_ARGENTINA, "es" },
455 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_ECUADOR, "es" },
456 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_CHILE, "es" },
457 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_URUGUAY, "es" },
458 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_PARAGUAY, "es" },
459 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_BOLIVIA, "es" },
460 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_EL_SALVADOR, "es" },
461 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_HONDURAS, "es" },
462 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_NICARAGUA, "es" },
463 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_PUERTO_RICO, "es" },
464 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FINNISH_FINLAND, "fi" },
465 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_FRANCE, "fr" },
466 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_BELGIUM, "fr" },
467 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_CANADA, "fr" },
468 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_SWITZERLAND, "fr" },
469 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_LUXEMBOURG, "fr" },
470 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_MONACO, "fr" },
471 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HEBREW_ISRAEL, "he" },
472 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HUNGARIAN_HUNGARY, "hu" },
473 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ICELANDIC_ICELAND, "is" },
474 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ITALIAN_ITALY, "it" },
475 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ITALIAN_SWITZERLAND, "it" },
476 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_JAPANESE_JAPAN, "ja" },
477 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA,"ko" },
478 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KOREAN_JOHAB_KOREA, "ko" },
479 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DUTCH_NETHERLANDS, "nl" },
480 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DUTCH_BELGIUM, "nl" },
481 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL, "no" },
482 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK, "nn" },
483 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_POLISH_POLAND, "pl" },
484 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PORTUGUESE_BRAZIL, "pt" },
485 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PORTUGUESE_PORTUGAL, "pt" },
486 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND,"rm" },
487 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ROMANIAN_ROMANIA, "ro" },
488 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MOLDAVIAN_MOLDAVIA, "mo" },
489 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_RUSSIAN_RUSSIA, "ru" },
490 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_RUSSIAN_MOLDAVIA, "ru" },
491 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CROATIAN_CROATIA, "hr" },
492 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SERBIAN_SERBIA_LATIN, "sr" },
493 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC, "sr" },
494 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SLOVAK_SLOVAKIA, "sk" },
495 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ALBANIAN_ALBANIA, "sq" },
496 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SWEDISH_SWEDEN, "sv" },
497 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SWEDISH_FINLAND, "sv" },
498 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_THAI_THAILAND, "th" },
499 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TURKISH_TURKEY, "tr" },
500 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_URDU_PAKISTAN, "ur" },
501 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_INDONESIAN_INDONESIA, "id" },
502 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_UKRAINIAN_UKRAINE, "uk" },
503 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BELARUSIAN_BELARUS, "be" },
504 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SLOVENE_SLOVENIA, "sl" },
505 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ESTONIAN_ESTONIA, "et" },
506 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_LATVIAN_LATVIA, "lv" },
507 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_LITHUANIAN_LITHUANIA, "lt" },
508 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA,"lt" },
510 #ifdef TT_MS_LANGID_MAORI_NEW_ZELAND
511 /* this seems to be an error that have been dropped */
512 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MAORI_NEW_ZEALAND, "mi" },
513 #endif
515 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FARSI_IRAN, "fa" },
516 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_VIETNAMESE_VIET_NAM, "vi" },
517 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARMENIAN_ARMENIA, "hy" },
518 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN, "az" },
519 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC, "az" },
520 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BASQUE_SPAIN, "eu" },
521 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SORBIAN_GERMANY, "wen" },
522 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MACEDONIAN_MACEDONIA, "mk" },
523 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SUTU_SOUTH_AFRICA, "st" },
524 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TSONGA_SOUTH_AFRICA, "ts" },
525 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TSWANA_SOUTH_AFRICA, "tn" },
526 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_VENDA_SOUTH_AFRICA, "ven" },
527 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_XHOSA_SOUTH_AFRICA, "xh" },
528 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ZULU_SOUTH_AFRICA, "zu" },
529 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA, "af" },
530 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GEORGIAN_GEORGIA, "ka" },
531 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS, "fo" },
532 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HINDI_INDIA, "hi" },
533 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MALTESE_MALTA, "mt" },
534 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SAAMI_LAPONIA, "se" },
536 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM,"gd" },
537 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_IRISH_GAELIC_IRELAND, "ga" },
539 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MALAY_MALAYSIA, "ms" },
540 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM, "ms" },
541 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KAZAK_KAZAKSTAN, "kk" },
542 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SWAHILI_KENYA, "sw" },
543 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN, "uz" },
544 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC, "uz" },
545 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TATAR_TATARSTAN, "tt" },
546 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BENGALI_INDIA, "bn" },
547 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PUNJABI_INDIA, "pa" },
548 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GUJARATI_INDIA, "gu" },
549 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ORIYA_INDIA, "or" },
550 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TAMIL_INDIA, "ta" },
551 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TELUGU_INDIA, "te" },
552 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KANNADA_INDIA, "kn" },
553 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MALAYALAM_INDIA, "ml" },
554 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ASSAMESE_INDIA, "as" },
555 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MARATHI_INDIA, "mr" },
556 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SANSKRIT_INDIA, "sa" },
557 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KONKANI_INDIA, "kok" },
559 /* new as of 2001-01-01 */
560 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ARABIC_GENERAL, "ar" },
561 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHINESE_GENERAL, "zh" },
562 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_GENERAL, "en" },
563 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_WEST_INDIES, "fr" },
564 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_REUNION, "fr" },
565 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_CONGO, "fr" },
567 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_SENEGAL, "fr" },
568 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_CAMEROON, "fr" },
569 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_COTE_D_IVOIRE, "fr" },
570 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_MALI, "fr" },
571 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA,"bs" },
572 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_URDU_INDIA, "ur" },
573 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TAJIK_TAJIKISTAN, "tg" },
574 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_YIDDISH_GERMANY, "yi" },
575 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN, "ky" },
577 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TURKMEN_TURKMENISTAN, "tk" },
578 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MONGOLIAN_MONGOLIA, "mn" },
580 /* the following seems to be inconsistent;
581 here is the current "official" way: */
582 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TIBETAN_BHUTAN, "bo" },
583 /* and here is what is used by Passport SDK */
584 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TIBETAN_CHINA, "bo" },
585 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DZONGHKA_BHUTAN, "dz" },
586 /* end of inconsistency */
588 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_WELSH_WALES, "cy" },
589 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KHMER_CAMBODIA, "km" },
590 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_LAO_LAOS, "lo" },
591 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BURMESE_MYANMAR, "my" },
592 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GALICIAN_SPAIN, "gl" },
593 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MANIPURI_INDIA, "mni" },
594 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SINDHI_INDIA, "sd" },
595 /* the following one is only encountered in Microsoft RTF specification */
596 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KASHMIRI_PAKISTAN, "ks" },
597 /* the following one is not in the Passport list, looks like an omission */
598 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KASHMIRI_INDIA, "ks" },
599 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_NEPALI_NEPAL, "ne" },
600 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_NEPALI_INDIA, "ne" },
601 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRISIAN_NETHERLANDS, "fy" },
603 /* new as of 2001-03-01 (from Office Xp) */
604 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_HONG_KONG, "en" },
605 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_INDIA, "en" },
606 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_MALAYSIA, "en" },
607 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_ENGLISH_SINGAPORE, "en" },
608 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SYRIAC_SYRIA, "syr" },
609 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SINHALESE_SRI_LANKA, "si" },
610 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_CHEROKEE_UNITED_STATES, "chr" },
611 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_INUKTITUT_CANADA, "iu" },
612 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_AMHARIC_ETHIOPIA, "am" },
613 #if 0
614 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TAMAZIGHT_MOROCCO },
615 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN },
616 #endif
617 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PASHTO_AFGHANISTAN, "ps" },
618 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FILIPINO_PHILIPPINES, "phi" },
619 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_DHIVEHI_MALDIVES, "div" },
621 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_OROMO_ETHIOPIA, "om" },
622 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TIGRIGNA_ETHIOPIA, "ti" },
623 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_TIGRIGNA_ERYTHREA, "ti" },
625 /* New additions from Windows Xp/Passport SDK 2001-11-10. */
627 /* don't ask what this one means... It is commented out currently. */
628 #if 0
629 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GREEK_GREECE2 },
630 #endif
632 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_UNITED_STATES, "es" },
633 /* The following two IDs blatantly violate MS specs by using a */
634 /* sublanguage >,. */
635 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SPANISH_LATIN_AMERICA, "es" },
636 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_NORTH_AFRICA, "fr" },
638 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_MOROCCO, "fr" },
639 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FRENCH_HAITI, "fr" },
640 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_BENGALI_BANGLADESH, "bn" },
641 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN, "ar" },
642 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN,"mn" },
643 #if 0
644 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_EDO_NIGERIA },
645 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_FULFULDE_NIGERIA },
646 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_IBIBIO_NIGERIA },
647 #endif
648 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HAUSA_NIGERIA, "ha" },
649 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_YORUBA_NIGERIA, "yo" },
650 /* language codes from, to, are (still) unknown. */
651 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_IGBO_NIGERIA, "ibo" },
652 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_KANURI_NIGERIA, "kau" },
653 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_GUARANI_PARAGUAY, "gn" },
654 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_HAWAIIAN_UNITED_STATES, "haw" },
655 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_LATIN, "la" },
656 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_SOMALI_SOMALIA, "so" },
657 #if 0
658 /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */
659 /* not written (but OTOH the peculiar writing system is worth */
660 /* studying). */
661 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_YI_CHINA },
662 #endif
663 { TT_PLATFORM_MICROSOFT, TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES,"pap" },
666 #define NUM_FC_FT_LANGUAGE (int) (sizeof (fcFtLanguage) / sizeof (fcFtLanguage[0]))
669 static const FT_UShort platform_order[] = {
670 TT_PLATFORM_MICROSOFT,
671 TT_PLATFORM_APPLE_UNICODE,
672 TT_PLATFORM_MACINTOSH,
674 #define NUM_PLATFORM_ORDER (sizeof (platform_order) / sizeof (platform_order[0]))
676 static const FT_UShort nameid_order[] = {
677 #ifdef TT_NAME_ID_WWS_FAMILY
678 TT_NAME_ID_WWS_FAMILY,
679 #endif
680 TT_NAME_ID_PREFERRED_FAMILY,
681 TT_NAME_ID_FONT_FAMILY,
682 TT_NAME_ID_MAC_FULL_NAME,
683 TT_NAME_ID_FULL_NAME,
684 #ifdef TT_NAME_ID_WWS_SUBFAMILY
685 TT_NAME_ID_WWS_SUBFAMILY,
686 #endif
687 TT_NAME_ID_PREFERRED_SUBFAMILY,
688 TT_NAME_ID_FONT_SUBFAMILY,
689 TT_NAME_ID_TRADEMARK,
690 TT_NAME_ID_MANUFACTURER,
693 #define NUM_NAMEID_ORDER (sizeof (nameid_order) / sizeof (nameid_order[0]))
695 typedef struct {
696 unsigned short language_id;
697 char fromcode[12];
698 } FcMacRomanFake;
700 static const FcMacRomanFake fcMacRomanFake[] = {
701 { TT_MS_LANGID_JAPANESE_JAPAN, "SJIS-WIN" },
702 { TT_MS_LANGID_ENGLISH_UNITED_STATES, "ASCII" },
705 #define NUM_FC_MAC_ROMAN_FAKE (int) (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0]))
708 typedef struct _FcStringConst {
709 const FcChar8 *name;
710 int value;
711 } FcStringConst;
713 static int FcStringContainsConst (const FcChar8 *string, const FcStringConst *c, int nc)
715 int i;
717 for (i = 0; i < nc; i++)
719 if (c[i].name[0] == '<')
721 if (FcStrContainsWord (string, c[i].name + 1))
722 return c[i].value;
724 else
726 if (FcStrContainsIgnoreBlanksAndCase (string, c[i].name))
727 return c[i].value;
730 return -1;
733 typedef FcChar8 *FC8;
735 static const FcStringConst weightConsts[] = {
736 { (FC8) "thin", FC_WEIGHT_THIN },
737 { (FC8) "extralight", FC_WEIGHT_EXTRALIGHT },
738 { (FC8) "ultralight", FC_WEIGHT_ULTRALIGHT },
739 { (FC8) "light", FC_WEIGHT_LIGHT },
740 { (FC8) "book", FC_WEIGHT_BOOK },
741 { (FC8) "regular", FC_WEIGHT_REGULAR },
742 { (FC8) "normal", FC_WEIGHT_NORMAL },
743 { (FC8) "medium", FC_WEIGHT_MEDIUM },
744 { (FC8) "demibold", FC_WEIGHT_DEMIBOLD },
745 { (FC8) "demi", FC_WEIGHT_DEMIBOLD },
746 { (FC8) "semibold", FC_WEIGHT_SEMIBOLD },
747 { (FC8) "extrabold", FC_WEIGHT_EXTRABOLD },
748 { (FC8) "superbold", FC_WEIGHT_EXTRABOLD },
749 { (FC8) "ultrabold", FC_WEIGHT_ULTRABOLD },
750 { (FC8) "bold", FC_WEIGHT_BOLD },
751 { (FC8) "ultrablack", FC_WEIGHT_ULTRABLACK },
752 { (FC8) "superblack", FC_WEIGHT_EXTRABLACK },
753 { (FC8) "extrablack", FC_WEIGHT_EXTRABLACK },
754 { (FC8) "<ultra", FC_WEIGHT_ULTRABOLD }, /* only if a word */
755 { (FC8) "black", FC_WEIGHT_BLACK },
756 { (FC8) "heavy", FC_WEIGHT_HEAVY },
759 #define NUM_WEIGHT_CONSTS (int) (sizeof (weightConsts) / sizeof (weightConsts[0]))
761 #define FcIsWeight(s) FcStringIsConst(s,weightConsts,NUM_WEIGHT_CONSTS)
762 #define FcContainsWeight(s) FcStringContainsConst (s,weightConsts,NUM_WEIGHT_CONSTS)
764 static const FcStringConst widthConsts[] = {
765 { (FC8) "ultracondensed", FC_WIDTH_ULTRACONDENSED },
766 { (FC8) "extracondensed", FC_WIDTH_EXTRACONDENSED },
767 { (FC8) "semicondensed", FC_WIDTH_SEMICONDENSED },
768 { (FC8) "condensed", FC_WIDTH_CONDENSED }, /* must be after *condensed */
769 { (FC8) "normal", FC_WIDTH_NORMAL },
770 { (FC8) "semiexpanded", FC_WIDTH_SEMIEXPANDED },
771 { (FC8) "extraexpanded", FC_WIDTH_EXTRAEXPANDED },
772 { (FC8) "ultraexpanded", FC_WIDTH_ULTRAEXPANDED },
773 { (FC8) "expanded", FC_WIDTH_EXPANDED }, /* must be after *expanded */
774 { (FC8) "extended", FC_WIDTH_EXPANDED },
777 #define NUM_WIDTH_CONSTS (int) (sizeof (widthConsts) / sizeof (widthConsts[0]))
779 #define FcIsWidth(s) FcStringIsConst(s,widthConsts,NUM_WIDTH_CONSTS)
780 #define FcContainsWidth(s) FcStringContainsConst (s,widthConsts,NUM_WIDTH_CONSTS)
782 static const FcStringConst slantConsts[] = {
783 { (FC8) "italic", FC_SLANT_ITALIC },
784 { (FC8) "kursiv", FC_SLANT_ITALIC },
785 { (FC8) "oblique", FC_SLANT_OBLIQUE },
788 #define NUM_SLANT_CONSTS (int) (sizeof (slantConsts) / sizeof (slantConsts[0]))
790 #define FcIsSlant(s) FcStringIsConst(s,slantConsts,NUM_SLANT_CONSTS)
791 #define FcContainsSlant(s) FcStringContainsConst (s,slantConsts,NUM_SLANT_CONSTS)
794 struct fontpattern *fcPatternAlloc(void)
796 struct fontpattern *pat = calloc(1, sizeof(struct fontpattern));
798 if (pat != NULL)
800 NewList(&pat->entries);
803 return pat;
806 void fcPatternDestroy(struct fontpattern *pat)
808 if (pat != NULL)
810 struct patternentry *pe, *pen;
812 ITERATELISTSAFE(pe, pen, &pat->entries)
814 if (pe->type == FC_ETYPE_STRING)
816 if (pe->value.s != NULL)
817 free(pe->value.s);
821 REMOVE(pe);
822 free(pe);
825 free(pat);
829 #if 0
831 struct fontpattern *fcQueryFace(const FT_Face face, char *fname, int id)
835 #else
837 static const FcCharEnt AppleRomanEnt[] = {
838 { 0x0020, 0x20 }, /* SPACE */
839 { 0x0021, 0x21 }, /* EXCLAMATION MARK */
840 { 0x0022, 0x22 }, /* QUOTATION MARK */
841 { 0x0023, 0x23 }, /* NUMBER SIGN */
842 { 0x0024, 0x24 }, /* DOLLAR SIGN */
843 { 0x0025, 0x25 }, /* PERCENT SIGN */
844 { 0x0026, 0x26 }, /* AMPERSAND */
845 { 0x0027, 0x27 }, /* APOSTROPHE */
846 { 0x0028, 0x28 }, /* LEFT PARENTHESIS */
847 { 0x0029, 0x29 }, /* RIGHT PARENTHESIS */
848 { 0x002A, 0x2A }, /* ASTERISK */
849 { 0x002B, 0x2B }, /* PLUS SIGN */
850 { 0x002C, 0x2C }, /* COMMA */
851 { 0x002D, 0x2D }, /* HYPHEN-MINUS */
852 { 0x002E, 0x2E }, /* FULL STOP */
853 { 0x002F, 0x2F }, /* SOLIDUS */
854 { 0x0030, 0x30 }, /* DIGIT ZERO */
855 { 0x0031, 0x31 }, /* DIGIT ONE */
856 { 0x0032, 0x32 }, /* DIGIT TWO */
857 { 0x0033, 0x33 }, /* DIGIT THREE */
858 { 0x0034, 0x34 }, /* DIGIT FOUR */
859 { 0x0035, 0x35 }, /* DIGIT FIVE */
860 { 0x0036, 0x36 }, /* DIGIT SIX */
861 { 0x0037, 0x37 }, /* DIGIT SEVEN */
862 { 0x0038, 0x38 }, /* DIGIT EIGHT */
863 { 0x0039, 0x39 }, /* DIGIT NINE */
864 { 0x003A, 0x3A }, /* COLON */
865 { 0x003B, 0x3B }, /* SEMICOLON */
866 { 0x003C, 0x3C }, /* LESS-THAN SIGN */
867 { 0x003D, 0x3D }, /* EQUALS SIGN */
868 { 0x003E, 0x3E }, /* GREATER-THAN SIGN */
869 { 0x003F, 0x3F }, /* QUESTION MARK */
870 { 0x0040, 0x40 }, /* COMMERCIAL AT */
871 { 0x0041, 0x41 }, /* LATIN CAPITAL LETTER A */
872 { 0x0042, 0x42 }, /* LATIN CAPITAL LETTER B */
873 { 0x0043, 0x43 }, /* LATIN CAPITAL LETTER C */
874 { 0x0044, 0x44 }, /* LATIN CAPITAL LETTER D */
875 { 0x0045, 0x45 }, /* LATIN CAPITAL LETTER E */
876 { 0x0046, 0x46 }, /* LATIN CAPITAL LETTER F */
877 { 0x0047, 0x47 }, /* LATIN CAPITAL LETTER G */
878 { 0x0048, 0x48 }, /* LATIN CAPITAL LETTER H */
879 { 0x0049, 0x49 }, /* LATIN CAPITAL LETTER I */
880 { 0x004A, 0x4A }, /* LATIN CAPITAL LETTER J */
881 { 0x004B, 0x4B }, /* LATIN CAPITAL LETTER K */
882 { 0x004C, 0x4C }, /* LATIN CAPITAL LETTER L */
883 { 0x004D, 0x4D }, /* LATIN CAPITAL LETTER M */
884 { 0x004E, 0x4E }, /* LATIN CAPITAL LETTER N */
885 { 0x004F, 0x4F }, /* LATIN CAPITAL LETTER O */
886 { 0x0050, 0x50 }, /* LATIN CAPITAL LETTER P */
887 { 0x0051, 0x51 }, /* LATIN CAPITAL LETTER Q */
888 { 0x0052, 0x52 }, /* LATIN CAPITAL LETTER R */
889 { 0x0053, 0x53 }, /* LATIN CAPITAL LETTER S */
890 { 0x0054, 0x54 }, /* LATIN CAPITAL LETTER T */
891 { 0x0055, 0x55 }, /* LATIN CAPITAL LETTER U */
892 { 0x0056, 0x56 }, /* LATIN CAPITAL LETTER V */
893 { 0x0057, 0x57 }, /* LATIN CAPITAL LETTER W */
894 { 0x0058, 0x58 }, /* LATIN CAPITAL LETTER X */
895 { 0x0059, 0x59 }, /* LATIN CAPITAL LETTER Y */
896 { 0x005A, 0x5A }, /* LATIN CAPITAL LETTER Z */
897 { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET */
898 { 0x005C, 0x5C }, /* REVERSE SOLIDUS */
899 { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET */
900 { 0x005E, 0x5E }, /* CIRCUMFLEX ACCENT */
901 { 0x005F, 0x5F }, /* LOW LINE */
902 { 0x0060, 0x60 }, /* GRAVE ACCENT */
903 { 0x0061, 0x61 }, /* LATIN SMALL LETTER A */
904 { 0x0062, 0x62 }, /* LATIN SMALL LETTER B */
905 { 0x0063, 0x63 }, /* LATIN SMALL LETTER C */
906 { 0x0064, 0x64 }, /* LATIN SMALL LETTER D */
907 { 0x0065, 0x65 }, /* LATIN SMALL LETTER E */
908 { 0x0066, 0x66 }, /* LATIN SMALL LETTER F */
909 { 0x0067, 0x67 }, /* LATIN SMALL LETTER G */
910 { 0x0068, 0x68 }, /* LATIN SMALL LETTER H */
911 { 0x0069, 0x69 }, /* LATIN SMALL LETTER I */
912 { 0x006A, 0x6A }, /* LATIN SMALL LETTER J */
913 { 0x006B, 0x6B }, /* LATIN SMALL LETTER K */
914 { 0x006C, 0x6C }, /* LATIN SMALL LETTER L */
915 { 0x006D, 0x6D }, /* LATIN SMALL LETTER M */
916 { 0x006E, 0x6E }, /* LATIN SMALL LETTER N */
917 { 0x006F, 0x6F }, /* LATIN SMALL LETTER O */
918 { 0x0070, 0x70 }, /* LATIN SMALL LETTER P */
919 { 0x0071, 0x71 }, /* LATIN SMALL LETTER Q */
920 { 0x0072, 0x72 }, /* LATIN SMALL LETTER R */
921 { 0x0073, 0x73 }, /* LATIN SMALL LETTER S */
922 { 0x0074, 0x74 }, /* LATIN SMALL LETTER T */
923 { 0x0075, 0x75 }, /* LATIN SMALL LETTER U */
924 { 0x0076, 0x76 }, /* LATIN SMALL LETTER V */
925 { 0x0077, 0x77 }, /* LATIN SMALL LETTER W */
926 { 0x0078, 0x78 }, /* LATIN SMALL LETTER X */
927 { 0x0079, 0x79 }, /* LATIN SMALL LETTER Y */
928 { 0x007A, 0x7A }, /* LATIN SMALL LETTER Z */
929 { 0x007B, 0x7B }, /* LEFT CURLY BRACKET */
930 { 0x007C, 0x7C }, /* VERTICAL LINE */
931 { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET */
932 { 0x007E, 0x7E }, /* TILDE */
933 { 0x00A0, 0xCA }, /* NO-BREAK SPACE */
934 { 0x00A1, 0xC1 }, /* INVERTED EXCLAMATION MARK */
935 { 0x00A2, 0xA2 }, /* CENT SIGN */
936 { 0x00A3, 0xA3 }, /* POUND SIGN */
937 { 0x00A5, 0xB4 }, /* YEN SIGN */
938 { 0x00A7, 0xA4 }, /* SECTION SIGN */
939 { 0x00A8, 0xAC }, /* DIAERESIS */
940 { 0x00A9, 0xA9 }, /* COPYRIGHT SIGN */
941 { 0x00AA, 0xBB }, /* FEMININE ORDINAL INDICATOR */
942 { 0x00AB, 0xC7 }, /* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
943 { 0x00AC, 0xC2 }, /* NOT SIGN */
944 { 0x00AE, 0xA8 }, /* REGISTERED SIGN */
945 { 0x00AF, 0xF8 }, /* MACRON */
946 { 0x00B0, 0xA1 }, /* DEGREE SIGN */
947 { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN */
948 { 0x00B4, 0xAB }, /* ACUTE ACCENT */
949 { 0x00B5, 0xB5 }, /* MICRO SIGN */
950 { 0x00B6, 0xA6 }, /* PILCROW SIGN */
951 { 0x00B7, 0xE1 }, /* MIDDLE DOT */
952 { 0x00B8, 0xFC }, /* CEDILLA */
953 { 0x00BA, 0xBC }, /* MASCULINE ORDINAL INDICATOR */
954 { 0x00BB, 0xC8 }, /* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
955 { 0x00BF, 0xC0 }, /* INVERTED QUESTION MARK */
956 { 0x00C0, 0xCB }, /* LATIN CAPITAL LETTER A WITH GRAVE */
957 { 0x00C1, 0xE7 }, /* LATIN CAPITAL LETTER A WITH ACUTE */
958 { 0x00C2, 0xE5 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
959 { 0x00C3, 0xCC }, /* LATIN CAPITAL LETTER A WITH TILDE */
960 { 0x00C4, 0x80 }, /* LATIN CAPITAL LETTER A WITH DIAERESIS */
961 { 0x00C5, 0x81 }, /* LATIN CAPITAL LETTER A WITH RING ABOVE */
962 { 0x00C6, 0xAE }, /* LATIN CAPITAL LETTER AE */
963 { 0x00C7, 0x82 }, /* LATIN CAPITAL LETTER C WITH CEDILLA */
964 { 0x00C8, 0xE9 }, /* LATIN CAPITAL LETTER E WITH GRAVE */
965 { 0x00C9, 0x83 }, /* LATIN CAPITAL LETTER E WITH ACUTE */
966 { 0x00CA, 0xE6 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
967 { 0x00CB, 0xE8 }, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
968 { 0x00CC, 0xED }, /* LATIN CAPITAL LETTER I WITH GRAVE */
969 { 0x00CD, 0xEA }, /* LATIN CAPITAL LETTER I WITH ACUTE */
970 { 0x00CE, 0xEB }, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
971 { 0x00CF, 0xEC }, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
972 { 0x00D1, 0x84 }, /* LATIN CAPITAL LETTER N WITH TILDE */
973 { 0x00D2, 0xF1 }, /* LATIN CAPITAL LETTER O WITH GRAVE */
974 { 0x00D3, 0xEE }, /* LATIN CAPITAL LETTER O WITH ACUTE */
975 { 0x00D4, 0xEF }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
976 { 0x00D5, 0xCD }, /* LATIN CAPITAL LETTER O WITH TILDE */
977 { 0x00D6, 0x85 }, /* LATIN CAPITAL LETTER O WITH DIAERESIS */
978 { 0x00D8, 0xAF }, /* LATIN CAPITAL LETTER O WITH STROKE */
979 { 0x00D9, 0xF4 }, /* LATIN CAPITAL LETTER U WITH GRAVE */
980 { 0x00DA, 0xF2 }, /* LATIN CAPITAL LETTER U WITH ACUTE */
981 { 0x00DB, 0xF3 }, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
982 { 0x00DC, 0x86 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS */
983 { 0x00DF, 0xA7 }, /* LATIN SMALL LETTER SHARP S */
984 { 0x00E0, 0x88 }, /* LATIN SMALL LETTER A WITH GRAVE */
985 { 0x00E1, 0x87 }, /* LATIN SMALL LETTER A WITH ACUTE */
986 { 0x00E2, 0x89 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
987 { 0x00E3, 0x8B }, /* LATIN SMALL LETTER A WITH TILDE */
988 { 0x00E4, 0x8A }, /* LATIN SMALL LETTER A WITH DIAERESIS */
989 { 0x00E5, 0x8C }, /* LATIN SMALL LETTER A WITH RING ABOVE */
990 { 0x00E6, 0xBE }, /* LATIN SMALL LETTER AE */
991 { 0x00E7, 0x8D }, /* LATIN SMALL LETTER C WITH CEDILLA */
992 { 0x00E8, 0x8F }, /* LATIN SMALL LETTER E WITH GRAVE */
993 { 0x00E9, 0x8E }, /* LATIN SMALL LETTER E WITH ACUTE */
994 { 0x00EA, 0x90 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */
995 { 0x00EB, 0x91 }, /* LATIN SMALL LETTER E WITH DIAERESIS */
996 { 0x00EC, 0x93 }, /* LATIN SMALL LETTER I WITH GRAVE */
997 { 0x00ED, 0x92 }, /* LATIN SMALL LETTER I WITH ACUTE */
998 { 0x00EE, 0x94 }, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
999 { 0x00EF, 0x95 }, /* LATIN SMALL LETTER I WITH DIAERESIS */
1000 { 0x00F1, 0x96 }, /* LATIN SMALL LETTER N WITH TILDE */
1001 { 0x00F2, 0x98 }, /* LATIN SMALL LETTER O WITH GRAVE */
1002 { 0x00F3, 0x97 }, /* LATIN SMALL LETTER O WITH ACUTE */
1003 { 0x00F4, 0x99 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
1004 { 0x00F5, 0x9B }, /* LATIN SMALL LETTER O WITH TILDE */
1005 { 0x00F6, 0x9A }, /* LATIN SMALL LETTER O WITH DIAERESIS */
1006 { 0x00F7, 0xD6 }, /* DIVISION SIGN */
1007 { 0x00F8, 0xBF }, /* LATIN SMALL LETTER O WITH STROKE */
1008 { 0x00F9, 0x9D }, /* LATIN SMALL LETTER U WITH GRAVE */
1009 { 0x00FA, 0x9C }, /* LATIN SMALL LETTER U WITH ACUTE */
1010 { 0x00FB, 0x9E }, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
1011 { 0x00FC, 0x9F }, /* LATIN SMALL LETTER U WITH DIAERESIS */
1012 { 0x00FF, 0xD8 }, /* LATIN SMALL LETTER Y WITH DIAERESIS */
1013 { 0x0131, 0xF5 }, /* LATIN SMALL LETTER DOTLESS I */
1014 { 0x0152, 0xCE }, /* LATIN CAPITAL LIGATURE OE */
1015 { 0x0153, 0xCF }, /* LATIN SMALL LIGATURE OE */
1016 { 0x0178, 0xD9 }, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
1017 { 0x0192, 0xC4 }, /* LATIN SMALL LETTER F WITH HOOK */
1018 { 0x02C6, 0xF6 }, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
1019 { 0x02C7, 0xFF }, /* CARON */
1020 { 0x02D8, 0xF9 }, /* BREVE */
1021 { 0x02D9, 0xFA }, /* DOT ABOVE */
1022 { 0x02DA, 0xFB }, /* RING ABOVE */
1023 { 0x02DB, 0xFE }, /* OGONEK */
1024 { 0x02DC, 0xF7 }, /* SMALL TILDE */
1025 { 0x02DD, 0xFD }, /* DOUBLE ACUTE ACCENT */
1026 { 0x03A9, 0xBD }, /* GREEK CAPITAL LETTER OMEGA */
1027 { 0x03C0, 0xB9 }, /* GREEK SMALL LETTER PI */
1028 { 0x2013, 0xD0 }, /* EN DASH */
1029 { 0x2014, 0xD1 }, /* EM DASH */
1030 { 0x2018, 0xD4 }, /* LEFT SINGLE QUOTATION MARK */
1031 { 0x2019, 0xD5 }, /* RIGHT SINGLE QUOTATION MARK */
1032 { 0x201A, 0xE2 }, /* SINGLE LOW-9 QUOTATION MARK */
1033 { 0x201C, 0xD2 }, /* LEFT DOUBLE QUOTATION MARK */
1034 { 0x201D, 0xD3 }, /* RIGHT DOUBLE QUOTATION MARK */
1035 { 0x201E, 0xE3 }, /* DOUBLE LOW-9 QUOTATION MARK */
1036 { 0x2020, 0xA0 }, /* DAGGER */
1037 { 0x2021, 0xE0 }, /* DOUBLE DAGGER */
1038 { 0x2022, 0xA5 }, /* BULLET */
1039 { 0x2026, 0xC9 }, /* HORIZONTAL ELLIPSIS */
1040 { 0x2030, 0xE4 }, /* PER MILLE SIGN */
1041 { 0x2039, 0xDC }, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
1042 { 0x203A, 0xDD }, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
1043 { 0x2044, 0xDA }, /* FRACTION SLASH */
1044 { 0x20AC, 0xDB }, /* EURO SIGN */
1045 { 0x2122, 0xAA }, /* TRADE MARK SIGN */
1046 { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL */
1047 { 0x2206, 0xC6 }, /* INCREMENT */
1048 { 0x220F, 0xB8 }, /* N-ARY PRODUCT */
1049 { 0x2211, 0xB7 }, /* N-ARY SUMMATION */
1050 { 0x221A, 0xC3 }, /* SQUARE ROOT */
1051 { 0x221E, 0xB0 }, /* INFINITY */
1052 { 0x222B, 0xBA }, /* INTEGRAL */
1053 { 0x2248, 0xC5 }, /* ALMOST EQUAL TO */
1054 { 0x2260, 0xAD }, /* NOT EQUAL TO */
1055 { 0x2264, 0xB2 }, /* LESS-THAN OR EQUAL TO */
1056 { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO */
1057 { 0x25CA, 0xD7 }, /* LOZENGE */
1058 { 0xF8FF, 0xF0 }, /* Apple logo */
1059 { 0xFB01, 0xDE }, /* LATIN SMALL LIGATURE FI */
1060 { 0xFB02, 0xDF }, /* LATIN SMALL LIGATURE FL */
1063 static const FcCharMap AppleRoman = {
1064 AppleRomanEnt,
1065 sizeof (AppleRomanEnt) / sizeof (AppleRomanEnt[0])
1068 /// AdobeSymboEnt
1070 static const FcCharEnt AdobeSymbolEnt[] = {
1071 { 0x0020, 0x20 }, /* SPACE # space */
1072 { 0x0021, 0x21 }, /* EXCLAMATION MARK # exclam */
1073 { 0x0023, 0x23 }, /* NUMBER SIGN # numbersign */
1074 { 0x0025, 0x25 }, /* PERCENT SIGN # percent */
1075 { 0x0026, 0x26 }, /* AMPERSAND # ampersand */
1076 { 0x0028, 0x28 }, /* LEFT PARENTHESIS # parenleft */
1077 { 0x0029, 0x29 }, /* RIGHT PARENTHESIS # parenright */
1078 { 0x002B, 0x2B }, /* PLUS SIGN # plus */
1079 { 0x002C, 0x2C }, /* COMMA # comma */
1080 { 0x002E, 0x2E }, /* FULL STOP # period */
1081 { 0x002F, 0x2F }, /* SOLIDUS # slash */
1082 { 0x0030, 0x30 }, /* DIGIT ZERO # zero */
1083 { 0x0031, 0x31 }, /* DIGIT ONE # one */
1084 { 0x0032, 0x32 }, /* DIGIT TWO # two */
1085 { 0x0033, 0x33 }, /* DIGIT THREE # three */
1086 { 0x0034, 0x34 }, /* DIGIT FOUR # four */
1087 { 0x0035, 0x35 }, /* DIGIT FIVE # five */
1088 { 0x0036, 0x36 }, /* DIGIT SIX # six */
1089 { 0x0037, 0x37 }, /* DIGIT SEVEN # seven */
1090 { 0x0038, 0x38 }, /* DIGIT EIGHT # eight */
1091 { 0x0039, 0x39 }, /* DIGIT NINE # nine */
1092 { 0x003A, 0x3A }, /* COLON # colon */
1093 { 0x003B, 0x3B }, /* SEMICOLON # semicolon */
1094 { 0x003C, 0x3C }, /* LESS-THAN SIGN # less */
1095 { 0x003D, 0x3D }, /* EQUALS SIGN # equal */
1096 { 0x003E, 0x3E }, /* GREATER-THAN SIGN # greater */
1097 { 0x003F, 0x3F }, /* QUESTION MARK # question */
1098 { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET # bracketleft */
1099 { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET # bracketright */
1100 { 0x005F, 0x5F }, /* LOW LINE # underscore */
1101 { 0x007B, 0x7B }, /* LEFT CURLY BRACKET # braceleft */
1102 { 0x007C, 0x7C }, /* VERTICAL LINE # bar */
1103 { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET # braceright */
1104 { 0x00A0, 0x20 }, /* NO-BREAK SPACE # space */
1105 { 0x00AC, 0xD8 }, /* NOT SIGN # logicalnot */
1106 { 0x00B0, 0xB0 }, /* DEGREE SIGN # degree */
1107 { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN # plusminus */
1108 { 0x00B5, 0x6D }, /* MICRO SIGN # mu */
1109 { 0x00D7, 0xB4 }, /* MULTIPLICATION SIGN # multiply */
1110 { 0x00F7, 0xB8 }, /* DIVISION SIGN # divide */
1111 { 0x0192, 0xA6 }, /* LATIN SMALL LETTER F WITH HOOK # florin */
1112 { 0x0391, 0x41 }, /* GREEK CAPITAL LETTER ALPHA # Alpha */
1113 { 0x0392, 0x42 }, /* GREEK CAPITAL LETTER BETA # Beta */
1114 { 0x0393, 0x47 }, /* GREEK CAPITAL LETTER GAMMA # Gamma */
1115 { 0x0394, 0x44 }, /* GREEK CAPITAL LETTER DELTA # Delta */
1116 { 0x0395, 0x45 }, /* GREEK CAPITAL LETTER EPSILON # Epsilon */
1117 { 0x0396, 0x5A }, /* GREEK CAPITAL LETTER ZETA # Zeta */
1118 { 0x0397, 0x48 }, /* GREEK CAPITAL LETTER ETA # Eta */
1119 { 0x0398, 0x51 }, /* GREEK CAPITAL LETTER THETA # Theta */
1120 { 0x0399, 0x49 }, /* GREEK CAPITAL LETTER IOTA # Iota */
1121 { 0x039A, 0x4B }, /* GREEK CAPITAL LETTER KAPPA # Kappa */
1122 { 0x039B, 0x4C }, /* GREEK CAPITAL LETTER LAMDA # Lambda */
1123 { 0x039C, 0x4D }, /* GREEK CAPITAL LETTER MU # Mu */
1124 { 0x039D, 0x4E }, /* GREEK CAPITAL LETTER NU # Nu */
1125 { 0x039E, 0x58 }, /* GREEK CAPITAL LETTER XI # Xi */
1126 { 0x039F, 0x4F }, /* GREEK CAPITAL LETTER OMICRON # Omicron */
1127 { 0x03A0, 0x50 }, /* GREEK CAPITAL LETTER PI # Pi */
1128 { 0x03A1, 0x52 }, /* GREEK CAPITAL LETTER RHO # Rho */
1129 { 0x03A3, 0x53 }, /* GREEK CAPITAL LETTER SIGMA # Sigma */
1130 { 0x03A4, 0x54 }, /* GREEK CAPITAL LETTER TAU # Tau */
1131 { 0x03A5, 0x55 }, /* GREEK CAPITAL LETTER UPSILON # Upsilon */
1132 { 0x03A6, 0x46 }, /* GREEK CAPITAL LETTER PHI # Phi */
1133 { 0x03A7, 0x43 }, /* GREEK CAPITAL LETTER CHI # Chi */
1134 { 0x03A8, 0x59 }, /* GREEK CAPITAL LETTER PSI # Psi */
1135 { 0x03A9, 0x57 }, /* GREEK CAPITAL LETTER OMEGA # Omega */
1136 { 0x03B1, 0x61 }, /* GREEK SMALL LETTER ALPHA # alpha */
1137 { 0x03B2, 0x62 }, /* GREEK SMALL LETTER BETA # beta */
1138 { 0x03B3, 0x67 }, /* GREEK SMALL LETTER GAMMA # gamma */
1139 { 0x03B4, 0x64 }, /* GREEK SMALL LETTER DELTA # delta */
1140 { 0x03B5, 0x65 }, /* GREEK SMALL LETTER EPSILON # epsilon */
1141 { 0x03B6, 0x7A }, /* GREEK SMALL LETTER ZETA # zeta */
1142 { 0x03B7, 0x68 }, /* GREEK SMALL LETTER ETA # eta */
1143 { 0x03B8, 0x71 }, /* GREEK SMALL LETTER THETA # theta */
1144 { 0x03B9, 0x69 }, /* GREEK SMALL LETTER IOTA # iota */
1145 { 0x03BA, 0x6B }, /* GREEK SMALL LETTER KAPPA # kappa */
1146 { 0x03BB, 0x6C }, /* GREEK SMALL LETTER LAMDA # lambda */
1147 { 0x03BC, 0x6D }, /* GREEK SMALL LETTER MU # mu */
1148 { 0x03BD, 0x6E }, /* GREEK SMALL LETTER NU # nu */
1149 { 0x03BE, 0x78 }, /* GREEK SMALL LETTER XI # xi */
1150 { 0x03BF, 0x6F }, /* GREEK SMALL LETTER OMICRON # omicron */
1151 { 0x03C0, 0x70 }, /* GREEK SMALL LETTER PI # pi */
1152 { 0x03C1, 0x72 }, /* GREEK SMALL LETTER RHO # rho */
1153 { 0x03C2, 0x56 }, /* GREEK SMALL LETTER FINAL SIGMA # sigma1 */
1154 { 0x03C3, 0x73 }, /* GREEK SMALL LETTER SIGMA # sigma */
1155 { 0x03C4, 0x74 }, /* GREEK SMALL LETTER TAU # tau */
1156 { 0x03C5, 0x75 }, /* GREEK SMALL LETTER UPSILON # upsilon */
1157 { 0x03C6, 0x66 }, /* GREEK SMALL LETTER PHI # phi */
1158 { 0x03C7, 0x63 }, /* GREEK SMALL LETTER CHI # chi */
1159 { 0x03C8, 0x79 }, /* GREEK SMALL LETTER PSI # psi */
1160 { 0x03C9, 0x77 }, /* GREEK SMALL LETTER OMEGA # omega */
1161 { 0x03D1, 0x4A }, /* GREEK THETA SYMBOL # theta1 */
1162 { 0x03D2, 0xA1 }, /* GREEK UPSILON WITH HOOK SYMBOL # Upsilon1 */
1163 { 0x03D5, 0x6A }, /* GREEK PHI SYMBOL # phi1 */
1164 { 0x03D6, 0x76 }, /* GREEK PI SYMBOL # omega1 */
1165 { 0x2022, 0xB7 }, /* BULLET # bullet */
1166 { 0x2026, 0xBC }, /* HORIZONTAL ELLIPSIS # ellipsis */
1167 { 0x2032, 0xA2 }, /* PRIME # minute */
1168 { 0x2033, 0xB2 }, /* DOUBLE PRIME # second */
1169 { 0x2044, 0xA4 }, /* FRACTION SLASH # fraction */
1170 { 0x20AC, 0xA0 }, /* EURO SIGN # Euro */
1171 { 0x2111, 0xC1 }, /* BLACK-LETTER CAPITAL I # Ifraktur */
1172 { 0x2118, 0xC3 }, /* SCRIPT CAPITAL P # weierstrass */
1173 { 0x211C, 0xC2 }, /* BLACK-LETTER CAPITAL R # Rfraktur */
1174 { 0x2126, 0x57 }, /* OHM SIGN # Omega */
1175 { 0x2135, 0xC0 }, /* ALEF SYMBOL # aleph */
1176 { 0x2190, 0xAC }, /* LEFTWARDS ARROW # arrowleft */
1177 { 0x2191, 0xAD }, /* UPWARDS ARROW # arrowup */
1178 { 0x2192, 0xAE }, /* RIGHTWARDS ARROW # arrowright */
1179 { 0x2193, 0xAF }, /* DOWNWARDS ARROW # arrowdown */
1180 { 0x2194, 0xAB }, /* LEFT RIGHT ARROW # arrowboth */
1181 { 0x21B5, 0xBF }, /* DOWNWARDS ARROW WITH CORNER LEFTWARDS # carriagereturn */
1182 { 0x21D0, 0xDC }, /* LEFTWARDS DOUBLE ARROW # arrowdblleft */
1183 { 0x21D1, 0xDD }, /* UPWARDS DOUBLE ARROW # arrowdblup */
1184 { 0x21D2, 0xDE }, /* RIGHTWARDS DOUBLE ARROW # arrowdblright */
1185 { 0x21D3, 0xDF }, /* DOWNWARDS DOUBLE ARROW # arrowdbldown */
1186 { 0x21D4, 0xDB }, /* LEFT RIGHT DOUBLE ARROW # arrowdblboth */
1187 { 0x2200, 0x22 }, /* FOR ALL # universal */
1188 { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL # partialdiff */
1189 { 0x2203, 0x24 }, /* THERE EXISTS # existential */
1190 { 0x2205, 0xC6 }, /* EMPTY SET # emptyset */
1191 { 0x2206, 0x44 }, /* INCREMENT # Delta */
1192 { 0x2207, 0xD1 }, /* NABLA # gradient */
1193 { 0x2208, 0xCE }, /* ELEMENT OF # element */
1194 { 0x2209, 0xCF }, /* NOT AN ELEMENT OF # notelement */
1195 { 0x220B, 0x27 }, /* CONTAINS AS MEMBER # suchthat */
1196 { 0x220F, 0xD5 }, /* N-ARY PRODUCT # product */
1197 { 0x2211, 0xE5 }, /* N-ARY SUMMATION # summation */
1198 { 0x2212, 0x2D }, /* MINUS SIGN # minus */
1199 { 0x2215, 0xA4 }, /* DIVISION SLASH # fraction */
1200 { 0x2217, 0x2A }, /* ASTERISK OPERATOR # asteriskmath */
1201 { 0x221A, 0xD6 }, /* SQUARE ROOT # radical */
1202 { 0x221D, 0xB5 }, /* PROPORTIONAL TO # proportional */
1203 { 0x221E, 0xA5 }, /* INFINITY # infinity */
1204 { 0x2220, 0xD0 }, /* ANGLE # angle */
1205 { 0x2227, 0xD9 }, /* LOGICAL AND # logicaland */
1206 { 0x2228, 0xDA }, /* LOGICAL OR # logicalor */
1207 { 0x2229, 0xC7 }, /* INTERSECTION # intersection */
1208 { 0x222A, 0xC8 }, /* UNION # union */
1209 { 0x222B, 0xF2 }, /* INTEGRAL # integral */
1210 { 0x2234, 0x5C }, /* THEREFORE # therefore */
1211 { 0x223C, 0x7E }, /* TILDE OPERATOR # similar */
1212 { 0x2245, 0x40 }, /* APPROXIMATELY EQUAL TO # congruent */
1213 { 0x2248, 0xBB }, /* ALMOST EQUAL TO # approxequal */
1214 { 0x2260, 0xB9 }, /* NOT EQUAL TO # notequal */
1215 { 0x2261, 0xBA }, /* IDENTICAL TO # equivalence */
1216 { 0x2264, 0xA3 }, /* LESS-THAN OR EQUAL TO # lessequal */
1217 { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO # greaterequal */
1218 { 0x2282, 0xCC }, /* SUBSET OF # propersubset */
1219 { 0x2283, 0xC9 }, /* SUPERSET OF # propersuperset */
1220 { 0x2284, 0xCB }, /* NOT A SUBSET OF # notsubset */
1221 { 0x2286, 0xCD }, /* SUBSET OF OR EQUAL TO # reflexsubset */
1222 { 0x2287, 0xCA }, /* SUPERSET OF OR EQUAL TO # reflexsuperset */
1223 { 0x2295, 0xC5 }, /* CIRCLED PLUS # circleplus */
1224 { 0x2297, 0xC4 }, /* CIRCLED TIMES # circlemultiply */
1225 { 0x22A5, 0x5E }, /* UP TACK # perpendicular */
1226 { 0x22C5, 0xD7 }, /* DOT OPERATOR # dotmath */
1227 { 0x2320, 0xF3 }, /* TOP HALF INTEGRAL # integraltp */
1228 { 0x2321, 0xF5 }, /* BOTTOM HALF INTEGRAL # integralbt */
1229 { 0x2329, 0xE1 }, /* LEFT-POINTING ANGLE BRACKET # angleleft */
1230 { 0x232A, 0xF1 }, /* RIGHT-POINTING ANGLE BRACKET # angleright */
1231 { 0x25CA, 0xE0 }, /* LOZENGE # lozenge */
1232 { 0x2660, 0xAA }, /* BLACK SPADE SUIT # spade */
1233 { 0x2663, 0xA7 }, /* BLACK CLUB SUIT # club */
1234 { 0x2665, 0xA9 }, /* BLACK HEART SUIT # heart */
1235 { 0x2666, 0xA8 }, /* BLACK DIAMOND SUIT # diamond */
1236 { 0xF6D9, 0xD3 }, /* COPYRIGHT SIGN SERIF # copyrightserif (CUS) */
1237 { 0xF6DA, 0xD2 }, /* REGISTERED SIGN SERIF # registerserif (CUS) */
1238 { 0xF6DB, 0xD4 }, /* TRADE MARK SIGN SERIF # trademarkserif (CUS) */
1239 { 0xF8E5, 0x60 }, /* RADICAL EXTENDER # radicalex (CUS) */
1240 { 0xF8E6, 0xBD }, /* VERTICAL ARROW EXTENDER # arrowvertex (CUS) */
1241 { 0xF8E7, 0xBE }, /* HORIZONTAL ARROW EXTENDER # arrowhorizex (CUS) */
1242 { 0xF8E8, 0xE2 }, /* REGISTERED SIGN SANS SERIF # registersans (CUS) */
1243 { 0xF8E9, 0xE3 }, /* COPYRIGHT SIGN SANS SERIF # copyrightsans (CUS) */
1244 { 0xF8EA, 0xE4 }, /* TRADE MARK SIGN SANS SERIF # trademarksans (CUS) */
1245 { 0xF8EB, 0xE6 }, /* LEFT PAREN TOP # parenlefttp (CUS) */
1246 { 0xF8EC, 0xE7 }, /* LEFT PAREN EXTENDER # parenleftex (CUS) */
1247 { 0xF8ED, 0xE8 }, /* LEFT PAREN BOTTOM # parenleftbt (CUS) */
1248 { 0xF8EE, 0xE9 }, /* LEFT SQUARE BRACKET TOP # bracketlefttp (CUS) */
1249 { 0xF8EF, 0xEA }, /* LEFT SQUARE BRACKET EXTENDER # bracketleftex (CUS) */
1250 { 0xF8F0, 0xEB }, /* LEFT SQUARE BRACKET BOTTOM # bracketleftbt (CUS) */
1251 { 0xF8F1, 0xEC }, /* LEFT CURLY BRACKET TOP # bracelefttp (CUS) */
1252 { 0xF8F2, 0xED }, /* LEFT CURLY BRACKET MID # braceleftmid (CUS) */
1253 { 0xF8F3, 0xEE }, /* LEFT CURLY BRACKET BOTTOM # braceleftbt (CUS) */
1254 { 0xF8F4, 0xEF }, /* CURLY BRACKET EXTENDER # braceex (CUS) */
1255 { 0xF8F5, 0xF4 }, /* INTEGRAL EXTENDER # integralex (CUS) */
1256 { 0xF8F6, 0xF6 }, /* RIGHT PAREN TOP # parenrighttp (CUS) */
1257 { 0xF8F7, 0xF7 }, /* RIGHT PAREN EXTENDER # parenrightex (CUS) */
1258 { 0xF8F8, 0xF8 }, /* RIGHT PAREN BOTTOM # parenrightbt (CUS) */
1259 { 0xF8F9, 0xF9 }, /* RIGHT SQUARE BRACKET TOP # bracketrighttp (CUS) */
1260 { 0xF8FA, 0xFA }, /* RIGHT SQUARE BRACKET EXTENDER # bracketrightex (CUS) */
1261 { 0xF8FB, 0xFB }, /* RIGHT SQUARE BRACKET BOTTOM # bracketrightbt (CUS) */
1262 { 0xF8FC, 0xFC }, /* RIGHT CURLY BRACKET TOP # bracerighttp (CUS) */
1263 { 0xF8FD, 0xFD }, /* RIGHT CURLY BRACKET MID # bracerightmid (CUS) */
1264 { 0xF8FE, 0xFE }, /* RIGHT CURLY BRACKET BOTTOM # bracerightbt (CUS) */
1267 ////
1269 static const FcCharMap AdobeSymbol = {
1270 AdobeSymbolEnt,
1271 sizeof (AdobeSymbolEnt) / sizeof (AdobeSymbolEnt[0]),
1275 static const FcFontDecode fcFontDecoders[] = {
1276 { ft_encoding_unicode, 0, (1 << 21) - 1 },
1277 { ft_encoding_symbol, &AdobeSymbol, (1 << 16) - 1 },
1278 { ft_encoding_apple_roman, &AppleRoman, (1 << 16) - 1 },
1281 #define NUM_DECODE (int) (sizeof (fcFontDecoders) / sizeof (fcFontDecoders[0]))
1283 static FcChar32 FcFreeTypePrivateToUcs4 (FcChar32 private, const FcCharMap *map);
1285 const FcCharMap *FcFreeTypeGetPrivateMap(FT_Encoding encoding)
1287 int i;
1289 for (i = 0; i < NUM_DECODE; i++)
1290 if (fcFontDecoders[i].encoding == encoding)
1291 return fcFontDecoders[i].map;
1292 return 0;
1295 /* A shift-JIS will have many high bits turned on */
1296 static FcBool FcLooksLikeSJIS (FcChar8 *string, int len)
1298 int nhigh = 0, nlow = 0;
1300 while (len-- > 0)
1302 if (*string++ & 0x80)
1303 nhigh++;
1304 else
1305 nlow++;
1307 /* Heuristic -- if more than 1/3 of the bytes have the high-bit set, this is likely to be SJIS and not ROMAN */
1308 if (nhigh * 2 > nlow)
1309 return FcTrue;
1311 return FcFalse;
1314 static char *fcSfntNameTranscode(FT_SfntName *sname)
1316 int i;
1317 const char *fromcode;
1318 char *utf8;
1320 for (i = 0; i < NUM_FC_FT_ENCODING; i++)
1321 if (fcFtEncoding[i].platform_id == sname->platform_id &&
1322 (fcFtEncoding[i].encoding_id == TT_ENCODING_DONT_CARE ||
1323 fcFtEncoding[i].encoding_id == sname->encoding_id))
1324 break;
1326 if (i == NUM_FC_FT_ENCODING)
1327 return 0;
1328 fromcode = fcFtEncoding[i].fromcode;
1330 /* Many names encoded for TT_PLATFORM_MACINTOSH are broken in various ways. Kludge around them. */
1332 if (!strcmp (fromcode, FC_ENCODING_MAC_ROMAN))
1334 if (sname->language_id == TT_MAC_LANGID_ENGLISH &&
1335 FcLooksLikeSJIS (sname->string, sname->string_len))
1337 fromcode = "SJIS";
1339 else if (sname->language_id >= 0x100)
1341 /* "real" Mac language IDs are all less than 150.
1342 * Names using one of the MS language IDs are assumed
1343 * to use an associated encoding (Yes, this is a kludge)
1345 int f;
1347 fromcode = NULL;
1348 for (f = 0; f < NUM_FC_MAC_ROMAN_FAKE; f++)
1349 if (fcMacRomanFake[f].language_id == sname->language_id)
1351 fromcode = fcMacRomanFake[f].fromcode;
1352 break;
1354 if (!fromcode)
1355 return 0;
1358 if (!strcmp (fromcode, "UCS-2BE") || !strcmp (fromcode, "UTF-16BE"))
1360 char *src = sname->string;
1361 int src_len = sname->string_len;
1362 int len;
1363 int wchar;
1364 int ilen, olen;
1365 char *u8;
1366 unsigned int ucs4;
1368 /* Convert Utf16 to Utf8 */
1370 if (!FcUtf16Len(src, FcEndianBig, src_len, &len, &wchar))
1371 return 0;
1373 /* Allocate plenty of space. Freed below */
1374 utf8 = malloc (len * FC_UTF8_MAX_LEN + 1);
1375 if (!utf8)
1376 return 0;
1378 u8 = utf8;
1380 while ((ilen = FcUtf16ToUcs4 (src, FcEndianBig, &ucs4, src_len)) > 0)
1382 src_len -= ilen;
1383 src += ilen;
1384 olen = FcUcs4ToUtf8 (ucs4, u8);
1385 u8 += olen;
1388 *u8 = '\0';
1389 goto done;
1391 if (!strcmp (fromcode, "ASCII") || !strcmp (fromcode, "ISO-8859-1"))
1393 FcChar8 *src = sname->string;
1394 int src_len = sname->string_len;
1395 int olen;
1396 FcChar8 *u8;
1397 FcChar32 ucs4;
1399 /* Convert Latin1 to Utf8. Freed below */
1400 utf8 = malloc (src_len * 2 + 1);
1401 if (!utf8)
1402 return 0;
1404 u8 = utf8;
1405 while (src_len > 0)
1407 ucs4 = *src++;
1408 src_len--;
1409 olen = FcUcs4ToUtf8 (ucs4, u8);
1410 u8 += olen;
1412 *u8 = '\0';
1413 goto done;
1415 if (!strcmp (fromcode, FC_ENCODING_MAC_ROMAN))
1417 FcChar8 *u8;
1418 const FcCharMap *map = FcFreeTypeGetPrivateMap (ft_encoding_apple_roman);
1419 FcChar8 *src = (FcChar8 *) sname->string;
1420 int src_len = sname->string_len;
1422 /* Convert AppleRoman to Utf8 */
1423 if (!map)
1424 return 0;
1426 utf8 = malloc (sname->string_len * 3 + 1);
1427 if (!utf8)
1428 return 0;
1430 u8 = utf8;
1431 while (src_len > 0)
1433 FcChar32 ucs4 = FcFreeTypePrivateToUcs4 (*src++, map);
1434 int olen = FcUcs4ToUtf8 (ucs4, u8);
1435 src_len--;
1436 u8 += olen;
1438 *u8 = '\0';
1439 goto done;
1442 return 0;
1443 done:
1444 if (FcStrCmpIgnoreBlanksAndCase (utf8, (FcChar8 *) "") == 0)
1446 free (utf8);
1447 return 0;
1449 return utf8;
1452 static const char *fcSfntNameLanguage(FT_SfntName *sname)
1454 int i;
1455 FT_UShort platform_id = sname->platform_id;
1456 FT_UShort language_id = sname->language_id;
1458 /* Many names encoded for TT_PLATFORM_MACINTOSH are broken in various ways. Kludge around them. */
1459 if (platform_id == TT_PLATFORM_MACINTOSH && sname->encoding_id == TT_MAC_ID_ROMAN && FcLooksLikeSJIS (sname->string, sname->string_len))
1461 language_id = TT_MAC_LANGID_JAPANESE;
1464 for (i = 0; i < NUM_FC_FT_LANGUAGE; i++)
1465 if (fcFtLanguage[i].platform_id == platform_id && (fcFtLanguage[i].language_id == TT_LANGUAGE_DONT_CARE || fcFtLanguage[i].language_id == language_id))
1467 if (fcFtLanguage[i].lang[0] == '\0')
1468 return NULL;
1469 else
1470 return (char *)fcFtLanguage[i].lang;
1472 return 0;
1475 static int fcStringInPatternElement(struct fontpattern *pat, const int elt, char *string)
1477 int e;
1478 for (e = 0;; e++)
1480 char *old = fcPatternGetString(pat, elt, e);
1481 if (old != NULL && !FcStrCmpIgnoreBlanksAndCase(old, string))
1482 return FcTrue;
1484 if (old != NULL)
1485 e++; /* try next element, otherwise bail out */
1486 else
1487 break;
1490 return FcFalse;
1495 struct fontpattern *fcQueryFace(const FT_Face face, char *fname, int id)
1497 struct fontpattern *pat = NULL;
1498 int slant = -1;
1499 int weight = -1;
1500 int width = -1;
1501 int serif = -1;
1502 int i;
1503 struct fontlangset *ls;
1504 struct fontcharset *cs;
1505 int spacing;
1506 TT_OS2 *os2;
1507 #if HAVE_FT_GET_PS_FONT_INFO
1508 PS_FontInfoRec psfontinfo;
1509 #endif
1510 #if HAVE_FT_GET_BDF_PROPERTY
1511 BDF_PropertyRec prop;
1512 #endif
1513 TT_Header *head;
1514 char *exclusiveLang = 0;
1515 FT_SfntName sname;
1516 unsigned int snamei, snamec;
1518 int nfamily = 0;
1519 int nstyle = 0;
1520 int nfullname = 0;
1521 int p, platform;
1522 int n, nameid;
1524 char *style = 0;
1525 int st;
1527 pat = fcPatternAlloc();
1528 if (pat == NULL)
1529 return NULL;
1531 /* Get the OS/2 table */
1532 os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2);
1534 /* Grub through the name table looking for family and style names. FreeType makes quite a hash of them */
1535 snamec = FT_Get_Sfnt_Name_Count(face);
1536 for (p = 0; p <= NUM_PLATFORM_ORDER; p++)
1538 if (p < NUM_PLATFORM_ORDER)
1539 platform = platform_order[p];
1540 else
1541 platform = 0xffff;
1543 /* Order nameids so preferred names appear first in the resulting list */
1544 for (n = 0; n < NUM_NAMEID_ORDER; n++)
1546 nameid = nameid_order[n];
1548 for (snamei = 0; snamei < snamec; snamei++)
1550 char *utf8;
1551 int elt = 0;
1553 if (FT_Get_Sfnt_Name (face, snamei, &sname) != 0)
1554 continue;
1555 if (sname.name_id != nameid)
1556 continue;
1558 /* Sort platforms in preference order, accepting all other platforms last */
1559 if (p < NUM_PLATFORM_ORDER)
1561 if (sname.platform_id != platform)
1562 continue;
1564 else
1566 int sp;
1568 for (sp = 0; sp < NUM_PLATFORM_ORDER; sp++)
1569 if (sname.platform_id == platform_order[sp])
1570 break;
1572 if (sp != NUM_PLATFORM_ORDER)
1573 continue;
1575 utf8 = fcSfntNameTranscode(&sname);
1577 if (utf8 == NULL)
1578 continue;
1580 switch (sname.name_id) {
1581 #ifdef TT_NAME_ID_WWS_FAMILY
1582 case TT_NAME_ID_WWS_FAMILY:
1583 #endif
1584 case TT_NAME_ID_PREFERRED_FAMILY:
1585 case TT_NAME_ID_FONT_FAMILY:
1586 #if 0
1587 case TT_NAME_ID_PS_NAME:
1588 case TT_NAME_ID_UNIQUE_ID:
1589 #endif
1591 if (FcDebug () & FC_DBG_SCANV)
1592 kprintf ("found family (n %2d p %d e %d l 0x%04x) %s\n",
1593 sname.name_id, sname.platform_id,
1594 sname.encoding_id, sname.language_id,
1595 utf8);
1597 elt = FC_FAMILY;
1598 break;
1599 case TT_NAME_ID_MAC_FULL_NAME:
1600 case TT_NAME_ID_FULL_NAME:
1602 if (FcDebug () & FC_DBG_SCANV)
1603 kprintf ("found full (n %2d p %d e %d l 0x%04x) %s\n",
1604 sname.name_id, sname.platform_id,
1605 sname.encoding_id, sname.language_id,
1606 utf8);
1609 elt = FC_FULLNAME;
1610 break;
1611 #ifdef TT_NAME_ID_WWS_SUBFAMILY
1612 case TT_NAME_ID_WWS_SUBFAMILY:
1613 #endif
1614 case TT_NAME_ID_PREFERRED_SUBFAMILY:
1615 case TT_NAME_ID_FONT_SUBFAMILY:
1617 if (FcDebug () & FC_DBG_SCANV)
1618 kprintf ("found style (n %2d p %d e %d l 0x%04x) %s\n",
1619 sname.name_id, sname.platform_id,
1620 sname.encoding_id, sname.language_id,
1621 utf8);
1624 elt = FC_STYLE;
1625 break;
1628 if (elt)
1630 if (fcStringInPatternElement(pat, elt, utf8))
1632 free(utf8);
1633 continue;
1636 /* add new element */
1637 if (!fcPatternAddString (pat, elt, utf8))
1639 free(utf8);
1640 goto bail1;
1642 free(utf8);
1644 else
1645 free (utf8);
1651 if (!nfamily && face->family_name && FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->family_name, (FcChar8 *) "") != 0)
1654 if (FcDebug () & FC_DBG_SCANV)
1655 kprintf ("using FreeType family \"%s\"\n", face->family_name);
1657 if (!fcPatternAddString (pat, FC_FAMILY, (FcChar8 *) face->family_name))
1658 goto bail1;
1659 ++nfamily;
1662 if (!nstyle && face->style_name && FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->style_name, (FcChar8 *) "") != 0)
1664 if (FcDebug () & FC_DBG_SCANV)
1665 kprintf ("using FreeType style \"%s\"\n", face->style_name);
1667 if (!fcPatternAddString (pat, FC_STYLE, (FcChar8 *) face->style_name))
1668 goto bail1;
1669 ++nstyle;
1672 if (!nfamily)
1674 FcChar8 *start, *end;
1675 FcChar8 *family;
1677 start = (FcChar8 *) strrchr ((char *) fname, '/');
1678 if (start)
1679 start++;
1680 else
1681 start = (FcChar8 *) fname;
1682 end = (FcChar8 *) strrchr ((char *) start, '.');
1683 if (!end)
1684 end = start + strlen ((char *) start);
1685 /* freed below */
1686 family = malloc (end - start + 1);
1687 strncpy ((char *) family, (char *) start, end - start);
1688 family[end - start] = '\0';
1690 if (FcDebug () & FC_DBG_SCANV)
1691 kprintf ("using filename for family %s\n", family);
1693 if (!fcPatternAddString (pat, FC_FAMILY, family))
1695 free (family);
1696 goto bail1;
1698 free (family);
1699 ++nfamily;
1702 if (!fcPatternAddString (pat, FC_FILE, fname))
1703 goto bail1;
1705 if (!fcPatternAddInteger (pat, FC_INDEX, id))
1706 goto bail1;
1708 if (os2 && os2->version >= 0x0001 && os2->version != 0xffff)
1710 for (i = 0; i < NUM_CODE_PAGE_RANGE; i++)
1712 FT_ULong bits;
1713 int bit;
1714 if (FcCodePageRange[i].bit < 32)
1716 bits = os2->ulCodePageRange1;
1717 bit = FcCodePageRange[i].bit;
1719 else
1721 bits = os2->ulCodePageRange2;
1722 bit = FcCodePageRange[i].bit - 32;
1724 if (bits & (1 << bit))
1726 /* If the font advertises support for multiple
1727 * "exclusive" languages, then include support
1728 * for any language found to have coverage
1731 if (exclusiveLang)
1733 exclusiveLang = 0;
1734 break;
1736 exclusiveLang = FcCodePageRange[i].lang;
1741 if (os2 && os2 && (unsigned)(((os2->sFamilyClass >> 8) & 0xff) - 1) < 5) /* kiero: from ftmanager source. too lazy to google for it... */
1743 fcPatternAddInteger(pat, FC_SERIF, TRUE);
1747 if (os2 && os2->version != 0xffff)
1749 if (os2->usWeightClass == 0)
1751 else if (os2->usWeightClass < 150)
1752 weight = FC_WEIGHT_THIN;
1753 else if (os2->usWeightClass < 250)
1754 weight = FC_WEIGHT_EXTRALIGHT;
1755 else if (os2->usWeightClass < 350)
1756 weight = FC_WEIGHT_LIGHT;
1757 else if (os2->usWeightClass < 450)
1758 weight = FC_WEIGHT_REGULAR;
1759 else if (os2->usWeightClass < 550)
1760 weight = FC_WEIGHT_MEDIUM;
1761 else if (os2->usWeightClass < 650)
1762 weight = FC_WEIGHT_SEMIBOLD;
1763 else if (os2->usWeightClass < 750)
1764 weight = FC_WEIGHT_BOLD;
1765 else if (os2->usWeightClass < 850)
1766 weight = FC_WEIGHT_EXTRABOLD;
1767 else if (os2->usWeightClass < 925)
1768 weight = FC_WEIGHT_BLACK;
1769 else if (os2->usWeightClass < 1000)
1770 weight = FC_WEIGHT_EXTRABLACK;
1772 if ((FcDebug() & FC_DBG_SCANV) && weight != -1)
1773 kprintf ("\tos2 weight class %d maps to weight %d\n",
1774 os2->usWeightClass, weight);
1777 switch (os2->usWidthClass) {
1778 case 1: width = FC_WIDTH_ULTRACONDENSED; break;
1779 case 2: width = FC_WIDTH_EXTRACONDENSED; break;
1780 case 3: width = FC_WIDTH_CONDENSED; break;
1781 case 4: width = FC_WIDTH_SEMICONDENSED; break;
1782 case 5: width = FC_WIDTH_NORMAL; break;
1783 case 6: width = FC_WIDTH_SEMIEXPANDED; break;
1784 case 7: width = FC_WIDTH_EXPANDED; break;
1785 case 8: width = FC_WIDTH_EXTRAEXPANDED; break;
1786 case 9: width = FC_WIDTH_ULTRAEXPANDED; break;
1789 if ((FcDebug() & FC_DBG_SCANV) && width != -1)
1790 kprintf ("\tos2 width class %d maps to width %d\n",
1791 os2->usWidthClass, width);
1795 /* Type 1: Check for FontInfo dictionary information Code from g2@magestudios.net (Gerard Escalante) */
1797 #if HAVE_FT_GET_PS_FONT_INFO
1798 if (FT_Get_PS_Font_Info(face, &psfontinfo) == 0)
1800 if (weight == -1 && psfontinfo.weight)
1802 weight = FcIsWeight ((FcChar8 *) psfontinfo.weight);
1803 if (FcDebug() & FC_DBG_SCANV)
1804 kprintf ("\tType1 weight %s maps to %d\n",
1805 psfontinfo.weight, weight);
1811 #endif /* HAVE_FT_GET_PS_FONT_INFO */
1813 #if HAVE_FT_GET_BDF_PROPERTY
1815 if (width == -1)
1817 if (FT_Get_BDF_Property(face, "RELATIVE_SETWIDTH", &prop) == 0 &&
1818 (prop.type == BDF_PROPERTY_TYPE_INTEGER ||
1819 prop.type == BDF_PROPERTY_TYPE_CARDINAL))
1821 FT_Int32 value;
1823 if (prop.type == BDF_PROPERTY_TYPE_INTEGER)
1824 value = prop.u.integer;
1825 else
1826 value = (FT_Int32) prop.u.cardinal;
1827 switch ((value + 5) / 10) {
1828 case 1: width = FC_WIDTH_ULTRACONDENSED; break;
1829 case 2: width = FC_WIDTH_EXTRACONDENSED; break;
1830 case 3: width = FC_WIDTH_CONDENSED; break;
1831 case 4: width = FC_WIDTH_SEMICONDENSED; break;
1832 case 5: width = FC_WIDTH_NORMAL; break;
1833 case 6: width = FC_WIDTH_SEMIEXPANDED; break;
1834 case 7: width = FC_WIDTH_EXPANDED; break;
1835 case 8: width = FC_WIDTH_EXTRAEXPANDED; break;
1836 case 9: width = FC_WIDTH_ULTRAEXPANDED; break;
1839 if (width == -1 && FT_Get_BDF_Property (face, "SETWIDTH_NAME", &prop) == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM)
1841 width = FcIsWidth ((FcChar8 *) prop.u.atom);
1842 if (FcDebug () & FC_DBG_SCANV)
1843 kprintf ("\tsetwidth %s maps to %d\n", prop.u.atom, width);
1846 #endif
1848 /* Look for weight, width and slant names in the style value */
1849 for (st = 0;; st++)
1851 style = fcPatternGetString (pat, FC_STYLE, st);
1852 if (style == NULL)
1853 break;
1855 if (weight == -1)
1857 weight = FcContainsWeight (style);
1859 if (FcDebug() & FC_DBG_SCANV)
1860 kprintf ("\tStyle %s maps to weight %d\n", style, weight);
1863 if (width == -1)
1865 width = FcContainsWidth (style);
1866 if (FcDebug() & FC_DBG_SCANV)
1867 kprintf ("\tStyle %s maps to width %d\n", style, width);
1870 if (slant == -1)
1872 slant = FcContainsSlant (style);
1874 if (FcDebug() & FC_DBG_SCANV)
1875 kprintf ("\tStyle %s maps to slant %d\n", style, slant);
1879 /* Pull default values from the FreeType flags if more specific values not found above */
1880 if (slant == -1)
1882 slant = FC_SLANT_ROMAN;
1883 if (face->style_flags & FT_STYLE_FLAG_ITALIC)
1884 slant = FC_SLANT_ITALIC;
1887 if (weight == -1)
1889 weight = FC_WEIGHT_MEDIUM;
1890 if (face->style_flags & FT_STYLE_FLAG_BOLD)
1891 weight = FC_WEIGHT_BOLD;
1894 if (width == -1)
1895 width = FC_WIDTH_NORMAL;
1898 if (!fcPatternAddInteger (pat, FC_SLANT, slant))
1899 goto bail1;
1901 if (!fcPatternAddInteger (pat, FC_WEIGHT, weight))
1902 goto bail1;
1904 if (!fcPatternAddInteger (pat, FC_WIDTH, width))
1905 goto bail1;
1907 /* Compute the unicode coverage for the font */
1908 #if 0
1909 cs = FcFreeTypeCharSetAndSpacing (face, blanks, &spacing);
1910 if (!cs)
1911 goto bail1;
1914 #if HAVE_FT_GET_BDF_PROPERTY
1915 /* For PCF fonts, override the computed spacing with the one from the property */
1916 if(FT_Get_BDF_Property(face, "SPACING", &prop) == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM)
1918 if(!strcmp(prop.u.atom, "c") || !strcmp(prop.u.atom, "C"))
1919 spacing = FC_CHARCELL;
1920 else if(!strcmp(prop.u.atom, "m") || !strcmp(prop.u.atom, "M"))
1921 spacing = FC_MONO;
1922 else if(!strcmp(prop.u.atom, "p") || !strcmp(prop.u.atom, "P"))
1923 spacing = FC_PROPORTIONAL;
1925 #endif
1927 if (spacing != FC_PROPORTIONAL)
1928 if (!fcPatternAddInteger (pat, FC_SPACING, spacing))
1929 goto bail2;
1931 #endif
1933 /* Skip over PCF fonts that have no encoded characters; they're
1934 * usually just Unicode fonts transcoded to some legacy encoding
1935 * FT forces us to approximate whether a font is a PCF font
1936 * or not by whether it has any BDF properties. Try PIXEL_SIZE;
1937 * I don't know how to get a list of BDF properties on the font. -PL
1939 #if 0
1940 if (FcCharSetCount (cs) == 0)
1942 #if HAVE_FT_GET_BDF_PROPERTY
1943 if(FT_Get_BDF_Property(face, "PIXEL_SIZE", &prop) == 0)
1944 goto bail2;
1945 #endif
1948 ls = FcFreeTypeLangSet (cs, exclusiveLang);
1949 if (!ls)
1950 goto bail2;
1952 if (!fcPatternAddLangSet (pat, FC_LANG, ls))
1954 FcLangSetDestroy (ls);
1955 goto bail2;
1958 FcLangSetDestroy (ls);
1961 /* Drop our reference to the charset */
1962 FcCharSetDestroy (cs);
1963 #endif
1965 return pat;
1967 bail2:
1969 #if 0
1970 FcCharSetDestroy (cs);
1971 #endif
1972 bail1:
1974 fcPatternDestroy (pat);
1975 bail0:
1977 return NULL;
1980 struct fontcache
1982 int valid;
1983 struct List entries;
1988 static struct fontpattern *fcQueryFont(char *fname, int id, int *count)
1990 FT_Face face;
1991 struct fontpattern *pat = NULL;
1993 if (FT_New_Face(ftLibrary, fname, id, &face))
1995 D(kprintf("failed to open tt font:%s, %d\n", fname, id));
1996 goto bail;
1998 *count = face->num_faces;
2000 pat = fcQueryFace(face, fname, id);
2002 FT_Done_Face(face);
2003 bail:
2005 return pat;
2009 #endif
2012 static DirectoryTraverseResult callback(struct FileInfoBlock *fib, char *path, int level, void *data)
2014 struct fontcache *cache = (struct fontcache*)data;
2015 int ccount;
2017 if (strMatch(path, "#?.(ttf|pfb)"))
2019 struct fontpattern *pat;
2020 if (FcDebug () & FC_DBG_SCANV)
2021 kprintf("scanning:%s\n", path);
2022 pat = fcQueryFont(path, 0, &ccount);
2023 if (FcDebug () & FC_DBG_SCANV)
2024 kprintf("scanning:%s done. pattern:%p\n", path, pat);
2026 if (pat != NULL)
2027 ADDTAIL(&cache->entries, pat);
2028 //else (don't abort scanning. ikn future add different error codes to distinguish between lack of memory and broken font files)
2029 // return DIRECTORY_TRAVERSE_ABORT;
2032 return DIRECTORY_TRAVERSE_CONTINUE;
2035 void fcDestroy(struct fontcache *cache)
2037 /* TODO. not really high priority as it will be dispose anyway */
2040 struct fontcache *fcCreate(char *directories[])
2042 struct fontcache *cache = calloc(1, sizeof(*cache));
2043 NewList(&cache->entries);
2045 if (FcDebug () & FC_DBG_SCANV)
2046 kprintf("FCCache: Initialize cache system...\n");
2048 if (!FT_Init_FreeType(&ftLibrary))
2050 while(*directories)
2052 char *dir = *directories++;
2053 BPTR dirlock = Lock(dir, ACCESS_READ);
2055 if (dirlock != NULL)
2057 int result;
2059 UnLock(dirlock);
2060 result = directoryTraverse(dir, DIRECTORY_SCAN_RECURSIVE, callback, cache);
2062 if (result != DIRECTORY_TRAVERSE_OK)
2064 fcDestroy(cache);
2065 cache = NULL;
2066 break;
2071 FT_Done_FreeType(ftLibrary);
2073 else
2075 D(kprintf("**********ERROR: Failed to initiclize freetype library\n"));
2077 return cache;
2080 struct fontpattern *fcMatch(struct fontcache *cache, struct fontpattern *pat, int *matchingcriteria)
2082 struct fontpattern *cpat;
2083 struct fontpattern *bestmatch = NULL;
2084 int bestmatchweight = 0;
2086 /* Find best match by calcularing weighted compatibility value */
2088 ITERATELIST(cpat, &cache->entries)
2090 struct patternentry *cpe, *pe;
2091 int cmatchingcriteria[FC_LAST_CRITERIA] = {0};
2092 int weight = 0;
2094 ITERATELIST(pe, &pat->entries) /* pe - for each entry in criteria pattern. assume that caller is not stupid and doesn't pass elements with 0-weight */
2096 ITERATELIST(cpe, &cpat->entries) /* cpe - for each entry in pattern in cache */
2098 int match = FALSE;
2100 if (cpe->element == pe->element)
2102 /* first go special elements */
2104 if (cpe->element == FC_FILE)
2106 char *filepart = FilePart(cpe->value.s);
2107 if (filepart != NULL) /* paranoid? */
2109 if (0 == stricmp(filepart, pe->value.s))
2110 match = TRUE;
2113 else /* then generic attributes */
2116 if (cpe->type == FC_ETYPE_STRING)
2118 /* TODO: make all strings uppercase and kill blanks */
2119 if (0 == FcStrCmpIgnoreBlanksAndCase(cpe->value.s, pe->value.s))
2121 match = TRUE;
2124 else if (cpe->type == FC_ETYPE_INTEGER)
2126 if (cpe->value.i == pe->value.i)
2128 match = TRUE;
2134 if (match)
2136 if (pe->excluding) /* if the match was found and the criteria is excluding we lower the score */
2138 /* if any attribute did match earlier then we don't go below 1 as it still matches better than font with zero matches */
2139 weight -= fcelementpriority[cpe->element];
2141 else
2143 /* if only excluding attributes were found earlier (<0) then we automaticly bump it to be >0 */
2144 weight += fcelementpriority[cpe->element];
2145 if (weight < 0)
2146 weight = 1;
2148 cmatchingcriteria[cpe->element] = TRUE;
2151 break;
2156 if (weight > bestmatchweight)
2158 bestmatch = cpat;
2159 bestmatchweight = weight;
2160 if (matchingcriteria != NULL)
2161 memcpy(matchingcriteria, cmatchingcriteria, sizeof(cmatchingcriteria));
2165 /* we can still land with no font matching! do we need some fallback? */
2167 if (bestmatch == NULL)
2169 if (FcDebug () & FC_DBG_SCANV)
2170 kprintf("*****ERROR: No match for pattern\n");
2173 return bestmatch;
2176 static int writeint(FILE *f, int val)
2178 return fwrite(&val, sizeof(val), 1, f);
2181 static int writestring(FILE *f, char *str)
2183 int l = strlen(str);
2184 int rc = writeint(f, l + 1);
2185 if (rc)
2186 rc = fwrite(str, l + 1, 1, f);
2188 return rc;
2191 int fcSave(struct fontcache *fontcache, char *fname)
2193 struct fontpattern *pat;
2194 FILE *f = fopen(fname, "w");
2196 if (f == NULL)
2197 return FALSE;
2199 D(kprintf("writting fontcache to %s\n", fname));
2201 /* write some header + version number */
2203 fprintf(f, "FCDTVER1");
2205 /* now for each pattern */
2207 ITERATELIST(pat, &fontcache->entries)
2209 struct patternentry *pe;
2210 int elements = 0;
2212 /* what we do here:
2213 * write number of entries for pattern
2214 * for each pattern entry:
2215 * write element
2216 * write id
2217 * write type
2218 * for int: write value
2219 * for string: write lenght including null termination
2220 * write string contents including null termination
2223 ListLength(&pat->entries, elements);
2224 writeint(f, elements);
2226 ITERATELIST(pe, &pat->entries)
2228 writeint(f, pe->element);
2229 writeint(f, pe->id);
2230 writeint(f, pe->type);
2231 if (pe->type == FC_ETYPE_STRING)
2232 writestring(f, pe->value.s);
2233 else
2234 writeint(f, pe->value.i);
2240 fclose(f);
2241 return TRUE;
2244 static int readint(FILE *f)
2246 int val = 0;
2247 fread(&val, sizeof(val), 1, f);
2248 return val;
2251 static char *readstring(FILE *f)
2253 int l = readint(f);
2254 char *val;
2256 assert(l > 0);
2258 val = malloc(l);
2259 if (val == NULL)
2260 return NULL;
2262 fread(val, l, 1, f);
2263 return val;
2266 struct fontcache *fcLoad(char *fname)
2268 FILE *f;
2269 char header[8];
2270 struct fontcache *fontcache;
2272 f = fopen(fname, "r");
2273 if (f == NULL)
2274 return NULL;
2276 fontcache = calloc(1, sizeof(*fontcache));
2278 if (fontcache == NULL)
2280 fclose(f);
2281 return NULL;
2284 NewList(&fontcache->entries);
2285 fread(header, sizeof(header), 1, f);
2287 if (memcmp(header, "FCDTVER1", sizeof(header)))
2289 fclose(f);
2290 fcDestroy(fontcache);
2291 return NULL;
2294 D(kprintf("loading font cache from %s\n", fname));
2296 for(;;)
2298 struct fontpattern *pat;
2299 int entries = readint(f);
2300 if (entries == 0) /* this means end of stream here */
2301 break;
2303 pat = fcPatternAlloc();
2304 if (pat != NULL)
2306 int i;
2307 for(i=0; i<entries; i++)
2309 int element = readint(f);
2310 int id = readint(f);
2311 int type = readint(f);
2312 union patternvalue val;
2313 if (type == FC_ETYPE_STRING)
2314 val.s = readstring(f);
2315 else
2316 val.i = readint(f);
2318 fcPatternAddEntryRaw(pat, element, type, &val, id);
2321 ADDTAIL(&fontcache->entries, pat);
2323 else
2325 break;
2330 fclose(f);
2331 return fontcache;
2334 int fcAddPattern(struct fontcache *fontcache, struct fontpattern *pat)
2336 if (fontcache != NULL && pat != NULL)
2338 ADDTAIL(&fontcache->entries, pat);
2339 return TRUE;
2341 return FALSE;
2345 #ifdef STANDALONE
2346 int main(void)
2349 struct Task *this = FindTask(NULL);
2350 this->tc_ETask->MaxHits = 1;
2357 /* scan all fonts installed in any given user directory */
2359 char *dirs[] = {"sys:fonts", "mossys:fonts", NULL};
2361 struct fontcache *cache = fcCreate(dirs);
2363 fcSave(cache, "ram:cache1");
2364 cache = fcLoad("ram:cache1");
2365 fcSave(cache, "ram:cache2");
2367 /* try to match simple slanted font */
2369 if (cache != NULL)
2371 struct fontpattern *pat = fcPatternAlloc();
2372 struct fontpattern *cpat;
2374 fcPatternAddString(pat, FC_FAMILY, "Times");
2375 //fcPatternAddString(pat, FC_FILE, "n019003l.pfb");
2377 cpat = fcMatch(cache, pat, NULL);
2378 if (cpat != NULL)
2380 char *name = fcPatternGetString(cpat, FC_FILE, 0);
2381 char *family = fcPatternGetString(cpat, FC_FAMILY, 0);
2383 else
2388 if (cache != NULL)
2390 struct fontpattern *pat = fcPatternAlloc();
2391 struct fontpattern *cpat;
2393 //fcPatternAddString(pat, FC_FAMILY, "Helvetica");
2394 fcPatternAddString(pat, FC_FILE, "n019003l.pfb");
2396 cpat = fcMatch(cache, pat, NULL);
2397 if (cpat != NULL)
2399 char *name = fcPatternGetString(cpat, FC_FILE, 0);
2400 char *family = fcPatternGetString(cpat, FC_FAMILY, 0);
2402 else
2414 return 0;
2416 #endif
2419 static FcChar32 FcFreeTypePrivateToUcs4 (FcChar32 private, const FcCharMap *map)
2421 int i;
2423 for (i = 0; i < map->nent; i++)
2424 if (map->ent[i].encode == private)
2425 return (FcChar32) map->ent[i].bmp;
2426 return ~0;