[Commit] fontconfig/src fcfreetype.c,1.30,1.31 fcint.h,1.37,1.38

Keith Packard commit@keithp.com
Sun, 04 May 2003 15:53:52 -0700


Committed by: keithp

Update of /local/src/CVS/fontconfig/src
In directory home.keithp.com:/tmp/cvs-serv24193/src

Modified Files:
	fcfreetype.c fcint.h 
Log Message:
Handle Adobe glyph names for fonts which include ADOBE_CUSTOM encodings


Index: fcfreetype.c
===================================================================
RCS file: /local/src/CVS/fontconfig/src/fcfreetype.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -d -r1.30 -r1.31
--- fcfreetype.c	2 May 2003 01:11:53 -0000	1.30
+++ fcfreetype.c	4 May 2003 22:53:49 -0000	1.31
@@ -1548,6 +1548,107 @@
     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 @@
 	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 @@
     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 @@
 #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: fcint.h
===================================================================
RCS file: /local/src/CVS/fontconfig/src/fcint.h,v
retrieving revision 1.37
retrieving revision 1.38
diff -u -d -r1.37 -r1.38
--- fcint.h	2 May 2003 01:11:53 -0000	1.37
+++ fcint.h	4 May 2003 22:53:49 -0000	1.38
@@ -219,6 +219,16 @@
 } 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
  * which is validated by comparing the directory timestamp with