From 7769c3213dc832f7643660d6aab5fade96cd57c3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 4 May 2003 22:53:49 +0000 Subject: [PATCH] Handle Adobe glyph names for fonts which include ADOBE_CUSTOM encodings --- Makefile.am | 2 +- configure.in | 1 + src/fcfreetype.c | 160 ++++++++++++++++++++++++++++++++++++++++++++++- src/fcint.h | 10 +++ 4 files changed, 170 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 272ddca..a96074e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -21,7 +21,7 @@ # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR # PERFORMANCE OF THIS SOFTWARE. -SUBDIRS=fontconfig fc-lang src fc-cache fc-list doc test +SUBDIRS=fontconfig fc-lang fc-glyphname src fc-cache fc-list doc test EXTRA_DIST = \ fontconfig.pc.in \ diff --git a/configure.in b/configure.in index 742c525..9a4497a 100644 --- a/configure.in +++ b/configure.in @@ -357,6 +357,7 @@ AC_OUTPUT([ Makefile fontconfig/Makefile fc-lang/Makefile +fc-glyphname/Makefile src/Makefile src/fontconfig.def fc-cache/Makefile diff --git a/src/fcfreetype.c b/src/fcfreetype.c index eef7081..95be9cc 100644 --- a/src/fcfreetype.c +++ b/src/fcfreetype.c @@ -1548,6 +1548,107 @@ FcFreeTypeGetPrivateMap (FT_Encoding encoding) return 0; } +#include "../fc-glyphname/fcglyphname.h" + +static FcChar32 +FcHashGlyphName (const FcChar8 *name) +{ + FcChar32 h = 0; + FcChar8 c; + + while ((c = *name++)) + { + h = ((h << 1) | (h >> 31)) ^ c; + } + return h; +} + +/* + * Use Type1 glyph names for fonts which have reliable names + * and which export an Adobe Custom mapping + */ +static FcBool +FcFreeTypeUseNames (FT_Face face) +{ + FT_Int map; + + if (!FT_Has_PS_Glyph_Names (face)) + return FcFalse; + for (map = 0; map < face->num_charmaps; map++) + if (face->charmaps[map]->encoding == FT_ENCODING_ADOBE_CUSTOM) + return FcTrue; + return FcFalse; +} + +static FcChar8 * +FcUcs4ToGlyphName (FcChar32 ucs4) +{ + int i = (int) (ucs4 % FC_GLYPHNAME_HASH); + int r = 0; + FcGlyphName *gn; + + while ((gn = ucs_to_name[i])) + { + if (gn->ucs == ucs4) + return gn->name; + if (!r) + { + r = (int) (ucs4 % FC_GLYPHNAME_REHASH); + if (!r) + r = 1; + } + i += r; + if (i >= FC_GLYPHNAME_HASH) + i -= FC_GLYPHNAME_HASH; + } + return 0; +} + +static FcChar32 +FcGlyphNameToUcs4 (FcChar8 *name) +{ + FcChar32 h = FcHashGlyphName (name); + int i = (int) (h % FC_GLYPHNAME_HASH); + int r = 0; + FcGlyphName *gn; + + while ((gn = name_to_ucs[i])) + { + if (!strcmp ((char *) name, (char *) gn->name)) + return gn->ucs; + if (!r) + { + r = (int) (h % FC_GLYPHNAME_REHASH); + if (!r) + r = 1; + } + i += r; + if (i >= FC_GLYPHNAME_HASH) + i -= FC_GLYPHNAME_HASH; + } + return 0xffff; +} + +/* + * Search through a font for a glyph by name. This is + * currently a linear search as there doesn't appear to be + * any defined order within the font + */ +static FT_UInt +FcFreeTypeGlyphNameIndex (FT_Face face, FcChar8 *name) +{ + FT_UInt gindex; + FcChar8 name_buf[FC_GLYPHNAME_MAXLEN + 2]; + + for (gindex = 0; gindex < face->num_glyphs; gindex++) + { + if (FT_Get_Glyph_Name (face, gindex, name_buf, FC_GLYPHNAME_MAXLEN+1) == 0) + if (!strcmp ((char *) name, (char *) name_buf)) + return gindex; + } + return 0; +} + /* * Map a UCS4 glyph to a glyph index. Use all available encoding * tables to try and find one that works. This information is expected @@ -1594,6 +1695,19 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4) if (glyphindex) return glyphindex; } + /* + * Check postscript name table if present + */ + if (FcFreeTypeUseNames (face)) + { + FcChar8 *name = FcUcs4ToGlyphName (ucs4); + if (name) + { + glyphindex = FcFreeTypeGlyphNameIndex (face, name); + if (glyphindex) + return glyphindex; + } + } return 0; } @@ -1673,6 +1787,9 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing) if (!fcs) goto bail0; +#ifdef CHECK + printf ("Family %s style %s\n", face->family_name, face->style_name); +#endif for (o = 0; o < NUM_DECODE; o++) { if (FT_Select_Charmap (face, fcFontDecoders[o].encoding) != 0) @@ -1780,15 +1897,54 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing) #endif } } + /* + * Add mapping from PS glyph names if available + */ + if (FcFreeTypeUseNames (face)) + { + FcChar8 name_buf[FC_GLYPHNAME_MAXLEN + 2]; + + for (glyph = 0; glyph < face->num_glyphs; glyph++) + { + if (FT_Get_Glyph_Name (face, glyph, name_buf, FC_GLYPHNAME_MAXLEN+1) == 0) + { + ucs4 = FcGlyphNameToUcs4 (name_buf); + if (ucs4 != 0xffff && + FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance)) + { + if (!has_advance) + { + has_advance = FcTrue; + all_advance = advance; + } + else if (advance != all_advance) + fixed_advance = FcFalse; + leaf = FcCharSetFindLeafCreate (fcs, ucs4); + if (!leaf) + goto bail1; + leaf->map[(ucs4 & 0xff) >> 5] |= (1 << (ucs4 & 0x1f)); +#ifdef CHECK + if (ucs4 > font_max) + font_max = ucs4; +#endif + } + } + } + } #ifdef CHECK printf ("%d glyphs %d encoded\n", (int) face->num_glyphs, FcCharSetCount (fcs)); for (ucs4 = 0; ucs4 <= font_max; ucs4++) { - FcBool has_char = FcFreeTypeCharIndex (face, ucs4) != 0; + FcBool has_char = (glyph = FcFreeTypeCharIndex (face, ucs4)) != 0; FcBool has_bit = FcCharSetHasChar (fcs, ucs4); if (has_char && !has_bit) - printf ("Bitmap missing char 0x%x\n", ucs4); + { + if (!FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance)) + printf ("Bitmap missing broken char 0x%x\n", ucs4); + else + printf ("Bitmap missing char 0x%x\n", ucs4); + } else if (!has_char && has_bit) printf ("Bitmap extra char 0x%x\n", ucs4); } diff --git a/src/fcint.h b/src/fcint.h index 9b469b7..4652e36 100644 --- a/src/fcint.h +++ b/src/fcint.h @@ -218,6 +218,16 @@ typedef struct _FcStrBuf { int size; } FcStrBuf; +/* + * To map adobe glyph names to unicode values, a precomputed hash + * table is used + */ + +typedef struct _FcGlyphName { + FcChar32 ucs; /* unicode value */ + FcChar8 name[1]; /* name extends beyond struct */ +} FcGlyphName; + /* * The per-user ~/.fonts.cache- file is loaded into * this data structure. Each directory gets a substructure -- 2.39.5