]> git.wh0rd.org Git - fontconfig.git/blob - src/fcfreetype.c
Force FC_FOUNDRY and FC_WIDTH to always be set so that matches looking for
[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 (width == -1)
946         width = FC_WIDTH_NORMAL;
947
948     if (foundry == 0)
949         foundry = "unknown";
950
951     if (!FcPatternAddInteger (pat, FC_SLANT, slant))
952         goto bail1;
953
954     if (!FcPatternAddInteger (pat, FC_WEIGHT, weight))
955         goto bail1;
956
957     if (!FcPatternAddInteger (pat, FC_WIDTH, width))
958         goto bail1;
959
960     if (!FcPatternAddString (pat, FC_FOUNDRY, foundry))
961         goto bail1;
962
963     /*
964      * Compute the unicode coverage for the font
965      */
966     cs = FcFreeTypeCharSetAndSpacing (face, blanks, &spacing);
967     if (!cs)
968         goto bail1;
969
970 #if HAVE_FT_GET_BDF_PROPERTY
971     /* For PCF fonts, override the computed spacing with the one from
972        the property */
973     if(MY_Get_BDF_Property(face, "SPACING", &prop) == 0 &&
974        prop.type == BDF_PROPERTY_TYPE_ATOM) {
975         if(!strcmp(prop.u.atom, "c") || !strcmp(prop.u.atom, "C"))
976             spacing = FC_CHARCELL;
977         else if(!strcmp(prop.u.atom, "m") || !strcmp(prop.u.atom, "M"))
978             spacing = FC_MONO;
979         else if(!strcmp(prop.u.atom, "p") || !strcmp(prop.u.atom, "P"))
980             spacing = FC_PROPORTIONAL;
981     }
982 #endif
983
984     /*
985      * Skip over PCF fonts that have no encoded characters; they're
986      * usually just Unicode fonts transcoded to some legacy encoding
987      */
988     if (FcCharSetCount (cs) == 0)
989     {
990         if (!strcmp(FT_MODULE_CLASS(&face->driver->root)->module_name, "pcf"))
991             goto bail2;
992     }
993
994     if (!FcPatternAddCharSet (pat, FC_CHARSET, cs))
995         goto bail2;
996
997     ls = FcFreeTypeLangSet (cs, exclusiveLang);
998     if (!ls)
999         goto bail2;
1000
1001     if (!FcPatternAddLangSet (pat, FC_LANG, ls))
1002     {
1003         FcLangSetDestroy (ls);
1004         goto bail2;
1005     }
1006
1007     FcLangSetDestroy (ls);
1008
1009     if (spacing != FC_PROPORTIONAL)
1010         if (!FcPatternAddInteger (pat, FC_SPACING, spacing))
1011             goto bail2;
1012
1013     if (!(face->face_flags & FT_FACE_FLAG_SCALABLE))
1014     {
1015         for (i = 0; i < face->num_fixed_sizes; i++)
1016             if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE,
1017                                      FcGetPixelSize (face, i)))
1018                 goto bail1;
1019         if (!FcPatternAddBool (pat, FC_ANTIALIAS, FcFalse))
1020             goto bail1;
1021 #if HAVE_FT_GET_BDF_PROPERTY
1022         if(face->num_fixed_sizes == 1) {
1023             int rc;
1024             int value;
1025             BDF_PropertyRec prop;
1026
1027             rc = MY_Get_BDF_Property(face, "POINT_SIZE", &prop);
1028             if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
1029                 value = prop.u.integer;
1030             else if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_CARDINAL)
1031                 value = prop.u.cardinal;
1032             else
1033                 goto nevermind;
1034             if(!FcPatternAddDouble(pat, FC_SIZE, value / 10.0))
1035                 goto nevermind;
1036
1037             rc = MY_Get_BDF_Property(face, "RESOLUTION_Y", &prop);
1038             if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
1039                 value = prop.u.integer;
1040             else if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_CARDINAL)
1041                 value = prop.u.cardinal;
1042             else
1043                 goto nevermind;
1044             if(!FcPatternAddDouble(pat, FC_DPI, (double)value))
1045                 goto nevermind;
1046
1047         }
1048     nevermind:
1049         ;
1050 #endif
1051     }
1052
1053     /*
1054      * Drop our reference to the charset
1055      */
1056     FcCharSetDestroy (cs);
1057     
1058     /*
1059      * Deallocate family/style values
1060      */
1061     
1062     if (family_allocated)
1063         free (family);
1064     if (style_allocated)
1065         free (style);
1066     
1067     FT_Done_Face (face);
1068     FT_Done_FreeType (ftLibrary);
1069     return pat;
1070
1071 bail2:
1072     FcCharSetDestroy (cs);
1073 bail1:
1074     FcPatternDestroy (pat);
1075     if (family_allocated)
1076         free (family);
1077     if (style_allocated)
1078         free (style);
1079 bail0:
1080     FT_Done_Face (face);
1081 bail:
1082     FT_Done_FreeType (ftLibrary);
1083     return 0;
1084 }
1085
1086
1087 /*
1088  * For our purposes, this approximation is sufficient
1089  */
1090 #if !HAVE_FT_GET_NEXT_CHAR
1091 #define FT_Get_Next_Char(face, ucs4, gi) ((ucs4) >= 0xffffff ? \
1092                                           (*(gi) = 0), 0 : \
1093                                           (*(gi) = 1), (ucs4) + 1)
1094 #warning "No FT_Get_Next_Char"
1095 #endif
1096
1097 typedef struct _FcCharEnt {
1098     FcChar16        bmp;
1099     unsigned char   encode;
1100 } FcCharEnt;
1101
1102 struct _FcCharMap {
1103     const FcCharEnt *ent;
1104     int             nent;
1105 };
1106
1107 typedef struct _FcFontDecode {
1108     FT_Encoding     encoding;
1109     const FcCharMap *map;
1110     FcChar32        max;
1111 } FcFontDecode;
1112
1113 static const FcCharEnt AppleRomanEnt[] = {
1114     { 0x0020, 0x20 }, /* SPACE */
1115     { 0x0021, 0x21 }, /* EXCLAMATION MARK */
1116     { 0x0022, 0x22 }, /* QUOTATION MARK */
1117     { 0x0023, 0x23 }, /* NUMBER SIGN */
1118     { 0x0024, 0x24 }, /* DOLLAR SIGN */
1119     { 0x0025, 0x25 }, /* PERCENT SIGN */
1120     { 0x0026, 0x26 }, /* AMPERSAND */
1121     { 0x0027, 0x27 }, /* APOSTROPHE */
1122     { 0x0028, 0x28 }, /* LEFT PARENTHESIS */
1123     { 0x0029, 0x29 }, /* RIGHT PARENTHESIS */
1124     { 0x002A, 0x2A }, /* ASTERISK */
1125     { 0x002B, 0x2B }, /* PLUS SIGN */
1126     { 0x002C, 0x2C }, /* COMMA */
1127     { 0x002D, 0x2D }, /* HYPHEN-MINUS */
1128     { 0x002E, 0x2E }, /* FULL STOP */
1129     { 0x002F, 0x2F }, /* SOLIDUS */
1130     { 0x0030, 0x30 }, /* DIGIT ZERO */
1131     { 0x0031, 0x31 }, /* DIGIT ONE */
1132     { 0x0032, 0x32 }, /* DIGIT TWO */
1133     { 0x0033, 0x33 }, /* DIGIT THREE */
1134     { 0x0034, 0x34 }, /* DIGIT FOUR */
1135     { 0x0035, 0x35 }, /* DIGIT FIVE */
1136     { 0x0036, 0x36 }, /* DIGIT SIX */
1137     { 0x0037, 0x37 }, /* DIGIT SEVEN */
1138     { 0x0038, 0x38 }, /* DIGIT EIGHT */
1139     { 0x0039, 0x39 }, /* DIGIT NINE */
1140     { 0x003A, 0x3A }, /* COLON */
1141     { 0x003B, 0x3B }, /* SEMICOLON */
1142     { 0x003C, 0x3C }, /* LESS-THAN SIGN */
1143     { 0x003D, 0x3D }, /* EQUALS SIGN */
1144     { 0x003E, 0x3E }, /* GREATER-THAN SIGN */
1145     { 0x003F, 0x3F }, /* QUESTION MARK */
1146     { 0x0040, 0x40 }, /* COMMERCIAL AT */
1147     { 0x0041, 0x41 }, /* LATIN CAPITAL LETTER A */
1148     { 0x0042, 0x42 }, /* LATIN CAPITAL LETTER B */
1149     { 0x0043, 0x43 }, /* LATIN CAPITAL LETTER C */
1150     { 0x0044, 0x44 }, /* LATIN CAPITAL LETTER D */
1151     { 0x0045, 0x45 }, /* LATIN CAPITAL LETTER E */
1152     { 0x0046, 0x46 }, /* LATIN CAPITAL LETTER F */
1153     { 0x0047, 0x47 }, /* LATIN CAPITAL LETTER G */
1154     { 0x0048, 0x48 }, /* LATIN CAPITAL LETTER H */
1155     { 0x0049, 0x49 }, /* LATIN CAPITAL LETTER I */
1156     { 0x004A, 0x4A }, /* LATIN CAPITAL LETTER J */
1157     { 0x004B, 0x4B }, /* LATIN CAPITAL LETTER K */
1158     { 0x004C, 0x4C }, /* LATIN CAPITAL LETTER L */
1159     { 0x004D, 0x4D }, /* LATIN CAPITAL LETTER M */
1160     { 0x004E, 0x4E }, /* LATIN CAPITAL LETTER N */
1161     { 0x004F, 0x4F }, /* LATIN CAPITAL LETTER O */
1162     { 0x0050, 0x50 }, /* LATIN CAPITAL LETTER P */
1163     { 0x0051, 0x51 }, /* LATIN CAPITAL LETTER Q */
1164     { 0x0052, 0x52 }, /* LATIN CAPITAL LETTER R */
1165     { 0x0053, 0x53 }, /* LATIN CAPITAL LETTER S */
1166     { 0x0054, 0x54 }, /* LATIN CAPITAL LETTER T */
1167     { 0x0055, 0x55 }, /* LATIN CAPITAL LETTER U */
1168     { 0x0056, 0x56 }, /* LATIN CAPITAL LETTER V */
1169     { 0x0057, 0x57 }, /* LATIN CAPITAL LETTER W */
1170     { 0x0058, 0x58 }, /* LATIN CAPITAL LETTER X */
1171     { 0x0059, 0x59 }, /* LATIN CAPITAL LETTER Y */
1172     { 0x005A, 0x5A }, /* LATIN CAPITAL LETTER Z */
1173     { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET */
1174     { 0x005C, 0x5C }, /* REVERSE SOLIDUS */
1175     { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET */
1176     { 0x005E, 0x5E }, /* CIRCUMFLEX ACCENT */
1177     { 0x005F, 0x5F }, /* LOW LINE */
1178     { 0x0060, 0x60 }, /* GRAVE ACCENT */
1179     { 0x0061, 0x61 }, /* LATIN SMALL LETTER A */
1180     { 0x0062, 0x62 }, /* LATIN SMALL LETTER B */
1181     { 0x0063, 0x63 }, /* LATIN SMALL LETTER C */
1182     { 0x0064, 0x64 }, /* LATIN SMALL LETTER D */
1183     { 0x0065, 0x65 }, /* LATIN SMALL LETTER E */
1184     { 0x0066, 0x66 }, /* LATIN SMALL LETTER F */
1185     { 0x0067, 0x67 }, /* LATIN SMALL LETTER G */
1186     { 0x0068, 0x68 }, /* LATIN SMALL LETTER H */
1187     { 0x0069, 0x69 }, /* LATIN SMALL LETTER I */
1188     { 0x006A, 0x6A }, /* LATIN SMALL LETTER J */
1189     { 0x006B, 0x6B }, /* LATIN SMALL LETTER K */
1190     { 0x006C, 0x6C }, /* LATIN SMALL LETTER L */
1191     { 0x006D, 0x6D }, /* LATIN SMALL LETTER M */
1192     { 0x006E, 0x6E }, /* LATIN SMALL LETTER N */
1193     { 0x006F, 0x6F }, /* LATIN SMALL LETTER O */
1194     { 0x0070, 0x70 }, /* LATIN SMALL LETTER P */
1195     { 0x0071, 0x71 }, /* LATIN SMALL LETTER Q */
1196     { 0x0072, 0x72 }, /* LATIN SMALL LETTER R */
1197     { 0x0073, 0x73 }, /* LATIN SMALL LETTER S */
1198     { 0x0074, 0x74 }, /* LATIN SMALL LETTER T */
1199     { 0x0075, 0x75 }, /* LATIN SMALL LETTER U */
1200     { 0x0076, 0x76 }, /* LATIN SMALL LETTER V */
1201     { 0x0077, 0x77 }, /* LATIN SMALL LETTER W */
1202     { 0x0078, 0x78 }, /* LATIN SMALL LETTER X */
1203     { 0x0079, 0x79 }, /* LATIN SMALL LETTER Y */
1204     { 0x007A, 0x7A }, /* LATIN SMALL LETTER Z */
1205     { 0x007B, 0x7B }, /* LEFT CURLY BRACKET */
1206     { 0x007C, 0x7C }, /* VERTICAL LINE */
1207     { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET */
1208     { 0x007E, 0x7E }, /* TILDE */
1209     { 0x00A0, 0xCA }, /* NO-BREAK SPACE */
1210     { 0x00A1, 0xC1 }, /* INVERTED EXCLAMATION MARK */
1211     { 0x00A2, 0xA2 }, /* CENT SIGN */
1212     { 0x00A3, 0xA3 }, /* POUND SIGN */
1213     { 0x00A5, 0xB4 }, /* YEN SIGN */
1214     { 0x00A7, 0xA4 }, /* SECTION SIGN */
1215     { 0x00A8, 0xAC }, /* DIAERESIS */
1216     { 0x00A9, 0xA9 }, /* COPYRIGHT SIGN */
1217     { 0x00AA, 0xBB }, /* FEMININE ORDINAL INDICATOR */
1218     { 0x00AB, 0xC7 }, /* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
1219     { 0x00AC, 0xC2 }, /* NOT SIGN */
1220     { 0x00AE, 0xA8 }, /* REGISTERED SIGN */
1221     { 0x00AF, 0xF8 }, /* MACRON */
1222     { 0x00B0, 0xA1 }, /* DEGREE SIGN */
1223     { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN */
1224     { 0x00B4, 0xAB }, /* ACUTE ACCENT */
1225     { 0x00B5, 0xB5 }, /* MICRO SIGN */
1226     { 0x00B6, 0xA6 }, /* PILCROW SIGN */
1227     { 0x00B7, 0xE1 }, /* MIDDLE DOT */
1228     { 0x00B8, 0xFC }, /* CEDILLA */
1229     { 0x00BA, 0xBC }, /* MASCULINE ORDINAL INDICATOR */
1230     { 0x00BB, 0xC8 }, /* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
1231     { 0x00BF, 0xC0 }, /* INVERTED QUESTION MARK */
1232     { 0x00C0, 0xCB }, /* LATIN CAPITAL LETTER A WITH GRAVE */
1233     { 0x00C1, 0xE7 }, /* LATIN CAPITAL LETTER A WITH ACUTE */
1234     { 0x00C2, 0xE5 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
1235     { 0x00C3, 0xCC }, /* LATIN CAPITAL LETTER A WITH TILDE */
1236     { 0x00C4, 0x80 }, /* LATIN CAPITAL LETTER A WITH DIAERESIS */
1237     { 0x00C5, 0x81 }, /* LATIN CAPITAL LETTER A WITH RING ABOVE */
1238     { 0x00C6, 0xAE }, /* LATIN CAPITAL LETTER AE */
1239     { 0x00C7, 0x82 }, /* LATIN CAPITAL LETTER C WITH CEDILLA */
1240     { 0x00C8, 0xE9 }, /* LATIN CAPITAL LETTER E WITH GRAVE */
1241     { 0x00C9, 0x83 }, /* LATIN CAPITAL LETTER E WITH ACUTE */
1242     { 0x00CA, 0xE6 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
1243     { 0x00CB, 0xE8 }, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
1244     { 0x00CC, 0xED }, /* LATIN CAPITAL LETTER I WITH GRAVE */
1245     { 0x00CD, 0xEA }, /* LATIN CAPITAL LETTER I WITH ACUTE */
1246     { 0x00CE, 0xEB }, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
1247     { 0x00CF, 0xEC }, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
1248     { 0x00D1, 0x84 }, /* LATIN CAPITAL LETTER N WITH TILDE */
1249     { 0x00D2, 0xF1 }, /* LATIN CAPITAL LETTER O WITH GRAVE */
1250     { 0x00D3, 0xEE }, /* LATIN CAPITAL LETTER O WITH ACUTE */
1251     { 0x00D4, 0xEF }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
1252     { 0x00D5, 0xCD }, /* LATIN CAPITAL LETTER O WITH TILDE */
1253     { 0x00D6, 0x85 }, /* LATIN CAPITAL LETTER O WITH DIAERESIS */
1254     { 0x00D8, 0xAF }, /* LATIN CAPITAL LETTER O WITH STROKE */
1255     { 0x00D9, 0xF4 }, /* LATIN CAPITAL LETTER U WITH GRAVE */
1256     { 0x00DA, 0xF2 }, /* LATIN CAPITAL LETTER U WITH ACUTE */
1257     { 0x00DB, 0xF3 }, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
1258     { 0x00DC, 0x86 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS */
1259     { 0x00DF, 0xA7 }, /* LATIN SMALL LETTER SHARP S */
1260     { 0x00E0, 0x88 }, /* LATIN SMALL LETTER A WITH GRAVE */
1261     { 0x00E1, 0x87 }, /* LATIN SMALL LETTER A WITH ACUTE */
1262     { 0x00E2, 0x89 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
1263     { 0x00E3, 0x8B }, /* LATIN SMALL LETTER A WITH TILDE */
1264     { 0x00E4, 0x8A }, /* LATIN SMALL LETTER A WITH DIAERESIS */
1265     { 0x00E5, 0x8C }, /* LATIN SMALL LETTER A WITH RING ABOVE */
1266     { 0x00E6, 0xBE }, /* LATIN SMALL LETTER AE */
1267     { 0x00E7, 0x8D }, /* LATIN SMALL LETTER C WITH CEDILLA */
1268     { 0x00E8, 0x8F }, /* LATIN SMALL LETTER E WITH GRAVE */
1269     { 0x00E9, 0x8E }, /* LATIN SMALL LETTER E WITH ACUTE */
1270     { 0x00EA, 0x90 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */
1271     { 0x00EB, 0x91 }, /* LATIN SMALL LETTER E WITH DIAERESIS */
1272     { 0x00EC, 0x93 }, /* LATIN SMALL LETTER I WITH GRAVE */
1273     { 0x00ED, 0x92 }, /* LATIN SMALL LETTER I WITH ACUTE */
1274     { 0x00EE, 0x94 }, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
1275     { 0x00EF, 0x95 }, /* LATIN SMALL LETTER I WITH DIAERESIS */
1276     { 0x00F1, 0x96 }, /* LATIN SMALL LETTER N WITH TILDE */
1277     { 0x00F2, 0x98 }, /* LATIN SMALL LETTER O WITH GRAVE */
1278     { 0x00F3, 0x97 }, /* LATIN SMALL LETTER O WITH ACUTE */
1279     { 0x00F4, 0x99 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
1280     { 0x00F5, 0x9B }, /* LATIN SMALL LETTER O WITH TILDE */
1281     { 0x00F6, 0x9A }, /* LATIN SMALL LETTER O WITH DIAERESIS */
1282     { 0x00F7, 0xD6 }, /* DIVISION SIGN */
1283     { 0x00F8, 0xBF }, /* LATIN SMALL LETTER O WITH STROKE */
1284     { 0x00F9, 0x9D }, /* LATIN SMALL LETTER U WITH GRAVE */
1285     { 0x00FA, 0x9C }, /* LATIN SMALL LETTER U WITH ACUTE */
1286     { 0x00FB, 0x9E }, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
1287     { 0x00FC, 0x9F }, /* LATIN SMALL LETTER U WITH DIAERESIS */
1288     { 0x00FF, 0xD8 }, /* LATIN SMALL LETTER Y WITH DIAERESIS */
1289     { 0x0131, 0xF5 }, /* LATIN SMALL LETTER DOTLESS I */
1290     { 0x0152, 0xCE }, /* LATIN CAPITAL LIGATURE OE */
1291     { 0x0153, 0xCF }, /* LATIN SMALL LIGATURE OE */
1292     { 0x0178, 0xD9 }, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
1293     { 0x0192, 0xC4 }, /* LATIN SMALL LETTER F WITH HOOK */
1294     { 0x02C6, 0xF6 }, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
1295     { 0x02C7, 0xFF }, /* CARON */
1296     { 0x02D8, 0xF9 }, /* BREVE */
1297     { 0x02D9, 0xFA }, /* DOT ABOVE */
1298     { 0x02DA, 0xFB }, /* RING ABOVE */
1299     { 0x02DB, 0xFE }, /* OGONEK */
1300     { 0x02DC, 0xF7 }, /* SMALL TILDE */
1301     { 0x02DD, 0xFD }, /* DOUBLE ACUTE ACCENT */
1302     { 0x03A9, 0xBD }, /* GREEK CAPITAL LETTER OMEGA */
1303     { 0x03C0, 0xB9 }, /* GREEK SMALL LETTER PI */
1304     { 0x2013, 0xD0 }, /* EN DASH */
1305     { 0x2014, 0xD1 }, /* EM DASH */
1306     { 0x2018, 0xD4 }, /* LEFT SINGLE QUOTATION MARK */
1307     { 0x2019, 0xD5 }, /* RIGHT SINGLE QUOTATION MARK */
1308     { 0x201A, 0xE2 }, /* SINGLE LOW-9 QUOTATION MARK */
1309     { 0x201C, 0xD2 }, /* LEFT DOUBLE QUOTATION MARK */
1310     { 0x201D, 0xD3 }, /* RIGHT DOUBLE QUOTATION MARK */
1311     { 0x201E, 0xE3 }, /* DOUBLE LOW-9 QUOTATION MARK */
1312     { 0x2020, 0xA0 }, /* DAGGER */
1313     { 0x2021, 0xE0 }, /* DOUBLE DAGGER */
1314     { 0x2022, 0xA5 }, /* BULLET */
1315     { 0x2026, 0xC9 }, /* HORIZONTAL ELLIPSIS */
1316     { 0x2030, 0xE4 }, /* PER MILLE SIGN */
1317     { 0x2039, 0xDC }, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
1318     { 0x203A, 0xDD }, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
1319     { 0x2044, 0xDA }, /* FRACTION SLASH */
1320     { 0x20AC, 0xDB }, /* EURO SIGN */
1321     { 0x2122, 0xAA }, /* TRADE MARK SIGN */
1322     { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL */
1323     { 0x2206, 0xC6 }, /* INCREMENT */
1324     { 0x220F, 0xB8 }, /* N-ARY PRODUCT */
1325     { 0x2211, 0xB7 }, /* N-ARY SUMMATION */
1326     { 0x221A, 0xC3 }, /* SQUARE ROOT */
1327     { 0x221E, 0xB0 }, /* INFINITY */
1328     { 0x222B, 0xBA }, /* INTEGRAL */
1329     { 0x2248, 0xC5 }, /* ALMOST EQUAL TO */
1330     { 0x2260, 0xAD }, /* NOT EQUAL TO */
1331     { 0x2264, 0xB2 }, /* LESS-THAN OR EQUAL TO */
1332     { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO */
1333     { 0x25CA, 0xD7 }, /* LOZENGE */
1334     { 0xF8FF, 0xF0 }, /* Apple logo */
1335     { 0xFB01, 0xDE }, /* LATIN SMALL LIGATURE FI */
1336     { 0xFB02, 0xDF }, /* LATIN SMALL LIGATURE FL */
1337 };
1338
1339 static const FcCharMap AppleRoman = {
1340     AppleRomanEnt,
1341     sizeof (AppleRomanEnt) / sizeof (AppleRomanEnt[0])
1342 };
1343
1344 static const FcCharEnt AdobeSymbolEnt[] = {
1345     { 0x0020, 0x20 }, /* SPACE  # space */
1346     { 0x0021, 0x21 }, /* EXCLAMATION MARK       # exclam */
1347     { 0x0023, 0x23 }, /* NUMBER SIGN    # numbersign */
1348     { 0x0025, 0x25 }, /* PERCENT SIGN   # percent */
1349     { 0x0026, 0x26 }, /* AMPERSAND      # ampersand */
1350     { 0x0028, 0x28 }, /* LEFT PARENTHESIS       # parenleft */
1351     { 0x0029, 0x29 }, /* RIGHT PARENTHESIS      # parenright */
1352     { 0x002B, 0x2B }, /* PLUS SIGN      # plus */
1353     { 0x002C, 0x2C }, /* COMMA  # comma */
1354     { 0x002E, 0x2E }, /* FULL STOP      # period */
1355     { 0x002F, 0x2F }, /* SOLIDUS        # slash */
1356     { 0x0030, 0x30 }, /* DIGIT ZERO     # zero */
1357     { 0x0031, 0x31 }, /* DIGIT ONE      # one */
1358     { 0x0032, 0x32 }, /* DIGIT TWO      # two */
1359     { 0x0033, 0x33 }, /* DIGIT THREE    # three */
1360     { 0x0034, 0x34 }, /* DIGIT FOUR     # four */
1361     { 0x0035, 0x35 }, /* DIGIT FIVE     # five */
1362     { 0x0036, 0x36 }, /* DIGIT SIX      # six */
1363     { 0x0037, 0x37 }, /* DIGIT SEVEN    # seven */
1364     { 0x0038, 0x38 }, /* DIGIT EIGHT    # eight */
1365     { 0x0039, 0x39 }, /* DIGIT NINE     # nine */
1366     { 0x003A, 0x3A }, /* COLON  # colon */
1367     { 0x003B, 0x3B }, /* SEMICOLON      # semicolon */
1368     { 0x003C, 0x3C }, /* LESS-THAN SIGN # less */
1369     { 0x003D, 0x3D }, /* EQUALS SIGN    # equal */
1370     { 0x003E, 0x3E }, /* GREATER-THAN SIGN      # greater */
1371     { 0x003F, 0x3F }, /* QUESTION MARK  # question */
1372     { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET    # bracketleft */
1373     { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET   # bracketright */
1374     { 0x005F, 0x5F }, /* LOW LINE       # underscore */
1375     { 0x007B, 0x7B }, /* LEFT CURLY BRACKET     # braceleft */
1376     { 0x007C, 0x7C }, /* VERTICAL LINE  # bar */
1377     { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET    # braceright */
1378     { 0x00A0, 0x20 }, /* NO-BREAK SPACE # space */
1379     { 0x00AC, 0xD8 }, /* NOT SIGN       # logicalnot */
1380     { 0x00B0, 0xB0 }, /* DEGREE SIGN    # degree */
1381     { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN        # plusminus */
1382     { 0x00B5, 0x6D }, /* MICRO SIGN     # mu */
1383     { 0x00D7, 0xB4 }, /* MULTIPLICATION SIGN    # multiply */
1384     { 0x00F7, 0xB8 }, /* DIVISION SIGN  # divide */
1385     { 0x0192, 0xA6 }, /* LATIN SMALL LETTER F WITH HOOK # florin */
1386     { 0x0391, 0x41 }, /* GREEK CAPITAL LETTER ALPHA     # Alpha */
1387     { 0x0392, 0x42 }, /* GREEK CAPITAL LETTER BETA      # Beta */
1388     { 0x0393, 0x47 }, /* GREEK CAPITAL LETTER GAMMA     # Gamma */
1389     { 0x0394, 0x44 }, /* GREEK CAPITAL LETTER DELTA     # Delta */
1390     { 0x0395, 0x45 }, /* GREEK CAPITAL LETTER EPSILON   # Epsilon */
1391     { 0x0396, 0x5A }, /* GREEK CAPITAL LETTER ZETA      # Zeta */
1392     { 0x0397, 0x48 }, /* GREEK CAPITAL LETTER ETA       # Eta */
1393     { 0x0398, 0x51 }, /* GREEK CAPITAL LETTER THETA     # Theta */
1394     { 0x0399, 0x49 }, /* GREEK CAPITAL LETTER IOTA      # Iota */
1395     { 0x039A, 0x4B }, /* GREEK CAPITAL LETTER KAPPA     # Kappa */
1396     { 0x039B, 0x4C }, /* GREEK CAPITAL LETTER LAMDA     # Lambda */
1397     { 0x039C, 0x4D }, /* GREEK CAPITAL LETTER MU        # Mu */
1398     { 0x039D, 0x4E }, /* GREEK CAPITAL LETTER NU        # Nu */
1399     { 0x039E, 0x58 }, /* GREEK CAPITAL LETTER XI        # Xi */
1400     { 0x039F, 0x4F }, /* GREEK CAPITAL LETTER OMICRON   # Omicron */
1401     { 0x03A0, 0x50 }, /* GREEK CAPITAL LETTER PI        # Pi */
1402     { 0x03A1, 0x52 }, /* GREEK CAPITAL LETTER RHO       # Rho */
1403     { 0x03A3, 0x53 }, /* GREEK CAPITAL LETTER SIGMA     # Sigma */
1404     { 0x03A4, 0x54 }, /* GREEK CAPITAL LETTER TAU       # Tau */
1405     { 0x03A5, 0x55 }, /* GREEK CAPITAL LETTER UPSILON   # Upsilon */
1406     { 0x03A6, 0x46 }, /* GREEK CAPITAL LETTER PHI       # Phi */
1407     { 0x03A7, 0x43 }, /* GREEK CAPITAL LETTER CHI       # Chi */
1408     { 0x03A8, 0x59 }, /* GREEK CAPITAL LETTER PSI       # Psi */
1409     { 0x03A9, 0x57 }, /* GREEK CAPITAL LETTER OMEGA     # Omega */
1410     { 0x03B1, 0x61 }, /* GREEK SMALL LETTER ALPHA       # alpha */
1411     { 0x03B2, 0x62 }, /* GREEK SMALL LETTER BETA        # beta */
1412     { 0x03B3, 0x67 }, /* GREEK SMALL LETTER GAMMA       # gamma */
1413     { 0x03B4, 0x64 }, /* GREEK SMALL LETTER DELTA       # delta */
1414     { 0x03B5, 0x65 }, /* GREEK SMALL LETTER EPSILON     # epsilon */
1415     { 0x03B6, 0x7A }, /* GREEK SMALL LETTER ZETA        # zeta */
1416     { 0x03B7, 0x68 }, /* GREEK SMALL LETTER ETA # eta */
1417     { 0x03B8, 0x71 }, /* GREEK SMALL LETTER THETA       # theta */
1418     { 0x03B9, 0x69 }, /* GREEK SMALL LETTER IOTA        # iota */
1419     { 0x03BA, 0x6B }, /* GREEK SMALL LETTER KAPPA       # kappa */
1420     { 0x03BB, 0x6C }, /* GREEK SMALL LETTER LAMDA       # lambda */
1421     { 0x03BC, 0x6D }, /* GREEK SMALL LETTER MU  # mu */
1422     { 0x03BD, 0x6E }, /* GREEK SMALL LETTER NU  # nu */
1423     { 0x03BE, 0x78 }, /* GREEK SMALL LETTER XI  # xi */
1424     { 0x03BF, 0x6F }, /* GREEK SMALL LETTER OMICRON     # omicron */
1425     { 0x03C0, 0x70 }, /* GREEK SMALL LETTER PI  # pi */
1426     { 0x03C1, 0x72 }, /* GREEK SMALL LETTER RHO # rho */
1427     { 0x03C2, 0x56 }, /* GREEK SMALL LETTER FINAL SIGMA # sigma1 */
1428     { 0x03C3, 0x73 }, /* GREEK SMALL LETTER SIGMA       # sigma */
1429     { 0x03C4, 0x74 }, /* GREEK SMALL LETTER TAU # tau */
1430     { 0x03C5, 0x75 }, /* GREEK SMALL LETTER UPSILON     # upsilon */
1431     { 0x03C6, 0x66 }, /* GREEK SMALL LETTER PHI # phi */
1432     { 0x03C7, 0x63 }, /* GREEK SMALL LETTER CHI # chi */
1433     { 0x03C8, 0x79 }, /* GREEK SMALL LETTER PSI # psi */
1434     { 0x03C9, 0x77 }, /* GREEK SMALL LETTER OMEGA       # omega */
1435     { 0x03D1, 0x4A }, /* GREEK THETA SYMBOL     # theta1 */
1436     { 0x03D2, 0xA1 }, /* GREEK UPSILON WITH HOOK SYMBOL # Upsilon1 */
1437     { 0x03D5, 0x6A }, /* GREEK PHI SYMBOL       # phi1 */
1438     { 0x03D6, 0x76 }, /* GREEK PI SYMBOL        # omega1 */
1439     { 0x2022, 0xB7 }, /* BULLET # bullet */
1440     { 0x2026, 0xBC }, /* HORIZONTAL ELLIPSIS    # ellipsis */
1441     { 0x2032, 0xA2 }, /* PRIME  # minute */
1442     { 0x2033, 0xB2 }, /* DOUBLE PRIME   # second */
1443     { 0x2044, 0xA4 }, /* FRACTION SLASH # fraction */
1444     { 0x20AC, 0xA0 }, /* EURO SIGN      # Euro */
1445     { 0x2111, 0xC1 }, /* BLACK-LETTER CAPITAL I # Ifraktur */
1446     { 0x2118, 0xC3 }, /* SCRIPT CAPITAL P       # weierstrass */
1447     { 0x211C, 0xC2 }, /* BLACK-LETTER CAPITAL R # Rfraktur */
1448     { 0x2126, 0x57 }, /* OHM SIGN       # Omega */
1449     { 0x2135, 0xC0 }, /* ALEF SYMBOL    # aleph */
1450     { 0x2190, 0xAC }, /* LEFTWARDS ARROW        # arrowleft */
1451     { 0x2191, 0xAD }, /* UPWARDS ARROW  # arrowup */
1452     { 0x2192, 0xAE }, /* RIGHTWARDS ARROW       # arrowright */
1453     { 0x2193, 0xAF }, /* DOWNWARDS ARROW        # arrowdown */
1454     { 0x2194, 0xAB }, /* LEFT RIGHT ARROW       # arrowboth */
1455     { 0x21B5, 0xBF }, /* DOWNWARDS ARROW WITH CORNER LEFTWARDS  # carriagereturn */
1456     { 0x21D0, 0xDC }, /* LEFTWARDS DOUBLE ARROW # arrowdblleft */
1457     { 0x21D1, 0xDD }, /* UPWARDS DOUBLE ARROW   # arrowdblup */
1458     { 0x21D2, 0xDE }, /* RIGHTWARDS DOUBLE ARROW        # arrowdblright */
1459     { 0x21D3, 0xDF }, /* DOWNWARDS DOUBLE ARROW # arrowdbldown */
1460     { 0x21D4, 0xDB }, /* LEFT RIGHT DOUBLE ARROW        # arrowdblboth */
1461     { 0x2200, 0x22 }, /* FOR ALL        # universal */
1462     { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL   # partialdiff */
1463     { 0x2203, 0x24 }, /* THERE EXISTS   # existential */
1464     { 0x2205, 0xC6 }, /* EMPTY SET      # emptyset */
1465     { 0x2206, 0x44 }, /* INCREMENT      # Delta */
1466     { 0x2207, 0xD1 }, /* NABLA  # gradient */
1467     { 0x2208, 0xCE }, /* ELEMENT OF     # element */
1468     { 0x2209, 0xCF }, /* NOT AN ELEMENT OF      # notelement */
1469     { 0x220B, 0x27 }, /* CONTAINS AS MEMBER     # suchthat */
1470     { 0x220F, 0xD5 }, /* N-ARY PRODUCT  # product */
1471     { 0x2211, 0xE5 }, /* N-ARY SUMMATION        # summation */
1472     { 0x2212, 0x2D }, /* MINUS SIGN     # minus */
1473     { 0x2215, 0xA4 }, /* DIVISION SLASH # fraction */
1474     { 0x2217, 0x2A }, /* ASTERISK OPERATOR      # asteriskmath */
1475     { 0x221A, 0xD6 }, /* SQUARE ROOT    # radical */
1476     { 0x221D, 0xB5 }, /* PROPORTIONAL TO        # proportional */
1477     { 0x221E, 0xA5 }, /* INFINITY       # infinity */
1478     { 0x2220, 0xD0 }, /* ANGLE  # angle */
1479     { 0x2227, 0xD9 }, /* LOGICAL AND    # logicaland */
1480     { 0x2228, 0xDA }, /* LOGICAL OR     # logicalor */
1481     { 0x2229, 0xC7 }, /* INTERSECTION   # intersection */
1482     { 0x222A, 0xC8 }, /* UNION  # union */
1483     { 0x222B, 0xF2 }, /* INTEGRAL       # integral */
1484     { 0x2234, 0x5C }, /* THEREFORE      # therefore */
1485     { 0x223C, 0x7E }, /* TILDE OPERATOR # similar */
1486     { 0x2245, 0x40 }, /* APPROXIMATELY EQUAL TO # congruent */
1487     { 0x2248, 0xBB }, /* ALMOST EQUAL TO        # approxequal */
1488     { 0x2260, 0xB9 }, /* NOT EQUAL TO   # notequal */
1489     { 0x2261, 0xBA }, /* IDENTICAL TO   # equivalence */
1490     { 0x2264, 0xA3 }, /* LESS-THAN OR EQUAL TO  # lessequal */
1491     { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO       # greaterequal */
1492     { 0x2282, 0xCC }, /* SUBSET OF      # propersubset */
1493     { 0x2283, 0xC9 }, /* SUPERSET OF    # propersuperset */
1494     { 0x2284, 0xCB }, /* NOT A SUBSET OF        # notsubset */
1495     { 0x2286, 0xCD }, /* SUBSET OF OR EQUAL TO  # reflexsubset */
1496     { 0x2287, 0xCA }, /* SUPERSET OF OR EQUAL TO        # reflexsuperset */
1497     { 0x2295, 0xC5 }, /* CIRCLED PLUS   # circleplus */
1498     { 0x2297, 0xC4 }, /* CIRCLED TIMES  # circlemultiply */
1499     { 0x22A5, 0x5E }, /* UP TACK        # perpendicular */
1500     { 0x22C5, 0xD7 }, /* DOT OPERATOR   # dotmath */
1501     { 0x2320, 0xF3 }, /* TOP HALF INTEGRAL      # integraltp */
1502     { 0x2321, 0xF5 }, /* BOTTOM HALF INTEGRAL   # integralbt */
1503     { 0x2329, 0xE1 }, /* LEFT-POINTING ANGLE BRACKET    # angleleft */
1504     { 0x232A, 0xF1 }, /* RIGHT-POINTING ANGLE BRACKET   # angleright */
1505     { 0x25CA, 0xE0 }, /* LOZENGE        # lozenge */
1506     { 0x2660, 0xAA }, /* BLACK SPADE SUIT       # spade */
1507     { 0x2663, 0xA7 }, /* BLACK CLUB SUIT        # club */
1508     { 0x2665, 0xA9 }, /* BLACK HEART SUIT       # heart */
1509     { 0x2666, 0xA8 }, /* BLACK DIAMOND SUIT     # diamond */
1510     { 0xF6D9, 0xD3 }, /* COPYRIGHT SIGN SERIF   # copyrightserif (CUS) */
1511     { 0xF6DA, 0xD2 }, /* REGISTERED SIGN SERIF  # registerserif (CUS) */
1512     { 0xF6DB, 0xD4 }, /* TRADE MARK SIGN SERIF  # trademarkserif (CUS) */
1513     { 0xF8E5, 0x60 }, /* RADICAL EXTENDER       # radicalex (CUS) */
1514     { 0xF8E6, 0xBD }, /* VERTICAL ARROW EXTENDER        # arrowvertex (CUS) */
1515     { 0xF8E7, 0xBE }, /* HORIZONTAL ARROW EXTENDER      # arrowhorizex (CUS) */
1516     { 0xF8E8, 0xE2 }, /* REGISTERED SIGN SANS SERIF     # registersans (CUS) */
1517     { 0xF8E9, 0xE3 }, /* COPYRIGHT SIGN SANS SERIF      # copyrightsans (CUS) */
1518     { 0xF8EA, 0xE4 }, /* TRADE MARK SIGN SANS SERIF     # trademarksans (CUS) */
1519     { 0xF8EB, 0xE6 }, /* LEFT PAREN TOP # parenlefttp (CUS) */
1520     { 0xF8EC, 0xE7 }, /* LEFT PAREN EXTENDER    # parenleftex (CUS) */
1521     { 0xF8ED, 0xE8 }, /* LEFT PAREN BOTTOM      # parenleftbt (CUS) */
1522     { 0xF8EE, 0xE9 }, /* LEFT SQUARE BRACKET TOP        # bracketlefttp (CUS) */
1523     { 0xF8EF, 0xEA }, /* LEFT SQUARE BRACKET EXTENDER   # bracketleftex (CUS) */
1524     { 0xF8F0, 0xEB }, /* LEFT SQUARE BRACKET BOTTOM     # bracketleftbt (CUS) */
1525     { 0xF8F1, 0xEC }, /* LEFT CURLY BRACKET TOP # bracelefttp (CUS) */
1526     { 0xF8F2, 0xED }, /* LEFT CURLY BRACKET MID # braceleftmid (CUS) */
1527     { 0xF8F3, 0xEE }, /* LEFT CURLY BRACKET BOTTOM      # braceleftbt (CUS) */
1528     { 0xF8F4, 0xEF }, /* CURLY BRACKET EXTENDER # braceex (CUS) */
1529     { 0xF8F5, 0xF4 }, /* INTEGRAL EXTENDER      # integralex (CUS) */
1530     { 0xF8F6, 0xF6 }, /* RIGHT PAREN TOP        # parenrighttp (CUS) */
1531     { 0xF8F7, 0xF7 }, /* RIGHT PAREN EXTENDER   # parenrightex (CUS) */
1532     { 0xF8F8, 0xF8 }, /* RIGHT PAREN BOTTOM     # parenrightbt (CUS) */
1533     { 0xF8F9, 0xF9 }, /* RIGHT SQUARE BRACKET TOP       # bracketrighttp (CUS) */
1534     { 0xF8FA, 0xFA }, /* RIGHT SQUARE BRACKET EXTENDER  # bracketrightex (CUS) */
1535     { 0xF8FB, 0xFB }, /* RIGHT SQUARE BRACKET BOTTOM    # bracketrightbt (CUS) */
1536     { 0xF8FC, 0xFC }, /* RIGHT CURLY BRACKET TOP        # bracerighttp (CUS) */
1537     { 0xF8FD, 0xFD }, /* RIGHT CURLY BRACKET MID        # bracerightmid (CUS) */
1538     { 0xF8FE, 0xFE }, /* RIGHT CURLY BRACKET BOTTOM     # bracerightbt (CUS) */
1539 };
1540
1541 static const FcCharMap AdobeSymbol = {
1542     AdobeSymbolEnt,
1543     sizeof (AdobeSymbolEnt) / sizeof (AdobeSymbolEnt[0]),
1544 };
1545     
1546 static const FcFontDecode fcFontDecoders[] = {
1547     { ft_encoding_unicode,      0,              (1 << 21) - 1 },
1548     { ft_encoding_symbol,       &AdobeSymbol,   (1 << 16) - 1 },
1549     { ft_encoding_apple_roman,  &AppleRoman,    (1 << 16) - 1 },
1550 };
1551
1552 #define NUM_DECODE  (sizeof (fcFontDecoders) / sizeof (fcFontDecoders[0]))
1553
1554 FcChar32
1555 FcFreeTypeUcs4ToPrivate (FcChar32 ucs4, const FcCharMap *map)
1556 {
1557     int         low, high, mid;
1558     FcChar16    bmp;
1559
1560     low = 0;
1561     high = map->nent - 1;
1562     if (ucs4 < map->ent[low].bmp || map->ent[high].bmp < ucs4)
1563         return ~0;
1564     while (low <= high)
1565     {
1566         mid = (high + low) >> 1;
1567         bmp = map->ent[mid].bmp;
1568         if (ucs4 == bmp)
1569             return (FT_ULong) map->ent[mid].encode;
1570         if (ucs4 < bmp)
1571             high = mid - 1;
1572         else
1573             low = mid + 1;
1574     }
1575     return ~0;
1576 }
1577
1578 FcChar32
1579 FcFreeTypePrivateToUcs4 (FcChar32 private, const FcCharMap *map)
1580 {
1581     int     i;
1582
1583     for (i = 0; i < map->nent; i++)
1584         if (map->ent[i].encode == private)
1585             return (FcChar32) map->ent[i].bmp;
1586     return ~0;
1587 }
1588
1589 const FcCharMap *
1590 FcFreeTypeGetPrivateMap (FT_Encoding encoding)
1591 {
1592     int i;
1593
1594     for (i = 0; i < NUM_DECODE; i++)
1595         if (fcFontDecoders[i].encoding == encoding)
1596             return fcFontDecoders[i].map;
1597     return 0;
1598 }
1599
1600 #include "../fc-glyphname/fcglyphname.h"
1601
1602 static FcChar32
1603 FcHashGlyphName (const FcChar8 *name)
1604 {
1605     FcChar32    h = 0;
1606     FcChar8     c;
1607
1608     while ((c = *name++))
1609     {
1610         h = ((h << 1) | (h >> 31)) ^ c;
1611     }
1612     return h;
1613 }
1614
1615 #if HAVE_FT_HAS_PS_GLYPH_NAMES
1616 /*
1617  * Use Type1 glyph names for fonts which have reliable names
1618  * and which export an Adobe Custom mapping
1619  */
1620 static FcBool
1621 FcFreeTypeUseNames (FT_Face face)
1622 {
1623     FT_Int  map;
1624     
1625     if (!FT_Has_PS_Glyph_Names (face))
1626         return FcFalse;
1627     for (map = 0; map < face->num_charmaps; map++)
1628         if (face->charmaps[map]->encoding == ft_encoding_adobe_custom)
1629             return FcTrue;
1630     return FcFalse;
1631 }
1632
1633 static FcChar8 *
1634 FcUcs4ToGlyphName (FcChar32 ucs4)
1635 {
1636     int         i = (int) (ucs4 % FC_GLYPHNAME_HASH);
1637     int         r = 0;
1638     FcGlyphName *gn;
1639
1640     while ((gn = ucs_to_name[i]))
1641     {
1642         if (gn->ucs == ucs4)
1643             return gn->name;
1644         if (!r) 
1645         {
1646             r = (int) (ucs4 % FC_GLYPHNAME_REHASH);
1647             if (!r)
1648                 r = 1;
1649         }
1650         i += r;
1651         if (i >= FC_GLYPHNAME_HASH)
1652             i -= FC_GLYPHNAME_HASH;
1653     }
1654     return 0;
1655 }
1656
1657 static FcChar32
1658 FcGlyphNameToUcs4 (FcChar8 *name)
1659 {
1660     FcChar32    h = FcHashGlyphName (name);
1661     int         i = (int) (h % FC_GLYPHNAME_HASH);
1662     int         r = 0;
1663     FcGlyphName *gn;
1664
1665     while ((gn = name_to_ucs[i]))
1666     {
1667         if (!strcmp ((char *) name, (char *) gn->name))
1668             return gn->ucs;
1669         if (!r) 
1670         {
1671             r = (int) (h % FC_GLYPHNAME_REHASH);
1672             if (!r)
1673                 r = 1;
1674         }
1675         i += r;
1676         if (i >= FC_GLYPHNAME_HASH)
1677             i -= FC_GLYPHNAME_HASH;
1678     }
1679     return 0xffff;
1680 }
1681
1682 /*
1683  * Search through a font for a glyph by name.  This is
1684  * currently a linear search as there doesn't appear to be
1685  * any defined order within the font
1686  */
1687 static FT_UInt
1688 FcFreeTypeGlyphNameIndex (FT_Face face, FcChar8 *name)
1689 {
1690     FT_UInt gindex;
1691     FcChar8 name_buf[FC_GLYPHNAME_MAXLEN + 2];
1692
1693     for (gindex = 0; gindex < face->num_glyphs; gindex++)
1694     {
1695         if (FT_Get_Glyph_Name (face, gindex, name_buf, FC_GLYPHNAME_MAXLEN+1) == 0)
1696             if (!strcmp ((char *) name, (char *) name_buf))
1697                 return gindex;
1698     }
1699     return 0;
1700 }
1701 #endif
1702
1703 /*
1704  * Map a UCS4 glyph to a glyph index.  Use all available encoding
1705  * tables to try and find one that works.  This information is expected
1706  * to be cached by higher levels, so performance isn't critical
1707  */
1708
1709 FT_UInt
1710 FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
1711 {
1712     int             initial, offset, decode;
1713     FT_UInt         glyphindex;
1714     FcChar32        charcode;
1715
1716     initial = 0;
1717     /*
1718      * Find the current encoding
1719      */
1720     if (face->charmap)
1721     {
1722         for (; initial < NUM_DECODE; initial++)
1723             if (fcFontDecoders[initial].encoding == face->charmap->encoding)
1724                 break;
1725         if (initial == NUM_DECODE)
1726             initial = 0;
1727     }
1728     /*
1729      * Check each encoding for the glyph, starting with the current one
1730      */
1731     for (offset = 0; offset < NUM_DECODE; offset++)
1732     {
1733         decode = (initial + offset) % NUM_DECODE;
1734         if (!face->charmap || face->charmap->encoding != fcFontDecoders[decode].encoding)
1735             if (FT_Select_Charmap (face, fcFontDecoders[decode].encoding) != 0)
1736                 continue;
1737         if (fcFontDecoders[decode].map)
1738         {
1739             charcode = FcFreeTypeUcs4ToPrivate (ucs4, fcFontDecoders[decode].map);
1740             if (charcode == ~0)
1741                 continue;
1742         }
1743         else
1744             charcode = ucs4;
1745         glyphindex = FT_Get_Char_Index (face, (FT_ULong) charcode);
1746         if (glyphindex)
1747             return glyphindex;
1748     }
1749 #if HAVE_FT_HAS_PS_GLYPH_NAMES
1750     /*
1751      * Check postscript name table if present
1752      */
1753     if (FcFreeTypeUseNames (face))
1754     {
1755         FcChar8 *name = FcUcs4ToGlyphName (ucs4);
1756         if (name)
1757         {
1758             glyphindex = FcFreeTypeGlyphNameIndex (face, name);
1759             if (glyphindex)
1760                 return glyphindex;
1761         }
1762     }
1763 #endif
1764     return 0;
1765 }
1766
1767 static FcBool
1768 FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4, 
1769                       FT_UInt glyph, FcBlanks *blanks,
1770                       FT_Pos *advance)
1771 {
1772     FT_Int          load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
1773     FT_GlyphSlot    slot;
1774     
1775     /*
1776      * For bitmap-only fonts, assume that they're OK.
1777      */
1778     if ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0)
1779         return FcTrue;
1780
1781     /*
1782      * When using scalable fonts, only report those glyphs
1783      * which can be scaled; otherwise those fonts will
1784      * only be available at some sizes, and never when
1785      * transformed.  Avoid this by simply reporting bitmap-only
1786      * glyphs as missing
1787      */
1788     if (face->face_flags & FT_FACE_FLAG_SCALABLE)
1789         load_flags |= FT_LOAD_NO_BITMAP;
1790     
1791     if (FT_Load_Glyph (face, glyph, load_flags))
1792         return FcFalse;
1793     
1794     slot = face->glyph;
1795     if (!glyph)
1796         return FcFalse;
1797     
1798     *advance = slot->metrics.horiAdvance;
1799
1800     switch (slot->format) {
1801     case ft_glyph_format_bitmap:
1802         /*
1803          * Bitmaps are assumed to be reasonable; if
1804          * this proves to be a rash assumption, this
1805          * code can be easily modified
1806          */
1807         return FcTrue;
1808     case ft_glyph_format_outline:
1809         /*
1810          * Glyphs with contours are always OK
1811          */
1812         if (slot->outline.n_contours != 0)
1813             return FcTrue;
1814         /*
1815          * Glyphs with no contours are only OK if
1816          * they're members of the Blanks set specified
1817          * in the configuration.  If blanks isn't set,
1818          * then allow any glyph to be blank
1819          */
1820         if (!blanks || FcBlanksIsMember (blanks, ucs4))
1821             return FcTrue;
1822         /* fall through ... */
1823     default:
1824         break;
1825     }
1826     return FcFalse;
1827 }
1828
1829 #define APPROXIMATELY_EQUAL(x,y) (ABS ((x) - (y)) <= MAX (ABS (x), ABS (y)) / 33)
1830
1831 FcCharSet *
1832 FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
1833 {
1834     FcChar32        page, off, max, ucs4;
1835 #ifdef CHECK
1836     FcChar32        font_max = 0;
1837 #endif
1838     FcCharSet       *fcs;
1839     FcCharLeaf      *leaf;
1840     const FcCharMap *map;
1841     int             o;
1842     int             i;
1843     FT_UInt         glyph;
1844     FT_Pos          advance, advance_one = 0, advance_two = 0;
1845     FcBool          has_advance = FcFalse, fixed_advance = FcTrue, dual_advance = FcFalse;
1846
1847     fcs = FcCharSetCreate ();
1848     if (!fcs)
1849         goto bail0;
1850     
1851 #ifdef CHECK
1852     printf ("Family %s style %s\n", face->family_name, face->style_name);
1853 #endif
1854     for (o = 0; o < NUM_DECODE; o++)
1855     {
1856         if (FT_Select_Charmap (face, fcFontDecoders[o].encoding) != 0)
1857             continue;
1858         map = fcFontDecoders[o].map;
1859         if (map)
1860         {
1861             /*
1862              * Non-Unicode tables are easy; there's a list of all possible
1863              * characters
1864              */
1865             for (i = 0; i < map->nent; i++)
1866             {
1867                 ucs4 = map->ent[i].bmp;
1868                 glyph = FT_Get_Char_Index (face, map->ent[i].encode);
1869                 if (glyph && 
1870                     FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance))
1871                 {
1872                     if (!has_advance)
1873                     {
1874                         has_advance = FcTrue;
1875                         advance_one = advance;
1876                     }
1877                     else if (!APPROXIMATELY_EQUAL (advance, advance_one))
1878                     {
1879                         if (fixed_advance)
1880                         {
1881                             dual_advance = FcTrue;
1882                             fixed_advance = FcFalse;
1883                             advance_two = advance;
1884                         }
1885                         else if (!APPROXIMATELY_EQUAL (advance, advance_two))
1886                             dual_advance = FcFalse;
1887                     }
1888
1889                     leaf = FcCharSetFindLeafCreate (fcs, ucs4);
1890                     if (!leaf)
1891                         goto bail1;
1892                     leaf->map[(ucs4 & 0xff) >> 5] |= (1 << (ucs4 & 0x1f));
1893 #ifdef CHECK
1894                     if (ucs4 > font_max)
1895                         font_max = ucs4;
1896 #endif
1897                 }
1898             }
1899         }
1900         else
1901         {
1902             FT_UInt gindex;
1903           
1904             max = fcFontDecoders[o].max;
1905             /*
1906              * Find the first encoded character in the font
1907              */
1908             if (FT_Get_Char_Index (face, 0))
1909             {
1910                 ucs4 = 0;
1911                 gindex = 1;
1912             }
1913             else
1914             {
1915                 ucs4 = FT_Get_Next_Char (face, 0, &gindex);
1916                 if (!ucs4)
1917                     gindex = 0;
1918             }
1919
1920             while (gindex)
1921             {
1922                 page = ucs4 >> 8;
1923                 leaf = 0;
1924                 while ((ucs4 >> 8) == page)
1925                 {
1926                     glyph = FT_Get_Char_Index (face, ucs4);
1927                     if (glyph && FcFreeTypeCheckGlyph (face, ucs4, 
1928                                                        glyph, blanks, &advance))
1929                     {
1930                         if (!has_advance)
1931                         {
1932                             has_advance = FcTrue;
1933                             advance_one = advance;
1934                         }
1935                         else if (!APPROXIMATELY_EQUAL (advance, advance_one))
1936                         {
1937                             if (fixed_advance)
1938                             {
1939                                 dual_advance = FcTrue;
1940                                 fixed_advance = FcFalse;
1941                                 advance_two = advance;
1942                             }
1943                             else if (!APPROXIMATELY_EQUAL (advance, advance_two))
1944                                 dual_advance = FcFalse;
1945                         }
1946
1947                         if (!leaf)
1948                         {
1949                             leaf = FcCharSetFindLeafCreate (fcs, ucs4);
1950                             if (!leaf)
1951                                 goto bail1;
1952                         }
1953                         off = ucs4 & 0xff;
1954                         leaf->map[off >> 5] |= (1 << (off & 0x1f));
1955 #ifdef CHECK
1956                         if (ucs4 > font_max)
1957                             font_max = ucs4;
1958 #endif
1959                     }
1960                     ucs4++;
1961                 }
1962                 ucs4 = FT_Get_Next_Char (face, ucs4 - 1, &gindex);
1963                 if (!ucs4)
1964                     gindex = 0;
1965             }
1966 #ifdef CHECK
1967             for (ucs4 = 0; ucs4 < 0x10000; ucs4++)
1968             {
1969                 FcBool      FT_Has, FC_Has;
1970
1971                 FT_Has = FT_Get_Char_Index (face, ucs4) != 0;
1972                 FC_Has = FcCharSetHasChar (fcs, ucs4);
1973                 if (FT_Has != FC_Has)
1974                 {
1975                     printf ("0x%08x FT says %d FC says %d\n", ucs4, FT_Has, FC_Has);
1976                 }
1977             }
1978 #endif
1979         }
1980     }
1981 #if HAVE_FT_HAS_PS_GLYPH_NAMES
1982     /*
1983      * Add mapping from PS glyph names if available
1984      */
1985     if (FcFreeTypeUseNames (face))
1986     {
1987         FcChar8 name_buf[FC_GLYPHNAME_MAXLEN + 2];
1988
1989         for (glyph = 0; glyph < face->num_glyphs; glyph++)
1990         {
1991             if (FT_Get_Glyph_Name (face, glyph, name_buf, FC_GLYPHNAME_MAXLEN+1) == 0)
1992             {
1993                 ucs4 = FcGlyphNameToUcs4 (name_buf);
1994                 if (ucs4 != 0xffff && 
1995                     FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance))
1996                 {
1997                     if (!has_advance)
1998                     {
1999                         has_advance = FcTrue;
2000                         advance_one = advance;
2001                     }
2002                     else if (!APPROXIMATELY_EQUAL (advance, advance_one))
2003                     {
2004                         if (fixed_advance)
2005                         {
2006                             dual_advance = FcTrue;
2007                             fixed_advance = FcFalse;
2008                             advance_two = advance;
2009                         }
2010                         else if (!APPROXIMATELY_EQUAL (advance, advance_two))
2011                             dual_advance = FcFalse;
2012                     }
2013                     leaf = FcCharSetFindLeafCreate (fcs, ucs4);
2014                     if (!leaf)
2015                         goto bail1;
2016                     leaf->map[(ucs4 & 0xff) >> 5] |= (1 << (ucs4 & 0x1f));
2017 #ifdef CHECK
2018                     if (ucs4 > font_max)
2019                         font_max = ucs4;
2020 #endif
2021                 }
2022             }
2023         }
2024     }
2025 #endif
2026 #ifdef CHECK
2027     printf ("%d glyphs %d encoded\n", (int) face->num_glyphs, FcCharSetCount (fcs));
2028     for (ucs4 = 0; ucs4 <= font_max; ucs4++)
2029     {
2030         FcBool  has_char = (glyph = FcFreeTypeCharIndex (face, ucs4)) != 0;
2031         FcBool  has_bit = FcCharSetHasChar (fcs, ucs4);
2032
2033         if (has_char && !has_bit)
2034         {
2035             if (!FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance))
2036                 printf ("Bitmap missing broken char 0x%x\n", ucs4);
2037             else
2038                 printf ("Bitmap missing char 0x%x\n", ucs4);
2039         }
2040         else if (!has_char && has_bit)
2041             printf ("Bitmap extra char 0x%x\n", ucs4);
2042     }
2043 #endif
2044     if (fixed_advance)
2045         *spacing = FC_MONO;
2046     else if (dual_advance && APPROXIMATELY_EQUAL (2 * MIN (advance_one, advance_two), MAX (advance_one, advance_two)))
2047         *spacing = FC_DUAL;
2048     else
2049         *spacing = FC_PROPORTIONAL;
2050     return fcs;
2051 bail1:
2052     FcCharSetDestroy (fcs);
2053 bail0:
2054     return 0;
2055 }
2056
2057 FcCharSet *
2058 FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks)
2059 {
2060     int spacing;
2061
2062     return FcFreeTypeCharSetAndSpacing (face, blanks, &spacing);
2063 }