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 (¤t_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