Handle Adobe glyph names for fonts which include ADOBE_CUSTOM encodings

This commit is contained in:
Keith Packard 2003-05-04 22:53:49 +00:00
parent 83321a017a
commit 7769c3213d
4 changed files with 170 additions and 3 deletions

View 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 \

View File

@ -357,6 +357,7 @@ AC_OUTPUT([
Makefile
fontconfig/Makefile
fc-lang/Makefile
fc-glyphname/Makefile
src/Makefile
src/fontconfig.def
fc-cache/Makefile

View 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);
}

View 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