]> git.wh0rd.org - fontconfig.git/blobdiff - src/fcfreetype.c
Bug 44826 - <alias> must contain only a single <family>
[fontconfig.git] / src / fcfreetype.c
index 52395c667029b00332154e18e6b41eda596d5c44..f2d0642031d9aff46e74f8fb2d458b7693a2be9b 100644 (file)
@@ -1,21 +1,21 @@
 /*
- * $RCSId: xc/lib/fontconfig/src/fcfreetype.c,v 1.11 2002/08/31 22:17:32 keithp Exp $
+ * fontconfig/src/fcfreetype.c
  *
- * Copyright © 2001 Keith Packard
+ * Copyright Â© 2001 Keith Packard
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * documentation for any purpose is hereby granted without fee, provided that
  * the above copyright notice appear in all copies and that both that
  * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of Keith Packard not be used in
+ * documentation, and that the name of the author(s) not be used in
  * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission.  Keith Packard makes no
+ * specific, written prior permission.  The authors make no
  * representations about the suitability of this software for any purpose.  It
  * is provided "as is" without express or implied warranty.
  *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
@@ -23,7 +23,7 @@
  */
 
 /*
-  Copyright © 2002-2003 by Juliusz Chroboczek
+  Copyright Â© 2002-2003 by Juliusz Chroboczek
 
   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   THE SOFTWARE.
 */
 
+#include "fcint.h"
+#include "fcftint.h"
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include "fcint.h"
-#include <freetype/freetype.h>
-#include <freetype/internal/ftobjs.h>
-#include <freetype/tttables.h>
-#include <freetype/ftsnames.h>
-#include <freetype/ttnameid.h>
-#include <freetype/t1tables.h>
-
-#if (FREETYPE_MINOR > 1 || (FREETYPE_MINOR == 1 && FREETYPE_PATCH >= 4))
-#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_Get_BDF_Property(f,n,p) : \
-                                   FT_Err_Invalid_Argument)
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_TRUETYPE_TABLES_H
+#include FT_SFNT_NAMES_H
+#include FT_TRUETYPE_IDS_H
+#include FT_TYPE1_TABLES_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
 #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
+
+#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
  */
 
 static const struct {
-    int                    bit;
-    const FcChar8   *lang;
+    char           bit;
+    const FcChar8   lang[6];
 } FcCodePageRange[] = {
-    { 17,      (const FcChar8 *) "ja" },
-    { 18,      (const FcChar8 *) "zh-cn" },
-    { 19,      (const FcChar8 *) "ko" },
-    { 20,      (const FcChar8 *) "zh-tw" },
+    { 17,      "ja" },
+    { 18,      "zh-cn" },
+    { 19,      "ko" },
+    { 20,      "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)
@@ -91,108 +99,752 @@ 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;
 }
 
-#define FC_NAME_PRIO_LANG          0x0f00
-#define FC_NAME_PRIO_LANG_ENGLISH   0x0200
-#define FC_NAME_PRIO_LANG_LATIN            0x0100
-#define FC_NAME_PRIO_LANG_NONE     0x0000
+typedef struct {
+    const FT_UShort    platform_id;
+    const FT_UShort    encoding_id;
+    const char fromcode[12];
+} FcFtEncoding;
+
+#define TT_ENCODING_DONT_CARE  0xffff
+#define FC_ENCODING_MAC_ROMAN  "MACINTOSH"
+
+static const FcFtEncoding   fcFtEncoding[] = {
+ {  TT_PLATFORM_APPLE_UNICODE, TT_ENCODING_DONT_CARE,  "UTF-16BE" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_ID_ROMAN,        "MACINTOSH" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_ID_JAPANESE,     "SJIS" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_ID_SYMBOL_CS,     "UTF-16BE" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_ID_UNICODE_CS,    "UTF-16BE" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_ID_SJIS,          "SJIS-WIN" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_ID_GB2312,        "GB2312" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_ID_BIG_5,         "BIG-5" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_ID_WANSUNG,       "Wansung" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_ID_JOHAB,         "Johab" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_ID_UCS_4,         "UTF-16BE" },
+ {  TT_PLATFORM_ISO,           TT_ISO_ID_7BIT_ASCII,   "ASCII" },
+ {  TT_PLATFORM_ISO,           TT_ISO_ID_10646,        "UTF-16BE" },
+ {  TT_PLATFORM_ISO,           TT_ISO_ID_8859_1,       "ISO-8859-1" },
+};
+
+#define NUM_FC_FT_ENCODING  (int) (sizeof (fcFtEncoding) / sizeof (fcFtEncoding[0]))
+
+typedef struct {
+    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,              "" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_ENGLISH,              "en" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_FRENCH,               "fr" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_GERMAN,               "de" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_ITALIAN,              "it" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_DUTCH,                "nl" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_SWEDISH,              "sv" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_SPANISH,              "es" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_DANISH,               "da" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_PORTUGUESE,           "pt" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_NORWEGIAN,            "no" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_HEBREW,               "he" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_JAPANESE,             "ja" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_ARABIC,               "ar" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_FINNISH,              "fi" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_GREEK,                "el" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_ICELANDIC,            "is" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_MALTESE,              "mt" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_TURKISH,              "tr" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_CROATIAN,             "hr" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_CHINESE_TRADITIONAL,  "zh-tw" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_URDU,                 "ur" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_HINDI,                "hi" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_THAI,                 "th" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_KOREAN,               "ko" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_LITHUANIAN,           "lt" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_POLISH,               "pl" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_HUNGARIAN,            "hu" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_ESTONIAN,             "et" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_LETTISH,              "lv" },
+/* {  TT_PLATFORM_MACINTOSH,   TT_MAC_LANGID_SAAMISK, ??? */
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_FAEROESE,             "fo" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_FARSI,                "fa" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_RUSSIAN,              "ru" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_CHINESE_SIMPLIFIED,   "zh-cn" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_FLEMISH,              "nl" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_IRISH,                "ga" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_ALBANIAN,             "sq" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_ROMANIAN,             "ro" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_CZECH,                "cs" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_SLOVAK,               "sk" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_SLOVENIAN,            "sl" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_YIDDISH,              "yi" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_SERBIAN,              "sr" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_MACEDONIAN,           "mk" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_BULGARIAN,            "bg" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_UKRAINIAN,            "uk" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_BYELORUSSIAN,         "be" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_UZBEK,                "uz" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_KAZAKH,               "kk" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_AZERBAIJANI,          "az" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_AZERBAIJANI_CYRILLIC_SCRIPT, "az" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_AZERBAIJANI_ARABIC_SCRIPT,    "ar" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_ARMENIAN,             "hy" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_GEORGIAN,             "ka" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_MOLDAVIAN,            "mo" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_KIRGHIZ,              "ky" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_TAJIKI,               "tg" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_TURKMEN,              "tk" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_MONGOLIAN,            "mo" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_MONGOLIAN_MONGOLIAN_SCRIPT,"mo" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_MONGOLIAN_CYRILLIC_SCRIPT, "mo" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_PASHTO,               "ps" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_KURDISH,              "ku" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_KASHMIRI,             "ks" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_SINDHI,               "sd" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_TIBETAN,              "bo" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_NEPALI,               "ne" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_SANSKRIT,             "sa" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_MARATHI,              "mr" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_BENGALI,              "bn" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_ASSAMESE,             "as" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_GUJARATI,             "gu" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_PUNJABI,              "pa" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_ORIYA,                "or" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_MALAYALAM,            "ml" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_KANNADA,              "kn" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_TAMIL,                "ta" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_TELUGU,               "te" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_SINHALESE,            "si" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_BURMESE,              "my" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_KHMER,                "km" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_LAO,                  "lo" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_VIETNAMESE,           "vi" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_INDONESIAN,           "id" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_TAGALOG,              "tl" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_MALAY_ROMAN_SCRIPT,   "ms" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_MALAY_ARABIC_SCRIPT,  "ms" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_AMHARIC,              "am" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_TIGRINYA,             "ti" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_GALLA,                "om" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_SOMALI,               "so" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_SWAHILI,              "sw" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_RUANDA,               "rw" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_RUNDI,                "rn" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_CHEWA,                "ny" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_MALAGASY,             "mg" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_ESPERANTO,            "eo" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_WELSH,                "cy" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_BASQUE,               "eu" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_CATALAN,              "ca" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_LATIN,                "la" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_QUECHUA,              "qu" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_GUARANI,              "gn" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_AYMARA,               "ay" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_TATAR,                "tt" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_UIGHUR,               "ug" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_DZONGKHA,             "dz" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_JAVANESE,             "jw" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_SUNDANESE,            "su" },
+
+#if 0  /* these seem to be errors that have been dropped */
+
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_SCOTTISH_GAELIC },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_IRISH_GAELIC },
+
+#endif
+
+  /* The following codes are new as of 2000-03-10 */
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_GALICIAN,             "gl" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_AFRIKAANS,            "af" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_BRETON,               "br" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_INUKTITUT,            "iu" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_SCOTTISH_GAELIC,      "gd" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_MANX_GAELIC,          "gv" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_IRISH_GAELIC,         "ga" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_TONGAN,               "to" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_GREEK_POLYTONIC,      "el" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_GREELANDIC,           "ik" },
+ {  TT_PLATFORM_MACINTOSH,     TT_MAC_LANGID_AZERBAIJANI_ROMAN_SCRIPT,"az" },
+
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_SAUDI_ARABIA,       "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_IRAQ,               "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_EGYPT,              "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_LIBYA,              "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_ALGERIA,            "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_MOROCCO,            "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_TUNISIA,            "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_OMAN,               "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_YEMEN,              "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_SYRIA,              "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_JORDAN,             "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_LEBANON,            "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_KUWAIT,             "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_UAE,                "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_BAHRAIN,            "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_QATAR,              "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_BULGARIAN_BULGARIA,        "bg" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_CATALAN_SPAIN,             "ca" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_CHINESE_TAIWAN,            "zh-tw" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_CHINESE_PRC,               "zh-cn" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_CHINESE_HONG_KONG,         "zh-hk" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_CHINESE_SINGAPORE,         "zh-sg" },
+
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_CHINESE_MACAU,             "zh-mo" },
+
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_CZECH_CZECH_REPUBLIC,      "cs" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_DANISH_DENMARK,            "da" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_GERMAN_GERMANY,            "de" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_GERMAN_SWITZERLAND,        "de" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_GERMAN_AUSTRIA,            "de" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_GERMAN_LUXEMBOURG,         "de" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_GERMAN_LIECHTENSTEI,       "de" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_GREEK_GREECE,              "el" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_UNITED_STATES,     "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_UNITED_KINGDOM,    "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_AUSTRALIA,         "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_CANADA,            "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_NEW_ZEALAND,       "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_IRELAND,           "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_SOUTH_AFRICA,      "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_JAMAICA,           "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_CARIBBEAN,         "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_BELIZE,            "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_TRINIDAD,          "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_ZIMBABWE,          "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_PHILIPPINES,       "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_SPAIN_TRADITIONAL_SORT,"es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_MEXICO,            "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_SPAIN_INTERNATIONAL_SORT,"es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_GUATEMALA,         "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_COSTA_RICA,        "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_PANAMA,            "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_DOMINICAN_REPUBLIC,"es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_VENEZUELA,         "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_COLOMBIA,          "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_PERU,              "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_ARGENTINA,         "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_ECUADOR,           "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_CHILE,             "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_URUGUAY,           "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_PARAGUAY,          "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_BOLIVIA,           "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_EL_SALVADOR,       "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_HONDURAS,          "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_NICARAGUA,         "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_PUERTO_RICO,       "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FINNISH_FINLAND,           "fi" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRENCH_FRANCE,             "fr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRENCH_BELGIUM,            "fr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRENCH_CANADA,             "fr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRENCH_SWITZERLAND,        "fr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRENCH_LUXEMBOURG,         "fr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRENCH_MONACO,             "fr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_HEBREW_ISRAEL,             "he" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_HUNGARIAN_HUNGARY,         "hu" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ICELANDIC_ICELAND,         "is" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ITALIAN_ITALY,             "it" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ITALIAN_SWITZERLAND,       "it" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_JAPANESE_JAPAN,            "ja" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_KOREAN_EXTENDED_WANSUNG_KOREA,"ko" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_KOREAN_JOHAB_KOREA,        "ko" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_DUTCH_NETHERLANDS,         "nl" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_DUTCH_BELGIUM,             "nl" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_NORWEGIAN_NORWAY_BOKMAL,   "no" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_NORWEGIAN_NORWAY_NYNORSK,  "nn" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_POLISH_POLAND,             "pl" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_PORTUGUESE_BRAZIL,         "pt" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_PORTUGUESE_PORTUGAL,       "pt" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_RHAETO_ROMANIC_SWITZERLAND,"rm" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ROMANIAN_ROMANIA,          "ro" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_MOLDAVIAN_MOLDAVIA,        "mo" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_RUSSIAN_RUSSIA,            "ru" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_RUSSIAN_MOLDAVIA,          "ru" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_CROATIAN_CROATIA,          "hr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SERBIAN_SERBIA_LATIN,      "sr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SERBIAN_SERBIA_CYRILLIC,   "sr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SLOVAK_SLOVAKIA,           "sk" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ALBANIAN_ALBANIA,          "sq" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SWEDISH_SWEDEN,            "sv" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SWEDISH_FINLAND,           "sv" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_THAI_THAILAND,             "th" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_TURKISH_TURKEY,            "tr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_URDU_PAKISTAN,             "ur" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_INDONESIAN_INDONESIA,      "id" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_UKRAINIAN_UKRAINE,         "uk" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_BELARUSIAN_BELARUS,        "be" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SLOVENE_SLOVENIA,          "sl" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ESTONIAN_ESTONIA,          "et" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_LATVIAN_LATVIA,            "lv" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_LITHUANIAN_LITHUANIA,      "lt" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_CLASSIC_LITHUANIAN_LITHUANIA,"lt" },
+
+#ifdef TT_MS_LANGID_MAORI_NEW_ZELAND
+    /* this seems to be an error that have been dropped */
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_MAORI_NEW_ZEALAND,         "mi" },
+#endif
+
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FARSI_IRAN,                "fa" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_VIETNAMESE_VIET_NAM,       "vi" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARMENIAN_ARMENIA,          "hy" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_AZERI_AZERBAIJAN_LATIN,    "az" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_AZERI_AZERBAIJAN_CYRILLIC, "az" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_BASQUE_SPAIN,              "eu" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SORBIAN_GERMANY,           "wen" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_MACEDONIAN_MACEDONIA,      "mk" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SUTU_SOUTH_AFRICA,         "st" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_TSONGA_SOUTH_AFRICA,       "ts" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_TSWANA_SOUTH_AFRICA,       "tn" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_VENDA_SOUTH_AFRICA,        "ven" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_XHOSA_SOUTH_AFRICA,        "xh" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ZULU_SOUTH_AFRICA,         "zu" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_AFRIKAANS_SOUTH_AFRICA,    "af" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_GEORGIAN_GEORGIA,          "ka" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FAEROESE_FAEROE_ISLANDS,   "fo" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_HINDI_INDIA,               "hi" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_MALTESE_MALTA,             "mt" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SAAMI_LAPONIA,             "se" },
+
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SCOTTISH_GAELIC_UNITED_KINGDOM,"gd" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_IRISH_GAELIC_IRELAND,      "ga" },
+
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_MALAY_MALAYSIA,            "ms" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_MALAY_BRUNEI_DARUSSALAM,   "ms" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_KAZAK_KAZAKSTAN,           "kk" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SWAHILI_KENYA,             "sw" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_UZBEK_UZBEKISTAN_LATIN,    "uz" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_UZBEK_UZBEKISTAN_CYRILLIC, "uz" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_TATAR_TATARSTAN,           "tt" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_BENGALI_INDIA,             "bn" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_PUNJABI_INDIA,             "pa" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_GUJARATI_INDIA,            "gu" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ORIYA_INDIA,               "or" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_TAMIL_INDIA,               "ta" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_TELUGU_INDIA,              "te" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_KANNADA_INDIA,             "kn" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_MALAYALAM_INDIA,           "ml" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ASSAMESE_INDIA,            "as" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_MARATHI_INDIA,             "mr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SANSKRIT_INDIA,            "sa" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_KONKANI_INDIA,             "kok" },
+
+  /* new as of 2001-01-01 */
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ARABIC_GENERAL,            "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_CHINESE_GENERAL,           "zh" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_GENERAL,           "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRENCH_WEST_INDIES,        "fr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRENCH_REUNION,            "fr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRENCH_CONGO,              "fr" },
+
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRENCH_SENEGAL,            "fr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRENCH_CAMEROON,           "fr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRENCH_COTE_D_IVOIRE,      "fr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRENCH_MALI,               "fr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_BOSNIAN_BOSNIA_HERZEGOVINA,"bs" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_URDU_INDIA,                "ur" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_TAJIK_TAJIKISTAN,          "tg" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_YIDDISH_GERMANY,           "yi" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_KIRGHIZ_KIRGHIZSTAN,       "ky" },
+
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_TURKMEN_TURKMENISTAN,      "tk" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_MONGOLIAN_MONGOLIA,        "mn" },
+
+  /* the following seems to be inconsistent;
+     here is the current "official" way: */
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_TIBETAN_BHUTAN,            "bo" },
+  /* and here is what is used by Passport SDK */
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_TIBETAN_CHINA,             "bo" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_DZONGHKA_BHUTAN,           "dz" },
+  /* end of inconsistency */
+
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_WELSH_WALES,               "cy" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_KHMER_CAMBODIA,            "km" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_LAO_LAOS,                  "lo" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_BURMESE_MYANMAR,           "my" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_GALICIAN_SPAIN,            "gl" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_MANIPURI_INDIA,            "mni" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SINDHI_INDIA,              "sd" },
+  /* the following one is only encountered in Microsoft RTF specification */
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_KASHMIRI_PAKISTAN,         "ks" },
+  /* the following one is not in the Passport list, looks like an omission */
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_KASHMIRI_INDIA,            "ks" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_NEPALI_NEPAL,              "ne" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_NEPALI_INDIA,              "ne" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRISIAN_NETHERLANDS,       "fy" },
+
+  /* new as of 2001-03-01 (from Office Xp) */
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_HONG_KONG,         "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_INDIA,             "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_MALAYSIA,          "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_ENGLISH_SINGAPORE,         "en" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SYRIAC_SYRIA,              "syr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SINHALESE_SRI_LANKA,       "si" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_CHEROKEE_UNITED_STATES,    "chr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_INUKTITUT_CANADA,          "iu" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_AMHARIC_ETHIOPIA,          "am" },
+#if 0
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_TAMAZIGHT_MOROCCO },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_TAMAZIGHT_MOROCCO_LATIN },
+#endif
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_PASHTO_AFGHANISTAN,        "ps" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FILIPINO_PHILIPPINES,      "phi" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_DHIVEHI_MALDIVES,          "div" },
+
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_OROMO_ETHIOPIA,            "om" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_TIGRIGNA_ETHIOPIA,         "ti" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_TIGRIGNA_ERYTHREA,         "ti" },
 
-#define FC_NAME_PRIO_ENC           0x00f0
-#define FC_NAME_PRIO_ENC_UNICODE    0x0010
-#define FC_NAME_PRIO_ENC_NONE      0x0000
+  /* New additions from Windows Xp/Passport SDK 2001-11-10. */
 
-#define FC_NAME_PRIO_NAME          0x000f
-#define FC_NAME_PRIO_NAME_FAMILY    0x0002
-#define FC_NAME_PRIO_NAME_PS       0x0001
-#define FC_NAME_PRIO_NAME_NONE     0x0000
+  /* don't ask what this one means... It is commented out currently. */
+#if 0
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_GREEK_GREECE2 },
+#endif
+
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_UNITED_STATES,     "es" },
+  /* The following two IDs blatantly violate MS specs by using a */
+  /* sublanguage >,.                                         */
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SPANISH_LATIN_AMERICA,     "es" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRENCH_NORTH_AFRICA,       "fr" },
+
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRENCH_MOROCCO,            "fr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FRENCH_HAITI,              "fr" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_BENGALI_BANGLADESH,        "bn" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_PUNJABI_ARABIC_PAKISTAN,   "ar" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_MONGOLIAN_MONGOLIA_MONGOLIAN,"mn" },
+#if 0
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_EDO_NIGERIA },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_FULFULDE_NIGERIA },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_IBIBIO_NIGERIA },
+#endif
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_HAUSA_NIGERIA,             "ha" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_YORUBA_NIGERIA,            "yo" },
+  /* language codes from, to, are (still) unknown. */
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_IGBO_NIGERIA,              "ibo" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_KANURI_NIGERIA,            "kau" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_GUARANI_PARAGUAY,          "gn" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_HAWAIIAN_UNITED_STATES,    "haw" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_LATIN,                     "la" },
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_SOMALI_SOMALIA,            "so" },
+#if 0
+  /* Note: Yi does not have a (proper) ISO 639-2 code, since it is mostly */
+  /*       not written (but OTOH the peculiar writing system is worth     */
+  /*       studying).                                                     */
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_YI_CHINA },
+#endif
+ {  TT_PLATFORM_MICROSOFT,     TT_MS_LANGID_PAPIAMENTU_NETHERLANDS_ANTILLES,"pap" },
+};
 
+#define NUM_FC_FT_LANGUAGE  (int) (sizeof (fcFtLanguage) / sizeof (fcFtLanguage[0]))
+
+typedef struct {
+    FT_UShort  language_id;
+    char       fromcode[12];
+} FcMacRomanFake;
+
+static const FcMacRomanFake fcMacRomanFake[] = {
+ {  TT_MS_LANGID_JAPANESE_JAPAN,       "SJIS-WIN" },
+ {  TT_MS_LANGID_ENGLISH_UNITED_STATES,        "ASCII" },
+};
+
+static FcChar8 *
+FcFontCapabilities(FT_Face face);
+
+#define NUM_FC_MAC_ROMAN_FAKE  (int) (sizeof (fcMacRomanFake) / sizeof (fcMacRomanFake[0]))
+
+#if USE_ICONV
+#include <iconv.h>
+#endif
+
+/*
+ * A shift-JIS will have many high bits turned on
+ */
 static FcBool
-FcUcs4IsLatin (FcChar32 ucs4)
+FcLooksLikeSJIS (FcChar8 *string, int len)
 {
-    FcChar32   page = ucs4 >> 8;
-    
-    if (page <= 2)
-       return FcTrue;
-    if (page == 0x1e)
-       return FcTrue;
-    if (0x20 <= page && page <= 0x23)
-       return FcTrue;
-    if (page == 0xfb)
-       return FcTrue;
-    /* halfwidth forms, don't include kana or white parens */
-    if (0xff01 <= ucs4 && ucs4 <= 0xff5e)
+    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 FcBool
-FcUtf8IsLatin (FcChar8 *str, int len)
+static FcChar8 *
+FcSfntNameTranscode (FT_SfntName *sname)
 {
-    while (len)
+    int               i;
+    const char *fromcode;
+#if USE_ICONV
+    iconv_t cd;
+#endif
+    FcChar8 *utf8;
+
+    for (i = 0; i < NUM_FC_FT_ENCODING; i++)
+       if (fcFtEncoding[i].platform_id == sname->platform_id &&
+           (fcFtEncoding[i].encoding_id == TT_ENCODING_DONT_CARE ||
+            fcFtEncoding[i].encoding_id == sname->encoding_id))
+           break;
+    if (i == NUM_FC_FT_ENCODING)
+       return 0;
+    fromcode = fcFtEncoding[i].fromcode;
+
+    /*
+     * Many names encoded for TT_PLATFORM_MACINTOSH are broken
+     * in various ways. Kludge around them.
+     */
+    if (!strcmp (fromcode, FC_ENCODING_MAC_ROMAN))
+    {
+       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;
+       }
+    }
+    if (!strcmp (fromcode, "UCS-2BE") || !strcmp (fromcode, "UTF-16BE"))
     {
+       FcChar8     *src = sname->string;
+       int         src_len = sname->string_len;
+       int         len;
+       int         wchar;
+       int         ilen, olen;
+       FcChar8     *u8;
        FcChar32    ucs4;
-       int         clen = FcUtf8ToUcs4 (str, &ucs4, len);
-       if (clen <= 0)
-           return FcFalse;
-       if (!FcUcs4IsLatin (ucs4))
-           return FcFalse;
-       len -= clen;
-       str += clen;
+       
+       /*
+        * Convert Utf16 to Utf8
+        */
+
+       if (!FcUtf16Len (src, FcEndianBig, src_len, &len, &wchar))
+           return 0;
+
+       /*
+        * Allocate plenty of space.  Freed below
+        */
+       utf8 = malloc (len * FC_UTF8_MAX_LEN + 1);
+       if (!utf8)
+           return 0;
+
+       u8 = utf8;
+
+       while ((ilen = FcUtf16ToUcs4 (src, FcEndianBig, &ucs4, src_len)) > 0)
+       {
+           src_len -= ilen;
+           src += ilen;
+           olen = FcUcs4ToUtf8 (ucs4, u8);
+           u8 += olen;
+       }
+       *u8 = '\0';
+       goto done;
     }
-    return FcTrue;
+    if (!strcmp (fromcode, "ASCII") || !strcmp (fromcode, "ISO-8859-1"))
+    {
+       FcChar8     *src = sname->string;
+       int         src_len = sname->string_len;
+       int         olen;
+       FcChar8     *u8;
+       FcChar32    ucs4;
+       
+       /*
+        * Convert Latin1 to Utf8. Freed below
+        */
+       utf8 = malloc (src_len * 2 + 1);
+       if (!utf8)
+           return 0;
+
+       u8 = utf8;
+       while (src_len > 0)
+       {
+           ucs4 = *src++;
+           src_len--;
+           olen = FcUcs4ToUtf8 (ucs4, u8);
+           u8 += olen;
+       }
+       *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, (FcChar8 *) "") == 0)
+    {
+       free (utf8);
+       return 0;
+    }
+    return utf8;
+}
+
+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 == platform_id &&
+           (fcFtLanguage[i].language_id == TT_LANGUAGE_DONT_CARE ||
+            fcFtLanguage[i].language_id == language_id))
+       {
+           if (fcFtLanguage[i].lang[0] == '\0')
+             return NULL;
+           else
+             return (FcChar8 *) fcFtLanguage[i].lang;
+       }
+    return 0;
 }
 
 /* Order is significant.  For example, some B&H fonts are hinted by
    URW++, and both strings appear in the notice. */
 
-static const struct {
-    const FcChar8   *notice;
-    const FcChar8   *foundry;
-} FcNoticeFoundries[] = {
-    { (const FcChar8*) "Bigelow",      (const FcChar8 *) "b&h" },
-    { (const FcChar8*) "Adobe",                (const FcChar8 *) "adobe" },
-    { (const FcChar8*) "Bitstream",    (const FcChar8 *) "bitstream" },
-    { (const FcChar8*) "Monotype",     (const FcChar8 *) "monotype" },
-    { (const FcChar8*) "Linotype",     (const FcChar8 *) "linotype" },
-    { (const FcChar8*) "LINOTYPE-HELL", (const FcChar8 *) "linotype" },
-    { (const FcChar8*) "IBM",          (const FcChar8 *) "ibm" },
-    { (const FcChar8*) "URW",          (const FcChar8 *) "urw" },
-    { (const FcChar8*) "International Typeface Corporation", 
-                                       (const FcChar8 *) "itc" },
-    { (const FcChar8*) "Tiro Typeworks",(const FcChar8 *) "tiro" },
-    { (const FcChar8*) "XFree86",      (const FcChar8 *) "xfree86" },
-    { (const FcChar8*) "Microsoft",    (const FcChar8 *) "microsoft" },
-    { (const FcChar8*) "Omega",                (const FcChar8 *) "omega" },
-    { (const FcChar8*) "Font21",       (const FcChar8 *) "hwan" },
-    { (const FcChar8*) "HanYang System",(const FcChar8 *) "hanyang" }
+static const char notice_foundry_data[] =
+       "Bigelow\0b&h\0"
+       "Adobe\0adobe\0"
+       "Bitstream\0bitstream\0"
+       "Monotype\0monotype\0"
+       "Linotype\0linotype\0"
+       "LINOTYPE-HELL\0linotype\0"
+       "IBM\0ibm\0"
+       "URW\0urw\0"
+       "International Typeface Corporation\0itc\0"
+       "Tiro Typeworks\0tiro\0"
+       "XFree86\0xfree86\0"
+       "Microsoft\0microsoft\0"
+       "Omega\0omega\0"
+       "Font21\0hwan\0"
+       "HanYang System\0hanyang";
+
+struct _notice_foundry {
+    /* these are the offsets into the
+     * notice_foundry_data array.
+     */
+    unsigned char notice_offset;
+    unsigned char foundry_offset;
 };
 
-#define NUM_NOTICE_FOUNDRIES   (sizeof (FcNoticeFoundries) / sizeof (FcNoticeFoundries[0]))
+static const struct _notice_foundry FcNoticeFoundries[] = {
+    { 0, 8 },
+    { 12, 18 },
+    { 24, 34 },
+    { 44, 53 },
+    { 62, 71 },
+    { 80, 94 },
+    { 103, 107 },
+    { 111, 115 },
+    { 119, 154 },
+    { 158, 173 },
+    { 178, 186 },
+    { 194, 204 },
+    { 214, 220 },
+    { 226, 233 },
+    { 238, 253 }
+};
+
+#define NUM_NOTICE_FOUNDRIES   (int) (sizeof (FcNoticeFoundries) / sizeof (FcNoticeFoundries[0]))
 
 static const FcChar8 *
-FcNoticeFoundry(const char *notice)
+FcNoticeFoundry(const FT_String *notice)
 {
     int i;
 
     if (notice)
        for(i = 0; i < NUM_NOTICE_FOUNDRIES; i++)
-           if (strstr ((const char *) notice, (const char *) FcNoticeFoundries[i].notice))
-               return FcNoticeFoundries[i].foundry;
+        {
+            const struct _notice_foundry *nf = &FcNoticeFoundries[i];
+            const char *n = notice_foundry_data + nf->notice_offset;
+            const char *f = notice_foundry_data + nf->foundry_offset;
+
+           if (strstr ((const char *) notice, n))
+               return (const FcChar8 *) f;
+        }
     return 0;
 }
 
 static FcBool
-FcVendorMatch(const char *vendor, const char *vendor_string)
+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++)
@@ -207,47 +859,47 @@ FcVendorMatch(const char *vendor, const char *vendor_string)
    entries for padding both with spaces and NULs. */
 
 static const struct {
-    const FcChar8   *vendor;
-    const FcChar8   *foundry;
+    const FT_Char   vendor[5];
+    const FcChar8   foundry[13];
 } FcVendorFoundries[] = {
-    { (const FcChar8*) "ADBE", (const FcChar8 *) "adobe"},
-    { (const FcChar8*) "AGFA", (const FcChar8 *) "agfa"},
-    { (const FcChar8*) "ALTS", (const FcChar8 *) "altsys"},
-    { (const FcChar8*) "APPL", (const FcChar8 *) "apple"},
-    { (const FcChar8*) "ARPH", (const FcChar8 *) "arphic"},
-    { (const FcChar8*) "ATEC", (const FcChar8 *) "alltype"},
-    { (const FcChar8*) "B&H",  (const FcChar8 *) "b&h"},
-    { (const FcChar8*) "BITS", (const FcChar8 *) "bitstream"},
-    { (const FcChar8*) "CANO", (const FcChar8 *) "cannon"},
-    { (const FcChar8*) "DYNA", (const FcChar8 *) "dynalab"},
-    { (const FcChar8*) "EPSN", (const FcChar8 *) "epson"},
-    { (const FcChar8*) "FJ",   (const FcChar8 *) "fujitsu"},
-    { (const FcChar8*) "IBM",  (const FcChar8 *) "ibm"},
-    { (const FcChar8*) "ITC",  (const FcChar8 *) "itc"},
-    { (const FcChar8*) "IMPR", (const FcChar8 *) "impress"},
-    { (const FcChar8*) "LARA", (const FcChar8 *) "larabiefonts"},
-    { (const FcChar8*) "LEAF", (const FcChar8 *) "interleaf"},
-    { (const FcChar8*) "LETR", (const FcChar8 *) "letraset"},
-    { (const FcChar8*) "LINO", (const FcChar8 *) "linotype"},
-    { (const FcChar8*) "MACR", (const FcChar8 *) "macromedia"},
-    { (const FcChar8*) "MONO", (const FcChar8 *) "monotype"},
-    { (const FcChar8*) "MS",   (const FcChar8 *) "microsoft"},
-    { (const FcChar8*) "MT",   (const FcChar8 *) "monotype"},
-    { (const FcChar8*) "NEC",  (const FcChar8 *) "nec"},
-    { (const FcChar8*) "PARA", (const FcChar8 *) "paratype"},
-    { (const FcChar8*) "QMSI", (const FcChar8 *) "qms"},
-    { (const FcChar8*) "RICO", (const FcChar8 *) "ricoh"},
-    { (const FcChar8*) "URW",  (const FcChar8 *) "urw"},
-    { (const FcChar8*) "Y&Y",  (const FcChar8 *) "y&y"}
+    { "ADBE", "adobe"},
+    { "AGFA", "agfa"},
+    { "ALTS", "altsys"},
+    { "APPL", "apple"},
+    { "ARPH", "arphic"},
+    { "ATEC", "alltype"},
+    { "B&H",  "b&h"},
+    { "BITS", "bitstream"},
+    { "CANO", "cannon"},
+    { "DYNA", "dynalab"},
+    { "EPSN", "epson"},
+    { "FJ",   "fujitsu"},
+    { "IBM",  "ibm"},
+    { "ITC",  "itc"},
+    { "IMPR", "impress"},
+    { "LARA", "larabiefonts"},
+    { "LEAF", "interleaf"},
+    { "LETR", "letraset"},
+    { "LINO", "linotype"},
+    { "MACR", "macromedia"},
+    { "MONO", "monotype"},
+    { "MS",   "microsoft"},
+    { "MT",   "monotype"},
+    { "NEC",  "nec"},
+    { "PARA", "paratype"},
+    { "QMSI", "qms"},
+    { "RICO", "ricoh"},
+    { "URW",  "urw"},
+    { "Y&Y",  "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 char *vendor)
+FcVendorFoundry(const FT_Char vendor[4])
 {
     int i;
-    
+
     if (vendor)
        for(i = 0; i < NUM_VENDOR_FOUNDRIES; i++)
            if (FcVendorMatch (vendor, FcVendorFoundries[i].vendor))
@@ -256,8 +908,8 @@ FcVendorFoundry(const char *vendor)
 }
 
 typedef struct _FcStringConst {
-    const char *name;
-    int                value;
+    const FcChar8   *name;
+    int                    value;
 } FcStringConst;
 
 static int
@@ -281,99 +933,197 @@ FcStringContainsConst (const FcChar8         *string,
     int        i;
 
     for (i = 0; i < nc; i++)
-       if (FcStrContainsIgnoreBlanksAndCase (string, c[i].name))
-           return c[i].value;
+    {
+       if (c[i].name[0] == '<')
+       {
+           if (FcStrContainsWord (string, c[i].name + 1))
+               return c[i].value;
+       }
+       else
+       {
+           if (FcStrContainsIgnoreBlanksAndCase (string, c[i].name))
+               return c[i].value;
+       }
+    }
     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) "extrabold",       FC_WEIGHT_EXTRABOLD },
+    { (FC8) "superbold",       FC_WEIGHT_EXTRABOLD },
+    { (FC8) "ultrabold",       FC_WEIGHT_ULTRABOLD },
+    { (FC8) "bold",            FC_WEIGHT_BOLD },
+    { (FC8) "ultrablack",      FC_WEIGHT_ULTRABLACK },
+    { (FC8) "superblack",      FC_WEIGHT_EXTRABLACK },
+    { (FC8) "extrablack",      FC_WEIGHT_EXTRABLACK },
+    { (FC8) "<ultra",          FC_WEIGHT_ULTRABOLD }, /* only if a word */
+    { (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 */
+    { (FC8) "extended",                FC_WIDTH_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) "kursiv",          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)
 
+static const FcStringConst  decorativeConsts[] = {
+    { (FC8) "shadow",          FcTrue },
+    { (FC8) "caps",            FcTrue },
+    { (FC8) "antiqua",         FcTrue },
+    { (FC8) "romansc",         FcTrue },
+    { (FC8) "embosed",         FcTrue },
+    { (FC8) "dunhill",         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)
+{
+#if HAVE_FT_GET_BDF_PROPERTY
+    if (face->num_fixed_sizes == 1)
+    {
+       BDF_PropertyRec prop;
+       int             rc;
+
+       rc = FT_Get_BDF_Property (face, "PIXEL_SIZE", &prop);
+       if (rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
+           return (double) prop.u.integer;
+    }
+#endif
+#if HAVE_FT_BITMAP_SIZE_Y_PPEM
+    return (double) face->available_sizes[i].y_ppem / 64.0;
+#else
+    return (double) face->available_sizes[i].height;
+#endif
+}
+
+static FcBool
+FcStringInPatternElement (FcPattern *pat, const char *elt, FcChar8 *string)
+{
+    int            e;
+    FcChar8 *old;
+    for (e = 0; FcPatternGetString (pat, elt, e, &old) == FcResultMatch; e++)
+       if (!FcStrCmpIgnoreBlanksAndCase (old, string))
+       {
+           return FcTrue;
+       }
+    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[] = {
+#ifdef TT_NAME_ID_WWS_FAMILY
+    TT_NAME_ID_WWS_FAMILY,
+#endif
+    TT_NAME_ID_PREFERRED_FAMILY,
+    TT_NAME_ID_FONT_FAMILY,
+    TT_NAME_ID_MAC_FULL_NAME,
+    TT_NAME_ID_FULL_NAME,
+#ifdef TT_NAME_ID_WWS_SUBFAMILY
+    TT_NAME_ID_WWS_SUBFAMILY,
+#endif
+    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;
-    FcChar8        *style = 0;
+#endif
+    FcChar8        *complex_;
     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;
     FT_UInt                snamei, snamec;
-    FcBool         family_allocated = FcFalse;
-    FcBool         style_allocated = FcFalse;
-    int                    family_prio = 0;
-    int                    style_prio = 0;
 
-    if (FT_Init_FreeType (&ftLibrary))
-       return 0;
-    
-    if (FT_New_Face (ftLibrary, (char *) file, id, &face))
-       goto bail;
+    int                    nfamily = 0;
+    int                    nfamily_lang = 0;
+    int                    nstyle = 0;
+    int                    nstyle_lang = 0;
+    int                    nfullname = 0;
+    int                    nfullname_lang = 0;
+    int                    p, platform;
+    int                    n, nameid;
 
-    *count = face->num_faces;
+    FcChar8        *style = 0;
+    int                    st;
 
     pat = FcPatternCreate ();
     if (!pat)
@@ -400,259 +1150,187 @@ FcFreeTypeQuery (const FcChar8 *file,
      * the Postscript FontInfo dictionary.  Finally, the
      * BDF properties will queried.
      */
-    
+
     if (os2 && os2->version >= 0x0001 && os2->version != 0xffff)
         foundry = FcVendorFoundry(os2->achVendID);
 
+    if (FcDebug () & FC_DBG_SCANV)
+       printf ("\n");
     /*
      * Grub through the name table looking for family
      * and style names.  FreeType makes quite a hash
      * 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;
-       int             len;
-       int             wchar;
-       FcChar8         *src;
-       int             src_len;
-       FcChar8         *u8;
-       FcChar32        ucs4;
-       int             ilen, olen;
-       int             prio = 0;
-       
-       const FcCharMap *map;
-       enum {
-           FcNameEncodingUtf16, 
-           FcNameEncodingAppleRoman,
-           FcNameEncodingLatin1 
-       } encoding;
-       
-       
-       if (FT_Get_Sfnt_Name (face, snamei, &sname) != 0)
-           break;
-       
+       if (p < NUM_PLATFORM_ORDER)
+           platform = platform_order[p];
+       else
+           platform = 0xffff;
+
        /*
-        * Look for Unicode strings
+        * Order nameids so preferred names appear first
+        * in the resulting list
         */
-       switch (sname.platform_id) {
-       case TT_PLATFORM_APPLE_UNICODE:
-           /*
-            * All APPLE_UNICODE encodings are Utf16 BE
-            *
-            * Because there's no language id for Unicode,
-            * assume it's English
-            */
-           prio |= FC_NAME_PRIO_LANG_ENGLISH;
-           prio |= FC_NAME_PRIO_ENC_UNICODE;
-           encoding = FcNameEncodingUtf16;
-           break;
-       case TT_PLATFORM_MACINTOSH:
-           switch (sname.encoding_id) {
-           case TT_MAC_ID_ROMAN:
-               encoding = FcNameEncodingAppleRoman;
-               break;
-           default:
-               continue;
-           }
-           switch (sname.language_id) {
-           case TT_MAC_LANGID_ENGLISH:
-               prio |= FC_NAME_PRIO_LANG_ENGLISH;
-               break;
-           default:
+       for (n = 0; n < NUM_NAMEID_ORDER; n++)
+       {
+           nameid = nameid_order[n];
+
+           for (snamei = 0; snamei < snamec; snamei++)
+           {
+               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;
+
                /*
-                * Sometimes Microsoft language ids
-                * end up in the macintosh table.  This
-                * is often accompanied by data in
-                * some mystic encoding.  Ignore these names
+                * Sort platforms in preference order, accepting
+                * all other platforms last
                 */
-               if (sname.language_id >= 0x100)
-                   continue;
-               break;
-           }
-           break;
-       case TT_PLATFORM_MICROSOFT:
-           switch (sname.encoding_id) {
-           case TT_MS_ID_UNICODE_CS:
-               encoding = FcNameEncodingUtf16;
-               prio |= FC_NAME_PRIO_ENC_UNICODE;
-               break;
-           default:
-               continue;
-           }
-           switch (sname.language_id & 0xff) {
-           case 0x09:
-               prio |= FC_NAME_PRIO_LANG_ENGLISH;
-               break;
-           default:
-               break;
-           }
-           break;
-       case TT_PLATFORM_ISO:
-           switch (sname.encoding_id) {
-           case TT_ISO_ID_10646:
-               encoding = FcNameEncodingUtf16;
-               prio |= FC_NAME_PRIO_ENC_UNICODE;
-               break;
-           case TT_ISO_ID_7BIT_ASCII:
-           case TT_ISO_ID_8859_1:
-               encoding = FcNameEncodingLatin1;
-               break;
-           default:
-               continue;
-           }
-           break;
-       default:
-           continue;
-       }
-       
-       /*
-        * Look for family and style names 
-        */
-       switch (sname.name_id) {
-       case TT_NAME_ID_FONT_FAMILY:
-           prio |= FC_NAME_PRIO_NAME_FAMILY;
-           break;
-       case TT_NAME_ID_PS_NAME:
-           prio |= FC_NAME_PRIO_NAME_PS;
-           break;
-       case TT_NAME_ID_FONT_SUBFAMILY:
-        case TT_NAME_ID_TRADEMARK:
-        case TT_NAME_ID_MANUFACTURER:
-            break;
-       default:
-           continue;
-       }
-           
-        src = (FcChar8 *) sname.string;
-        src_len = sname.string_len;
-       
-       switch (encoding) {
-       case FcNameEncodingUtf16:
-           /*
-            * Convert Utf16 to Utf8
-            */
-           
-           if (!FcUtf16Len (src, FcEndianBig, src_len, &len, &wchar))
-               continue;
-    
-           /*
-            * Allocate plenty of space.  Freed below
-            */
-           utf8 = malloc (len * FC_UTF8_MAX_LEN + 1);
-           if (!utf8)
-               continue;
-               
-           u8 = utf8;
-           
-           while ((ilen = FcUtf16ToUcs4 (src, FcEndianBig, &ucs4, src_len)) > 0)
-           {
-               src_len -= ilen;
-               src += ilen;
-               olen = FcUcs4ToUtf8 (ucs4, u8);
-               u8 += olen;
-           }
-           *u8 = '\0';
-           break;
-       case FcNameEncodingLatin1:
-           /*
-            * Convert Latin1 to Utf8. Freed below
-            */
-           utf8 = malloc (src_len * 2 + 1);
-           if (!utf8)
-               continue;
+               if (p < NUM_PLATFORM_ORDER)
+               {
+                   if (sname.platform_id != platform)
+                       continue;
+               }
+               else
+               {
+                   int     sp;
 
-           u8 = utf8;
-           while (src_len > 0)
-           {
-               ucs4 = *src++;
-               src_len--;
-               olen = FcUcs4ToUtf8 (ucs4, u8);
-               u8 += olen;
-           }
-           *u8 = '\0';
-           break;
-       case FcNameEncodingAppleRoman:
-           /*
-            * Convert AppleRoman to Utf8
-            */
-           map = FcFreeTypeGetPrivateMap (ft_encoding_apple_roman);
-           if (!map)
-               continue;
+                   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);
 
-           /* freed below */
-           utf8 = malloc (src_len * 3 + 1);
-           if (!utf8)
-               continue;
+               if (!utf8)
+                   continue;
 
-           u8 = utf8;
-           while (src_len > 0)
-           {
-               ucs4 = FcFreeTypePrivateToUcs4 (*src++, map);
-               src_len--;
-               olen = FcUcs4ToUtf8 (ucs4, u8);
-               u8 += olen;
+               switch (sname.name_id) {
+#ifdef TT_NAME_ID_WWS_FAMILY
+               case TT_NAME_ID_WWS_FAMILY:
+#endif
+               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;
+#ifdef TT_NAME_ID_WWS_SUBFAMILY
+               case TT_NAME_ID_WWS_SUBFAMILY:
+#endif
+               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 (FcStringInPatternElement (pat, elt, utf8))
+                   {
+                       free (utf8);
+                       continue;
+                   }
+
+                   /* add new element */
+                   if (!FcPatternAddString (pat, elt, utf8))
+                   {
+                       free (utf8);
+                       goto bail1;
+                   }
+                   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;
+               }
+               else
+                   free (utf8);
            }
-           *u8 = '\0';
-           break;
-       default:
-           continue;
        }
-       if ((prio & FC_NAME_PRIO_LANG) == FC_NAME_PRIO_LANG_NONE)
-           if (FcUtf8IsLatin (utf8, strlen ((char *) utf8)))
-               prio |= FC_NAME_PRIO_LANG_LATIN;
-                              
+    }
+
+    if (!nfamily && face->family_name &&
+       FcStrCmpIgnoreBlanksAndCase ((FcChar8 *) face->family_name, (FcChar8 *) "") != 0)
+    {
        if (FcDebug () & FC_DBG_SCANV)
-           printf ("\nfound name (name %d platform %d encoding %d language 0x%x prio 0x%x) %s\n",
-                   sname.name_id, sname.platform_id,
-                   sname.encoding_id, sname.language_id,
-                   prio, utf8);
-    
-       switch (sname.name_id) {
-       case TT_NAME_ID_FONT_FAMILY:
-       case TT_NAME_ID_PS_NAME:
-           if (!family || prio > family_prio)
-           {
-               if (family)
-                   free (family);
-               family = utf8;
-               utf8 = 0;
-               family_allocated = FcTrue;
-               family_prio = prio;
-           }
-           break;
-       case TT_NAME_ID_FONT_SUBFAMILY:
-           if (!style || prio > style_prio)
-           {
-               if (style)
-                   free (style);
-               style = utf8;
-               utf8 = 0;
-               style_allocated = FcTrue;
-               style_prio = prio;
-           }
-           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(utf8);
-            break;
-       }
-       if (utf8)
-           free (utf8);
+           printf ("using FreeType family \"%s\"\n", face->family_name);
+       if (!FcPatternAddString (pat, FC_FAMILY, (FcChar8 *) face->family_name))
+           goto bail1;
+       ++nfamily;
+    }
+
+    if (!nstyle && face->style_name &&
+       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, (FcChar8 *) face->style_name))
+           goto bail1;
+       ++nstyle;
     }
-    
-    if (!family)
-       family = (FcChar8 *) face->family_name;
-    
-    if (!style)
-       style = (FcChar8 *) face->style_name;
-    
-    if (!family)
+
+    if (!nfamily)
     {
        FcChar8 *start, *end;
+       FcChar8 *family;
        
        start = (FcChar8 *) strrchr ((char *) file, '/');
        if (start)
@@ -666,19 +1344,15 @@ FcFreeTypeQuery (const FcChar8   *file,
        family = malloc (end - start + 1);
        strncpy ((char *) family, (char *) start, end - start);
        family[end - start] = '\0';
-       family_allocated = FcTrue;
-    }
-
-    if (FcDebug() & FC_DBG_SCAN)
-       printf ("\n\"%s\" \"%s\"\n", family, style ? style : (FcChar8 *) "<none>");
-
-    if (!FcPatternAddString (pat, FC_FAMILY, family))
-       goto bail1;
-
-    if (style)
-    {
-       if (!FcPatternAddString (pat, FC_STYLE, style))
+       if (FcDebug () & FC_DBG_SCANV)
+           printf ("using filename for family %s\n", family);
+       if (!FcPatternAddString (pat, FC_FAMILY, family))
+       {
+           free (family);
            goto bail1;
+       }
+       free (family);
+       ++nfamily;
     }
 
     if (!FcPatternAddString (pat, FC_FILE, file))
@@ -687,9 +1361,6 @@ FcFreeTypeQuery (const FcChar8     *file,
     if (!FcPatternAddInteger (pat, FC_INDEX, id))
        goto bail1;
 
-    if (!FcPatternAddString (pat, FC_SOURCE, (FcChar8 *) "FreeType"))
-       goto bail1;
-
 #if 0
     /*
      * don't even try this -- CJK 'monospace' fonts are really
@@ -734,7 +1405,7 @@ FcFreeTypeQuery (const FcChar8     *file,
            }
            if (bits & (1 << bit))
            {
-               /* 
+               /*
                 * If the font advertises support for multiple
                 * "exclusive" languages, then include support
                 * for any language found to have coverage
@@ -769,8 +1440,13 @@ FcFreeTypeQuery (const FcChar8    *file,
            weight = FC_WEIGHT_BOLD;
        else if (os2->usWeightClass < 850)
            weight = FC_WEIGHT_EXTRABOLD;
-       else if (os2->usWeightClass < 950)
+       else if (os2->usWeightClass < 925)
            weight = FC_WEIGHT_BLACK;
+       else if (os2->usWeightClass < 1000)
+           weight = FC_WEIGHT_EXTRABLACK;
+       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;
@@ -783,41 +1459,53 @@ 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)))
+    {
+       if (!FcPatternAddString (pat, FC_CAPABILITY, complex_))
+       {
+           free (complex_);
+           goto bail1;
+       }
+       free (complex_);
     }
 
     /*
      * Type 1: Check for FontInfo dictionary information
      * 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);
+           weight = FcIsWeight ((FcChar8 *) psfontinfo.weight);
            if (FcDebug() & FC_DBG_SCANV)
                printf ("\tType1 weight %s maps to %d\n",
                        psfontinfo.weight, weight);
        }
-#endif
-     
+
 #if 0
-       /* 
+       /*
         * Don't bother with italic_angle; FreeType already extracts that
         * information for us and sticks it into style_flags
         */
         if (psfontinfo.italic_angle)
-            slant = FC_SLANT_ITALIC; 
+            slant = FC_SLANT_ITALIC;
         else
-            slant = FC_SLANT_ROMAN; 
+            slant = FC_SLANT_ROMAN;
 #endif
 
         if(!foundry)
             foundry = FcNoticeFoundry(psfontinfo.notice);
     }
-    
-#ifdef USE_FTBDF
+#endif /* HAVE_FT_GET_PS_FONT_INFO */
+
+#if HAVE_FT_GET_BDF_PROPERTY
     /*
      * Finally, look for a FOUNDRY BDF property if no other
      * mechanism has managed to locate a foundry
@@ -826,21 +1514,19 @@ 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)
     {
-       BDF_PropertyRec prop;
-       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))
        {
            FT_Int32    value;
-           
+       
            if (prop.type == BDF_PROPERTY_TYPE_INTEGER)
                value = prop.u.integer;
            else
@@ -858,21 +1544,20 @@ 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);
        }
     }
-
 #endif
 
     /*
      * Look for weight, width and slant names in the style value
      */
-    if (style)
+    for (st = 0; FcPatternGetString (pat, FC_STYLE, st, &style) == FcResultMatch; st++)
     {
        if (weight == -1)
        {
@@ -892,6 +1577,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
@@ -911,21 +1602,26 @@ FcFreeTypeQuery (const FcChar8   *file,
            weight = FC_WEIGHT_BOLD;
     }
 
+    if (width == -1)
+       width = FC_WIDTH_NORMAL;
+
+    if (foundry == 0)
+       foundry = (FcChar8 *) "unknown";
+
     if (!FcPatternAddInteger (pat, FC_SLANT, slant))
        goto bail1;
 
     if (!FcPatternAddInteger (pat, FC_WEIGHT, weight))
        goto bail1;
 
-    if (width != -1)
-       if (!FcPatternAddInteger (pat, FC_WIDTH, width))
-           goto bail1;
+    if (!FcPatternAddInteger (pat, FC_WIDTH, width))
+       goto bail1;
 
-    if(foundry) 
-    {
-        if(!FcPatternAddString (pat, FC_FOUNDRY, foundry))
-            goto bail1;
-    }
+    if (!FcPatternAddString (pat, FC_FOUNDRY, foundry))
+       goto bail1;
+
+    if (!FcPatternAddBool (pat, FC_DECORATIVE, decorative))
+       goto bail1;
 
     /*
      * Compute the unicode coverage for the font
@@ -934,16 +1630,16 @@ FcFreeTypeQuery (const FcChar8   *file,
     if (!cs)
        goto bail1;
 
-#ifdef USE_FTBDF
+#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"))
+        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"))
+        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"))
+        else if(!strcmp(prop.u.atom, "p") || !strcmp(prop.u.atom, "P"))
             spacing = FC_PROPORTIONAL;
     }
 #endif
@@ -951,11 +1647,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
+     * FT 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))
@@ -966,7 +1667,12 @@ FcFreeTypeQuery (const FcChar8    *file,
        goto bail2;
 
     if (!FcPatternAddLangSet (pat, FC_LANG, ls))
+    {
+       FcLangSetDestroy (ls);
        goto bail2;
+    }
+
+    FcLangSetDestroy (ls);
 
     if (spacing != FC_PROPORTIONAL)
        if (!FcPatternAddInteger (pat, FC_SPACING, spacing))
@@ -976,116 +1682,72 @@ FcFreeTypeQuery (const FcChar8  *file,
     {
        for (i = 0; i < face->num_fixed_sizes; i++)
            if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE,
-                                    (double) face->available_sizes[i].height))
-               goto bail1;
+                                    FcGetPixelSize (face, i)))
+               goto bail2;
        if (!FcPatternAddBool (pat, FC_ANTIALIAS, FcFalse))
-           goto bail1;
-#ifdef USE_FTBDF
-        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
+           goto bail2;
     }
+#if HAVE_FT_GET_X11_FONT_FORMAT
+    /*
+     * Use the (not well documented or supported) X-specific function
+     * from FreeType to figure out the font format
+     */
+    {
+       const char *font_format = FT_Get_X11_Font_Format (face);
+       if (font_format)
+           FcPatternAddString (pat, FC_FONTFORMAT, (FcChar8 *) font_format);
+    }
+#endif
 
     /*
      * Drop our reference to the charset
      */
     FcCharSetDestroy (cs);
-    
-    /*
-     * Deallocate family/style values
-     */
-    
-    if (family_allocated)
-       free (family);
-    if (style_allocated)
-       free (style);
-    
-    FT_Done_Face (face);
-    FT_Done_FreeType (ftLibrary);
+
     return pat;
 
 bail2:
     FcCharSetDestroy (cs);
 bail1:
     FcPatternDestroy (pat);
-    if (family_allocated)
-       free (family);
-    if (style_allocated)
-       free (style);
 bail0:
-    FT_Done_Face (face);
-bail:
-    FT_Done_FreeType (ftLibrary);
-    return 0;
+    return NULL;
 }
 
+FcPattern *
+FcFreeTypeQuery(const FcChar8  *file,
+               int             id,
+               FcBlanks        *blanks,
+               int             *count)
+{
+    FT_Face        face;
+    FT_Library     ftLibrary;
+    FcPattern      *pat = NULL;
 
-/*
- * Figure out whether the available freetype has FT_Get_Next_Char
- */
+    if (FT_Init_FreeType (&ftLibrary))
+       return NULL;
 
-#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
+    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 pat;
+}
 
 /*
  * 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)
-#warning "No FT_Get_Next_Char"
+#warning "No FT_Get_Next_Char: Please install freetype version 2.1.0 or newer"
 #endif
 
 typedef struct _FcCharEnt {
@@ -1104,237 +1766,6 @@ typedef struct _FcFontDecode {
     FcChar32       max;
 } FcFontDecode;
 
-static const FcCharEnt AppleRomanEnt[] = {
-    { 0x0020, 0x20 }, /* SPACE */
-    { 0x0021, 0x21 }, /* EXCLAMATION MARK */
-    { 0x0022, 0x22 }, /* QUOTATION MARK */
-    { 0x0023, 0x23 }, /* NUMBER SIGN */
-    { 0x0024, 0x24 }, /* DOLLAR SIGN */
-    { 0x0025, 0x25 }, /* PERCENT SIGN */
-    { 0x0026, 0x26 }, /* AMPERSAND */
-    { 0x0027, 0x27 }, /* APOSTROPHE */
-    { 0x0028, 0x28 }, /* LEFT PARENTHESIS */
-    { 0x0029, 0x29 }, /* RIGHT PARENTHESIS */
-    { 0x002A, 0x2A }, /* ASTERISK */
-    { 0x002B, 0x2B }, /* PLUS SIGN */
-    { 0x002C, 0x2C }, /* COMMA */
-    { 0x002D, 0x2D }, /* HYPHEN-MINUS */
-    { 0x002E, 0x2E }, /* FULL STOP */
-    { 0x002F, 0x2F }, /* SOLIDUS */
-    { 0x0030, 0x30 }, /* DIGIT ZERO */
-    { 0x0031, 0x31 }, /* DIGIT ONE */
-    { 0x0032, 0x32 }, /* DIGIT TWO */
-    { 0x0033, 0x33 }, /* DIGIT THREE */
-    { 0x0034, 0x34 }, /* DIGIT FOUR */
-    { 0x0035, 0x35 }, /* DIGIT FIVE */
-    { 0x0036, 0x36 }, /* DIGIT SIX */
-    { 0x0037, 0x37 }, /* DIGIT SEVEN */
-    { 0x0038, 0x38 }, /* DIGIT EIGHT */
-    { 0x0039, 0x39 }, /* DIGIT NINE */
-    { 0x003A, 0x3A }, /* COLON */
-    { 0x003B, 0x3B }, /* SEMICOLON */
-    { 0x003C, 0x3C }, /* LESS-THAN SIGN */
-    { 0x003D, 0x3D }, /* EQUALS SIGN */
-    { 0x003E, 0x3E }, /* GREATER-THAN SIGN */
-    { 0x003F, 0x3F }, /* QUESTION MARK */
-    { 0x0040, 0x40 }, /* COMMERCIAL AT */
-    { 0x0041, 0x41 }, /* LATIN CAPITAL LETTER A */
-    { 0x0042, 0x42 }, /* LATIN CAPITAL LETTER B */
-    { 0x0043, 0x43 }, /* LATIN CAPITAL LETTER C */
-    { 0x0044, 0x44 }, /* LATIN CAPITAL LETTER D */
-    { 0x0045, 0x45 }, /* LATIN CAPITAL LETTER E */
-    { 0x0046, 0x46 }, /* LATIN CAPITAL LETTER F */
-    { 0x0047, 0x47 }, /* LATIN CAPITAL LETTER G */
-    { 0x0048, 0x48 }, /* LATIN CAPITAL LETTER H */
-    { 0x0049, 0x49 }, /* LATIN CAPITAL LETTER I */
-    { 0x004A, 0x4A }, /* LATIN CAPITAL LETTER J */
-    { 0x004B, 0x4B }, /* LATIN CAPITAL LETTER K */
-    { 0x004C, 0x4C }, /* LATIN CAPITAL LETTER L */
-    { 0x004D, 0x4D }, /* LATIN CAPITAL LETTER M */
-    { 0x004E, 0x4E }, /* LATIN CAPITAL LETTER N */
-    { 0x004F, 0x4F }, /* LATIN CAPITAL LETTER O */
-    { 0x0050, 0x50 }, /* LATIN CAPITAL LETTER P */
-    { 0x0051, 0x51 }, /* LATIN CAPITAL LETTER Q */
-    { 0x0052, 0x52 }, /* LATIN CAPITAL LETTER R */
-    { 0x0053, 0x53 }, /* LATIN CAPITAL LETTER S */
-    { 0x0054, 0x54 }, /* LATIN CAPITAL LETTER T */
-    { 0x0055, 0x55 }, /* LATIN CAPITAL LETTER U */
-    { 0x0056, 0x56 }, /* LATIN CAPITAL LETTER V */
-    { 0x0057, 0x57 }, /* LATIN CAPITAL LETTER W */
-    { 0x0058, 0x58 }, /* LATIN CAPITAL LETTER X */
-    { 0x0059, 0x59 }, /* LATIN CAPITAL LETTER Y */
-    { 0x005A, 0x5A }, /* LATIN CAPITAL LETTER Z */
-    { 0x005B, 0x5B }, /* LEFT SQUARE BRACKET */
-    { 0x005C, 0x5C }, /* REVERSE SOLIDUS */
-    { 0x005D, 0x5D }, /* RIGHT SQUARE BRACKET */
-    { 0x005E, 0x5E }, /* CIRCUMFLEX ACCENT */
-    { 0x005F, 0x5F }, /* LOW LINE */
-    { 0x0060, 0x60 }, /* GRAVE ACCENT */
-    { 0x0061, 0x61 }, /* LATIN SMALL LETTER A */
-    { 0x0062, 0x62 }, /* LATIN SMALL LETTER B */
-    { 0x0063, 0x63 }, /* LATIN SMALL LETTER C */
-    { 0x0064, 0x64 }, /* LATIN SMALL LETTER D */
-    { 0x0065, 0x65 }, /* LATIN SMALL LETTER E */
-    { 0x0066, 0x66 }, /* LATIN SMALL LETTER F */
-    { 0x0067, 0x67 }, /* LATIN SMALL LETTER G */
-    { 0x0068, 0x68 }, /* LATIN SMALL LETTER H */
-    { 0x0069, 0x69 }, /* LATIN SMALL LETTER I */
-    { 0x006A, 0x6A }, /* LATIN SMALL LETTER J */
-    { 0x006B, 0x6B }, /* LATIN SMALL LETTER K */
-    { 0x006C, 0x6C }, /* LATIN SMALL LETTER L */
-    { 0x006D, 0x6D }, /* LATIN SMALL LETTER M */
-    { 0x006E, 0x6E }, /* LATIN SMALL LETTER N */
-    { 0x006F, 0x6F }, /* LATIN SMALL LETTER O */
-    { 0x0070, 0x70 }, /* LATIN SMALL LETTER P */
-    { 0x0071, 0x71 }, /* LATIN SMALL LETTER Q */
-    { 0x0072, 0x72 }, /* LATIN SMALL LETTER R */
-    { 0x0073, 0x73 }, /* LATIN SMALL LETTER S */
-    { 0x0074, 0x74 }, /* LATIN SMALL LETTER T */
-    { 0x0075, 0x75 }, /* LATIN SMALL LETTER U */
-    { 0x0076, 0x76 }, /* LATIN SMALL LETTER V */
-    { 0x0077, 0x77 }, /* LATIN SMALL LETTER W */
-    { 0x0078, 0x78 }, /* LATIN SMALL LETTER X */
-    { 0x0079, 0x79 }, /* LATIN SMALL LETTER Y */
-    { 0x007A, 0x7A }, /* LATIN SMALL LETTER Z */
-    { 0x007B, 0x7B }, /* LEFT CURLY BRACKET */
-    { 0x007C, 0x7C }, /* VERTICAL LINE */
-    { 0x007D, 0x7D }, /* RIGHT CURLY BRACKET */
-    { 0x007E, 0x7E }, /* TILDE */
-    { 0x00A0, 0xCA }, /* NO-BREAK SPACE */
-    { 0x00A1, 0xC1 }, /* INVERTED EXCLAMATION MARK */
-    { 0x00A2, 0xA2 }, /* CENT SIGN */
-    { 0x00A3, 0xA3 }, /* POUND SIGN */
-    { 0x00A5, 0xB4 }, /* YEN SIGN */
-    { 0x00A7, 0xA4 }, /* SECTION SIGN */
-    { 0x00A8, 0xAC }, /* DIAERESIS */
-    { 0x00A9, 0xA9 }, /* COPYRIGHT SIGN */
-    { 0x00AA, 0xBB }, /* FEMININE ORDINAL INDICATOR */
-    { 0x00AB, 0xC7 }, /* LEFT-POINTING DOUBLE ANGLE QUOTATION MARK */
-    { 0x00AC, 0xC2 }, /* NOT SIGN */
-    { 0x00AE, 0xA8 }, /* REGISTERED SIGN */
-    { 0x00AF, 0xF8 }, /* MACRON */
-    { 0x00B0, 0xA1 }, /* DEGREE SIGN */
-    { 0x00B1, 0xB1 }, /* PLUS-MINUS SIGN */
-    { 0x00B4, 0xAB }, /* ACUTE ACCENT */
-    { 0x00B5, 0xB5 }, /* MICRO SIGN */
-    { 0x00B6, 0xA6 }, /* PILCROW SIGN */
-    { 0x00B7, 0xE1 }, /* MIDDLE DOT */
-    { 0x00B8, 0xFC }, /* CEDILLA */
-    { 0x00BA, 0xBC }, /* MASCULINE ORDINAL INDICATOR */
-    { 0x00BB, 0xC8 }, /* RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK */
-    { 0x00BF, 0xC0 }, /* INVERTED QUESTION MARK */
-    { 0x00C0, 0xCB }, /* LATIN CAPITAL LETTER A WITH GRAVE */
-    { 0x00C1, 0xE7 }, /* LATIN CAPITAL LETTER A WITH ACUTE */
-    { 0x00C2, 0xE5 }, /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */
-    { 0x00C3, 0xCC }, /* LATIN CAPITAL LETTER A WITH TILDE */
-    { 0x00C4, 0x80 }, /* LATIN CAPITAL LETTER A WITH DIAERESIS */
-    { 0x00C5, 0x81 }, /* LATIN CAPITAL LETTER A WITH RING ABOVE */
-    { 0x00C6, 0xAE }, /* LATIN CAPITAL LETTER AE */
-    { 0x00C7, 0x82 }, /* LATIN CAPITAL LETTER C WITH CEDILLA */
-    { 0x00C8, 0xE9 }, /* LATIN CAPITAL LETTER E WITH GRAVE */
-    { 0x00C9, 0x83 }, /* LATIN CAPITAL LETTER E WITH ACUTE */
-    { 0x00CA, 0xE6 }, /* LATIN CAPITAL LETTER E WITH CIRCUMFLEX */
-    { 0x00CB, 0xE8 }, /* LATIN CAPITAL LETTER E WITH DIAERESIS */
-    { 0x00CC, 0xED }, /* LATIN CAPITAL LETTER I WITH GRAVE */
-    { 0x00CD, 0xEA }, /* LATIN CAPITAL LETTER I WITH ACUTE */
-    { 0x00CE, 0xEB }, /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */
-    { 0x00CF, 0xEC }, /* LATIN CAPITAL LETTER I WITH DIAERESIS */
-    { 0x00D1, 0x84 }, /* LATIN CAPITAL LETTER N WITH TILDE */
-    { 0x00D2, 0xF1 }, /* LATIN CAPITAL LETTER O WITH GRAVE */
-    { 0x00D3, 0xEE }, /* LATIN CAPITAL LETTER O WITH ACUTE */
-    { 0x00D4, 0xEF }, /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */
-    { 0x00D5, 0xCD }, /* LATIN CAPITAL LETTER O WITH TILDE */
-    { 0x00D6, 0x85 }, /* LATIN CAPITAL LETTER O WITH DIAERESIS */
-    { 0x00D8, 0xAF }, /* LATIN CAPITAL LETTER O WITH STROKE */
-    { 0x00D9, 0xF4 }, /* LATIN CAPITAL LETTER U WITH GRAVE */
-    { 0x00DA, 0xF2 }, /* LATIN CAPITAL LETTER U WITH ACUTE */
-    { 0x00DB, 0xF3 }, /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */
-    { 0x00DC, 0x86 }, /* LATIN CAPITAL LETTER U WITH DIAERESIS */
-    { 0x00DF, 0xA7 }, /* LATIN SMALL LETTER SHARP S */
-    { 0x00E0, 0x88 }, /* LATIN SMALL LETTER A WITH GRAVE */
-    { 0x00E1, 0x87 }, /* LATIN SMALL LETTER A WITH ACUTE */
-    { 0x00E2, 0x89 }, /* LATIN SMALL LETTER A WITH CIRCUMFLEX */
-    { 0x00E3, 0x8B }, /* LATIN SMALL LETTER A WITH TILDE */
-    { 0x00E4, 0x8A }, /* LATIN SMALL LETTER A WITH DIAERESIS */
-    { 0x00E5, 0x8C }, /* LATIN SMALL LETTER A WITH RING ABOVE */
-    { 0x00E6, 0xBE }, /* LATIN SMALL LETTER AE */
-    { 0x00E7, 0x8D }, /* LATIN SMALL LETTER C WITH CEDILLA */
-    { 0x00E8, 0x8F }, /* LATIN SMALL LETTER E WITH GRAVE */
-    { 0x00E9, 0x8E }, /* LATIN SMALL LETTER E WITH ACUTE */
-    { 0x00EA, 0x90 }, /* LATIN SMALL LETTER E WITH CIRCUMFLEX */
-    { 0x00EB, 0x91 }, /* LATIN SMALL LETTER E WITH DIAERESIS */
-    { 0x00EC, 0x93 }, /* LATIN SMALL LETTER I WITH GRAVE */
-    { 0x00ED, 0x92 }, /* LATIN SMALL LETTER I WITH ACUTE */
-    { 0x00EE, 0x94 }, /* LATIN SMALL LETTER I WITH CIRCUMFLEX */
-    { 0x00EF, 0x95 }, /* LATIN SMALL LETTER I WITH DIAERESIS */
-    { 0x00F1, 0x96 }, /* LATIN SMALL LETTER N WITH TILDE */
-    { 0x00F2, 0x98 }, /* LATIN SMALL LETTER O WITH GRAVE */
-    { 0x00F3, 0x97 }, /* LATIN SMALL LETTER O WITH ACUTE */
-    { 0x00F4, 0x99 }, /* LATIN SMALL LETTER O WITH CIRCUMFLEX */
-    { 0x00F5, 0x9B }, /* LATIN SMALL LETTER O WITH TILDE */
-    { 0x00F6, 0x9A }, /* LATIN SMALL LETTER O WITH DIAERESIS */
-    { 0x00F7, 0xD6 }, /* DIVISION SIGN */
-    { 0x00F8, 0xBF }, /* LATIN SMALL LETTER O WITH STROKE */
-    { 0x00F9, 0x9D }, /* LATIN SMALL LETTER U WITH GRAVE */
-    { 0x00FA, 0x9C }, /* LATIN SMALL LETTER U WITH ACUTE */
-    { 0x00FB, 0x9E }, /* LATIN SMALL LETTER U WITH CIRCUMFLEX */
-    { 0x00FC, 0x9F }, /* LATIN SMALL LETTER U WITH DIAERESIS */
-    { 0x00FF, 0xD8 }, /* LATIN SMALL LETTER Y WITH DIAERESIS */
-    { 0x0131, 0xF5 }, /* LATIN SMALL LETTER DOTLESS I */
-    { 0x0152, 0xCE }, /* LATIN CAPITAL LIGATURE OE */
-    { 0x0153, 0xCF }, /* LATIN SMALL LIGATURE OE */
-    { 0x0178, 0xD9 }, /* LATIN CAPITAL LETTER Y WITH DIAERESIS */
-    { 0x0192, 0xC4 }, /* LATIN SMALL LETTER F WITH HOOK */
-    { 0x02C6, 0xF6 }, /* MODIFIER LETTER CIRCUMFLEX ACCENT */
-    { 0x02C7, 0xFF }, /* CARON */
-    { 0x02D8, 0xF9 }, /* BREVE */
-    { 0x02D9, 0xFA }, /* DOT ABOVE */
-    { 0x02DA, 0xFB }, /* RING ABOVE */
-    { 0x02DB, 0xFE }, /* OGONEK */
-    { 0x02DC, 0xF7 }, /* SMALL TILDE */
-    { 0x02DD, 0xFD }, /* DOUBLE ACUTE ACCENT */
-    { 0x03A9, 0xBD }, /* GREEK CAPITAL LETTER OMEGA */
-    { 0x03C0, 0xB9 }, /* GREEK SMALL LETTER PI */
-    { 0x2013, 0xD0 }, /* EN DASH */
-    { 0x2014, 0xD1 }, /* EM DASH */
-    { 0x2018, 0xD4 }, /* LEFT SINGLE QUOTATION MARK */
-    { 0x2019, 0xD5 }, /* RIGHT SINGLE QUOTATION MARK */
-    { 0x201A, 0xE2 }, /* SINGLE LOW-9 QUOTATION MARK */
-    { 0x201C, 0xD2 }, /* LEFT DOUBLE QUOTATION MARK */
-    { 0x201D, 0xD3 }, /* RIGHT DOUBLE QUOTATION MARK */
-    { 0x201E, 0xE3 }, /* DOUBLE LOW-9 QUOTATION MARK */
-    { 0x2020, 0xA0 }, /* DAGGER */
-    { 0x2021, 0xE0 }, /* DOUBLE DAGGER */
-    { 0x2022, 0xA5 }, /* BULLET */
-    { 0x2026, 0xC9 }, /* HORIZONTAL ELLIPSIS */
-    { 0x2030, 0xE4 }, /* PER MILLE SIGN */
-    { 0x2039, 0xDC }, /* SINGLE LEFT-POINTING ANGLE QUOTATION MARK */
-    { 0x203A, 0xDD }, /* SINGLE RIGHT-POINTING ANGLE QUOTATION MARK */
-    { 0x2044, 0xDA }, /* FRACTION SLASH */
-    { 0x20AC, 0xDB }, /* EURO SIGN */
-    { 0x2122, 0xAA }, /* TRADE MARK SIGN */
-    { 0x2202, 0xB6 }, /* PARTIAL DIFFERENTIAL */
-    { 0x2206, 0xC6 }, /* INCREMENT */
-    { 0x220F, 0xB8 }, /* N-ARY PRODUCT */
-    { 0x2211, 0xB7 }, /* N-ARY SUMMATION */
-    { 0x221A, 0xC3 }, /* SQUARE ROOT */
-    { 0x221E, 0xB0 }, /* INFINITY */
-    { 0x222B, 0xBA }, /* INTEGRAL */
-    { 0x2248, 0xC5 }, /* ALMOST EQUAL TO */
-    { 0x2260, 0xAD }, /* NOT EQUAL TO */
-    { 0x2264, 0xB2 }, /* LESS-THAN OR EQUAL TO */
-    { 0x2265, 0xB3 }, /* GREATER-THAN OR EQUAL TO */
-    { 0x25CA, 0xD7 }, /* LOZENGE */
-    { 0xF8FF, 0xF0 }, /* Apple logo */
-    { 0xFB01, 0xDE }, /* LATIN SMALL LIGATURE FI */
-    { 0xFB02, 0xDF }, /* LATIN SMALL LIGATURE FL */
-};
-
-static const FcCharMap AppleRoman = {
-    AppleRomanEnt,
-    sizeof (AppleRomanEnt) / sizeof (AppleRomanEnt[0])
-};
-
 static const FcCharEnt AdobeSymbolEnt[] = {
     { 0x0020, 0x20 }, /* SPACE # space */
     { 0x0021, 0x21 }, /* EXCLAMATION MARK      # exclam */
@@ -1536,14 +1967,19 @@ static const FcCharMap AdobeSymbol = {
     AdobeSymbolEnt,
     sizeof (AdobeSymbolEnt) / sizeof (AdobeSymbolEnt[0]),
 };
-    
+
 static const FcFontDecode fcFontDecoders[] = {
     { ft_encoding_unicode,     0,              (1 << 21) - 1 },
     { ft_encoding_symbol,      &AdobeSymbol,   (1 << 16) - 1 },
-    { 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)
@@ -1606,6 +2042,7 @@ FcHashGlyphName (const FcChar8 *name)
     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
@@ -1614,7 +2051,7 @@ 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++)
@@ -1623,18 +2060,18 @@ 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;
+    FcGlyphId  gn;
 
-    while ((gn = ucs_to_name[i]))
+    while ((gn = _fc_ucs_to_name[i]) != -1)
     {
-       if (gn->ucs == ucs4)
-           return gn->name;
-       if (!r) 
+       if (_fc_glyph_names[gn].ucs == ucs4)
+           return _fc_glyph_names[gn].name;
+       if (!r)
        {
            r = (int) (ucs4 % FC_GLYPHNAME_REHASH);
            if (!r)
@@ -1653,13 +2090,13 @@ FcGlyphNameToUcs4 (FcChar8 *name)
     FcChar32   h = FcHashGlyphName (name);
     int                i = (int) (h % FC_GLYPHNAME_HASH);
     int                r = 0;
-    FcGlyphName        *gn;
+    FcGlyphId  gn;
 
-    while ((gn = name_to_ucs[i]))
+    while ((gn = _fc_name_to_ucs[i]) != -1)
     {
-       if (!strcmp ((char *) name, (char *) gn->name))
-           return gn->ucs;
-       if (!r) 
+       if (!strcmp ((char *) name, (char *) _fc_glyph_names[gn].name))
+           return _fc_glyph_names[gn].ucs;
+       if (!r)
        {
            r = (int) (h % FC_GLYPHNAME_REHASH);
            if (!r)
@@ -1672,25 +2109,39 @@ 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
  * 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];
+    FcChar8 name_buf[FC_GLYPHNAME_BUFLEN + 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 (FT_Get_Glyph_Name (face, gindex, name_buf, FC_GLYPHNAME_BUFLEN+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
@@ -1704,8 +2155,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
      */
@@ -1717,6 +2173,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
      */
@@ -1729,7 +2191,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
@@ -1738,12 +2200,13 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
        if (glyphindex)
            return glyphindex;
     }
+#if HAVE_FT_HAS_PS_GLYPH_NAMES
     /*
      * Check postscript name table if present
      */
     if (FcFreeTypeUseNames (face))
     {
-       FcChar8 *name = FcUcs4ToGlyphName (ucs4);
+       const FcChar8   *name = FcUcs4ToGlyphName (ucs4);
        if (name)
        {
            glyphindex = FcFreeTypeGlyphNameIndex (face, name);
@@ -1751,17 +2214,22 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
                return glyphindex;
        }
     }
+#endif
     return 0;
 }
 
 static FcBool
-FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4, 
+FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4,
                      FT_UInt glyph, FcBlanks *blanks,
-                     FT_Pos *advance)
+                     FT_Pos *advance,
+                     FcBool using_strike)
 {
     FT_Int         load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
     FT_GlyphSlot    slot;
-    
+
+    if (using_strike)
+       load_flags &= ~FT_LOAD_NO_SCALE;
+
     /*
      * When using scalable fonts, only report those glyphs
      * which can be scaled; otherwise those fonts will
@@ -1771,14 +2239,14 @@ FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4,
      */
     if (face->face_flags & FT_FACE_FLAG_SCALABLE)
        load_flags |= FT_LOAD_NO_BITMAP;
-    
+
     if (FT_Load_Glyph (face, glyph, load_flags))
        return FcFalse;
-    
+
     slot = face->glyph;
     if (!glyph)
        return FcFalse;
-    
+
     *advance = slot->metrics.horiAdvance;
 
     switch (slot->format) {
@@ -1810,10 +2278,12 @@ FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4,
     return FcFalse;
 }
 
-FcCharSet *
-FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
+#define APPROXIMATELY_EQUAL(x,y) (FC_ABS ((x) - (y)) <= FC_MAX (FC_ABS (x), FC_ABS (y)) / 33)
+
+static FcCharSet *
+FcFreeTypeCharSetAndSpacingForSize (FT_Face face, FcBlanks *blanks, int *spacing, FT_Int strike_index)
 {
-    FcChar32       page, off, max, ucs4;
+    FcChar32       page, off, ucs4;
 #ifdef CHECK
     FcChar32       font_max = 0;
 #endif
@@ -1823,13 +2293,22 @@ 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;
+    FcBool         using_strike = FcFalse;
 
     fcs = FcCharSetCreate ();
     if (!fcs)
        goto bail0;
-    
+
+#if HAVE_FT_SELECT_SIZE
+    if (strike_index >= 0) {
+       if (FT_Select_Size (face, strike_index) != FT_Err_Ok)
+           goto bail1;
+       using_strike = FcTrue;
+    }
+#endif
+
 #ifdef CHECK
     printf ("Family %s style %s\n", face->family_name, face->style_name);
 #endif
@@ -1848,16 +2327,37 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
            {
                ucs4 = map->ent[i].bmp;
                glyph = FT_Get_Char_Index (face, map->ent[i].encode);
-               if (glyph && 
-                   FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance))
+               if (glyph &&
+                   FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance, using_strike))
                {
-                   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;
-                       all_advance = 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 (advance != all_advance)
-                       fixed_advance = FcFalse;
+
                    leaf = FcCharSetFindLeafCreate (fcs, ucs4);
                    if (!leaf)
                        goto bail1;
@@ -1871,59 +2371,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, using_strike))
                {
-                   glyph = FT_Get_Char_Index (face, ucs4);
-                   if (glyph && FcFreeTypeCheckGlyph (face, ucs4, 
-                                                      glyph, blanks, &advance))
+                   if (advance)
                    {
                        if (!has_advance)
                        {
                            has_advance = FcTrue;
-                           all_advance = advance;
+                           advance_one = advance;
                        }
-                       else if (advance != all_advance)
-                           fixed_advance = FcFalse;
-                       if (!leaf)
+                       else if (!APPROXIMATELY_EQUAL (advance, advance_one))
                        {
-                           leaf = FcCharSetFindLeafCreate (fcs, ucs4);
-                           if (!leaf)
-                               goto bail1;
+                           if (fixed_advance)
+                           {
+                               dual_advance = FcTrue;
+                               fixed_advance = FcFalse;
+                               advance_two = advance;
+                           }
+                           else if (!APPROXIMATELY_EQUAL (advance, advance_two))
+                               dual_advance = FcFalse;
                        }
-                       off = ucs4 & 0xff;
-                       leaf->map[off >> 5] |= (1 << (off & 0x1f));
+                   }
+
+                   if ((ucs4 >> 8) != page)
+                   {
+                       page = (ucs4 >> 8);
+                       leaf = FcCharSetFindLeafCreate (fcs, ucs4);
+                       if (!leaf)
+                           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++)
@@ -1940,28 +2429,41 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
 #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];
+       FcChar8 name_buf[FC_GLYPHNAME_BUFLEN + 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)
+           if (FT_Get_Glyph_Name (face, glyph, name_buf, FC_GLYPHNAME_BUFLEN+1) == 0)
            {
                ucs4 = FcGlyphNameToUcs4 (name_buf);
-               if (ucs4 != 0xffff && 
-                   FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance))
+               if (ucs4 != 0xffff &&
+                   FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance, using_strike))
                {
-                   if (!has_advance)
+                   if (advance)
                    {
-                       has_advance = FcTrue;
-                       all_advance = 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 (advance != all_advance)
-                       fixed_advance = FcFalse;
                    leaf = FcCharSetFindLeafCreate (fcs, ucs4);
                    if (!leaf)
                        goto bail1;
@@ -1974,6 +2476,7 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
            }
        }
     }
+#endif
 #ifdef CHECK
     printf ("%d glyphs %d encoded\n", (int) face->num_glyphs, FcCharSetCount (fcs));
     for (ucs4 = 0; ucs4 <= font_max; ucs4++)
@@ -1983,7 +2486,7 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
 
        if (has_char && !has_bit)
        {
-           if (!FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance))
+           if (!FcFreeTypeCheckGlyph (face, ucs4, glyph, blanks, &advance, using_strike))
                printf ("Bitmap missing broken char 0x%x\n", ucs4);
            else
                printf ("Bitmap missing char 0x%x\n", ucs4);
@@ -1994,6 +2497,8 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
 #endif
     if (fixed_advance)
        *spacing = FC_MONO;
+    else if (dual_advance && APPROXIMATELY_EQUAL (2 * FC_MIN (advance_one, advance_two), FC_MAX (advance_one, advance_two)))
+        *spacing = FC_DUAL;
     else
        *spacing = FC_PROPORTIONAL;
     return fcs;
@@ -2003,6 +2508,39 @@ bail0:
     return 0;
 }
 
+FcCharSet *
+FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
+{
+    FcCharSet  *cs;
+
+    cs = FcFreeTypeCharSetAndSpacingForSize (face, blanks, spacing, -1);
+    /*
+     * Check for bitmap-only ttf fonts that are missing the glyf table.
+     * In that case, pick a size and look for glyphs in that size instead
+     */
+    if (FcCharSetCount (cs) == 0)
+    {
+       /* Check for non-scalable TT fonts */
+       if (!(face->face_flags & FT_FACE_FLAG_SCALABLE) &&
+           face->num_fixed_sizes > 0 &&
+           FT_Get_Sfnt_Table (face, ft_sfnt_head))
+       {
+           FT_Int  strike_index = 0;
+           int     i;
+
+           /* Select the face closest to 16 pixels tall */
+           for (i = 1; i < face->num_fixed_sizes; i++) {
+               if (abs (face->available_sizes[i].height - 16) <
+                   abs (face->available_sizes[strike_index].height - 16))
+                   strike_index = i;
+           }
+           FcCharSetDestroy (cs);
+           cs = FcFreeTypeCharSetAndSpacingForSize (face, blanks, spacing, strike_index);
+       }
+    }
+    return cs;
+}
+
 FcCharSet *
 FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks)
 {
@@ -2010,3 +2548,198 @@ FcFreeTypeCharSet (FT_Face face, FcBlanks *blanks)
 
     return FcFreeTypeCharSetAndSpacing (face, blanks, &spacing);
 }
+
+
+#define TTAG_GPOS  FT_MAKE_TAG( 'G', 'P', 'O', 'S' )
+#define TTAG_GSUB  FT_MAKE_TAG( 'G', 'S', 'U', 'B' )
+#define TTAG_SILF  FT_MAKE_TAG( 'S', 'i', 'l', 'f')
+
+#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[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
+compareulong (const void *a, const void *b)
+{
+    const FT_ULong *ua = (const FT_ULong *) a;
+    const FT_ULong *ub = (const FT_ULong *) b;
+    return *ua - *ub;
+}
+
+
+static int
+GetScriptTags(FT_Face face, FT_ULong tabletag, FT_ULong **stags)
+{
+    FT_ULong   cur_offset, new_offset, base_offset;
+    FT_Stream  stream = face->stream;
+    FT_Error   error;
+    FT_UShort  n, p;
+    FT_Memory  memory;
+    int        script_count;
+
+    if (!stream)
+        return 0;
+
+    memory = stream->memory;
+
+    if (( error = ftglue_face_goto_table( face, tabletag, stream ) ))
+       return 0;
+
+    base_offset = ftglue_stream_pos ( stream );
+
+    /* skip version */
+
+    if ( ftglue_stream_seek ( stream, base_offset + 4L ) || ftglue_stream_frame_enter( stream, 2L ) )
+       return 0;
+
+    new_offset = GET_UShort() + base_offset;
+
+    ftglue_stream_frame_exit( stream );
+
+    cur_offset = ftglue_stream_pos( stream );
+
+    if ( ftglue_stream_seek( stream, new_offset ) != FT_Err_Ok )
+       return 0;
+
+    base_offset = ftglue_stream_pos( stream );
+
+    if ( ftglue_stream_frame_enter( stream, 2L ) )
+       return 0;
+
+    script_count = GET_UShort ();
+
+    ftglue_stream_frame_exit( stream );
+
+    *stags = malloc(script_count * sizeof (FT_ULong));
+    if (!stags)
+       return 0;
+
+    p = 0;
+    for ( n = 0; n < script_count; n++ )
+    {
+        if ( ftglue_stream_frame_enter( stream, 6L ) )
+           goto Fail;
+
+       (*stags)[p] = GET_ULong ();
+       new_offset = GET_UShort () + base_offset;
+
+        ftglue_stream_frame_exit( stream );
+
+       cur_offset = ftglue_stream_pos( stream );
+
+       error = ftglue_stream_seek( stream, new_offset );
+
+       if ( error == FT_Err_Ok )
+           p++;
+
+       (void)ftglue_stream_seek( stream, cur_offset );
+    }
+
+    if (!p)
+       goto Fail;
+
+    /* sort the tag list before returning it */
+    qsort(*stags, script_count, sizeof(FT_ULong), compareulong);
+
+    return script_count;
+
+Fail:
+    free(*stags);
+    *stags = NULL;
+    return 0;
+}
+
+static FcChar8 *
+FcFontCapabilities(FT_Face face)
+{
+    FcBool issilgraphitefont = 0;
+    FT_Error err;
+    FT_ULong len = 0;
+    FT_ULong *gsubtags=NULL, *gpostags=NULL;
+    FT_UShort gsub_count=0, gpos_count=0;
+    FT_ULong maxsize;
+    FcChar8 *complex_ = NULL;
+    int indx1 = 0, indx2 = 0;
+
+    err = FT_Load_Sfnt_Table(face, TTAG_SILF, 0, 0, &len);
+    issilgraphitefont = ( err == FT_Err_Ok);
+
+    gpos_count = GetScriptTags(face, TTAG_GPOS, &gpostags);
+    gsub_count = GetScriptTags(face, TTAG_GSUB, &gsubtags);
+
+    if (!issilgraphitefont && !gsub_count && !gpos_count)
+       goto bail;
+
+    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((char *) complex_, "ttable:Silf ");
+
+    while ((indx1 < gsub_count) || (indx2 < gpos_count)) {
+       if (indx1 == gsub_count) {
+           addtag(complex_, gpostags[indx2]);
+           indx2++;
+       } else if ((indx2 == gpos_count) || (gsubtags[indx1] < gpostags[indx2])) {
+           addtag(complex_, gsubtags[indx1]);
+           indx1++;
+       } else if (gsubtags[indx1] == gpostags[indx2]) {
+           addtag(complex_, gsubtags[indx1]);
+           indx1++;
+           indx2++;
+       } else {
+           addtag(complex_, gpostags[indx2]);
+           indx2++;
+       }
+    }
+    if (FcDebug () & FC_DBG_SCANV)
+       printf("complex_ features in this font: %s\n", complex_);
+bail:
+    free(gsubtags);
+    free(gpostags);
+    return complex_;
+}
+
+#define __fcfreetype__
+#include "fcaliastail.h"
+#include "fcftaliastail.h"
+#undef __fcfreetype__