]> git.wh0rd.org - fontconfig.git/blobdiff - src/fcfreetype.c
Avoid #warning directives on non-GCC compilers. (bug 7683)
[fontconfig.git] / src / fcfreetype.c
index 39aaa794da7ff85953b8c6a5f1ebef7d563c280b..f85e2f8931eae1bc8b2305829ce355a9e6a08c37 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
@@ -95,7 +89,7 @@ static const struct {
     { 20,      (const FcChar8 *) "zh-tw" },
 };
 
-#define NUM_CODE_PAGE_RANGE (sizeof FcCodePageRange / sizeof FcCodePageRange[0])
+#define NUM_CODE_PAGE_RANGE (int) (sizeof FcCodePageRange / sizeof FcCodePageRange[0])
 
 FcBool
 FcFreeTypeIsExclusiveLang (const FcChar8  *lang)
@@ -104,16 +98,16 @@ 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;
 }
 
 typedef struct {
-    FT_UShort  platform_id;
-    FT_UShort  encoding_id;
-    char       *fromcode;
+    const FT_UShort    platform_id;
+    const FT_UShort    encoding_id;
+    const char fromcode[12];
 } FcFtEncoding;
 
 #define TT_ENCODING_DONT_CARE  0xffff
@@ -135,18 +129,18 @@ static const FcFtEncoding   fcFtEncoding[] = {
  {  TT_PLATFORM_ISO,           TT_ISO_ID_8859_1,       "ISO-8859-1" },
 };
 
-#define NUM_FC_FT_ENCODING  (sizeof (fcFtEncoding) / sizeof (fcFtEncoding[0]))
+#define NUM_FC_FT_ENCODING  (int) (sizeof (fcFtEncoding) / sizeof (fcFtEncoding[0]))
 
 typedef struct {
-    FT_UShort  platform_id;
-    FT_UShort  language_id;
-    char       *lang;
+    const FT_UShort    platform_id;
+    const FT_UShort    language_id;
+    const char lang[8];
 } FcFtLanguage;
 
 #define TT_LANGUAGE_DONT_CARE  0xffff
 
 static const FcFtLanguage   fcFtLanguage[] = {
- {  TT_PLATFORM_APPLE_UNICODE, TT_LANGUAGE_DONT_CARE,              0 },
+ {  TT_PLATFORM_APPLE_UNICODE, TT_LANGUAGE_DONT_CARE,              "" },
  {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_ENGLISH,              "en" },
  {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_FRENCH,               "fr" },
  {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_GERMAN,               "de" },
@@ -545,11 +539,11 @@ static const FcFtLanguage   fcFtLanguage[] = {
  {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES,"pap" },
 };
 
-#define NUM_FC_FT_LANGUAGE  (sizeof (fcFtLanguage) / sizeof (fcFtLanguage[0]))
+#define NUM_FC_FT_LANGUAGE  (int) (sizeof (fcFtLanguage) / sizeof (fcFtLanguage[0]))
 
 typedef struct {
     FT_UShort  language_id;
-    char       *fromcode;
+    char       fromcode[12];
 } FcMacRomanFake;
 
 static const FcMacRomanFake fcMacRomanFake[] = {
@@ -560,18 +554,17 @@ static const FcMacRomanFake fcMacRomanFake[] = {
 static FcChar8 *
 FcFontCapabilities(FT_Face face);
 
-#define NUM_FC_MAC_ROMAN_FAKE  (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0]))
+#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
 
 static FcChar8 *
 FcSfntNameTranscode (FT_SfntName *sname)
 {
-    int            i;
-    char    *fromcode;
+    int               i;
+    const char *fromcode;
 #if USE_ICONV
     iconv_t cd;
 #endif
@@ -596,7 +589,7 @@ FcSfntNameTranscode (FT_SfntName *sname)
     {
        int     f;
 
-       fromcode = 0;
+       fromcode = NULL;
        for (f = 0; f < NUM_FC_MAC_ROMAN_FAKE; f++)
            if (fcMacRomanFake[f].language_id == sname->language_id)
            {
@@ -606,36 +599,6 @@ FcSfntNameTranscode (FT_SfntName *sname)
        if (!fromcode)
            return 0;
     }
-#if USE_ICONV
-    cd = iconv_open ("UTF-8", fromcode);
-    if (cd)
-    {
-       size_t      in_bytes_left = sname->string_len;
-       size_t      out_bytes_left = sname->string_len * FC_UTF8_MAX_LEN;
-       char        *inbuf, *outbuf;
-       
-       utf8 = malloc (out_bytes_left + 1);
-       if (!utf8)
-           return 0;
-       
-       outbuf = (char *) utf8;
-       inbuf = (char *) sname->string;
-       
-       while (in_bytes_left)
-       {
-           size_t      did = iconv (cd, 
-                                &inbuf, &in_bytes_left,
-                                &outbuf, &out_bytes_left);
-           if (did == (size_t) (-1))
-           {
-               free (utf8);
-               return 0;
-           }
-       }
-       *outbuf = '\0';
-       goto done;
-    }
-#endif
     if (!strcmp (fromcode, "UCS-2BE") || !strcmp (fromcode, "UTF-16BE"))
     {
        FcChar8     *src = sname->string;
@@ -726,9 +689,44 @@ FcSfntNameTranscode (FT_SfntName *sname)
        *u8 = '\0';
        goto done;
     }
+#if USE_ICONV
+    cd = iconv_open ("UTF-8", fromcode);
+    if (cd && cd != (iconv_t) (-1))
+    {
+       size_t      in_bytes_left = sname->string_len;
+       size_t      out_bytes_left = sname->string_len * FC_UTF8_MAX_LEN;
+       char        *inbuf, *outbuf;
+       
+       utf8 = malloc (out_bytes_left + 1);
+       if (!utf8)
+       {
+           iconv_close (cd);
+           return 0;
+       }
+       
+       outbuf = (char *) utf8;
+       inbuf = (char *) sname->string;
+       
+       while (in_bytes_left)
+       {
+           size_t      did = iconv (cd, 
+                                &inbuf, &in_bytes_left,
+                                &outbuf, &out_bytes_left);
+           if (did == (size_t) (-1))
+           {
+               iconv_close (cd);
+               free (utf8);
+               return 0;
+           }
+       }
+       iconv_close (cd);
+       *outbuf = '\0';
+       goto done;
+    }
+#endif
     return 0;
 done:
-    if (FcStrCmpIgnoreBlanksAndCase (utf8, "") == 0)
+    if (FcStrCmpIgnoreBlanksAndCase (utf8, (FcChar8 *) "") == 0)
     {
        free (utf8);
        return 0;
@@ -736,7 +734,7 @@ done:
     return utf8;
 }
 
-static FcChar8 *
+static const FcChar8 *
 FcSfntNameLanguage (FT_SfntName *sname)
 {
     int i;
@@ -744,7 +742,12 @@ FcSfntNameLanguage (FT_SfntName *sname)
        if (fcFtLanguage[i].platform_id == sname->platform_id &&
            (fcFtLanguage[i].language_id == TT_LANGUAGE_DONT_CARE ||
             fcFtLanguage[i].language_id == sname->language_id))
-           return fcFtLanguage[i].lang;
+       {
+           if (fcFtLanguage[i].lang[0] == '\0')
+             return NULL;
+           else
+             return (FcChar8 *) fcFtLanguage[i].lang;
+       }
     return 0;
 }
 
@@ -776,7 +779,7 @@ static const struct {
                                        (const FcChar8 *) "hanyang" }
 };
 
-#define NUM_NOTICE_FOUNDRIES   (sizeof (FcNoticeFoundries) / sizeof (FcNoticeFoundries[0]))
+#define NUM_NOTICE_FOUNDRIES   (int) (sizeof (FcNoticeFoundries) / sizeof (FcNoticeFoundries[0]))
 
 static const FcChar8 *
 FcNoticeFoundry(const FT_String *notice)
@@ -796,7 +799,7 @@ FcVendorMatch(const FT_Char vendor[4], const FT_Char *vendor_string)
     /* vendor is not necessarily NUL-terminated. */
     int i, len;
     
-    len = strlen(vendor_string);
+    len = strlen((char *) vendor_string);
     if (memcmp(vendor, vendor_string, len) != 0)
         return FcFalse;
     for (i = len; i < 4; i++)
@@ -845,7 +848,7 @@ static const struct {
     { (const FT_Char *) "Y&Y",  (const FcChar8 *) "y&y"}
 };
 
-#define NUM_VENDOR_FOUNDRIES   (sizeof (FcVendorFoundries) / sizeof (FcVendorFoundries[0]))
+#define NUM_VENDOR_FOUNDRIES   (int) (sizeof (FcVendorFoundries) / sizeof (FcVendorFoundries[0]))
 
 static const FcChar8 *
 FcVendorFoundry(const FT_Char vendor[4])
@@ -890,53 +893,55 @@ FcStringContainsConst (const FcChar8          *string,
     return -1;
 }
 
+typedef FcChar8 *FC8;
+
 static const FcStringConst  weightConsts[] = {
-    { "thin",          FC_WEIGHT_THIN },
-    { "extralight",    FC_WEIGHT_EXTRALIGHT },
-    { "ultralight",    FC_WEIGHT_ULTRALIGHT },
-    { "light",         FC_WEIGHT_LIGHT },
-    { "book",          FC_WEIGHT_BOOK },
-    { "regular",       FC_WEIGHT_REGULAR },
-    { "normal",                FC_WEIGHT_NORMAL },
-    { "medium",                FC_WEIGHT_MEDIUM },
-    { "demibold",      FC_WEIGHT_DEMIBOLD },
-    { "demi",          FC_WEIGHT_DEMIBOLD },
-    { "semibold",      FC_WEIGHT_SEMIBOLD },
-    { "bold",          FC_WEIGHT_BOLD },
-    { "extrabold",     FC_WEIGHT_EXTRABOLD },
-    { "ultrabold",     FC_WEIGHT_ULTRABOLD },
-    { "black",         FC_WEIGHT_BLACK },
-    { "heavy",         FC_WEIGHT_HEAVY },
+    { (FC8) "thin",            FC_WEIGHT_THIN },
+    { (FC8) "extralight",      FC_WEIGHT_EXTRALIGHT },
+    { (FC8) "ultralight",      FC_WEIGHT_ULTRALIGHT },
+    { (FC8) "light",           FC_WEIGHT_LIGHT },
+    { (FC8) "book",            FC_WEIGHT_BOOK },
+    { (FC8) "regular",         FC_WEIGHT_REGULAR },
+    { (FC8) "normal",          FC_WEIGHT_NORMAL },
+    { (FC8) "medium",          FC_WEIGHT_MEDIUM },
+    { (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) "ultrabold",       FC_WEIGHT_ULTRABOLD },
+    { (FC8) "black",           FC_WEIGHT_BLACK },
+    { (FC8) "heavy",           FC_WEIGHT_HEAVY },
 };
 
-#define NUM_WEIGHT_CONSTS  (sizeof (weightConsts) / sizeof (weightConsts[0]))
+#define NUM_WEIGHT_CONSTS  (int) (sizeof (weightConsts) / sizeof (weightConsts[0]))
 
 #define FcIsWeight(s)      FcStringIsConst(s,weightConsts,NUM_WEIGHT_CONSTS)
 #define FcContainsWeight(s) FcStringContainsConst (s,weightConsts,NUM_WEIGHT_CONSTS)
 
 static const FcStringConst  widthConsts[] = {
-    { "ultracondensed",        FC_WIDTH_ULTRACONDENSED },
-    { "extracondensed",        FC_WIDTH_EXTRACONDENSED },
-    { "semicondensed",  FC_WIDTH_SEMICONDENSED },
-    { "condensed",     FC_WIDTH_CONDENSED },   /* must be after *condensed */
-    { "normal",                FC_WIDTH_NORMAL },
-    { "semiexpanded",  FC_WIDTH_SEMIEXPANDED },
-    { "extraexpanded", FC_WIDTH_EXTRAEXPANDED },
-    { "ultraexpanded", FC_WIDTH_ULTRAEXPANDED },
-    { "expanded",      FC_WIDTH_EXPANDED },    /* must be after *expanded */
+    { (FC8) "ultracondensed",  FC_WIDTH_ULTRACONDENSED },
+    { (FC8) "extracondensed",  FC_WIDTH_EXTRACONDENSED },
+    { (FC8) "semicondensed",   FC_WIDTH_SEMICONDENSED },
+    { (FC8) "condensed",       FC_WIDTH_CONDENSED },   /* must be after *condensed */
+    { (FC8) "normal",          FC_WIDTH_NORMAL },
+    { (FC8) "semiexpanded",    FC_WIDTH_SEMIEXPANDED },
+    { (FC8) "extraexpanded",   FC_WIDTH_EXTRAEXPANDED },
+    { (FC8) "ultraexpanded",   FC_WIDTH_ULTRAEXPANDED },
+    { (FC8) "expanded",                FC_WIDTH_EXPANDED },    /* must be after *expanded */
 };
 
-#define NUM_WIDTH_CONSTS    (sizeof (widthConsts) / sizeof (widthConsts[0]))
+#define NUM_WIDTH_CONSTS    (int) (sizeof (widthConsts) / sizeof (widthConsts[0]))
 
 #define FcIsWidth(s)       FcStringIsConst(s,widthConsts,NUM_WIDTH_CONSTS)
 #define FcContainsWidth(s)  FcStringContainsConst (s,widthConsts,NUM_WIDTH_CONSTS)
 
 static const FcStringConst  slantConsts[] = {
-    { "italic",                FC_SLANT_ITALIC },
-    { "oblique",       FC_SLANT_OBLIQUE },
+    { (FC8) "italic",          FC_SLANT_ITALIC },
+    { (FC8) "oblique",         FC_SLANT_OBLIQUE },
 };
 
-#define NUM_SLANT_CONSTS    (sizeof (slantConsts) / sizeof (slantConsts[0]))
+#define NUM_SLANT_CONSTS    (int) (sizeof (slantConsts) / sizeof (slantConsts[0]))
 
 #define FcIsSlant(s)       FcStringIsConst(s,slantConsts,NUM_SLANT_CONSTS)
 #define FcContainsSlant(s)  FcStringContainsConst (s,slantConsts,NUM_SLANT_CONSTS)
@@ -950,7 +955,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;
     }
@@ -963,7 +968,7 @@ FcGetPixelSize (FT_Face face, int i)
 }
 
 static FcBool
-FcStringInPatternElement (FcPattern *pat, char *elt, FcChar8 *string)
+FcStringInPatternElement (FcPattern *pat, const char *elt, FcChar8 *string)
 {
     int            e;
     FcChar8 *old;
@@ -971,7 +976,6 @@ FcStringInPatternElement (FcPattern *pat, char *elt, FcChar8 *string)
        if (!FcStrCmpIgnoreBlanksAndCase (old, string))
        {
            return FcTrue;
-           break;
        }
     return FcFalse;
 }
@@ -1067,8 +1071,8 @@ FcFreeTypeQuery (const FcChar8    *file,
     for (snamei = 0; snamei < snamec; snamei++)
     {
        FcChar8         *utf8;
-       FcChar8         *lang;
-       char            *elt = 0, *eltlang = 0;
+       const FcChar8   *lang;
+       const char      *elt = 0, *eltlang = 0;
        int             *np = 0, *nlangp = 0;
 
        if (FT_Get_Sfnt_Name (face, snamei, &sname) != 0)
@@ -1149,7 +1153,7 @@ FcFreeTypeQuery (const FcChar8    *file,
                /* pad lang list with 'xx' to line up with elt */
                while (*nlangp < *np)
                {
-                   if (!FcPatternAddString (pat, eltlang, "xx"))
+                   if (!FcPatternAddString (pat, eltlang, (FcChar8 *) "xx"))
                        goto bail1;
                    ++*nlangp;
                }
@@ -1164,21 +1168,21 @@ FcFreeTypeQuery (const FcChar8  *file,
     }
     
     if (!nfamily && face->family_name && 
-       FcStrCmpIgnoreBlanksAndCase (face->family_name, "") != 0)
+       FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->family_name, (FcChar8 *) "") != 0)
     {
        if (FcDebug () & FC_DBG_SCANV)
            printf ("using FreeType family \"%s\"\n", face->family_name);
-       if (!FcPatternAddString (pat, FC_FAMILY, face->family_name))
+       if (!FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) face->family_name))
            goto bail1;
        ++nfamily;
     }
     
     if (!nstyle && face->style_name &&
-       FcStrCmpIgnoreBlanksAndCase (face->style_name, "") != 0)
+       FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->style_name, (FcChar8 *) "") != 0)
     {
        if (FcDebug () & FC_DBG_SCANV)
            printf ("using FreeType style \"%s\"\n", face->style_name);
-       if (!FcPatternAddString (pat, FC_STYLE, face->style_name))
+       if (!FcPatternAddString (pat, FC_STYLE, (FcChar8 *) face->style_name))
            goto bail1;
        ++nstyle;
     }
@@ -1216,7 +1220,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;
@@ -1395,7 +1399,7 @@ FcFreeTypeQuery (const FcChar8    *file,
     {
        if (weight == -1 && psfontinfo.weight)
        {
-           weight = FcIsWeight (psfontinfo.weight);
+           weight = FcIsWeight ((FcChar8 *) psfontinfo.weight);
            if (FcDebug() & FC_DBG_SCANV)
                printf ("\tType1 weight %s maps to %d\n",
                        psfontinfo.weight, weight);
@@ -1426,15 +1430,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 = prop.u.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))
        {
@@ -1457,10 +1460,10 @@ 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 (prop.u.atom);
+           width = FcIsWidth ((FcChar8 *) prop.u.atom);
            if (FcDebug () & FC_DBG_SCANV)
                printf ("\tsetwidth %s maps to %d\n", prop.u.atom, width);
        }
@@ -1513,7 +1516,7 @@ FcFreeTypeQuery (const FcChar8    *file,
        width = FC_WIDTH_NORMAL;
 
     if (foundry == 0)
-       foundry = "unknown";
+       foundry = (FcChar8 *) "unknown";
 
     if (!FcPatternAddInteger (pat, FC_SLANT, slant))
        goto bail1;
@@ -1537,7 +1540,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;
@@ -1551,11 +1554,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))
@@ -1582,16 +1590,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)
@@ -1601,7 +1613,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)
@@ -1624,7 +1636,7 @@ FcFreeTypeQuery (const FcChar8    *file,
     {
        const char *font_format = FT_Get_X11_Font_Format (face);
        if (font_format)
-           FcPatternAddString (pat, FC_FONTFORMAT, font_format);
+           FcPatternAddString (pat, FC_FONTFORMAT, (FcChar8 *) font_format);
     }
 #endif
 
@@ -2118,7 +2130,13 @@ static const FcFontDecode fcFontDecoders[] = {
     { ft_encoding_apple_roman, &AppleRoman,    (1 << 16) - 1 },
 };
 
-#define NUM_DECODE  (sizeof (fcFontDecoders) / sizeof (fcFontDecoders[0]))
+#define NUM_DECODE  (int) (sizeof (fcFontDecoders) / sizeof (fcFontDecoders[0]))
+
+static const FcChar32  prefer_unicode[] = {
+    0x20ac,    /* EURO SIGN */
+};
+
+#define NUM_PREFER_UNICODE  (int) (sizeof (prefer_unicode) / sizeof (prefer_unicode[0]))
 
 FcChar32
 FcFreeTypeUcs4ToPrivate (FcChar32 ucs4, const FcCharMap *map)
@@ -2199,12 +2217,12 @@ FcFreeTypeUseNames (FT_Face face)
     return FcFalse;
 }
 
-static FcChar8 *
+static const FcChar8 *
 FcUcs4ToGlyphName (FcChar32 ucs4)
 {
     int                i = (int) (ucs4 % FC_GLYPHNAME_HASH);
     int                r = 0;
-    FcGlyphName        *gn;
+    const FcGlyphName  *gn;
 
     while ((gn = ucs_to_name[i]))
     {
@@ -2229,7 +2247,7 @@ FcGlyphNameToUcs4 (FcChar8 *name)
     FcChar32   h = FcHashGlyphName (name);
     int                i = (int) (h % FC_GLYPHNAME_HASH);
     int                r = 0;
-    FcGlyphName        *gn;
+    const FcGlyphName  *gn;
 
     while ((gn = name_to_ucs[i]))
     {
@@ -2254,12 +2272,12 @@ FcGlyphNameToUcs4 (FcChar8 *name)
  * any defined order within the font
  */
 static FT_UInt
-FcFreeTypeGlyphNameIndex (FT_Face face, FcChar8 *name)
+FcFreeTypeGlyphNameIndex (FT_Face face, const FcChar8 *name)
 {
     FT_UInt gindex;
     FcChar8 name_buf[FC_GLYPHNAME_MAXLEN + 2];
 
-    for (gindex = 0; gindex < face->num_glyphs; gindex++)
+    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 (!strcmp ((char *) name, (char *) name_buf))
@@ -2281,8 +2299,13 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
     int                    initial, offset, decode;
     FT_UInt        glyphindex;
     FcChar32       charcode;
+    int                    p;
 
     initial = 0;
+
+    if (!face)
+        return 0;
+
     /*
      * Find the current encoding
      */
@@ -2294,6 +2317,12 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
        if (initial == NUM_DECODE)
            initial = 0;
     }
+    for (p = 0; p < NUM_PREFER_UNICODE; p++)
+       if (ucs4 == prefer_unicode[p])
+       {
+           initial = 0;
+           break;
+       }
     /*
      * Check each encoding for the glyph, starting with the current one
      */
@@ -2306,7 +2335,7 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
        if (fcFontDecoders[decode].map)
        {
            charcode = FcFreeTypeUcs4ToPrivate (ucs4, fcFontDecoders[decode].map);
-           if (charcode == ~0)
+           if (charcode == ~0U)
                continue;
        }
        else
@@ -2321,7 +2350,7 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
      */
     if (FcFreeTypeUseNames (face))
     {
-       FcChar8 *name = FcUcs4ToGlyphName (ucs4);
+       const FcChar8   *name = FcUcs4ToGlyphName (ucs4);
        if (name)
        {
            glyphindex = FcFreeTypeGlyphNameIndex (face, name);
@@ -2341,12 +2370,6 @@ FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4,
     FT_Int         load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
     FT_GlyphSlot    slot;
     
-    /*
-     * For bitmap-only fonts, assume that they're OK.
-     */
-    if ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0)
-       return FcTrue;
-
     /*
      * When using scalable fonts, only report those glyphs
      * which can be scaled; otherwise those fonts will
@@ -2403,7 +2426,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
@@ -2441,22 +2464,33 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
                if (glyph && 
                    FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance))
                {
-                   if (!has_advance)
+                   /* 
+                    * ignore glyphs with zero advance. They’re
+                    * combining characters, and while their behaviour
+                    * isn’t well defined for monospaced applications in
+                    * Unicode, there are many fonts which include
+                    * zero-width combining characters in otherwise
+                    * monospaced fonts.
+                    */
+                   if (advance)
                    {
-                       has_advance = FcTrue;
-                       advance_one = 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;
+                       }
                    }
-                   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)
@@ -2473,7 +2507,6 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
        {
            FT_UInt gindex;
          
-           max = fcFontDecoders[o].max;
            /*
             * Find the first encoded character in the font
             */
@@ -2499,22 +2532,25 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
                    if (glyph && FcFreeTypeCheckGlyph (face, ucs4, 
                                                       glyph, blanks, &advance))
                    {
-                       if (!has_advance)
+                       if (advance)
                        {
-                           has_advance = FcTrue;
-                           advance_one = 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;
+                           }
                        }
-                       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)
                        {
@@ -2558,7 +2594,7 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
     {
        FcChar8 name_buf[FC_GLYPHNAME_MAXLEN + 2];
 
-       for (glyph = 0; glyph < face->num_glyphs; glyph++)
+       for (glyph = 0; glyph < (FT_UInt) face->num_glyphs; glyph++)
        {
            if (FT_Get_Glyph_Name (face, glyph, name_buf, FC_GLYPHNAME_MAXLEN+1) == 0)
            {
@@ -2566,22 +2602,25 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
                if (ucs4 != 0xffff && 
                    FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance))
                {
-                   if (!has_advance)
+                   if (advance)
                    {
-                       has_advance = FcTrue;
-                       advance_one = 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;
+                       }
                    }
-                   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;
@@ -2643,17 +2682,43 @@ FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks)
 #define TTO_Err_Empty_Script              0x1005
 #define TTO_Err_Invalid_SubTable          0x1001
 
+#define OTLAYOUT_HEAD      "otlayout:"
+#define OTLAYOUT_HEAD_LEN   9
+#define OTLAYOUT_ID_LEN            4
+/* space + head + id */
+#define OTLAYOUT_LEN       (1 + OTLAYOUT_HEAD_LEN + OTLAYOUT_ID_LEN)
 
+/*
+ * This is a bit generous; the registry has only lower case and space
+ * except for 'DFLT'.
+ */
+#define FcIsSpace(x)       (040 == (x))
+#define FcIsValidScript(x)  (FcIsLower(x) || FcIsUpper (x) || FcIsSpace(x))
+                            
 static void
 addtag(FcChar8 *complex, FT_ULong tag)
 {
-    FcChar8 tagstring[15];
-    sprintf (tagstring, "otlayout:%c%c%c%c ",
-       (unsigned char)(tag >> 24),
-       (unsigned char)((tag & 0xff0000) >> 16),
-       (unsigned char)((tag & 0xff00) >> 8),
-       (unsigned char)(tag & 0xff));
-    strncat(complex, tagstring, 14);
+    FcChar8 tagstring[OTLAYOUT_ID_LEN + 1];
+
+    tagstring[0] = (FcChar8)(tag >> 24),
+    tagstring[1] = (FcChar8)(tag >> 16),
+    tagstring[2] = (FcChar8)(tag >> 8),
+    tagstring[3] = (FcChar8)(tag);
+    tagstring[4] = '\0';
+    
+    /* skip tags which aren't alphabetic, under the assumption that
+     * they're probably broken
+     */
+    if (!FcIsValidScript(tagstring[0]) ||
+       !FcIsValidScript(tagstring[1]) ||
+       !FcIsValidScript(tagstring[2]) ||
+       !FcIsValidScript(tagstring[3]))
+       return;
+
+    if (*complex != '\0')
+       strcat ((char *) complex, " ");
+    strcat ((char *) complex, "otlayout:");
+    strcat ((char *) complex, (char *) tagstring);
 }
 
 static int
@@ -2669,68 +2734,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)
@@ -2739,13 +2804,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:
-    FT_FREE( *stags );
+    *script_count = 0;
+    ftglue_free( memory, *stags );
+    *stags = NULL;
     return error;
 }
 
@@ -2756,7 +2823,8 @@ FcFontCapabilities(FT_Face face)
     FT_Error err;
     FT_ULong len = 0;
     FT_ULong *gsubtags=NULL, *gpostags=NULL;
-    FT_UShort gsub_count=0, gpos_count=0, maxsize;
+    FT_UShort gsub_count=0, gpos_count=0;
+    FT_ULong maxsize;
     FT_Memory  memory = face->stream->memory;
     FcChar8 *complex = NULL;
     int indx1 = 0, indx2 = 0;
@@ -2764,23 +2832,23 @@ FcFontCapabilities(FT_Face face)
     err = FT_Load_Sfnt_Table(face, TTAG_SILF, 0, 0, &len);
     issilgraphitefont = ( err == FT_Err_Ok);
 
-    err = GetScriptTags(face, TTAG_GPOS, &gpostags, &gpos_count);
-    err = GetScriptTags(face, TTAG_GSUB, &gsubtags, &gsub_count);
+    if (GetScriptTags(face, TTAG_GPOS, &gpostags, &gpos_count) != FT_Err_Ok)
+       gpos_count = 0;
+    if (GetScriptTags(face, TTAG_GSUB, &gsubtags, &gsub_count) != FT_Err_Ok)
+       gsub_count = 0;
+    
     if (!issilgraphitefont && !gsub_count && !gpos_count)
-    {
        goto bail;
-    }
 
-    maxsize = ((gpos_count + gsub_count) * 15) + (issilgraphitefont ? 13 : 0);
+    maxsize = (((FT_ULong) gpos_count + (FT_ULong) gsub_count) * OTLAYOUT_LEN + 
+              (issilgraphitefont ? 13 : 0));
     complex = malloc (sizeof (FcChar8) * maxsize);
+    if (!complex)
+       goto bail;
+
+    complex[0] = '\0';
     if (issilgraphitefont)
-    {
-        strcpy(complex, "ttable:Silf ");
-    }
-    else
-    {
-        strcpy(complex, "");
-    }
+        strcpy((char *) complex, "ttable:Silf ");
 
     while ((indx1 < gsub_count) || (indx2 < gpos_count)) {
        if (indx1 == gsub_count) {
@@ -2801,7 +2869,7 @@ 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;
 }