]> git.wh0rd.org Git - fontconfig.git/blob - src/fcfreetype.c
Fix build error with BDF prop local. Free langset after query
[fontconfig.git] / src / fcfreetype.c
1 /*
2  * $RCSId: xc/lib/fontconfig/src/fcfreetype.c,v 1.11 2002/08/31 22:17:32 keithp Exp $
3  *
4  * Copyright © 2001 Keith Packard
5  *
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.
15  *
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.
23  */
24
25 /*
26   Copyright © 2002-2003 by Juliusz Chroboczek
27
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:
34
35   The above copyright notice and this permission notice shall be included in
36   all copies or substantial portions of the Software.
37
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
44   THE SOFTWARE.
45 */
46
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include "fcint.h"
51 #include <freetype/freetype.h>
52 #include <freetype/internal/ftobjs.h>
53 #include <freetype/tttables.h>
54 #include <freetype/ftsnames.h>
55 #include <freetype/ttnameid.h>
56 #include <freetype/t1tables.h>
57
58 #if (FREETYPE_MINOR > 1 || (FREETYPE_MINOR == 1 && FREETYPE_PATCH >= 4))
59 #include <freetype/ftbdf.h>
60 #include <freetype/ftmodule.h>
61 #define USE_FTBDF
62 #define HAS_BDF_PROPERTY(f) ((f) && (f)->driver && \
63                              (f)->driver->root.clazz->get_interface)
64 #define MY_Get_BDF_Property(f,n,p) (HAS_BDF_PROPERTY(f) ? \
65                                     FT_Get_BDF_Property(f,n,p) : \
66                                     FT_Err_Invalid_Argument)
67 #endif
68
69
70 /*
71  * Keep Han languages separated by eliminating languages
72  * that the codePageRange bits says aren't supported
73  */
74
75 static const struct {
76     int             bit;
77     const FcChar8   *lang;
78 } FcCodePageRange[] = {
79     { 17,       (const FcChar8 *) "ja" },
80     { 18,       (const FcChar8 *) "zh-cn" },
81     { 19,       (const FcChar8 *) "ko" },
82     { 20,       (const FcChar8 *) "zh-tw" },
83 };
84
85 #define NUM_CODE_PAGE_RANGE (sizeof FcCodePageRange / sizeof FcCodePageRange[0])
86
87 FcBool
88 FcFreeTypeIsExclusiveLang (const FcChar8  *lang)
89 {
90     int     i;
91
92     for (i = 0; i < NUM_CODE_PAGE_RANGE; i++)
93     {
94         if (FcLangCompare (lang, FcCodePageRange[i].lang) != FcLangDifferentLang)
95             return FcTrue;
96     }
97     return FcFalse;
98 }
99
100 #define FC_NAME_PRIO_LANG           0x0f00
101 #define FC_NAME_PRIO_LANG_ENGLISH   0x0200
102 #define FC_NAME_PRIO_LANG_LATIN     0x0100
103 #define FC_NAME_PRIO_LANG_NONE      0x0000
104
105 #define FC_NAME_PRIO_ENC            0x00f0
106 #define FC_NAME_PRIO_ENC_UNICODE    0x0010
107 #define FC_NAME_PRIO_ENC_NONE       0x0000
108
109 #define FC_NAME_PRIO_NAME           0x000f
110 #define FC_NAME_PRIO_NAME_FAMILY    0x0002
111 #define FC_NAME_PRIO_NAME_PS        0x0001
112 #define FC_NAME_PRIO_NAME_NONE      0x0000
113
114 static FcBool
115 FcUcs4IsLatin (FcChar32 ucs4)
116 {
117     FcChar32    page = ucs4 >> 8;
118     
119     if (page <= 2)
120         return FcTrue;
121     if (page == 0x1e)
122         return FcTrue;
123     if (0x20 <= page && page <= 0x23)
124         return FcTrue;
125     if (page == 0xfb)
126         return FcTrue;
127     /* halfwidth forms, don't include kana or white parens */
128     if (0xff01 <= ucs4 && ucs4 <= 0xff5e)
129         return FcTrue;
130     return FcFalse;
131 }
132
133 static FcBool
134 FcUtf8IsLatin (FcChar8 *str, int len)
135 {
136     while (len)
137     {
138         FcChar32    ucs4;
139         int         clen = FcUtf8ToUcs4 (str, &ucs4, len);
140         if (clen <= 0)
141             return FcFalse;
142         if (!FcUcs4IsLatin (ucs4))
143             return FcFalse;
144         len -= clen;
145         str += clen;
146     }
147     return FcTrue;
148 }
149
150 /* Order is significant.  For example, some B&H fonts are hinted by
151    URW++, and both strings appear in the notice. */
152
153 static const struct {
154     const FcChar8   *notice;
155     const FcChar8   *foundry;
156 } FcNoticeFoundries[] = {
157     { (const FcChar8*) "Bigelow",       (const FcChar8 *) "b&h" },
158     { (const FcChar8*) "Adobe",         (const FcChar8 *) "adobe" },
159     { (const FcChar8*) "Bitstream",     (const FcChar8 *) "bitstream" },
160     { (const FcChar8*) "Monotype",      (const FcChar8 *) "monotype" },
161     { (const FcChar8*) "Linotype",      (const FcChar8 *) "linotype" },
162     { (const FcChar8*) "LINOTYPE-HELL", (const FcChar8 *) "linotype" },
163     { (const FcChar8*) "IBM",           (const FcChar8 *) "ibm" },
164     { (const FcChar8*) "URW",           (const FcChar8 *) "urw" },
165     { (const FcChar8*) "International Typeface Corporation", 
166                                         (const FcChar8 *) "itc" },
167     { (const FcChar8*) "Tiro Typeworks",(const FcChar8 *) "tiro" },
168     { (const FcChar8*) "XFree86",       (const FcChar8 *) "xfree86" },
169     { (const FcChar8*) "Microsoft",     (const FcChar8 *) "microsoft" },
170     { (const FcChar8*) "Omega",         (const FcChar8 *) "omega" },
171     { (const FcChar8*) "Font21",        (const FcChar8 *) "hwan" },
172     { (const FcChar8*) "HanYang System",(const FcChar8 *) "hanyang" }
173 };
174
175 #define NUM_NOTICE_FOUNDRIES    (sizeof (FcNoticeFoundries) / sizeof (FcNoticeFoundries[0]))
176
177 static const FcChar8 *
178 FcNoticeFoundry(const char *notice)
179 {
180     int i;
181
182     if (notice)
183         for(i = 0; i < NUM_NOTICE_FOUNDRIES; i++)
184             if (strstr ((const char *) notice, (const char *) FcNoticeFoundries[i].notice))
185                 return FcNoticeFoundries[i].foundry;
186     return 0;
187 }
188
189 static FcBool
190 FcVendorMatch(const char *vendor, const char *vendor_string)
191 {
192     /* vendor is not necessarily NUL-terminated. */
193     int i, len;
194     
195     len = strlen(vendor_string);
196     if (memcmp(vendor, vendor_string, len) != 0)
197         return FcFalse;
198     for (i = len; i < 4; i++)
199         if (vendor[i] != ' ' && vendor[i] != '\0')
200             return FcFalse;
201     return FcTrue;
202 }
203
204 /* This table is partly taken from ttmkfdir by Joerg Pommnitz. */
205
206 /* It should not contain useless entries (such as UNKN) nor duplicate
207    entries for padding both with spaces and NULs. */
208
209 static const struct {
210     const FcChar8   *vendor;
211     const FcChar8   *foundry;
212 } FcVendorFoundries[] = {
213     { (const FcChar8*) "ADBE", (const FcChar8 *) "adobe"},
214     { (const FcChar8*) "AGFA", (const FcChar8 *) "agfa"},
215     { (const FcChar8*) "ALTS", (const FcChar8 *) "altsys"},
216     { (const FcChar8*) "APPL", (const FcChar8 *) "apple"},
217     { (const FcChar8*) "ARPH", (const FcChar8 *) "arphic"},
218     { (const FcChar8*) "ATEC", (const FcChar8 *) "alltype"},
219     { (const FcChar8*) "B&H",  (const FcChar8 *) "b&h"},
220     { (const FcChar8*) "BITS", (const FcChar8 *) "bitstream"},
221     { (const FcChar8*) "CANO", (const FcChar8 *) "cannon"},
222     { (const FcChar8*) "DYNA", (const FcChar8 *) "dynalab"},
223     { (const FcChar8*) "EPSN", (const FcChar8 *) "epson"},
224     { (const FcChar8*) "FJ",   (const FcChar8 *) "fujitsu"},
225     { (const FcChar8*) "IBM",  (const FcChar8 *) "ibm"},
226     { (const FcChar8*) "ITC",  (const FcChar8 *) "itc"},
227     { (const FcChar8*) "IMPR", (const FcChar8 *) "impress"},
228     { (const FcChar8*) "LARA", (const FcChar8 *) "larabiefonts"},
229     { (const FcChar8*) "LEAF", (const FcChar8 *) "interleaf"},
230     { (const FcChar8*) "LETR", (const FcChar8 *) "letraset"},
231     { (const FcChar8*) "LINO", (const FcChar8 *) "linotype"},
232     { (const FcChar8*) "MACR", (const FcChar8 *) "macromedia"},
233     { (const FcChar8*) "MONO", (const FcChar8 *) "monotype"},
234     { (const FcChar8*) "MS",   (const FcChar8 *) "microsoft"},
235     { (const FcChar8*) "MT",   (const FcChar8 *) "monotype"},
236     { (const FcChar8*) "NEC",  (const FcChar8 *) "nec"},
237     { (const FcChar8*) "PARA", (const FcChar8 *) "paratype"},
238     { (const FcChar8*) "QMSI", (const FcChar8 *) "qms"},
239     { (const FcChar8*) "RICO", (const FcChar8 *) "ricoh"},
240     { (const FcChar8*) "URW",  (const FcChar8 *) "urw"},
241     { (const FcChar8*) "Y&Y",  (const FcChar8 *) "y&y"}
242 };
243
244 #define NUM_VENDOR_FOUNDRIES    (sizeof (FcVendorFoundries) / sizeof (FcVendorFoundries[0]))
245
246 static const FcChar8 *
247 FcVendorFoundry(const char *vendor)
248 {
249     int i;
250     
251     if (vendor)
252         for(i = 0; i < NUM_VENDOR_FOUNDRIES; i++)
253             if (FcVendorMatch (vendor, FcVendorFoundries[i].vendor))
254                 return FcVendorFoundries[i].foundry;
255     return 0;
256 }
257
258 typedef struct _FcStringConst {
259     const char  *name;
260     int         value;
261 } FcStringConst;
262
263 static int
264 FcStringIsConst (const FcChar8          *string,
265                  const FcStringConst    *c,
266                  int                    nc)
267 {
268     int i;
269
270     for (i = 0; i < nc; i++)
271         if (FcStrCmpIgnoreBlanksAndCase (string, c[i].name) == 0)
272             return c[i].value;
273     return -1;
274 }
275
276 static int
277 FcStringContainsConst (const FcChar8        *string,
278                        const FcStringConst  *c,
279                        int                  nc)
280 {
281     int i;
282
283     for (i = 0; i < nc; i++)
284         if (FcStrContainsIgnoreBlanksAndCase (string, c[i].name))
285             return c[i].value;
286     return -1;
287 }
288
289 static const FcStringConst  weightConsts[] = {
290     { "thin",           FC_WEIGHT_THIN },
291     { "extralight",     FC_WEIGHT_EXTRALIGHT },
292     { "ultralight",     FC_WEIGHT_ULTRALIGHT },
293     { "light",          FC_WEIGHT_LIGHT },
294     { "book",           FC_WEIGHT_BOOK },
295     { "regular",        FC_WEIGHT_REGULAR },
296     { "normal",         FC_WEIGHT_NORMAL },
297     { "medium",         FC_WEIGHT_MEDIUM },
298     { "demibold",       FC_WEIGHT_DEMIBOLD },
299     { "demi",           FC_WEIGHT_DEMIBOLD },
300     { "semibold",       FC_WEIGHT_SEMIBOLD },
301     { "bold",           FC_WEIGHT_BOLD },
302     { "extrabold",      FC_WEIGHT_EXTRABOLD },
303     { "ultrabold",      FC_WEIGHT_ULTRABOLD },
304     { "black",          FC_WEIGHT_BLACK },
305     { "heavy",          FC_WEIGHT_HEAVY },
306 };
307
308 #define NUM_WEIGHT_CONSTS  (sizeof (weightConsts) / sizeof (weightConsts[0]))
309
310 #define FcIsWeight(s)       FcStringIsConst(s,weightConsts,NUM_WEIGHT_CONSTS)
311 #define FcContainsWeight(s) FcStringContainsConst (s,weightConsts,NUM_WEIGHT_CONSTS)
312
313 static const FcStringConst  widthConsts[] = {
314     { "ultracondensed", FC_WIDTH_ULTRACONDENSED },
315     { "extracondensed", FC_WIDTH_EXTRACONDENSED },
316     { "semicondensed",  FC_WIDTH_SEMICONDENSED },
317     { "condensed",      FC_WIDTH_CONDENSED },   /* must be after *condensed */
318     { "normal",         FC_WIDTH_NORMAL },
319     { "semiexpanded",   FC_WIDTH_SEMIEXPANDED },
320     { "extraexpanded",  FC_WIDTH_EXTRAEXPANDED },
321     { "ultraexpanded",  FC_WIDTH_ULTRAEXPANDED },
322     { "expanded",       FC_WIDTH_EXPANDED },    /* must be after *expanded */
323 };
324
325 #define NUM_WIDTH_CONSTS    (sizeof (widthConsts) / sizeof (widthConsts[0]))
326
327 #define FcIsWidth(s)        FcStringIsConst(s,widthConsts,NUM_WIDTH_CONSTS)
328 #define FcContainsWidth(s)  FcStringContainsConst (s,widthConsts,NUM_WIDTH_CONSTS)
329
330 static const FcStringConst  slantConsts[] = {
331     { "italic",         FC_SLANT_ITALIC },
332     { "oblique",        FC_SLANT_OBLIQUE },
333 };
334
335 #define NUM_SLANT_CONSTS    (sizeof (slantConsts) / sizeof (slantConsts[0]))
336
337 #define FcIsSlant(s)        FcStringIsConst(s,slantConsts,NUM_SLANT_CONSTS)
338 #define FcContainsSlant(s)  FcStringContainsConst (s,slantConsts,NUM_SLANT_CONSTS)
339
340 FcPattern *
341 FcFreeTypeQuery (const FcChar8  *file,
342                  int            id,
343                  FcBlanks       *blanks,
344                  int            *count)
345 {
346     FT_Face         face;
347     FcPattern       *pat;
348     int             slant = -1;
349     int             weight = -1;
350     int             width = -1;
351     int             i;
352     FcCharSet       *cs;
353     FcLangSet       *ls;
354     FT_Library      ftLibrary;
355     FcChar8         *family = 0;
356     FcChar8         *style = 0;
357     const FcChar8   *foundry = 0;
358     int             spacing;
359     TT_OS2          *os2;
360     PS_FontInfoRec  psfontinfo;
361 #ifdef USE_FTBDF
362     BDF_PropertyRec prop;
363 #endif
364     TT_Header       *head;
365     const FcChar8   *exclusiveLang = 0;
366     FT_SfntName     sname;
367     FT_UInt         snamei, snamec;
368     FcBool          family_allocated = FcFalse;
369     FcBool          style_allocated = FcFalse;
370     int             family_prio = 0;
371     int             style_prio = 0;
372
373     if (FT_Init_FreeType (&ftLibrary))
374         return 0;
375     
376     if (FT_New_Face (ftLibrary, (char *) file, id, &face))
377         goto bail;
378
379     *count = face->num_faces;
380
381     pat = FcPatternCreate ();
382     if (!pat)
383         goto bail0;
384
385     if (!FcPatternAddBool (pat, FC_OUTLINE,
386                            (face->face_flags & FT_FACE_FLAG_SCALABLE) != 0))
387         goto bail1;
388
389     if (!FcPatternAddBool (pat, FC_SCALABLE,
390                            (face->face_flags & FT_FACE_FLAG_SCALABLE) != 0))
391         goto bail1;
392
393
394     /*
395      * Get the OS/2 table
396      */
397     os2 = (TT_OS2 *) FT_Get_Sfnt_Table (face, ft_sfnt_os2);
398
399     /*
400      * Look first in the OS/2 table for the foundry, if
401      * not found here, the various notices will be searched for
402      * that information, either from the sfnt name tables or
403      * the Postscript FontInfo dictionary.  Finally, the
404      * BDF properties will queried.
405      */
406     
407     if (os2 && os2->version >= 0x0001 && os2->version != 0xffff)
408         foundry = FcVendorFoundry(os2->achVendID);
409
410     /*
411      * Grub through the name table looking for family
412      * and style names.  FreeType makes quite a hash
413      * of them
414      */
415     snamec = FT_Get_Sfnt_Name_Count (face);
416     for (snamei = 0; snamei < snamec; snamei++)
417     {
418         FcChar8         *utf8;
419         int             len;
420         int             wchar;
421         FcChar8         *src;
422         int             src_len;
423         FcChar8         *u8;
424         FcChar32        ucs4;
425         int             ilen, olen;
426         int             prio = 0;
427         
428         const FcCharMap *map;
429         enum {
430             FcNameEncodingUtf16, 
431             FcNameEncodingAppleRoman,
432             FcNameEncodingLatin1 
433         } encoding;
434         
435         
436         if (FT_Get_Sfnt_Name (face, snamei, &sname) != 0)
437             break;
438         
439         /*
440          * Look for Unicode strings
441          */
442         switch (sname.platform_id) {
443         case TT_PLATFORM_APPLE_UNICODE:
444             /*
445              * All APPLE_UNICODE encodings are Utf16 BE
446              *
447              * Because there's no language id for Unicode,
448              * assume it's English
449              */
450             prio |= FC_NAME_PRIO_LANG_ENGLISH;
451             prio |= FC_NAME_PRIO_ENC_UNICODE;
452             encoding = FcNameEncodingUtf16;
453             break;
454         case TT_PLATFORM_MACINTOSH:
455             switch (sname.encoding_id) {
456             case TT_MAC_ID_ROMAN:
457                 encoding = FcNameEncodingAppleRoman;
458                 break;
459             default:
460                 continue;
461             }
462             switch (sname.language_id) {
463             case TT_MAC_LANGID_ENGLISH:
464                 prio |= FC_NAME_PRIO_LANG_ENGLISH;
465                 break;
466             default:
467                 /*
468                  * Sometimes Microsoft language ids
469                  * end up in the macintosh table.  This
470                  * is often accompanied by data in
471                  * some mystic encoding.  Ignore these names
472                  */
473                 if (sname.language_id >= 0x100)
474                     continue;
475                 break;
476             }
477             break;
478         case TT_PLATFORM_MICROSOFT:
479             switch (sname.encoding_id) {
480             case TT_MS_ID_UNICODE_CS:
481                 encoding = FcNameEncodingUtf16;
482                 prio |= FC_NAME_PRIO_ENC_UNICODE;
483                 break;
484             default:
485                 continue;
486             }
487             switch (sname.language_id & 0xff) {
488             case 0x09:
489                 prio |= FC_NAME_PRIO_LANG_ENGLISH;
490                 break;
491             default:
492                 break;
493             }
494             break;
495         case TT_PLATFORM_ISO:
496             switch (sname.encoding_id) {
497             case TT_ISO_ID_10646:
498                 encoding = FcNameEncodingUtf16;
499                 prio |= FC_NAME_PRIO_ENC_UNICODE;
500                 break;
501             case TT_ISO_ID_7BIT_ASCII:
502             case TT_ISO_ID_8859_1:
503                 encoding = FcNameEncodingLatin1;
504                 break;
505             default:
506                 continue;
507             }
508             break;
509         default:
510             continue;
511         }
512         
513         /*
514          * Look for family and style names 
515          */
516         switch (sname.name_id) {
517         case TT_NAME_ID_FONT_FAMILY:
518             prio |= FC_NAME_PRIO_NAME_FAMILY;
519             break;
520         case TT_NAME_ID_PS_NAME:
521             prio |= FC_NAME_PRIO_NAME_PS;
522             break;
523         case TT_NAME_ID_FONT_SUBFAMILY:
524         case TT_NAME_ID_TRADEMARK:
525         case TT_NAME_ID_MANUFACTURER:
526             break;
527         default:
528             continue;
529         }
530             
531         src = (FcChar8 *) sname.string;
532         src_len = sname.string_len;
533         
534         switch (encoding) {
535         case FcNameEncodingUtf16:
536             /*
537              * Convert Utf16 to Utf8
538              */
539             
540             if (!FcUtf16Len (src, FcEndianBig, src_len, &len, &wchar))
541                 continue;
542     
543             /*
544              * Allocate plenty of space.  Freed below
545              */
546             utf8 = malloc (len * FC_UTF8_MAX_LEN + 1);
547             if (!utf8)
548                 continue;
549                 
550             u8 = utf8;
551             
552             while ((ilen = FcUtf16ToUcs4 (src, FcEndianBig, &ucs4, src_len)) > 0)
553             {
554                 src_len -= ilen;
555                 src += ilen;
556                 olen = FcUcs4ToUtf8 (ucs4, u8);
557                 u8 += olen;
558             }
559             *u8 = '\0';
560             break;
561         case FcNameEncodingLatin1:
562             /*
563              * Convert Latin1 to Utf8. Freed below
564              */
565             utf8 = malloc (src_len * 2 + 1);
566             if (!utf8)
567                 continue;
568
569             u8 = utf8;
570             while (src_len > 0)
571             {
572                 ucs4 = *src++;
573                 src_len--;
574                 olen = FcUcs4ToUtf8 (ucs4, u8);
575                 u8 += olen;
576             }
577             *u8 = '\0';
578             break;
579         case FcNameEncodingAppleRoman:
580             /*
581              * Convert AppleRoman to Utf8
582              */
583             map = FcFreeTypeGetPrivateMap (ft_encoding_apple_roman);
584             if (!map)
585                 continue;
586
587             /* freed below */
588             utf8 = malloc (src_len * 3 + 1);
589             if (!utf8)
590                 continue;
591
592             u8 = utf8;
593             while (src_len > 0)
594             {
595                 ucs4 = FcFreeTypePrivateToUcs4 (*src++, map);
596                 src_len--;
597                 olen = FcUcs4ToUtf8 (ucs4, u8);
598                 u8 += olen;
599             }
600             *u8 = '\0';
601             break;
602         default:
603             continue;
604         }
605         if ((prio & FC_NAME_PRIO_LANG) == FC_NAME_PRIO_LANG_NONE)
606             if (FcUtf8IsLatin (utf8, strlen ((char *) utf8)))
607                 prio |= FC_NAME_PRIO_LANG_LATIN;
608                                
609         if (FcDebug () & FC_DBG_SCANV)
610             printf ("\nfound name (name %d platform %d encoding %d language 0x%x prio 0x%x) %s\n",
611                     sname.name_id, sname.platform_id,
612                     sname.encoding_id, sname.language_id,
613                     prio, utf8);
614     
615         switch (sname.name_id) {
616         case TT_NAME_ID_FONT_FAMILY:
617         case TT_NAME_ID_PS_NAME:
618             if (!family || prio > family_prio)
619             {
620                 if (family)
621                     free (family);
622                 family = utf8;
623                 utf8 = 0;
624                 family_allocated = FcTrue;
625                 family_prio = prio;
626             }
627             break;
628         case TT_NAME_ID_FONT_SUBFAMILY:
629             if (!style || prio > style_prio)
630             {
631                 if (style)
632                     free (style);
633                 style = utf8;
634                 utf8 = 0;
635                 style_allocated = FcTrue;
636                 style_prio = prio;
637             }
638             break;
639         case TT_NAME_ID_TRADEMARK:
640         case TT_NAME_ID_MANUFACTURER:
641             /* If the foundry wasn't found in the OS/2 table, look here */
642             if(!foundry)
643                 foundry = FcNoticeFoundry(utf8);
644             break;
645         }
646         if (utf8)
647             free (utf8);
648     }
649     
650     if (!family)
651         family = (FcChar8 *) face->family_name;
652     
653     if (!style)
654         style = (FcChar8 *) face->style_name;
655     
656     if (!family)
657     {
658         FcChar8 *start, *end;
659         
660         start = (FcChar8 *) strrchr ((char *) file, '/');
661         if (start)
662             start++;
663         else
664             start = (FcChar8 *) file;
665         end = (FcChar8 *) strrchr ((char *) start, '.');
666         if (!end)
667             end = start + strlen ((char *) start);
668         /* freed below */
669         family = malloc (end - start + 1);
670         strncpy ((char *) family, (char *) start, end - start);
671         family[end - start] = '\0';
672         family_allocated = FcTrue;
673     }
674
675     if (FcDebug() & FC_DBG_SCAN)
676         printf ("\n\"%s\" \"%s\"\n", family, style ? style : (FcChar8 *) "<none>");
677
678     if (!FcPatternAddString (pat, FC_FAMILY, family))
679         goto bail1;
680
681     if (style)
682     {
683         if (!FcPatternAddString (pat, FC_STYLE, style))
684             goto bail1;
685     }
686
687     if (!FcPatternAddString (pat, FC_FILE, file))
688         goto bail1;
689
690     if (!FcPatternAddInteger (pat, FC_INDEX, id))
691         goto bail1;
692
693     if (!FcPatternAddString (pat, FC_SOURCE, (FcChar8 *) "FreeType"))
694         goto bail1;
695
696 #if 0
697     /*
698      * don't even try this -- CJK 'monospace' fonts are really
699      * dual width, and most other fonts don't bother to set
700      * the attribute.  Sigh.
701      */
702     if ((face->face_flags & FT_FACE_FLAG_FIXED_WIDTH) != 0)
703         if (!FcPatternAddInteger (pat, FC_SPACING, FC_MONO))
704             goto bail1;
705 #endif
706
707     /*
708      * Find the font revision (if available)
709      */
710     head = (TT_Header *) FT_Get_Sfnt_Table (face, ft_sfnt_head);
711     if (head)
712     {
713         if (!FcPatternAddInteger (pat, FC_FONTVERSION, head->Font_Revision))
714             goto bail1;
715     }
716     else
717     {
718         if (!FcPatternAddInteger (pat, FC_FONTVERSION, 0))
719             goto bail1;
720     }
721
722     if (os2 && os2->version >= 0x0001 && os2->version != 0xffff)
723     {
724         for (i = 0; i < NUM_CODE_PAGE_RANGE; i++)
725         {
726             FT_ULong    bits;
727             int         bit;
728             if (FcCodePageRange[i].bit < 32)
729             {
730                 bits = os2->ulCodePageRange1;
731                 bit = FcCodePageRange[i].bit;
732             }
733             else
734             {
735                 bits = os2->ulCodePageRange2;
736                 bit = FcCodePageRange[i].bit - 32;
737             }
738             if (bits & (1 << bit))
739             {
740                 /* 
741                  * If the font advertises support for multiple
742                  * "exclusive" languages, then include support
743                  * for any language found to have coverage
744                  */
745                 if (exclusiveLang)
746                 {
747                     exclusiveLang = 0;
748                     break;
749                 }
750                 exclusiveLang = FcCodePageRange[i].lang;
751             }
752         }
753     }
754
755     if (os2 && os2->version != 0xffff)
756     {
757         if (os2->usWeightClass == 0)
758             ;
759         else if (os2->usWeightClass < 150)
760             weight = FC_WEIGHT_THIN;
761         else if (os2->usWeightClass < 250)
762             weight = FC_WEIGHT_EXTRALIGHT;
763         else if (os2->usWeightClass < 350)
764             weight = FC_WEIGHT_LIGHT;
765         else if (os2->usWeightClass < 450)
766             weight = FC_WEIGHT_REGULAR;
767         else if (os2->usWeightClass < 550)
768             weight = FC_WEIGHT_MEDIUM;
769         else if (os2->usWeightClass < 650)
770             weight = FC_WEIGHT_SEMIBOLD;
771         else if (os2->usWeightClass < 750)
772             weight = FC_WEIGHT_BOLD;
773         else if (os2->usWeightClass < 850)
774             weight = FC_WEIGHT_EXTRABOLD;
775         else if (os2->usWeightClass < 950)
776             weight = FC_WEIGHT_BLACK;
777
778         switch (os2->usWidthClass) {
779         case 1: width = FC_WIDTH_ULTRACONDENSED; break;
780         case 2: width = FC_WIDTH_EXTRACONDENSED; break;
781         case 3: width = FC_WIDTH_CONDENSED; break;
782         case 4: width = FC_WIDTH_SEMICONDENSED; break;
783         case 5: width = FC_WIDTH_NORMAL; break;
784         case 6: width = FC_WIDTH_SEMIEXPANDED; break;
785         case 7: width = FC_WIDTH_EXPANDED; break;
786         case 8: width = FC_WIDTH_EXTRAEXPANDED; break;
787         case 9: width = FC_WIDTH_ULTRAEXPANDED; break;
788         }
789     }
790
791     /*
792      * Type 1: Check for FontInfo dictionary information
793      * Code from g2@magestudios.net (Gerard Escalante)
794      */
795     
796     if (FT_Get_PS_Font_Info(face, &psfontinfo) == 0)
797     {
798         if (weight == -1 && psfontinfo.weight)
799         {
800             weight = FcIsWeight (psfontinfo.weight);
801             if (FcDebug() & FC_DBG_SCANV)
802                 printf ("\tType1 weight %s maps to %d\n",
803                         psfontinfo.weight, weight);
804         }
805      
806 #if 0
807         /* 
808          * Don't bother with italic_angle; FreeType already extracts that
809          * information for us and sticks it into style_flags
810          */
811         if (psfontinfo.italic_angle)
812             slant = FC_SLANT_ITALIC; 
813         else
814             slant = FC_SLANT_ROMAN; 
815 #endif
816
817         if(!foundry)
818             foundry = FcNoticeFoundry(psfontinfo.notice);
819     }
820     
821 #ifdef USE_FTBDF
822     /*
823      * Finally, look for a FOUNDRY BDF property if no other
824      * mechanism has managed to locate a foundry
825      */
826
827     if (!foundry)
828     {
829         int             rc;
830         BDF_PropertyRec prop;
831         rc = MY_Get_BDF_Property(face, "FOUNDRY", &prop);
832         if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM)
833             foundry = prop.u.atom;
834     }
835
836     if (width == -1)
837     {
838         if (MY_Get_BDF_Property(face, "RELATIVE_SETWIDTH", &prop) == 0 &&
839             (prop.type == BDF_PROPERTY_TYPE_INTEGER ||
840              prop.type == BDF_PROPERTY_TYPE_CARDINAL))
841         {
842             FT_Int32    value;
843             
844             if (prop.type == BDF_PROPERTY_TYPE_INTEGER)
845                 value = prop.u.integer;
846             else
847                 value = (FT_Int32) prop.u.cardinal;
848             switch ((value + 5) / 10) {
849             case 1: width = FC_WIDTH_ULTRACONDENSED; break;
850             case 2: width = FC_WIDTH_EXTRACONDENSED; break;
851             case 3: width = FC_WIDTH_CONDENSED; break;
852             case 4: width = FC_WIDTH_SEMICONDENSED; break;
853             case 5: width = FC_WIDTH_NORMAL; break;
854             case 6: width = FC_WIDTH_SEMIEXPANDED; break;
855             case 7: width = FC_WIDTH_EXPANDED; break;
856             case 8: width = FC_WIDTH_EXTRAEXPANDED; break;
857             case 9: width = FC_WIDTH_ULTRAEXPANDED; break;
858             }
859         }
860         if (width == -1 &&
861             MY_Get_BDF_Property (face, "SETWIDTH_NAME", &prop) == 0 &&
862             prop.type == BDF_PROPERTY_TYPE_ATOM)
863         {
864             width = FcIsWidth (prop.u.atom);
865             if (FcDebug () & FC_DBG_SCANV)
866                 printf ("\tsetwidth %s maps to %d\n", prop.u.atom, width);
867         }
868     }
869
870 #endif
871
872     /*
873      * Look for weight, width and slant names in the style value
874      */
875     if (style)
876     {
877         if (weight == -1)
878         {
879             weight = FcContainsWeight (style);
880             if (FcDebug() & FC_DBG_SCANV)
881                 printf ("\tStyle %s maps to weight %d\n", style, weight);
882         }
883         if (width == -1)
884         {
885             width = FcContainsWidth (style);
886             if (FcDebug() & FC_DBG_SCANV)
887                 printf ("\tStyle %s maps to width %d\n", style, width);
888         }
889         if (slant == -1)
890         {
891             slant = FcContainsSlant (style);
892             if (FcDebug() & FC_DBG_SCANV)
893                 printf ("\tStyle %s maps to slant %d\n", style, slant);
894         }
895     }
896     /*
897      * Pull default values from the FreeType flags if more
898      * specific values not found above
899      */
900     if (slant == -1)
901     {
902         slant = FC_SLANT_ROMAN;
903         if (face->style_flags & FT_STYLE_FLAG_ITALIC)
904             slant = FC_SLANT_ITALIC;
905     }
906
907     if (weight == -1)
908     {
909         weight = FC_WEIGHT_MEDIUM;
910         if (face->style_flags & FT_STYLE_FLAG_BOLD)
911             weight = FC_WEIGHT_BOLD;
912     }
913
914     if (!FcPatternAddInteger (pat, FC_SLANT, slant))
915         goto bail1;
916
917     if (!FcPatternAddInteger (pat, FC_WEIGHT, weight))
918         goto bail1;
919
920     if (width != -1)
921         if (!FcPatternAddInteger (pat, FC_WIDTH, width))
922             goto bail1;
923
924     if(foundry) 
925     {
926         if(!FcPatternAddString (pat, FC_FOUNDRY, foundry))
927             goto bail1;
928     }
929
930     /*
931      * Compute the unicode coverage for the font
932      */
933     cs = FcFreeTypeCharSetAndSpacing (face, blanks, &spacing);
934     if (!cs)
935         goto bail1;
936
937 #ifdef USE_FTBDF
938     /* For PCF fonts, override the computed spacing with the one from
939        the property */
940     if(MY_Get_BDF_Property(face, "SPACING", &prop) == 0 &&
941        prop.type == BDF_PROPERTY_TYPE_ATOM) {
942         if(strcmp(prop.u.atom, "c") || strcmp(prop.u.atom, "C"))
943             spacing = FC_CHARCELL;
944         else if(strcmp(prop.u.atom, "m") || strcmp(prop.u.atom, "M"))
945             spacing = FC_MONO;
946         else if(strcmp(prop.u.atom, "p") || strcmp(prop.u.atom, "P"))
947             spacing = FC_PROPORTIONAL;
948     }
949 #endif
950
951     /*
952      * Skip over PCF fonts that have no encoded characters; they're
953      * usually just Unicode fonts transcoded to some legacy encoding
954      */
955     if (FcCharSetCount (cs) == 0)
956     {
957         if (!strcmp(FT_MODULE_CLASS(&face->driver->root)->module_name, "pcf"))
958             goto bail2;
959     }
960
961     if (!FcPatternAddCharSet (pat, FC_CHARSET, cs))
962         goto bail2;
963
964     ls = FcFreeTypeLangSet (cs, exclusiveLang);
965     if (!ls)
966         goto bail2;
967
968     if (!FcPatternAddLangSet (pat, FC_LANG, ls))
969     {
970         FcLangSetDestroy (ls);
971         goto bail2;
972     }
973
974     FcLangSetDestroy (ls);
975
976     if (spacing != FC_PROPORTIONAL)
977         if (!FcPatternAddInteger (pat, FC_SPACING, spacing))
978             goto bail2;
979
980     if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
981     {
982         for (i = 0; i < face->num_fixed_sizes; i++)
983             if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE,
984                                      (double) face->available_sizes[i].height))
985                 goto bail1;
986         if (!FcPatternAddBool (pat, FC_ANTIALIAS, FcFalse))
987             goto bail1;
988 #ifdef USE_FTBDF
989         if(face->num_fixed_sizes == 1) {
990             int rc;
991             int value;
992             BDF_PropertyRec prop;
993
994             rc = MY_Get_BDF_Property(face, "PIXEL_SIZE", &prop);
995             if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
996                 value = prop.u.integer;
997             else if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_CARDINAL)
998                 value = prop.u.cardinal;
999             else
1000                 goto nevermind;
1001             if(value != face->available_sizes[0].height)
1002                 /* ``impossible'' */
1003                 goto nevermind;
1004
1005             rc = MY_Get_BDF_Property(face, "POINT_SIZE", &prop);
1006             if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
1007                 value = prop.u.integer;
1008             else if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_CARDINAL)
1009                 value = prop.u.cardinal;
1010             else
1011                 goto nevermind;
1012             if(!FcPatternAddDouble(pat, FC_SIZE, value / 10.0))
1013                 goto nevermind;
1014
1015             rc = MY_Get_BDF_Property(face, "RESOLUTION_Y", &prop);
1016             if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
1017                 value = prop.u.integer;
1018             else if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_CARDINAL)
1019                 value = prop.u.cardinal;
1020             else
1021                 goto nevermind;
1022             if(!FcPatternAddDouble(pat, FC_DPI, (double)value))
1023                 goto nevermind;
1024
1025         }
1026     nevermind:
1027         ;
1028 #endif
1029     }
1030
1031     /*
1032      * Drop our reference to the charset
1033      */
1034     FcCharSetDestroy (cs);
1035     
1036     /*
1037      * Deallocate family/style values
1038      */
1039     
1040     if (family_allocated)
1041         free (family);
1042     if (style_allocated)
1043         free (style);
1044     
1045     FT_Done_Face (face);
1046     FT_Done_FreeType (ftLibrary);
1047     return pat;
1048
1049 bail2:
1050     FcCharSetDestroy (cs);
1051 bail1:
1052     FcPatternDestroy (pat);
1053     if (family_allocated)
1054         free (family);
1055     if (style_allocated)
1056         free (style);
1057 bail0:
1058     FT_Done_Face (face);
1059 bail:
1060     FT_Done_FreeType (ftLibrary);
1061     return 0;
1062 }
1063
1064
1065 /*
1066  * Figure out whether the available freetype has FT_Get_Next_Char
1067  */
1068
1069 #if FREETYPE_MAJOR > 2
1070 # define HAS_NEXT_CHAR
1071 #else
1072 # if FREETYPE_MAJOR == 2
1073 #  if FREETYPE_MINOR > 0
1074 #   define HAS_NEXT_CHAR
1075 #  else
1076 #   if FREETYPE_MINOR == 0
1077 #    if FREETYPE_PATCH >= 9
1078 #     define HAS_NEXT_CHAR
1079 #    endif
1080 #   endif
1081 #  endif
1082 # endif
1083 #endif
1084
1085 /*
1086  * For our purposes, this approximation is sufficient
1087  */
1088 #ifndef HAS_NEXT_CHAR
1089 #define FT_Get_First_Char(face, gi) ((*(gi) = 1), 1)
1090 #define FT_Get_Next_Char(face, ucs4, gi) ((ucs4) >= 0xffffff ? \
1091                                           (*(gi) = 0), 0 : \
1092                                           (*(gi) = 1), (ucs4) + 1)
1093 #warning "No FT_Get_Next_Char"
1094 #endif
1095
1096 typedef struct _FcCharEnt {
1097     FcChar16        bmp;
1098     unsigned char   encode;
1099 } FcCharEnt;
1100
1101 struct _FcCharMap {
1102     const FcCharEnt *ent;
1103     int             nent;
1104 };
1105
1106 typedef struct _FcFontDecode {
1107     FT_Encoding     encoding;
1108     const FcCharMap *map;
1109     FcChar32        max;
1110 } FcFontDecode;
1111
1112 static const FcCharEnt AppleRomanEnt[] = {
1113     { 0x0020, 0x20 }, /* SPACE */
1114     { 0x0021, 0x21 }, /* EXCLAMATION MARK */
1115     { 0x0022, 0x22 }, /* QUOTATION MARK */
1116     { 0x0023, 0x23 }, /* NUMBER SIGN */
1117     { 0x0024, 0x24 }, /* DOLLAR SIGN */
1118     { 0x0025, 0x25 }, /* PERCENT SIGN */
1119     { 0x0026, 0x26 }, /* AMPERSAND */
1120     { 0x0027, 0x27 }, /* APOSTROPHE */
1121     { 0x0028, 0x28 }, /* LEFT PARENTHESIS */
1122     { 0x0029, 0x29 }, /* RIGHT PARENTHESIS */
1123     { 0x002A, 0x2A }, /* ASTERISK */
1124     { 0x002B, 0x2B }, /* PLUS SIGN */
1125     { 0x002C, 0x2C }, /* COMMA */
1126     { 0x002D, 0x2D }, /* HYPHEN-MINUS */
1127     { 0x002E, 0x2E }, /* FULL STOP */
1128     { 0x002F, 0x2F }, /* SOLIDUS */
1129     { 0x0030, 0x30 }, /* DIGIT ZERO */
1130     { 0x0031, 0x31 }, /* DIGIT ONE */
1131     { 0x0032, 0x32 }, /* DIGIT TWO */
1132     { 0x0033, 0x33 }, /* DIGIT THREE */
1133     { 0x0034, 0x34 }, /* DIGIT FOUR */
1134     { 0x0035, 0x35 }, /* DIGIT FIVE */
1135     { 0x0036, 0x36 }, /* DIGIT SIX */
1136     { 0x0037, 0x37 }, /* DIGIT SEVEN */
1137     { 0x0038, 0x38 }, /* DIGIT EIGHT */
1138     { 0x0039, 0x39 }, /* DIGIT NINE */
1139     { 0x003A, 0x3A }, /* COLON */
1140     { 0x003B, 0x3B }, /* SEMICOLON */
1141     { 0x003C, 0x3C }, /* LESS-THAN SIGN */
1142     { 0x003D, 0x3D }, /* EQUALS SIGN */
1143     { 0x003E, 0x3E }, /* GREATER-THAN SIGN */
1144     { 0x003F, 0x3F }, /* QUESTION MARK */
1145     { 0x0040, 0x40 }, /* COMMERCIAL AT */
1146     { 0x0041, 0x41 }, /* LATIN CAPITAL LETTER A */
1147     { 0x0042, 0x42 }, /* LATIN CAPITAL LETTER B */
1148     { 0x0043, 0x43 }, /* LATIN CAPITAL LETTER C */
1149     { 0x0044, 0x44 }, /* LATIN CAPITAL LETTER D */
1150     { 0x0045, 0x45 }, /* LATIN CAPITAL LETTER E */
1151     { 0x0046, 0x46 }, /* LATIN CAPITAL LETTER F */
1152     { 0x0047, 0x47 }, /* LATIN CAPITAL LETTER G */
1153     { 0x0048, 0x48 }, /* LATIN CAPITAL LETTER H */
1154     { 0x0049, 0x49 }, /* LATIN CAPITAL LETTER I */
1155     { 0x004A, 0x4A }, /* LATIN CAPITAL LETTER J */
1156     { 0x004B, 0x4B }, /* LATIN CAPITAL LETTER K */
1157     { 0x004C, 0x4C }, /* LATIN CAPITAL LETTER L */
1158     { 0x004D, 0x4D }, /* LATIN CAPITAL LETTER M */
1159     { 0x004E, 0x4E }, /* LATIN CAPITAL LETTER N */
1160     { 0x004F, 0x4F }, /* LATIN CAPITAL LETTER O */
1161     { 0x0050, 0x50 }, /* LATIN CAPITAL LETTER P */
1162     { 0x0051, 0x51 }, /* LATIN CAPITAL LETTER Q */
1163     { 0x0052, 0x52 }, /* LATIN CAPITAL LETTER R */
1164     { 0x0053, 0x53 }, /* LATIN CAPITAL LETTER S */
1165     { 0x0054, 0x54 }, /* LATIN CAPITAL LETTER T */
1166     { 0x0055, 0x55 }, /* LATIN CAPITAL LETTER U */
1167     { 0x0056, 0x56 }, /* LATIN CAPITAL LETTER V */
1168     { 0x0057, 0x57 }, /* LATIN CAPITAL LETTER W */
1169     { 0x0058, 0x58 }, /* LATIN CAPITAL LETTER X */
1170     { 0x0059, 0x59 }, /* LATIN CAPITAL LETTER Y */
1171     { 0x005A, 0x5A }, /* LATIN CAPITAL LETTER Z */
1172     { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET */
1173     { 0x005C, 0x5C }, /* REVERSE SOLIDUS */
1174     { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET */
1175     { 0x005E, 0x5E }, /* CIRCUMFLEX ACCENT */
1176     { 0x005F, 0x5F }, /* LOW LINE */
1177     { 0x0060, 0x60 }, /* GRAVE ACCENT */
1178     { 0x0061, 0x61 }, /* LATIN SMALL LETTER A */
1179     { 0x0062, 0x62 }, /* LATIN SMALL LETTER B */
1180     { 0x0063, 0x63 }, /* LATIN SMALL LETTER C */
1181     { 0x0064, 0x64 }, /* LATIN SMALL LETTER D */
1182     { 0x0065, 0x65 }, /* LATIN SMALL LETTER E */
1183     { 0x0066, 0x66 }, /* LATIN SMALL LETTER F */
1184     { 0x0067, 0x67 }, /* LATIN SMALL LETTER G */
1185     { 0x0068, 0x68 }, /* LATIN SMALL LETTER H */
1186     { 0x0069, 0x69 }, /* LATIN SMALL LETTER I */
1187     { 0x006A, 0x6A }, /* LATIN SMALL LETTER J */
1188     { 0x006B, 0x6B }, /* LATIN SMALL LETTER K */
1189     { 0x006C, 0x6C }, /* LATIN SMALL LETTER L */
1190     { 0x006D, 0x6D }, /* LATIN SMALL LETTER M */
1191     { 0x006E, 0x6E }, /* LATIN SMALL LETTER N */
1192     { 0x006F, 0x6F }, /* LATIN SMALL LETTER O */
1193     { 0x0070, 0x70 }, /* LATIN SMALL LETTER P */
1194     { 0x0071, 0x71 }, /* LATIN SMALL LETTER Q */
1195     { 0x0072, 0x72 }, /* LATIN SMALL LETTER R */
1196     { 0x0073, 0x73 }, /* LATIN SMALL LETTER S */
1197     { 0x0074, 0x74 }, /* LATIN SMALL LETTER T */
1198     { 0x0075, 0x75 }, /* LATIN SMALL LETTER U */
1199     { 0x0076, 0x76 }, /* LATIN SMALL LETTER V */
1200     { 0x0077, 0x77 }, /* LATIN SMALL LETTER W */
1201     { 0x0078, 0x78 }, /* LATIN SMALL LETTER X */
1202     { 0x0079, 0x79 }, /* LATIN SMALL LETTER Y */
1203     { 0x007A, 0x7A }, /* LATIN SMALL LETTER Z */
1204     { 0x007B, 0x7B }, /* LEFT CURLY BRACKET */
1205     { 0x007C, 0x7C }, /* VERTICAL LINE */
1206     { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET */
1207     { 0x007E, 0x7E }, /* TILDE */
1208     { 0x00A0, 0xCA }, /* NO-BREAK SPACE */
1209     { 0x00A1, 0xC1 }, /* INVERTED EXCLAMATION MARK */
1210     { 0x00A2, 0xA2 }, /* CENT SIGN */
1211     { 0x00A3, 0xA3 }, /* POUND SIGN */
1212     { 0x00A5, 0xB4 }, /* YEN SIGN */
1213     { 0x00A7, 0xA4 }, /* SECTION SIGN */
1214     { 0x00A8, 0xAC }, /* DIAERESIS */
1215     { 0x00A9, 0xA9 }, /* COPYRIGHT SIGN */
1216     { 0x00AA, 0xBB }, /* FEMININE ORDINAL INDICATOR */
1217     { 0x00AB, 0xC7 }, /* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
1218     { 0x00AC, 0xC2 }, /* NOT SIGN */
1219     { 0x00AE, 0xA8 }, /* REGISTERED SIGN */
1220     { 0x00AF, 0xF8 }, /* MACRON */
1221     { 0x00B0, 0xA1 }, /* DEGREE SIGN */
1222     { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN */
1223     { 0x00B4, 0xAB }, /* ACUTE ACCENT */
1224     { 0x00B5, 0xB5 }, /* MICRO SIGN */
1225     { 0x00B6, 0xA6 }, /* PILCROW SIGN */
1226     { 0x00B7, 0xE1 }, /* MIDDLE DOT */
1227     { 0x00B8, 0xFC }, /* CEDILLA */
1228     { 0x00BA, 0xBC }, /* MASCULINE ORDINAL INDICATOR */
1229     { 0x00BB, 0xC8 }, /* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
1230     { 0x00BF, 0xC0 }, /* INVERTED QUESTION MARK */
1231     { 0x00C0, 0xCB }, /* LATIN CAPITAL LETTER A WITH GRAVE */
1232     { 0x00C1, 0xE7 }, /* LATIN CAPITAL LETTER A WITH ACUTE */
1233     { 0x00C2, 0xE5 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
1234     { 0x00C3, 0xCC }, /* LATIN CAPITAL LETTER A WITH TILDE */
1235     { 0x00C4, 0x80 }, /* LATIN CAPITAL LETTER A WITH DIAERESIS */
1236     { 0x00C5, 0x81 }, /* LATIN CAPITAL LETTER A WITH RING ABOVE */
1237     { 0x00C6, 0xAE }, /* LATIN CAPITAL LETTER AE */
1238     { 0x00C7, 0x82 }, /* LATIN CAPITAL LETTER C WITH CEDILLA */
1239     { 0x00C8, 0xE9 }, /* LATIN CAPITAL LETTER E WITH GRAVE */
1240     { 0x00C9, 0x83 }, /* LATIN CAPITAL LETTER E WITH ACUTE */
1241     { 0x00CA, 0xE6 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
1242     { 0x00CB, 0xE8 }, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
1243     { 0x00CC, 0xED }, /* LATIN CAPITAL LETTER I WITH GRAVE */
1244     { 0x00CD, 0xEA }, /* LATIN CAPITAL LETTER I WITH ACUTE */
1245     { 0x00CE, 0xEB }, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
1246     { 0x00CF, 0xEC }, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
1247     { 0x00D1, 0x84 }, /* LATIN CAPITAL LETTER N WITH TILDE */
1248     { 0x00D2, 0xF1 }, /* LATIN CAPITAL LETTER O WITH GRAVE */
1249     { 0x00D3, 0xEE }, /* LATIN CAPITAL LETTER O WITH ACUTE */
1250     { 0x00D4, 0xEF }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
1251     { 0x00D5, 0xCD }, /* LATIN CAPITAL LETTER O WITH TILDE */
1252     { 0x00D6, 0x85 }, /* LATIN CAPITAL LETTER O WITH DIAERESIS */
1253     { 0x00D8, 0xAF }, /* LATIN CAPITAL LETTER O WITH STROKE */
1254     { 0x00D9, 0xF4 }, /* LATIN CAPITAL LETTER U WITH GRAVE */
1255     { 0x00DA, 0xF2 }, /* LATIN CAPITAL LETTER U WITH ACUTE */
1256     { 0x00DB, 0xF3 }, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
1257     { 0x00DC, 0x86 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS */
1258     { 0x00DF, 0xA7 }, /* LATIN SMALL LETTER SHARP S */
1259     { 0x00E0, 0x88 }, /* LATIN SMALL LETTER A WITH GRAVE */
1260     { 0x00E1, 0x87 }, /* LATIN SMALL LETTER A WITH ACUTE */
1261     { 0x00E2, 0x89 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
1262     { 0x00E3, 0x8B }, /* LATIN SMALL LETTER A WITH TILDE */
1263     { 0x00E4, 0x8A }, /* LATIN SMALL LETTER A WITH DIAERESIS */
1264     { 0x00E5, 0x8C }, /* LATIN SMALL LETTER A WITH RING ABOVE */
1265     { 0x00E6, 0xBE }, /* LATIN SMALL LETTER AE */
1266     { 0x00E7, 0x8D }, /* LATIN SMALL LETTER C WITH CEDILLA */
1267     { 0x00E8, 0x8F }, /* LATIN SMALL LETTER E WITH GRAVE */
1268     { 0x00E9, 0x8E }, /* LATIN SMALL LETTER E WITH ACUTE */
1269     { 0x00EA, 0x90 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */
1270     { 0x00EB, 0x91 }, /* LATIN SMALL LETTER E WITH DIAERESIS */
1271     { 0x00EC, 0x93 }, /* LATIN SMALL LETTER I WITH GRAVE */
1272     { 0x00ED, 0x92 }, /* LATIN SMALL LETTER I WITH ACUTE */
1273     { 0x00EE, 0x94 }, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
1274     { 0x00EF, 0x95 }, /* LATIN SMALL LETTER I WITH DIAERESIS */
1275     { 0x00F1, 0x96 }, /* LATIN SMALL LETTER N WITH TILDE */
1276     { 0x00F2, 0x98 }, /* LATIN SMALL LETTER O WITH GRAVE */
1277     { 0x00F3, 0x97 }, /* LATIN SMALL LETTER O WITH ACUTE */
1278     { 0x00F4, 0x99 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
1279     { 0x00F5, 0x9B }, /* LATIN SMALL LETTER O WITH TILDE */
1280     { 0x00F6, 0x9A }, /* LATIN SMALL LETTER O WITH DIAERESIS */
1281     { 0x00F7, 0xD6 }, /* DIVISION SIGN */
1282     { 0x00F8, 0xBF }, /* LATIN SMALL LETTER O WITH STROKE */
1283     { 0x00F9, 0x9D }, /* LATIN SMALL LETTER U WITH GRAVE */
1284     { 0x00FA, 0x9C }, /* LATIN SMALL LETTER U WITH ACUTE */
1285     { 0x00FB, 0x9E }, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
1286     { 0x00FC, 0x9F }, /* LATIN SMALL LETTER U WITH DIAERESIS */
1287     { 0x00FF, 0xD8 }, /* LATIN SMALL LETTER Y WITH DIAERESIS */
1288     { 0x0131, 0xF5 }, /* LATIN SMALL LETTER DOTLESS I */
1289     { 0x0152, 0xCE }, /* LATIN CAPITAL LIGATURE OE */
1290     { 0x0153, 0xCF }, /* LATIN SMALL LIGATURE OE */
1291     { 0x0178, 0xD9 }, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
1292     { 0x0192, 0xC4 }, /* LATIN SMALL LETTER F WITH HOOK */
1293     { 0x02C6, 0xF6 }, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
1294     { 0x02C7, 0xFF }, /* CARON */
1295     { 0x02D8, 0xF9 }, /* BREVE */
1296     { 0x02D9, 0xFA }, /* DOT ABOVE */
1297     { 0x02DA, 0xFB }, /* RING ABOVE */
1298     { 0x02DB, 0xFE }, /* OGONEK */
1299     { 0x02DC, 0xF7 }, /* SMALL TILDE */
1300     { 0x02DD, 0xFD }, /* DOUBLE ACUTE ACCENT */
1301     { 0x03A9, 0xBD }, /* GREEK CAPITAL LETTER OMEGA */
1302     { 0x03C0, 0xB9 }, /* GREEK SMALL LETTER PI */
1303     { 0x2013, 0xD0 }, /* EN DASH */
1304     { 0x2014, 0xD1 }, /* EM DASH */
1305     { 0x2018, 0xD4 }, /* LEFT SINGLE QUOTATION MARK */
1306     { 0x2019, 0xD5 }, /* RIGHT SINGLE QUOTATION MARK */
1307     { 0x201A, 0xE2 }, /* SINGLE LOW-9 QUOTATION MARK */
1308     { 0x201C, 0xD2 }, /* LEFT DOUBLE QUOTATION MARK */
1309     { 0x201D, 0xD3 }, /* RIGHT DOUBLE QUOTATION MARK */
1310     { 0x201E, 0xE3 }, /* DOUBLE LOW-9 QUOTATION MARK */
1311     { 0x2020, 0xA0 }, /* DAGGER */
1312     { 0x2021, 0xE0 }, /* DOUBLE DAGGER */
1313     { 0x2022, 0xA5 }, /* BULLET */
1314     { 0x2026, 0xC9 }, /* HORIZONTAL ELLIPSIS */
1315     { 0x2030, 0xE4 }, /* PER MILLE SIGN */
1316     { 0x2039, 0xDC }, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
1317     { 0x203A, 0xDD }, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
1318     { 0x2044, 0xDA }, /* FRACTION SLASH */
1319     { 0x20AC, 0xDB }, /* EURO SIGN */
1320     { 0x2122, 0xAA }, /* TRADE MARK SIGN */
1321     { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL */
1322     { 0x2206, 0xC6 }, /* INCREMENT */
1323     { 0x220F, 0xB8 }, /* N-ARY PRODUCT */
1324     { 0x2211, 0xB7 }, /* N-ARY SUMMATION */
1325     { 0x221A, 0xC3 }, /* SQUARE ROOT */
1326     { 0x221E, 0xB0 }, /* INFINITY */
1327     { 0x222B, 0xBA }, /* INTEGRAL */
1328     { 0x2248, 0xC5 }, /* ALMOST EQUAL TO */
1329     { 0x2260, 0xAD }, /* NOT EQUAL TO */
1330     { 0x2264, 0xB2 }, /* LESS-THAN OR EQUAL TO */
1331     { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO */
1332     { 0x25CA, 0xD7 }, /* LOZENGE */
1333     { 0xF8FF, 0xF0 }, /* Apple logo */
1334     { 0xFB01, 0xDE }, /* LATIN SMALL LIGATURE FI */
1335     { 0xFB02, 0xDF }, /* LATIN SMALL LIGATURE FL */
1336 };
1337
1338 static const FcCharMap AppleRoman = {
1339     AppleRomanEnt,
1340     sizeof (AppleRomanEnt) / sizeof (AppleRomanEnt[0])
1341 };
1342
1343 static const FcCharEnt AdobeSymbolEnt[] = {
1344     { 0x0020, 0x20 }, /* SPACE  # space */
1345     { 0x0021, 0x21 }, /* EXCLAMATION MARK       # exclam */
1346     { 0x0023, 0x23 }, /* NUMBER SIGN    # numbersign */
1347     { 0x0025, 0x25 }, /* PERCENT SIGN   # percent */
1348     { 0x0026, 0x26 }, /* AMPERSAND      # ampersand */
1349     { 0x0028, 0x28 }, /* LEFT PARENTHESIS       # parenleft */
1350     { 0x0029, 0x29 }, /* RIGHT PARENTHESIS      # parenright */
1351     { 0x002B, 0x2B }, /* PLUS SIGN      # plus */
1352     { 0x002C, 0x2C }, /* COMMA  # comma */
1353     { 0x002E, 0x2E }, /* FULL STOP      # period */
1354     { 0x002F, 0x2F }, /* SOLIDUS        # slash */
1355     { 0x0030, 0x30 }, /* DIGIT ZERO     # zero */
1356     { 0x0031, 0x31 }, /* DIGIT ONE      # one */
1357     { 0x0032, 0x32 }, /* DIGIT TWO      # two */
1358     { 0x0033, 0x33 }, /* DIGIT THREE    # three */
1359     { 0x0034, 0x34 }, /* DIGIT FOUR     # four */
1360     { 0x0035, 0x35 }, /* DIGIT FIVE     # five */
1361     { 0x0036, 0x36 }, /* DIGIT SIX      # six */
1362     { 0x0037, 0x37 }, /* DIGIT SEVEN    # seven */
1363     { 0x0038, 0x38 }, /* DIGIT EIGHT    # eight */
1364     { 0x0039, 0x39 }, /* DIGIT NINE     # nine */
1365     { 0x003A, 0x3A }, /* COLON  # colon */
1366     { 0x003B, 0x3B }, /* SEMICOLON      # semicolon */
1367     { 0x003C, 0x3C }, /* LESS-THAN SIGN # less */
1368     { 0x003D, 0x3D }, /* EQUALS SIGN    # equal */
1369     { 0x003E, 0x3E }, /* GREATER-THAN SIGN      # greater */
1370     { 0x003F, 0x3F }, /* QUESTION MARK  # question */
1371     { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET    # bracketleft */
1372     { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET   # bracketright */
1373     { 0x005F, 0x5F }, /* LOW LINE       # underscore */
1374     { 0x007B, 0x7B }, /* LEFT CURLY BRACKET     # braceleft */
1375     { 0x007C, 0x7C }, /* VERTICAL LINE  # bar */
1376     { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET    # braceright */
1377     { 0x00A0, 0x20 }, /* NO-BREAK SPACE # space */
1378     { 0x00AC, 0xD8 }, /* NOT SIGN       # logicalnot */
1379     { 0x00B0, 0xB0 }, /* DEGREE SIGN    # degree */
1380     { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN        # plusminus */
1381     { 0x00B5, 0x6D }, /* MICRO SIGN     # mu */
1382     { 0x00D7, 0xB4 }, /* MULTIPLICATION SIGN    # multiply */
1383     { 0x00F7, 0xB8 }, /* DIVISION SIGN  # divide */
1384     { 0x0192, 0xA6 }, /* LATIN SMALL LETTER F WITH HOOK # florin */
1385     { 0x0391, 0x41 }, /* GREEK CAPITAL LETTER ALPHA     # Alpha */
1386     { 0x0392, 0x42 }, /* GREEK CAPITAL LETTER BETA      # Beta */
1387     { 0x0393, 0x47 }, /* GREEK CAPITAL LETTER GAMMA     # Gamma */
1388     { 0x0394, 0x44 }, /* GREEK CAPITAL LETTER DELTA     # Delta */
1389     { 0x0395, 0x45 }, /* GREEK CAPITAL LETTER EPSILON   # Epsilon */
1390     { 0x0396, 0x5A }, /* GREEK CAPITAL LETTER ZETA      # Zeta */
1391     { 0x0397, 0x48 }, /* GREEK CAPITAL LETTER ETA       # Eta */
1392     { 0x0398, 0x51 }, /* GREEK CAPITAL LETTER THETA     # Theta */
1393     { 0x0399, 0x49 }, /* GREEK CAPITAL LETTER IOTA      # Iota */
1394     { 0x039A, 0x4B }, /* GREEK CAPITAL LETTER KAPPA     # Kappa */
1395     { 0x039B, 0x4C }, /* GREEK CAPITAL LETTER LAMDA     # Lambda */
1396     { 0x039C, 0x4D }, /* GREEK CAPITAL LETTER MU        # Mu */
1397     { 0x039D, 0x4E }, /* GREEK CAPITAL LETTER NU        # Nu */
1398     { 0x039E, 0x58 }, /* GREEK CAPITAL LETTER XI        # Xi */
1399     { 0x039F, 0x4F }, /* GREEK CAPITAL LETTER OMICRON   # Omicron */
1400     { 0x03A0, 0x50 }, /* GREEK CAPITAL LETTER PI        # Pi */
1401     { 0x03A1, 0x52 }, /* GREEK CAPITAL LETTER RHO       # Rho */
1402     { 0x03A3, 0x53 }, /* GREEK CAPITAL LETTER SIGMA     # Sigma */
1403     { 0x03A4, 0x54 }, /* GREEK CAPITAL LETTER TAU       # Tau */
1404     { 0x03A5, 0x55 }, /* GREEK CAPITAL LETTER UPSILON   # Upsilon */
1405     { 0x03A6, 0x46 }, /* GREEK CAPITAL LETTER PHI       # Phi */
1406     { 0x03A7, 0x43 }, /* GREEK CAPITAL LETTER CHI       # Chi */
1407     { 0x03A8, 0x59 }, /* GREEK CAPITAL LETTER PSI       # Psi */
1408     { 0x03A9, 0x57 }, /* GREEK CAPITAL LETTER OMEGA     # Omega */
1409     { 0x03B1, 0x61 }, /* GREEK SMALL LETTER ALPHA       # alpha */
1410     { 0x03B2, 0x62 }, /* GREEK SMALL LETTER BETA        # beta */
1411     { 0x03B3, 0x67 }, /* GREEK SMALL LETTER GAMMA       # gamma */
1412     { 0x03B4, 0x64 }, /* GREEK SMALL LETTER DELTA       # delta */
1413     { 0x03B5, 0x65 }, /* GREEK SMALL LETTER EPSILON     # epsilon */
1414     { 0x03B6, 0x7A }, /* GREEK SMALL LETTER ZETA        # zeta */
1415     { 0x03B7, 0x68 }, /* GREEK SMALL LETTER ETA # eta */
1416     { 0x03B8, 0x71 }, /* GREEK SMALL LETTER THETA       # theta */
1417     { 0x03B9, 0x69 }, /* GREEK SMALL LETTER IOTA        # iota */
1418     { 0x03BA, 0x6B }, /* GREEK SMALL LETTER KAPPA       # kappa */
1419     { 0x03BB, 0x6C }, /* GREEK SMALL LETTER LAMDA       # lambda */
1420     { 0x03BC, 0x6D }, /* GREEK SMALL LETTER MU  # mu */
1421     { 0x03BD, 0x6E }, /* GREEK SMALL LETTER NU  # nu */
1422     { 0x03BE, 0x78 }, /* GREEK SMALL LETTER XI  # xi */
1423     { 0x03BF, 0x6F }, /* GREEK SMALL LETTER OMICRON     # omicron */
1424     { 0x03C0, 0x70 }, /* GREEK SMALL LETTER PI  # pi */
1425     { 0x03C1, 0x72 }, /* GREEK SMALL LETTER RHO # rho */
1426     { 0x03C2, 0x56 }, /* GREEK SMALL LETTER FINAL SIGMA # sigma1 */
1427     { 0x03C3, 0x73 }, /* GREEK SMALL LETTER SIGMA       # sigma */
1428     { 0x03C4, 0x74 }, /* GREEK SMALL LETTER TAU # tau */
1429     { 0x03C5, 0x75 }, /* GREEK SMALL LETTER UPSILON     # upsilon */
1430     { 0x03C6, 0x66 }, /* GREEK SMALL LETTER PHI # phi */
1431     { 0x03C7, 0x63 }, /* GREEK SMALL LETTER CHI # chi */
1432     { 0x03C8, 0x79 }, /* GREEK SMALL LETTER PSI # psi */
1433     { 0x03C9, 0x77 }, /* GREEK SMALL LETTER OMEGA       # omega */
1434     { 0x03D1, 0x4A }, /* GREEK THETA SYMBOL     # theta1 */
1435     { 0x03D2, 0xA1 }, /* GREEK UPSILON WITH HOOK SYMBOL # Upsilon1 */
1436     { 0x03D5, 0x6A }, /* GREEK PHI SYMBOL       # phi1 */
1437     { 0x03D6, 0x76 }, /* GREEK PI SYMBOL        # omega1 */
1438     { 0x2022, 0xB7 }, /* BULLET # bullet */
1439     { 0x2026, 0xBC }, /* HORIZONTAL ELLIPSIS    # ellipsis */
1440     { 0x2032, 0xA2 }, /* PRIME  # minute */
1441     { 0x2033, 0xB2 }, /* DOUBLE PRIME   # second */
1442     { 0x2044, 0xA4 }, /* FRACTION SLASH # fraction */
1443     { 0x20AC, 0xA0 }, /* EURO SIGN      # Euro */
1444     { 0x2111, 0xC1 }, /* BLACK-LETTER CAPITAL I # Ifraktur */
1445     { 0x2118, 0xC3 }, /* SCRIPT CAPITAL P       # weierstrass */
1446     { 0x211C, 0xC2 }, /* BLACK-LETTER CAPITAL R # Rfraktur */
1447     { 0x2126, 0x57 }, /* OHM SIGN       # Omega */
1448     { 0x2135, 0xC0 }, /* ALEF SYMBOL    # aleph */
1449     { 0x2190, 0xAC }, /* LEFTWARDS ARROW        # arrowleft */
1450     { 0x2191, 0xAD }, /* UPWARDS ARROW  # arrowup */
1451     { 0x2192, 0xAE }, /* RIGHTWARDS ARROW       # arrowright */
1452     { 0x2193, 0xAF }, /* DOWNWARDS ARROW        # arrowdown */
1453     { 0x2194, 0xAB }, /* LEFT RIGHT ARROW       # arrowboth */
1454     { 0x21B5, 0xBF }, /* DOWNWARDS ARROW WITH CORNER LEFTWARDS  # carriagereturn */
1455     { 0x21D0, 0xDC }, /* LEFTWARDS DOUBLE ARROW # arrowdblleft */
1456     { 0x21D1, 0xDD }, /* UPWARDS DOUBLE ARROW   # arrowdblup */
1457     { 0x21D2, 0xDE }, /* RIGHTWARDS DOUBLE ARROW        # arrowdblright */
1458     { 0x21D3, 0xDF }, /* DOWNWARDS DOUBLE ARROW # arrowdbldown */
1459     { 0x21D4, 0xDB }, /* LEFT RIGHT DOUBLE ARROW        # arrowdblboth */
1460     { 0x2200, 0x22 }, /* FOR ALL        # universal */
1461     { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL   # partialdiff */
1462     { 0x2203, 0x24 }, /* THERE EXISTS   # existential */
1463     { 0x2205, 0xC6 }, /* EMPTY SET      # emptyset */
1464     { 0x2206, 0x44 }, /* INCREMENT      # Delta */
1465     { 0x2207, 0xD1 }, /* NABLA  # gradient */
1466     { 0x2208, 0xCE }, /* ELEMENT OF     # element */
1467     { 0x2209, 0xCF }, /* NOT AN ELEMENT OF      # notelement */
1468     { 0x220B, 0x27 }, /* CONTAINS AS MEMBER     # suchthat */
1469     { 0x220F, 0xD5 }, /* N-ARY PRODUCT  # product */
1470     { 0x2211, 0xE5 }, /* N-ARY SUMMATION        # summation */
1471     { 0x2212, 0x2D }, /* MINUS SIGN     # minus */
1472     { 0x2215, 0xA4 }, /* DIVISION SLASH # fraction */
1473     { 0x2217, 0x2A }, /* ASTERISK OPERATOR      # asteriskmath */
1474     { 0x221A, 0xD6 }, /* SQUARE ROOT    # radical */
1475     { 0x221D, 0xB5 }, /* PROPORTIONAL TO        # proportional */
1476     { 0x221E, 0xA5 }, /* INFINITY       # infinity */
1477     { 0x2220, 0xD0 }, /* ANGLE  # angle */
1478     { 0x2227, 0xD9 }, /* LOGICAL AND    # logicaland */
1479     { 0x2228, 0xDA }, /* LOGICAL OR     # logicalor */
1480     { 0x2229, 0xC7 }, /* INTERSECTION   # intersection */
1481     { 0x222A, 0xC8 }, /* UNION  # union */
1482     { 0x222B, 0xF2 }, /* INTEGRAL       # integral */
1483     { 0x2234, 0x5C }, /* THEREFORE      # therefore */
1484     { 0x223C, 0x7E }, /* TILDE OPERATOR # similar */
1485     { 0x2245, 0x40 }, /* APPROXIMATELY EQUAL TO # congruent */
1486     { 0x2248, 0xBB }, /* ALMOST EQUAL TO        # approxequal */
1487     { 0x2260, 0xB9 }, /* NOT EQUAL TO   # notequal */
1488     { 0x2261, 0xBA }, /* IDENTICAL TO   # equivalence */
1489     { 0x2264, 0xA3 }, /* LESS-THAN OR EQUAL TO  # lessequal */
1490     { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO       # greaterequal */
1491     { 0x2282, 0xCC }, /* SUBSET OF      # propersubset */
1492     { 0x2283, 0xC9 }, /* SUPERSET OF    # propersuperset */
1493     { 0x2284, 0xCB }, /* NOT A SUBSET OF        # notsubset */
1494     { 0x2286, 0xCD }, /* SUBSET OF OR EQUAL TO  # reflexsubset */
1495     { 0x2287, 0xCA }, /* SUPERSET OF OR EQUAL TO        # reflexsuperset */
1496     { 0x2295, 0xC5 }, /* CIRCLED PLUS   # circleplus */
1497     { 0x2297, 0xC4 }, /* CIRCLED TIMES  # circlemultiply */
1498     { 0x22A5, 0x5E }, /* UP TACK        # perpendicular */
1499     { 0x22C5, 0xD7 }, /* DOT OPERATOR   # dotmath */
1500     { 0x2320, 0xF3 }, /* TOP HALF INTEGRAL      # integraltp */
1501     { 0x2321, 0xF5 }, /* BOTTOM HALF INTEGRAL   # integralbt */
1502     { 0x2329, 0xE1 }, /* LEFT-POINTING ANGLE BRACKET    # angleleft */
1503     { 0x232A, 0xF1 }, /* RIGHT-POINTING ANGLE BRACKET   # angleright */
1504     { 0x25CA, 0xE0 }, /* LOZENGE        # lozenge */
1505     { 0x2660, 0xAA }, /* BLACK SPADE SUIT       # spade */
1506     { 0x2663, 0xA7 }, /* BLACK CLUB SUIT        # club */
1507     { 0x2665, 0xA9 }, /* BLACK HEART SUIT       # heart */
1508     { 0x2666, 0xA8 }, /* BLACK DIAMOND SUIT     # diamond */
1509     { 0xF6D9, 0xD3 }, /* COPYRIGHT SIGN SERIF   # copyrightserif (CUS) */
1510     { 0xF6DA, 0xD2 }, /* REGISTERED SIGN SERIF  # registerserif (CUS) */
1511     { 0xF6DB, 0xD4 }, /* TRADE MARK SIGN SERIF  # trademarkserif (CUS) */
1512     { 0xF8E5, 0x60 }, /* RADICAL EXTENDER       # radicalex (CUS) */
1513     { 0xF8E6, 0xBD }, /* VERTICAL ARROW EXTENDER        # arrowvertex (CUS) */
1514     { 0xF8E7, 0xBE }, /* HORIZONTAL ARROW EXTENDER      # arrowhorizex (CUS) */
1515     { 0xF8E8, 0xE2 }, /* REGISTERED SIGN SANS SERIF     # registersans (CUS) */
1516     { 0xF8E9, 0xE3 }, /* COPYRIGHT SIGN SANS SERIF      # copyrightsans (CUS) */
1517     { 0xF8EA, 0xE4 }, /* TRADE MARK SIGN SANS SERIF     # trademarksans (CUS) */
1518     { 0xF8EB, 0xE6 }, /* LEFT PAREN TOP # parenlefttp (CUS) */
1519     { 0xF8EC, 0xE7 }, /* LEFT PAREN EXTENDER    # parenleftex (CUS) */
1520     { 0xF8ED, 0xE8 }, /* LEFT PAREN BOTTOM      # parenleftbt (CUS) */
1521     { 0xF8EE, 0xE9 }, /* LEFT SQUARE BRACKET TOP        # bracketlefttp (CUS) */
1522     { 0xF8EF, 0xEA }, /* LEFT SQUARE BRACKET EXTENDER   # bracketleftex (CUS) */
1523     { 0xF8F0, 0xEB }, /* LEFT SQUARE BRACKET BOTTOM     # bracketleftbt (CUS) */
1524     { 0xF8F1, 0xEC }, /* LEFT CURLY BRACKET TOP # bracelefttp (CUS) */
1525     { 0xF8F2, 0xED }, /* LEFT CURLY BRACKET MID # braceleftmid (CUS) */
1526     { 0xF8F3, 0xEE }, /* LEFT CURLY BRACKET BOTTOM      # braceleftbt (CUS) */
1527     { 0xF8F4, 0xEF }, /* CURLY BRACKET EXTENDER # braceex (CUS) */
1528     { 0xF8F5, 0xF4 }, /* INTEGRAL EXTENDER      # integralex (CUS) */
1529     { 0xF8F6, 0xF6 }, /* RIGHT PAREN TOP        # parenrighttp (CUS) */
1530     { 0xF8F7, 0xF7 }, /* RIGHT PAREN EXTENDER   # parenrightex (CUS) */
1531     { 0xF8F8, 0xF8 }, /* RIGHT PAREN BOTTOM     # parenrightbt (CUS) */
1532     { 0xF8F9, 0xF9 }, /* RIGHT SQUARE BRACKET TOP       # bracketrighttp (CUS) */
1533     { 0xF8FA, 0xFA }, /* RIGHT SQUARE BRACKET EXTENDER  # bracketrightex (CUS) */
1534     { 0xF8FB, 0xFB }, /* RIGHT SQUARE BRACKET BOTTOM    # bracketrightbt (CUS) */
1535     { 0xF8FC, 0xFC }, /* RIGHT CURLY BRACKET TOP        # bracerighttp (CUS) */
1536     { 0xF8FD, 0xFD }, /* RIGHT CURLY BRACKET MID        # bracerightmid (CUS) */
1537     { 0xF8FE, 0xFE }, /* RIGHT CURLY BRACKET BOTTOM     # bracerightbt (CUS) */
1538 };
1539
1540 static const FcCharMap AdobeSymbol = {
1541     AdobeSymbolEnt,
1542     sizeof (AdobeSymbolEnt) / sizeof (AdobeSymbolEnt[0]),
1543 };
1544     
1545 static const FcFontDecode fcFontDecoders[] = {
1546     { ft_encoding_unicode,      0,              (1 << 21) - 1 },
1547     { ft_encoding_symbol,       &AdobeSymbol,   (1 << 16) - 1 },
1548     { ft_encoding_apple_roman,  &AppleRoman,    (1 << 16) - 1 },
1549 };
1550
1551 #define NUM_DECODE  (sizeof (fcFontDecoders) / sizeof (fcFontDecoders[0]))
1552
1553 FcChar32
1554 FcFreeTypeUcs4ToPrivate (FcChar32 ucs4, const FcCharMap *map)
1555 {
1556     int         low, high, mid;
1557     FcChar16    bmp;
1558
1559     low = 0;
1560     high = map->nent - 1;
1561     if (ucs4 < map->ent[low].bmp || map->ent[high].bmp < ucs4)
1562         return ~0;
1563     while (low <= high)
1564     {
1565         mid = (high + low) >> 1;
1566         bmp = map->ent[mid].bmp;
1567         if (ucs4 == bmp)
1568             return (FT_ULong) map->ent[mid].encode;
1569         if (ucs4 < bmp)
1570             high = mid - 1;
1571         else
1572             low = mid + 1;
1573     }
1574     return ~0;
1575 }
1576
1577 FcChar32
1578 FcFreeTypePrivateToUcs4 (FcChar32 private, const FcCharMap *map)
1579 {
1580     int     i;
1581
1582     for (i = 0; i < map->nent; i++)
1583         if (map->ent[i].encode == private)
1584             return (FcChar32) map->ent[i].bmp;
1585     return ~0;
1586 }
1587
1588 const FcCharMap *
1589 FcFreeTypeGetPrivateMap (FT_Encoding encoding)
1590 {
1591     int i;
1592
1593     for (i = 0; i < NUM_DECODE; i++)
1594         if (fcFontDecoders[i].encoding == encoding)
1595             return fcFontDecoders[i].map;
1596     return 0;
1597 }
1598
1599 #include "../fc-glyphname/fcglyphname.h"
1600
1601 static FcChar32
1602 FcHashGlyphName (const FcChar8 *name)
1603 {
1604     FcChar32    h = 0;
1605     FcChar8     c;
1606
1607     while ((c = *name++))
1608     {
1609         h = ((h << 1) | (h >> 31)) ^ c;
1610     }
1611     return h;
1612 }
1613
1614 /*
1615  * Use Type1 glyph names for fonts which have reliable names
1616  * and which export an Adobe Custom mapping
1617  */
1618 static FcBool
1619 FcFreeTypeUseNames (FT_Face face)
1620 {
1621     FT_Int  map;
1622     
1623     if (!FT_Has_PS_Glyph_Names (face))
1624         return FcFalse;
1625     for (map = 0; map < face->num_charmaps; map++)
1626         if (face->charmaps[map]->encoding == ft_encoding_adobe_custom)
1627             return FcTrue;
1628     return FcFalse;
1629 }
1630
1631 static FcChar8 *
1632 FcUcs4ToGlyphName (FcChar32 ucs4)
1633 {
1634     int         i = (int) (ucs4 % FC_GLYPHNAME_HASH);
1635     int         r = 0;
1636     FcGlyphName *gn;
1637
1638     while ((gn = ucs_to_name[i]))
1639     {
1640         if (gn->ucs == ucs4)
1641             return gn->name;
1642         if (!r) 
1643         {
1644             r = (int) (ucs4 % FC_GLYPHNAME_REHASH);
1645             if (!r)
1646                 r = 1;
1647         }
1648         i += r;
1649         if (i >= FC_GLYPHNAME_HASH)
1650             i -= FC_GLYPHNAME_HASH;
1651     }
1652     return 0;
1653 }
1654
1655 static FcChar32
1656 FcGlyphNameToUcs4 (FcChar8 *name)
1657 {
1658     FcChar32    h = FcHashGlyphName (name);
1659     int         i = (int) (h % FC_GLYPHNAME_HASH);
1660     int         r = 0;
1661     FcGlyphName *gn;
1662
1663     while ((gn = name_to_ucs[i]))
1664     {
1665         if (!strcmp ((char *) name, (char *) gn->name))
1666             return gn->ucs;
1667         if (!r) 
1668         {
1669             r = (int) (h % FC_GLYPHNAME_REHASH);
1670             if (!r)
1671                 r = 1;
1672         }
1673         i += r;
1674         if (i >= FC_GLYPHNAME_HASH)
1675             i -= FC_GLYPHNAME_HASH;
1676     }
1677     return 0xffff;
1678 }
1679
1680 /*
1681  * Search through a font for a glyph by name.  This is
1682  * currently a linear search as there doesn't appear to be
1683  * any defined order within the font
1684  */
1685 static FT_UInt
1686 FcFreeTypeGlyphNameIndex (FT_Face face, FcChar8 *name)
1687 {
1688     FT_UInt gindex;
1689     FcChar8 name_buf[FC_GLYPHNAME_MAXLEN + 2];
1690
1691     for (gindex = 0; gindex < face->num_glyphs; gindex++)
1692     {
1693         if (FT_Get_Glyph_Name (face, gindex, name_buf, FC_GLYPHNAME_MAXLEN+1) == 0)
1694             if (!strcmp ((char *) name, (char *) name_buf))
1695                 return gindex;
1696     }
1697     return 0;
1698 }
1699
1700 /*
1701  * Map a UCS4 glyph to a glyph index.  Use all available encoding
1702  * tables to try and find one that works.  This information is expected
1703  * to be cached by higher levels, so performance isn't critical
1704  */
1705
1706 FT_UInt
1707 FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
1708 {
1709     int             initial, offset, decode;
1710     FT_UInt         glyphindex;
1711     FcChar32        charcode;
1712
1713     initial = 0;
1714     /*
1715      * Find the current encoding
1716      */
1717     if (face->charmap)
1718     {
1719         for (; initial < NUM_DECODE; initial++)
1720             if (fcFontDecoders[initial].encoding == face->charmap->encoding)
1721                 break;
1722         if (initial == NUM_DECODE)
1723             initial = 0;
1724     }
1725     /*
1726      * Check each encoding for the glyph, starting with the current one
1727      */
1728     for (offset = 0; offset < NUM_DECODE; offset++)
1729     {
1730         decode = (initial + offset) % NUM_DECODE;
1731         if (!face->charmap || face->charmap->encoding != fcFontDecoders[decode].encoding)
1732             if (FT_Select_Charmap (face, fcFontDecoders[decode].encoding) != 0)
1733                 continue;
1734         if (fcFontDecoders[decode].map)
1735         {
1736             charcode = FcFreeTypeUcs4ToPrivate (ucs4, fcFontDecoders[decode].map);
1737             if (charcode == ~0)
1738                 continue;
1739         }
1740         else
1741             charcode = ucs4;
1742         glyphindex = FT_Get_Char_Index (face, (FT_ULong) charcode);
1743         if (glyphindex)
1744             return glyphindex;
1745     }
1746     /*
1747      * Check postscript name table if present
1748      */
1749     if (FcFreeTypeUseNames (face))
1750     {
1751         FcChar8 *name = FcUcs4ToGlyphName (ucs4);
1752         if (name)
1753         {
1754             glyphindex = FcFreeTypeGlyphNameIndex (face, name);
1755             if (glyphindex)
1756                 return glyphindex;
1757         }
1758     }
1759     return 0;
1760 }
1761
1762 static FcBool
1763 FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4, 
1764                       FT_UInt glyph, FcBlanks *blanks,
1765                       FT_Pos *advance)
1766 {
1767     FT_Int          load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
1768     FT_GlyphSlot    slot;
1769     
1770     /*
1771      * When using scalable fonts, only report those glyphs
1772      * which can be scaled; otherwise those fonts will
1773      * only be available at some sizes, and never when
1774      * transformed.  Avoid this by simply reporting bitmap-only
1775      * glyphs as missing
1776      */
1777     if (face->face_flags & FT_FACE_FLAG_SCALABLE)
1778         load_flags |= FT_LOAD_NO_BITMAP;
1779     
1780     if (FT_Load_Glyph (face, glyph, load_flags))
1781         return FcFalse;
1782     
1783     slot = face->glyph;
1784     if (!glyph)
1785         return FcFalse;
1786     
1787     *advance = slot->metrics.horiAdvance;
1788
1789     switch (slot->format) {
1790     case ft_glyph_format_bitmap:
1791         /*
1792          * Bitmaps are assumed to be reasonable; if
1793          * this proves to be a rash assumption, this
1794          * code can be easily modified
1795          */
1796         return FcTrue;
1797     case ft_glyph_format_outline:
1798         /*
1799          * Glyphs with contours are always OK
1800          */
1801         if (slot->outline.n_contours != 0)
1802             return FcTrue;
1803         /*
1804          * Glyphs with no contours are only OK if
1805          * they're members of the Blanks set specified
1806          * in the configuration.  If blanks isn't set,
1807          * then allow any glyph to be blank
1808          */
1809         if (!blanks || FcBlanksIsMember (blanks, ucs4))
1810             return FcTrue;
1811         /* fall through ... */
1812     default:
1813         break;
1814     }
1815     return FcFalse;
1816 }
1817
1818 FcCharSet *
1819 FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
1820 {
1821     FcChar32        page, off, max, ucs4;
1822 #ifdef CHECK
1823     FcChar32        font_max = 0;
1824 #endif
1825     FcCharSet       *fcs;
1826     FcCharLeaf      *leaf;
1827     const FcCharMap *map;
1828     int             o;
1829     int             i;
1830     FT_UInt         glyph;
1831     FT_Pos          advance, all_advance = 0;
1832     FcBool          has_advance = FcFalse, fixed_advance = FcTrue;
1833
1834     fcs = FcCharSetCreate ();
1835     if (!fcs)
1836         goto bail0;
1837     
1838 #ifdef CHECK
1839     printf ("Family %s style %s\n", face->family_name, face->style_name);
1840 #endif
1841     for (o = 0; o < NUM_DECODE; o++)
1842     {
1843         if (FT_Select_Charmap (face, fcFontDecoders[o].encoding) != 0)
1844             continue;
1845         map = fcFontDecoders[o].map;
1846         if (map)
1847         {
1848             /*
1849              * Non-Unicode tables are easy; there's a list of all possible
1850              * characters
1851              */
1852             for (i = 0; i < map->nent; i++)
1853             {
1854                 ucs4 = map->ent[i].bmp;
1855                 glyph = FT_Get_Char_Index (face, map->ent[i].encode);
1856                 if (glyph && 
1857                     FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance))
1858                 {
1859                     if (!has_advance)
1860                     {
1861                         has_advance = FcTrue;
1862                         all_advance = advance;
1863                     }
1864                     else if (advance != all_advance)
1865                         fixed_advance = FcFalse;
1866                     leaf = FcCharSetFindLeafCreate (fcs, ucs4);
1867                     if (!leaf)
1868                         goto bail1;
1869                     leaf->map[(ucs4 & 0xff) >> 5] |= (1 << (ucs4 & 0x1f));
1870 #ifdef CHECK
1871                     if (ucs4 > font_max)
1872                         font_max = ucs4;
1873 #endif
1874                 }
1875             }
1876         }
1877         else
1878         {
1879             FT_UInt gindex;
1880           
1881             max = fcFontDecoders[o].max;
1882             /*
1883              * Find the first encoded character in the font
1884              */
1885             if (FT_Get_Char_Index (face, 0))
1886             {
1887                 ucs4 = 0;
1888                 gindex = 1;
1889             }
1890             else
1891             {
1892                 ucs4 = FT_Get_Next_Char (face, 0, &gindex);
1893                 if (!ucs4)
1894                     gindex = 0;
1895             }
1896
1897             while (gindex)
1898             {
1899                 page = ucs4 >> 8;
1900                 leaf = 0;
1901                 while ((ucs4 >> 8) == page)
1902                 {
1903                     glyph = FT_Get_Char_Index (face, ucs4);
1904                     if (glyph && FcFreeTypeCheckGlyph (face, ucs4, 
1905                                                        glyph, blanks, &advance))
1906                     {
1907                         if (!has_advance)
1908                         {
1909                             has_advance = FcTrue;
1910                             all_advance = advance;
1911                         }
1912                         else if (advance != all_advance)
1913                             fixed_advance = FcFalse;
1914                         if (!leaf)
1915                         {
1916                             leaf = FcCharSetFindLeafCreate (fcs, ucs4);
1917                             if (!leaf)
1918                                 goto bail1;
1919                         }
1920                         off = ucs4 & 0xff;
1921                         leaf->map[off >> 5] |= (1 << (off & 0x1f));
1922 #ifdef CHECK
1923                         if (ucs4 > font_max)
1924                             font_max = ucs4;
1925 #endif
1926                     }
1927                     ucs4++;
1928                 }
1929                 ucs4 = FT_Get_Next_Char (face, ucs4 - 1, &gindex);
1930                 if (!ucs4)
1931                     gindex = 0;
1932             }
1933 #ifdef CHECK
1934             for (ucs4 = 0; ucs4 < 0x10000; ucs4++)
1935             {
1936                 FcBool      FT_Has, FC_Has;
1937
1938                 FT_Has = FT_Get_Char_Index (face, ucs4) != 0;
1939                 FC_Has = FcCharSetHasChar (fcs, ucs4);
1940                 if (FT_Has != FC_Has)
1941                 {
1942                     printf ("0x%08x FT says %d FC says %d\n", ucs4, FT_Has, FC_Has);
1943                 }
1944             }
1945 #endif
1946         }
1947     }
1948     /*
1949      * Add mapping from PS glyph names if available
1950      */
1951     if (FcFreeTypeUseNames (face))
1952     {
1953         FcChar8 name_buf[FC_GLYPHNAME_MAXLEN + 2];
1954
1955         for (glyph = 0; glyph < face->num_glyphs; glyph++)
1956         {
1957             if (FT_Get_Glyph_Name (face, glyph, name_buf, FC_GLYPHNAME_MAXLEN+1) == 0)
1958             {
1959                 ucs4 = FcGlyphNameToUcs4 (name_buf);
1960                 if (ucs4 != 0xffff && 
1961                     FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance))
1962                 {
1963                     if (!has_advance)
1964                     {
1965                         has_advance = FcTrue;
1966                         all_advance = advance;
1967                     }
1968                     else if (advance != all_advance)
1969                         fixed_advance = FcFalse;
1970                     leaf = FcCharSetFindLeafCreate (fcs, ucs4);
1971                     if (!leaf)
1972                         goto bail1;
1973                     leaf->map[(ucs4 & 0xff) >> 5] |= (1 << (ucs4 & 0x1f));
1974 #ifdef CHECK
1975                     if (ucs4 > font_max)
1976                         font_max = ucs4;
1977 #endif
1978                 }
1979             }
1980         }
1981     }
1982 #ifdef CHECK
1983     printf ("%d glyphs %d encoded\n", (int) face->num_glyphs, FcCharSetCount (fcs));
1984     for (ucs4 = 0; ucs4 <= font_max; ucs4++)
1985     {
1986         FcBool  has_char = (glyph = FcFreeTypeCharIndex (face, ucs4)) != 0;
1987         FcBool  has_bit = FcCharSetHasChar (fcs, ucs4);
1988
1989         if (has_char && !has_bit)
1990         {
1991             if (!FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance))
1992                 printf ("Bitmap missing broken char 0x%x\n", ucs4);
1993             else
1994                 printf ("Bitmap missing char 0x%x\n", ucs4);
1995         }
1996         else if (!has_char && has_bit)
1997             printf ("Bitmap extra char 0x%x\n", ucs4);
1998     }
1999 #endif
2000     if (fixed_advance)
2001         *spacing = FC_MONO;
2002     else
2003         *spacing = FC_PROPORTIONAL;
2004     return fcs;
2005 bail1:
2006     FcCharSetDestroy (fcs);
2007 bail0:
2008     return 0;
2009 }
2010
2011 FcCharSet *
2012 FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks)
2013 {
2014     int spacing;
2015
2016     return FcFreeTypeCharSetAndSpacing (face, blanks, &spacing);
2017 }