]> git.wh0rd.org - fontconfig.git/commitdiff
Handle Adobe glyph names for fonts which include ADOBE_CUSTOM encodings
authorKeith Packard <keithp@keithp.com>
Sun, 4 May 2003 22:53:49 +0000 (22:53 +0000)
committerKeith Packard <keithp@keithp.com>
Sun, 4 May 2003 22:53:49 +0000 (22:53 +0000)
Makefile.am
configure.in
src/fcfreetype.c
src/fcint.h

index 272ddcaa7b55b84117aa6c2b183abb355cc7ff0e..a96074e7786a014f5fa5599cf48e60a037819723 100644 (file)
@@ -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 \
index 742c5257da3d83558e1997325b1ed6c73b30fd71..9a4497a5cc61226d008b1052bc18bc340cc51abb 100644 (file)
@@ -357,6 +357,7 @@ AC_OUTPUT([
 Makefile 
 fontconfig/Makefile
 fc-lang/Makefile
+fc-glyphname/Makefile
 src/Makefile
 src/fontconfig.def
 fc-cache/Makefile
index eef7081e2959714f0619e94adc100a6393781809..95be9cce712c654f9f4e1f57b04285d6d4b5f702 100644 (file)
@@ -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);
     }
index 9b469b72b54152ad2d2d51d9fd4071cee0647312..4652e369a888dc38e885aa93978fb407f01cf275 100644 (file)
@@ -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-<version> file is loaded into
  * this data structure.  Each directory gets a substructure