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