#include <freetype/ttnameid.h>
#include <freetype/t1tables.h>
-#if (FREETYPE_MINOR > 1 || (FREETYPE_MINOR == 1 && FREETYPE_PATCH >= 4))
+#if HAVE_FT_GET_BDF_PROPERTY
#include <freetype/ftbdf.h>
#include <freetype/ftmodule.h>
-#define USE_FTBDF
#define HAS_BDF_PROPERTY(f) ((f) && (f)->driver && \
(f)->driver->root.clazz->get_interface)
#define MY_Get_BDF_Property(f,n,p) (HAS_BDF_PROPERTY(f) ? \
FT_Err_Invalid_Argument)
#endif
+#if !HAVE_FT_GET_BDF_PROPERTY
+#warning "No FT_Get_BDF_Property"
+#endif
+
+#if !HAVE_FT_GET_PS_FONT_INFO
+#warning "No FT_Get_Font_Info"
+#endif
/*
* Keep Han languages separated by eliminating languages
const FcChar8 *foundry = 0;
int spacing;
TT_OS2 *os2;
+#if HAVE_FT_GET_PS_FONT_INFO
PS_FontInfoRec psfontinfo;
+#endif
+#if HAVE_FT_GET_BDF_PROPERTY
+ BDF_PropertyRec prop;
+#endif
TT_Header *head;
const FcChar8 *exclusiveLang = 0;
FT_SfntName sname;
* Code from g2@magestudios.net (Gerard Escalante)
*/
+#if HAVE_FT_GET_PS_FONT_INFO
if (FT_Get_PS_Font_Info(face, &psfontinfo) == 0)
{
-#if 0
if (weight == -1 && psfontinfo.weight)
{
weight = FcIsWeight (psfontinfo.weight);
printf ("\tType1 weight %s maps to %d\n",
psfontinfo.weight, weight);
}
-#endif
#if 0
/*
if(!foundry)
foundry = FcNoticeFoundry(psfontinfo.notice);
}
+#endif /* HAVE_FT_GET_PS_FONT_INFO */
-#ifdef USE_FTBDF
+#if HAVE_FT_GET_BDF_PROPERTY
/*
* Finally, look for a FOUNDRY BDF property if no other
* mechanism has managed to locate a foundry
if (width == -1)
{
- BDF_PropertyRec prop;
if (MY_Get_BDF_Property(face, "RELATIVE_SETWIDTH", &prop) == 0 &&
(prop.type == BDF_PROPERTY_TYPE_INTEGER ||
prop.type == BDF_PROPERTY_TYPE_CARDINAL))
case 9: width = FC_WIDTH_ULTRAEXPANDED; break;
}
}
- else if (MY_Get_BDF_Property (face, "SETWIDTH_NAME", &prop) == 0 &&
- prop.type == BDF_PROPERTY_TYPE_ATOM)
+ if (width == -1 &&
+ MY_Get_BDF_Property (face, "SETWIDTH_NAME", &prop) == 0 &&
+ prop.type == BDF_PROPERTY_TYPE_ATOM)
{
- static struct {
- FcChar8 *width_name;
- int width;
- } FcSetWidths[] = {
- };
- int i;
-
+ width = FcIsWidth (prop.u.atom);
if (FcDebug () & FC_DBG_SCANV)
- printf ("\tsetwidth: %s\n", prop.u.atom);
- for (i = 0; i < sizeof (FcSetWidths) / sizeof (FcSetWidths[0]); i++)
- if (!FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) prop.u.atom,
- FcSetWidths[i].width_name))
- {
- width = FcSetWidths[i].width;
- break;
- }
+ printf ("\tsetwidth %s maps to %d\n", prop.u.atom, width);
}
}
-
#endif
/*
if (!cs)
goto bail1;
+#if HAVE_FT_GET_BDF_PROPERTY
+ /* For PCF fonts, override the computed spacing with the one from
+ the property */
+ if(MY_Get_BDF_Property(face, "SPACING", &prop) == 0 &&
+ prop.type == BDF_PROPERTY_TYPE_ATOM) {
+ if(strcmp(prop.u.atom, "c") || strcmp(prop.u.atom, "C"))
+ spacing = FC_CHARCELL;
+ else if(strcmp(prop.u.atom, "m") || strcmp(prop.u.atom, "M"))
+ spacing = FC_MONO;
+ else if(strcmp(prop.u.atom, "p") || strcmp(prop.u.atom, "P"))
+ spacing = FC_PROPORTIONAL;
+ }
+#endif
+
/*
* Skip over PCF fonts that have no encoded characters; they're
* usually just Unicode fonts transcoded to some legacy encoding
goto bail2;
if (!FcPatternAddLangSet (pat, FC_LANG, ls))
+ {
+ FcLangSetDestroy (ls);
goto bail2;
+ }
+
+ FcLangSetDestroy (ls);
if (spacing != FC_PROPORTIONAL)
if (!FcPatternAddInteger (pat, FC_SPACING, spacing))
goto bail1;
if (!FcPatternAddBool (pat, FC_ANTIALIAS, FcFalse))
goto bail1;
+#if HAVE_FT_GET_BDF_PROPERTY
+ if(face->num_fixed_sizes == 1) {
+ int rc;
+ int value;
+ BDF_PropertyRec prop;
+
+ rc = MY_Get_BDF_Property(face, "PIXEL_SIZE", &prop);
+ if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
+ value = prop.u.integer;
+ else if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_CARDINAL)
+ value = prop.u.cardinal;
+ else
+ goto nevermind;
+ if(value != face->available_sizes[0].height)
+ /* ``impossible'' */
+ goto nevermind;
+
+ rc = MY_Get_BDF_Property(face, "POINT_SIZE", &prop);
+ if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
+ value = prop.u.integer;
+ else if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_CARDINAL)
+ value = prop.u.cardinal;
+ else
+ goto nevermind;
+ if(!FcPatternAddDouble(pat, FC_SIZE, value / 10.0))
+ goto nevermind;
+
+ rc = MY_Get_BDF_Property(face, "RESOLUTION_Y", &prop);
+ if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
+ value = prop.u.integer;
+ else if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_CARDINAL)
+ value = prop.u.cardinal;
+ else
+ goto nevermind;
+ if(!FcPatternAddDouble(pat, FC_DPI, (double)value))
+ goto nevermind;
+
+ }
+ nevermind:
+ ;
+#endif
}
/*
}
-/*
- * Figure out whether the available freetype has FT_Get_Next_Char
- */
-
-#if FREETYPE_MAJOR > 2
-# define HAS_NEXT_CHAR
-#else
-# if FREETYPE_MAJOR == 2
-# if FREETYPE_MINOR > 0
-# define HAS_NEXT_CHAR
-# else
-# if FREETYPE_MINOR == 0
-# if FREETYPE_PATCH >= 9
-# define HAS_NEXT_CHAR
-# endif
-# endif
-# endif
-# endif
-#endif
-
/*
* For our purposes, this approximation is sufficient
*/
-#ifndef HAS_NEXT_CHAR
-#define FT_Get_First_Char(face, gi) ((*(gi) = 1), 1)
+#if !HAVE_FT_GET_NEXT_CHAR
#define FT_Get_Next_Char(face, ucs4, gi) ((ucs4) >= 0xffffff ? \
(*(gi) = 0), 0 : \
(*(gi) = 1), (ucs4) + 1)
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;
+}
+
+#if HAVE_FT_HAS_PS_GLYPH_NAMES
+/*
+ * 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;
+}
+#endif
+
/*
* Map a UCS4 glyph to a glyph index. Use all available encoding
* tables to try and find one that works. This information is expected
if (glyphindex)
return glyphindex;
}
+#if HAVE_FT_HAS_PS_GLYPH_NAMES
+ /*
+ * Check postscript name table if present
+ */
+ if (FcFreeTypeUseNames (face))
+ {
+ FcChar8 *name = FcUcs4ToGlyphName (ucs4);
+ if (name)
+ {
+ glyphindex = FcFreeTypeGlyphNameIndex (face, name);
+ if (glyphindex)
+ return glyphindex;
+ }
+ }
+#endif
return 0;
}
FT_UInt glyph, FcBlanks *blanks,
FT_Pos *advance)
{
- FT_Int load_flags = FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
+ FT_Int load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
FT_GlyphSlot slot;
/*
return FcFalse;
}
+#define APPROXIMATELY_EQUAL(x,y) (ABS ((x) - (y)) <= MAX (ABS (x), ABS (y)) / 33)
+
FcCharSet *
FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
{
int o;
int i;
FT_UInt glyph;
- FT_Pos advance, all_advance = 0;
- FcBool has_advance = FcFalse, fixed_advance = FcTrue;
+ FT_Pos advance, advance_one = 0, advance_two = 0;
+ FcBool has_advance = FcFalse, fixed_advance = FcTrue, dual_advance = FcFalse;
fcs = FcCharSetCreate ();
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)
if (!has_advance)
{
has_advance = FcTrue;
- all_advance = advance;
+ advance_one = advance;
}
- else if (advance != all_advance)
- fixed_advance = FcFalse;
+ else if (!APPROXIMATELY_EQUAL (advance, advance_one))
+ {
+ if (fixed_advance)
+ {
+ dual_advance = FcTrue;
+ fixed_advance = FcFalse;
+ advance_two = advance;
+ }
+ else if (!APPROXIMATELY_EQUAL (advance, advance_two))
+ dual_advance = FcFalse;
+ }
+
leaf = FcCharSetFindLeafCreate (fcs, ucs4);
if (!leaf)
goto bail1;
if (!has_advance)
{
has_advance = FcTrue;
- all_advance = advance;
+ advance_one = advance;
}
- else if (advance != all_advance)
- fixed_advance = FcFalse;
+ else if (!APPROXIMATELY_EQUAL (advance, advance_one))
+ {
+ if (fixed_advance)
+ {
+ dual_advance = FcTrue;
+ fixed_advance = FcFalse;
+ advance_two = advance;
+ }
+ else if (!APPROXIMATELY_EQUAL (advance, advance_two))
+ dual_advance = FcFalse;
+ }
+
if (!leaf)
{
leaf = FcCharSetFindLeafCreate (fcs, ucs4);
#endif
}
}
+#if HAVE_FT_HAS_PS_GLYPH_NAMES
+ /*
+ * 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;
+ advance_one = advance;
+ }
+ else if (!APPROXIMATELY_EQUAL (advance, advance_one))
+ {
+ if (fixed_advance)
+ {
+ dual_advance = FcTrue;
+ fixed_advance = FcFalse;
+ advance_two = advance;
+ }
+ else if (!APPROXIMATELY_EQUAL (advance, advance_two))
+ dual_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
+ }
+ }
+ }
+ }
+#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);
}
#endif
if (fixed_advance)
*spacing = FC_MONO;
+ else if (dual_advance && APPROXIMATELY_EQUAL (2 * MIN (advance_one, advance_two), MAX (advance_one, advance_two)))
+ *spacing = FC_DUAL;
else
*spacing = FC_PROPORTIONAL;
return fcs;