PangoXft and PangoFT2 patch from hell



Here is a patch that adds some generic font aliasing support to Pango. It 
also has code for the Xft backend to support font-aliases from the Xft 
config files. It also contains a rewrite of the pangoft2 backend to use 
the same config file format as the Xft backend so that you will always get 
the same fonts in Xft and FT2. The PangoFT2 internal API is also 
simplified because it doesn't have to do fontsets.

The minixft.tar.gz tarball must be unpacked in $SRC/pango/mini-xft, and 
contains a copy of Xft without X dependencies.

Warning. This patch is huge.

/ Alex

Attachment: minixft.tar.gz
Description: GNU Zip compressed data

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/10 23:21:23
@@ -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/10 23:21:23
@@ -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/10 23:21:23
@@ -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/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/10 23:21:23
@@ -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;
 
-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;
+  if (context->font_map)
+    g_object_unref (G_OBJECT (context->font_map));
 
-  g_free (value);
+  g_object_ref (G_OBJECT (font_map));
+  context->font_map = font_map;
 }
 
 /**
@@ -196,75 +181,22 @@ 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)
 	*families = NULL;
       
       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,16 +528,13 @@ 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];  
+  PangoFont **fonts;
+  PangoCoverage **coverages;  
 };
 
 #define FONT_SET_INITIALIZER { 0, }
@@ -663,7 +578,12 @@ font_set_free (FontSet *font_set)
 	  pango_coverage_unref (font_set->coverages[j]);
 	}
     }
+  g_free (font_set->fonts);
+  font_set->fonts = NULL;
 
+  g_free (font_set->coverages);
+  font_set->coverages = NULL;
+
   font_set->n_families = 0;
 }
 
@@ -673,87 +593,16 @@ font_set_load (FontSet                  
 	       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);
+  font_set->n_families = pango_font_map_load_fonts (context->font_map,
+						    desc,
+						    &font_set->fonts);
+
+  font_set->coverages = g_new (PangoCoverage *, font_set->n_families);
+  for (j = 0; j < font_set->n_families; j++)
+    font_set->coverages[j] = pango_font_get_coverage (font_set->fonts[j], language);
 }
 
 static gboolean
@@ -930,7 +779,7 @@ pango_context_get_metrics (PangoContext 
 			   PangoLanguage                *language)
 {
   FontSet current_fonts = FONT_SET_INITIALIZER;
-  PangoFontMetrics *raw_metrics[MAX_FAMILIES];
+  PangoFontMetrics **raw_metrics;
   PangoFontMetrics *metrics;
   const char *sample_str;
   const char *p;
@@ -950,10 +799,8 @@ pango_context_get_metrics (PangoContext 
       int count = 0;
 
       metrics = pango_font_metrics_new ();
+      raw_metrics = g_new0 (PangoFontMetrics *, current_fonts.n_families);
 
-      for (i=0; i < MAX_FAMILIES; i++)
-	raw_metrics[i] = NULL;
-  
       p = sample_str;
       while (*p)
 	{
@@ -976,12 +823,14 @@ pango_context_get_metrics (PangoContext 
 	  count++;
 	}
 
-      for (i=0; i < MAX_FAMILIES; i++)
+      for (i = 0; i < current_fonts.n_families; i++)
 	if (raw_metrics[i])
 	  pango_font_metrics_unref (raw_metrics[i]);
 
       metrics->approximate_char_width /= count;
       metrics->approximate_digit_width /= count;
+
+      g_free (raw_metrics);
     }
       
   font_set_free (&current_fonts);
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/10 23:21:23
@@ -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-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/10 23:21:23
@@ -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 int   pango_font_map_real_load_fonts (PangoFontMap                 *fontmap,
+					     const PangoFontDescription   *desc,
+					     PangoFont                  ***fonts);
+
 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_fonts = pango_font_map_real_load_fonts;
+}
+
 /**
  * pango_font_map_load_font:
  * @fontmap: a #PangoFontMap
@@ -84,4 +98,134 @@ pango_font_map_list_families (PangoFontM
   g_return_if_fail (fontmap != NULL);
 
   PANGO_FONT_MAP_GET_CLASS (fontmap)->list_families (fontmap, families, n_families);
+}
+
+int
+pango_font_map_load_fonts (PangoFontMap                 *fontmap,
+			   const PangoFontDescription   *desc,
+			   PangoFont                  ***fonts)
+{
+  g_return_val_if_fail (fontmap != NULL, 0);
+
+  return PANGO_FONT_MAP_GET_CLASS (fontmap)->load_fonts (fontmap, desc, fonts);
+}
+
+void
+pango_font_map_fontset_add_fonts (PangoFontMap          *fontmap,
+				  GPtrArray             *fonts,
+				  PangoFontDescription  *desc,
+				  char                  *family)
+{
+  char **aliases;
+  int n_aliases;
+  int j;
+  PangoFont *font;
+
+  n_aliases = pango_lookup_aliases (family,
+				    &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)
+	    g_ptr_array_add (fonts, font);
+	}
+    }
+  else
+    {
+      pango_font_description_set_family_static (desc, family);
+      font = pango_font_map_load_font (fontmap, desc);
+      if (font)
+	g_ptr_array_add (fonts, font);
+    }
+}
+
+static int
+pango_font_map_real_load_fonts (PangoFontMap                 *fontmap,
+				const PangoFontDescription   *desc,
+				PangoFont                  ***fonts_out)
+{
+  PangoFontDescription *tmp_desc = pango_font_description_copy_static (desc);
+  char **families;
+  int i, num;
+  GPtrArray *fonts;
+
+  families = g_strsplit (pango_font_description_get_family (desc), ",", -1);
+
+  num = 0;
+  while (families[num])
+    num++;
+
+  fonts = g_ptr_array_sized_new (num);
+  
+  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 (fonts->len == 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 (fonts->len == 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 (fonts->len == 0)
+    {
+      g_warning ("All font failbacks failed!!!!");
+      exit (1);
+    }
+
+  num = fonts->len;
+  *fonts_out = (PangoFont **)g_ptr_array_free (fonts, FALSE);
+ 
+  return num;
 }
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/10 23:21:23
@@ -35,6 +35,9 @@ typedef struct _PangoFontMap PangoFontMa
 GType      pango_font_map_get_type       (void) G_GNUC_CONST;
 PangoFont *pango_font_map_load_font     (PangoFontMap                 *fontmap,
 					 const PangoFontDescription   *desc);
+int        pango_font_map_load_fonts    (PangoFontMap                 *fontmap,
+					 const PangoFontDescription   *desc,
+					 PangoFont                  ***fonts);
 void       pango_font_map_list_families (PangoFontMap                 *fontmap,
 					 PangoFontFamily            ***families,
 					 int                          *n_families);
@@ -61,6 +64,9 @@ struct _PangoFontMapClass
   void       (*list_families) (PangoFontMap               *fontmap,
 			       PangoFontFamily          ***families,
 			       int                        *n_families);
+  int        (*load_fonts)    (PangoFontMap               *fontmap,
+			       const PangoFontDescription *desc,
+			       PangoFont                ***fonts);
 };
 
 #endif /* PANGO_ENABLE_BACKEND */
Index: pango/pango-utils.c
===================================================================
RCS file: /cvs/gnome/pango/pango/pango-utils.c,v
retrieving revision 1.28
diff -u -p -r1.28 pango-utils.c
--- pango/pango-utils.c	2001/11/02 14:21:19	1.28
+++ pango/pango-utils.c	2001/11/10 23:21:23
@@ -48,6 +48,15 @@
 
 #endif
 
+struct PangoAlias {
+  gchar *alias;
+  int n_families;
+  gchar **families;
+  gboolean visible; /* Do we want/need this? */
+};
+
+GHashTable *pango_aliases_ht = NULL;
+
 /**
  * pango_trim_string:
  * @str: a string
@@ -557,7 +566,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 +1259,238 @@ 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 gchar *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.
+ **/
+gint
+pango_lookup_aliases (const gchar   *fontname,
+		      gchar       ***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;
+      return alias->n_families;
+    }
+
+  *families = NULL;
+  return 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/10 23:21:23
@@ -38,6 +38,8 @@ gboolean pango_scan_int       (const cha
 
 #ifdef PANGO_ENABLE_BACKEND
 char *   pango_config_key_get (const char  *key);
+gint     pango_lookup_aliases (const char   *fontname,
+			       char       ***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/10 23:21:23
@@ -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/10 23:21:23
@@ -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,47 @@
 #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 _PangoFT2FontSet      PangoFT2FontSet;
 
 /* Number of freed fonts */
 #define MAX_FREED_FONTS 16
 
-struct _PangoFT2FontMap
+struct _PangoFT2Family
 {
-  PangoFontMap parent_instance;
-
-  FT_Library library;
+  PangoFontFamily parent_instance;
+  
+  PangoFT2FontMap *fontmap;
+  char *family_name;
 
-  PangoFT2FontCache *font_cache;
-  GQueue *freed_fonts;
+  PangoFT2Face **faces;
+  int n_faces;		/* -1 == uninitialized */
+};
 
-  /* Maps Pango family names to PangoFT2FamilyEntry structs */
-  GHashTable *families;
 
-  /* Maps the family and style of a face to a PangoFT2OA struct */
-  GHashTable *faces;
+struct _PangoFT2FontMap
+{
+  PangoFontMap parent_instance;
 
-  int n_fonts;
+  FT_Library library;
 
-  double resolution;		/* (points / pixel) * PANGO_SCALE */
+  GHashTable *font_hash; /* Maps PangoFontDescription -> XftPattern */
+  GHashTable *fontset_hash; /* Maps PangoFontDescription -> PangoXftFontSet */
+  GHashTable *coverage_hash; /* Maps font file name -> PangoCoverage */
+
+  GHashTable *fonts; /* Maps XftPattern -> PangoFT2Font */
+  GQueue *freed_fonts; /* Fonts in fonts that has been freed */
+
+  /* List of all families availible */
+  PangoFT2Family **families;
+  int n_families;		/* -1 == uninitialized */
 };
 
-struct _PangoFT2Family
+struct _PangoFT2FontSet
 {
-  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 ())
@@ -102,24 +110,23 @@ static void       pango_ft2_font_map_fin
 
 static PangoFont *pango_ft2_font_map_load_font     (PangoFontMap                 *fontmap,
 						    const PangoFontDescription   *description);
+static int        pango_ft2_font_map_load_fonts    (PangoFontMap                 *fontmap,
+						    const PangoFontDescription   *desc,
+						    PangoFont                  ***fonts_out);
+static void       pango_ft2_font_set_free          (PangoFT2FontSet              *font_set);
 
 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_cache_remove  (PangoFontMap                 *fontmap,
+						    PangoFT2Font                 *ft2font);
+static void       pango_ft2_font_map_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 +156,140 @@ 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 (PangoFT2FontSet *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->font_hash =
+    g_hash_table_new_full ((GHashFunc)pango_font_description_hash,
+			   (GEqualFunc)pango_font_description_equal,
+			   (GDestroyNotify)pango_font_description_free,
+			   (GDestroyNotify)MiniXftPatternDestroy);
+  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_fonts = pango_ft2_font_map_load_fonts;
+  class->list_families = pango_ft2_font_map_list_families;
 }
 
 /**
@@ -288,9 +304,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 +318,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 +333,298 @@ 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->font_hash);
+  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);
     }
   
-  g_slist_free (family_list);
+  if (n_families)
+    *n_families = ft2fontmap->n_families;
+  
+  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);
-    }
+  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;
+}
 
-  return ft2family;
+static int
+pango_ft2_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 PangoFont *
-pango_ft2_font_map_load_font (PangoFontMap               *fontmap,
-			      const PangoFontDescription *description)
+
+static MiniXftPattern *
+pango_ft2_make_pattern (const PangoFontDescription *description)
 {
-  PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
-  PangoFT2Family *family_entry;
-  PangoFont *result = NULL;
-  GSList *tmp_list;
-  gchar *name;
+  MiniXftPattern *pattern;
+  PangoStyle pango_style;
+  int slant;
+  int weight;
+  
+  pango_style = pango_font_description_get_style (description);
 
-  g_return_val_if_fail (description != NULL, NULL);
+  slant = pango_ft2_convert_slant (pango_style);
+  weight = pango_ft2_convert_weight (pango_font_description_get_weight (description));
   
-  name = g_ascii_strdown (pango_font_description_get_family (description), -1);
+  /* 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);
 
-  family_entry = g_hash_table_lookup (ft2fontmap->families, name);
-  g_free (name);
+  return pattern;
+}
+
+static PangoFont *
+pango_ft2_font_map_new_font (PangoFontMap    *fontmap,
+			     MiniXftPattern  *match)
+{
+  PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
+  PangoFT2Font *font;
+  
+  /* Look up cache */
+  font = g_hash_table_lookup (ft2fontmap->fonts, match);
   
-  if (family_entry)
+  if (font)
     {
-      PangoFT2Face *best_match = NULL;
+      /* Revive fonts from cache */
+      if (font->in_cache)
+	pango_ft2_font_map_cache_remove (fontmap, font);
       
-      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;
-	}
+      return (PangoFont *)g_object_ref (G_OBJECT(font));
+    }
+  
+  return  (PangoFont *)_pango_ft2_font_new (fontmap, MiniXftPatternDuplicate (match));
+}
 
-      if (best_match)
-	{
-	  GSList *tmp_list = best_match->cached_fonts;
 
-	  gint size = pango_font_description_get_size (description);
+static PangoFont *
+pango_ft2_font_map_load_font (PangoFontMap               *fontmap,
+			      const PangoFontDescription *description)
+{
+  PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
+  MiniXftPattern *pattern, *match;
+  MiniXftResult res;
 
-	  while (tmp_list)
-	    {
-	      PangoFT2Font *ft2font = tmp_list->data;
+  match = g_hash_table_lookup (ft2fontmap->font_hash, description);
 
-	      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 (match == NULL)
+    {
+      pattern = pango_ft2_make_pattern (description);
+      
+      match = MiniXftFontMatch ((Display *)1, 0, pattern, &res);
+      
+      MiniXftPatternDestroy (pattern);
 
-	  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;
-	    }
-	}
+      g_hash_table_insert (ft2fontmap->font_hash,
+			   pango_font_description_copy (description),
+			   match);
     }
 
-  return result;
+  if (match)
+    return  pango_ft2_font_map_new_font (fontmap, match);
+
+  return NULL;
 }
 
-static gboolean
-pango_ft2_font_map_read_alias_file (PangoFT2FontMap *ft2fontmap,
-				    const char      *filename)
+static int
+pango_ft2_font_map_load_fonts (PangoFontMap                 *fontmap,
+			       const PangoFontDescription   *desc,
+			       PangoFont                  ***fonts_out)
 {
-  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++;
+  PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
+  MiniXftPattern *pattern, *pattern_copy;
+  MiniXftPattern *match;
+  int i, n;
+  char *family, *family_res;
+  MiniXftResult res;
+  int id;
+  PangoFT2FontSet *patterns;
+  int max_patterns;
 
-	  if (!pango_skip_space (&p))
-	    continue;
+  patterns = g_hash_table_lookup (ft2fontmap->fontset_hash, desc);
 
-	  if (!pango_scan_string (&p, tmp_buf))
-	    goto error;
+  if (patterns == NULL)
+    {
+      pattern = pango_ft2_make_pattern (desc);
 
-	  face = g_object_new (PANGO_FT2_TYPE_FACE, NULL);
-	  face->n_fonts = 0;
-	  face->open_args = NULL;
-	  face->face_indices = NULL;
+      MiniXftConfigSubstitute (pattern);
+      MiniXftDefaultSubstitute ((Display *)1, 0, pattern);
 
-	  face->description = pango_font_description_new ();
+      pattern_copy = MiniXftPatternDuplicate (pattern);
 
-	  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;
+      patterns = g_new (PangoFT2FontSet, 1);
+      patterns->n_patterns = 0;
+      max_patterns = 5;
+      patterns->patterns = g_new (MiniXftPattern *, max_patterns);
 
-	  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);
+      MiniXftInit (0);
+      MiniXftInitFtLibrary ();
 	  
-	  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++;
-	    }
+      match = NULL;
+      id = 0;
+      while (MiniXftPatternGetString (pattern, XFT_FAMILY, id++, &family) == MiniXftResultMatch)
+	{
+	  MiniXftPatternDel (pattern_copy, XFT_FAMILY);
+	  MiniXftPatternAddString (pattern_copy, XFT_FAMILY, family);
 
-	  face->open_args = g_new (FT_Open_Args *, nfaces);
-	  face->face_indices = g_new (FT_Long, nfaces);
+	  match = MiniXftFontSetMatch (&_MiniXftFontSet, 1, pattern_copy, &res);
 	  
-	  for (i = 0; i < nfaces; i++)
+	  if (match &&
+	      MiniXftPatternGetString (match, XFT_FAMILY, 0, &family_res) == MiniXftResultMatch &&
+	      g_ascii_strcasecmp (family, family_res) == 0)
 	    {
-	      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
+	      if (patterns->n_patterns == max_patterns)
 		{
-		  face->open_args[face->n_fonts] = oa->open_args;
-		  face->face_indices[face->n_fonts] = oa->face_index;
-		  face->n_fonts++;
+		  max_patterns *= 2;
+		  patterns->patterns = g_realloc (patterns->patterns,
+						  sizeof(MiniXftPattern *) * max_patterns);
 		}
 
-	      pango_font_description_free (desc);
+	      patterns->patterns[patterns->n_patterns++] = match;
+	      match = NULL;
 	    }
-
-	  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 (match)
+	    MiniXftPatternDestroy (match);
 	}
-
-      if (ferror (infile))
-	g_warning ("Error reading file '%s': %s", filename, g_strerror(errno));
-
-      ret_val = TRUE;
-      goto out;
-
-    error:
-      if (face)
+      
+      if (patterns->n_patterns == 0)
 	{
-	  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);
+	  match = MiniXftFontSetMatch (&_MiniXftFontSet, 1, pattern, &res);
+	  patterns->patterns[patterns->n_patterns++] = match;
 	}
-
-      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);
+      MiniXftPatternDestroy (pattern);
+      MiniXftPatternDestroy (pattern_copy);
 
-      fclose (infile);
+      g_hash_table_insert (ft2fontmap->fontset_hash,
+			   pango_font_description_copy (desc),
+			   patterns);
     }
 
-  return ret_val;
-}
-
-static void
-pango_ft2_font_map_read_aliases (PangoFT2FontMap *ft2fontmap)
-{
-  char **files;
-  char *files_str = pango_config_key_get ("PangoFT2/AliasFiles");
-  int n;
-  gboolean read_aliasfile;
-
-  if (!files_str)
-    {
-      const char *home = g_get_home_dir ();
-      char *file1 = NULL;
-      char *file2;
-
-      if (home && *home)
-	file1 = g_build_filename  (home, ".pangoft2_aliases", NULL);
-      
-      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);
-    }
-
-  files = pango_split_file_list (files_str);
+  *fonts_out = g_new (PangoFont *, patterns->n_patterns);
   
   n = 0;
-  while (files[n])
-    n++;
-
-
-  read_aliasfile = FALSE;
+  for (i = 0; i < patterns->n_patterns; i++)
+    (*fonts_out)[n++] = pango_ft2_font_map_new_font (fontmap, patterns->patterns[i]);
   
-  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);
-}
-
-#if DEBUGGING
-
-static void
-pango_print_desc (PangoFontDescription *desc)
-{
-  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" : " ???"))))))))));
-}
-
-static void
-pango_ft2_print_oa (PangoFT2OA *oa)
-{
-  g_print ("%s:%ld", oa->open_args->pathname, oa->face_index);
-}
-
-#endif
-
-static void
-pango_ft2_insert_face (PangoFT2FontMap *ft2fontmap,
-		       FT_Face          face,
-		       const char      *path,
-		       int              face_index)
-{
-  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;
-
-  family_name = g_ascii_strdown (face->family_name, -1);
-
-  if (face->style_flags & FT_STYLE_FLAG_ITALIC)
-    style = PANGO_STYLE_ITALIC;
-  else
-    style = PANGO_STYLE_NORMAL;
-
-  variant = PANGO_VARIANT_NORMAL;
-
-  if (face->style_flags & FT_STYLE_FLAG_BOLD)
-    weight = PANGO_WEIGHT_BOLD;
-  else
-    weight = PANGO_WEIGHT_NORMAL;
-
-  stretch = PANGO_STRETCH_NORMAL;
-
-  if (face->style_name)
-    {
-      gchar **styles = g_strsplit (face->style_name, " ", 0);
-      gint i = 0;
-
-      while (styles[i])
-	{
-	  (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
-
-  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;
-
-      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)
-	{
-#if 0
-	  PING ((" family and description matched (!)"));
-#endif
-	  return;
-	}
-
-      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);
-
-  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);
-    }
-#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);
-
-  return PANGO_FT2_FONT_MAP (font_map)->font_cache;
+  return n;
 }
 
 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 +639,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 +661,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,117 +670,103 @@ 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 *
 pango_ft2_face_get_face_name (PangoFontFace *face)
 {
   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 +803,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 +838,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/10 23:21:23
@@ -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                  *match);
+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/10 23:21:23
@@ -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  *match)
 {
-  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 (match != NULL, NULL);
+
+  ft2font = (PangoFT2Font *)g_object_new (PANGO_TYPE_FT2_FONT, NULL);
+
+  ft2font->fontmap = fontmap;
+  ft2font->font_pattern = match;
+  
+  g_object_ref (G_OBJECT (fontmap));
+  ft2font->description = _pango_ft2_font_desc_from_pattern (match);
+  ft2font->face = NULL;
+
+  if (MiniXftPatternGetDouble (match, 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;
+  gchar *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/10 23:21:23
@@ -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/10 23:21:23
@@ -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/10 23:21:23
@@ -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/10 23:21:23
@@ -112,22 +112,21 @@ pango_xft_font_class_init (PangoXftFontC
 
 PangoXftFont *
 _pango_xft_font_new (PangoFontMap               *fontmap,
-		     const PangoFontDescription *description,
-		     XftFont                    *xft_font)
+		     XftPattern                 *match)
 {
   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 (match != NULL, NULL);
 
   xfont = (PangoXftFont *)g_object_new (PANGO_TYPE_XFT_FONT, NULL);
   
   xfont->fontmap = fontmap;
+  xfont->font_pattern = match;
   
   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 (match);
+  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);
+  gchar *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/10 23:21:23
@@ -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 _PangoXftFontSet      PangoXftFontSet;
 
 #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,21 @@ typedef struct _PangoXftFace         Pan
 struct _PangoXftFontMap
 {
   PangoFontMap parent_instance;
+
+  GHashTable *font_hash; /* Maps PangoFontDescription -> XftPattern */
+  GHashTable *fontset_hash; /* Maps PangoFontDescription -> PangoXftFontSet */
+  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 +78,12 @@ struct _PangoXftFamily
   int n_faces;		/* -1 == uninitialized */
 };
 
+struct _PangoXftFontSet
+{
+  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))
@@ -88,10 +105,15 @@ static void       pango_xft_font_map_cla
 static void       pango_xft_font_map_finalize      (GObject                      *object);
 static PangoFont *pango_xft_font_map_load_font     (PangoFontMap                 *fontmap,
 						    const PangoFontDescription   *description);
+static int        pango_xft_font_map_load_fonts    (PangoFontMap                 *fontmap,
+						    const PangoFontDescription   *desc,
+						    PangoFont                  ***fonts_out);
 static void       pango_xft_font_map_list_families (PangoFontMap                 *fontmap,
 						    PangoFontFamily            ***families,
 						    int                          *n_families);
 
+static void pango_xft_font_set_free         (PangoXftFontSet *font_set);
+
 static void pango_xft_font_map_cache_clear  (PangoXftFontMap *xfontmap);
 static void pango_xft_font_map_cache_remove (PangoFontMap    *fontmap,
 					     PangoXftFont    *xfont);
@@ -141,11 +163,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_fonts = pango_xft_font_map_load_fonts;
   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 +281,19 @@ 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->font_hash = g_hash_table_new_full ((GHashFunc)pango_font_description_hash,
+					       (GEqualFunc)pango_font_description_equal,
+					       (GDestroyNotify)pango_font_description_free,
+					       (GDestroyNotify)XftPatternDestroy);
+  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 +330,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);
@@ -234,29 +344,34 @@ pango_xft_font_map_finalize (GObject *ob
 
   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 +418,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 +433,212 @@ 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);
 
-  if (xft_font)
+  return pattern;
+}
+
+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);
       
-      int charmap;
+      return (PangoFont *)g_object_ref (G_OBJECT(font));
+    }
+  
+  return  (PangoFont *)_pango_xft_font_new (fontmap, XftPatternDuplicate (match));
+}
 
-      g_assert (!xft_font->core);
+static PangoFont *
+pango_xft_font_map_load_font (PangoFontMap               *fontmap,
+			      const PangoFontDescription *description)
+{
+  PangoXftFontMap *xfontmap = (PangoXftFontMap *)fontmap;
+  XftPattern *pattern, *match;
+  XftResult res;
+  
+  match = g_hash_table_lookup (xfontmap->font_hash, description);
+
+  if (match == NULL)
+    {
+      pattern = pango_xft_make_pattern (description);
       
-      face = xft_font->u.ft.font->face;
+      match = XftFontMatch (xfontmap->display, xfontmap->screen, pattern, &res);
+      XftPatternDestroy (pattern);
 
-      for (charmap = 0; charmap < face->num_charmaps; charmap++)
-	if (face->charmaps[charmap]->encoding == ft_encoding_unicode)
-	  break;
+      g_hash_table_insert (xfontmap->font_hash,
+			   pango_font_description_copy (description),
+			   match);
+    }
+
+  if (match)
+    return  pango_xft_font_map_new_font (fontmap, match);
+
+  return NULL;
+}
+
+
+static void
+pango_xft_font_set_free (PangoXftFontSet *font_set)
+{
+  int i;
+  
+  for (i = 0; i < font_set->n_patterns; i++)
+    XftPatternDestroy (font_set->patterns[i]);
 
-      if (charmap == face->num_charmaps)
-	goto error;
+  g_free (font_set);
+}
 
-      error = FT_Set_Charmap(face, face->charmaps[charmap]);
+static int
+pango_xft_font_map_load_fonts (PangoFontMap                 *fontmap,
+			       const PangoFontDescription   *desc,
+			       PangoFont                  ***fonts_out)
+{
+  PangoXftFontMap *xfontmap = (PangoXftFontMap *)fontmap;
+  XftPattern *pattern, *pattern_copy;
+  XftPattern *match;
+  int i, n;
+  char *family, *family_res;
+  XftResult res;
+  int id;
+  PangoXftFontSet *patterns;
+  int max_patterns;
+
+  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);
       
-      if (error)
-	goto error;
+      pattern = pango_xft_make_pattern (desc);
+
+      XftConfigSubstitute (pattern);
+      XftDefaultSubstitute (xfontmap->display, xfontmap->screen, pattern);
+
+      pattern_copy = XftPatternDuplicate (pattern);
+
+      patterns = g_new (PangoXftFontSet, 1);
+      patterns->n_patterns = 0;
+      max_patterns = 5;
+      patterns->patterns = g_new (XftPattern *, max_patterns);
+
+      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)
+	    {
+	      if (patterns->n_patterns == max_patterns)
+		{
+		  max_patterns *= 2;
+		  patterns->patterns = g_realloc (patterns->patterns, sizeof(XftPattern *) * max_patterns);
+		}
+
+	      patterns->patterns[patterns->n_patterns++] = match;
+	      match = NULL;
+	    }
+	  if (match)
+	    XftPatternDestroy (match);
+	}
       
-      font = _pango_xft_font_new (fontmap, description, xft_font);
-    }
-  else
-    return NULL;
+      if (patterns->n_patterns == 0)
+	{
+	  match = XftFontSetMatch (&xfontmap->font_set, 1, pattern, &res);
+	  patterns->patterns[patterns->n_patterns++] = match;
+	}
 
-  return (PangoFont *)font;
+      XftPatternDestroy (pattern);
+      XftPatternDestroy (pattern_copy);
 
- error:
 
-  XftFontClose (xfontmap->display, xft_font);
-  return NULL;
+      g_hash_table_insert (xfontmap->fontset_hash,
+			   pango_font_description_copy (desc),
+			   patterns);
+    }
+
+  
+  *fonts_out = g_new (PangoFont *, patterns->n_patterns);
+  
+  n = 0;
+  for (i = 0; i < patterns->n_patterns; i++)
+    (*fonts_out)[n++] = pango_xft_font_map_new_font (fontmap, patterns->patterns[i]);
+  
+  return n;
 }
 
+
 void
 _pango_xft_font_map_cache_add (PangoFontMap *fontmap,
 			       PangoXftFont *xfont)
@@ -482,8 +726,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 +804,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 +889,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/10 23:21:23
@@ -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                  *match);
 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]