Re: PangoXft and PangoFT2 patch from hell



On 16 Nov 2001, Owen Taylor wrote:

> I've read through the patch now, except for the PangoFT2 parts. 
> I assume that part is just doing the same thing as the PangoXft
> part, and I'm less familiar with the code to begin with.

Ok. Here is the next revision.
 
> * We shouldn't require LEX and YACC, for tarballs. So, we need to  
>   check the results of AM_PROG_LEX, AC_PROG_YACC and define  
>   some sort of @REBUILD_MINI_XFT@ based on this. (See handling 
>   of @REBUILD@ in GTK+)

I didn't do this yet. I'll do so, but maybe we should get the API in as 
soon as possible.

/ Alex

Index: configure.in
===================================================================
RCS file: /cvs/gnome/pango/configure.in,v
retrieving revision 1.82
diff -u -p -r1.82 configure.in
--- configure.in	2001/10/28 22:54:09	1.82
+++ configure.in	2001/11/18 01:40:27
@@ -15,7 +15,9 @@ AM_CONFIG_HEADER(config.h)
 AC_PROG_CC
 AC_LIBTOOL_WIN32_DLL
 AM_PROG_LIBTOOL
-
+AM_PROG_LEX
+AC_PROG_YACC
+	
 AC_MSG_CHECKING([for some Win32 platform])
 case "$host" in
   *-*-mingw*|*-*-cygwin*)
@@ -553,6 +555,7 @@ AC_OUTPUT([
 Makefile 
 pango/Makefile
 pango/mini-fribidi/Makefile
+pango/mini-xft/Makefile
 pango/opentype/Makefile
 pango/makefile.mingw
 pango/pango.rc
Index: modules/basic/basic-ft2.c
===================================================================
RCS file: /cvs/gnome/pango/modules/basic/basic-ft2.c,v
retrieving revision 1.11
diff -u -p -r1.11 basic-ft2.c
--- modules/basic/basic-ft2.c	2001/06/14 20:38:20	1.11
+++ modules/basic/basic-ft2.c	2001/11/18 01:40:30
@@ -119,21 +119,13 @@ static PangoGlyph 
 find_char (PangoFont *font,
 	   gunichar   wc)
 {
-  int i;
-  int n_subfonts;
-
-  n_subfonts = pango_ft2_n_subfonts (font);
+  FT_Face face;
+  FT_UInt index;
 
-  for (i = 0; i < n_subfonts; i++)
-    {
-      FT_Face face;
-      FT_UInt index;
-
-      face = pango_ft2_get_face (font, i+1);
-      index = FT_Get_Char_Index (face, wc);
-      if (index && index <= face->num_glyphs)
-	return PANGO_FT2_MAKE_GLYPH (i+1, index);
-    }
+  face = pango_ft2_font_get_face (font);
+  index = FT_Get_Char_Index (face, wc);
+  if (index && index <= face->num_glyphs)
+    return index;
 
   return 0;
 }
@@ -285,19 +277,7 @@ static PangoCoverage *
 basic_engine_get_coverage (PangoFont  *font,
 			   PangoLanguage *lang)
 {
-  PangoCoverage *result;
-#if 0
-  gunichar wc;
-  
-  result = pango_coverage_new ();
-  
-  for (wc = 0; wc < 65536; wc++)
-    if (find_char (font, wc))
-      pango_coverage_set (result, wc, PANGO_COVERAGE_EXACT);
-#else
-  result = pango_ft2_get_coverage (font, lang);
-#endif
-  return result;
+  return pango_ft2_font_get_coverage (font, lang);
 }
 
 static PangoEngine *
@@ -346,3 +326,4 @@ void 
 MODULE_ENTRY(script_engine_unload) (PangoEngine *engine)
 {
 }
+
Index: pango/Makefile.am
===================================================================
RCS file: /cvs/gnome/pango/pango/Makefile.am,v
retrieving revision 1.59
diff -u -p -r1.59 Makefile.am
--- pango/Makefile.am	2001/10/28 22:54:14	1.59
+++ pango/Makefile.am	2001/11/18 01:40:30
@@ -6,6 +6,9 @@ GPATH = $(srcdir)
 
 if HAVE_FREETYPE
 OPENTYPE_SUBDIR=opentype
+XFT_SUBDIR = mini-xft
+else
+XFT_SUBDIR = 
 endif
 
 if HAVE_FRIBIDI
@@ -13,9 +16,9 @@ else
 FRIBIDI_SUBDIR = mini-fribidi
 endif
 
-SUBDIRS = $(OPENTYPE_SUBDIR) $(FRIBIDI_SUBDIR)
+SUBDIRS = $(OPENTYPE_SUBDIR) $(FRIBIDI_SUBDIR) $(XFT_SUBDIR)
 
-DIST_SUBDIRS = mini-fribidi opentype
+DIST_SUBDIRS = mini-fribidi mini-xft opentype
 
 INCLUDES = 					\
 	-DPANGO_ENABLE_BACKEND			\
@@ -183,11 +186,10 @@ libpangoft2_la_SOURCES =   	\
 	pangoft2.h		\
 	pangoft2.c		\
 	pangoft2-private.h	\
-	pangoft2-fontcache.c	\
 	pangoft2-fontmap.c	\
 	module-defs-ft2.c
 
-libpangoft2_la_LIBADD = $(INCLUDED_FT2_MODULES) $(FREETYPE_LIBS) libpango.la
+libpangoft2_la_LIBADD = $(INCLUDED_FT2_MODULES) $(FREETYPE_LIBS) mini-xft/libmini-xft.la libpango.la
 libpangoft2_la_LDFLAGS = -release $(VERSION) $(GLIB_LIBS) $(no_undefined) $(pangoft2_export_symbols)
 libpangoft2_la_DEPENDENCIES = $(INCLUDED_FT2_MODULES) libpango.la
 
Index: pango/fonts.c
===================================================================
RCS file: /cvs/gnome/pango/pango/fonts.c,v
retrieving revision 1.40
diff -u -p -r1.40 fonts.c
--- pango/fonts.c	2001/11/11 23:36:26	1.40
+++ pango/fonts.c	2001/11/18 01:40:31
@@ -1405,3 +1405,352 @@ pango_font_face_get_face_name (PangoFont
 
   return PANGO_FONT_FACE_GET_CLASS (face)->get_face_name (face);
 }
+
+/*
+ * PangoFontset
+ */
+
+static void  pango_fontset_class_init (PangoFontsetClass    *class);
+static PangoFontMetrics *pango_fontset_real_get_metrics (PangoFontset  *fontset,
+							 PangoLanguage *language);
+
+GType
+pango_fontset_get_type (void)
+{
+  static GType object_type = 0;
+
+  if (!object_type)
+    {
+      static const GTypeInfo object_info =
+      {
+        sizeof (PangoFontsetClass),
+        (GBaseInitFunc) NULL,
+        (GBaseFinalizeFunc) NULL,
+        (GClassInitFunc) pango_fontset_class_init,
+        NULL,           /* class_finalize */
+        NULL,           /* class_data */
+        sizeof (PangoFontset),
+        0,              /* n_preallocs */
+	NULL            /* init */
+      };
+      
+      object_type = g_type_register_static (G_TYPE_OBJECT,
+                                            "PangoFontset",
+                                            &object_info, 0);
+    }
+  
+  return object_type;
+}
+
+static void
+pango_fontset_class_init (PangoFontsetClass *class)
+{
+  class->get_metrics = pango_fontset_real_get_metrics;
+}
+
+/**
+ * pango_fontset_get_font:
+ * @fontset: a #PangoFontset
+ * @wc: a unicode character
+ * @language: language tag used to determine which script to get the font
+ *            for, or %NULL to indicate to get the the entire font.
+ *
+ * Returns the font in the fontset that contains the best glyph for the
+ * unicode character wc.
+ *
+ * Returns: a #PangoFont. The caller must call g_object_unref when finished
+ *          with the font.
+ **/
+PangoFont *
+pango_fontset_get_font (PangoFontset  *fontset,
+			guint          wc,
+			PangoLanguage *language)
+{
+  g_return_val_if_fail (fontset != NULL, NULL);
+
+  return PANGO_FONTSET_GET_CLASS (fontset)->get_font (fontset, wc, language);
+}
+
+/**
+ * pango_fontset_get_metrics:
+ * @fontset: a #PangoFontset
+ * @desc: a #PangoFontDescription structure
+ * @language: language tag used to determine which script to get the metrics
+ *            for, or %NULL to indicate to get the metrics for the entire
+ *            font.
+ * 
+ * Get overall metric information for the fonts in the fontset.
+ * Since the metrics may be substantially different for
+ * different scripts, a language tag can be provided to indicate that
+ * the metrics should be retrieved that correspond to the script(s)
+ * used by that language.
+ *
+ * Returns: a #PangoMetrics object. The caller must call pango_font_metrics_unref()
+ *   when finished using the object.
+ **/
+PangoFontMetrics *
+pango_fontset_get_metrics (PangoFontset  *fontset,
+			   PangoLanguage *language)
+{
+  g_return_val_if_fail (fontset != NULL, NULL);
+
+  return PANGO_FONTSET_GET_CLASS (fontset)->get_metrics (fontset, language);
+}
+
+
+static PangoFontMetrics *
+pango_fontset_real_get_metrics (PangoFontset  *fontset,
+				PangoLanguage *language)
+{
+  PangoFontMetrics *metrics, *raw_metrics;
+  const char *sample_str;
+  const char *p;
+  int count;
+  GHashTable *fonts_seen;
+  PangoFont *font;
+   
+  sample_str = pango_language_get_sample_string (language);
+
+  count = 0;
+  metrics = pango_font_metrics_new ();
+  fonts_seen = g_hash_table_new_full (NULL, NULL, g_object_unref, NULL);
+
+  p = sample_str;
+  while (*p)
+    {
+      gunichar wc = g_utf8_get_char (p);
+      font = pango_fontset_get_font (fontset, wc, language);
+      if (font)
+	{
+	  if (g_hash_table_lookup (fonts_seen, font) == NULL)
+	    {
+	      raw_metrics = pango_font_get_metrics (font, language);
+	      g_hash_table_insert (fonts_seen, font, font);
+	  
+	      if (count == 0)
+		{
+		  *metrics = *raw_metrics;
+		  metrics->approximate_char_width = raw_metrics->approximate_char_width;
+		  metrics->approximate_digit_width = raw_metrics->approximate_digit_width;
+		}
+	      else
+		{
+		  metrics->ascent = MAX (metrics->ascent, raw_metrics->ascent);
+		  metrics->descent = MAX (metrics->descent, raw_metrics->descent);
+		  metrics->approximate_char_width += raw_metrics->approximate_char_width;
+		  metrics->approximate_digit_width += raw_metrics->approximate_digit_width;
+		}
+	      count++;
+	    }
+	  else
+	    g_object_unref (font);
+	}
+	  
+      p = g_utf8_next_char (p);
+    }
+
+  g_hash_table_destroy (fonts_seen);
+  
+  metrics->approximate_char_width /= count;
+  metrics->approximate_digit_width /= count;
+
+  return metrics;
+}
+
+
+/*
+ * PangoFontsetSimple
+ */
+
+#define PANGO_FONTSET_SIMPLE_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FONTSET_SIMPLE, PangoFontsetSimpleClass))
+#define PANGO_IS_FONTSET_SIMPLE_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FONTSET_SIMPLE))
+#define PANGO_FONTSET_SIMPLE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FONTSET_SIMPLE, PangoFontsetSimpleClass))
+
+static void              pango_fontset_simple_class_init  (PangoFontsetSimpleClass *class);
+static void              pango_fontset_simple_finalize    (GObject                 *object);
+static void              pango_fontset_simple_init        (PangoFontsetSimple      *fontset);
+static PangoFontMetrics *pango_fontset_simple_get_metrics (PangoFontset            *fontset,
+							   PangoLanguage           *language);
+static  PangoFont *      pango_fontset_simple_get_font    (PangoFontset            *fontset,
+							   guint                    wc,
+							   PangoLanguage           *language);
+
+
+
+struct _PangoFontsetSimple
+{
+  PangoFontset parent_instance;
+
+  GPtrArray *fonts;
+  GPtrArray *coverages;
+  PangoLanguage *language;
+};
+
+struct _PangoFontsetSimpleClass
+{
+  PangoFontsetClass parent_class;
+};
+
+static PangoFontsetClass *simple_parent_class;	/* Parent class structure for PangoFontsetSimple */
+
+PangoFontsetSimple *
+pango_fontset_simple_new (void)
+{
+  return g_object_new (PANGO_TYPE_FONTSET_SIMPLE, NULL);
+}
+
+GType
+pango_fontset_simple_get_type (void)
+{
+  static GType object_type = 0;
+
+  if (!object_type)
+    {
+      static const GTypeInfo object_info =
+      {
+        sizeof (PangoFontsetSimpleClass),
+        (GBaseInitFunc) NULL,
+        (GBaseFinalizeFunc) NULL,
+        (GClassInitFunc) pango_fontset_simple_class_init,
+        NULL,           /* class_finalize */
+        NULL,           /* class_data */
+        sizeof (PangoFontsetSimple),
+        0,              /* n_preallocs */
+        (GInstanceInitFunc) pango_fontset_simple_init,
+      };
+      
+      object_type = g_type_register_static (PANGO_TYPE_FONTSET,
+                                            "PangoFontsetSimple",
+                                            &object_info, 0);
+    }
+  
+  return object_type;
+}
+
+static void
+pango_fontset_simple_class_init (PangoFontsetSimpleClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  PangoFontsetClass *fontset_class = PANGO_FONTSET_CLASS (class);
+
+  simple_parent_class = g_type_class_peek_parent (class);
+  
+  object_class->finalize = pango_fontset_simple_finalize;
+  fontset_class->get_font = pango_fontset_simple_get_font;
+  fontset_class->get_metrics = pango_fontset_simple_get_metrics;
+}
+
+static void 
+pango_fontset_simple_init (PangoFontsetSimple *fontset)
+{
+  fontset->fonts = g_ptr_array_new ();
+  fontset->coverages = g_ptr_array_new ();
+  fontset->language = NULL;
+}
+
+static void
+pango_fontset_simple_finalize (GObject *object)
+{
+  PangoFontsetSimple *fontset = PANGO_FONTSET_SIMPLE (object);
+  PangoCoverage *coverage;
+  int i;
+
+  for (i = 0; i < fontset->fonts->len; i++)
+    g_object_unref (g_ptr_array_index(fontset->fonts, i));
+
+  g_ptr_array_free (fontset->fonts, TRUE);
+
+  for (i = 0; i < fontset->coverages->len; i++)
+    {
+      coverage = g_ptr_array_index (fontset->coverages, i);
+      if (coverage)
+	pango_coverage_unref (coverage);
+    }
+  
+  g_ptr_array_free (fontset->coverages, TRUE);
+
+  G_OBJECT_CLASS (simple_parent_class)->finalize (object);
+}
+
+void
+pango_fontset_simple_append (PangoFontsetSimple *fontset,
+			     PangoFont          *font)
+{
+  g_ptr_array_add (fontset->fonts, font);
+  g_ptr_array_add (fontset->coverages, NULL);
+}
+
+int
+pango_fontset_simple_size (PangoFontsetSimple *fontset)
+{
+  return fontset->fonts->len;
+}
+
+static PangoFontMetrics *
+pango_fontset_simple_get_metrics (PangoFontset  *fontset,
+				  PangoLanguage *language)
+{
+  PangoFontsetSimple *simple = PANGO_FONTSET_SIMPLE (fontset);
+  
+  if (simple->fonts->len == 1)
+    return pango_font_get_metrics (PANGO_FONT (g_ptr_array_index(simple->fonts, 0)),
+				   language);
+  
+  return PANGO_FONTSET_CLASS (simple_parent_class)->get_metrics (fontset, language);
+}
+
+static PangoFont *
+pango_fontset_simple_get_font (PangoFontset  *fontset,
+			       guint          wc,
+			       PangoLanguage *language)
+{
+  PangoFontsetSimple *simple = PANGO_FONTSET_SIMPLE (fontset);
+  PangoCoverageLevel best_level = PANGO_COVERAGE_NONE;
+  PangoCoverageLevel level;
+  PangoFont *font;
+  PangoCoverage *coverage;
+  int result = -1;
+  int i;
+  
+  /* Only cache coverages from one language, this assumes
+   * that apps normally only use one language at a time. */
+  if (simple->language != language)
+    {
+      for (i = 0; i < simple->coverages->len; i++)
+	{
+	  coverage = g_ptr_array_index (simple->coverages, i);
+	  
+	  if (coverage)
+	    pango_coverage_unref (coverage);
+	  
+	  g_ptr_array_index (simple->coverages, i) = NULL;
+	}
+      simple->language = language;
+    }
+  
+  for (i = 0; i < simple->fonts->len; i++)
+    {
+      coverage = g_ptr_array_index (simple->coverages, i);
+      
+      if (coverage == NULL)
+	{
+	  font = g_ptr_array_index (simple->fonts, i);
+	  
+	  coverage = pango_font_get_coverage (font, language);
+	  g_ptr_array_index (simple->coverages, i) = coverage;
+	}
+      
+      level = pango_coverage_get (coverage, wc);
+      
+      if (result == -1 || level > best_level)
+	{
+	  result = i;
+	  best_level = level;
+	  if (level == PANGO_COVERAGE_EXACT)
+	    break;
+	}
+    }
+
+  font = g_ptr_array_index(simple->fonts, result);
+  return g_object_ref (font);
+}
Index: pango/pango-context.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-context.c,v
retrieving revision 1.42
diff -u -p -r1.42 pango-context.c
--- pango/pango-context.c	2001/09/19 23:44:50	1.42
+++ pango/pango-context.c	2001/11/18 01:40:32
@@ -35,7 +35,7 @@ struct _PangoContext
   PangoDirection base_dir;
   PangoFontDescription *font_desc;
 
-  GSList *font_maps;
+  PangoFontMap *font_map;
 };
 
 struct _PangoContextClass
@@ -92,7 +92,7 @@ pango_context_init (PangoContext *contex
 {
   context->base_dir = PANGO_DIRECTION_LTR;
   context->language = NULL;
-  context->font_maps = NULL;
+  context->font_map = NULL;
 
   context->font_desc = pango_font_description_new ();
   pango_font_description_set_family (context->font_desc, "serif");
@@ -120,8 +120,8 @@ pango_context_finalize (GObject *object)
 
   context = PANGO_CONTEXT (object);
 
-  g_slist_foreach (context->font_maps, (GFunc)g_object_unref, NULL);
-  g_slist_free (context->font_maps);
+  if (context->font_map)
+    g_object_unref (G_OBJECT(context->font_map));
 
   pango_font_description_free (context->font_desc);
   
@@ -147,39 +147,24 @@ pango_context_new (void)
 }
 
 /**
- * pango_context_add_font_map:
+ * pango_context_set_font_map:
  * @context: a #PangoContext
- * @font_map: the #PangoFontMap to add.
+ * @font_map: the #PangoFontMap to set.
  * 
- * Add a font map to the list of font maps that are searched for fonts
- * when fonts are looked-up in this context.
+ * Sets the font map to be searched when fonts are looked-up in this context.
  **/
 void
-pango_context_add_font_map (PangoContext *context,
+pango_context_set_font_map (PangoContext *context,
 			    PangoFontMap *font_map)
 {
   g_return_if_fail (context != NULL);
   g_return_if_fail (font_map != NULL);
-  
-  g_object_ref (G_OBJECT (font_map));
-  context->font_maps =  g_slist_append (context->font_maps, font_map);
-}
 
-typedef struct
-{
-  int n_found;
-  PangoFontFamily **families;
-} ListFamiliesInfo;
+  if (context->font_map)
+    g_object_unref (G_OBJECT (context->font_map));
 
-static void
-list_families_foreach (gpointer key, gpointer value, gpointer user_data)
-{
-  ListFamiliesInfo *info = user_data;
-
-  if (info->families)
-    info->families[info->n_found++] = value;
-
-  g_free (value);
+  g_object_ref (G_OBJECT (font_map));
+  context->font_map = font_map;
 }
 
 /**
@@ -196,17 +181,13 @@ pango_context_list_families (PangoContex
 			     PangoFontFamily     ***families,
 			     int                   *n_families)
 {
-  int n_maps;
-  
   g_return_if_fail (context != NULL);
   g_return_if_fail (families == NULL || n_families != NULL);
 
   if (n_families == NULL)
     return;
-  
-  n_maps = g_slist_length (context->font_maps);
   
-  if (n_maps == 0)
+  if (context->font_map == NULL)
     {
       *n_families = 0;
       if (families)
@@ -214,57 +195,8 @@ pango_context_list_families (PangoContex
       
       return;
     }
-  else if (n_maps == 1)
-
-    pango_font_map_list_families (context->font_maps->data, families, n_families);
-  else
-    {
-      GHashTable *family_hash;
-      GSList *tmp_list;
-      ListFamiliesInfo info;
-
-      *n_families = 0;
-
-      family_hash = g_hash_table_new (g_str_hash, g_str_equal);
-
-      tmp_list = context->font_maps;
-      while (tmp_list)
-	{
-	  PangoFontFamily **tmp_families;
-	  int tmp_n_families;
-	  int i;
-	  
-	  pango_font_map_list_families (tmp_list->data, &tmp_families, &tmp_n_families);
-
-	  for (i=0; i<*n_families; i++)
-	    {
-	      const char *family = pango_font_family_get_name (tmp_families[i]);
-		  
-	      if (!g_hash_table_lookup (family_hash, tmp_families[i]))
-		{
-		  g_hash_table_insert (family_hash, (char *)family, tmp_families[i]);
-		  (*n_families)++;
-		}
-	    }
-	  
-	  g_free (tmp_families);
-
-	  tmp_list = tmp_list->next;
-	}
-
-      info.n_found = 0;
-
-      if (families)
-	{
-	  *families = g_new (PangoFontFamily *, *n_families);
-	  info.families = *families;
-	}
-      else
-	info.families = NULL;
-	  
-      g_hash_table_foreach (family_hash, list_families_foreach, &info);
-      g_hash_table_destroy (family_hash);
-    }
+  else 
+    pango_font_map_list_families (context->font_map, families, n_families);
 }
 
 /**
@@ -281,23 +213,9 @@ PangoFont *
 pango_context_load_font (PangoContext               *context,
 			 const PangoFontDescription *desc)
 {
-  GSList *tmp_list;
-
   g_return_val_if_fail (context != NULL, NULL);
-
-  tmp_list = context->font_maps;
-  while (tmp_list)
-    {
-      PangoFont *font;
-      
-      font = pango_font_map_load_font (tmp_list->data, desc);
-      if (font)
-	return font;
-      
-      tmp_list = tmp_list->next;
-    }
 
-  return NULL;
+  return  pango_font_map_load_font (context->font_map, desc);
 }
 
 /**
@@ -610,152 +528,6 @@ static PangoEngineShape fallback_shaper 
   fallback_engine_get_coverage
 };
 
-/* FIXME: Remove this artificial limit */
-#define MAX_FAMILIES 16
-
-typedef struct _FontSet FontSet;
-
-struct _FontSet
-{
-  int n_families;
-  PangoFont *fonts[MAX_FAMILIES];
-  PangoCoverage *coverages[MAX_FAMILIES];  
-};
-
-#define FONT_SET_INITIALIZER { 0, }
-
-static gint
-font_set_get_font (FontSet  *font_set,
-		   gunichar  wc)
-{
-  PangoCoverageLevel best_level = PANGO_COVERAGE_NONE;
-
-  int result = -1;
-  int i;
-  
-  for (i=0; i < font_set->n_families; i++)
-    {
-      if (font_set->fonts[i])
-	{
-	  PangoCoverageLevel level = pango_coverage_get (font_set->coverages[i], wc);
-	  
-	  if (result == -1 || level > best_level)
-	    {
-	      result = i;
-	      best_level = level;
-	    }
-	}
-    }
-
-  return result;
-}
-
-static void
-font_set_free (FontSet *font_set)
-{
-  int j;
-  
-  for (j=0; j < font_set->n_families; j++)
-    {
-      if (font_set->fonts[j])
-	{
-	  g_object_unref (font_set->fonts[j]);
-	  pango_coverage_unref (font_set->coverages[j]);
-	}
-    }
-
-  font_set->n_families = 0;
-}
-
-static void
-font_set_load (FontSet                    *font_set,
-	       PangoContext               *context,
-	       PangoLanguage              *language,
-	       const PangoFontDescription *desc)
-{
-  PangoFontDescription *tmp_desc = pango_font_description_copy_static (desc);
-  char **families;
-  int j;
-
-  font_set_free (font_set);
-
-  families = g_strsplit (pango_font_description_get_family (desc), ",", -1);
-
-  font_set->n_families = 0;
-  for (j=0; families[j] && font_set->n_families < MAX_FAMILIES; j++)
-    {
-      pango_font_description_set_family_static (tmp_desc, families[j]);
-      font_set->fonts[font_set->n_families] = pango_context_load_font (context, tmp_desc);
-      
-      if (font_set->fonts[font_set->n_families])
-	{
-	  font_set->coverages[font_set->n_families] = pango_font_get_coverage (font_set->fonts[font_set->n_families], language);
-	  (font_set->n_families)++;
-	}
-    }
-  
-  g_strfreev (families);
-  pango_font_description_set_family_static (tmp_desc, pango_font_description_get_family (desc));
-
-  /* The font description was completely unloadable, try with
-   * family == "Sans"
-   */
-  if (font_set->n_families == 0)
-    {
-      char *ctmp1, *ctmp2;
-      
-      ctmp1 = pango_font_description_to_string (desc);
-      pango_font_description_set_family_static (tmp_desc, "Sans");
-      ctmp2 = pango_font_description_to_string (tmp_desc);
-      
-      g_warning ("Couldn't load font \"%s\" falling back to \"%s\"", ctmp1, ctmp2);
-      g_free (ctmp1);
-      g_free (ctmp2);
-      
-      font_set->fonts[0] = pango_context_load_font (context, tmp_desc);
-      if (font_set->fonts[0])
-	{
-	  font_set->coverages[0] = pango_font_get_coverage (font_set->fonts[0], language);
-	  font_set->n_families = 1;
-	}
-    }
-  
-  /* We couldn't try with Sans and the specified style. Try Sans Normal
-   */
-  if (font_set->n_families == 0)
-    {
-      char *ctmp1, *ctmp2;
-      
-      ctmp1 = pango_font_description_to_string (tmp_desc);
-      pango_font_description_set_style (tmp_desc, PANGO_STYLE_NORMAL);
-      pango_font_description_set_weight (tmp_desc, PANGO_WEIGHT_NORMAL);
-      pango_font_description_set_variant (tmp_desc, PANGO_VARIANT_NORMAL);
-      pango_font_description_set_stretch (tmp_desc, PANGO_STRETCH_NORMAL);
-      ctmp2 = pango_font_description_to_string (tmp_desc);
-      
-      g_warning ("Couldn't load font \"%s\" falling back to \"%s\"", ctmp1, ctmp2);
-      g_free (ctmp1);
-      g_free (ctmp2);
-      
-      font_set->fonts[0] = pango_context_load_font (context, tmp_desc);
-      if (font_set->fonts[0])
-	{
-	  font_set->coverages[0] = pango_font_get_coverage (font_set->fonts[0], language);
-	  font_set->n_families = 1;
-	}
-    }
-
-  /* Everything failed, we are screwed, there is no way to continue
-   */
-  if (font_set->n_families == 0)
-    {
-      g_warning ("All font failbacks failed!!!!");
-      exit (1);
-    }
-
-  pango_font_description_free (tmp_desc);
-}
-
 static gboolean
 advance_iterator_to (PangoAttrIterator *iterator,
                      int                start_index)
@@ -794,12 +566,11 @@ add_engines (PangoContext      *context,
   GSList *extra_attrs = NULL;
   PangoMap *lang_map = NULL;
   PangoFontDescription *current_desc = NULL;
-  FontSet current_fonts = FONT_SET_INITIALIZER;
+  PangoFontset *current_fonts = NULL;
   PangoAttrIterator *iterator;
   gboolean first_iteration = TRUE;
   gunichar wc;
   int i = 0;
-  int font_index;
 
   if (cached_iter)
     iterator = cached_iter;
@@ -858,7 +629,11 @@ add_engines (PangoContext      *context,
 	      pango_font_description_free (current_desc);
 	      current_desc = next_desc;
 
-	      font_set_load (&current_fonts, context, language, current_desc);
+	      if (current_fonts)
+		g_object_unref (current_fonts);
+	      
+	      current_fonts = pango_font_map_load_fontset (context->font_map,
+							   current_desc);
 	    }
 	  else
 	    pango_font_description_free (next_desc);
@@ -868,14 +643,7 @@ add_engines (PangoContext      *context,
       pos = g_utf8_next_char (pos);
       
       analysis->lang_engine = (PangoEngineLang *)pango_map_get_engine (lang_map, wc);
-      font_index = font_set_get_font (&current_fonts, wc);
-      if (font_index != -1)
-	{
-	  analysis->font = current_fonts.fonts[font_index];
-	  g_object_ref (analysis->font);
-	}
-      else
-	analysis->font = NULL;
+      analysis->font = pango_fontset_get_font (current_fonts, wc, language);
       analysis->language = language;
       
       /* FIXME: handle reference counting properly on the shapers */
@@ -894,7 +662,8 @@ add_engines (PangoContext      *context,
 
   if (current_desc)
     pango_font_description_free (current_desc);
-  font_set_free (&current_fonts);
+  if (current_fonts)
+    g_object_unref (current_fonts);
 
   if (iterator != cached_iter)
     pango_attr_iterator_destroy (iterator);
@@ -929,62 +698,17 @@ pango_context_get_metrics (PangoContext 
 			   const PangoFontDescription   *desc,
 			   PangoLanguage                *language)
 {
-  FontSet current_fonts = FONT_SET_INITIALIZER;
-  PangoFontMetrics *raw_metrics[MAX_FAMILIES];
+  PangoFontset *current_fonts = NULL;
   PangoFontMetrics *metrics;
-  const char *sample_str;
-  const char *p;
-  int i;
 
   g_return_val_if_fail (PANGO_IS_CONTEXT (context), NULL);
   g_return_val_if_fail (desc != NULL, NULL);
 
-  sample_str = pango_language_get_sample_string (language);
+  current_fonts = pango_font_map_load_fontset (context->font_map, desc);
 
-  font_set_load (&current_fonts, context, language, desc);
-
-  if (current_fonts.n_families == 1)
-    metrics = pango_font_get_metrics (current_fonts.fonts[0], language);
-  else
-    {
-      int count = 0;
-
-      metrics = pango_font_metrics_new ();
-
-      for (i=0; i < MAX_FAMILIES; i++)
-	raw_metrics[i] = NULL;
+  metrics = pango_fontset_get_metrics (current_fonts, language);
   
-      p = sample_str;
-      while (*p)
-	{
-	  gunichar wc = g_utf8_get_char (p);
-	  int index = font_set_get_font (&current_fonts, wc);
-	  if (!raw_metrics[index])
-	    raw_metrics[index] = pango_font_get_metrics (current_fonts.fonts[index], language);
-
-	  if (count == 0)
-	    *metrics = *raw_metrics[index];
-	  else
-	    {
-	      metrics->ascent = MAX (metrics->ascent, raw_metrics[index]->ascent);
-	      metrics->descent = MAX (metrics->descent, raw_metrics[index]->descent);
-	      metrics->approximate_char_width += raw_metrics[index]->approximate_char_width;
-	      metrics->approximate_digit_width += raw_metrics[index]->approximate_digit_width;
-	    }
-	  
-	  p = g_utf8_next_char (p);
-	  count++;
-	}
-
-      for (i=0; i < MAX_FAMILIES; i++)
-	if (raw_metrics[i])
-	  pango_font_metrics_unref (raw_metrics[i]);
-
-      metrics->approximate_char_width /= count;
-      metrics->approximate_digit_width /= count;
-    }
-      
-  font_set_free (&current_fonts);
+  g_object_unref (current_fonts);
 
   return metrics;
 }
Index: pango/pango-context.h
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-context.h,v
retrieving revision 1.14
diff -u -p -r1.14 pango-context.h
--- pango/pango-context.h	2001/09/18 20:05:17	1.14
+++ pango/pango-context.h	2001/11/18 01:40:32
@@ -50,7 +50,7 @@ GType         pango_context_get_type    
 
 #ifdef PANGO_ENABLE_BACKEND
 PangoContext *pango_context_new           (void);
-void          pango_context_add_font_map  (PangoContext                 *context,
+void          pango_context_set_font_map  (PangoContext                 *context,
 					   PangoFontMap                 *font_map);
 #endif /* PANGO_ENABLE_BACKEND */
 
Index: pango/pango-font.h
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-font.h,v
retrieving revision 1.24
diff -u -p -r1.24 pango-font.h
--- pango/pango-font.h	2001/09/20 12:01:52	1.24
+++ pango/pango-font.h	2001/11/18 01:40:33
@@ -309,6 +309,70 @@ struct _PangoFontClass
 					       PangoLanguage  *language);
 };
 
+
+#endif /* PANGO_ENABLE_BACKEND */
+
+/*
+ * PangoFontset
+ */
+
+#define PANGO_TYPE_FONTSET              (pango_fontset_get_type ())
+#define PANGO_FONTSET(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FONTSET, PangoFontset))
+#define PANGO_IS_FONTSET(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FONTSET))
+
+GType pango_fontset_get_type (void) G_GNUC_CONST;
+
+typedef struct _PangoFontset        PangoFontset;
+
+PangoFont *       pango_fontset_get_font    (PangoFontset  *fontset,
+					     guint          wc,
+					     PangoLanguage *language);
+PangoFontMetrics *pango_fontset_get_metrics (PangoFontset  *fontset,
+					     PangoLanguage *language);
+
+#ifdef PANGO_ENABLE_BACKEND
+
+typedef struct _PangoFontsetClass   PangoFontsetClass;
+
+#define PANGO_FONTSET_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FONTSET, PangoFontsetClass))
+#define PANGO_IS_FONTSET_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FONTSET))
+#define PANGO_FONTSET_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FONTSET, PangoFontsetClass))
+
+struct _PangoFontset
+{
+  GObject parent_instance;
+};
+
+struct _PangoFontsetClass
+{
+  GObjectClass parent_class;
+
+  PangoFont *       (*get_font)    (PangoFontset  *fontset,
+				    guint          wc,
+				    PangoLanguage *language);
+
+  PangoFontMetrics *(*get_metrics) (PangoFontset  *fontset,
+				    PangoLanguage *language);
+};
+
+/*
+ * PangoFontsetSimple
+ */
+
+#define PANGO_TYPE_FONTSET_SIMPLE       (pango_fontset_simple_get_type ())
+#define PANGO_FONTSET_SIMPLE(object)    (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FONTSET_SIMPLE, PangoFontsetSimple))
+#define PANGO_IS_FONTSET_SIMPLE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FONTSET_SIMPLE))
+
+typedef struct _PangoFontsetSimple  PangoFontsetSimple;
+typedef struct _PangoFontsetSimpleClass  PangoFontsetSimpleClass;
+
+GType pango_fontset_simple_get_type (void) G_GNUC_CONST;
+
+PangoFontsetSimple * pango_fontset_simple_new    (void);
+void                 pango_fontset_simple_append (PangoFontsetSimple *fontset,
+						  PangoFont          *font);
+int                  pango_fontset_simple_size   (PangoFontsetSimple *fontset);
+
 #endif /* PANGO_ENABLE_BACKEND */
 
 G_END_DECLS
Index: pango/pango-fontmap.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-fontmap.c,v
retrieving revision 1.7
diff -u -p -r1.7 pango-fontmap.c
--- pango/pango-fontmap.c	2001/10/27 20:34:17	1.7
+++ pango/pango-fontmap.c	2001/11/18 01:40:33
@@ -20,7 +20,14 @@
  */
 
 #include "pango-fontmap.h"
+#include "pango-utils.h"
+#include <stdlib.h>
 
+static void          pango_font_map_class_init        (PangoFontMapClass          *class);
+static PangoFontset *pango_font_map_real_load_fontset (PangoFontMap               *fontmap,
+						       const PangoFontDescription *desc);
+
+
 GType
 pango_font_map_get_type (void)
 {
@@ -33,7 +40,7 @@ pango_font_map_get_type (void)
         sizeof (PangoFontMapClass),
         (GBaseInitFunc) NULL,
         (GBaseFinalizeFunc) NULL,
-        NULL,           /* class_init */
+        (GClassInitFunc) pango_font_map_class_init,
         NULL,           /* class_finalize */
         NULL,           /* class_data */
         sizeof (PangoFontMap),
@@ -49,6 +56,13 @@ pango_font_map_get_type (void)
   return object_type;
 }
 
+
+static void
+pango_font_map_class_init (PangoFontMapClass *class)
+{
+  class->load_fontset = pango_font_map_real_load_fontset;
+}
+
 /**
  * pango_font_map_load_font:
  * @fontmap: a #PangoFontMap
@@ -84,4 +98,136 @@ pango_font_map_list_families (PangoFontM
   g_return_if_fail (fontmap != NULL);
 
   PANGO_FONT_MAP_GET_CLASS (fontmap)->list_families (fontmap, families, n_families);
+}
+
+/**
+ * pango_font_map_load_fontset:
+ * @fontmap: a #PangoFontMap
+ * @desc: a #PangoFontDescription describing the font to load
+ * 
+ * Load a set of fonts in the fontmap that can be used to render
+ * a font matching @desc.
+ *
+ * Returns the fontset, or %NULL if no font matched.
+ **/
+PangoFontset *
+pango_font_map_load_fontset (PangoFontMap                 *fontmap,
+			     const PangoFontDescription   *desc)
+{
+  g_return_val_if_fail (fontmap != NULL, 0);
+
+  return PANGO_FONT_MAP_GET_CLASS (fontmap)->load_fontset (fontmap, desc);
+}
+
+static void
+pango_font_map_fontset_add_fonts (PangoFontMap          *fontmap,
+				  PangoFontsetSimple    *fonts,
+				  PangoFontDescription  *desc,
+				  char                  *family)
+{
+  char **aliases;
+  int n_aliases;
+  int j;
+  PangoFont *font;
+
+  pango_lookup_aliases (family,
+			&aliases,
+			&n_aliases);
+      
+  if (n_aliases)
+    {
+      for (j = 0; j < n_aliases; j++)
+	{
+	  pango_font_description_set_family_static (desc, aliases[j]);
+	  font = pango_font_map_load_font (fontmap, desc);
+	  if (font)
+	    pango_fontset_simple_append (fonts, font);
+	}
+    }
+  else
+    {
+      pango_font_description_set_family_static (desc, family);
+      font = pango_font_map_load_font (fontmap, desc);
+      if (font)
+	pango_fontset_simple_append (fonts, font);
+    }
+}
+
+static PangoFontset *
+pango_font_map_real_load_fontset (PangoFontMap                 *fontmap,
+				  const PangoFontDescription   *desc)
+{
+  PangoFontDescription *tmp_desc = pango_font_description_copy_static (desc);
+  char **families;
+  int i;
+  PangoFontsetSimple *fonts;
+
+  families = g_strsplit (pango_font_description_get_family (desc), ",", -1);
+
+  fonts = pango_fontset_simple_new ();
+  
+  for (i = 0; families[i]; i++)
+    pango_font_map_fontset_add_fonts (fontmap,
+				      fonts,
+				      tmp_desc,
+				      families[i]);
+  
+  g_strfreev (families);
+  pango_font_description_set_family_static (tmp_desc,
+					    pango_font_description_get_family (desc));
+
+  /* The font description was completely unloadable, try with
+   * family == "Sans"
+   */
+  if (pango_fontset_simple_size (fonts) == 0)
+    {
+      char *ctmp1, *ctmp2;
+      
+      ctmp1 = pango_font_description_to_string (desc);
+      pango_font_description_set_family_static (tmp_desc, "Sans");
+      ctmp2 = pango_font_description_to_string (tmp_desc);
+      
+      g_warning ("Couldn't load font \"%s\" falling back to \"%s\"", ctmp1, ctmp2);
+      g_free (ctmp1);
+      g_free (ctmp2);
+      
+      pango_font_map_fontset_add_fonts (fontmap,
+					fonts,
+					tmp_desc,
+					"Sans");
+    }
+  
+  /* We couldn't try with Sans and the specified style. Try Sans Normal
+   */
+  if (pango_fontset_simple_size (fonts) == 0)
+    {
+      char *ctmp1, *ctmp2;
+      
+      pango_font_description_set_family_static (tmp_desc, "Sans");
+      ctmp1 = pango_font_description_to_string (tmp_desc);
+      pango_font_description_set_style (tmp_desc, PANGO_STYLE_NORMAL);
+      pango_font_description_set_weight (tmp_desc, PANGO_WEIGHT_NORMAL);
+      pango_font_description_set_variant (tmp_desc, PANGO_VARIANT_NORMAL);
+      pango_font_description_set_stretch (tmp_desc, PANGO_STRETCH_NORMAL);
+      ctmp2 = pango_font_description_to_string (tmp_desc);
+      
+      g_warning ("Couldn't load font \"%s\" falling back to \"%s\"", ctmp1, ctmp2);
+      g_free (ctmp1);
+      g_free (ctmp2);
+      
+      pango_font_map_fontset_add_fonts (fontmap,
+					fonts,
+					tmp_desc,
+					"Sans");
+    }
+
+  /* Everything failed, we are screwed, there is no way to continue
+   */
+  if (pango_fontset_simple_size (fonts) == 0)
+    {
+      g_warning ("All font failbacks failed!!!!");
+      exit (1);
+    }
+
+  return PANGO_FONTSET (fonts);
 }
Index: pango/pango-fontmap.h
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-fontmap.h,v
retrieving revision 1.5
diff -u -p -r1.5 pango-fontmap.h
--- pango/pango-fontmap.h	2001/09/18 20:05:17	1.5
+++ pango/pango-fontmap.h	2001/11/18 01:40:33
@@ -32,13 +32,16 @@ G_BEGIN_DECLS
 
 typedef struct _PangoFontMap PangoFontMap;
 
-GType      pango_font_map_get_type       (void) G_GNUC_CONST;
-PangoFont *pango_font_map_load_font     (PangoFontMap                 *fontmap,
-					 const PangoFontDescription   *desc);
-void       pango_font_map_list_families (PangoFontMap                 *fontmap,
-					 PangoFontFamily            ***families,
-					 int                          *n_families);
+GType         pango_font_map_get_type       (void) G_GNUC_CONST;
+PangoFont *   pango_font_map_load_font     (PangoFontMap                 *fontmap,
+					    const PangoFontDescription   *desc);
+PangoFontset *pango_font_map_load_fontset  (PangoFontMap                 *fontmap,
+					    const PangoFontDescription   *desc);
+void          pango_font_map_list_families (PangoFontMap                 *fontmap,
+					    PangoFontFamily            ***families,
+					    int                          *n_families);
 
+
 #ifdef PANGO_ENABLE_BACKEND
 
 #define PANGO_FONT_MAP_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FONT_MAP, PangoFontMapClass))
@@ -56,11 +59,13 @@ struct _PangoFontMapClass
 {
   GObjectClass parent_class;
   
-  PangoFont *(*load_font)     (PangoFontMap               *fontmap,
-			       const PangoFontDescription *desc);
-  void       (*list_families) (PangoFontMap               *fontmap,
-			       PangoFontFamily          ***families,
-			       int                        *n_families);
+  PangoFont *   (*load_font)     (PangoFontMap               *fontmap,
+				  const PangoFontDescription *desc);
+  void          (*list_families) (PangoFontMap               *fontmap,
+				  PangoFontFamily          ***families,
+				  int                        *n_families);
+  PangoFontset *(*load_fontset)  (PangoFontMap               *fontmap,
+				  const PangoFontDescription *desc);
 };
 
 #endif /* PANGO_ENABLE_BACKEND */
Index: pango/pango-utils.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-utils.c,v
retrieving revision 1.29
diff -u -p -r1.29 pango-utils.c
--- pango/pango-utils.c	2001/11/11 23:36:26	1.29
+++ pango/pango-utils.c	2001/11/18 01:40:34
@@ -48,6 +48,16 @@
 
 #endif
 
+struct PangoAlias
+{
+  char *alias;
+  int n_families;
+  char **families;
+  gboolean visible; /* Do we want/need this? */
+};
+
+GHashTable *pango_aliases_ht = NULL;
+
 /**
  * pango_trim_string:
  * @str: a string
@@ -557,7 +567,7 @@ read_config_file (const char *filename, 
     }
       
   if (ferror (file))
-    errstring = g_strdup ("g_strerror(errno)");
+    errstring = g_strdup (g_strerror(errno));
   
  error:
 
@@ -1250,3 +1260,235 @@ pango_get_mirror_char (gunichar        c
 }
 
 #endif /* HAVE_FRIBIDI */
+
+
+guint
+alias_hash (struct PangoAlias *alias)
+{
+  return g_str_hash (alias->alias);
+}
+
+gboolean
+alias_equal (struct PangoAlias *alias1,
+	     struct PangoAlias *alias2)
+{
+  return g_str_equal (alias1->alias,
+		      alias2->alias);
+}
+
+
+void
+alias_free (struct PangoAlias *alias)
+{
+  int i;
+  g_free (alias->alias);
+
+  for (i = 0; i < alias->n_families; i++)
+    g_free (alias->families[i]);
+
+  g_free (alias->families);
+  
+  g_free (alias);
+}
+
+static void
+read_alias_file (const char *filename)
+{
+  FILE *file;
+    
+  GString *line_buffer;
+  GString *tmp_buffer1;
+  GString *tmp_buffer2;
+  char *errstring = NULL;
+  const char *pos;
+  int line = 0;
+  struct PangoAlias alias_key;
+  struct PangoAlias *alias;
+  char **new_families;
+  int n_new;
+  int i;
+
+  file = fopen (filename, "r");
+  if (!file)
+    return;
+
+  line_buffer = g_string_new (NULL);
+  tmp_buffer1 = g_string_new (NULL);
+  tmp_buffer2 = g_string_new (NULL);
+
+  while (pango_read_line (file, line_buffer))
+    {
+      gboolean empty = FALSE;
+      gboolean append = FALSE;
+      line++;
+
+      pos = line_buffer->str;
+      if (!pango_skip_space (&pos))
+	continue;
+      
+      if (!pango_scan_word (&pos, tmp_buffer1) ||
+	  !pango_skip_space (&pos))
+	{
+	  errstring = g_strdup ("Line is not of the form KEY=VALUE or KEY+=VALUE");
+	  goto error;
+	}
+      
+      if (*pos == '+')
+	{
+	  append = TRUE;
+	  pos++;
+	}
+
+      if (*(pos++) != '=')
+	{
+	  errstring = g_strdup ("Line is not of the form KEY=VALUE or KEY+=VALUE");
+	  goto error;
+	}
+      
+      if (!pango_skip_space (&pos))
+	{
+	  empty = TRUE;
+	}
+      else
+	{
+	  if (!pango_scan_string (&pos, tmp_buffer2))
+	    {
+	      errstring = g_strdup ("Error parsing value string");
+	      goto error;
+	    }
+	  if (pango_skip_space (&pos))
+	    {
+	      errstring = g_strdup ("Junk after value string");
+	      goto error;
+	    }
+	}
+
+      alias_key.alias = g_ascii_strdown (tmp_buffer1->str, -1);
+      
+      /* Remove any existing values */
+      alias = g_hash_table_lookup (pango_aliases_ht, &alias_key);
+      
+      if (!alias)
+	{
+	  alias = g_new0 (struct PangoAlias, 1);
+	  alias->alias = alias_key.alias;
+	  
+	  g_hash_table_insert (pango_aliases_ht,
+			       alias, alias);
+	}
+      else
+	g_free (alias_key.alias);
+	  
+      new_families = g_strsplit (tmp_buffer2->str, ",", -1);
+      
+      n_new = 0;
+      while (new_families[n_new])
+	n_new++;
+      
+      if (alias->families && append)
+	{
+	  alias->families = g_realloc (alias->families,
+				       sizeof (char *) *(n_new + alias->n_families));
+	  for (i = 0; i < n_new; i++)
+	    alias->families[alias->n_families + i] = new_families[i];
+	  g_free (new_families);
+	  alias->n_families += n_new;
+	}
+      else
+	{
+	  for (i = 0; i < alias->n_families; i++)
+	    g_free (alias->families[i]);
+	  g_free (alias->families);
+	  
+	  alias->families = new_families;
+	  alias->n_families = n_new;
+	}
+    }
+
+  if (ferror (file))
+    errstring = g_strdup (g_strerror(errno));
+  
+ error:
+
+  if (errstring)
+    {
+      fprintf (stderr, "Pango:%s:%d: %s\n", filename, line, errstring);
+      g_free (errstring);
+    }
+      
+  g_string_free (line_buffer, TRUE);
+  g_string_free (tmp_buffer1, TRUE);
+  g_string_free (tmp_buffer2, TRUE);
+
+  fclose (file);
+}
+
+void
+pango_load_aliases (void)
+{
+  char *filename;
+  const char *home;
+
+  pango_aliases_ht = g_hash_table_new_full ((GHashFunc)alias_hash,
+					    (GEqualFunc)alias_equal,
+					    (GDestroyNotify)alias_free,
+					    NULL);
+
+
+  filename = g_strconcat (pango_get_sysconf_subdirectory (),
+			  G_DIR_SEPARATOR_S "pango.aliases",
+			  NULL);
+  read_alias_file (filename);
+  g_free (filename);
+  
+  home = g_get_home_dir ();
+  if (home && *home)
+    {
+      filename = g_strconcat (home,
+			      G_DIR_SEPARATOR_S ".pango.aliases",
+			      NULL);
+      read_alias_file (filename);
+      g_free (filename);
+    }
+}
+
+
+/**
+ * pango_lookup_aliases:
+ * @fontname: an ascii string
+ * @families: will be set to an array of font family names.
+ *    this array is owned by pango and should not be freed.
+ *
+ * Look up all user defined aliases for the alias #fontname.
+ * The resulting font family names will be stored in #families,
+ * and the number of families will be returned.
+ * 
+ * Return value: the number of font famillies stored in the #families argument.
+ *   This value is owned by Pango and must not be freed.
+ **/
+void
+pango_lookup_aliases (const char   *fontname,
+		      char       ***families,
+		      int          *n_families)
+{
+  struct PangoAlias alias_key;
+  struct PangoAlias *alias;
+  
+  if (pango_aliases_ht == NULL)
+    pango_load_aliases ();
+
+  alias_key.alias = g_ascii_strdown (fontname, -1);
+  alias = g_hash_table_lookup (pango_aliases_ht, &alias_key);
+  g_free (alias_key.alias);
+
+  if (alias)
+    {
+      *families = alias->families;
+      *n_families = alias->n_families;
+    }
+  else
+    {
+      *families = NULL;
+      *n_families = 0;
+    }
+}
Index: pango/pango-utils.h
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-utils.h,v
retrieving revision 1.14
diff -u -p -r1.14 pango-utils.h
--- pango/pango-utils.h	2001/10/18 19:50:08	1.14
+++ pango/pango-utils.h	2001/11/18 01:40:34
@@ -38,6 +38,9 @@ gboolean pango_scan_int       (const cha
 
 #ifdef PANGO_ENABLE_BACKEND
 char *   pango_config_key_get (const char  *key);
+void     pango_lookup_aliases (const char   *fontname,
+			       char       ***families,
+			       int          *n_families);
 #endif /* PANGO_ENABLE_BACKEND */
 
 /* Functions for parsing textual representations
Index: pango/pangoft2-fontcache.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangoft2-fontcache.c,v
retrieving revision 1.8
diff -u -p -r1.8 pangoft2-fontcache.c
--- pango/pangoft2-fontcache.c	2000/12/21 09:54:01	1.8
+++ pango/pangoft2-fontcache.c	2001/11/18 01:40:35
@@ -66,7 +66,7 @@ free_cache_entry (PangoFT2OA        *oa,
   error = FT_Done_Face (entry->face);
   if (error != FT_Err_Ok)
     g_warning ("Error from FT_Done_Face: %s",
-	       pango_ft2_ft_strerror (error));
+	       _pango_ft2_ft_strerror (error));
 
   g_free (entry);
 }
@@ -215,7 +215,7 @@ pango_ft2_font_cache_load (PangoFT2FontC
       if (error != FT_Err_Ok)
 	{
 	  g_warning ("Error from FT_Open_Face: %s",
-		     pango_ft2_ft_strerror (error));
+		     _pango_ft2_ft_strerror (error));
 	  return NULL;
 	}
 
Index: pango/pangoft2-fontmap.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangoft2-fontmap.c,v
retrieving revision 1.23
diff -u -p -r1.23 pangoft2-fontmap.c
--- pango/pangoft2-fontmap.c	2001/11/02 14:21:19	1.23
+++ pango/pangoft2-fontmap.c	2001/11/18 01:40:36
@@ -36,6 +36,8 @@
 #include "pango-utils.h"
 #include "pangoft2-private.h"
 
+#include "mini-xft/MiniXftFreetype.h"
+
 #ifdef G_OS_WIN32
 #define STRICT
 #include <windows.h>
@@ -45,41 +47,46 @@
 #define PANGO_FT2_FONT_MAP(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FT2_FONT_MAP, PangoFT2FontMap))
 #define PANGO_FT2_IS_FONT_MAP(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FT2_FONT_MAP))
 
-typedef struct _PangoFT2Family       PangoFT2Family;
 typedef struct _PangoFT2FontMap      PangoFT2FontMap;
 typedef struct _PangoFT2SizeInfo     PangoFT2SizeInfo;
+typedef struct _PangoFT2PatternSet   PangoFT2PatternSet;
 
 /* Number of freed fonts */
 #define MAX_FREED_FONTS 16
 
+struct _PangoFT2Family
+{
+  PangoFontFamily parent_instance;
+  
+  PangoFT2FontMap *fontmap;
+  char *family_name;
+
+  PangoFT2Face **faces;
+  int n_faces;		/* -1 == uninitialized */
+};
+
+
 struct _PangoFT2FontMap
 {
   PangoFontMap parent_instance;
 
   FT_Library library;
-
-  PangoFT2FontCache *font_cache;
-  GQueue *freed_fonts;
-
-  /* Maps Pango family names to PangoFT2FamilyEntry structs */
-  GHashTable *families;
 
-  /* Maps the family and style of a face to a PangoFT2OA struct */
-  GHashTable *faces;
+  GHashTable *fontset_hash; /* Maps PangoFontDescription -> PangoXftFontSet */
+  GHashTable *coverage_hash; /* Maps font file name -> PangoCoverage */
 
-  int n_fonts;
+  GHashTable *fonts; /* Maps XftPattern -> PangoFT2Font */
+  GQueue *freed_fonts; /* Fonts in fonts that has been freed */
 
-  double resolution;		/* (points / pixel) * PANGO_SCALE */
+  /* List of all families availible */
+  PangoFT2Family **families;
+  int n_families;		/* -1 == uninitialized */
 };
 
-struct _PangoFT2Family
+struct _PangoFT2PatternSet
 {
-  PangoFontFamily parent_instance;
-  
-  char *family_name;
-
-  /* List of PangoFT2FontEntry structs */
-  GSList *font_entries;
+  int n_patterns;
+  MiniXftPattern **patterns;
 };
 
 #define PANGO_FT2_TYPE_FAMILY              (pango_ft2_family_get_type ())
@@ -93,33 +100,27 @@ struct _PangoFT2Family
 static GType    pango_ft2_font_map_get_type      (void);
 GType           pango_ft2_family_get_type          (void);
 GType           pango_ft2_face_get_type            (void);
-
-static void       pango_ft2_font_map_init          (PangoFT2FontMap             *fontmap);
 
-static void       pango_ft2_font_map_class_init    (PangoFontMapClass           *class);
+static void          pango_ft2_font_map_init          (PangoFT2FontMap              *fontmap);
+static void          pango_ft2_font_map_class_init    (PangoFontMapClass            *class);
+static void          pango_ft2_font_map_finalize      (GObject                      *object);
+static PangoFont *   pango_ft2_font_map_load_font     (PangoFontMap                 *fontmap,
+						       const PangoFontDescription   *description);
+static PangoFontset *pango_ft2_font_map_load_fontset  (PangoFontMap                 *fontmap,
+						       const PangoFontDescription   *desc);
+static void          pango_ft2_font_set_free          (PangoFT2PatternSet           *font_set);
+static void          pango_ft2_font_map_list_families (PangoFontMap                 *fontmap,
+						       PangoFontFamily            ***families,
+						       int                          *n_families);
+static void          pango_ft2_font_map_cache_remove  (PangoFontMap                 *fontmap,
+						       PangoFT2Font                 *ft2font);
+static void          pango_ft2_font_map_cache_clear   (PangoFT2FontMap              *ft2fontmap);
 
-static void       pango_ft2_font_map_finalize      (GObject                      *object);
 
-static PangoFont *pango_ft2_font_map_load_font     (PangoFontMap                 *fontmap,
-						    const PangoFontDescription   *description);
 
-static void       pango_ft2_font_map_list_families (PangoFontMap                 *fontmap,
-						    PangoFontFamily            ***families,
-						    int                          *n_families);
-
-static void       pango_ft2_fontmap_cache_clear    (PangoFT2FontMap              *ft2fontmap);
-
-static void       pango_ft2_font_map_read_aliases  (PangoFT2FontMap              *ft2fontmap);
-    						  
-static void       pango_ft2_insert_face            (PangoFT2FontMap   		 *fontmap,
-						    FT_Face                       face,
-						    const char        	         *path,
-						    int                           face_index);
-
 static PangoFontClass  *parent_class;	/* Parent class structure for PangoFT2FontMap */
 
 static PangoFT2FontMap *pango_ft2_global_fontmap = NULL;
-static char **pango_ft2_font_directories = NULL;
 
 static GType
 pango_ft2_font_map_get_type (void)
@@ -149,131 +150,135 @@ pango_ft2_font_map_get_type (void)
   return object_type;
 }
 
-static void 
-pango_ft2_font_map_init (PangoFT2FontMap *ft2fontmap)
-{
-  ft2fontmap->families = g_hash_table_new (g_str_hash, g_str_equal);
-  ft2fontmap->faces = g_hash_table_new ((GHashFunc)pango_font_description_hash,
-					(GEqualFunc)pango_font_description_equal);
-  ft2fontmap->n_fonts = 0;
-}
-
 static void
-pango_ft2_font_map_class_init (PangoFontMapClass *class)
+pango_ft2_font_set_free (PangoFT2PatternSet *font_set)
 {
-  GObjectClass *object_class = G_OBJECT_CLASS (class);
-  char *font_path;
-  
-  parent_class = g_type_class_peek_parent (class);
+  int i;
   
-  object_class->finalize = pango_ft2_font_map_finalize;
-  class->load_font = pango_ft2_font_map_load_font;
-  class->list_families = pango_ft2_font_map_list_families;
+  for (i = 0; i < font_set->n_patterns; i++)
+    MiniXftPatternDestroy (font_set->patterns[i]);
 
-  font_path = pango_config_key_get ("PangoFT2/FontPath");
+  g_free (font_set);
+}
 
-  if (!font_path)
-    {
-      font_path = g_build_filename (pango_get_lib_subdirectory (),
-				    "ft2fonts",
-				    NULL);
+static guint
+pango_ft2_pattern_hash (MiniXftPattern *pattern)
+{
+  char *str;
+  int i;
+  double d;
+  guint hash = 0;
+  
+  MiniXftPatternGetString (pattern, XFT_FILE, 0, &str);
+  if (str)
+    hash = g_str_hash (str);
 
-#ifdef G_OS_WIN32
-      {
-	char win_dir[100];
-	char *tmp_str;
+  if (MiniXftPatternGetInteger (pattern, XFT_INDEX, 0, &i) == MiniXftResultMatch)
+    hash ^= i;
 
-	GetWindowsDirectory (win_dir, sizeof (win_dir));
-	tmp_str = g_build_filename (font_path,
-				    win_dir,
-				    "fonts",
-				    NULL);
-	g_free (font_path);
-	font_path = tmp_str;
-      }		       
-#endif
-    }
+  if (MiniXftPatternGetDouble (pattern, XFT_PIXEL_SIZE, 0, &d) == MiniXftResultMatch)
+    hash ^= (guint) (d*1000.0);
 
-  pango_ft2_font_directories = pango_split_file_list (font_path);
-  g_free (font_path);
+  return hash;
 }
 
 static gboolean
-pango_ft2_is_font_file (const char *name)
+pango_ft2_pattern_equal (MiniXftPattern *pattern1,
+			 MiniXftPattern *pattern2)
 {
-  int len;
+  char *file1, *file2;
+  int index1, index2;
+  double size1, size2;
+  MiniXftResult res1, res2;
+  int int1, int2;
+  Bool bool1, bool2;
+  
+  MiniXftPatternGetString (pattern1, XFT_FILE, 0, &file1);
+  MiniXftPatternGetString (pattern2, XFT_FILE, 0, &file2);
 
-  len = strlen (name);
-  if (len > 4 &&
-      (g_ascii_strncasecmp (&name[len-4], ".pfa", 4) == 0 ||
-       g_ascii_strncasecmp (&name[len-4], ".pfb", 4) == 0 ||
-       g_ascii_strncasecmp (&name[len-4], ".ttf", 4) == 0 ||
-       g_ascii_strncasecmp (&name[len-4], ".ttc", 4) == 0))
-    return TRUE;
+  g_assert (file1 != NULL && file2 != NULL);
 
-  return FALSE;
+  if (strcmp (file1, file2) != 0)
+    return FALSE;
+  
+  if (MiniXftPatternGetInteger (pattern1, XFT_INDEX, 0, &index1) != MiniXftResultMatch)
+    return FALSE;
+  
+  if (MiniXftPatternGetInteger (pattern2, XFT_INDEX, 0, &index2) != MiniXftResultMatch)
+    return FALSE;
+
+  if (index1 != index2)
+    return FALSE;
+
+  if (MiniXftPatternGetDouble (pattern1, XFT_PIXEL_SIZE, 0, &size1) != MiniXftResultMatch)
+    return FALSE;
+
+  if (MiniXftPatternGetDouble (pattern2, XFT_PIXEL_SIZE, 0, &size2) != MiniXftResultMatch)
+    return FALSE;
+
+  if (size1 != size2)
+    return FALSE;
+
+  res1 = MiniXftPatternGetInteger (pattern1, XFT_RGBA, 0, &int1);
+  res2 = MiniXftPatternGetInteger (pattern2, XFT_RGBA, 0, &int2);
+  if (res1 != res2 || (res1 == MiniXftResultMatch && int1 != int2))
+    return FALSE;
+  
+  res1 = MiniXftPatternGetBool (pattern1, XFT_ANTIALIAS, 0, &bool1);
+  res2 = MiniXftPatternGetBool (pattern2, XFT_ANTIALIAS, 0, &bool2);
+  if (res1 != res2 || (res1 == MiniXftResultMatch && bool1 != bool2))
+    return FALSE;
+  
+  res1 = MiniXftPatternGetBool (pattern1, XFT_MINSPACE, 0, &bool1);
+  res2 = MiniXftPatternGetBool (pattern2, XFT_MINSPACE, 0, &bool2);
+  if (res1 != res2 || (res1 == MiniXftResultMatch && bool1 != bool2))
+    return FALSE;
+
+  res1 = MiniXftPatternGetInteger (pattern1, XFT_SPACING, 0, &int1);
+  res2 = MiniXftPatternGetInteger (pattern2, XFT_SPACING, 0, &int2);
+  if (res1 != res2 || (res1 == MiniXftResultMatch && int1 != int2))
+    return FALSE;
+
+  res1 = MiniXftPatternGetInteger (pattern1, XFT_CHAR_WIDTH, 0, &int1);
+  res2 = MiniXftPatternGetInteger (pattern2, XFT_CHAR_WIDTH, 0, &int2);
+  if (res1 != res2 || (res1 == MiniXftResultMatch && int1 != int2))
+    return FALSE;
+  
+  return TRUE;
 }
 
-static gboolean
-pango_ft2_scan_directory (const char      *path,
-			  PangoFT2FontMap *ft2fontmap)
+
+static void 
+pango_ft2_font_map_init (PangoFT2FontMap *ft2fontmap)
 {
-  DIR *dir;
-  struct dirent *entry;
-  char *fullname;
-  FT_Face face;
-  FT_Error error;
-  int i;
-  gboolean found_font = FALSE;
 
-  dir = opendir (path);
-  if (!dir)
-    /* Don't warn; it's OK to have nonexistent entries in the font path */
-    return FALSE;
+  ft2fontmap->fonts =
+    g_hash_table_new ((GHashFunc)pango_ft2_pattern_hash,
+		      (GEqualFunc)pango_ft2_pattern_equal);
+  ft2fontmap->fontset_hash =
+    g_hash_table_new_full ((GHashFunc)pango_font_description_hash,
+			   (GEqualFunc)pango_font_description_equal,
+			   (GDestroyNotify)pango_font_description_free,
+			   (GDestroyNotify)pango_ft2_font_set_free);
+  
+  ft2fontmap->coverage_hash =
+    g_hash_table_new_full (g_str_hash, g_str_equal,
+			   (GDestroyNotify)g_free,
+			   (GDestroyNotify)pango_coverage_unref);
+  ft2fontmap->freed_fonts = g_queue_new ();
+}
 
-  while ((entry = readdir (dir)) != NULL)
-    {
-      fullname = g_build_filename (path, entry->d_name, NULL);
-      if (pango_ft2_is_font_file (fullname))
-	{
-	  error = FT_New_Face (ft2fontmap->library, fullname, 0, &face);
-	  if (error != FT_Err_Ok)
-	    g_warning ("Error loading font from '%s': %s",
-		       fullname, pango_ft2_ft_strerror (error));
-	  else
-	    {
-	      if (face->face_flags & FT_FACE_FLAG_SCALABLE)
-		{
-		  pango_ft2_insert_face (ft2fontmap, face, fullname, 0);
-		  found_font = TRUE;
-		}
-	      
-	      for (i = 1; i < face->num_faces; i++)
-		{
-		  error = FT_Done_Face (face);
-		  if (error != FT_Err_Ok)
-		    g_warning ("Error from FT_Done_Face: %s",
-			       pango_ft2_ft_strerror (error));
-		  error = FT_New_Face (ft2fontmap->library, fullname, i, &face);
-		  if (error != FT_Err_Ok)
-		    g_warning ("Error loading font %d from '%s': %s",
-			       i, fullname, pango_ft2_ft_strerror (error));
-		  else if (face->face_flags & FT_FACE_FLAG_SCALABLE)
-		    {
-		      pango_ft2_insert_face (ft2fontmap, face, fullname, i);
-		      found_font = TRUE;
-		    }
-		}
-	      error = FT_Done_Face (face);
-	      if (error != FT_Err_Ok)
-		g_warning ("Error from FT_Done_Face: %s",
-			   pango_ft2_ft_strerror (error));
-	    }
-	}
-      g_free (fullname);
-    }
-  closedir (dir);
-  return found_font;
+static void
+pango_ft2_font_map_class_init (PangoFontMapClass *class)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (class);
+  
+  parent_class = g_type_class_peek_parent (class);
+  
+  object_class->finalize = pango_ft2_font_map_finalize;
+  class->load_font = pango_ft2_font_map_load_font;
+  class->load_fontset = pango_ft2_font_map_load_fontset;
+  class->list_families = pango_ft2_font_map_list_families;
 }
 
 /**
@@ -288,9 +293,7 @@ pango_ft2_scan_directory (const char    
 PangoFontMap *
 pango_ft2_font_map_for_display (void)
 {
-  char **tmp_list;
   FT_Error error;
-  gboolean read_font;
 
   /* Make sure that the type system is initialized */
   g_type_init ();
@@ -304,27 +307,10 @@ pango_ft2_font_map_for_display (void)
   if (error != FT_Err_Ok)
     {
       g_warning ("Error from FT_Init_FreeType: %s",
-		 pango_ft2_ft_strerror (error));
+		 _pango_ft2_ft_strerror (error));
       return NULL;
     }
 
-  pango_ft2_global_fontmap->font_cache = pango_ft2_font_cache_new (pango_ft2_global_fontmap->library);
-  pango_ft2_global_fontmap->freed_fonts = g_queue_new ();
-  
-  tmp_list = pango_ft2_font_directories;
-
-  read_font = FALSE;
-  while (*tmp_list)
-    {
-      read_font |= pango_ft2_scan_directory ((const char *) *tmp_list, pango_ft2_global_fontmap);
-      tmp_list++;
-    }
-
-  if (!read_font)
-    g_warning ("No fonts found by pangoft2. Things will probably not work");
-  
-  pango_ft2_font_map_read_aliases (pango_ft2_global_fontmap);
-
   return PANGO_FONT_MAP (pango_ft2_global_fontmap);
 }
 
@@ -336,560 +322,288 @@ pango_ft2_font_map_for_display (void)
 void
 pango_ft2_shutdown_display (void)
 {
-  pango_ft2_fontmap_cache_clear (pango_ft2_global_fontmap);
+  pango_ft2_font_map_cache_clear (pango_ft2_global_fontmap);
 
   g_object_unref (G_OBJECT (pango_ft2_global_fontmap));
 
   pango_ft2_global_fontmap = NULL;
 }
 
+
 static void
 pango_ft2_font_map_finalize (GObject *object)
 {
   PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (object);
   
-  g_list_foreach (ft2fontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
   g_queue_free (ft2fontmap->freed_fonts);
+  g_hash_table_destroy (ft2fontmap->fontset_hash);
+  g_hash_table_destroy (ft2fontmap->coverage_hash);
   
-  pango_ft2_font_cache_free (ft2fontmap->font_cache);
-
   FT_Done_FreeType (ft2fontmap->library);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-static void
-list_families_foreach (gpointer key, gpointer value, gpointer user_data)
+/* Add a mapping from xfont->font_pattern to xfont */
+void
+_pango_ft2_font_map_add (PangoFontMap *fontmap,
+			 PangoFT2Font *ft2font)
 {
-  GSList **list = user_data;
+  PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *) fontmap;
 
-  *list = g_slist_prepend (*list, value);
+  g_hash_table_insert (ft2fontmap->fonts,
+		       ft2font->font_pattern,
+		       ft2font);
 }
 
+/* Remove mapping from xfont->font_pattern to xfont */
+void
+_pango_ft2_font_map_remove (PangoFontMap *fontmap,
+			    PangoFT2Font *ft2font)
+{
+  PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *) fontmap;
+
+  g_hash_table_remove (ft2fontmap->fonts,
+		       ft2font->font_pattern);
+}
+
 static void
 pango_ft2_font_map_list_families (PangoFontMap           *fontmap,
 				  PangoFontFamily      ***families,
 				  int                    *n_families)
 {
-  GSList *family_list = NULL;
-  GSList *tmp_list;
   PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
-
-  if (!n_families)
-    return;
-
-  g_hash_table_foreach (ft2fontmap->families, list_families_foreach, &family_list);
-
-  *n_families = g_slist_length (family_list);
+  MiniXftFontSet *fontset;
+  int i;
 
-  if (families)
+  if (ft2fontmap->n_families < 0)
     {
-      int i = 0;
-	
-      *families = g_new (PangoFontFamily *, *n_families);
+      fontset = MiniXftListFonts ((Display *)1, 0,
+				  XFT_CORE, MiniXftTypeBool, False,
+				  XFT_ENCODING, MiniXftTypeString, "iso10646-1",
+				  NULL,
+				  XFT_FAMILY,
+				  NULL);
+
+      ft2fontmap->n_families = fontset->nfont;
+      ft2fontmap->families = g_new (PangoFT2Family *, ft2fontmap->n_families);
 
-      tmp_list = family_list;
-      while (tmp_list)
+      for (i = 0; i < fontset->nfont; i++)
 	{
-	  (*families)[i] = tmp_list->data;
-	  i++;
-	  tmp_list = tmp_list->next;
+	  char *s;
+	  MiniXftResult res;
+	  
+	  res = MiniXftPatternGetString (fontset->fonts[i], XFT_FAMILY, 0, &s);
+	  g_assert (res == MiniXftResultMatch);
+	  
+	  ft2fontmap->families[i] = g_object_new (PANGO_FT2_TYPE_FAMILY, NULL);
+	  ft2fontmap->families[i]->family_name = g_strdup (s);
+	  ft2fontmap->families[i]->fontmap = ft2fontmap;
 	}
+
+      MiniXftFontSetDestroy (fontset);
     }
+  
+  if (n_families)
+    *n_families = ft2fontmap->n_families;
   
-  g_slist_free (family_list);
+  if (families)
+    *families = g_memdup (ft2fontmap->families, ft2fontmap->n_families * sizeof (PangoFontFamily *));
 }
 
-static PangoFT2Family *
-pango_ft2_get_family (PangoFT2FontMap *ft2fontmap,
-		      const char      *family_name)
+static int
+pango_ft2_convert_weight (PangoWeight pango_weight)
 {
-  PangoFT2Family *ft2family = g_hash_table_lookup (ft2fontmap->families, family_name);
-  if (!ft2family)
-    {
-      ft2family = g_object_new (PANGO_FT2_TYPE_FAMILY, NULL);
-      ft2family->family_name = g_strdup (family_name);
-      ft2family->font_entries = NULL;
-      
-      g_hash_table_insert (ft2fontmap->families, ft2family->family_name, ft2family);
-    }
-
-  return ft2family;
+  int weight;
+  
+  if (pango_weight < (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_LIGHT) / 2)
+    weight = XFT_WEIGHT_LIGHT;
+  else if (pango_weight < (PANGO_WEIGHT_NORMAL + 600) / 2)
+    weight = XFT_WEIGHT_MEDIUM;
+  else if (pango_weight < (600 + PANGO_WEIGHT_BOLD) / 2)
+    weight = XFT_WEIGHT_DEMIBOLD;
+  else if (pango_weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2)
+    weight = XFT_WEIGHT_BOLD;
+  else
+    weight = XFT_WEIGHT_BLACK;
+  
+  return weight;
 }
 
-static PangoFont *
-pango_ft2_font_map_load_font (PangoFontMap               *fontmap,
-			      const PangoFontDescription *description)
+static int
+pango_ft2_convert_slant (PangoStyle pango_style)
 {
-  PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
-  PangoFT2Family *family_entry;
-  PangoFont *result = NULL;
-  GSList *tmp_list;
-  gchar *name;
-
-  g_return_val_if_fail (description != NULL, NULL);
+  int slant;
   
-  name = g_ascii_strdown (pango_font_description_get_family (description), -1);
-
-  family_entry = g_hash_table_lookup (ft2fontmap->families, name);
-  g_free (name);
+  if (pango_style == PANGO_STYLE_ITALIC)
+    slant = XFT_SLANT_ITALIC;
+  else if (pango_style == PANGO_STYLE_OBLIQUE)
+    slant = XFT_SLANT_OBLIQUE;
+  else
+    slant = XFT_SLANT_ROMAN;
   
-  if (family_entry)
-    {
-      PangoFT2Face *best_match = NULL;
-      
-      tmp_list = family_entry->font_entries;
-      while (tmp_list)
-	{
-	  PangoFT2Face *face = tmp_list->data;
-	  
-	  if (pango_font_description_better_match (description,
-						   best_match ? best_match->description : NULL,
-						   face->description))
-	    best_match = face;
-	  
-	  tmp_list = tmp_list->next;
-	}
-
-      if (best_match)
-	{
-	  GSList *tmp_list = best_match->cached_fonts;
-
-	  gint size = pango_font_description_get_size (description);
-
-	  while (tmp_list)
-	    {
-	      PangoFT2Font *ft2font = tmp_list->data;
-
-	      if (ft2font->size == size)
-		{
-		  result = (PangoFont *)ft2font;
-	      
-		  g_object_ref (G_OBJECT (result));
-		  if (ft2font->in_cache)
-		    pango_ft2_fontmap_cache_remove (fontmap, ft2font);
-		  break;
-		}
-	      tmp_list = tmp_list->next;
-	    }
-
-	  if (!result)
-	    {
-	      PangoFT2Font *ft2font =
-		(PangoFT2Font *) pango_ft2_load_font (fontmap,
-						      best_match->open_args,
-						      best_match->face_indices,
-						      best_match->n_fonts,
-						      size);
-	      
-	      ft2font->fontmap = fontmap;
-	      ft2font->entry = best_match;
-	      best_match->cached_fonts = g_slist_prepend (best_match->cached_fonts, ft2font);
-	      
-	      result = (PangoFont *)ft2font;
-	    }
-	}
-    }
-
-  return result;
+  return slant;
 }
 
-static gboolean
-pango_ft2_font_map_read_alias_file (PangoFT2FontMap *ft2fontmap,
-				    const char      *filename)
-{
-  FILE *infile;
-  int lineno = 0;
-  int nfaces;
-  int i;
-  PangoFT2Face *face = NULL;
-  gchar **faces;
-  gboolean ret_val = FALSE;
-
-  infile = fopen (filename, "r");
-  if (infile)
-    {
-      GString *line_buf = g_string_new (NULL);
-      GString *tmp_buf = g_string_new (NULL);
-
-      while (pango_read_line (infile, line_buf))
-	{
-	  PangoFT2Family *family_entry;
-	  PangoStyle style;
-	  PangoVariant variant;
-	  PangoWeight weight;
-	  PangoStretch stretch;
-
-	  const char *p = line_buf->str;
-	  
-	  lineno++;
-
-	  if (!pango_skip_space (&p))
-	    continue;
-
-	  if (!pango_scan_string (&p, tmp_buf))
-	    goto error;
-
-	  face = g_object_new (PANGO_FT2_TYPE_FACE, NULL);
-	  face->n_fonts = 0;
-	  face->open_args = NULL;
-	  face->face_indices = NULL;
-
-	  face->description = pango_font_description_new ();
-
-	  g_string_ascii_down (tmp_buf);
-	  pango_font_description_set_family (face->description, tmp_buf->str);
-	  
-	  if (!pango_scan_string (&p, tmp_buf))
-	    goto error;
-
-	  if (!pango_parse_style (tmp_buf->str, &style, TRUE))
-	    goto error;
-	  pango_font_description_set_style (face->description, style);
-
-	  if (!pango_scan_string (&p, tmp_buf))
-	    goto error;
-
-	  if (!pango_parse_variant (tmp_buf->str, &variant, TRUE))
-	    goto error;
-	  pango_font_description_set_variant (face->description, variant);
-	  
-	  if (!pango_scan_string (&p, tmp_buf))
-	    goto error;
-
-	  if (!pango_parse_weight (tmp_buf->str, &weight, TRUE))
-	    goto error;
-	  pango_font_description_set_weight (face->description, weight);
-	  
-	  if (!pango_scan_string (&p, tmp_buf))
-	    goto error;
-
-	  if (!pango_parse_stretch (tmp_buf->str, &stretch, TRUE))
-	    goto error;
-	  pango_font_description_set_stretch (face->description, stretch);
-
-	  if (!pango_scan_string (&p, tmp_buf))
-	    goto error;
-
-	  /* Remove excess whitespace and check for complete fields */
-
-	  faces = g_strsplit (tmp_buf->str, ",", -1);
-	  nfaces = 0;
-	  for (i = 0; faces[i]; i++)
-	    {
-	      char *trimmed = pango_trim_string (faces[i]);
-	      g_free (faces[i]);
-	      faces[i] = trimmed;
-	      nfaces++;
-	    }
-
-	  face->open_args = g_new (FT_Open_Args *, nfaces);
-	  face->face_indices = g_new (FT_Long, nfaces);
-	  
-	  for (i = 0; i < nfaces; i++)
-	    {
-	      PangoFontDescription *desc = pango_font_description_copy_static (face->description);
-	      PangoFT2OA *oa;
-
-	      pango_font_description_set_family_static (desc, faces[i]);
-	      oa = g_hash_table_lookup (ft2fontmap->faces, desc);
-	      if (!oa)
-		g_warning ("Face '%s' on line %d of '%s' not found", faces[i], lineno, filename);
-	      else
-		{
-		  face->open_args[face->n_fonts] = oa->open_args;
-		  face->face_indices[face->n_fonts] = oa->face_index;
-		  face->n_fonts++;
-		}
-
-	      pango_font_description_free (desc);
-	    }
-
-	  g_strfreev (faces);
-	  
-	  /* Insert the font entry into our structures */
 
-	  family_entry = pango_ft2_get_family (ft2fontmap, pango_font_description_get_family (face->description));
-	  family_entry->font_entries = g_slist_prepend (family_entry->font_entries, face);
-	  ft2fontmap->n_fonts++;
-
-	  /* Save space by consolidating duplicated string */
-	  pango_font_description_set_family_static (face->description, family_entry->family_name);
-	  face->cached_fonts = NULL;
-	  face->coverage = NULL;
-	}
-
-      if (ferror (infile))
-	g_warning ("Error reading file '%s': %s", filename, g_strerror(errno));
-
-      ret_val = TRUE;
-      goto out;
-
-    error:
-      if (face)
-	{
-	  if (face->open_args)
-	    g_free (face->open_args);
-	  if (face->face_indices)
-	    g_free (face->face_indices);
-	  if (face->description)
-	    pango_font_description_free (face->description);
-	  g_free (face);
-	}
-
-      g_warning ("Error parsing line %d of alias file '%s'", lineno, filename);
-
-    out:
-      g_string_free (tmp_buf, TRUE);
-      g_string_free (line_buf, TRUE);
+static MiniXftPattern *
+pango_ft2_make_pattern (const PangoFontDescription *description)
+{
+  MiniXftPattern *pattern;
+  PangoStyle pango_style;
+  int slant;
+  int weight;
+  
+  pango_style = pango_font_description_get_style (description);
 
-      fclose (infile);
-    }
+  slant = pango_ft2_convert_slant (pango_style);
+  weight = pango_ft2_convert_weight (pango_font_description_get_weight (description));
+  
+  /* To fool Xft into not munging glyph indices, we open it as glyphs-fontspecific
+   * then set the encoding ourself
+   */
+  pattern = MiniXftPatternBuild (0,
+				 XFT_ENCODING, MiniXftTypeString, "glyphs-fontspecific",
+				 XFT_CORE, MiniXftTypeBool, False,
+				 XFT_FAMILY, MiniXftTypeString,  pango_font_description_get_family (description),
+				 XFT_WEIGHT, MiniXftTypeInteger, weight,
+				 XFT_SLANT,  MiniXftTypeInteger, slant,
+				 XFT_SIZE, MiniXftTypeDouble, (double)pango_font_description_get_size (description)/PANGO_SCALE,
+				 NULL);
 
-  return ret_val;
+  return pattern;
 }
 
-static void
-pango_ft2_font_map_read_aliases (PangoFT2FontMap *ft2fontmap)
+static PangoFont *
+pango_ft2_font_map_new_font (PangoFontMap    *fontmap,
+			     MiniXftPattern  *match)
 {
-  char **files;
-  char *files_str = pango_config_key_get ("PangoFT2/AliasFiles");
-  int n;
-  gboolean read_aliasfile;
-
-  if (!files_str)
+  PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
+  PangoFT2Font *font;
+  
+  /* Look up cache */
+  font = g_hash_table_lookup (ft2fontmap->fonts, match);
+  
+  if (font)
     {
-      const char *home = g_get_home_dir ();
-      char *file1 = NULL;
-      char *file2;
-
-      if (home && *home)
-	file1 = g_build_filename  (home, ".pangoft2_aliases", NULL);
+      /* Revive fonts from cache */
+      if (font->in_cache)
+	pango_ft2_font_map_cache_remove (fontmap, font);
       
-      file2 = g_build_filename (pango_get_sysconf_subdirectory (),
-				"pangoft2.aliases",
-				NULL);
-
-      files_str = g_build_path (G_SEARCHPATH_SEPARATOR_S,
-				file1 ? file1 : file2,
-				file1 ? file2 : NULL,
-				NULL);
-			     
-      g_free (file1);
-      g_free (file2);
+      return (PangoFont *)g_object_ref (G_OBJECT(font));
     }
-
-  files = pango_split_file_list (files_str);
-  
-  n = 0;
-  while (files[n])
-    n++;
-
-
-  read_aliasfile = FALSE;
   
-  while (n-- > 0)
-    read_aliasfile |= pango_ft2_font_map_read_alias_file (ft2fontmap, files[n]);
-
-  if (!read_aliasfile)
-    g_warning ("Didn't read any pango ft2 fontalias file. Things will probably not work.");
-
-  g_strfreev (files);
-  g_free (files_str);
+  return  (PangoFont *)_pango_ft2_font_new (fontmap, MiniXftPatternDuplicate (match));
 }
 
-#if DEBUGGING
 
-static void
-pango_print_desc (PangoFontDescription *desc)
+static PangoFont *
+pango_ft2_font_map_load_font (PangoFontMap               *fontmap,
+			      const PangoFontDescription *description)
 {
-  PangoStyle style = pango_font_description_get_style (desc);
-  PangoVariant variant = pango_font_description_get_variant (desc);
-  PangoWeight weight = pango_font_description_get_weight (desc);
-  PangoStretch stretch = pango_font_description_get_stretch (desc);
-  
-  g_print ("%s%s%s%s%s",
-	   pango_font_description_get_family (desc),
-	   (style == PANGO_STYLE_NORMAL ? "" :
-	    (style == PANGO_STYLE_OBLIQUE ? " OBLIQUE" :
-	     (style == PANGO_STYLE_ITALIC ? " ITALIC" : " ???"))),
-	   (variant == PANGO_VARIANT_NORMAL ? "" :
-	    (variant == PANGO_VARIANT_SMALL_CAPS ? " SMALL CAPS" : "???")),
-	   (weight >= (PANGO_WEIGHT_LIGHT + PANGO_WEIGHT_NORMAL) / 2 &&
-	    weight < (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_BOLD) / 2 ? "" :
-	    (weight < (PANGO_WEIGHT_ULTRALIGHT + PANGO_WEIGHT_LIGHT) / 2 ? " ULTRALIGHT" :
-	     (weight >= (PANGO_WEIGHT_ULTRALIGHT + PANGO_WEIGHT_LIGHT) / 2 &&
-	      weight < (PANGO_WEIGHT_LIGHT + PANGO_WEIGHT_NORMAL) / 2 ? " LIGHT" :
-	      (weight >= (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_BOLD) / 2 &&
-	       weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2 ? " BOLD" :
-	       (weight >= (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2 &&
-		weight < (PANGO_WEIGHT_ULTRABOLD + PANGO_WEIGHT_HEAVY) / 2 ? " ULTRABOLD" :
-		" HEAVY"))))),
-	   (stretch == PANGO_STRETCH_ULTRA_CONDENSED ? " ULTRA CONDENSED" :
-	    (stretch == PANGO_STRETCH_EXTRA_CONDENSED ? " EXTRA CONDENSED" :
-	     (stretch == PANGO_STRETCH_CONDENSED ? " CONDENSED" :
-	      (stretch == PANGO_STRETCH_SEMI_CONDENSED ? " SEMI CONDENSED" :
-	       (stretch == PANGO_STRETCH_NORMAL ? "" :
-		(stretch == PANGO_STRETCH_SEMI_EXPANDED ? " SEMI EXPANDED" :
-		 (stretch == PANGO_STRETCH_EXPANDED ? " EXPANDED" :
-		  (stretch == PANGO_STRETCH_EXTRA_EXPANDED ? " EXTRA EXPANDED" :
-		   (stretch == PANGO_STRETCH_ULTRA_EXPANDED ? " ULTRA EXPANDED" : " ???"))))))))));
-}
+  PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
+  MiniXftPattern *pattern, *match;
+  MiniXftResult res;
 
-static void
-pango_ft2_print_oa (PangoFT2OA *oa)
-{
-  g_print ("%s:%ld", oa->open_args->pathname, oa->face_index);
-}
+  pattern = pango_ft2_make_pattern (description);
+      
+  match = MiniXftFontMatch ((Display *)1, 0, pattern, &res);
+      
+  MiniXftPatternDestroy (pattern);
+  
+  if (match)
+    return  pango_ft2_font_map_new_font (fontmap, match);
 
-#endif
+  return NULL;
+}
 
-static void
-pango_ft2_insert_face (PangoFT2FontMap *ft2fontmap,
-		       FT_Face          face,
-		       const char      *path,
-		       int              face_index)
+static PangoFontset *
+pango_ft2_font_map_load_fontset (PangoFontMap                 *fontmap,
+				 const PangoFontDescription   *desc)
 {
-  PangoFontDescription *description;
-  char *family_name;
-  PangoStyle style;
-  PangoVariant variant;
-  PangoWeight weight;
-  PangoStretch stretch;
-  GSList *tmp_list;
-  PangoFT2Family *family_entry;
-  PangoFT2Face *face_entry;
-  PangoFT2OA *oa;
-  FT_Open_Args *open_args;
+  PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
+  MiniXftPattern *pattern, *pattern_copy;
+  MiniXftPattern *match;
+  int i;
+  char *family, *family_res;
+  MiniXftResult res;
+  int id;
+  PangoFT2PatternSet *patterns;
+  int max_patterns;
+  PangoFontsetSimple *simple;
 
-  family_name = g_ascii_strdown (face->family_name, -1);
+  patterns = g_hash_table_lookup (ft2fontmap->fontset_hash, desc);
 
-  if (face->style_flags & FT_STYLE_FLAG_ITALIC)
-    style = PANGO_STYLE_ITALIC;
-  else
-    style = PANGO_STYLE_NORMAL;
-
-  variant = PANGO_VARIANT_NORMAL;
+  if (patterns == NULL)
+    {
+      pattern = pango_ft2_make_pattern (desc);
 
-  if (face->style_flags & FT_STYLE_FLAG_BOLD)
-    weight = PANGO_WEIGHT_BOLD;
-  else
-    weight = PANGO_WEIGHT_NORMAL;
+      MiniXftConfigSubstitute (pattern);
+      MiniXftDefaultSubstitute ((Display *)1, 0, pattern);
 
-  stretch = PANGO_STRETCH_NORMAL;
+      pattern_copy = MiniXftPatternDuplicate (pattern);
 
-  if (face->style_name)
-    {
-      gchar **styles = g_strsplit (face->style_name, " ", 0);
-      gint i = 0;
+      patterns = g_new (PangoFT2PatternSet, 1);
+      patterns->n_patterns = 0;
+      max_patterns = 5;
+      patterns->patterns = g_new (MiniXftPattern *, max_patterns);
 
-      while (styles[i])
+      MiniXftInit (0);
+      MiniXftInitFtLibrary ();
+	  
+      match = NULL;
+      id = 0;
+      while (MiniXftPatternGetString (pattern, XFT_FAMILY, id++, &family) == MiniXftResultMatch)
 	{
-	  (void) (pango_parse_style (styles[i], &style, FALSE) ||
-		  pango_parse_variant (styles[i], &variant, FALSE) ||
-		  pango_parse_weight (styles[i], &weight, FALSE) ||
-		  pango_parse_stretch (styles[i], &stretch, FALSE));
-	  i++;
-	}
-      g_strfreev (styles);
-    }
-
-#if 0
-  PING ((""));
-  pango_print_desc (description);
-#endif
+	  MiniXftPatternDel (pattern_copy, XFT_FAMILY);
+	  MiniXftPatternAddString (pattern_copy, XFT_FAMILY, family);
 
-  family_entry = pango_ft2_get_family (ft2fontmap, family_name);
-  g_free (family_name);
-
-  tmp_list = family_entry->font_entries;
-  while (tmp_list)
-    {
-      face_entry = tmp_list->data;
+	  match = MiniXftFontSetMatch (&_MiniXftFontSet, 1, pattern_copy, &res);
+	  
+	  if (match &&
+	      MiniXftPatternGetString (match, XFT_FAMILY, 0, &family_res) == MiniXftResultMatch &&
+	      g_ascii_strcasecmp (family, family_res) == 0)
+	    {
+	      if (patterns->n_patterns == max_patterns)
+		{
+		  max_patterns *= 2;
+		  patterns->patterns = g_realloc (patterns->patterns,
+						  sizeof(MiniXftPattern *) * max_patterns);
+		}
 
-      if (pango_font_description_get_style (face_entry->description) == style &&
-	  pango_font_description_get_weight (face_entry->description) == weight &&
-	  pango_font_description_get_stretch (face_entry->description) == stretch &&
-	  pango_font_description_get_variant (face_entry->description) == variant)
+	      patterns->patterns[patterns->n_patterns++] = match;
+	      match = NULL;
+	    }
+	  if (match)
+	    MiniXftPatternDestroy (match);
+	}
+      
+      if (patterns->n_patterns == 0)
 	{
-#if 0
-	  PING ((" family and description matched (!)"));
-#endif
-	  return;
+	  match = MiniXftFontSetMatch (&_MiniXftFontSet, 1, pattern, &res);
+	  patterns->patterns[patterns->n_patterns++] = match;
 	}
-
-      tmp_list = tmp_list->next;
-    }
 
-  description = pango_font_description_new ();
-  pango_font_description_set_family_static (description, family_entry->family_name);
-  pango_font_description_set_style (description, style);
-  pango_font_description_set_weight (description, weight);
-  pango_font_description_set_stretch (description, stretch);
-  pango_font_description_set_variant (description, variant);
+      MiniXftPatternDestroy (pattern);
+      MiniXftPatternDestroy (pattern_copy);
 
-  oa = g_hash_table_lookup (ft2fontmap->faces, description);
-  if (!oa)
-    {
-      oa = g_new (PangoFT2OA, 1);
-      open_args = g_new (FT_Open_Args, 1);
-      open_args->flags = ft_open_pathname;
-      open_args->pathname = g_strdup (path);
-      open_args->driver = NULL;
-      open_args->num_params = 0;
-      oa->open_args = open_args;
-      oa->face_index = face_index;
-#if 0
-      PING (("adding mapping: "));
-      pango_ft2_print_oa (oa);
-#endif
-      g_hash_table_insert (ft2fontmap->faces, description, oa);
+      g_hash_table_insert (ft2fontmap->fontset_hash,
+			   pango_font_description_copy (desc),
+			   patterns);
     }
-#if 0
-  g_print ("\n");
-#endif
-
-  face_entry = g_object_new (PANGO_FT2_TYPE_FACE, NULL);
-  face_entry->description = description;
-  face_entry->cached_fonts = NULL;
-  face_entry->coverage = NULL;
-  face_entry->open_args = g_new (FT_Open_Args *, 1);
-  face_entry->open_args[0] = oa->open_args;
-  face_entry->face_indices = g_new (FT_Long, 1);
-  face_entry->face_indices[0] = oa->face_index;
-  face_entry->n_fonts = 1;
-  family_entry->font_entries = g_slist_append (family_entry->font_entries, face_entry);
-  ft2fontmap->n_fonts++;
-}
 
-static void
-free_coverages_foreach (gpointer key,
-			gpointer value,
-			gpointer data)
-{
-  pango_coverage_unref (value);
-}
-
-/**
- * pango_ft2_font_map_get_font_cache:
- * @font_map: a #PangoFT2FontMap.
- *
- * Obtains the font cache associated with the given font map.
- *
- * Returns: the #PangoFT2FontCache of @font_map.
- **/
-PangoFT2FontCache *
-pango_ft2_font_map_get_font_cache (PangoFontMap *font_map)
-{
-  g_return_val_if_fail (font_map != NULL, NULL);
-  g_return_val_if_fail (PANGO_FT2_IS_FONT_MAP (font_map), NULL);
+  simple = pango_fontset_simple_new ();
 
-  return PANGO_FT2_FONT_MAP (font_map)->font_cache;
+  for (i = 0; i < patterns->n_patterns; i++)
+    pango_fontset_simple_append (simple,
+				 pango_ft2_font_map_new_font (fontmap, patterns->patterns[i]));
+  
+  return PANGO_FONTSET (simple);
 }
 
 void
-pango_ft2_fontmap_cache_add (PangoFontMap *fontmap,
-			     PangoFT2Font *ft2font)
+_pango_ft2_font_map_cache_add (PangoFontMap *fontmap,
+			       PangoFT2Font *ft2font)
 {
   PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (fontmap);
 
@@ -904,9 +618,9 @@ pango_ft2_fontmap_cache_add (PangoFontMa
   ft2font->in_cache = TRUE;
 }
 
-void
-pango_ft2_fontmap_cache_remove (PangoFontMap *fontmap,
-				PangoFT2Font *ft2font)
+static void
+pango_ft2_font_map_cache_remove (PangoFontMap *fontmap,
+				 PangoFT2Font *ft2font)
 {
   PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (fontmap);
 
@@ -926,7 +640,7 @@ pango_ft2_fontmap_cache_remove (PangoFon
 }
 
 static void
-pango_ft2_fontmap_cache_clear (PangoFT2FontMap *ft2fontmap)
+pango_ft2_font_map_cache_clear (PangoFT2FontMap *ft2fontmap)
 {
   g_list_foreach (ft2fontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
   g_list_free (ft2fontmap->freed_fonts->head);
@@ -935,98 +649,95 @@ pango_ft2_fontmap_cache_clear (PangoFT2F
   ft2fontmap->freed_fonts->length = 0;
 }
 
-static void
-pango_ft2_face_dump (int           indent,
-		     PangoFT2Face *face)
+/* 
+ * PangoFT2Face
+ */
+
+PangoFontDescription *
+_pango_ft2_font_desc_from_pattern (MiniXftPattern *pattern)
 {
+  PangoFontDescription *desc;
+  PangoStyle style;
+  PangoWeight weight;
+  
+  char *s;
   int i;
 
-  printf ("%*sPangoFT2Face %p:\n"
-	  "%*s  lfp:\n",
-	  indent, "", face,
-	  indent, "");
-  
-  for (i = 0; i < face->n_fonts; i++)
-    printf ("%*s    PangoFT2OpenArgs:%s:%ld\n",
-	    indent, "", face->open_args[i]->pathname, face->face_indices[i]);
-  
-  printf ("%*s  description:\n"
-	  "%*s    family_name: %s\n"
-	  "%*s    style: %d\n"
-	  "%*s    variant: %d\n"
-	  "%*s    weight: %d\n"
-	  "%*s    stretch: %d\n"
-	  "%*s  coverage: %p\n",
-	  indent, "",
-	  indent, "", pango_font_description_get_family (face->description),
-	  indent, "", pango_font_description_get_style (face->description),
-	  indent, "", pango_font_description_get_variant (face->description),
-	  indent, "", pango_font_description_get_weight (face->description),
-	  indent, "", pango_font_description_get_stretch (face->description),
-	  indent, "", face->coverage);
-}
+  desc = pango_font_description_new ();
 
-static void
-pango_ft2_family_entry_dump (int             indent,
-			     PangoFT2Family *entry)
-{
-  GSList *tmp_list = entry->font_entries;
-  
-  printf ("%*sPangoFT2Family %p:\n"
-	  "%*s  family_name: %s\n"
-	  "%*s  font_entries:\n",
-	  indent, "", entry,
-	  indent, "", entry->family_name,
-	  indent, "");
+  g_assert (MiniXftPatternGetString (pattern, XFT_FAMILY, 0, &s) == MiniXftResultMatch);
 
-  while (tmp_list)
+  pango_font_description_set_family (desc, s);
+  
+  if (MiniXftPatternGetInteger (pattern, XFT_SLANT, 0, &i) == MiniXftResultMatch)
     {
-      PangoFT2Face *face = tmp_list->data;
-      
-      pango_ft2_face_dump (indent + 2, face);
-      tmp_list = tmp_list->next;
+      if (i == XFT_SLANT_ROMAN)
+	style = PANGO_STYLE_NORMAL;
+      else if (i == XFT_SLANT_OBLIQUE)
+	style = PANGO_STYLE_OBLIQUE;
+      else
+	style = PANGO_STYLE_ITALIC;
     }
-}
+  else
+    style = PANGO_STYLE_NORMAL;
 
-static void
-dump_family (gpointer key,
-	     gpointer value,
-	     gpointer user_data)
-{
-  PangoFT2Family *entry = value;
-  int indent = (int) user_data;
+  pango_font_description_set_style (desc, style);
 
-  pango_ft2_family_entry_dump (indent, entry);
-}
+  if (MiniXftPatternGetInteger (pattern, XFT_WEIGHT, 0, &i) == MiniXftResultMatch)
+    { 
+     if (i < XFT_WEIGHT_LIGHT)
+	weight = PANGO_WEIGHT_ULTRALIGHT;
+      else if (i < (XFT_WEIGHT_LIGHT + XFT_WEIGHT_MEDIUM) / 2)
+	weight = PANGO_WEIGHT_LIGHT;
+      else if (i < (XFT_WEIGHT_MEDIUM + XFT_WEIGHT_DEMIBOLD) / 2)
+	weight = PANGO_WEIGHT_NORMAL;
+      else if (i < (XFT_WEIGHT_DEMIBOLD + XFT_WEIGHT_BOLD) / 2)
+	weight = 600;
+      else if (i < (XFT_WEIGHT_BOLD + XFT_WEIGHT_BLACK) / 2)
+	weight = PANGO_WEIGHT_BOLD;
+      else
+	weight = PANGO_WEIGHT_ULTRABOLD;
+    }
+  else
+    weight = PANGO_WEIGHT_NORMAL;
 
-/**
- * pango_ft2_fontmap_dump:
- * @indent: the indent to use.
- * @fontmap: a #PangoFT2FontMap.
- *
- * Writes a description of the given font map to stdout.
- **/
-void
-pango_ft2_fontmap_dump (int           indent,
-			PangoFontMap *fontmap)
-{
-  PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (fontmap);
+  pango_font_description_set_weight (desc, weight);
+  
+  pango_font_description_set_variant (desc, PANGO_VARIANT_NORMAL);
+  pango_font_description_set_stretch (desc, PANGO_STRETCH_NORMAL);
 
-  printf ("%*sPangoFT2FontMap %p:\n",
-	  indent, "", ft2fontmap);
-  g_hash_table_foreach (ft2fontmap->families, dump_family, (gpointer) (indent + 2));
+  return desc;
 }
 
-/* 
- * PangoFT2Face
- */
 
 static PangoFontDescription *
 pango_ft2_face_describe (PangoFontFace *face)
 {
-  PangoFT2Face *ft2face = PANGO_FT2_FACE (face);
+  PangoFT2Face *ft2face = (PangoFT2Face *) face;
+  PangoFT2Family *ft2family = ft2face->family;
+  PangoFontDescription *desc = NULL;
+  MiniXftResult res;
+  MiniXftPattern *match_pattern;
+  MiniXftPattern *result_pattern;
+
+  match_pattern = MiniXftPatternBuild (NULL,
+				       XFT_ENCODING, MiniXftTypeString, "iso10646-1",
+				       XFT_FAMILY, MiniXftTypeString, ft2family->family_name,
+				       XFT_CORE, MiniXftTypeBool, False,
+				       XFT_STYLE, MiniXftTypeString, ft2face->style,
+				       NULL);
+  g_assert (match_pattern);
+  
+  result_pattern = MiniXftFontMatch ((Display *)1, 0, match_pattern, &res);
+  if (result_pattern)
+    {
+      desc = _pango_ft2_font_desc_from_pattern (result_pattern);
+      MiniXftPatternDestroy (result_pattern);
+    }
 
-  return pango_font_description_copy (ft2face->description);
+  MiniXftPatternDestroy (match_pattern);
+  
+  return desc;
 }
 
 static const char *
@@ -1034,18 +745,7 @@ pango_ft2_face_get_face_name (PangoFontF
 {
   PangoFT2Face *ft2face = PANGO_FT2_FACE (face);
 
-  if (!ft2face->face_name)
-    {
-      PangoFontDescription *desc = pango_font_face_describe (face);
-      
-      pango_font_description_unset_fields (desc,
-					   PANGO_FONT_MASK_FAMILY | PANGO_FONT_MASK_SIZE);
-
-      ft2face->face_name = pango_font_description_to_string (desc);
-      pango_font_description_free (desc);
-    }
-
-  return ft2face->face_name;
+  return ft2face->style;
 }
 
 static void
@@ -1082,113 +782,33 @@ pango_ft2_face_get_type (void)
   
   return object_type;
 }
-
-PangoCoverage *
-pango_ft2_face_get_coverage (PangoFT2Face      *face,
-			     PangoFont         *font,
-			     PangoLanguage     *language)
-{
-  guint32 ch;
-  PangoMap *shape_map;
-  PangoCoverage *coverage;
-  PangoCoverage *result;
-  PangoCoverageLevel font_level;
-  PangoMapEntry *map_entry;
-  GHashTable *coverage_hash;
-  PangoFontDescription *description;
-  FILE *cache_file;
-  char *file_name;
-  char *cache_file_name;
-  char *font_as_filename;
-  guchar *buf;
-  size_t buflen;
-
-  if (face)
-    if (face->coverage)
-      {
-	pango_coverage_ref (face->coverage);
-	return face->coverage;
-      }
-
-  description = pango_font_describe (font);
-  font_as_filename = pango_font_description_to_filename (description);
-  file_name = g_strconcat (font_as_filename, ".",
-			   language ? pango_language_to_string (language) : "",
-			   NULL);
-  g_free (font_as_filename);
-  cache_file_name = g_build_filename (pango_get_sysconf_subdirectory (),
-				      "cache.ft2", file_name, NULL);
-  g_free (file_name);
-  pango_font_description_free (description);
-
-  PING (("trying to load %s", cache_file_name));
-  result = NULL;
-  if (g_file_get_contents (cache_file_name, (char **)&buf, &buflen, NULL))
-    {
-      result = pango_coverage_from_bytes (buf, buflen);
-      g_free (buf);
-    }
 
-  if (!result)
-    {
-      result = pango_coverage_new ();
-
-      coverage_hash = g_hash_table_new (g_str_hash, g_str_equal);
-  
-      shape_map = pango_ft2_get_shaper_map (language);
-
-      for (ch = 0; ch < 65536; ch++)
-	{
-	  map_entry = pango_map_get_entry (shape_map, ch);
-	  if (map_entry->info)
-	    {
-	      coverage = g_hash_table_lookup (coverage_hash, map_entry->info->id);
-	      if (!coverage)
-		{
-		  PangoEngineShape *engine = (PangoEngineShape *)pango_map_get_engine (shape_map, ch);
-		  coverage = engine->get_coverage (font, language);
-		  g_hash_table_insert (coverage_hash, map_entry->info->id, coverage);
-		}
-	      
-	      font_level = pango_coverage_get (coverage, ch);
-	      if (font_level == PANGO_COVERAGE_EXACT && !map_entry->is_exact)
-		font_level = PANGO_COVERAGE_APPROXIMATE;
-
-	      if (font_level != PANGO_COVERAGE_NONE)
-		pango_coverage_set (result, ch, font_level);
-	    }
-	}
-
-      g_hash_table_foreach (coverage_hash, free_coverages_foreach, NULL);
-      g_hash_table_destroy (coverage_hash);
-
-      cache_file = fopen (cache_file_name, "wb");
-      if (cache_file)
-	{
-	  pango_coverage_to_bytes (result, &buf, &buflen);
-	  PING (("saving %d bytes to %s", buflen, cache_file_name));
-	  fwrite (buf, buflen, 1, cache_file);
-	  fclose (cache_file);
-	  g_free (buf);
-	}
-    }
+void
+_pango_ft2_font_map_set_coverage (PangoFontMap  *fontmap,
+				  const char    *name,
+				  PangoCoverage *coverage)
+{
+  PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
 
-  if (face)
-    {
-      face->coverage = result;
-      pango_coverage_ref (result);
-    }
+  g_hash_table_insert (ft2fontmap->coverage_hash, g_strdup (name),
+		       pango_coverage_ref (coverage));
+}
 
-  g_free (cache_file_name);
+PangoCoverage *
+_pango_ft2_font_map_get_coverage (PangoFontMap  *fontmap,
+				  const char    *name)
+{
+  PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
 
-  return result;
+  return g_hash_table_lookup (ft2fontmap->coverage_hash, name);
 }
 
-void
-pango_ft2_face_remove (PangoFT2Face *face,
-		       PangoFont    *font)
+FT_Library
+_pango_ft2_font_map_get_library (PangoFontMap *fontmap)
 {
-  face->cached_fonts = g_slist_remove (face->cached_fonts, font);
+  PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
+  
+  return ft2fontmap->library;
 }
 
 /*
@@ -1197,26 +817,48 @@ pango_ft2_face_remove (PangoFT2Face *fac
 
 static void
 pango_ft2_family_list_faces (PangoFontFamily  *family,
-			   PangoFontFace  ***faces,
-			   int              *n_faces)
+			     PangoFontFace  ***faces,
+			     int              *n_faces)
 {
   PangoFT2Family *ft2family = PANGO_FT2_FAMILY (family);
 
-  *n_faces = g_slist_length (ft2family->font_entries);
-  if (faces)
+  if (ft2family->n_faces < 0)
     {
-      GSList *tmp_list;
-      int i = 0;
+      MiniXftFontSet *fontset;
+      int i;
+      
+      fontset = MiniXftListFonts ((Display *)1, 0,
+				  XFT_ENCODING, MiniXftTypeString, "iso10646-1",
+				  XFT_FAMILY, MiniXftTypeString, ft2family->family_name,
+				  XFT_CORE, MiniXftTypeBool, False,
+				  NULL,
+				  XFT_STYLE,
+				  NULL);
       
-      *faces = g_new (PangoFontFace *, *n_faces);
+      ft2family->n_faces = fontset->nfont;
+      ft2family->faces = g_new (PangoFT2Face *, ft2family->n_faces);
 
-      tmp_list = ft2family->font_entries;
-      while (tmp_list)
+      for (i = 0; i < fontset->nfont; i++)
 	{
-	  (*faces)[i++] = tmp_list->data;
-	  tmp_list = tmp_list->next;
+	  char *s;
+	  MiniXftResult res;
+	  
+	  res = MiniXftPatternGetString (fontset->fonts[i], XFT_STYLE, 0, &s);
+	  g_assert (res == MiniXftResultMatch);
+	  
+	  ft2family->faces[i] = g_object_new (PANGO_FT2_TYPE_FACE, NULL);
+	  ft2family->faces[i]->style = g_strdup (s);
+	  ft2family->faces[i]->family = ft2family;
 	}
+      
+      MiniXftFontSetDestroy (fontset);
     }
+  
+  if (n_faces)
+    *n_faces = ft2family->n_faces;
+  
+  if (faces)
+    *faces = g_memdup (ft2family->faces, ft2family->n_faces * sizeof (PangoFontFace *));
 }
 
 const char *
Index: pango/pangoft2-private.h
===================================================================
RCS file: /cvs/gnome/pango/pango/pangoft2-private.h,v
retrieving revision 1.11
diff -u -p -r1.11 pangoft2-private.h
--- pango/pangoft2-private.h	2001/09/18 21:32:09	1.11
+++ pango/pangoft2-private.h	2001/11/18 01:40:36
@@ -25,6 +25,7 @@
 
 #include "pango-modules.h"
 #include "pangoft2.h"
+#include "mini-xft/MiniXft.h"
 
 /* Debugging... */
 /*#define DEBUGGING 1*/
@@ -52,43 +53,27 @@
    ((d) - PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6)
 #define PANGO_UNITS_26_6(d) (PANGO_SCALE_26_6 * (d))
 
-typedef struct _PangoFT2OA PangoFT2OA;
-typedef struct _PangoFT2Font PangoFT2Font;
+typedef struct _PangoFT2Font      PangoFT2Font;
 typedef struct _PangoFT2GlyphInfo PangoFT2GlyphInfo;
-typedef struct _PangoFT2Face PangoFT2Face;
-typedef struct _PangoFT2SubfontInfo PangoFT2SubfontInfo;
+typedef struct _PangoFT2Face      PangoFT2Face;
+typedef struct _PangoFT2Family    PangoFT2Family;
 
-struct _PangoFT2OA
-{
-  FT_Open_Args *open_args;
-  FT_Long face_index;
-};
 
 struct _PangoFT2Font
 {
   PangoFont font;
 
-  /* A PangoFT2Font consists of one or several FT2 fonts (faces) that
-   * are assumed to blend visually well, and cover separate parts of
-   * the Unicode characters. The FT2 faces are not kept unnecessarily
-   * open, thus also we keep both the FT_Open_Args (and face index),
-   * and FT_Face.
-   */
-  PangoFT2OA **oa;
-  FT_Face *faces;
-  int n_fonts;
+  MiniXftPattern *font_pattern;
+  FT_Face face;
 
   int size;
 
-  GSList *metrics_by_lang;
-
   PangoFontMap *fontmap;
+  PangoFontDescription *description;
+  
   /* If TRUE, font is in cache of recently unused fonts and not otherwise
-   * in use.
-   */
+   * in use. */
   gboolean in_cache;
-  
-  PangoFT2Face *entry;
 
   GHashTable *glyph_info;
 };
@@ -103,27 +88,30 @@ struct _PangoFT2Face
 {
   PangoFontFace parent_instance;
   
-  FT_Open_Args **open_args;
-  FT_Long *face_indices;
-  int n_fonts;
-  PangoFontDescription *description;
-  PangoCoverage *coverage;
-  char *face_name;
-
-  GSList *cached_fonts;
+  PangoFT2Family *family;
+  char *style;
 };
 
-PangoMap      *pango_ft2_get_shaper_map          (PangoLanguage     *language);
-PangoCoverage *pango_ft2_face_get_coverage       (PangoFT2Face      *face,
-						  PangoFont         *font,
-						  PangoLanguage     *language);
-void           pango_ft2_face_remove             (PangoFT2Face      *face,
-						  PangoFont         *font);
-FT_Library    *pango_ft2_fontmap_get_library     (PangoFontMap      *fontmap);
-void           pango_ft2_fontmap_cache_add       (PangoFontMap      *fontmap,
-						  PangoFT2Font      *ft2font);
-void           pango_ft2_fontmap_cache_remove    (PangoFontMap      *fontmap,
-						  PangoFT2Font      *ft2font);
-const char    *pango_ft2_ft_strerror             (FT_Error           error);
+PangoFT2Font * _pango_ft2_font_new                (PangoFontMap                *font,
+						   MiniXftPattern              *pattern);
+PangoMap      *_pango_ft2_get_shaper_map          (PangoLanguage     *language);
+void           _pango_ft2_font_map_set_coverage   (PangoFontMap                *fontmap,
+						   const char                  *name,
+						   PangoCoverage               *coverage);
+PangoCoverage *_pango_ft2_font_map_get_coverage   (PangoFontMap                *fontmap,
+						   const char                  *name);
+void           _pango_ft2_face_remove             (PangoFT2Face      *face,
+						   PangoFont         *font);
+FT_Library     _pango_ft2_font_map_get_library    (PangoFontMap      *fontmap);
+void           _pango_ft2_font_map_cache_add      (PangoFontMap      *fontmap,
+						   PangoFT2Font      *ft2font);
+void           _pango_ft2_font_map_cache_remove    (PangoFontMap      *fontmap,
+						   PangoFT2Font      *ft2font);
+void           _pango_ft2_font_map_add            (PangoFontMap      *fontmap,
+						   PangoFT2Font      *ft2font);
+void           _pango_ft2_font_map_remove         (PangoFontMap      *fontmap,
+						   PangoFT2Font      *ft2font);
+const char    *_pango_ft2_ft_strerror             (FT_Error           error);
+PangoFontDescription *_pango_ft2_font_desc_from_pattern (MiniXftPattern *pattern);
 
 #endif /* __PANGOFT2_PRIVATE_H__ */
Index: pango/pangoft2.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangoft2.c,v
retrieving revision 1.26
diff -u -p -r1.26 pangoft2.c
--- pango/pangoft2.c	2001/10/26 21:41:02	1.26
+++ pango/pangoft2.c	2001/11/18 01:40:38
@@ -46,12 +46,6 @@ typedef struct _PangoFT2FontClass   Pang
 typedef struct _PangoFT2MetricsInfo PangoFT2MetricsInfo;
 typedef struct _PangoFT2ContextInfo PangoFT2ContextInfo;
 
-struct _PangoFT2MetricsInfo
-{
-  const char *sample_str;
-  PangoFontMetrics *metrics;
-};
-
 struct _PangoFT2FontClass
 {
   PangoFontClass parent_class;
@@ -66,9 +60,6 @@ static void pango_ft2_font_finalize   (G
 
 static PangoFontDescription *pango_ft2_font_describe          (PangoFont            *font);
 
-static PangoCoverage *       pango_ft2_font_get_coverage      (PangoFont            *font,
-							       PangoLanguage        *language);
-
 static PangoEngineShape *    pango_ft2_font_find_shaper       (PangoFont            *font,
 							       PangoLanguage        *language,
 							       guint32               ch);
@@ -87,67 +78,88 @@ static void                  pango_ft2_g
 							       gboolean       	    *fg_set,
 							       PangoAttrColor 	    *bg_color,
 							       gboolean       	    *bg_set);
+
+static GType pango_ft2_font_get_type (void);
 
-static char *
-pango_ft2_open_args_describe (PangoFT2OA *oa)
+PangoFT2Font *
+_pango_ft2_font_new (PangoFontMap    *fontmap,
+		     MiniXftPattern  *pattern)
 {
-  if (oa->open_args->flags & ft_open_memory)
-    return g_strdup_printf ("memory at %p", oa->open_args->memory_base);
-  else if (oa->open_args->flags == ft_open_pathname)
-    return g_strdup_printf ("file '%s'", oa->open_args->pathname);
-  else if (oa->open_args->flags & ft_open_stream)
-    return g_strdup_printf ("FT_Stream at %p", oa->open_args->stream);
-  else
-    return g_strdup_printf ("open_args at %p, face_index %ld", oa->open_args, oa->face_index);
+  PangoFT2Font *ft2font;
+  double d;
+
+  g_return_val_if_fail (fontmap != NULL, NULL);
+  g_return_val_if_fail (pattern != NULL, NULL);
+
+  ft2font = (PangoFT2Font *)g_object_new (PANGO_TYPE_FT2_FONT, NULL);
+
+  ft2font->fontmap = fontmap;
+  ft2font->font_pattern = pattern;
+  
+  g_object_ref (G_OBJECT (fontmap));
+  ft2font->description = _pango_ft2_font_desc_from_pattern (pattern);
+  ft2font->face = NULL;
+
+  if (MiniXftPatternGetDouble (pattern, XFT_PIXEL_SIZE, 0, &d) == MiniXftResultMatch)
+    ft2font->size = d*PANGO_SCALE;
+
+  _pango_ft2_font_map_add (ft2font->fontmap, ft2font);
+
+  return ft2font;
 }
 
+
 /**
- * pango_ft2_get_face:
+ * pango_ft2_font_get_face:
  * @font: a #PangoFont
- * @subfont_index: the index of a subfont
  * 
- * Looks up a subfont in a #PangoFT2Font and returns a pointer to the 
- * native FreeType2 FT_Face structure. This may be useful if you want
- * to use FreeType2 functions directly.
+ * Returns the native FreeType2 FT_Face structure used for this PangoFont.
+ * This may be useful if you want to use FreeType2 functions directly.
  * 
- * Return value: a pointer to a #FT_Face structure.
+ * Return value: a pointer to a #FT_Face structure, with the size set correctly
  **/
 FT_Face
-pango_ft2_get_face (PangoFont      *font,
-		    PangoFT2Subfont subfont_index)
+pango_ft2_font_get_face (PangoFont      *font)
 {
   PangoFT2Font *ft2font = (PangoFT2Font *)font;
-  PangoFT2FontCache *cache;
   FT_Face face;
   FT_Error error;
+  MiniXftPattern *pattern;
+  char *filename;
+  int id;
+
+  pattern = ft2font->font_pattern;
 
-  if (subfont_index < 1 || subfont_index > ft2font->n_fonts)
+  if (!ft2font->face)
     {
-      g_warning ("Invalid subfont %d", subfont_index);
-      return NULL;
+      if (MiniXftPatternGetString (pattern, XFT_FILE, 0, &filename) != MiniXftResultMatch)
+	goto bail0;
+    
+      if (MiniXftPatternGetInteger (pattern, XFT_INDEX, 0, &id) != MiniXftResultMatch)
+	goto bail0;
+    
+      error = FT_New_Face (_pango_ft2_font_map_get_library (ft2font->fontmap),
+			   filename, id, &ft2font->face);
+      ft2font->face->generic.data = 0;
     }
+ bail0:
   
-  if (!ft2font->faces[subfont_index-1])
+  if (!ft2font->face)
     {
-      cache = pango_ft2_font_map_get_font_cache (ft2font->fontmap);
-  
-      ft2font->faces[subfont_index-1] =
-	pango_ft2_font_cache_load (cache,
-				   ft2font->oa[subfont_index-1]->open_args,
-				   ft2font->oa[subfont_index-1]->face_index);
-
-      if (!ft2font->faces[subfont_index-1])
-	g_warning ("Cannot load font for %s",
-		   pango_ft2_open_args_describe (ft2font->oa[subfont_index-1]));
+      g_warning ("Cannot load font\n");
+      return NULL;
     }
 
-  face = ft2font->faces[subfont_index-1];
+  face = ft2font->face;
 
   if (ft2font->size != GPOINTER_TO_UINT (face->generic.data))
     {
       face->generic.data = GUINT_TO_POINTER (ft2font->size);
 
-      error = FT_Set_Char_Size (face, 0, PANGO_PIXELS_26_6 (ft2font->size), 72, 72);
+      error = FT_Set_Char_Size (face,
+				PANGO_PIXELS_26_6 (ft2font->size),
+				PANGO_PIXELS_26_6 (ft2font->size),
+				0, 0);
       if (error)
 	g_warning ("Error in FT_Set_Char_Size: %d", error);
     }
@@ -157,6 +169,7 @@ pango_ft2_get_face (PangoFont      *font
 
 /**
  * pango_ft2_get_context:
+ * @dpi:  the dpi of the target device
  * 
  * Retrieves a #PangoContext appropriate for rendering with the PangoFT2
  * backend.
@@ -164,7 +177,7 @@ pango_ft2_get_face (PangoFont      *font
  * Return value: the new #PangoContext
  **/
 PangoContext *
-pango_ft2_get_context (void)
+pango_ft2_get_context (double dpi)
 {
   PangoContext *result;
   static gboolean registered_modules = FALSE;
@@ -177,9 +190,11 @@ pango_ft2_get_context (void)
       for (i = 0; _pango_included_ft2_modules[i].list; i++)
         pango_module_register (&_pango_included_ft2_modules[i]);
     }
+
+  MiniXftSetDPI (dpi);
   
   result = pango_context_new ();
-  pango_context_add_font_map (result, pango_ft2_font_map_for_display ());
+  pango_context_set_font_map (result, pango_ft2_font_map_for_display ());
 
   return result;
 }
@@ -215,14 +230,10 @@ pango_ft2_font_get_type (void)
 static void 
 pango_ft2_font_init (PangoFT2Font *ft2font)
 {
-  ft2font->oa = NULL;
-  ft2font->faces = NULL;
-
-  ft2font->n_fonts = 0;
+  ft2font->face = NULL;
 
-  ft2font->metrics_by_lang = NULL;
+  ft2font->size = 0;
 
-  ft2font->entry = NULL;
   ft2font->glyph_info = g_hash_table_new (NULL, NULL);
 }
 
@@ -245,54 +256,6 @@ pango_ft2_font_class_init (PangoFT2FontC
 }
 
 /**
- * pango_ft2_load_font:
- * @fontmap: a #PangoFontmap
- * @open_args: parameters that control loading
- * @face_indices: 
- * @n_fonts: 
- * @size: 
- * 
- * Loads a logical font based on XXX
- * 
- * Return value: a new #PangoFont
- **/
-PangoFont *
-pango_ft2_load_font (PangoFontMap  *fontmap,
-		     FT_Open_Args **open_args,
-		     FT_Long       *face_indices,
-		     int            n_fonts,
-		     int            size)
-{
-  PangoFT2Font *result;
-  int i;
-
-  g_return_val_if_fail (fontmap != NULL, NULL);
-  g_return_val_if_fail (open_args != NULL, NULL);
-  g_return_val_if_fail (face_indices != NULL, NULL);
-  g_return_val_if_fail (n_fonts > 0, NULL);
-
-  result = (PangoFT2Font *)g_object_new (PANGO_TYPE_FT2_FONT, NULL);
-  
-  result->fontmap = fontmap;
-  g_object_ref (G_OBJECT (result->fontmap));
-
-  result->oa = g_new (PangoFT2OA *, n_fonts);
-  result->faces = g_new (FT_Face, n_fonts);
-  result->n_fonts = n_fonts;
-  result->size = size;
-
-  for (i = 0; i < n_fonts; i++)
-    {
-      result->oa[i] = g_new (PangoFT2OA, 1);
-      result->oa[i]->open_args = open_args[i];
-      result->oa[i]->face_index = face_indices[i];
-      result->faces[i] = NULL;
-    }
-
-  return &result->font;
-}
- 
-/**
  * pango_ft2_render:
  * @bitmap:  the FreeType2 bitmap onto which to draw the string
  * @font:    the font in which to draw the string
@@ -315,7 +278,6 @@ pango_ft2_render (FT_Bitmap        *bitm
   int i;
   int x_position = 0;
   int ix, iy, ixoff, iyoff, y_start, y_limit, x_start, x_limit;
-  PangoFT2Subfont subfont_index;
   PangoGlyphInfo *gi;
   guchar *p, *q;
 
@@ -329,9 +291,8 @@ pango_ft2_render (FT_Bitmap        *bitm
     {
       if (gi->glyph)
 	{
-	  glyph_index = PANGO_FT2_GLYPH_INDEX (gi->glyph);
-	  subfont_index = PANGO_FT2_GLYPH_SUBFONT (gi->glyph);
-	  face = pango_ft2_get_face (font, subfont_index);
+	  glyph_index = gi->glyph;
+	  face = pango_ft2_font_get_face (font);
 
 	  if (face)
 	    {
@@ -418,15 +379,9 @@ pango_ft2_render (FT_Bitmap        *bitm
 }
 
 static FT_Glyph_Metrics *
-pango_ft2_get_per_char (PangoFont       *font,
-			PangoFT2Subfont  subfont_index,
-			guint32          glyph_index)
+pango_ft2_get_per_char (FT_Face   face,
+			guint32   glyph_index)
 {
-  FT_Face face;
-
-  if (!(face = pango_ft2_get_face (font, subfont_index)))
-    return NULL;
-
   FT_Load_Glyph (face, glyph_index, FT_LOAD_DEFAULT);
   return &face->glyph->metrics;
 }
@@ -439,22 +394,17 @@ pango_ft2_font_get_glyph_extents (PangoF
 {
   PangoFT2Font *ft2font = (PangoFT2Font *)font;
   PangoFT2GlyphInfo *info;
-  PangoFT2Subfont subfont_index;
-  FT_UInt glyph_index;
   FT_Glyph_Metrics *gm;
 
   info = g_hash_table_lookup (ft2font->glyph_info, GUINT_TO_POINTER (glyph));
 
   if (!info)
     {
+      FT_Face face = pango_ft2_font_get_face (font);
       info = g_new (PangoFT2GlyphInfo, 1);
-      glyph_index = PANGO_FT2_GLYPH_INDEX (glyph);
-      subfont_index = PANGO_FT2_GLYPH_SUBFONT (glyph);
       
-      if (glyph && (gm = pango_ft2_get_per_char (font, subfont_index, glyph_index)))
+      if (glyph && (gm = pango_ft2_get_per_char (face, glyph)))
 	{
-	  FT_Face face = pango_ft2_get_face (font, subfont_index);
-	  
 	  info->ink_rect.x = PANGO_UNITS_26_6 (gm->horiBearingX);
 	  info->ink_rect.width = PANGO_UNITS_26_6 (gm->width);
 	  info->ink_rect.y = -PANGO_UNITS_26_6 (gm->horiBearingY);
@@ -481,7 +431,7 @@ pango_ft2_font_get_glyph_extents (PangoF
 
       g_hash_table_insert (ft2font->glyph_info, GUINT_TO_POINTER(glyph), info);
     }
-  
+
   if (ink_rect)
     *ink_rect = info->ink_rect;
   if (logical_rect)
@@ -504,280 +454,67 @@ pango_ft2_font_get_kerning (PangoFont *f
 			    PangoGlyph left,
 			    PangoGlyph right)
 {
-  PangoFT2Subfont subfont_index;
   FT_Face face;
-  FT_UInt left_glyph_index, right_glyph_index;
   FT_Error error;
   FT_Vector kerning;
 
-  subfont_index = PANGO_FT2_GLYPH_SUBFONT (left);
-  if (PANGO_FT2_GLYPH_SUBFONT (right) != subfont_index)
-    return 0;
-  
-  face = pango_ft2_get_face (font, subfont_index);
+  face = pango_ft2_font_get_face (font);
   if (!face)
     return 0;
 
   if (!FT_HAS_KERNING (face))
     return 0;
-
-  left_glyph_index = PANGO_FT2_GLYPH_INDEX (left);
-  right_glyph_index = PANGO_FT2_GLYPH_INDEX (right);
 
-  if (!left_glyph_index || !right_glyph_index)
+  if (!left || !right)
     return 0;
 
-  error = FT_Get_Kerning (face, left_glyph_index, right_glyph_index,
+  error = FT_Get_Kerning (face, left, right,
 			  ft_kerning_default, &kerning);
   if (error != FT_Err_Ok)
     g_warning ("FT_Get_Kerning returns error: %s",
-	       pango_ft2_ft_strerror (error));
+	       _pango_ft2_ft_strerror (error));
 
   return PANGO_UNITS_26_6 (kerning.x);
 }
 
-/* Get composite font metrics for all subfonts in list
- */
-static void
-get_font_metrics_from_subfonts (PangoFont        *font,
-				GSList           *subfonts,
-				PangoFontMetrics *metrics)
-{
-  GSList *tmp_list = subfonts;
-  gboolean first = TRUE;
-  
-  metrics->ascent = 0;
-  metrics->descent = 0;
-  
-  while (tmp_list)
-    {
-      FT_Face face = pango_ft2_get_face (font, GPOINTER_TO_UINT (tmp_list->data));
-      
-      g_assert (face != NULL);
-
-      if (first)
-	{
-	  metrics->ascent = PANGO_UNITS_26_6 (face->size->metrics.ascender);
-	  metrics->descent = PANGO_UNITS_26_6 (-face->size->metrics.descender);
-	  metrics->approximate_digit_width = PANGO_UNITS_26_6 (face->size->metrics.max_advance);
-	  metrics->approximate_char_width = PANGO_UNITS_26_6 (face->size->metrics.max_advance);
-	  first = FALSE;
-	}
-      else
-	{
-	  metrics->ascent = MAX (PANGO_UNITS_26_6 (face->size->metrics.ascender), metrics->ascent);
-	  metrics->descent = MAX (PANGO_UNITS_26_6 (-face->size->metrics.descender), metrics->descent);
-	  metrics->approximate_digit_width =
-	    MAX (PANGO_UNITS_26_6 (face->size->metrics.max_advance), metrics->approximate_digit_width);
-	  metrics->approximate_char_width =
-	    MAX (PANGO_UNITS_26_6 (face->size->metrics.max_advance), metrics->approximate_char_width);
-	}
-
-      tmp_list = tmp_list->next;
-    }
-}
-
-/* Get composite font metrics for all subfonts resulting from shaping
- * string str with the given font
- *
- * This duplicates quite a bit of code from pango_itemize. This function
- * should die and we should simply add the ability to specify particular
- * fonts when itemizing.
- */
-static void
-get_font_metrics_from_string (PangoFont        *font,
-			      PangoLanguage    *language,
-			      const char       *str,
-			      PangoFontMetrics *metrics)
-{
-  const char *start, *p;
-  PangoGlyphString *glyph_str = pango_glyph_string_new ();
-  PangoEngineShape *shaper, *last_shaper;
-  int last_level;
-  gunichar *text_ucs4;
-  long n_chars, i;
-  guint8 *embedding_levels;
-  PangoDirection base_dir = PANGO_DIRECTION_LTR;
-  GSList *subfonts = NULL;
-
-  text_ucs4 = g_utf8_to_ucs4_fast (str, -1, &n_chars);
-  if (!text_ucs4)
-    return;
-
-  embedding_levels = g_new (guint8, n_chars);
-  pango_log2vis_get_embedding_levels (text_ucs4, n_chars, &base_dir,
-				      embedding_levels);
-  g_free (text_ucs4);
-
-  last_shaper = NULL;
-  last_level = 0;
-  
-  i = 0;
-  p = start = str;
-  while (*p)
-    {
-      gunichar wc = g_utf8_get_char (p);
-      p = g_utf8_next_char (p);
-	  
-      shaper = pango_font_find_shaper (font, language, wc);
-      if (p > start &&
-	  (shaper != last_shaper || last_level != embedding_levels[i]))
-	{
-	  PangoAnalysis analysis;
-	  int j;
-
-	  analysis.shape_engine = shaper;
-	  analysis.lang_engine = NULL;
-	  analysis.font = font;
-	  analysis.level = last_level;
-	  
-	  pango_shape (start, p - start, &analysis, glyph_str);
-
-	  for (j = 0; j < glyph_str->num_glyphs; j++)
-	    {
-	      PangoFT2Subfont subfont_index = PANGO_FT2_GLYPH_SUBFONT (glyph_str->glyphs[j].glyph);
-	      if (!g_slist_find (subfonts, GUINT_TO_POINTER ((guint)subfont_index)))
-		subfonts = g_slist_prepend (subfonts, GUINT_TO_POINTER ((guint)subfont_index));
-	    }
-	  
-	  start = p;
-	}
-
-      last_shaper = shaper;
-      last_level = embedding_levels[i];
-      i++;
-    }
-
-  get_font_metrics_from_subfonts (font, subfonts, metrics);
-  g_slist_free (subfonts);
-  
-  pango_glyph_string_free (glyph_str);
-  g_free (embedding_levels);
-
-  return;
-}
-
 static PangoFontMetrics *
 pango_ft2_font_get_metrics (PangoFont        *font,
 			    PangoLanguage    *language)
 {
-  PangoFT2MetricsInfo *info = NULL; /* Quiet GCC */
-  PangoFT2Font *ft2font = (PangoFT2Font *)font;
-  GSList *tmp_list;
-      
-  const char *sample_str = pango_language_get_sample_string (language);
+  PangoFontMetrics *metrics;
+  FT_Face face;
   
-  tmp_list = ft2font->metrics_by_lang;
-  while (tmp_list)
-    {
-      info = tmp_list->data;
-      
-      if (info->sample_str == sample_str)        /* We _don't_ need strcmp */
-	break;
+  face = pango_ft2_font_get_face (font);
 
-      tmp_list = tmp_list->next;
-    }
-
-  if (!tmp_list)
-    {
-      info = g_new (PangoFT2MetricsInfo, 1);
-      info->sample_str = sample_str;
-      info->metrics = pango_font_metrics_new ();
-      get_font_metrics_from_string (font, language, sample_str, info->metrics);
-
-      ft2font->metrics_by_lang = g_slist_prepend (ft2font->metrics_by_lang, info);
-    }
-      
-  return pango_font_metrics_ref (info->metrics);
-}
-
-/**
- * pango_ft2_n_subfonts:
- * @font: a #PangoFont
- *
- * Returns the number of subfonts in a #PangoFT2Font.
- *
- * Return value: the number of subfonts in @font
- **/
-int
-pango_ft2_n_subfonts (PangoFont *font)
-{
-  PangoFT2Font *ft2font = (PangoFT2Font *)font;
-
-  g_return_val_if_fail (font != NULL, 0);
+  metrics = pango_font_metrics_new ();
+  
+  metrics->ascent = PANGO_UNITS_26_6 (face->size->metrics.ascender);
+  metrics->descent = PANGO_UNITS_26_6 (-face->size->metrics.descender);
+  metrics->approximate_digit_width = PANGO_UNITS_26_6 (face->size->metrics.max_advance);
+  metrics->approximate_char_width = PANGO_UNITS_26_6 (face->size->metrics.max_advance);
 
-  return ft2font->n_fonts;
+  return pango_font_metrics_ref (metrics);
 }
 
-/**
- * pango_ft2_get_coverage:
- * @font: a #PangoFT2Font.
- * @language: the language to compute the coverage for.
- * 
- * Computes the coverage of @language by @font.
- * 
- * Returns: a newly-allocated #PangoCoverage.
- **/
-PangoCoverage *
-pango_ft2_get_coverage (PangoFont     *font,
-			PangoLanguage *language)
+static PangoCoverage *
+pango_ft2_calc_coverage (PangoFont     *font,
+			 PangoLanguage *language)
 {
-  PangoFT2Font *ft2font = (PangoFT2Font *)font;
-  PangoCoverage *result = pango_coverage_new ();
-  PangoCoverage *tmp;
-  PangoGlyph glyph;
+  PangoCoverage *result;
   FT_Face face;
   gunichar wc;
-  int i;
 
-  for (i = 1; i <= ft2font->n_fonts; i++)
+  result = pango_coverage_new ();
+  face = pango_ft2_font_get_face (font);
+  for (wc = 0; wc < 65536; wc++)
     {
-      tmp = pango_coverage_new ();
-      face = pango_ft2_get_face (font, i);
-      for (wc = 0; wc < 65536; wc++)
-	{
-	  glyph = PANGO_FT2_MAKE_GLYPH (i, wc);
-	  if (FT_Get_Char_Index (face, wc))
-	    pango_coverage_set (tmp, wc, PANGO_COVERAGE_EXACT);
-	}
-      pango_coverage_max (result, tmp);
-      pango_coverage_unref (tmp);
+      if (FT_Get_Char_Index (face, wc))
+	pango_coverage_set (result, wc, PANGO_COVERAGE_EXACT);
     }
 
   return result;
 }
 
-/**
- * pango_ft2_font_subfont_open_args:
- * @font: a #PangoFont which must be from the FT2 backend
- * @subfont_id: the id of a subfont within the @font
- * @open_args: pointer where to store the #FT_Open_Args for this subfont
- * @face_index: pointer where to store the face index for this subfont
- * 
- * Determine the FT_Open_Args and face index for the specified subfont.
- **/
-void
-pango_ft2_font_subfont_open_args (PangoFont        *font,
-				  PangoFT2Subfont   subfont_id,
-				  FT_Open_Args    **open_args,
-				  FT_Long          *face_index)
-{
-  PangoFT2Font *ft2font = (PangoFT2Font *)font;
-  *open_args = NULL;
-  *face_index = 0;
-
-  g_return_if_fail (font != NULL);
-  g_return_if_fail (PANGO_FT2_IS_FONT (font));
-
-  if (subfont_id < 1 || subfont_id > ft2font->n_fonts)
-    g_warning ("pango_ft2_font_subfont_open_args: Invalid subfont_id specified");
-  else
-    {
-      *open_args = ft2font->oa[subfont_id-1]->open_args;
-      *face_index = ft2font->oa[subfont_id-1]->face_index;
-    }
-}
-
 static void
 pango_ft2_font_dispose (GObject *object)
 {
@@ -788,7 +525,7 @@ pango_ft2_font_dispose (GObject *object)
    * freed.
    */
   if (!ft2font->in_cache && ft2font->fontmap)
-    pango_ft2_fontmap_cache_add (ft2font->fontmap, ft2font);
+    _pango_ft2_font_map_cache_add (ft2font->fontmap, ft2font);
 
   G_OBJECT_CLASS (parent_class)->dispose (object);
 }
@@ -802,39 +539,25 @@ pango_ft2_free_glyph_info_callback (gpoi
 }
 
 static void
-free_metrics_info (PangoFT2MetricsInfo *info)
-{
-  pango_font_metrics_unref (info->metrics);
-  g_free (info);
-}
-
-static void
 pango_ft2_font_finalize (GObject *object)
 {
   PangoFT2Font *ft2font = (PangoFT2Font *)object;
-  PangoFT2FontCache *cache = pango_ft2_font_map_get_font_cache (ft2font->fontmap);
-  int i;
 
-  PING ((" "));
+  _pango_ft2_font_map_remove (ft2font->fontmap, ft2font);
 
-  for (i = 0; i < ft2font->n_fonts; i++)
+  if (ft2font->face)
     {
-      if (ft2font->faces[i])
-	pango_ft2_font_cache_unload (cache, ft2font->faces[i]);
+      FT_Done_Face (ft2font->face);
+      ft2font->face = NULL;
     }
-
-  g_free (ft2font->oa);
-  g_free (ft2font->faces);
 
-  g_slist_foreach (ft2font->metrics_by_lang, (GFunc)free_metrics_info, NULL);
-  g_slist_free (ft2font->metrics_by_lang);
+  pango_font_description_free (ft2font->description);
+  MiniXftPatternDestroy (ft2font->font_pattern);
   
-  if (ft2font->entry)
-    pango_ft2_face_remove (ft2font->entry, (PangoFont *)ft2font);
-
   g_object_unref (G_OBJECT (ft2font->fontmap));
 
-  g_hash_table_foreach_remove (ft2font->glyph_info, pango_ft2_free_glyph_info_callback, NULL);
+  g_hash_table_foreach_remove (ft2font->glyph_info,
+			       pango_ft2_free_glyph_info_callback, NULL);
   g_hash_table_destroy (ft2font->glyph_info);
   
   G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -848,7 +571,7 @@ pango_ft2_font_describe (PangoFont *font
 
   ft2font = PANGO_FT2_FONT (font);
 
-  desc = pango_font_description_copy (ft2font->entry->description);
+  desc = pango_font_description_copy (ft2font->description);
   pango_font_description_set_size (desc, ft2font->size);
 
   return desc;
@@ -869,13 +592,31 @@ pango_ft2_get_shaper_map (PangoLanguage 
   return pango_find_map (language, engine_type_id, render_type_id);
 }
 
-static PangoCoverage *
+PangoCoverage *
 pango_ft2_font_get_coverage (PangoFont     *font,
 			     PangoLanguage *language)
 {
   PangoFT2Font *ft2font = (PangoFT2Font *)font;
+  char *filename = NULL;
+  FT_Face face;
+  PangoCoverage *coverage;
+  
+  MiniXftPatternGetString (ft2font->font_pattern, XFT_FILE, 0, &filename);
+  
+  coverage = _pango_ft2_font_map_get_coverage (ft2font->fontmap, filename);
+
+  if (coverage)
+    return pango_coverage_ref (coverage);
 
-  return pango_ft2_face_get_coverage (ft2font->entry, font, language);
+  /* Ugh, this is going to be SLOW */
+
+  face = pango_ft2_font_get_face (font);
+
+  coverage = pango_ft2_calc_coverage (font, language);
+
+  _pango_ft2_font_map_set_coverage (ft2font->fontmap, filename, coverage);
+      
+  return coverage;
 }
 
 static PangoEngineShape *
@@ -902,7 +643,7 @@ pango_ft2_font_find_shaper (PangoFont   
 PangoGlyph
 pango_ft2_get_unknown_glyph (PangoFont *font)
 {
-  return PANGO_FT2_MAKE_GLYPH (1, 0);
+  return 0;
 }
 
 /**
@@ -1140,7 +881,7 @@ ft_error_compare (const void *pkey,
 }
 
 const char *
-pango_ft2_ft_strerror (FT_Error error)
+_pango_ft2_ft_strerror (FT_Error error)
 {
 #undef __FTERRORS_H__
 #define FT_ERRORDEF( e, v, s )  { e, s },
Index: pango/pangoft2.h
===================================================================
RCS file: /cvs/gnome/pango/pango/pangoft2.h,v
retrieving revision 1.7
diff -u -p -r1.7 pangoft2.h
--- pango/pangoft2.h	2001/09/18 20:05:17	1.7
+++ pango/pangoft2.h	2001/11/18 01:40:38
@@ -31,15 +31,9 @@ G_BEGIN_DECLS
 
 #define PANGO_RENDER_TYPE_FT2 "PangoRenderFT2"
 
-/* Calls for applications
- */
-PangoContext  *pango_ft2_get_context        (void);
+/* Calls for applications */
+PangoContext  *pango_ft2_get_context        (double dpi);
 
-PangoFont     *pango_ft2_load_font          (PangoFontMap     *fontmap,
-					     FT_Open_Args    **open_args,
-					     FT_Long	      *face_indices,
-					     int               n_fonts,
-					     int               size);
 void           pango_ft2_render             (FT_Bitmap        *bitmap,
 					     PangoFont        *font,
 					     PangoGlyphString *glyphs,
@@ -54,50 +48,18 @@ void           pango_ft2_render_layout  
 					     int               x, 
 					     int               y);
 
+PangoFontMap      *pango_ft2_font_map_for_display    (void);
+void               pango_ft2_shutdown_display        (void);
 
 /* API for rendering modules
  */
-typedef guint16 PangoFT2Subfont;
-
-#define PANGO_FT2_MAKE_GLYPH(subfont,index) ((subfont)<<16 | (index))
-#define PANGO_FT2_GLYPH_SUBFONT(glyph) ((glyph)>>16)
-#define PANGO_FT2_GLYPH_INDEX(glyph) ((glyph) & 0xFFFF)
-
-int            pango_ft2_n_subfonts        (PangoFont       *font);
 PangoGlyph     pango_ft2_get_unknown_glyph (PangoFont       *font);
 int            pango_ft2_font_get_kerning  (PangoFont       *font,
 					    PangoGlyph       left,
 					    PangoGlyph       right);
-PangoCoverage *pango_ft2_get_coverage      (PangoFont       *font,
+FT_Face        pango_ft2_font_get_face     (PangoFont       *font);
+PangoCoverage *pango_ft2_font_get_coverage (PangoFont       *font,
 					    PangoLanguage   *language);
-FT_Face        pango_ft2_get_face          (PangoFont       *font,
-					    PangoFT2Subfont  subfont_index);
-
-/* API for libraries that want to use PangoFT2 mixed with classic
- * FT2 fonts.
- */
-typedef struct _PangoFT2FontCache PangoFT2FontCache;
-
-PangoFT2FontCache *pango_ft2_font_cache_new          (FT_Library         library);
-void               pango_ft2_font_cache_free         (PangoFT2FontCache *cache);
-FT_Face            pango_ft2_font_cache_load         (PangoFT2FontCache *cache,
-						      FT_Open_Args      *args,
-						      FT_Long            face_index);
-void               pango_ft2_font_cache_unload       (PangoFT2FontCache *cache,
-						      FT_Face            face);
-PangoFontMap      *pango_ft2_font_map_for_display    (void);
-void               pango_ft2_shutdown_display        (void);
-PangoFT2FontCache *pango_ft2_font_map_get_font_cache (PangoFontMap      *font_map);
-void               pango_ft2_font_subfont_open_args  (PangoFont         *font,
-						      PangoFT2Subfont    subfont_id,
-						      FT_Open_Args     **open_args,
-						      FT_Long           *face_index);
-
-
-/* Debugging.
- */
-void     pango_ft2_fontmap_dump (int           indent,
-				 PangoFontMap *fontmap);
 
 G_END_DECLS
 
Index: pango/pangowin32.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangowin32.c,v
retrieving revision 1.28
diff -u -p -r1.28 pangowin32.c
--- pango/pangowin32.c	2001/10/26 21:41:03	1.28
+++ pango/pangowin32.c	2001/11/18 01:40:39
@@ -129,7 +129,7 @@ pango_win32_get_context (void)
     }
 
   result = pango_context_new ();
-  pango_context_add_font_map (result, pango_win32_font_map_for_display ());
+  pango_context_set_font_map (result, pango_win32_font_map_for_display ());
 
   return result;
 }
Index: pango/pangox.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangox.c,v
retrieving revision 1.68
diff -u -p -r1.68 pangox.c
--- pango/pangox.c	2001/10/18 18:47:50	1.68
+++ pango/pangox.c	2001/11/18 01:40:44
@@ -275,7 +275,7 @@ pango_x_get_context (Display *display)
                            g_quark_from_static_string ("pango-x-info"),
                            info, (GDestroyNotify)g_free);
   
-  pango_context_add_font_map (result, pango_x_font_map_for_display (display));
+  pango_context_set_font_map (result, pango_x_font_map_for_display (display));
 
   return result;
 }
Index: pango/pangoxft-font.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangoxft-font.c,v
retrieving revision 1.15
diff -u -p -r1.15 pangoxft-font.c
--- pango/pangoxft-font.c	2001/11/05 17:45:32	1.15
+++ pango/pangoxft-font.c	2001/11/18 01:40:47
@@ -112,22 +112,21 @@ pango_xft_font_class_init (PangoXftFontC
 
 PangoXftFont *
 _pango_xft_font_new (PangoFontMap               *fontmap,
-		     const PangoFontDescription *description,
-		     XftFont                    *xft_font)
+		     XftPattern                 *pattern)
 {
   PangoXftFont *xfont;
 
   g_return_val_if_fail (fontmap != NULL, NULL);
-  g_return_val_if_fail (description != NULL, NULL);
-  g_return_val_if_fail (xft_font != NULL, NULL);
+  g_return_val_if_fail (pattern != NULL, NULL);
 
   xfont = (PangoXftFont *)g_object_new (PANGO_TYPE_XFT_FONT, NULL);
   
   xfont->fontmap = fontmap;
+  xfont->font_pattern = pattern;
   
   g_object_ref (G_OBJECT (fontmap));
-  xfont->description = pango_font_description_copy (description);
-  xfont->xft_font = xft_font;
+  xfont->description = _pango_xft_font_desc_from_pattern (pattern);
+  xfont->xft_font = NULL;
 
   _pango_xft_font_map_add (xfont->fontmap, xfont);
 
@@ -158,7 +157,7 @@ get_mini_font (PangoFont *font)
       xfont->mini_font = pango_font_map_load_font (xfont->fontmap, desc);
       pango_font_description_free (desc);
       
-      mini_xft = ((PangoXftFont *)xfont->mini_font)->xft_font;
+      mini_xft = pango_xft_font_get_font (xfont->mini_font);
       face = pango_xft_font_get_face (xfont->mini_font);
       
       for (i = 0 ; i < 16 ; i++)
@@ -247,6 +246,7 @@ pango_xft_real_render (Display          
 		       gint              y)
 {
   PangoXftFont *xfont = PANGO_XFT_FONT (font);
+  XftFont *xft_font = pango_xft_font_get_font (font);
   int i;
   int x_off = 0;
 
@@ -271,12 +271,12 @@ pango_xft_real_render (Display          
 	      int j, k;
 	      
 	      PangoFont *mini_font = get_mini_font (font);
-	      XftFont *mini_xft = ((PangoXftFont *)mini_font)->xft_font;
+	      XftFont *mini_xft = pango_xft_font_get_font (mini_font);
 	      FT_Face face = pango_xft_font_get_face (xfont->mini_font);
       
 	      glyph &= ~PANGO_XFT_UNKNOWN_FLAG;
 
-	      ys[0] = y + PANGO_PIXELS (glyphs->glyphs[i].geometry.y_offset) - xfont->xft_font->ascent + (xfont->xft_font->ascent + xfont->xft_font->descent - xfont->mini_height * 2 - xfont->mini_pad * 5) / 2;
+	      ys[0] = y + PANGO_PIXELS (glyphs->glyphs[i].geometry.y_offset) - xft_font->ascent + (xft_font->ascent + xft_font->descent - xfont->mini_height * 2 - xfont->mini_pad * 5) / 2;
 	      ys[1] = ys[0] + 2 * xfont->mini_pad + xfont->mini_height;
 	      ys[2] = ys[1] + xfont->mini_height + xfont->mini_pad;
 
@@ -307,12 +307,12 @@ pango_xft_real_render (Display          
 	  else
 	    {
 	      if (draw)
-		XftDrawString32 (draw, color, xfont->xft_font,
+		XftDrawString32 (draw, color, xft_font,
 				 x + PANGO_PIXELS (x_off + glyphs->glyphs[i].geometry.x_offset),
 				 y + PANGO_PIXELS (glyphs->glyphs[i].geometry.y_offset),
 				 &glyph, 1);
 	      else
-		XftRenderString32 (display, src_picture, xfont->xft_font->u.ft.font, dest_picture, 0, 0,
+		XftRenderString32 (display, src_picture, xft_font->u.ft.font, dest_picture, 0, 0,
 				   x + PANGO_PIXELS (x_off + glyphs->glyphs[i].geometry.x_offset),
 				   y + PANGO_PIXELS (glyphs->glyphs[i].geometry.y_offset),
 				   &glyph, 1);
@@ -385,13 +385,13 @@ static PangoFontMetrics *
 pango_xft_font_get_metrics (PangoFont        *font,
 			    PangoLanguage    *language)
 {
-  PangoXftFont *xfont = (PangoXftFont *)font;
   PangoFontMetrics *metrics = pango_font_metrics_new ();
+  XftFont *xft_font = pango_xft_font_get_font (font);
 
-  metrics->ascent = PANGO_SCALE * xfont->xft_font->ascent;
-  metrics->descent = PANGO_SCALE * xfont->xft_font->descent;
-  metrics->approximate_digit_width = PANGO_SCALE * xfont->xft_font->max_advance_width;
-  metrics->approximate_char_width = PANGO_SCALE * xfont->xft_font->max_advance_width;
+  metrics->ascent = PANGO_SCALE * xft_font->ascent;
+  metrics->descent = PANGO_SCALE * xft_font->descent;
+  metrics->approximate_digit_width = PANGO_SCALE * xft_font->max_advance_width;
+  metrics->approximate_char_width = PANGO_SCALE * xft_font->max_advance_width;
 
   return metrics;
 }
@@ -428,9 +428,11 @@ pango_xft_font_finalize (GObject *object
     g_object_unref (xfont->ot_info);
 
   pango_font_description_free (xfont->description);
-  
-  XftFontClose (display, xfont->xft_font);
+  XftPatternDestroy (xfont->font_pattern);
 
+  if (xfont->xft_font)
+    XftFontClose (display, xfont->xft_font);
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
@@ -447,15 +449,17 @@ pango_xft_font_get_coverage (PangoFont  
 			     PangoLanguage *language)
 {
   PangoXftFont *xfont = (PangoXftFont *)font;
-  const gchar *family = pango_font_description_get_family (xfont->description);
+  char *filename = NULL;
   FT_Face face;
   PangoCoverage *coverage;
   Display *display;
   int i;
   
   _pango_xft_font_map_get_info (xfont->fontmap, &display, NULL);
+
+  XftPatternGetString (xfont->font_pattern, XFT_FILE, 0, &filename);
   
-  coverage = _pango_xft_font_map_get_coverage (xfont->fontmap, family);
+  coverage = _pango_xft_font_map_get_coverage (xfont->fontmap, filename);
 
   if (coverage)
     return pango_coverage_ref (coverage);
@@ -473,7 +477,7 @@ pango_xft_font_get_coverage (PangoFont  
 	pango_coverage_set (coverage, i, PANGO_COVERAGE_EXACT);
     }
 
-  _pango_xft_font_map_set_coverage (xfont->fontmap, family, coverage);
+  _pango_xft_font_map_set_coverage (xfont->fontmap, g_strdup (filename), coverage);
       
   return coverage;
 }
@@ -485,6 +489,7 @@ pango_xft_font_get_glyph_extents (PangoF
 				  PangoRectangle   *logical_rect)
 {
   PangoXftFont *xfont = (PangoXftFont *)font;
+  XftFont *xft_font = pango_xft_font_get_font (font);
   XGlyphInfo extents;
   Display *display;
 
@@ -500,7 +505,7 @@ pango_xft_font_get_glyph_extents (PangoF
       if (ink_rect)
 	{
 	  ink_rect->x = 0;
-	  ink_rect->y = PANGO_SCALE * (- xfont->xft_font->ascent + (xfont->xft_font->ascent + xfont->xft_font->descent - xfont->mini_height * 2 - xfont->mini_pad * 5) / 2);
+	  ink_rect->y = PANGO_SCALE * (- xft_font->ascent + (xft_font->ascent + xft_font->descent - xfont->mini_height * 2 - xfont->mini_pad * 5) / 2);
 	  ink_rect->width = PANGO_SCALE * (xfont->mini_width * 2 + xfont->mini_pad * 5);
 	  ink_rect->height = PANGO_SCALE * (xfont->mini_height * 2 + xfont->mini_pad * 5);
 	}
@@ -508,14 +513,14 @@ pango_xft_font_get_glyph_extents (PangoF
       if (logical_rect)
 	{
 	  logical_rect->x = 0;
-	  logical_rect->y = - PANGO_SCALE * xfont->xft_font->ascent;
+	  logical_rect->y = - PANGO_SCALE * xft_font->ascent;
 	  logical_rect->width = PANGO_SCALE * (xfont->mini_width * 2 + xfont->mini_pad * 6);
-	  logical_rect->height = (xfont->xft_font->ascent + xfont->xft_font->descent) * PANGO_SCALE;
+	  logical_rect->height = (xft_font->ascent + xft_font->descent) * PANGO_SCALE;
 	}
     }
   else
     {
-      XftTextExtents32 (display, xfont->xft_font, &glyph, 1, &extents);
+      XftTextExtents32 (display, xft_font, &glyph, 1, &extents);
 
       if (ink_rect)
 	{
@@ -528,9 +533,9 @@ pango_xft_font_get_glyph_extents (PangoF
       if (logical_rect)
 	{
 	  logical_rect->x = 0;
-	  logical_rect->y = - xfont->xft_font->ascent * PANGO_SCALE;
+	  logical_rect->y = - xft_font->ascent * PANGO_SCALE;
 	  logical_rect->width = extents.xOff * PANGO_SCALE;
-	  logical_rect->height = (xfont->xft_font->ascent + xfont->xft_font->descent) * PANGO_SCALE;
+	  logical_rect->height = (xft_font->ascent + xft_font->descent) * PANGO_SCALE;
 	}
     }
 }
@@ -573,11 +578,34 @@ XftFont *
 pango_xft_font_get_font (PangoFont *font)
 {
   PangoXftFont *xfont;
+  Display *display;
+  int screen;
+  FT_Face face;
+  FT_Error error;
+  int charmap;
 
   g_return_val_if_fail (PANGO_XFT_IS_FONT (font), NULL);
   
   xfont = PANGO_XFT_FONT (font);
 
+  if (xfont->xft_font == NULL)
+    {
+      _pango_xft_font_map_get_info (xfont->fontmap, &display, &screen);
+
+      xfont->xft_font = XftFontOpenPattern (display, xfont->font_pattern);
+
+      face = xfont->xft_font->u.ft.font->face;
+
+      /* There should be a unicode encoding, since we queried for it */
+      for (charmap = 0; charmap < face->num_charmaps; charmap++)
+	if (face->charmaps[charmap]->encoding == ft_encoding_unicode)
+	  break;
+  
+      g_assert (charmap != face->num_charmaps);
+  
+      error = FT_Set_Charmap(face, face->charmaps[charmap]);
+    }
+  
   return xfont->xft_font;
 }
 
@@ -633,16 +661,16 @@ pango_xft_font_get_unknown_glyph (PangoF
 FT_Face
 pango_xft_font_get_face (PangoFont *font)
 {
-  PangoXftFont *xfont;
+  XftFont *xft_font;
 
   g_return_val_if_fail (PANGO_XFT_IS_FONT (font), NULL);
 
-  xfont = PANGO_XFT_FONT (font);
+  xft_font = pango_xft_font_get_font (font);
   
-  if (xfont->xft_font->core)
+  if (xft_font->core)
     return NULL;
   else
-    return xfont->xft_font->u.ft.font->face;
+    return xft_font->u.ft.font->face;
 }
 
 /**
Index: pango/pangoxft-fontmap.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pangoxft-fontmap.c,v
retrieving revision 1.8
diff -u -p -r1.8 pangoxft-fontmap.c
--- pango/pangoxft-fontmap.c	2001/10/26 21:41:03	1.8
+++ pango/pangoxft-fontmap.c	2001/11/18 01:40:49
@@ -19,11 +19,14 @@
  * Boston, MA 02111-1307, USA.
  */
 
+#include <string.h>
+
 #include "pango-fontmap.h"
 #include "pangoxft.h"
 #include "pangoxft-private.h"
 #include "modules.h"
 
+#include "X11/Xft/Xft.h"
 #include "X11/Xft/XftFreetype.h"
 
 /* Number of freed fonts */
@@ -32,6 +35,7 @@
 typedef struct _PangoXftFontMap      PangoXftFontMap;
 typedef struct _PangoXftFamily       PangoXftFamily;
 typedef struct _PangoXftFace         PangoXftFace;
+typedef struct _PangoXftPatternSet   PangoXftPatternSet;
 
 #define PANGO_TYPE_XFT_FONT_MAP              (pango_xft_font_map_get_type ())
 #define PANGO_XFT_FONT_MAP(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_XFT_FONT_MAP, PangoXftFontMap))
@@ -40,14 +44,20 @@ typedef struct _PangoXftFace         Pan
 struct _PangoXftFontMap
 {
   PangoFontMap parent_instance;
+
+  GHashTable *fontset_hash; /* Maps PangoFontDescription -> PangoXftPatternSet */
+  GHashTable *coverage_hash; /* Maps font file name -> PangoCoverage */
 
-  GHashTable *font_hash;
-  GHashTable *coverage_hash;
-  GQueue *freed_fonts;
+  GHashTable *fonts; /* Maps XftPattern -> PangoXftFont */
+  GQueue *freed_fonts; /* Fonts in fonts that has been freed */
 
+  /* List of all families availible */
   PangoXftFamily **families;
   int n_families;		/* -1 == uninitialized */
 
+  /* List of all fonts (XftPatterns) availible */
+  XftFontSet *font_set;
+
   Display *display;
   int screen;  
 };
@@ -67,6 +77,12 @@ struct _PangoXftFamily
   int n_faces;		/* -1 == uninitialized */
 };
 
+struct _PangoXftPatternSet
+{
+  int n_patterns;
+  XftPattern **patterns;
+};
+
 #define PANGO_XFT_TYPE_FACE              (pango_xft_face_get_type ())
 #define PANGO_XFT_FACE(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_XFT_TYPE_FACE, PangoXftFace))
 #define PANGO_XFT_IS_FACE(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_XFT_TYPE_FACE))
@@ -83,18 +99,23 @@ static GType    pango_xft_font_map_get_t
 GType           pango_xft_family_get_type     (void);
 GType           pango_xft_face_get_type       (void);
 
-static void       pango_xft_font_map_init          (PangoXftFontMap              *fontmap);
-static void       pango_xft_font_map_class_init    (PangoFontMapClass            *class);
-static void       pango_xft_font_map_finalize      (GObject                      *object);
-static PangoFont *pango_xft_font_map_load_font     (PangoFontMap                 *fontmap,
-						    const PangoFontDescription   *description);
-static void       pango_xft_font_map_list_families (PangoFontMap                 *fontmap,
-						    PangoFontFamily            ***families,
-						    int                          *n_families);
-
-static void pango_xft_font_map_cache_clear  (PangoXftFontMap *xfontmap);
-static void pango_xft_font_map_cache_remove (PangoFontMap    *fontmap,
-					     PangoXftFont    *xfont);
+static void          pango_xft_font_map_init          (PangoXftFontMap              *fontmap);
+static void          pango_xft_font_map_class_init    (PangoFontMapClass            *class);
+static void          pango_xft_font_map_finalize      (GObject                      *object);
+static PangoFont *   pango_xft_font_map_load_font     (PangoFontMap                 *fontmap,
+						       const PangoFontDescription   *description);
+static PangoFontset *pango_xft_font_map_load_fontset  (PangoFontMap                 *fontmap,
+						       const PangoFontDescription   *desc);
+static void          pango_xft_font_map_list_families (PangoFontMap                 *fontmap,
+						       PangoFontFamily            ***families,
+						       int                          *n_families);
+
+
+static void pango_xft_font_set_free         (PangoXftPatternSet *font_set);
+
+static void pango_xft_font_map_cache_clear  (PangoXftFontMap    *xfontmap);
+static void pango_xft_font_map_cache_remove (PangoFontMap       *fontmap,
+					     PangoXftFont       *xfont);
 
 static PangoFontClass *parent_class;	/* Parent class structure for PangoXftFontMap */
 
@@ -141,11 +162,98 @@ pango_xft_font_map_class_init (PangoFont
   
   object_class->finalize = pango_xft_font_map_finalize;
   class->load_font = pango_xft_font_map_load_font;
+  class->load_fontset = pango_xft_font_map_load_fontset;
   class->list_families = pango_xft_font_map_list_families;
 }
 
 static GSList *fontmaps = NULL;
 
+guint
+pango_xft_pattern_hash (XftPattern *pattern)
+{
+  char *str;
+  int i;
+  double d;
+  guint hash = 0;
+  
+  XftPatternGetString (pattern, XFT_FILE, 0, &str);
+  if (str)
+    hash = g_str_hash (str);
+
+  if (XftPatternGetInteger (pattern, XFT_INDEX, 0, &i) == XftResultMatch)
+    hash ^= i;
+
+  if (XftPatternGetDouble (pattern, XFT_PIXEL_SIZE, 0, &d) == XftResultMatch)
+    hash ^= (guint) (d*1000.0);
+
+  return hash;
+}
+
+gboolean
+pango_xft_pattern_equal (XftPattern *pattern1,
+			 XftPattern *pattern2)
+{
+  char *file1, *file2;
+  int index1, index2;
+  double size1, size2;
+  XftResult res1, res2;
+  int int1, int2;
+  Bool bool1, bool2;
+  
+  XftPatternGetString (pattern1, XFT_FILE, 0, &file1);
+  XftPatternGetString (pattern2, XFT_FILE, 0, &file2);
+
+  g_assert (file1 != NULL && file2 != NULL);
+
+  if (strcmp (file1, file2) != 0)
+    return FALSE;
+  
+  if (XftPatternGetInteger (pattern1, XFT_INDEX, 0, &index1) != XftResultMatch)
+    return FALSE;
+  
+  if (XftPatternGetInteger (pattern2, XFT_INDEX, 0, &index2) != XftResultMatch)
+    return FALSE;
+
+  if (index1 != index2)
+    return FALSE;
+
+  if (XftPatternGetDouble (pattern1, XFT_PIXEL_SIZE, 0, &size1) != XftResultMatch)
+    return FALSE;
+
+  if (XftPatternGetDouble (pattern2, XFT_PIXEL_SIZE, 0, &size2) != XftResultMatch)
+    return FALSE;
+
+  if (size1 != size2)
+    return FALSE;
+
+  res1 = XftPatternGetInteger (pattern1, XFT_RGBA, 0, &int1);
+  res2 = XftPatternGetInteger (pattern2, XFT_RGBA, 0, &int2);
+  if (res1 != res2 || (res1 == XftResultMatch && int1 != int2))
+    return FALSE;
+  
+  res1 = XftPatternGetBool (pattern1, XFT_ANTIALIAS, 0, &bool1);
+  res2 = XftPatternGetBool (pattern2, XFT_ANTIALIAS, 0, &bool2);
+  if (res1 != res2 || (res1 == XftResultMatch && bool1 != bool2))
+    return FALSE;
+  
+  res1 = XftPatternGetBool (pattern1, XFT_MINSPACE, 0, &bool1);
+  res2 = XftPatternGetBool (pattern2, XFT_MINSPACE, 0, &bool2);
+  if (res1 != res2 || (res1 == XftResultMatch && bool1 != bool2))
+    return FALSE;
+
+  res1 = XftPatternGetInteger (pattern1, XFT_SPACING, 0, &int1);
+  res2 = XftPatternGetInteger (pattern2, XFT_SPACING, 0, &int2);
+  if (res1 != res2 || (res1 == XftResultMatch && int1 != int2))
+    return FALSE;
+
+  res1 = XftPatternGetInteger (pattern1, XFT_CHAR_WIDTH, 0, &int1);
+  res2 = XftPatternGetInteger (pattern2, XFT_CHAR_WIDTH, 0, &int2);
+  if (res1 != res2 || (res1 == XftResultMatch && int1 != int2))
+    return FALSE;
+  
+  return TRUE;
+}
+
 static PangoFontMap *
 pango_xft_get_font_map (Display *display,
 			int      screen)
@@ -172,9 +280,15 @@ pango_xft_get_font_map (Display *display
   xfontmap->display = display;
   xfontmap->screen = screen;
 
-  xfontmap->font_hash = g_hash_table_new ((GHashFunc)pango_font_description_hash,
-					  (GEqualFunc)pango_font_description_equal);
-  xfontmap->coverage_hash = g_hash_table_new (g_str_hash, g_str_equal);
+  xfontmap->fonts = g_hash_table_new ((GHashFunc)pango_xft_pattern_hash,
+				      (GEqualFunc)pango_xft_pattern_equal);
+  xfontmap->fontset_hash = g_hash_table_new_full ((GHashFunc)pango_font_description_hash,
+						  (GEqualFunc)pango_font_description_equal,
+						  (GDestroyNotify)pango_font_description_free,
+						  (GDestroyNotify)pango_xft_font_set_free);
+  xfontmap->coverage_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+						   (GDestroyNotify)g_free,
+						   (GDestroyNotify)pango_coverage_unref);
   xfontmap->freed_fonts = g_queue_new ();
 
   fontmaps = g_slist_prepend (fontmaps, xfontmap);
@@ -211,21 +325,12 @@ pango_xft_get_context (Display *display,
     }
   
   result = pango_context_new ();
-  pango_context_add_font_map (result, pango_xft_get_font_map (display, screen));
+  pango_context_set_font_map (result, pango_xft_get_font_map (display, screen));
 
   return result;
 }
 
 static void
-coverage_foreach (gpointer key, gpointer value, gpointer data)
-{
-  PangoCoverage *coverage = value;
-
-  g_free (key);
-  pango_coverage_unref (coverage);
-}
-
-static void
 pango_xft_font_map_finalize (GObject *object)
 {
   PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (object);
@@ -233,30 +338,34 @@ pango_xft_font_map_finalize (GObject *ob
   fontmaps = g_slist_remove (fontmaps, object);
 
   g_queue_free (xfontmap->freed_fonts);
-  g_hash_table_destroy (xfontmap->font_hash);
-
-  g_hash_table_foreach (xfontmap->coverage_hash, coverage_foreach, NULL);
+  g_hash_table_destroy (xfontmap->fontset_hash);
   g_hash_table_destroy (xfontmap->coverage_hash);
   
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+
+/* Add a mapping from xfont->font_pattern to xfont */
 void
 _pango_xft_font_map_add (PangoFontMap *fontmap,
-			PangoXftFont *xfont)
+			 PangoXftFont *xfont)
 {
   PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
 
-  g_hash_table_insert (xfontmap->font_hash, xfont->description, xfont);
+  g_hash_table_insert (xfontmap->fonts,
+		       xfont->font_pattern,
+		       xfont);
 }
 
+/* Remove mapping from xfont->font_pattern to xfont */
 void
 _pango_xft_font_map_remove (PangoFontMap *fontmap,
 			   PangoXftFont *xfont)
 {
   PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
 
-  g_hash_table_remove (xfontmap->font_hash, xfont->description);
+  g_hash_table_remove (xfontmap->fonts,
+		       xfont->font_pattern);
 }
 
 static void
@@ -303,38 +412,10 @@ pango_xft_font_map_list_families (PangoF
     *families = g_memdup (xfontmap->families, xfontmap->n_families * sizeof (PangoFontFamily *));
 }
 
-static PangoFont *
-pango_xft_font_map_load_font (PangoFontMap               *fontmap,
-			      const PangoFontDescription *description)
+static int
+pango_xft_convert_weight (PangoWeight pango_weight)
 {
-  PangoXftFontMap *xfontmap = (PangoXftFontMap *)fontmap;
-  PangoXftFont *font;
-  PangoStyle pango_style;
-  int slant;
-  PangoWeight pango_weight;
   int weight;
-  XftFont *xft_font;
-
-  font = g_hash_table_lookup (xfontmap->font_hash, description);
-
-  if (font)
-    {
-      if (font->in_cache)
-	pango_xft_font_map_cache_remove (fontmap, font);
-      
-      return (PangoFont *)g_object_ref (G_OBJECT (font));
-    }
-
-  pango_style = pango_font_description_get_style (description);
-  
-  if (pango_style == PANGO_STYLE_ITALIC)
-    slant = XFT_SLANT_ITALIC;
-  else if (pango_style == PANGO_STYLE_OBLIQUE)
-    slant = XFT_SLANT_OBLIQUE;
-  else
-    slant = XFT_SLANT_ROMAN;
-
-  pango_weight = pango_font_description_get_weight (description);
   
   if (pango_weight < (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_LIGHT) / 2)
     weight = XFT_WEIGHT_LIGHT;
@@ -346,55 +427,199 @@ pango_xft_font_map_load_font (PangoFontM
     weight = XFT_WEIGHT_BOLD;
   else
     weight = XFT_WEIGHT_BLACK;
+  
+  return weight;
+}
+
+static int
+pango_xft_convert_slant (PangoStyle pango_style)
+{
+  int slant;
+  
+  if (pango_style == PANGO_STYLE_ITALIC)
+    slant = XFT_SLANT_ITALIC;
+  else if (pango_style == PANGO_STYLE_OBLIQUE)
+    slant = XFT_SLANT_OBLIQUE;
+  else
+    slant = XFT_SLANT_ROMAN;
+  
+  return slant;
+}
+
+
+static XftPattern *
+pango_xft_make_pattern (const PangoFontDescription *description)
+{
+  XftPattern *pattern;
+  PangoStyle pango_style;
+  int slant;
+  int weight;
+  
+  pango_style = pango_font_description_get_style (description);
 
+  slant = pango_xft_convert_slant (pango_style);
+  weight = pango_xft_convert_weight (pango_font_description_get_weight (description));
+  
   /* To fool Xft into not munging glyph indices, we open it as glyphs-fontspecific
    * then set the encoding ourself
    */
-  xft_font = XftFontOpen (xfontmap->display, xfontmap->screen,
-			  XFT_ENCODING, XftTypeString, "glyphs-fontspecific",
-			  XFT_CORE, XftTypeBool, False,
-			  XFT_FAMILY, XftTypeString,  pango_font_description_get_family (description),
-			  XFT_WEIGHT, XftTypeInteger, weight,
-			  XFT_SLANT,  XftTypeInteger, slant,
-			  XFT_SIZE, XftTypeDouble, (double)pango_font_description_get_size (description)/PANGO_SCALE,
-			  NULL);
+  pattern = XftPatternBuild (0,
+			     XFT_ENCODING, XftTypeString, "glyphs-fontspecific",
+			     XFT_CORE, XftTypeBool, False,
+			     XFT_FAMILY, XftTypeString,  pango_font_description_get_family (description),
+			     XFT_WEIGHT, XftTypeInteger, weight,
+			     XFT_SLANT,  XftTypeInteger, slant,
+			     XFT_SIZE, XftTypeDouble, (double)pango_font_description_get_size (description)/PANGO_SCALE,
+			     NULL);
+
+  return pattern;
+}
 
-  if (xft_font)
+static PangoFont *
+pango_xft_font_map_new_font (PangoFontMap  *fontmap,
+			     XftPattern    *match)
+{
+  PangoXftFontMap *xfontmap = (PangoXftFontMap *)fontmap;
+  PangoXftFont *font;
+  
+  /* Look up cache */
+  font = g_hash_table_lookup (xfontmap->fonts, match);
+  
+  if (font)
     {
-      FT_Face face;
-      FT_Error error;
+      /* Revive fonts from cache */
+      if (font->in_cache)
+	pango_xft_font_map_cache_remove (fontmap, font);
+      
+      return (PangoFont *)g_object_ref (G_OBJECT(font));
+    }
+  
+  return  (PangoFont *)_pango_xft_font_new (fontmap, XftPatternDuplicate (match));
+}
+
+static PangoFont *
+pango_xft_font_map_load_font (PangoFontMap               *fontmap,
+			      const PangoFontDescription *description)
+{
+  PangoXftFontMap *xfontmap = (PangoXftFontMap *)fontmap;
+  XftPattern *pattern, *match;
+  XftResult res;
+  
+  pattern = pango_xft_make_pattern (description);
       
-      int charmap;
+  match = XftFontMatch (xfontmap->display, xfontmap->screen, pattern, &res);
+  XftPatternDestroy (pattern);
+  
+  if (match)
+    return  pango_xft_font_map_new_font (fontmap, match);
+
+  return NULL;
+}
+
+
+static void
+pango_xft_font_set_free (PangoXftPatternSet *font_set)
+{
+  int i;
+  
+  for (i = 0; i < font_set->n_patterns; i++)
+    XftPatternDestroy (font_set->patterns[i]);
+
+  g_free (font_set);
+}
 
-      g_assert (!xft_font->core);
+static PangoFontset *
+pango_xft_font_map_load_fontset (PangoFontMap                 *fontmap,
+				 const PangoFontDescription   *desc)
+{
+  PangoXftFontMap *xfontmap = (PangoXftFontMap *)fontmap;
+  XftPattern *pattern, *pattern_copy;
+  XftPattern *match;
+  int i;
+  char *family, *family_res;
+  XftResult res;
+  int id;
+  GPtrArray *array;
+  PangoXftPatternSet *patterns;
+  int max_patterns;
+  PangoFontsetSimple *simple;
+
+  patterns = g_hash_table_lookup (xfontmap->fontset_hash, desc);
+
+  if (patterns == NULL)
+    {
+      if (xfontmap->font_set == NULL)
+	xfontmap->font_set = XftListFonts (xfontmap->display, xfontmap->screen,
+					   XFT_CORE, XftTypeBool, False,
+					   XFT_ENCODING, XftTypeString, "iso10646-1",
+					   NULL,
+					   XFT_FOUNDRY,  XFT_STYLE,      XFT_FAMILY,
+					   XFT_ENCODING, XFT_FILE,       XFT_INDEX,
+					   XFT_CORE,     XFT_FAMILY,     XFT_WEIGHT,
+					   XFT_SLANT,    XFT_CHAR_WIDTH, XFT_MATRIX, 
+					   XFT_RGBA,     XFT_ANTIALIAS,  XFT_MINSPACE,
+					   XFT_SPACING,  XFT_SIZE,
+					   NULL);
       
-      face = xft_font->u.ft.font->face;
+      pattern = pango_xft_make_pattern (desc);
 
-      for (charmap = 0; charmap < face->num_charmaps; charmap++)
-	if (face->charmaps[charmap]->encoding == ft_encoding_unicode)
-	  break;
+      XftConfigSubstitute (pattern);
+      XftDefaultSubstitute (xfontmap->display, xfontmap->screen, pattern);
 
-      if (charmap == face->num_charmaps)
-	goto error;
+      pattern_copy = XftPatternDuplicate (pattern);
 
-      error = FT_Set_Charmap(face, face->charmaps[charmap]);
+      array = g_ptr_array_new ();
       
-      if (error)
-	goto error;
+      patterns = g_new (PangoXftPatternSet, 1);
+
+      match = NULL;
+      id = 0;
+      while (XftPatternGetString (pattern, XFT_FAMILY, id++, &family) == XftResultMatch)
+	{
+	  XftPatternDel (pattern_copy, XFT_FAMILY);
+	  XftPatternAddString (pattern_copy, XFT_FAMILY, family);
+	  
+	  match = XftFontSetMatch (&xfontmap->font_set, 1, pattern_copy, &res);
+	  
+	  if (match &&
+	      XftPatternGetString (match, XFT_FAMILY, 0, &family_res) == XftResultMatch &&
+	      g_ascii_strcasecmp (family, family_res) == 0)
+	    {
+	      g_ptr_array_add (array, match);
+	      match = NULL;
+	    }
+	  if (match)
+	    XftPatternDestroy (match);
+	}
       
-      font = _pango_xft_font_new (fontmap, description, xft_font);
-    }
-  else
-    return NULL;
+      if (array->len == 0)
+	{
+	  match = XftFontSetMatch (&xfontmap->font_set, 1, pattern, &res);
+	  g_ptr_array_add (array, match);
+	}
 
-  return (PangoFont *)font;
+      XftPatternDestroy (pattern);
+      XftPatternDestroy (pattern_copy);
 
- error:
+      patterns->n_patterns = array->len;
+      patterns->patterns = g_ptr_array_free (array, FALSE);
+      
+      g_hash_table_insert (xfontmap->fontset_hash,
+			   pango_font_description_copy (desc),
+			   patterns);
+    }
 
-  XftFontClose (xfontmap->display, xft_font);
-  return NULL;
+  
+  simple = pango_fontset_simple_new ();
+
+  for (i = 0; i < patterns->n_patterns; i++)
+    pango_fontset_simple_append (simple,
+				 pango_xft_font_map_new_font (fontmap, patterns->patterns[i]));
+  
+  return PANGO_FONTSET (simple);
 }
 
+
 void
 _pango_xft_font_map_cache_add (PangoFontMap *fontmap,
 			       PangoXftFont *xfont)
@@ -482,8 +707,8 @@ _pango_xft_font_map_get_info (PangoFontM
  * PangoXftFace
  */
 
-static PangoFontDescription *
-font_desc_from_pattern (XftPattern *pattern)
+PangoFontDescription *
+_pango_xft_font_desc_from_pattern (XftPattern *pattern)
 {
   PangoFontDescription *desc;
   PangoStyle style;
@@ -560,7 +785,7 @@ pango_xft_face_describe (PangoFontFace *
   result_pattern = XftFontMatch (xfontmap->display, xfontmap->screen, match_pattern, &res);
   if (result_pattern)
     {
-      desc = font_desc_from_pattern (result_pattern);
+      desc = _pango_xft_font_desc_from_pattern (result_pattern);
       XftPatternDestroy (result_pattern);
     }
 
@@ -645,7 +870,8 @@ pango_xft_family_list_faces (PangoFontFa
 	  XftResult res;
 	  
 	  res = XftPatternGetString (fontset->fonts[i], XFT_STYLE, 0, &s);
-	  g_assert (res == XftResultMatch);
+	  if (res != XftResultMatch)
+	    s = "Regular";
 	  
 	  xfamily->faces[i] = g_object_new (PANGO_XFT_TYPE_FACE, NULL);
 	  xfamily->faces[i]->style = g_strdup (s);
Index: pango/pangoxft-private.h
===================================================================
RCS file: /cvs/gnome/pango/pango/pangoxft-private.h,v
retrieving revision 1.3
diff -u -p -r1.3 pangoxft-private.h
--- pango/pangoxft-private.h	2001/09/18 20:05:18	1.3
+++ pango/pangoxft-private.h	2001/11/18 01:40:49
@@ -32,7 +32,8 @@ typedef struct _PangoXftFont PangoXftFon
 struct _PangoXftFont
 {
   PangoFont parent_instance;
-  
+
+  XftPattern *font_pattern;
   XftFont *xft_font;
   PangoFont *mini_font;
   PangoFontMap *fontmap;
@@ -47,8 +48,7 @@ struct _PangoXftFont
 };
 
 PangoXftFont * _pango_xft_font_new              (PangoFontMap                *font,
-						 const PangoFontDescription  *description,
-						 XftFont                     *xft_font);
+						 XftPattern                  *pattern);
 void           _pango_xft_font_map_cache_add    (PangoFontMap                *fontmap,
 						 PangoXftFont                *xfont);
 void           _pango_xft_font_map_add          (PangoFontMap                *fontmap,
@@ -63,6 +63,8 @@ PangoCoverage *_pango_xft_font_map_get_c
 void           _pango_xft_font_map_get_info     (PangoFontMap                *fontmap,
 						 Display                    **display,
 						 int                         *screen);
+
+PangoFontDescription * _pango_xft_font_desc_from_pattern (XftPattern *pattern);
 
 G_END_DECLS
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]