2 * $RCSId: xc/lib/fontconfig/src/fcfreetype.c,v 1.11 2002/08/31 22:17:32 keithp Exp $
4 * Copyright © 2001 Keith Packard
6 * Permission to use, copy, modify, distribute, and sell this software and its
7 * documentation for any purpose is hereby granted without fee, provided that
8 * the above copyright notice appear in all copies and that both that
9 * copyright notice and this permission notice appear in supporting
10 * documentation, and that the name of Keith Packard not be used in
11 * advertising or publicity pertaining to distribution of the software without
12 * specific, written prior permission. Keith Packard makes no
13 * representations about the suitability of this software for any purpose. It
14 * is provided "as is" without express or implied warranty.
16 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
17 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
18 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
19 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
20 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
21 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
22 * PERFORMANCE OF THIS SOFTWARE.
26 Copyright © 2002-2003 by Juliusz Chroboczek
28 Permission is hereby granted, free of charge, to any person obtaining a copy
29 of this software and associated documentation files (the "Software"), to deal
30 in the Software without restriction, including without limitation the rights
31 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
32 copies of the Software, and to permit persons to whom the Software is
33 furnished to do so, subject to the following conditions:
35 The above copyright notice and this permission notice shall be included in
36 all copies or substantial portions of the Software.
38 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
39 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
41 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
43 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
52 #include FT_FREETYPE_H
53 #include FT_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
59 #if HAVE_FT_GET_BDF_PROPERTY
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)
69 #if !HAVE_FT_GET_BDF_PROPERTY
70 #warning "No FT_Get_BDF_Property"
73 #if !HAVE_FT_GET_PS_FONT_INFO
74 #warning "No FT_Get_Font_Info"
78 * Keep Han languages separated by eliminating languages
79 * that the codePageRange bits says aren't supported
85 } FcCodePageRange
[] = {
86 { 17, (const FcChar8
*) "ja" },
87 { 18, (const FcChar8
*) "zh-cn" },
88 { 19, (const FcChar8
*) "ko" },
89 { 20, (const FcChar8
*) "zh-tw" },
92 #define NUM_CODE_PAGE_RANGE (sizeof FcCodePageRange / sizeof FcCodePageRange[0])
95 FcFreeTypeIsExclusiveLang (const FcChar8
*lang
)
99 for (i
= 0; i
< NUM_CODE_PAGE_RANGE
; i
++)
101 if (FcLangCompare (lang
, FcCodePageRange
[i
].lang
) != FcLangDifferentLang
)
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
112 #define FC_NAME_PRIO_ENC 0x00f0
113 #define FC_NAME_PRIO_ENC_UNICODE 0x0010
114 #define FC_NAME_PRIO_ENC_NONE 0x0000
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
122 FcUcs4IsLatin (FcChar32 ucs4
)
124 FcChar32 page
= ucs4
>> 8;
130 if (0x20 <= page
&& page
<= 0x23)
134 /* halfwidth forms, don't include kana or white parens */
135 if (0xff01 <= ucs4
&& ucs4
<= 0xff5e)
141 FcUtf8IsLatin (FcChar8
*str
, int len
)
146 int clen
= FcUtf8ToUcs4 (str
, &ucs4
, len
);
149 if (!FcUcs4IsLatin (ucs4
))
157 /* Order is significant. For example, some B&H fonts are hinted by
158 URW++, and both strings appear in the notice. */
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" }
182 #define NUM_NOTICE_FOUNDRIES (sizeof (FcNoticeFoundries) / sizeof (FcNoticeFoundries[0]))
184 static const FcChar8
*
185 FcNoticeFoundry(const char *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
;
197 FcVendorMatch(const char *vendor
, const char *vendor_string
)
199 /* vendor is not necessarily NUL-terminated. */
202 len
= strlen(vendor_string
);
203 if (memcmp(vendor
, vendor_string
, len
) != 0)
205 for (i
= len
; i
< 4; i
++)
206 if (vendor
[i
] != ' ' && vendor
[i
] != '\0')
211 /* This table is partly taken from ttmkfdir by Joerg Pommnitz. */
213 /* It should not contain useless entries (such as UNKN) nor duplicate
214 entries for padding both with spaces and NULs. */
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"}
251 #define NUM_VENDOR_FOUNDRIES (sizeof (FcVendorFoundries) / sizeof (FcVendorFoundries[0]))
253 static const FcChar8
*
254 FcVendorFoundry(const char *vendor
)
259 for(i
= 0; i
< NUM_VENDOR_FOUNDRIES
; i
++)
260 if (FcVendorMatch (vendor
, FcVendorFoundries
[i
].vendor
))
261 return FcVendorFoundries
[i
].foundry
;
265 typedef struct _FcStringConst
{
271 FcStringIsConst (const FcChar8
*string
,
272 const FcStringConst
*c
,
277 for (i
= 0; i
< nc
; i
++)
278 if (FcStrCmpIgnoreBlanksAndCase (string
, c
[i
].name
) == 0)
284 FcStringContainsConst (const FcChar8
*string
,
285 const FcStringConst
*c
,
290 for (i
= 0; i
< nc
; i
++)
291 if (FcStrContainsIgnoreBlanksAndCase (string
, c
[i
].name
))
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
},
315 #define NUM_WEIGHT_CONSTS (sizeof (weightConsts) / sizeof (weightConsts[0]))
317 #define FcIsWeight(s) FcStringIsConst(s,weightConsts,NUM_WEIGHT_CONSTS)
318 #define FcContainsWeight(s) FcStringContainsConst (s,weightConsts,NUM_WEIGHT_CONSTS)
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 */
332 #define NUM_WIDTH_CONSTS (sizeof (widthConsts) / sizeof (widthConsts[0]))
334 #define FcIsWidth(s) FcStringIsConst(s,widthConsts,NUM_WIDTH_CONSTS)
335 #define FcContainsWidth(s) FcStringContainsConst (s,widthConsts,NUM_WIDTH_CONSTS)
337 static const FcStringConst slantConsts
[] = {
338 { "italic", FC_SLANT_ITALIC
},
339 { "oblique", FC_SLANT_OBLIQUE
},
342 #define NUM_SLANT_CONSTS (sizeof (slantConsts) / sizeof (slantConsts[0]))
344 #define FcIsSlant(s) FcStringIsConst(s,slantConsts,NUM_SLANT_CONSTS)
345 #define FcContainsSlant(s) FcStringContainsConst (s,slantConsts,NUM_SLANT_CONSTS)
348 FcGetPixelSize (FT_Face face
, int i
)
350 #if HAVE_FT_GET_BDF_PROPERTY
351 if (face
->num_fixed_sizes
== 1)
353 BDF_PropertyRec prop
;
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
;
361 #if HAVE_FT_BITMAP_SIZE_Y_PPEM
362 return (double) face
->available_sizes
[i
].y_ppem
/ 64.0;
364 return (double) face
->available_sizes
[i
].height
/ 64.0;
369 FcFreeTypeQuery (const FcChar8
*file
,
382 FT_Library ftLibrary
;
385 const FcChar8
*foundry
= 0;
388 #if HAVE_FT_GET_PS_FONT_INFO
389 PS_FontInfoRec psfontinfo
;
391 #if HAVE_FT_GET_BDF_PROPERTY
392 BDF_PropertyRec prop
;
395 const FcChar8
*exclusiveLang
= 0;
397 FT_UInt snamei
, snamec
;
398 FcBool family_allocated
= FcFalse
;
399 FcBool style_allocated
= FcFalse
;
403 if (FT_Init_FreeType (&ftLibrary
))
406 if (FT_New_Face (ftLibrary
, (char *) file
, id
, &face
))
409 *count
= face
->num_faces
;
411 pat
= FcPatternCreate ();
415 if (!FcPatternAddBool (pat
, FC_OUTLINE
,
416 (face
->face_flags
& FT_FACE_FLAG_SCALABLE
) != 0))
419 if (!FcPatternAddBool (pat
, FC_SCALABLE
,
420 (face
->face_flags
& FT_FACE_FLAG_SCALABLE
) != 0))
427 os2
= (TT_OS2
*) FT_Get_Sfnt_Table (face
, ft_sfnt_os2
);
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.
437 if (os2
&& os2
->version
>= 0x0001 && os2
->version
!= 0xffff)
438 foundry
= FcVendorFoundry(os2
->achVendID
);
441 * Grub through the name table looking for family
442 * and style names. FreeType makes quite a hash
445 snamec
= FT_Get_Sfnt_Name_Count (face
);
446 for (snamei
= 0; snamei
< snamec
; snamei
++)
458 const FcCharMap
*map
;
461 FcNameEncodingAppleRoman
,
466 if (FT_Get_Sfnt_Name (face
, snamei
, &sname
) != 0)
470 * Look for Unicode strings
472 switch (sname
.platform_id
) {
473 case TT_PLATFORM_APPLE_UNICODE
:
475 * All APPLE_UNICODE encodings are Utf16 BE
477 * Because there's no language id for Unicode,
478 * assume it's English
480 prio
|= FC_NAME_PRIO_LANG_ENGLISH
;
481 prio
|= FC_NAME_PRIO_ENC_UNICODE
;
482 encoding
= FcNameEncodingUtf16
;
484 case TT_PLATFORM_MACINTOSH
:
485 switch (sname
.encoding_id
) {
486 case TT_MAC_ID_ROMAN
:
487 encoding
= FcNameEncodingAppleRoman
;
492 switch (sname
.language_id
) {
493 case TT_MAC_LANGID_ENGLISH
:
494 prio
|= FC_NAME_PRIO_LANG_ENGLISH
;
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
503 if (sname
.language_id
>= 0x100)
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
;
517 switch (sname
.language_id
& 0xff) {
519 prio
|= FC_NAME_PRIO_LANG_ENGLISH
;
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
;
531 case TT_ISO_ID_7BIT_ASCII
:
532 case TT_ISO_ID_8859_1
:
533 encoding
= FcNameEncodingLatin1
;
544 * Look for family and style names
546 switch (sname
.name_id
) {
547 case TT_NAME_ID_FONT_FAMILY
:
548 prio
|= FC_NAME_PRIO_NAME_FAMILY
;
550 case TT_NAME_ID_PS_NAME
:
551 prio
|= FC_NAME_PRIO_NAME_PS
;
553 case TT_NAME_ID_FONT_SUBFAMILY
:
554 case TT_NAME_ID_TRADEMARK
:
555 case TT_NAME_ID_MANUFACTURER
:
561 src
= (FcChar8
*) sname
.string
;
562 src_len
= sname
.string_len
;
565 case FcNameEncodingUtf16
:
567 * Convert Utf16 to Utf8
570 if (!FcUtf16Len (src
, FcEndianBig
, src_len
, &len
, &wchar
))
574 * Allocate plenty of space. Freed below
576 utf8
= malloc (len
* FC_UTF8_MAX_LEN
+ 1);
582 while ((ilen
= FcUtf16ToUcs4 (src
, FcEndianBig
, &ucs4
, src_len
)) > 0)
586 olen
= FcUcs4ToUtf8 (ucs4
, u8
);
591 case FcNameEncodingLatin1
:
593 * Convert Latin1 to Utf8. Freed below
595 utf8
= malloc (src_len
* 2 + 1);
604 olen
= FcUcs4ToUtf8 (ucs4
, u8
);
609 case FcNameEncodingAppleRoman
:
611 * Convert AppleRoman to Utf8
613 map
= FcFreeTypeGetPrivateMap (ft_encoding_apple_roman
);
618 utf8
= malloc (src_len
* 3 + 1);
625 ucs4
= FcFreeTypePrivateToUcs4 (*src
++, map
);
627 olen
= FcUcs4ToUtf8 (ucs4
, u8
);
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
;
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
,
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
)
654 family_allocated
= FcTrue
;
658 case TT_NAME_ID_FONT_SUBFAMILY
:
659 if (!style
|| prio
> style_prio
)
665 style_allocated
= FcTrue
;
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 */
673 foundry
= FcNoticeFoundry(utf8
);
681 family
= (FcChar8
*) face
->family_name
;
684 style
= (FcChar8
*) face
->style_name
;
688 FcChar8
*start
, *end
;
690 start
= (FcChar8
*) strrchr ((char *) file
, '/');
694 start
= (FcChar8
*) file
;
695 end
= (FcChar8
*) strrchr ((char *) start
, '.');
697 end
= start
+ strlen ((char *) start
);
699 family
= malloc (end
- start
+ 1);
700 strncpy ((char *) family
, (char *) start
, end
- start
);
701 family
[end
- start
] = '\0';
702 family_allocated
= FcTrue
;
705 if (FcDebug() & FC_DBG_SCAN
)
706 printf ("\n\"%s\" \"%s\"\n", family
, style
? style
: (FcChar8
*) "<none>");
708 if (!FcPatternAddString (pat
, FC_FAMILY
, family
))
713 if (!FcPatternAddString (pat
, FC_STYLE
, style
))
717 if (!FcPatternAddString (pat
, FC_FILE
, file
))
720 if (!FcPatternAddInteger (pat
, FC_INDEX
, id
))
723 if (!FcPatternAddString (pat
, FC_SOURCE
, (FcChar8
*) "FreeType"))
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.
732 if ((face
->face_flags
& FT_FACE_FLAG_FIXED_WIDTH
) != 0)
733 if (!FcPatternAddInteger (pat
, FC_SPACING
, FC_MONO
))
738 * Find the font revision (if available)
740 head
= (TT_Header
*) FT_Get_Sfnt_Table (face
, ft_sfnt_head
);
743 if (!FcPatternAddInteger (pat
, FC_FONTVERSION
, head
->Font_Revision
))
748 if (!FcPatternAddInteger (pat
, FC_FONTVERSION
, 0))
752 if (os2
&& os2
->version
>= 0x0001 && os2
->version
!= 0xffff)
754 for (i
= 0; i
< NUM_CODE_PAGE_RANGE
; i
++)
758 if (FcCodePageRange
[i
].bit
< 32)
760 bits
= os2
->ulCodePageRange1
;
761 bit
= FcCodePageRange
[i
].bit
;
765 bits
= os2
->ulCodePageRange2
;
766 bit
= FcCodePageRange
[i
].bit
- 32;
768 if (bits
& (1 << bit
))
771 * If the font advertises support for multiple
772 * "exclusive" languages, then include support
773 * for any language found to have coverage
780 exclusiveLang
= FcCodePageRange
[i
].lang
;
785 if (os2
&& os2
->version
!= 0xffff)
787 if (os2
->usWeightClass
== 0)
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
;
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;
822 * Type 1: Check for FontInfo dictionary information
823 * Code from g2@magestudios.net (Gerard Escalante)
826 #if HAVE_FT_GET_PS_FONT_INFO
827 if (FT_Get_PS_Font_Info(face
, &psfontinfo
) == 0)
829 if (weight
== -1 && psfontinfo
.weight
)
831 weight
= FcIsWeight (psfontinfo
.weight
);
832 if (FcDebug() & FC_DBG_SCANV
)
833 printf ("\tType1 weight %s maps to %d\n",
834 psfontinfo
.weight
, weight
);
839 * Don't bother with italic_angle; FreeType already extracts that
840 * information for us and sticks it into style_flags
842 if (psfontinfo
.italic_angle
)
843 slant
= FC_SLANT_ITALIC
;
845 slant
= FC_SLANT_ROMAN
;
849 foundry
= FcNoticeFoundry(psfontinfo
.notice
);
851 #endif /* HAVE_FT_GET_PS_FONT_INFO */
853 #if HAVE_FT_GET_BDF_PROPERTY
855 * Finally, look for a FOUNDRY BDF property if no other
856 * mechanism has managed to locate a foundry
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
;
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
))
876 if (prop
.type
== BDF_PROPERTY_TYPE_INTEGER
)
877 value
= prop
.u
.integer
;
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;
893 MY_Get_BDF_Property (face
, "SETWIDTH_NAME", &prop
) == 0 &&
894 prop
.type
== BDF_PROPERTY_TYPE_ATOM
)
896 width
= FcIsWidth (prop
.u
.atom
);
897 if (FcDebug () & FC_DBG_SCANV
)
898 printf ("\tsetwidth %s maps to %d\n", prop
.u
.atom
, width
);
904 * Look for weight, width and slant names in the style value
910 weight
= FcContainsWeight (style
);
911 if (FcDebug() & FC_DBG_SCANV
)
912 printf ("\tStyle %s maps to weight %d\n", style
, weight
);
916 width
= FcContainsWidth (style
);
917 if (FcDebug() & FC_DBG_SCANV
)
918 printf ("\tStyle %s maps to width %d\n", style
, width
);
922 slant
= FcContainsSlant (style
);
923 if (FcDebug() & FC_DBG_SCANV
)
924 printf ("\tStyle %s maps to slant %d\n", style
, slant
);
928 * Pull default values from the FreeType flags if more
929 * specific values not found above
933 slant
= FC_SLANT_ROMAN
;
934 if (face
->style_flags
& FT_STYLE_FLAG_ITALIC
)
935 slant
= FC_SLANT_ITALIC
;
940 weight
= FC_WEIGHT_MEDIUM
;
941 if (face
->style_flags
& FT_STYLE_FLAG_BOLD
)
942 weight
= FC_WEIGHT_BOLD
;
945 if (!FcPatternAddInteger (pat
, FC_SLANT
, slant
))
948 if (!FcPatternAddInteger (pat
, FC_WEIGHT
, weight
))
952 if (!FcPatternAddInteger (pat
, FC_WIDTH
, width
))
957 if(!FcPatternAddString (pat
, FC_FOUNDRY
, foundry
))
962 * Compute the unicode coverage for the font
964 cs
= FcFreeTypeCharSetAndSpacing (face
, blanks
, &spacing
);
968 #if HAVE_FT_GET_BDF_PROPERTY
969 /* For PCF fonts, override the computed spacing with the one from
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"))
977 else if(!strcmp(prop
.u
.atom
, "p") || !strcmp(prop
.u
.atom
, "P"))
978 spacing
= FC_PROPORTIONAL
;
983 * Skip over PCF fonts that have no encoded characters; they're
984 * usually just Unicode fonts transcoded to some legacy encoding
986 if (FcCharSetCount (cs
) == 0)
988 if (!strcmp(FT_MODULE_CLASS(&face
->driver
->root
)->module_name
, "pcf"))
992 if (!FcPatternAddCharSet (pat
, FC_CHARSET
, cs
))
995 ls
= FcFreeTypeLangSet (cs
, exclusiveLang
);
999 if (!FcPatternAddLangSet (pat
, FC_LANG
, ls
))
1001 FcLangSetDestroy (ls
);
1005 FcLangSetDestroy (ls
);
1007 if (spacing
!= FC_PROPORTIONAL
)
1008 if (!FcPatternAddInteger (pat
, FC_SPACING
, spacing
))
1011 if (!(face
->face_flags
& FT_FACE_FLAG_SCALABLE
))
1013 for (i
= 0; i
< face
->num_fixed_sizes
; i
++)
1014 if (!FcPatternAddDouble (pat
, FC_PIXEL_SIZE
,
1015 FcGetPixelSize (face
, i
)))
1017 if (!FcPatternAddBool (pat
, FC_ANTIALIAS
, FcFalse
))
1019 #if HAVE_FT_GET_BDF_PROPERTY
1020 if(face
->num_fixed_sizes
== 1) {
1023 BDF_PropertyRec prop
;
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
;
1032 if(!FcPatternAddDouble(pat
, FC_SIZE
, value
/ 10.0))
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
;
1042 if(!FcPatternAddDouble(pat
, FC_DPI
, (double)value
))
1052 * Drop our reference to the charset
1054 FcCharSetDestroy (cs
);
1057 * Deallocate family/style values
1060 if (family_allocated
)
1062 if (style_allocated
)
1065 FT_Done_Face (face
);
1066 FT_Done_FreeType (ftLibrary
);
1070 FcCharSetDestroy (cs
);
1072 FcPatternDestroy (pat
);
1073 if (family_allocated
)
1075 if (style_allocated
)
1078 FT_Done_Face (face
);
1080 FT_Done_FreeType (ftLibrary
);
1086 * For our purposes, this approximation is sufficient
1088 #if !HAVE_FT_GET_NEXT_CHAR
1089 #define FT_Get_Next_Char(face, ucs4, gi) ((ucs4) >= 0xffffff ? \
1091 (*(gi) = 1), (ucs4) + 1)
1092 #warning "No FT_Get_Next_Char"
1095 typedef struct _FcCharEnt
{
1097 unsigned char encode
;
1101 const FcCharEnt
*ent
;
1105 typedef struct _FcFontDecode
{
1106 FT_Encoding encoding
;
1107 const FcCharMap
*map
;
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 */
1337 static const FcCharMap AppleRoman
= {
1339 sizeof (AppleRomanEnt
) / sizeof (AppleRomanEnt
[0])
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) */
1539 static const FcCharMap AdobeSymbol
= {
1541 sizeof (AdobeSymbolEnt
) / sizeof (AdobeSymbolEnt
[0]),
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 },
1550 #define NUM_DECODE (sizeof (fcFontDecoders) / sizeof (fcFontDecoders[0]))
1553 FcFreeTypeUcs4ToPrivate (FcChar32 ucs4
, const FcCharMap
*map
)
1559 high
= map
->nent
- 1;
1560 if (ucs4
< map
->ent
[low
].bmp
|| map
->ent
[high
].bmp
< ucs4
)
1564 mid
= (high
+ low
) >> 1;
1565 bmp
= map
->ent
[mid
].bmp
;
1567 return (FT_ULong
) map
->ent
[mid
].encode
;
1577 FcFreeTypePrivateToUcs4 (FcChar32
private, const FcCharMap
*map
)
1581 for (i
= 0; i
< map
->nent
; i
++)
1582 if (map
->ent
[i
].encode
== private)
1583 return (FcChar32
) map
->ent
[i
].bmp
;
1588 FcFreeTypeGetPrivateMap (FT_Encoding encoding
)
1592 for (i
= 0; i
< NUM_DECODE
; i
++)
1593 if (fcFontDecoders
[i
].encoding
== encoding
)
1594 return fcFontDecoders
[i
].map
;
1598 #include "../fc-glyphname/fcglyphname.h"
1601 FcHashGlyphName (const FcChar8
*name
)
1606 while ((c
= *name
++))
1608 h
= ((h
<< 1) | (h
>> 31)) ^ c
;
1613 #if HAVE_FT_HAS_PS_GLYPH_NAMES
1615 * Use Type1 glyph names for fonts which have reliable names
1616 * and which export an Adobe Custom mapping
1619 FcFreeTypeUseNames (FT_Face face
)
1623 if (!FT_Has_PS_Glyph_Names (face
))
1625 for (map
= 0; map
< face
->num_charmaps
; map
++)
1626 if (face
->charmaps
[map
]->encoding
== ft_encoding_adobe_custom
)
1632 FcUcs4ToGlyphName (FcChar32 ucs4
)
1634 int i
= (int) (ucs4
% FC_GLYPHNAME_HASH
);
1638 while ((gn
= ucs_to_name
[i
]))
1640 if (gn
->ucs
== ucs4
)
1644 r
= (int) (ucs4
% FC_GLYPHNAME_REHASH
);
1649 if (i
>= FC_GLYPHNAME_HASH
)
1650 i
-= FC_GLYPHNAME_HASH
;
1656 FcGlyphNameToUcs4 (FcChar8
*name
)
1658 FcChar32 h
= FcHashGlyphName (name
);
1659 int i
= (int) (h
% FC_GLYPHNAME_HASH
);
1663 while ((gn
= name_to_ucs
[i
]))
1665 if (!strcmp ((char *) name
, (char *) gn
->name
))
1669 r
= (int) (h
% FC_GLYPHNAME_REHASH
);
1674 if (i
>= FC_GLYPHNAME_HASH
)
1675 i
-= FC_GLYPHNAME_HASH
;
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
1686 FcFreeTypeGlyphNameIndex (FT_Face face
, FcChar8
*name
)
1689 FcChar8 name_buf
[FC_GLYPHNAME_MAXLEN
+ 2];
1691 for (gindex
= 0; gindex
< face
->num_glyphs
; gindex
++)
1693 if (FT_Get_Glyph_Name (face
, gindex
, name_buf
, FC_GLYPHNAME_MAXLEN
+1) == 0)
1694 if (!strcmp ((char *) name
, (char *) name_buf
))
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
1708 FcFreeTypeCharIndex (FT_Face face
, FcChar32 ucs4
)
1710 int initial
, offset
, decode
;
1716 * Find the current encoding
1720 for (; initial
< NUM_DECODE
; initial
++)
1721 if (fcFontDecoders
[initial
].encoding
== face
->charmap
->encoding
)
1723 if (initial
== NUM_DECODE
)
1727 * Check each encoding for the glyph, starting with the current one
1729 for (offset
= 0; offset
< NUM_DECODE
; offset
++)
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)
1735 if (fcFontDecoders
[decode
].map
)
1737 charcode
= FcFreeTypeUcs4ToPrivate (ucs4
, fcFontDecoders
[decode
].map
);
1743 glyphindex
= FT_Get_Char_Index (face
, (FT_ULong
) charcode
);
1747 #if HAVE_FT_HAS_PS_GLYPH_NAMES
1749 * Check postscript name table if present
1751 if (FcFreeTypeUseNames (face
))
1753 FcChar8
*name
= FcUcs4ToGlyphName (ucs4
);
1756 glyphindex
= FcFreeTypeGlyphNameIndex (face
, name
);
1766 FcFreeTypeCheckGlyph (FT_Face face
, FcChar32 ucs4
,
1767 FT_UInt glyph
, FcBlanks
*blanks
,
1770 FT_Int load_flags
= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
| FT_LOAD_NO_SCALE
| FT_LOAD_NO_HINTING
;
1774 * For bitmap-only fonts, assume that they're OK.
1776 if ((face
->face_flags
& FT_FACE_FLAG_SCALABLE
) == 0)
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
1786 if (face
->face_flags
& FT_FACE_FLAG_SCALABLE
)
1787 load_flags
|= FT_LOAD_NO_BITMAP
;
1789 if (FT_Load_Glyph (face
, glyph
, load_flags
))
1796 *advance
= slot
->metrics
.horiAdvance
;
1798 switch (slot
->format
) {
1799 case ft_glyph_format_bitmap
:
1801 * Bitmaps are assumed to be reasonable; if
1802 * this proves to be a rash assumption, this
1803 * code can be easily modified
1806 case ft_glyph_format_outline
:
1808 * Glyphs with contours are always OK
1810 if (slot
->outline
.n_contours
!= 0)
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
1818 if (!blanks
|| FcBlanksIsMember (blanks
, ucs4
))
1820 /* fall through ... */
1827 #define APPROXIMATELY_EQUAL(x,y) (ABS ((x) - (y)) <= MAX (ABS (x), ABS (y)) / 33)
1830 FcFreeTypeCharSetAndSpacing (FT_Face face
, FcBlanks
*blanks
, int *spacing
)
1832 FcChar32 page
, off
, max
, ucs4
;
1834 FcChar32 font_max
= 0;
1838 const FcCharMap
*map
;
1842 FT_Pos advance
, advance_one
= 0, advance_two
= 0;
1843 FcBool has_advance
= FcFalse
, fixed_advance
= FcTrue
, dual_advance
= FcFalse
;
1845 fcs
= FcCharSetCreate ();
1850 printf ("Family %s style %s\n", face
->family_name
, face
->style_name
);
1852 for (o
= 0; o
< NUM_DECODE
; o
++)
1854 if (FT_Select_Charmap (face
, fcFontDecoders
[o
].encoding
) != 0)
1856 map
= fcFontDecoders
[o
].map
;
1860 * Non-Unicode tables are easy; there's a list of all possible
1863 for (i
= 0; i
< map
->nent
; i
++)
1865 ucs4
= map
->ent
[i
].bmp
;
1866 glyph
= FT_Get_Char_Index (face
, map
->ent
[i
].encode
);
1868 FcFreeTypeCheckGlyph (face
, ucs4
, glyph
, blanks
, &advance
))
1872 has_advance
= FcTrue
;
1873 advance_one
= advance
;
1875 else if (!APPROXIMATELY_EQUAL (advance
, advance_one
))
1879 dual_advance
= FcTrue
;
1880 fixed_advance
= FcFalse
;
1881 advance_two
= advance
;
1883 else if (!APPROXIMATELY_EQUAL (advance
, advance_two
))
1884 dual_advance
= FcFalse
;
1887 leaf
= FcCharSetFindLeafCreate (fcs
, ucs4
);
1890 leaf
->map
[(ucs4
& 0xff) >> 5] |= (1 << (ucs4
& 0x1f));
1892 if (ucs4
> font_max
)
1902 max
= fcFontDecoders
[o
].max
;
1904 * Find the first encoded character in the font
1906 if (FT_Get_Char_Index (face
, 0))
1913 ucs4
= FT_Get_Next_Char (face
, 0, &gindex
);
1922 while ((ucs4
>> 8) == page
)
1924 glyph
= FT_Get_Char_Index (face
, ucs4
);
1925 if (glyph
&& FcFreeTypeCheckGlyph (face
, ucs4
,
1926 glyph
, blanks
, &advance
))
1930 has_advance
= FcTrue
;
1931 advance_one
= advance
;
1933 else if (!APPROXIMATELY_EQUAL (advance
, advance_one
))
1937 dual_advance
= FcTrue
;
1938 fixed_advance
= FcFalse
;
1939 advance_two
= advance
;
1941 else if (!APPROXIMATELY_EQUAL (advance
, advance_two
))
1942 dual_advance
= FcFalse
;
1947 leaf
= FcCharSetFindLeafCreate (fcs
, ucs4
);
1952 leaf
->map
[off
>> 5] |= (1 << (off
& 0x1f));
1954 if (ucs4
> font_max
)
1960 ucs4
= FT_Get_Next_Char (face
, ucs4
- 1, &gindex
);
1965 for (ucs4
= 0; ucs4
< 0x10000; ucs4
++)
1967 FcBool FT_Has
, FC_Has
;
1969 FT_Has
= FT_Get_Char_Index (face
, ucs4
) != 0;
1970 FC_Has
= FcCharSetHasChar (fcs
, ucs4
);
1971 if (FT_Has
!= FC_Has
)
1973 printf ("0x%08x FT says %d FC says %d\n", ucs4
, FT_Has
, FC_Has
);
1979 #if HAVE_FT_HAS_PS_GLYPH_NAMES
1981 * Add mapping from PS glyph names if available
1983 if (FcFreeTypeUseNames (face
))
1985 FcChar8 name_buf
[FC_GLYPHNAME_MAXLEN
+ 2];
1987 for (glyph
= 0; glyph
< face
->num_glyphs
; glyph
++)
1989 if (FT_Get_Glyph_Name (face
, glyph
, name_buf
, FC_GLYPHNAME_MAXLEN
+1) == 0)
1991 ucs4
= FcGlyphNameToUcs4 (name_buf
);
1992 if (ucs4
!= 0xffff &&
1993 FcFreeTypeCheckGlyph (face
, ucs4
, glyph
, blanks
, &advance
))
1997 has_advance
= FcTrue
;
1998 advance_one
= advance
;
2000 else if (!APPROXIMATELY_EQUAL (advance
, advance_one
))
2004 dual_advance
= FcTrue
;
2005 fixed_advance
= FcFalse
;
2006 advance_two
= advance
;
2008 else if (!APPROXIMATELY_EQUAL (advance
, advance_two
))
2009 dual_advance
= FcFalse
;
2011 leaf
= FcCharSetFindLeafCreate (fcs
, ucs4
);
2014 leaf
->map
[(ucs4
& 0xff) >> 5] |= (1 << (ucs4
& 0x1f));
2016 if (ucs4
> font_max
)
2025 printf ("%d glyphs %d encoded\n", (int) face
->num_glyphs
, FcCharSetCount (fcs
));
2026 for (ucs4
= 0; ucs4
<= font_max
; ucs4
++)
2028 FcBool has_char
= (glyph
= FcFreeTypeCharIndex (face
, ucs4
)) != 0;
2029 FcBool has_bit
= FcCharSetHasChar (fcs
, ucs4
);
2031 if (has_char
&& !has_bit
)
2033 if (!FcFreeTypeCheckGlyph (face
, ucs4
, glyph
, blanks
, &advance
))
2034 printf ("Bitmap missing broken char 0x%x\n", ucs4
);
2036 printf ("Bitmap missing char 0x%x\n", ucs4
);
2038 else if (!has_char
&& has_bit
)
2039 printf ("Bitmap extra char 0x%x\n", ucs4
);
2044 else if (dual_advance
&& APPROXIMATELY_EQUAL (2 * MIN (advance_one
, advance_two
), MAX (advance_one
, advance_two
)))
2047 *spacing
= FC_PROPORTIONAL
;
2050 FcCharSetDestroy (fcs
);
2056 FcFreeTypeCharSet (FT_Face face
, FcBlanks
*blanks
)
2060 return FcFreeTypeCharSetAndSpacing (face
, blanks
, &spacing
);