]> git.wh0rd.org - fontconfig.git/blobdiff - src/fcfreetype.c
Work around FreeType bug when glyph name buffer is too small.
[fontconfig.git] / src / fcfreetype.c
index 20194f1818ec04474536aa61b73fd4cb30bc8f50..c79ab3b7712bb411f7d18692ac9322c6be3be0a4 100644 (file)
   THE SOFTWARE.
 */
 
+#include "fcint.h"
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include "fcint.h"
 #include <ft2build.h>
 #include FT_FREETYPE_H
-#include FT_INTERNAL_OBJECTS_H
 #include FT_TRUETYPE_TABLES_H
 #include FT_SFNT_NAMES_H
 #include FT_TRUETYPE_IDS_H
 #include FT_TYPE1_TABLES_H
-#include FT_INTERNAL_STREAM_H
-#include FT_INTERNAL_SFNT_H
-#include FT_INTERNAL_TRUETYPE_TYPES_H
 #if HAVE_FT_GET_X11_FONT_FORMAT
 #include FT_XFREE86_H
 #endif
-
 #if HAVE_FT_GET_BDF_PROPERTY
 #include FT_BDF_H
 #include FT_MODULE_H
-#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_Get_BDF_Property(f,n,p) : \
-                                   FT_Err_Invalid_Argument)
 #endif
 
+#include "ftglue.h"
+
+#if HAVE_WARNING_CPP_DIRECTIVE
 #if !HAVE_FT_GET_BDF_PROPERTY
 #warning "No FT_Get_BDF_Property: Please install freetype 2.1.4 or later"
 #endif
@@ -79,6 +72,7 @@
 #if !HAVE_FT_GET_PS_FONT_INFO
 #warning "No FT_Get_PS_Font_Info: Please install freetype 2.1.1 or later"
 #endif
+#endif
 
 /*
  * Keep Han languages separated by eliminating languages
@@ -104,7 +98,7 @@ FcFreeTypeIsExclusiveLang (const FcChar8  *lang)
 
     for (i = 0; i < NUM_CODE_PAGE_RANGE; i++)
     {
-       if (FcLangCompare (lang, FcCodePageRange[i].lang) != FcLangDifferentLang)
+       if (FcLangCompare (lang, FcCodePageRange[i].lang) == FcLangEqual)
            return FcTrue;
     }
     return FcFalse;
@@ -562,11 +556,32 @@ FcFontCapabilities(FT_Face face);
 
 #define NUM_FC_MAC_ROMAN_FAKE  (int) (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0]))
 
-#if HAVE_ICONV && HAVE_ICONV_H
-#define USE_ICONV 1
+#if USE_ICONV
 #include <iconv.h>
 #endif
 
+/*
+ * A shift-JIS will have many high bits turned on
+ */
+static FcBool
+FcLooksLikeSJIS (FcChar8 *string, int len)
+{
+    int            nhigh = 0, nlow = 0;
+
+    while (len-- > 0)
+    {
+       if (*string++ & 0x80) nhigh++;
+       else nlow++;
+    }
+    /*
+     * Heuristic -- if more than 1/3 of the bytes have the high-bit set,
+     * this is likely to be SJIS and not ROMAN
+     */
+    if (nhigh * 2 > nlow)
+       return FcTrue;
+    return FcFalse;
+}
+
 static FcChar8 *
 FcSfntNameTranscode (FT_SfntName *sname)
 {
@@ -587,24 +602,35 @@ FcSfntNameTranscode (FT_SfntName *sname)
     fromcode = fcFtEncoding[i].fromcode;
 
     /*
-     * "real" Mac language IDs are all less than 150.
-     * Names using one of the MS language IDs are assumed
-     * to use an associated encoding (Yes, this is a kludge)
+     * Many names encoded for TT_PLATFORM_MACINTOSH are broken
+     * in various ways. Kludge around them.
      */
-    if (!strcmp (fromcode, FC_ENCODING_MAC_ROMAN) &&
-       sname->language_id >= 0x100)
+    if (!strcmp (fromcode, FC_ENCODING_MAC_ROMAN))
     {
-       int     f;
+       if (sname->language_id == TT_MAC_LANGID_ENGLISH &&
+           FcLooksLikeSJIS (sname->string, sname->string_len))
+       {
+           fromcode = "SJIS";
+       }
+       else if (sname->language_id >= 0x100)
+       {
+           /*
+            * "real" Mac language IDs are all less than 150.
+            * Names using one of the MS language IDs are assumed
+            * to use an associated encoding (Yes, this is a kludge)
+            */
+           int f;
 
-       fromcode = NULL;
-       for (f = 0; f < NUM_FC_MAC_ROMAN_FAKE; f++)
-           if (fcMacRomanFake[f].language_id == sname->language_id)
-           {
-               fromcode = fcMacRomanFake[f].fromcode;
-               break;
-           }
-       if (!fromcode)
-           return 0;
+           fromcode = NULL;
+           for (f = 0; f < NUM_FC_MAC_ROMAN_FAKE; f++)
+               if (fcMacRomanFake[f].language_id == sname->language_id)
+               {
+                   fromcode = fcMacRomanFake[f].fromcode;
+                   break;
+               }
+           if (!fromcode)
+               return 0;
+       }
     }
     if (!strcmp (fromcode, "UCS-2BE") || !strcmp (fromcode, "UTF-16BE"))
     {
@@ -745,10 +771,24 @@ static const FcChar8 *
 FcSfntNameLanguage (FT_SfntName *sname)
 {
     int i;
+    FT_UShort  platform_id = sname->platform_id;
+    FT_UShort  language_id = sname->language_id;
+
+    /*
+     * Many names encoded for TT_PLATFORM_MACINTOSH are broken
+     * in various ways. Kludge around them.
+     */
+    if (platform_id == TT_PLATFORM_MACINTOSH &&
+       sname->encoding_id == TT_MAC_ID_ROMAN &&
+       FcLooksLikeSJIS (sname->string, sname->string_len))
+    {
+       language_id = TT_MAC_LANGID_JAPANESE;
+    }
+    
     for (i = 0; i < NUM_FC_FT_LANGUAGE; i++)
-       if (fcFtLanguage[i].platform_id == sname->platform_id &&
+       if (fcFtLanguage[i].platform_id == platform_id &&
            (fcFtLanguage[i].language_id == TT_LANGUAGE_DONT_CARE ||
-            fcFtLanguage[i].language_id == sname->language_id))
+            fcFtLanguage[i].language_id == language_id))
        {
            if (fcFtLanguage[i].lang[0] == '\0')
              return NULL;
@@ -914,9 +954,10 @@ static const FcStringConst  weightConsts[] = {
     { (FC8) "demibold",                FC_WEIGHT_DEMIBOLD },
     { (FC8) "demi",            FC_WEIGHT_DEMIBOLD },
     { (FC8) "semibold",                FC_WEIGHT_SEMIBOLD },
-    { (FC8) "bold",            FC_WEIGHT_BOLD },
     { (FC8) "extrabold",       FC_WEIGHT_EXTRABOLD },
+    { (FC8) "superbold",       FC_WEIGHT_EXTRABOLD },
     { (FC8) "ultrabold",       FC_WEIGHT_ULTRABOLD },
+    { (FC8) "bold",            FC_WEIGHT_BOLD },
     { (FC8) "black",           FC_WEIGHT_BLACK },
     { (FC8) "heavy",           FC_WEIGHT_HEAVY },
 };
@@ -945,6 +986,7 @@ static const FcStringConst  widthConsts[] = {
 
 static const FcStringConst  slantConsts[] = {
     { (FC8) "italic",          FC_SLANT_ITALIC },
+    { (FC8) "kursiv",          FC_SLANT_ITALIC },
     { (FC8) "oblique",         FC_SLANT_OBLIQUE },
 };
 
@@ -953,6 +995,20 @@ static const FcStringConst  slantConsts[] = {
 #define FcIsSlant(s)       FcStringIsConst(s,slantConsts,NUM_SLANT_CONSTS)
 #define FcContainsSlant(s)  FcStringContainsConst (s,slantConsts,NUM_SLANT_CONSTS)
 
+static const FcStringConst  decorativeConsts[] = {
+    { (FC8) "shadow",          FcTrue },
+    { (FC8) "smallcaps",       FcTrue },
+    { (FC8) "antiqua",         FcTrue },
+    { (FC8) "romansc",         FcTrue },
+    { (FC8) "embosed",         FcTrue },
+    { (FC8) "romansmallcaps",  FcTrue },
+};
+
+#define NUM_DECORATIVE_CONSTS  (int) (sizeof (decorativeConsts) / sizeof (decorativeConsts[0]))
+
+#define FcIsDecorative(s)   FcStringIsConst(s,decorativeConsts,NUM_DECORATIVE_CONSTS)
+#define FcContainsDecorative(s)        FcStringContainsConst (s,decorativeConsts,NUM_DECORATIVE_CONSTS)
+
 static double
 FcGetPixelSize (FT_Face face, int i)
 {
@@ -962,7 +1018,7 @@ FcGetPixelSize (FT_Face face, int i)
        BDF_PropertyRec prop;
        int             rc;
 
-       rc = MY_Get_BDF_Property (face, "PIXEL_SIZE", &prop);
+       rc = FT_Get_BDF_Property (face, "PIXEL_SIZE", &prop);
        if (rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
            return (double) prop.u.integer;
     }
@@ -983,26 +1039,43 @@ FcStringInPatternElement (FcPattern *pat, const char *elt, FcChar8 *string)
        if (!FcStrCmpIgnoreBlanksAndCase (old, string))
        {
            return FcTrue;
-           break;
        }
     return FcFalse;
 }
 
+static const FT_UShort platform_order[] = {
+    TT_PLATFORM_MICROSOFT,
+    TT_PLATFORM_APPLE_UNICODE,
+    TT_PLATFORM_MACINTOSH,
+};
+#define NUM_PLATFORM_ORDER (sizeof (platform_order) / sizeof (platform_order[0]))
+
+static const FT_UShort nameid_order[] = {
+    TT_NAME_ID_PREFERRED_FAMILY,
+    TT_NAME_ID_FONT_FAMILY,
+    TT_NAME_ID_MAC_FULL_NAME,
+    TT_NAME_ID_FULL_NAME,
+    TT_NAME_ID_PREFERRED_SUBFAMILY,
+    TT_NAME_ID_FONT_SUBFAMILY,
+    TT_NAME_ID_TRADEMARK,
+    TT_NAME_ID_MANUFACTURER,
+};
+
+#define NUM_NAMEID_ORDER  (sizeof (nameid_order) / sizeof (nameid_order[0]))
 FcPattern *
-FcFreeTypeQuery (const FcChar8 *file,
-                int            id,
-                FcBlanks       *blanks,
-                int            *count)
+FcFreeTypeQueryFace (const FT_Face  face,
+                    const FcChar8  *file,
+                    int            id,
+                    FcBlanks       *blanks)
 {
-    FT_Face        face;
     FcPattern      *pat;
     int                    slant = -1;
     int                    weight = -1;
     int                    width = -1;
+    FcBool         decorative = FcFalse;
     int                    i;
     FcCharSet      *cs;
     FcLangSet      *ls;
-    FT_Library     ftLibrary;
 #if 0
     FcChar8        *family = 0;
 #endif
@@ -1027,18 +1100,12 @@ FcFreeTypeQuery (const FcChar8  *file,
     int                    nstyle_lang = 0;
     int                    nfullname = 0;
     int                    nfullname_lang = 0;
+    int                    p, platform;
+    int                    n, nameid;
 
     FcChar8        *style = 0;
     int                    st;
     
-    if (FT_Init_FreeType (&ftLibrary))
-       return 0;
-    
-    if (FT_New_Face (ftLibrary, (char *) file, id, &face))
-       goto bail;
-
-    *count = face->num_faces;
-
     pat = FcPatternCreate ();
     if (!pat)
        goto bail0;
@@ -1076,105 +1143,145 @@ FcFreeTypeQuery (const FcChar8        *file,
      * of them
      */
     snamec = FT_Get_Sfnt_Name_Count (face);
-    for (snamei = 0; snamei < snamec; snamei++)
+    for (p = 0; p <= NUM_PLATFORM_ORDER; p++)
     {
-       FcChar8         *utf8;
-       const FcChar8   *lang;
-       const char      *elt = 0, *eltlang = 0;
-       int             *np = 0, *nlangp = 0;
-
-       if (FT_Get_Sfnt_Name (face, snamei, &sname) != 0)
-           continue;
-       
-       utf8 = FcSfntNameTranscode (&sname);
-       lang = FcSfntNameLanguage (&sname);
+       if (p < NUM_PLATFORM_ORDER)
+           platform = platform_order[p];
+       else
+           platform = 0xffff;
 
-       if (!utf8)
-           continue;
-       
-       switch (sname.name_id) {
-       case TT_NAME_ID_FONT_FAMILY:
-#if 0      
-       case TT_NAME_ID_PS_NAME:
-       case TT_NAME_ID_UNIQUE_ID:
-#endif
-           if (FcDebug () & FC_DBG_SCANV)
-               printf ("found family (n %2d p %d e %d l 0x%04x) %s\n",
-                   sname.name_id, sname.platform_id,
-                   sname.encoding_id, sname.language_id,
-                   utf8);
-    
-           elt = FC_FAMILY;
-           eltlang = FC_FAMILYLANG;
-           np = &nfamily;
-           nlangp = &nfamily_lang;
-           break;
-       case TT_NAME_ID_FULL_NAME:
-       case TT_NAME_ID_MAC_FULL_NAME:
-           if (FcDebug () & FC_DBG_SCANV)
-               printf ("found full   (n %2d p %d e %d l 0x%04x) %s\n",
-                   sname.name_id, sname.platform_id,
-                   sname.encoding_id, sname.language_id,
-                   utf8);
-    
-           elt = FC_FULLNAME;
-           eltlang = FC_FULLNAMELANG;
-           np = &nfullname;
-           nlangp = &nfullname_lang;
-           break;
-       case TT_NAME_ID_FONT_SUBFAMILY:
-           if (FcDebug () & FC_DBG_SCANV)
-               printf ("found style  (n %2d p %d e %d l 0x%04x) %s\n",
-                   sname.name_id, sname.platform_id,
-                   sname.encoding_id, sname.language_id,
-                   utf8);
-    
-           elt = FC_STYLE;
-           eltlang = FC_STYLELANG;
-           np = &nstyle;
-           nlangp = &nstyle_lang;
-           break;
-        case TT_NAME_ID_TRADEMARK:
-        case TT_NAME_ID_MANUFACTURER:
-           /* If the foundry wasn't found in the OS/2 table, look here */
-            if(!foundry)
-                foundry = FcNoticeFoundry((FT_String *) utf8);
-            break;
-       }
-       if (elt)
+       /*
+        * Order nameids so preferred names appear first
+        * in the resulting list
+        */
+       for (n = 0; n < NUM_NAMEID_ORDER; n++)
        {
-           if (FcStringInPatternElement (pat, elt, utf8))
-           {
-               free (utf8);
-               continue;
-           }
+           nameid = nameid_order[n];
 
-           /* add new element */
-           if (!FcPatternAddString (pat, elt, utf8))
-           {
-               free (utf8);
-               goto bail1;
-           }
-           free (utf8);
-           if (lang)
+           for (snamei = 0; snamei < snamec; snamei++)
            {
-               /* pad lang list with 'xx' to line up with elt */
-               while (*nlangp < *np)
+               FcChar8         *utf8;
+               const FcChar8   *lang;
+               const char      *elt = 0, *eltlang = 0;
+               int             *np = 0, *nlangp = 0;
+
+               if (FT_Get_Sfnt_Name (face, snamei, &sname) != 0)
+                   continue;
+               if (sname.name_id != nameid)
+                   continue;
+
+               /*
+                * Sort platforms in preference order, accepting
+                * all other platforms last
+                */
+               if (p < NUM_PLATFORM_ORDER)
+               {
+                   if (sname.platform_id != platform)
+                       continue;
+               }
+               else
+               {
+                   int     sp;
+
+                   for (sp = 0; sp < NUM_PLATFORM_ORDER; sp++)
+                       if (sname.platform_id == platform_order[sp])
+                           break;
+                   if (sp != NUM_PLATFORM_ORDER)
+                       continue;
+               }
+               utf8 = FcSfntNameTranscode (&sname);
+               lang = FcSfntNameLanguage (&sname);
+
+               if (!utf8)
+                   continue;
+
+               switch (sname.name_id) {
+               case TT_NAME_ID_PREFERRED_FAMILY:
+               case TT_NAME_ID_FONT_FAMILY:
+#if 0      
+               case TT_NAME_ID_PS_NAME:
+               case TT_NAME_ID_UNIQUE_ID:
+#endif
+                   if (FcDebug () & FC_DBG_SCANV)
+                       printf ("found family (n %2d p %d e %d l 0x%04x) %s\n",
+                               sname.name_id, sname.platform_id,
+                               sname.encoding_id, sname.language_id,
+                               utf8);
+
+                   elt = FC_FAMILY;
+                   eltlang = FC_FAMILYLANG;
+                   np = &nfamily;
+                   nlangp = &nfamily_lang;
+                   break;
+               case TT_NAME_ID_MAC_FULL_NAME:
+               case TT_NAME_ID_FULL_NAME:
+                   if (FcDebug () & FC_DBG_SCANV)
+                       printf ("found full   (n %2d p %d e %d l 0x%04x) %s\n",
+                               sname.name_id, sname.platform_id,
+                               sname.encoding_id, sname.language_id,
+                               utf8);
+
+                   elt = FC_FULLNAME;
+                   eltlang = FC_FULLNAMELANG;
+                   np = &nfullname;
+                   nlangp = &nfullname_lang;
+                   break;
+               case TT_NAME_ID_PREFERRED_SUBFAMILY:
+               case TT_NAME_ID_FONT_SUBFAMILY:
+                   if (FcDebug () & FC_DBG_SCANV)
+                       printf ("found style  (n %2d p %d e %d l 0x%04x) %s\n",
+                               sname.name_id, sname.platform_id,
+                               sname.encoding_id, sname.language_id,
+                               utf8);
+
+                   elt = FC_STYLE;
+                   eltlang = FC_STYLELANG;
+                   np = &nstyle;
+                   nlangp = &nstyle_lang;
+                   break;
+               case TT_NAME_ID_TRADEMARK:
+               case TT_NAME_ID_MANUFACTURER:
+                   /* If the foundry wasn't found in the OS/2 table, look here */
+                   if(!foundry)
+                       foundry = FcNoticeFoundry((FT_String *) utf8);
+                   break;
+               }
+               if (elt)
                {
-                   if (!FcPatternAddString (pat, eltlang, (FcChar8 *) "xx"))
+                   if (FcStringInPatternElement (pat, elt, utf8))
+                   {
+                       free (utf8);
+                       continue;
+                   }
+
+                   /* add new element */
+                   if (!FcPatternAddString (pat, elt, utf8))
+                   {
+                       free (utf8);
                        goto bail1;
-                   ++*nlangp;
+                   }
+                   free (utf8);
+                   if (lang)
+                   {
+                       /* pad lang list with 'xx' to line up with elt */
+                       while (*nlangp < *np)
+                       {
+                           if (!FcPatternAddString (pat, eltlang, (FcChar8 *) "xx"))
+                               goto bail1;
+                           ++*nlangp;
+                       }
+                       if (!FcPatternAddString (pat, eltlang, lang))
+                           goto bail1;
+                       ++*nlangp;
+                   }
+                   ++*np;
                }
-               if (!FcPatternAddString (pat, eltlang, lang))
-                   goto bail1;
-               ++*nlangp;
+               else
+                   free (utf8);
            }
-           ++*np;
        }
-        else
-           free (utf8);
     }
-    
+
     if (!nfamily && face->family_name && 
        FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->family_name, (FcChar8 *) "") != 0)
     {
@@ -1228,7 +1335,7 @@ FcFreeTypeQuery (const FcChar8    *file,
      * or which are simply a FC_FAMILY and FC_STYLE glued together
      */
     {
-       int     fn, fa, st;
+       int     fn, fa;
        FcChar8 *full;
        FcChar8 *fam;
        FcChar8 *style;
@@ -1374,6 +1481,9 @@ FcFreeTypeQuery (const FcChar8    *file,
            weight = FC_WEIGHT_EXTRABOLD;
        else if (os2->usWeightClass < 950)
            weight = FC_WEIGHT_BLACK;
+       if ((FcDebug() & FC_DBG_SCANV) && weight != -1)
+           printf ("\tos2 weight class %d maps to weight %d\n",
+                   os2->usWeightClass, weight);
 
        switch (os2->usWidthClass) {
        case 1: width = FC_WIDTH_ULTRACONDENSED; break;
@@ -1386,6 +1496,9 @@ FcFreeTypeQuery (const FcChar8    *file,
        case 8: width = FC_WIDTH_EXTRAEXPANDED; break;
        case 9: width = FC_WIDTH_ULTRAEXPANDED; break;
        }
+       if ((FcDebug() & FC_DBG_SCANV) && width != -1)
+           printf ("\tos2 width class %d maps to width %d\n",
+                   os2->usWidthClass, width);
     }
     if (os2 && (complex = FcFontCapabilities(face)))
     {
@@ -1438,15 +1551,14 @@ FcFreeTypeQuery (const FcChar8  *file,
     if (!foundry)
     {
        int             rc;
-       BDF_PropertyRec prop;
-       rc = MY_Get_BDF_Property(face, "FOUNDRY", &prop);
+       rc = FT_Get_BDF_Property(face, "FOUNDRY", &prop);
        if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_ATOM)
            foundry = (FcChar8 *) prop.u.atom;
     }
 
     if (width == -1)
     {
-       if (MY_Get_BDF_Property(face, "RELATIVE_SETWIDTH", &prop) == 0 &&
+       if (FT_Get_BDF_Property(face, "RELATIVE_SETWIDTH", &prop) == 0 &&
            (prop.type == BDF_PROPERTY_TYPE_INTEGER ||
             prop.type == BDF_PROPERTY_TYPE_CARDINAL))
        {
@@ -1469,7 +1581,7 @@ FcFreeTypeQuery (const FcChar8    *file,
            }
        }
        if (width == -1 &&
-           MY_Get_BDF_Property (face, "SETWIDTH_NAME", &prop) == 0 &&
+           FT_Get_BDF_Property (face, "SETWIDTH_NAME", &prop) == 0 &&
            prop.type == BDF_PROPERTY_TYPE_ATOM)
        {
            width = FcIsWidth ((FcChar8 *) prop.u.atom);
@@ -1502,6 +1614,12 @@ FcFreeTypeQuery (const FcChar8   *file,
            if (FcDebug() & FC_DBG_SCANV)
                printf ("\tStyle %s maps to slant %d\n", style, slant);
        }
+       if (decorative == FcFalse)
+       {
+           decorative = FcContainsDecorative (style) > 0;
+           if (FcDebug() & FC_DBG_SCANV)
+               printf ("\tStyle %s maps to decorative %d\n", style, decorative);
+       }
     }
     /*
      * Pull default values from the FreeType flags if more
@@ -1539,6 +1657,9 @@ FcFreeTypeQuery (const FcChar8    *file,
     if (!FcPatternAddString (pat, FC_FOUNDRY, foundry))
        goto bail1;
 
+    if (!FcPatternAddBool (pat, FC_DECORATIVE, decorative))
+       goto bail1;
+
     /*
      * Compute the unicode coverage for the font
      */
@@ -1549,7 +1670,7 @@ FcFreeTypeQuery (const FcChar8    *file,
 #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 &&
+    if(FT_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;
@@ -1563,11 +1684,16 @@ FcFreeTypeQuery (const FcChar8  *file,
     /*
      * Skip over PCF fonts that have no encoded characters; they're
      * usually just Unicode fonts transcoded to some legacy encoding
+     * ftglue.c forces us to approximate whether a font is a PCF font
+     * or not by whether it has any BDF properties.  Try PIXEL_SIZE;
+     * I don't know how to get a list of BDF properties on the font. -PL
      */
     if (FcCharSetCount (cs) == 0)
     {
-       if (!strcmp(FT_MODULE_CLASS(&face->driver->root)->module_name, "pcf"))
+#if HAVE_FT_GET_BDF_PROPERTY
+       if(FT_Get_BDF_Property(face, "PIXEL_SIZE", &prop) == 0)
            goto bail2;
+#endif
     }
 
     if (!FcPatternAddCharSet (pat, FC_CHARSET, cs))
@@ -1594,16 +1720,20 @@ FcFreeTypeQuery (const FcChar8  *file,
        for (i = 0; i < face->num_fixed_sizes; i++)
            if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE,
                                     FcGetPixelSize (face, i)))
-               goto bail1;
+               goto bail2;
        if (!FcPatternAddBool (pat, FC_ANTIALIAS, FcFalse))
-           goto bail1;
+           goto bail2;
 #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, "POINT_SIZE", &prop);
+           /* skip bitmap fonts which do not even have a family name */
+           rc =  FT_Get_BDF_Property(face, "FAMILY_NAME", &prop);
+           if (rc != 0 || prop.type != BDF_PROPERTY_TYPE_ATOM)
+               goto bail2;
+
+            rc = FT_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)
@@ -1613,7 +1743,7 @@ FcFreeTypeQuery (const FcChar8    *file,
             if(!FcPatternAddDouble(pat, FC_SIZE, value / 10.0))
                 goto nevermind;
 
-            rc = MY_Get_BDF_Property(face, "RESOLUTION_Y", &prop);
+            rc = FT_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)
@@ -1645,12 +1775,6 @@ FcFreeTypeQuery (const FcChar8   *file,
      */
     FcCharSetDestroy (cs);
     
-    /*
-     * Deallocate family/style values
-     */
-    
-    FT_Done_Face (face);
-    FT_Done_FreeType (ftLibrary);
     return pat;
 
 bail2:
@@ -1658,13 +1782,35 @@ bail2:
 bail1:
     FcPatternDestroy (pat);
 bail0:
+    return NULL;
+}
+
+FcPattern *
+FcFreeTypeQuery(const FcChar8  *file,
+               int             id,
+               FcBlanks        *blanks,
+               int             *count)
+{
+    FT_Face        face;
+    FT_Library     ftLibrary;
+    FcPattern      *pat = NULL;
+    
+    if (FT_Init_FreeType (&ftLibrary))
+       return NULL;
+    
+    if (FT_New_Face (ftLibrary, (char *) file, id, &face))
+       goto bail;
+
+    *count = face->num_faces;
+
+    pat = FcFreeTypeQueryFace (face, file, id, blanks);
+
     FT_Done_Face (face);
 bail:
     FT_Done_FreeType (ftLibrary);
-    return 0;
+    return pat;
 }
 
-
 /*
  * For our purposes, this approximation is sufficient
  */
@@ -2266,6 +2412,19 @@ FcGlyphNameToUcs4 (FcChar8 *name)
     return 0xffff;
 }
 
+/*
+ * Work around a bug in some FreeType versions which fail
+ * to correctly bounds check glyph name buffers and overwrite
+ * the stack. As Postscript names have a limit of 127 characters,
+ * this should be sufficient.
+ */
+
+#if FC_GLYPHNAME_MAXLEN < 127
+# define FC_GLYPHNAME_BUFLEN 127
+#else
+# define FC_GLYPHNAME_BUFLEN FC_GLYPHNAME_MAXLEN
+#endif
+
 /*
  * Search through a font for a glyph by name.  This is
  * currently a linear search as there doesn't appear to be
@@ -2275,11 +2434,11 @@ static FT_UInt
 FcFreeTypeGlyphNameIndex (FT_Face face, const FcChar8 *name)
 {
     FT_UInt gindex;
-    FcChar8 name_buf[FC_GLYPHNAME_MAXLEN + 2];
+    FcChar8 name_buf[FC_GLYPHNAME_BUFLEN + 2];
 
     for (gindex = 0; gindex < (FT_UInt) face->num_glyphs; gindex++)
     {
-       if (FT_Get_Glyph_Name (face, gindex, name_buf, FC_GLYPHNAME_MAXLEN+1) == 0)
+       if (FT_Get_Glyph_Name (face, gindex, name_buf, FC_GLYPHNAME_BUFLEN+1) == 0)
            if (!strcmp ((char *) name, (char *) name_buf))
                return gindex;
     }
@@ -2302,6 +2461,10 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
     int                    p;
 
     initial = 0;
+
+    if (!face)
+        return 0;
+
     /*
      * Find the current encoding
      */
@@ -2422,7 +2585,7 @@ FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4,
 FcCharSet *
 FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
 {
-    FcChar32       page, off, max, ucs4;
+    FcChar32       page, off, ucs4;
 #ifdef CHECK
     FcChar32       font_max = 0;
 #endif
@@ -2501,72 +2664,48 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
        }
        else
        {
-           FT_UInt gindex;
-         
-           max = fcFontDecoders[o].max;
-           /*
-            * Find the first encoded character in the font
-            */
-           if (FT_Get_Char_Index (face, 0))
-           {
-               ucs4 = 0;
-               gindex = 1;
-           }
-           else
-           {
-               ucs4 = FT_Get_Next_Char (face, 0, &gindex);
-               if (!ucs4)
-                   gindex = 0;
-           }
-
-           while (gindex)
+            page = ~0;
+            leaf = NULL;
+            ucs4 = FT_Get_First_Char (face, &glyph);
+            while (glyph != 0)
            {
-               page = ucs4 >> 8;
-               leaf = 0;
-               while ((ucs4 >> 8) == page)
+               if (FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance))
                {
-                   glyph = FT_Get_Char_Index (face, ucs4);
-                   if (glyph && FcFreeTypeCheckGlyph (face, ucs4, 
-                                                      glyph, blanks, &advance))
+                   if (advance)
                    {
-                       if (advance)
+                       if (!has_advance)
                        {
-                           if (!has_advance)
-                           {
-                               has_advance = FcTrue;
-                               advance_one = advance;
-                           }
-                           else if (!APPROXIMATELY_EQUAL (advance, advance_one))
+                           has_advance = FcTrue;
+                           advance_one = advance;
+                       }
+                       else if (!APPROXIMATELY_EQUAL (advance, advance_one))
+                       {
+                           if (fixed_advance)
                            {
-                               if (fixed_advance)
-                               {
-                                   dual_advance = FcTrue;
-                                   fixed_advance = FcFalse;
-                                   advance_two = advance;
-                               }
-                               else if (!APPROXIMATELY_EQUAL (advance, advance_two))
-                                   dual_advance = FcFalse;
+                               dual_advance = FcTrue;
+                               fixed_advance = FcFalse;
+                               advance_two = advance;
                            }
+                           else if (!APPROXIMATELY_EQUAL (advance, advance_two))
+                               dual_advance = FcFalse;
                        }
+                   }
 
+                   if ((ucs4 >> 8) != page)
+                   {
+                       page = (ucs4 >> 8);
+                       leaf = FcCharSetFindLeafCreate (fcs, ucs4);
                        if (!leaf)
-                       {
-                           leaf = FcCharSetFindLeafCreate (fcs, ucs4);
-                           if (!leaf)
-                               goto bail1;
-                       }
-                       off = ucs4 & 0xff;
-                       leaf->map[off >> 5] |= (1 << (off & 0x1f));
+                           goto bail1;
+                   }
+                   off = ucs4 & 0xff;
+                   leaf->map[off >> 5] |= (1 << (off & 0x1f));
 #ifdef CHECK
-                       if (ucs4 > font_max)
-                           font_max = ucs4;
+                   if (ucs4 > font_max)
+                       font_max = ucs4;
 #endif
-                   }
-                   ucs4++;
                }
-               ucs4 = FT_Get_Next_Char (face, ucs4 - 1, &gindex);
-               if (!ucs4)
-                   gindex = 0;
+               ucs4 = FT_Get_Next_Char (face, ucs4, &glyph);
            }
 #ifdef CHECK
            for (ucs4 = 0; ucs4 < 0x10000; ucs4++)
@@ -2589,11 +2728,11 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
      */
     if (FcFreeTypeUseNames (face))
     {
-       FcChar8 name_buf[FC_GLYPHNAME_MAXLEN + 2];
+       FcChar8 name_buf[FC_GLYPHNAME_BUFLEN + 2];
 
        for (glyph = 0; glyph < (FT_UInt) face->num_glyphs; glyph++)
        {
-           if (FT_Get_Glyph_Name (face, glyph, name_buf, FC_GLYPHNAME_MAXLEN+1) == 0)
+           if (FT_Get_Glyph_Name (face, glyph, name_buf, FC_GLYPHNAME_BUFLEN+1) == 0)
            {
                ucs4 = FcGlyphNameToUcs4 (name_buf);
                if (ucs4 != 0xffff && 
@@ -2731,68 +2870,68 @@ static FT_Error
 GetScriptTags(FT_Face face, FT_ULong tabletag, FT_ULong **stags, FT_UShort *script_count)
 {
     FT_ULong         cur_offset, new_offset, base_offset;
-    TT_Face          tt_face = (TT_Face)face;
     FT_Stream  stream = face->stream;
     FT_Error   error;
     FT_UShort          n, p;
-    FT_Memory  memory = stream->memory;
+    FT_Memory  memory;
 
     if ( !stream )
        return TT_Err_Invalid_Face_Handle;
 
-    if (( error = tt_face->goto_table( tt_face, tabletag, stream, 0 ) ))
+    memory = stream->memory;
+
+    if (( error = ftglue_face_goto_table( face, tabletag, stream ) ))
        return error;
 
-    base_offset = FT_STREAM_POS();
+    base_offset = ftglue_stream_pos ( stream );
 
     /* skip version */
 
-    if ( FT_STREAM_SEEK( base_offset + 4L ) || FT_FRAME_ENTER( 2L ) )
+    if ( ftglue_stream_seek ( stream, base_offset + 4L ) || ftglue_stream_frame_enter( stream, 2L ) )
        return error;
 
-    new_offset = FT_GET_USHORT() + base_offset;
+    new_offset = GET_UShort() + base_offset;
 
-    FT_FRAME_EXIT();
+    ftglue_stream_frame_exit( stream );
 
-    cur_offset = FT_STREAM_POS();
+    cur_offset = ftglue_stream_pos( stream );
 
-    if ( FT_STREAM_SEEK( new_offset ) != TT_Err_Ok )
+    if ( ftglue_stream_seek( stream, new_offset ) != TT_Err_Ok )
        return error;
 
-    base_offset = FT_STREAM_POS();
+    base_offset = ftglue_stream_pos( stream );
 
-    if ( FT_FRAME_ENTER( 2L ) )
+    if ( ftglue_stream_frame_enter( stream, 2L ) )
        return error;
 
-    *script_count = FT_GET_USHORT();
+    *script_count = GET_UShort ();
+
+    ftglue_stream_frame_exit( stream );
 
-    FT_FRAME_EXIT();
+    *stags = ftglue_alloc(memory, *script_count * sizeof( FT_ULong ), &error);
 
-    if ( FT_SET_ERROR (FT_MEM_ALLOC_ARRAY( *stags, *script_count, FT_ULong )) )
+    if (error)
        return error;
 
     p = 0;
     for ( n = 0; n < *script_count; n++ )
     {
-       if ( FT_FRAME_ENTER( 6L ) )
+        if ( ftglue_stream_frame_enter( stream, 6L ) )
            goto Fail;
 
-       (*stags)[p] = FT_GET_ULONG();
-       new_offset = FT_GET_USHORT() + base_offset;
+       (*stags)[p] = GET_ULong ();
+       new_offset = GET_UShort () + base_offset;
 
-       FT_FRAME_EXIT();
+        ftglue_stream_frame_exit( stream );
 
-       cur_offset = FT_STREAM_POS();
+       cur_offset = ftglue_stream_pos( stream );
 
-       if ( FT_STREAM_SEEK( new_offset ) )
-           goto Fail;
+       error = ftglue_stream_seek( stream, new_offset );
 
        if ( error == TT_Err_Ok )
            p++;
-       else if ( error != TTO_Err_Empty_Script )
-           goto Fail;
 
-       (void)FT_STREAM_SEEK( cur_offset );
+       (void)ftglue_stream_seek( stream, cur_offset );
     }
 
     if (!p)
@@ -2801,14 +2940,15 @@ GetScriptTags(FT_Face face, FT_ULong tabletag, FT_ULong **stags, FT_UShort *scri
        goto Fail;
     }
 
-    // sort the tag list before returning it
+    /* sort the tag list before returning it */
     qsort(*stags, *script_count, sizeof(FT_ULong), compareulong);
 
     return TT_Err_Ok;
 
 Fail:
     *script_count = 0;
-    FT_FREE( *stags );
+    ftglue_free( memory, *stags );
+    *stags = NULL;
     return error;
 }
 
@@ -2865,7 +3005,11 @@ FcFontCapabilities(FT_Face face)
     if (FcDebug () & FC_DBG_SCANV)
        printf("complex features in this font: %s\n", complex);
 bail:
-    FT_FREE(gsubtags);
-    FT_FREE(gpostags);
+    ftglue_free(memory, gsubtags);
+    ftglue_free(memory, gpostags);
     return complex;
 }
+
+#define __fcfreetype__
+#include "fcaliastail.h"
+#undef __fcfreetype__