summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--ChangeLog.pre-1-1011
-rw-r--r--ChangeLog.pre-1-211
-rw-r--r--ChangeLog.pre-1-411
-rw-r--r--ChangeLog.pre-1-611
-rw-r--r--ChangeLog.pre-1-811
-rw-r--r--pango/Makefile.am3
-rw-r--r--pango/pangofc-fontmap.c1054
-rw-r--r--pango/pangofc-fontmap.cI1054
-rw-r--r--pango/pangoft2-fontmap.c984
-rw-r--r--pango/pangoft2-private.h17
-rw-r--r--pango/pangoft2.c60
-rw-r--r--pango/pangoxft-font.c62
-rw-r--r--pango/pangoxft-fontmap.c1056
-rw-r--r--pango/pangoxft-private.h12
15 files changed, 2333 insertions, 2035 deletions
diff --git a/ChangeLog b/ChangeLog
index 334a706f..662dab15 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+Fri Aug 16 17:49:38 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.cI pango/pangoxft-fontmap.c
+ pango/pangoft2-fontmap.c pango/pangoxft-private.h
+ pango/pangoft2-private.h pango/pangoxft-font.c
+ pango/pangoft2.h: Move the common code between PangoXftFontmap
+ and PangoFT2Fontmap into a new file that is included from both
+ with appropriate #defines. This provides most of the
+ recent Xft backend improvements for the FT2 backend
+ as well.
+
Tue Aug 13 16:38:19 2002 Owen Taylor <otaylor@redhat.com>
* pango/pangoxft-fontmap.c (pango_xft_font_map_get_patterns):
diff --git a/ChangeLog.pre-1-10 b/ChangeLog.pre-1-10
index 334a706f..662dab15 100644
--- a/ChangeLog.pre-1-10
+++ b/ChangeLog.pre-1-10
@@ -1,3 +1,14 @@
+Fri Aug 16 17:49:38 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.cI pango/pangoxft-fontmap.c
+ pango/pangoft2-fontmap.c pango/pangoxft-private.h
+ pango/pangoft2-private.h pango/pangoxft-font.c
+ pango/pangoft2.h: Move the common code between PangoXftFontmap
+ and PangoFT2Fontmap into a new file that is included from both
+ with appropriate #defines. This provides most of the
+ recent Xft backend improvements for the FT2 backend
+ as well.
+
Tue Aug 13 16:38:19 2002 Owen Taylor <otaylor@redhat.com>
* pango/pangoxft-fontmap.c (pango_xft_font_map_get_patterns):
diff --git a/ChangeLog.pre-1-2 b/ChangeLog.pre-1-2
index 334a706f..662dab15 100644
--- a/ChangeLog.pre-1-2
+++ b/ChangeLog.pre-1-2
@@ -1,3 +1,14 @@
+Fri Aug 16 17:49:38 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.cI pango/pangoxft-fontmap.c
+ pango/pangoft2-fontmap.c pango/pangoxft-private.h
+ pango/pangoft2-private.h pango/pangoxft-font.c
+ pango/pangoft2.h: Move the common code between PangoXftFontmap
+ and PangoFT2Fontmap into a new file that is included from both
+ with appropriate #defines. This provides most of the
+ recent Xft backend improvements for the FT2 backend
+ as well.
+
Tue Aug 13 16:38:19 2002 Owen Taylor <otaylor@redhat.com>
* pango/pangoxft-fontmap.c (pango_xft_font_map_get_patterns):
diff --git a/ChangeLog.pre-1-4 b/ChangeLog.pre-1-4
index 334a706f..662dab15 100644
--- a/ChangeLog.pre-1-4
+++ b/ChangeLog.pre-1-4
@@ -1,3 +1,14 @@
+Fri Aug 16 17:49:38 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.cI pango/pangoxft-fontmap.c
+ pango/pangoft2-fontmap.c pango/pangoxft-private.h
+ pango/pangoft2-private.h pango/pangoxft-font.c
+ pango/pangoft2.h: Move the common code between PangoXftFontmap
+ and PangoFT2Fontmap into a new file that is included from both
+ with appropriate #defines. This provides most of the
+ recent Xft backend improvements for the FT2 backend
+ as well.
+
Tue Aug 13 16:38:19 2002 Owen Taylor <otaylor@redhat.com>
* pango/pangoxft-fontmap.c (pango_xft_font_map_get_patterns):
diff --git a/ChangeLog.pre-1-6 b/ChangeLog.pre-1-6
index 334a706f..662dab15 100644
--- a/ChangeLog.pre-1-6
+++ b/ChangeLog.pre-1-6
@@ -1,3 +1,14 @@
+Fri Aug 16 17:49:38 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.cI pango/pangoxft-fontmap.c
+ pango/pangoft2-fontmap.c pango/pangoxft-private.h
+ pango/pangoft2-private.h pango/pangoxft-font.c
+ pango/pangoft2.h: Move the common code between PangoXftFontmap
+ and PangoFT2Fontmap into a new file that is included from both
+ with appropriate #defines. This provides most of the
+ recent Xft backend improvements for the FT2 backend
+ as well.
+
Tue Aug 13 16:38:19 2002 Owen Taylor <otaylor@redhat.com>
* pango/pangoxft-fontmap.c (pango_xft_font_map_get_patterns):
diff --git a/ChangeLog.pre-1-8 b/ChangeLog.pre-1-8
index 334a706f..662dab15 100644
--- a/ChangeLog.pre-1-8
+++ b/ChangeLog.pre-1-8
@@ -1,3 +1,14 @@
+Fri Aug 16 17:49:38 2002 Owen Taylor <otaylor@redhat.com>
+
+ * pango/pangofc-fontmap.cI pango/pangoxft-fontmap.c
+ pango/pangoft2-fontmap.c pango/pangoxft-private.h
+ pango/pangoft2-private.h pango/pangoxft-font.c
+ pango/pangoft2.h: Move the common code between PangoXftFontmap
+ and PangoFT2Fontmap into a new file that is included from both
+ with appropriate #defines. This provides most of the
+ recent Xft backend improvements for the FT2 backend
+ as well.
+
Tue Aug 13 16:38:19 2002 Owen Taylor <otaylor@redhat.com>
* pango/pangoxft-fontmap.c (pango_xft_font_map_get_patterns):
diff --git a/pango/Makefile.am b/pango/Makefile.am
index 16bd611b..6924cba4 100644
--- a/pango/Makefile.am
+++ b/pango/Makefile.am
@@ -290,12 +290,13 @@ EXTRA_DIST = \
module-defs-ft2.c.win32 \
module-defs-win32.c.win32 \
module-defs.h \
+ pangofc-fontmap.cI \
pango.def \
pangowin32.def \
pangoft2.def \
makefile.mingw \
makefile.mingw.in \
- makefile.msc \
+ makefile.msc \
pango.rc \
pango.rc.in \
pangoft2.rc \
diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c
new file mode 100644
index 00000000..13b5c1cd
--- /dev/null
+++ b/pango/pangofc-fontmap.c
@@ -0,0 +1,1054 @@
+/* Pango
+ * pangofc-fontmap.cI: Common font handling between Xft and FT2
+ *
+ * Copyright (C) 2000,2001,2002 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This file is included by both pangoxft-fontmap.c and pangoft2-fontmap.c
+ * after making appropriate #defines for public symbols.
+ */
+
+/* Number of freed fonts to keep around */
+#define MAX_FREED_FONTS 128
+
+typedef struct _PangoFcCoverageKey PangoFcCoverageKey;
+typedef struct _PangoFcFace PangoFcFace;
+typedef struct _PangoFcPatternSet PangoFcPatternSet;
+
+#define PANGO_FC_TYPE_FAMILY (pango_fc_family_get_type ())
+#define PANGO_FC_FAMILY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_FC_TYPE_FAMILY, PangoFcFamily))
+#define PANGO_FC_IS_FAMILY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_FC_TYPE_FAMILY))
+
+#define PANGO_FC_TYPE_FACE (pango_fc_face_get_type ())
+#define PANGO_FC_FACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_FC_TYPE_FACE, PangoFcFace))
+#define PANGO_FC_IS_FACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_FC_TYPE_FACE))
+
+struct _PangoFcCoverageKey
+{
+ char *filename;
+ int id; /* needed to handle TTC files with multiple faces */
+};
+
+struct _PangoFcFace
+{
+ PangoFontFace parent_instance;
+
+ PangoFcFamily *family;
+ char *style;
+};
+
+struct _PangoFcFamily
+{
+ PangoFontFamily parent_instance;
+
+ PangoFcFontMap *fontmap;
+ char *family_name;
+
+ PangoFcFace **faces;
+ int n_faces; /* -1 == uninitialized */
+};
+
+struct _PangoFcPatternSet
+{
+ int n_patterns;
+ FcPattern **patterns;
+};
+
+GType pango_fc_font_map_get_type (void);
+static GType pango_fc_family_get_type (void);
+static GType pango_fc_face_get_type (void);
+
+static void pango_fc_font_map_init (PangoFcFontMap *fontmap);
+static void pango_fc_font_map_class_init (PangoFontMapClass *class);
+static void pango_fc_font_map_finalize (GObject *object);
+static PangoFont * pango_fc_font_map_load_font (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *description);
+static PangoFontset *pango_fc_font_map_load_fontset (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language);
+static void pango_fc_font_map_list_families (PangoFontMap *fontmap,
+ PangoFontFamily ***families,
+ int *n_families);
+
+
+static void pango_fc_font_set_free (PangoFcPatternSet *font_set);
+
+static void pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap);
+static void pango_fc_font_map_cache_remove (PangoFontMap *fontmap,
+ PangoFcFont *xfont);
+static void pango_fc_default_substitute (PangoFcFontMap *fontmap,
+ FcPattern *pattern);
+static void pango_fc_do_finalize (PangoFcFontMap *fontmap);
+
+static guint pango_fc_pattern_hash (FcPattern *pattern);
+static gboolean pango_fc_pattern_equal (FcPattern *pattern1,
+ FcPattern *pattern2);
+static guint pango_fc_coverage_key_hash (PangoFcCoverageKey *key);
+static gboolean pango_fc_coverage_key_equal (PangoFcCoverageKey *key1,
+ PangoFcCoverageKey *key2);
+
+static PangoFontClass *parent_class; /* Parent class structure for PangoFcFontMap */
+
+GType
+pango_fc_font_map_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (!object_type)
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (PangoFontMapClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_fc_font_map_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoFcFontMap),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) pango_fc_font_map_init,
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_MAP,
+ PANGO_FC_NAME "FontMap",
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+static void
+pango_fc_font_map_init (PangoFcFontMap *fcfontmap)
+{
+ fcfontmap->n_families = -1;
+
+ fcfontmap->fonts = g_hash_table_new ((GHashFunc)pango_fc_pattern_hash,
+ (GEqualFunc)pango_fc_pattern_equal);
+
+ fcfontmap->coverage_hash = g_hash_table_new_full ((GHashFunc)pango_fc_coverage_key_hash,
+ (GEqualFunc)pango_fc_coverage_key_equal,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)pango_coverage_unref);
+ fcfontmap->freed_fonts = g_queue_new ();
+}
+
+static void
+pango_fc_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_fc_font_map_finalize;
+ class->load_font = pango_fc_font_map_load_font;
+ class->load_fontset = pango_fc_font_map_load_fontset;
+ class->list_families = pango_fc_font_map_list_families;
+}
+
+static GSList *fontmaps = NULL;
+
+static guint
+pango_fc_pattern_hash (FcPattern *pattern)
+{
+#if 1
+ return FcPatternHash (pattern);
+#else
+ /* Hashing only part of the pattern can improve speed a bit.
+ */
+ char *str;
+ int i;
+ double d;
+ guint hash = 0;
+
+ FcPatternGetString (pattern, FC_FILE, 0, (FcChar8 **) &str);
+ if (str)
+ hash = g_str_hash (str);
+
+ if (FcPatternGetInteger (pattern, FC_INDEX, 0, &i) == FcResultMatch)
+ hash ^= i;
+
+ if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &d) == FcResultMatch)
+ hash ^= (guint) (d*1000.0);
+
+ return hash;
+#endif
+}
+
+static gboolean
+pango_fc_pattern_equal (FcPattern *pattern1,
+ FcPattern *pattern2)
+{
+ if (pattern1 == pattern2)
+ return TRUE;
+ else
+ return FcPatternEqual (pattern1, pattern2);
+}
+
+static guint
+pango_fc_coverage_key_hash (PangoFcCoverageKey *key)
+{
+ return g_str_hash (key->filename) ^ key->id;
+}
+
+static gboolean
+pango_fc_coverage_key_equal (PangoFcCoverageKey *key1,
+ PangoFcCoverageKey *key2)
+{
+ return key1->id == key2->id && strcmp (key1->filename, key2->filename) == 0;
+}
+
+typedef struct _FontsetHashListNode FontsetHashListNode;
+
+struct _FontsetHashListNode {
+ GHashTable *fontset_hash;
+ PangoLanguage *language;
+};
+
+/* Get the description => fontset map for a particular
+ * language tag.
+ */
+static GHashTable *
+pango_fc_get_fontset_hash (PangoFcFontMap *fcfontmap,
+ PangoLanguage *language)
+{
+ /* We treat NULL as a distinct language tag, but
+ * we should actually determine the real language
+ * tag it corresponds to to avoid duplicate entries
+ * in the list.
+ */
+ GList *tmp_list = fcfontmap->fontset_hash_list;
+ while (tmp_list)
+ {
+ FontsetHashListNode *node = tmp_list->data;
+ if (node->language == language)
+ {
+ if (tmp_list != fcfontmap->fontset_hash_list)
+ {
+ /* Put the found node at the beginning
+ */
+ fcfontmap->fontset_hash_list = g_list_remove_link (fcfontmap->fontset_hash_list, tmp_list);
+ fcfontmap->fontset_hash_list->prev = tmp_list;
+ tmp_list->next = fcfontmap->fontset_hash_list;
+ fcfontmap->fontset_hash_list = tmp_list;
+ }
+
+ return node->fontset_hash;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ {
+ FontsetHashListNode *node = g_new (FontsetHashListNode, 1);
+ fcfontmap->fontset_hash_list = g_list_prepend (fcfontmap->fontset_hash_list, node);
+
+ node->fontset_hash =
+ g_hash_table_new_full ((GHashFunc)pango_font_description_hash,
+ (GEqualFunc)pango_font_description_equal,
+ (GDestroyNotify)pango_font_description_free,
+ (GDestroyNotify)pango_fc_font_set_free);
+ node->language = language;
+
+ return node->fontset_hash;
+ }
+}
+
+static void
+pango_fc_clear_fontset_hash_list (PangoFcFontMap *fcfontmap)
+{
+ GList *tmp_list = fcfontmap->fontset_hash_list;
+ while (tmp_list)
+ {
+ FontsetHashListNode *node = tmp_list->data;
+
+ g_hash_table_destroy (node->fontset_hash);
+ g_free (node);
+
+ tmp_list = tmp_list->next;
+ }
+
+ g_list_free (fcfontmap->fontset_hash_list);
+ fcfontmap->fontset_hash_list = NULL;
+}
+
+static void
+pango_fc_font_map_finalize (GObject *object)
+{
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (object);
+
+ fontmaps = g_slist_remove (fontmaps, object);
+
+ if (fcfontmap->substitute_destroy)
+ fcfontmap->substitute_destroy (fcfontmap->substitute_data);
+
+ pango_fc_font_map_cache_clear (fcfontmap);
+ g_queue_free (fcfontmap->freed_fonts);
+ pango_fc_clear_fontset_hash_list (fcfontmap);
+ g_hash_table_destroy (fcfontmap->coverage_hash);
+
+ if (fcfontmap->fonts)
+ g_hash_table_destroy (fcfontmap->fonts);
+
+ pango_fc_do_finalize (fcfontmap);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+/* Add a mapping from xfont->font_pattern to xfont */
+void
+_pango_fc_font_map_add (PangoFontMap *fontmap,
+ PangoFcFont *xfont)
+{
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
+
+ g_hash_table_insert (fcfontmap->fonts,
+ xfont->font_pattern,
+ xfont);
+}
+
+/* Remove mapping from xfont->font_pattern to xfont */
+void
+_pango_fc_font_map_remove (PangoFontMap *fontmap,
+ PangoFcFont *xfont)
+{
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
+
+ g_hash_table_remove (fcfontmap->fonts,
+ xfont->font_pattern);
+}
+
+static PangoFcFamily *
+create_family (PangoFcFontMap *fcfontmap,
+ const char *family_name)
+{
+ PangoFcFamily *family = g_object_new (PANGO_FC_TYPE_FAMILY, NULL);
+ family->fontmap = fcfontmap;
+ family->family_name = g_strdup (family_name);
+
+ return family;
+}
+
+static gboolean
+is_alias_family (const char *family_name)
+{
+ switch (family_name[0])
+ {
+ case 'm':
+ case 'M':
+ return (g_ascii_strcasecmp (family_name, "monospace") == 0);
+ case 's':
+ case 'S':
+ return (g_ascii_strcasecmp (family_name, "sans") == 0 ||
+ g_ascii_strcasecmp (family_name, "serif") == 0);
+ }
+
+ return FALSE;
+}
+
+static void
+pango_fc_font_map_list_families (PangoFontMap *fontmap,
+ PangoFontFamily ***families,
+ int *n_families)
+{
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
+ FcFontSet *fontset;
+ int i;
+ int count;
+
+ if (fcfontmap->closed)
+ {
+ if (families)
+ *families = NULL;
+ if (n_families)
+ n_families = 0;
+
+ return;
+ }
+
+ if (fcfontmap->n_families < 0)
+ {
+ FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, NULL);
+ FcPattern *pat = FcPatternCreate ();
+
+ fontset = FcFontList (NULL, pat, os);
+
+ FcPatternDestroy (pat);
+ FcObjectSetDestroy (os);
+
+ fcfontmap->families = g_new (PangoFcFamily *, fontset->nfont + 3); /* 3 standard aliases */
+
+ count = 0;
+ for (i = 0; i < fontset->nfont; i++)
+ {
+ char *s;
+ FcResult res;
+
+ res = FcPatternGetString (fontset->fonts[i], FC_FAMILY, 0, (FcChar8 **) &s);
+ g_assert (res == FcResultMatch);
+
+ if (!is_alias_family (s))
+ fcfontmap->families[count++] = create_family (fcfontmap, s);
+ }
+
+ FcFontSetDestroy (fontset);
+
+ fcfontmap->families[count++] = create_family (fcfontmap, "Sans");
+ fcfontmap->families[count++] = create_family (fcfontmap, "Serif");
+ fcfontmap->families[count++] = create_family (fcfontmap, "Monospace");
+
+ fcfontmap->n_families = count;
+ }
+
+ if (n_families)
+ *n_families = fcfontmap->n_families;
+
+ if (families)
+ *families = g_memdup (fcfontmap->families, fcfontmap->n_families * sizeof (PangoFontFamily *));
+}
+
+static int
+pango_fc_convert_weight (PangoWeight pango_weight)
+{
+ int weight;
+
+ if (pango_weight < (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_LIGHT) / 2)
+ weight = FC_WEIGHT_LIGHT;
+ else if (pango_weight < (PANGO_WEIGHT_NORMAL + 600) / 2)
+ weight = FC_WEIGHT_MEDIUM;
+ else if (pango_weight < (600 + PANGO_WEIGHT_BOLD) / 2)
+ weight = FC_WEIGHT_DEMIBOLD;
+ else if (pango_weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2)
+ weight = FC_WEIGHT_BOLD;
+ else
+ weight = FC_WEIGHT_BLACK;
+
+ return weight;
+}
+
+static int
+pango_fc_convert_slant (PangoStyle pango_style)
+{
+ int slant;
+
+ if (pango_style == PANGO_STYLE_ITALIC)
+ slant = FC_SLANT_ITALIC;
+ else if (pango_style == PANGO_STYLE_OBLIQUE)
+ slant = FC_SLANT_OBLIQUE;
+ else
+ slant = FC_SLANT_ROMAN;
+
+ return slant;
+}
+
+
+static FcPattern *
+pango_fc_make_pattern (const PangoFontDescription *description)
+{
+ FcPattern *pattern;
+ PangoStyle pango_style;
+ int slant;
+ int weight;
+ char **families;
+ int i;
+
+ pango_style = pango_font_description_get_style (description);
+
+ slant = pango_fc_convert_slant (pango_style);
+ weight = pango_fc_convert_weight (pango_font_description_get_weight (description));
+
+ pattern = FcPatternBuild (0,
+ FC_WEIGHT, FcTypeInteger, weight,
+ FC_SLANT, FcTypeInteger, slant,
+ FC_SIZE, FcTypeDouble, (double)pango_font_description_get_size (description)/PANGO_SCALE,
+ NULL);
+
+ families = g_strsplit (pango_font_description_get_family (description), ",", -1);
+
+ for (i = 0; families[i]; i++)
+ FcPatternAddString (pattern, FC_FAMILY, families[i]);
+
+ g_strfreev (families);
+
+ return pattern;
+}
+
+static PangoFont *
+pango_fc_font_map_new_font (PangoFontMap *fontmap,
+ FcPattern *match)
+{
+ PangoFcFontMap *fcfontmap = (PangoFcFontMap *)fontmap;
+ PangoFcFont *font;
+
+ /* Returning NULL here actually violates a contract
+ * that loading load_font() will never return NULL.
+ * We probably should actually create a dummy
+ * font that doesn't draw anything and has empty
+ * metrics.
+ */
+ if (fcfontmap->closed)
+ return NULL;
+
+ /* Look up cache */
+ font = g_hash_table_lookup (fcfontmap->fonts, match);
+
+ if (font)
+ {
+ g_object_ref (font);
+
+ /* Revive font from cache */
+ if (font->in_cache)
+ pango_fc_font_map_cache_remove (fontmap, font);
+
+ return (PangoFont *)font;
+ }
+
+ FcPatternReference (match);
+ return (PangoFont *)_pango_fc_font_new (fontmap, match);
+}
+
+static PangoFcPatternSet *
+pango_fc_font_map_get_patterns (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language)
+{
+ PangoFcFontMap *fcfontmap = (PangoFcFontMap *)fontmap;
+ FcPattern *pattern, *font_pattern;
+ FcResult res;
+ int f;
+ PangoFcPatternSet *patterns;
+ FcFontSet *font_patterns;
+ GHashTable *fontset_hash;
+
+ if (!language && context)
+ language = pango_context_get_language (context);
+
+ fontset_hash = pango_fc_get_fontset_hash (fcfontmap, language);
+ patterns = g_hash_table_lookup (fontset_hash, desc);
+
+ if (patterns == NULL)
+ {
+ pattern = pango_fc_make_pattern (desc);
+ if (language)
+ FcPatternAddString (pattern, FC_LANG, (FcChar8 *) pango_language_to_string (language));
+
+ pango_fc_default_substitute (fcfontmap, pattern);
+
+ font_patterns = FcFontSort (NULL, pattern, FcTrue, 0, &res);
+
+ if (!font_patterns)
+ return NULL;
+
+ patterns = g_new (PangoFcPatternSet, 1);
+ patterns->patterns = g_new (FcPattern *, font_patterns->nfont);
+ patterns->n_patterns = 0;
+
+ for (f = 0; f < font_patterns->nfont; f++)
+ {
+ font_pattern = FcFontRenderPrepare (NULL, pattern,
+ font_patterns->fonts[f]);
+
+ if (font_pattern)
+ patterns->patterns[patterns->n_patterns++] = font_pattern;
+ }
+
+ FcPatternDestroy (pattern);
+
+ FcFontSetSortDestroy (font_patterns);
+
+ g_hash_table_insert (fontset_hash,
+ pango_font_description_copy (desc),
+ patterns);
+ }
+
+ return patterns;
+}
+
+static PangoFont *
+pango_fc_font_map_load_font (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *description)
+{
+ PangoFcPatternSet *patterns = pango_fc_font_map_get_patterns (fontmap, context, description, NULL);
+ if (!patterns)
+ return NULL;
+
+ if (patterns->n_patterns > 0)
+ return pango_fc_font_map_new_font (fontmap, patterns->patterns[0]);
+
+ return NULL;
+}
+
+static void
+pango_fc_font_set_free (PangoFcPatternSet *font_set)
+{
+ int i;
+
+ for (i = 0; i < font_set->n_patterns; i++)
+ FcPatternDestroy (font_set->patterns[i]);
+
+ g_free (font_set);
+}
+
+
+static PangoFontset *
+pango_fc_font_map_load_fontset (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language)
+{
+ PangoFontsetSimple *simple;
+ int i;
+ PangoFcPatternSet *patterns = pango_fc_font_map_get_patterns (fontmap, context, desc, language);
+ if (!patterns)
+ return NULL;
+
+ simple = pango_fontset_simple_new (language);
+
+ for (i = 0; i < patterns->n_patterns; i++)
+ {
+ PangoFont *font = pango_fc_font_map_new_font (fontmap, patterns->patterns[i]);
+ if (font)
+ pango_fontset_simple_append (simple, font);
+ }
+
+ return PANGO_FONTSET (simple);
+}
+
+
+void
+_pango_fc_font_map_cache_add (PangoFontMap *fontmap,
+ PangoFcFont *xfont)
+{
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
+
+ g_object_ref (G_OBJECT (xfont));
+ g_queue_push_head (fcfontmap->freed_fonts, xfont);
+ xfont->in_cache = TRUE;
+
+ if (fcfontmap->freed_fonts->length > MAX_FREED_FONTS)
+ {
+ GObject *old_font = g_queue_pop_tail (fcfontmap->freed_fonts);
+ g_object_unref (old_font);
+ }
+}
+
+static void
+pango_fc_font_map_cache_remove (PangoFontMap *fontmap,
+ PangoFcFont *xfont)
+{
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
+
+ GList *link = g_list_find (fcfontmap->freed_fonts->head, xfont);
+ if (link == fcfontmap->freed_fonts->tail)
+ {
+ fcfontmap->freed_fonts->tail = fcfontmap->freed_fonts->tail->prev;
+ if (fcfontmap->freed_fonts->tail)
+ fcfontmap->freed_fonts->tail->next = NULL;
+ }
+
+ fcfontmap->freed_fonts->head = g_list_delete_link (fcfontmap->freed_fonts->head, link);
+ fcfontmap->freed_fonts->length--;
+ xfont->in_cache = FALSE;
+
+ g_object_unref (G_OBJECT (xfont));
+}
+
+static void
+pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap)
+{
+ g_list_foreach (fcfontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
+ g_list_free (fcfontmap->freed_fonts->head);
+ fcfontmap->freed_fonts->head = NULL;
+ fcfontmap->freed_fonts->tail = NULL;
+ fcfontmap->freed_fonts->length = 0;
+}
+
+static void
+pango_fc_font_map_set_coverage (PangoFcFontMap *fcfontmap,
+ PangoFcCoverageKey *key,
+ PangoCoverage *coverage)
+{
+ PangoFcCoverageKey *key_dup;
+
+ key_dup = g_malloc (sizeof (PangoFcCoverageKey) + strlen (key->filename) + 1);
+ key_dup->id = key->id;
+ key_dup->filename = (char *) (key_dup + 1);
+ strcpy (key_dup->filename, key->filename);
+
+ g_hash_table_insert (fcfontmap->coverage_hash,
+ key_dup, pango_coverage_ref (coverage));
+}
+
+PangoCoverage *
+_pango_fc_font_map_get_coverage (PangoFontMap *fontmap,
+ FcPattern *pattern)
+{
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
+ PangoFcCoverageKey key;
+ PangoCoverage *coverage;
+ FcChar32 map[FC_CHARSET_MAP_SIZE];
+ FcChar32 ucs4, pos;
+ FcCharSet *charset;
+ int i;
+
+ /*
+ * Assume that coverage information is identified by
+ * a filename/index pair; there shouldn't be any reason
+ * this isn't true, but it's not specified anywhere
+ */
+ if (FcPatternGetString (pattern, FC_FILE, 0, (FcChar8 **) &key.filename) != FcResultMatch)
+ return NULL;
+
+ if (FcPatternGetInteger (pattern, FC_INDEX, 0, &key.id) != FcResultMatch)
+ return NULL;
+
+ coverage = g_hash_table_lookup (fcfontmap->coverage_hash, &key);
+ if (coverage)
+ return pango_coverage_ref (coverage);
+
+ /*
+ * Pull the coverage out of the pattern, this
+ * doesn't require loading the font
+ */
+ if (FcPatternGetCharSet (pattern, FC_CHARSET, 0, &charset) != FcResultMatch)
+ return NULL;
+
+ /*
+ * Convert an Fc CharSet into a pango coverage structure. Sure
+ * would be nice to just use the Fc structure in place...
+ */
+ coverage = pango_coverage_new ();
+ for (ucs4 = FcCharSetFirstPage (charset, map, &pos);
+ ucs4 != FC_CHARSET_DONE;
+ ucs4 = FcCharSetNextPage (charset, map, &pos))
+ {
+ for (i = 0; i < FC_CHARSET_MAP_SIZE; i++)
+ {
+ FcChar32 bits = map[i];
+ FcChar32 base = ucs4 + i * 32;
+ int b = 0;
+ bits = map[i];
+ while (bits)
+ {
+ if (bits & 1)
+ pango_coverage_set (coverage, base + b, PANGO_COVERAGE_EXACT);
+
+ bits >>= 1;
+ b++;
+ }
+ }
+ }
+
+ pango_fc_font_map_set_coverage (fcfontmap, &key, coverage);
+
+ return coverage;
+}
+
+/*
+ * PangoFcFace
+ */
+
+PangoFontDescription *
+_pango_fc_font_desc_from_pattern (FcPattern *pattern, gboolean include_size)
+{
+ PangoFontDescription *desc;
+ PangoStyle style;
+ PangoWeight weight;
+ double size;
+
+ char *s;
+ int i;
+
+ desc = pango_font_description_new ();
+
+ g_assert (FcPatternGetString (pattern, FC_FAMILY, 0, (FcChar8 **) &s) == FcResultMatch);
+
+ pango_font_description_set_family (desc, s);
+
+ if (FcPatternGetInteger (pattern, FC_SLANT, 0, &i) == FcResultMatch)
+ {
+ if (i == FC_SLANT_ROMAN)
+ style = PANGO_STYLE_NORMAL;
+ else if (i == FC_SLANT_OBLIQUE)
+ style = PANGO_STYLE_OBLIQUE;
+ else
+ style = PANGO_STYLE_ITALIC;
+ }
+ else
+ style = PANGO_STYLE_NORMAL;
+
+ pango_font_description_set_style (desc, style);
+
+ if (FcPatternGetInteger (pattern, FC_WEIGHT, 0, &i) == FcResultMatch)
+ {
+ if (i < FC_WEIGHT_LIGHT)
+ weight = PANGO_WEIGHT_ULTRALIGHT;
+ else if (i < (FC_WEIGHT_LIGHT + FC_WEIGHT_MEDIUM) / 2)
+ weight = PANGO_WEIGHT_LIGHT;
+ else if (i < (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2)
+ weight = PANGO_WEIGHT_NORMAL;
+ else if (i < (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2)
+ weight = 600;
+ else if (i < (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2)
+ weight = PANGO_WEIGHT_BOLD;
+ else
+ weight = PANGO_WEIGHT_ULTRABOLD;
+ }
+ else
+ weight = PANGO_WEIGHT_NORMAL;
+
+ if (include_size && FcPatternGetDouble (pattern, FC_SIZE, 0, &size) == FcResultMatch)
+ pango_font_description_set_size (desc, size * PANGO_SCALE);
+
+ 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);
+
+ return desc;
+}
+
+static PangoFontDescription *
+make_alias_description (PangoFcFamily *fcfamily,
+ gboolean bold,
+ gboolean italic)
+{
+ PangoFontDescription *desc = pango_font_description_new ();
+
+ pango_font_description_set_family (desc, fcfamily->family_name);
+ pango_font_description_set_style (desc, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
+ pango_font_description_set_variant (desc, PANGO_VARIANT_NORMAL);
+ pango_font_description_set_weight (desc, bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
+ pango_font_description_set_stretch (desc, PANGO_STRETCH_NORMAL);
+
+ return desc;
+}
+
+static PangoFontDescription *
+pango_fc_face_describe (PangoFontFace *face)
+{
+ PangoFcFace *fcface = PANGO_FC_FACE (face);
+ PangoFcFamily *fcfamily = fcface->family;
+ PangoFontDescription *desc = NULL;
+ FcResult res;
+ FcPattern *match_pattern;
+ FcPattern *result_pattern;
+
+ if (is_alias_family (fcfamily->family_name))
+ {
+ if (strcmp (fcface->style, "Regular") == 0)
+ return make_alias_description (fcfamily, FALSE, FALSE);
+ else if (strcmp (fcface->style, "Bold") == 0)
+ return make_alias_description (fcfamily, TRUE, FALSE);
+ else if (strcmp (fcface->style, "Italic") == 0)
+ return make_alias_description (fcfamily, FALSE, TRUE);
+ else /* Bold Italic */
+ return make_alias_description (fcfamily, TRUE, TRUE);
+ }
+
+ match_pattern = FcPatternBuild (NULL,
+ FC_FAMILY, FcTypeString, fcfamily->family_name,
+ FC_STYLE, FcTypeString, fcface->style,
+ NULL);
+
+ g_assert (match_pattern);
+
+ result_pattern = FcFontMatch (NULL, match_pattern, &res);
+ if (result_pattern)
+ {
+ desc = _pango_fc_font_desc_from_pattern (result_pattern, FALSE);
+ FcPatternDestroy (result_pattern);
+ }
+
+ FcPatternDestroy (match_pattern);
+
+ return desc;
+}
+
+static const char *
+pango_fc_face_get_face_name (PangoFontFace *face)
+{
+ PangoFcFace *fcface = PANGO_FC_FACE (face);
+
+ return fcface->style;
+}
+
+static void
+pango_fc_face_class_init (PangoFontFaceClass *class)
+{
+ class->describe = pango_fc_face_describe;
+ class->get_face_name = pango_fc_face_get_face_name;
+}
+
+static GType
+pango_fc_face_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (!object_type)
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (PangoFontFaceClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_fc_face_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoFcFace),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_FACE,
+ PANGO_FC_NAME "Face",
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+/*
+ * PangoFcFamily
+ */
+static PangoFcFace *
+create_face (PangoFcFamily *fcfamily,
+ const char *style)
+{
+ PangoFcFace *face = g_object_new (PANGO_FC_TYPE_FACE, NULL);
+ face->style = g_strdup (style);
+ face->family = fcfamily;
+
+ return face;
+}
+
+static void
+pango_fc_family_list_faces (PangoFontFamily *family,
+ PangoFontFace ***faces,
+ int *n_faces)
+{
+ PangoFcFamily *fcfamily = PANGO_FC_FAMILY (family);
+ PangoFcFontMap *fcfontmap = fcfamily->fontmap;
+
+ if (fcfamily->n_faces < 0)
+ {
+ FcFontSet *fontset;
+ int i;
+
+ if (is_alias_family (fcfamily->family_name) || fcfontmap->closed)
+ {
+ fcfamily->n_faces = 4;
+ fcfamily->faces = g_new (PangoFcFace *, fcfamily->n_faces);
+
+ i = 0;
+ fcfamily->faces[i++] = create_face (fcfamily, "Regular");
+ fcfamily->faces[i++] = create_face (fcfamily, "Bold");
+ fcfamily->faces[i++] = create_face (fcfamily, "Italic");
+ fcfamily->faces[i++] = create_face (fcfamily, "Bold Italic");
+ }
+ else
+ {
+ FcObjectSet *os = FcObjectSetBuild (FC_STYLE, NULL);
+ FcPattern *pat = FcPatternBuild (NULL,
+ FC_FAMILY, FcTypeString, fcfamily->family_name,
+ NULL);
+
+ fontset = FcFontList (NULL, pat, os);
+
+ FcPatternDestroy (pat);
+ FcObjectSetDestroy (os);
+
+ fcfamily->n_faces = fontset->nfont;
+ fcfamily->faces = g_new (PangoFcFace *, fcfamily->n_faces);
+
+ for (i = 0; i < fontset->nfont; i++)
+ {
+ FcChar8 *s;
+ FcResult res;
+
+ res = FcPatternGetString (fontset->fonts[i], FC_STYLE, 0, &s);
+ if (res != FcResultMatch)
+ s = "Regular";
+
+ fcfamily->faces[i] = create_face (fcfamily, s);
+ }
+
+ FcFontSetDestroy (fontset);
+ }
+ }
+
+ if (n_faces)
+ *n_faces = fcfamily->n_faces;
+
+ if (faces)
+ *faces = g_memdup (fcfamily->faces, fcfamily->n_faces * sizeof (PangoFontFace *));
+}
+
+static const char *
+pango_fc_family_get_name (PangoFontFamily *family)
+{
+ PangoFcFamily *fcfamily = PANGO_FC_FAMILY (family);
+
+ return fcfamily->family_name;
+}
+
+static void
+pango_fc_family_class_init (PangoFontFamilyClass *class)
+{
+ class->list_faces = pango_fc_family_list_faces;
+ class->get_name = pango_fc_family_get_name;
+}
+
+static void
+pango_fc_family_init (PangoFcFamily *fcfamily)
+{
+ fcfamily->n_faces = -1;
+}
+
+static GType
+pango_fc_family_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (!object_type)
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (PangoFontFamilyClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_fc_family_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoFcFamily),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) pango_fc_family_init,
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_FAMILY,
+ PANGO_FC_NAME "Family",
+ &object_info, 0);
+ }
+
+ return object_type;
+}
diff --git a/pango/pangofc-fontmap.cI b/pango/pangofc-fontmap.cI
new file mode 100644
index 00000000..13b5c1cd
--- /dev/null
+++ b/pango/pangofc-fontmap.cI
@@ -0,0 +1,1054 @@
+/* Pango
+ * pangofc-fontmap.cI: Common font handling between Xft and FT2
+ *
+ * Copyright (C) 2000,2001,2002 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * This file is included by both pangoxft-fontmap.c and pangoft2-fontmap.c
+ * after making appropriate #defines for public symbols.
+ */
+
+/* Number of freed fonts to keep around */
+#define MAX_FREED_FONTS 128
+
+typedef struct _PangoFcCoverageKey PangoFcCoverageKey;
+typedef struct _PangoFcFace PangoFcFace;
+typedef struct _PangoFcPatternSet PangoFcPatternSet;
+
+#define PANGO_FC_TYPE_FAMILY (pango_fc_family_get_type ())
+#define PANGO_FC_FAMILY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_FC_TYPE_FAMILY, PangoFcFamily))
+#define PANGO_FC_IS_FAMILY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_FC_TYPE_FAMILY))
+
+#define PANGO_FC_TYPE_FACE (pango_fc_face_get_type ())
+#define PANGO_FC_FACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_FC_TYPE_FACE, PangoFcFace))
+#define PANGO_FC_IS_FACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_FC_TYPE_FACE))
+
+struct _PangoFcCoverageKey
+{
+ char *filename;
+ int id; /* needed to handle TTC files with multiple faces */
+};
+
+struct _PangoFcFace
+{
+ PangoFontFace parent_instance;
+
+ PangoFcFamily *family;
+ char *style;
+};
+
+struct _PangoFcFamily
+{
+ PangoFontFamily parent_instance;
+
+ PangoFcFontMap *fontmap;
+ char *family_name;
+
+ PangoFcFace **faces;
+ int n_faces; /* -1 == uninitialized */
+};
+
+struct _PangoFcPatternSet
+{
+ int n_patterns;
+ FcPattern **patterns;
+};
+
+GType pango_fc_font_map_get_type (void);
+static GType pango_fc_family_get_type (void);
+static GType pango_fc_face_get_type (void);
+
+static void pango_fc_font_map_init (PangoFcFontMap *fontmap);
+static void pango_fc_font_map_class_init (PangoFontMapClass *class);
+static void pango_fc_font_map_finalize (GObject *object);
+static PangoFont * pango_fc_font_map_load_font (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *description);
+static PangoFontset *pango_fc_font_map_load_fontset (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language);
+static void pango_fc_font_map_list_families (PangoFontMap *fontmap,
+ PangoFontFamily ***families,
+ int *n_families);
+
+
+static void pango_fc_font_set_free (PangoFcPatternSet *font_set);
+
+static void pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap);
+static void pango_fc_font_map_cache_remove (PangoFontMap *fontmap,
+ PangoFcFont *xfont);
+static void pango_fc_default_substitute (PangoFcFontMap *fontmap,
+ FcPattern *pattern);
+static void pango_fc_do_finalize (PangoFcFontMap *fontmap);
+
+static guint pango_fc_pattern_hash (FcPattern *pattern);
+static gboolean pango_fc_pattern_equal (FcPattern *pattern1,
+ FcPattern *pattern2);
+static guint pango_fc_coverage_key_hash (PangoFcCoverageKey *key);
+static gboolean pango_fc_coverage_key_equal (PangoFcCoverageKey *key1,
+ PangoFcCoverageKey *key2);
+
+static PangoFontClass *parent_class; /* Parent class structure for PangoFcFontMap */
+
+GType
+pango_fc_font_map_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (!object_type)
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (PangoFontMapClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_fc_font_map_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoFcFontMap),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) pango_fc_font_map_init,
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_MAP,
+ PANGO_FC_NAME "FontMap",
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+static void
+pango_fc_font_map_init (PangoFcFontMap *fcfontmap)
+{
+ fcfontmap->n_families = -1;
+
+ fcfontmap->fonts = g_hash_table_new ((GHashFunc)pango_fc_pattern_hash,
+ (GEqualFunc)pango_fc_pattern_equal);
+
+ fcfontmap->coverage_hash = g_hash_table_new_full ((GHashFunc)pango_fc_coverage_key_hash,
+ (GEqualFunc)pango_fc_coverage_key_equal,
+ (GDestroyNotify)g_free,
+ (GDestroyNotify)pango_coverage_unref);
+ fcfontmap->freed_fonts = g_queue_new ();
+}
+
+static void
+pango_fc_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_fc_font_map_finalize;
+ class->load_font = pango_fc_font_map_load_font;
+ class->load_fontset = pango_fc_font_map_load_fontset;
+ class->list_families = pango_fc_font_map_list_families;
+}
+
+static GSList *fontmaps = NULL;
+
+static guint
+pango_fc_pattern_hash (FcPattern *pattern)
+{
+#if 1
+ return FcPatternHash (pattern);
+#else
+ /* Hashing only part of the pattern can improve speed a bit.
+ */
+ char *str;
+ int i;
+ double d;
+ guint hash = 0;
+
+ FcPatternGetString (pattern, FC_FILE, 0, (FcChar8 **) &str);
+ if (str)
+ hash = g_str_hash (str);
+
+ if (FcPatternGetInteger (pattern, FC_INDEX, 0, &i) == FcResultMatch)
+ hash ^= i;
+
+ if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &d) == FcResultMatch)
+ hash ^= (guint) (d*1000.0);
+
+ return hash;
+#endif
+}
+
+static gboolean
+pango_fc_pattern_equal (FcPattern *pattern1,
+ FcPattern *pattern2)
+{
+ if (pattern1 == pattern2)
+ return TRUE;
+ else
+ return FcPatternEqual (pattern1, pattern2);
+}
+
+static guint
+pango_fc_coverage_key_hash (PangoFcCoverageKey *key)
+{
+ return g_str_hash (key->filename) ^ key->id;
+}
+
+static gboolean
+pango_fc_coverage_key_equal (PangoFcCoverageKey *key1,
+ PangoFcCoverageKey *key2)
+{
+ return key1->id == key2->id && strcmp (key1->filename, key2->filename) == 0;
+}
+
+typedef struct _FontsetHashListNode FontsetHashListNode;
+
+struct _FontsetHashListNode {
+ GHashTable *fontset_hash;
+ PangoLanguage *language;
+};
+
+/* Get the description => fontset map for a particular
+ * language tag.
+ */
+static GHashTable *
+pango_fc_get_fontset_hash (PangoFcFontMap *fcfontmap,
+ PangoLanguage *language)
+{
+ /* We treat NULL as a distinct language tag, but
+ * we should actually determine the real language
+ * tag it corresponds to to avoid duplicate entries
+ * in the list.
+ */
+ GList *tmp_list = fcfontmap->fontset_hash_list;
+ while (tmp_list)
+ {
+ FontsetHashListNode *node = tmp_list->data;
+ if (node->language == language)
+ {
+ if (tmp_list != fcfontmap->fontset_hash_list)
+ {
+ /* Put the found node at the beginning
+ */
+ fcfontmap->fontset_hash_list = g_list_remove_link (fcfontmap->fontset_hash_list, tmp_list);
+ fcfontmap->fontset_hash_list->prev = tmp_list;
+ tmp_list->next = fcfontmap->fontset_hash_list;
+ fcfontmap->fontset_hash_list = tmp_list;
+ }
+
+ return node->fontset_hash;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ {
+ FontsetHashListNode *node = g_new (FontsetHashListNode, 1);
+ fcfontmap->fontset_hash_list = g_list_prepend (fcfontmap->fontset_hash_list, node);
+
+ node->fontset_hash =
+ g_hash_table_new_full ((GHashFunc)pango_font_description_hash,
+ (GEqualFunc)pango_font_description_equal,
+ (GDestroyNotify)pango_font_description_free,
+ (GDestroyNotify)pango_fc_font_set_free);
+ node->language = language;
+
+ return node->fontset_hash;
+ }
+}
+
+static void
+pango_fc_clear_fontset_hash_list (PangoFcFontMap *fcfontmap)
+{
+ GList *tmp_list = fcfontmap->fontset_hash_list;
+ while (tmp_list)
+ {
+ FontsetHashListNode *node = tmp_list->data;
+
+ g_hash_table_destroy (node->fontset_hash);
+ g_free (node);
+
+ tmp_list = tmp_list->next;
+ }
+
+ g_list_free (fcfontmap->fontset_hash_list);
+ fcfontmap->fontset_hash_list = NULL;
+}
+
+static void
+pango_fc_font_map_finalize (GObject *object)
+{
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (object);
+
+ fontmaps = g_slist_remove (fontmaps, object);
+
+ if (fcfontmap->substitute_destroy)
+ fcfontmap->substitute_destroy (fcfontmap->substitute_data);
+
+ pango_fc_font_map_cache_clear (fcfontmap);
+ g_queue_free (fcfontmap->freed_fonts);
+ pango_fc_clear_fontset_hash_list (fcfontmap);
+ g_hash_table_destroy (fcfontmap->coverage_hash);
+
+ if (fcfontmap->fonts)
+ g_hash_table_destroy (fcfontmap->fonts);
+
+ pango_fc_do_finalize (fcfontmap);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+
+/* Add a mapping from xfont->font_pattern to xfont */
+void
+_pango_fc_font_map_add (PangoFontMap *fontmap,
+ PangoFcFont *xfont)
+{
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
+
+ g_hash_table_insert (fcfontmap->fonts,
+ xfont->font_pattern,
+ xfont);
+}
+
+/* Remove mapping from xfont->font_pattern to xfont */
+void
+_pango_fc_font_map_remove (PangoFontMap *fontmap,
+ PangoFcFont *xfont)
+{
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
+
+ g_hash_table_remove (fcfontmap->fonts,
+ xfont->font_pattern);
+}
+
+static PangoFcFamily *
+create_family (PangoFcFontMap *fcfontmap,
+ const char *family_name)
+{
+ PangoFcFamily *family = g_object_new (PANGO_FC_TYPE_FAMILY, NULL);
+ family->fontmap = fcfontmap;
+ family->family_name = g_strdup (family_name);
+
+ return family;
+}
+
+static gboolean
+is_alias_family (const char *family_name)
+{
+ switch (family_name[0])
+ {
+ case 'm':
+ case 'M':
+ return (g_ascii_strcasecmp (family_name, "monospace") == 0);
+ case 's':
+ case 'S':
+ return (g_ascii_strcasecmp (family_name, "sans") == 0 ||
+ g_ascii_strcasecmp (family_name, "serif") == 0);
+ }
+
+ return FALSE;
+}
+
+static void
+pango_fc_font_map_list_families (PangoFontMap *fontmap,
+ PangoFontFamily ***families,
+ int *n_families)
+{
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
+ FcFontSet *fontset;
+ int i;
+ int count;
+
+ if (fcfontmap->closed)
+ {
+ if (families)
+ *families = NULL;
+ if (n_families)
+ n_families = 0;
+
+ return;
+ }
+
+ if (fcfontmap->n_families < 0)
+ {
+ FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, NULL);
+ FcPattern *pat = FcPatternCreate ();
+
+ fontset = FcFontList (NULL, pat, os);
+
+ FcPatternDestroy (pat);
+ FcObjectSetDestroy (os);
+
+ fcfontmap->families = g_new (PangoFcFamily *, fontset->nfont + 3); /* 3 standard aliases */
+
+ count = 0;
+ for (i = 0; i < fontset->nfont; i++)
+ {
+ char *s;
+ FcResult res;
+
+ res = FcPatternGetString (fontset->fonts[i], FC_FAMILY, 0, (FcChar8 **) &s);
+ g_assert (res == FcResultMatch);
+
+ if (!is_alias_family (s))
+ fcfontmap->families[count++] = create_family (fcfontmap, s);
+ }
+
+ FcFontSetDestroy (fontset);
+
+ fcfontmap->families[count++] = create_family (fcfontmap, "Sans");
+ fcfontmap->families[count++] = create_family (fcfontmap, "Serif");
+ fcfontmap->families[count++] = create_family (fcfontmap, "Monospace");
+
+ fcfontmap->n_families = count;
+ }
+
+ if (n_families)
+ *n_families = fcfontmap->n_families;
+
+ if (families)
+ *families = g_memdup (fcfontmap->families, fcfontmap->n_families * sizeof (PangoFontFamily *));
+}
+
+static int
+pango_fc_convert_weight (PangoWeight pango_weight)
+{
+ int weight;
+
+ if (pango_weight < (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_LIGHT) / 2)
+ weight = FC_WEIGHT_LIGHT;
+ else if (pango_weight < (PANGO_WEIGHT_NORMAL + 600) / 2)
+ weight = FC_WEIGHT_MEDIUM;
+ else if (pango_weight < (600 + PANGO_WEIGHT_BOLD) / 2)
+ weight = FC_WEIGHT_DEMIBOLD;
+ else if (pango_weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2)
+ weight = FC_WEIGHT_BOLD;
+ else
+ weight = FC_WEIGHT_BLACK;
+
+ return weight;
+}
+
+static int
+pango_fc_convert_slant (PangoStyle pango_style)
+{
+ int slant;
+
+ if (pango_style == PANGO_STYLE_ITALIC)
+ slant = FC_SLANT_ITALIC;
+ else if (pango_style == PANGO_STYLE_OBLIQUE)
+ slant = FC_SLANT_OBLIQUE;
+ else
+ slant = FC_SLANT_ROMAN;
+
+ return slant;
+}
+
+
+static FcPattern *
+pango_fc_make_pattern (const PangoFontDescription *description)
+{
+ FcPattern *pattern;
+ PangoStyle pango_style;
+ int slant;
+ int weight;
+ char **families;
+ int i;
+
+ pango_style = pango_font_description_get_style (description);
+
+ slant = pango_fc_convert_slant (pango_style);
+ weight = pango_fc_convert_weight (pango_font_description_get_weight (description));
+
+ pattern = FcPatternBuild (0,
+ FC_WEIGHT, FcTypeInteger, weight,
+ FC_SLANT, FcTypeInteger, slant,
+ FC_SIZE, FcTypeDouble, (double)pango_font_description_get_size (description)/PANGO_SCALE,
+ NULL);
+
+ families = g_strsplit (pango_font_description_get_family (description), ",", -1);
+
+ for (i = 0; families[i]; i++)
+ FcPatternAddString (pattern, FC_FAMILY, families[i]);
+
+ g_strfreev (families);
+
+ return pattern;
+}
+
+static PangoFont *
+pango_fc_font_map_new_font (PangoFontMap *fontmap,
+ FcPattern *match)
+{
+ PangoFcFontMap *fcfontmap = (PangoFcFontMap *)fontmap;
+ PangoFcFont *font;
+
+ /* Returning NULL here actually violates a contract
+ * that loading load_font() will never return NULL.
+ * We probably should actually create a dummy
+ * font that doesn't draw anything and has empty
+ * metrics.
+ */
+ if (fcfontmap->closed)
+ return NULL;
+
+ /* Look up cache */
+ font = g_hash_table_lookup (fcfontmap->fonts, match);
+
+ if (font)
+ {
+ g_object_ref (font);
+
+ /* Revive font from cache */
+ if (font->in_cache)
+ pango_fc_font_map_cache_remove (fontmap, font);
+
+ return (PangoFont *)font;
+ }
+
+ FcPatternReference (match);
+ return (PangoFont *)_pango_fc_font_new (fontmap, match);
+}
+
+static PangoFcPatternSet *
+pango_fc_font_map_get_patterns (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language)
+{
+ PangoFcFontMap *fcfontmap = (PangoFcFontMap *)fontmap;
+ FcPattern *pattern, *font_pattern;
+ FcResult res;
+ int f;
+ PangoFcPatternSet *patterns;
+ FcFontSet *font_patterns;
+ GHashTable *fontset_hash;
+
+ if (!language && context)
+ language = pango_context_get_language (context);
+
+ fontset_hash = pango_fc_get_fontset_hash (fcfontmap, language);
+ patterns = g_hash_table_lookup (fontset_hash, desc);
+
+ if (patterns == NULL)
+ {
+ pattern = pango_fc_make_pattern (desc);
+ if (language)
+ FcPatternAddString (pattern, FC_LANG, (FcChar8 *) pango_language_to_string (language));
+
+ pango_fc_default_substitute (fcfontmap, pattern);
+
+ font_patterns = FcFontSort (NULL, pattern, FcTrue, 0, &res);
+
+ if (!font_patterns)
+ return NULL;
+
+ patterns = g_new (PangoFcPatternSet, 1);
+ patterns->patterns = g_new (FcPattern *, font_patterns->nfont);
+ patterns->n_patterns = 0;
+
+ for (f = 0; f < font_patterns->nfont; f++)
+ {
+ font_pattern = FcFontRenderPrepare (NULL, pattern,
+ font_patterns->fonts[f]);
+
+ if (font_pattern)
+ patterns->patterns[patterns->n_patterns++] = font_pattern;
+ }
+
+ FcPatternDestroy (pattern);
+
+ FcFontSetSortDestroy (font_patterns);
+
+ g_hash_table_insert (fontset_hash,
+ pango_font_description_copy (desc),
+ patterns);
+ }
+
+ return patterns;
+}
+
+static PangoFont *
+pango_fc_font_map_load_font (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *description)
+{
+ PangoFcPatternSet *patterns = pango_fc_font_map_get_patterns (fontmap, context, description, NULL);
+ if (!patterns)
+ return NULL;
+
+ if (patterns->n_patterns > 0)
+ return pango_fc_font_map_new_font (fontmap, patterns->patterns[0]);
+
+ return NULL;
+}
+
+static void
+pango_fc_font_set_free (PangoFcPatternSet *font_set)
+{
+ int i;
+
+ for (i = 0; i < font_set->n_patterns; i++)
+ FcPatternDestroy (font_set->patterns[i]);
+
+ g_free (font_set);
+}
+
+
+static PangoFontset *
+pango_fc_font_map_load_fontset (PangoFontMap *fontmap,
+ PangoContext *context,
+ const PangoFontDescription *desc,
+ PangoLanguage *language)
+{
+ PangoFontsetSimple *simple;
+ int i;
+ PangoFcPatternSet *patterns = pango_fc_font_map_get_patterns (fontmap, context, desc, language);
+ if (!patterns)
+ return NULL;
+
+ simple = pango_fontset_simple_new (language);
+
+ for (i = 0; i < patterns->n_patterns; i++)
+ {
+ PangoFont *font = pango_fc_font_map_new_font (fontmap, patterns->patterns[i]);
+ if (font)
+ pango_fontset_simple_append (simple, font);
+ }
+
+ return PANGO_FONTSET (simple);
+}
+
+
+void
+_pango_fc_font_map_cache_add (PangoFontMap *fontmap,
+ PangoFcFont *xfont)
+{
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
+
+ g_object_ref (G_OBJECT (xfont));
+ g_queue_push_head (fcfontmap->freed_fonts, xfont);
+ xfont->in_cache = TRUE;
+
+ if (fcfontmap->freed_fonts->length > MAX_FREED_FONTS)
+ {
+ GObject *old_font = g_queue_pop_tail (fcfontmap->freed_fonts);
+ g_object_unref (old_font);
+ }
+}
+
+static void
+pango_fc_font_map_cache_remove (PangoFontMap *fontmap,
+ PangoFcFont *xfont)
+{
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
+
+ GList *link = g_list_find (fcfontmap->freed_fonts->head, xfont);
+ if (link == fcfontmap->freed_fonts->tail)
+ {
+ fcfontmap->freed_fonts->tail = fcfontmap->freed_fonts->tail->prev;
+ if (fcfontmap->freed_fonts->tail)
+ fcfontmap->freed_fonts->tail->next = NULL;
+ }
+
+ fcfontmap->freed_fonts->head = g_list_delete_link (fcfontmap->freed_fonts->head, link);
+ fcfontmap->freed_fonts->length--;
+ xfont->in_cache = FALSE;
+
+ g_object_unref (G_OBJECT (xfont));
+}
+
+static void
+pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap)
+{
+ g_list_foreach (fcfontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
+ g_list_free (fcfontmap->freed_fonts->head);
+ fcfontmap->freed_fonts->head = NULL;
+ fcfontmap->freed_fonts->tail = NULL;
+ fcfontmap->freed_fonts->length = 0;
+}
+
+static void
+pango_fc_font_map_set_coverage (PangoFcFontMap *fcfontmap,
+ PangoFcCoverageKey *key,
+ PangoCoverage *coverage)
+{
+ PangoFcCoverageKey *key_dup;
+
+ key_dup = g_malloc (sizeof (PangoFcCoverageKey) + strlen (key->filename) + 1);
+ key_dup->id = key->id;
+ key_dup->filename = (char *) (key_dup + 1);
+ strcpy (key_dup->filename, key->filename);
+
+ g_hash_table_insert (fcfontmap->coverage_hash,
+ key_dup, pango_coverage_ref (coverage));
+}
+
+PangoCoverage *
+_pango_fc_font_map_get_coverage (PangoFontMap *fontmap,
+ FcPattern *pattern)
+{
+ PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap);
+ PangoFcCoverageKey key;
+ PangoCoverage *coverage;
+ FcChar32 map[FC_CHARSET_MAP_SIZE];
+ FcChar32 ucs4, pos;
+ FcCharSet *charset;
+ int i;
+
+ /*
+ * Assume that coverage information is identified by
+ * a filename/index pair; there shouldn't be any reason
+ * this isn't true, but it's not specified anywhere
+ */
+ if (FcPatternGetString (pattern, FC_FILE, 0, (FcChar8 **) &key.filename) != FcResultMatch)
+ return NULL;
+
+ if (FcPatternGetInteger (pattern, FC_INDEX, 0, &key.id) != FcResultMatch)
+ return NULL;
+
+ coverage = g_hash_table_lookup (fcfontmap->coverage_hash, &key);
+ if (coverage)
+ return pango_coverage_ref (coverage);
+
+ /*
+ * Pull the coverage out of the pattern, this
+ * doesn't require loading the font
+ */
+ if (FcPatternGetCharSet (pattern, FC_CHARSET, 0, &charset) != FcResultMatch)
+ return NULL;
+
+ /*
+ * Convert an Fc CharSet into a pango coverage structure. Sure
+ * would be nice to just use the Fc structure in place...
+ */
+ coverage = pango_coverage_new ();
+ for (ucs4 = FcCharSetFirstPage (charset, map, &pos);
+ ucs4 != FC_CHARSET_DONE;
+ ucs4 = FcCharSetNextPage (charset, map, &pos))
+ {
+ for (i = 0; i < FC_CHARSET_MAP_SIZE; i++)
+ {
+ FcChar32 bits = map[i];
+ FcChar32 base = ucs4 + i * 32;
+ int b = 0;
+ bits = map[i];
+ while (bits)
+ {
+ if (bits & 1)
+ pango_coverage_set (coverage, base + b, PANGO_COVERAGE_EXACT);
+
+ bits >>= 1;
+ b++;
+ }
+ }
+ }
+
+ pango_fc_font_map_set_coverage (fcfontmap, &key, coverage);
+
+ return coverage;
+}
+
+/*
+ * PangoFcFace
+ */
+
+PangoFontDescription *
+_pango_fc_font_desc_from_pattern (FcPattern *pattern, gboolean include_size)
+{
+ PangoFontDescription *desc;
+ PangoStyle style;
+ PangoWeight weight;
+ double size;
+
+ char *s;
+ int i;
+
+ desc = pango_font_description_new ();
+
+ g_assert (FcPatternGetString (pattern, FC_FAMILY, 0, (FcChar8 **) &s) == FcResultMatch);
+
+ pango_font_description_set_family (desc, s);
+
+ if (FcPatternGetInteger (pattern, FC_SLANT, 0, &i) == FcResultMatch)
+ {
+ if (i == FC_SLANT_ROMAN)
+ style = PANGO_STYLE_NORMAL;
+ else if (i == FC_SLANT_OBLIQUE)
+ style = PANGO_STYLE_OBLIQUE;
+ else
+ style = PANGO_STYLE_ITALIC;
+ }
+ else
+ style = PANGO_STYLE_NORMAL;
+
+ pango_font_description_set_style (desc, style);
+
+ if (FcPatternGetInteger (pattern, FC_WEIGHT, 0, &i) == FcResultMatch)
+ {
+ if (i < FC_WEIGHT_LIGHT)
+ weight = PANGO_WEIGHT_ULTRALIGHT;
+ else if (i < (FC_WEIGHT_LIGHT + FC_WEIGHT_MEDIUM) / 2)
+ weight = PANGO_WEIGHT_LIGHT;
+ else if (i < (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2)
+ weight = PANGO_WEIGHT_NORMAL;
+ else if (i < (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2)
+ weight = 600;
+ else if (i < (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2)
+ weight = PANGO_WEIGHT_BOLD;
+ else
+ weight = PANGO_WEIGHT_ULTRABOLD;
+ }
+ else
+ weight = PANGO_WEIGHT_NORMAL;
+
+ if (include_size && FcPatternGetDouble (pattern, FC_SIZE, 0, &size) == FcResultMatch)
+ pango_font_description_set_size (desc, size * PANGO_SCALE);
+
+ 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);
+
+ return desc;
+}
+
+static PangoFontDescription *
+make_alias_description (PangoFcFamily *fcfamily,
+ gboolean bold,
+ gboolean italic)
+{
+ PangoFontDescription *desc = pango_font_description_new ();
+
+ pango_font_description_set_family (desc, fcfamily->family_name);
+ pango_font_description_set_style (desc, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
+ pango_font_description_set_variant (desc, PANGO_VARIANT_NORMAL);
+ pango_font_description_set_weight (desc, bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
+ pango_font_description_set_stretch (desc, PANGO_STRETCH_NORMAL);
+
+ return desc;
+}
+
+static PangoFontDescription *
+pango_fc_face_describe (PangoFontFace *face)
+{
+ PangoFcFace *fcface = PANGO_FC_FACE (face);
+ PangoFcFamily *fcfamily = fcface->family;
+ PangoFontDescription *desc = NULL;
+ FcResult res;
+ FcPattern *match_pattern;
+ FcPattern *result_pattern;
+
+ if (is_alias_family (fcfamily->family_name))
+ {
+ if (strcmp (fcface->style, "Regular") == 0)
+ return make_alias_description (fcfamily, FALSE, FALSE);
+ else if (strcmp (fcface->style, "Bold") == 0)
+ return make_alias_description (fcfamily, TRUE, FALSE);
+ else if (strcmp (fcface->style, "Italic") == 0)
+ return make_alias_description (fcfamily, FALSE, TRUE);
+ else /* Bold Italic */
+ return make_alias_description (fcfamily, TRUE, TRUE);
+ }
+
+ match_pattern = FcPatternBuild (NULL,
+ FC_FAMILY, FcTypeString, fcfamily->family_name,
+ FC_STYLE, FcTypeString, fcface->style,
+ NULL);
+
+ g_assert (match_pattern);
+
+ result_pattern = FcFontMatch (NULL, match_pattern, &res);
+ if (result_pattern)
+ {
+ desc = _pango_fc_font_desc_from_pattern (result_pattern, FALSE);
+ FcPatternDestroy (result_pattern);
+ }
+
+ FcPatternDestroy (match_pattern);
+
+ return desc;
+}
+
+static const char *
+pango_fc_face_get_face_name (PangoFontFace *face)
+{
+ PangoFcFace *fcface = PANGO_FC_FACE (face);
+
+ return fcface->style;
+}
+
+static void
+pango_fc_face_class_init (PangoFontFaceClass *class)
+{
+ class->describe = pango_fc_face_describe;
+ class->get_face_name = pango_fc_face_get_face_name;
+}
+
+static GType
+pango_fc_face_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (!object_type)
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (PangoFontFaceClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_fc_face_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoFcFace),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) NULL,
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_FACE,
+ PANGO_FC_NAME "Face",
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+/*
+ * PangoFcFamily
+ */
+static PangoFcFace *
+create_face (PangoFcFamily *fcfamily,
+ const char *style)
+{
+ PangoFcFace *face = g_object_new (PANGO_FC_TYPE_FACE, NULL);
+ face->style = g_strdup (style);
+ face->family = fcfamily;
+
+ return face;
+}
+
+static void
+pango_fc_family_list_faces (PangoFontFamily *family,
+ PangoFontFace ***faces,
+ int *n_faces)
+{
+ PangoFcFamily *fcfamily = PANGO_FC_FAMILY (family);
+ PangoFcFontMap *fcfontmap = fcfamily->fontmap;
+
+ if (fcfamily->n_faces < 0)
+ {
+ FcFontSet *fontset;
+ int i;
+
+ if (is_alias_family (fcfamily->family_name) || fcfontmap->closed)
+ {
+ fcfamily->n_faces = 4;
+ fcfamily->faces = g_new (PangoFcFace *, fcfamily->n_faces);
+
+ i = 0;
+ fcfamily->faces[i++] = create_face (fcfamily, "Regular");
+ fcfamily->faces[i++] = create_face (fcfamily, "Bold");
+ fcfamily->faces[i++] = create_face (fcfamily, "Italic");
+ fcfamily->faces[i++] = create_face (fcfamily, "Bold Italic");
+ }
+ else
+ {
+ FcObjectSet *os = FcObjectSetBuild (FC_STYLE, NULL);
+ FcPattern *pat = FcPatternBuild (NULL,
+ FC_FAMILY, FcTypeString, fcfamily->family_name,
+ NULL);
+
+ fontset = FcFontList (NULL, pat, os);
+
+ FcPatternDestroy (pat);
+ FcObjectSetDestroy (os);
+
+ fcfamily->n_faces = fontset->nfont;
+ fcfamily->faces = g_new (PangoFcFace *, fcfamily->n_faces);
+
+ for (i = 0; i < fontset->nfont; i++)
+ {
+ FcChar8 *s;
+ FcResult res;
+
+ res = FcPatternGetString (fontset->fonts[i], FC_STYLE, 0, &s);
+ if (res != FcResultMatch)
+ s = "Regular";
+
+ fcfamily->faces[i] = create_face (fcfamily, s);
+ }
+
+ FcFontSetDestroy (fontset);
+ }
+ }
+
+ if (n_faces)
+ *n_faces = fcfamily->n_faces;
+
+ if (faces)
+ *faces = g_memdup (fcfamily->faces, fcfamily->n_faces * sizeof (PangoFontFace *));
+}
+
+static const char *
+pango_fc_family_get_name (PangoFontFamily *family)
+{
+ PangoFcFamily *fcfamily = PANGO_FC_FAMILY (family);
+
+ return fcfamily->family_name;
+}
+
+static void
+pango_fc_family_class_init (PangoFontFamilyClass *class)
+{
+ class->list_faces = pango_fc_family_list_faces;
+ class->get_name = pango_fc_family_get_name;
+}
+
+static void
+pango_fc_family_init (PangoFcFamily *fcfamily)
+{
+ fcfamily->n_faces = -1;
+}
+
+static GType
+pango_fc_family_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (!object_type)
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (PangoFontFamilyClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_fc_family_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoFcFamily),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) pango_fc_family_init,
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT_FAMILY,
+ PANGO_FC_NAME "Family",
+ &object_info, 0);
+ }
+
+ return object_type;
+}
diff --git a/pango/pangoft2-fontmap.c b/pango/pangoft2-fontmap.c
index 47132f01..ad15e6d1 100644
--- a/pango/pangoft2-fontmap.c
+++ b/pango/pangoft2-fontmap.c
@@ -43,23 +43,7 @@
#include <windows.h>
#endif
-typedef struct _PangoFT2SizeInfo PangoFT2SizeInfo;
-typedef struct _PangoFT2PatternSet PangoFT2PatternSet;
-
-/* Number of freed fonts */
-#define MAX_FREED_FONTS 16
-
-struct _PangoFT2Family
-{
- PangoFontFamily parent_instance;
-
- PangoFT2FontMap *fontmap;
- char *family_name;
-
- PangoFT2Face **faces;
- int n_faces; /* -1 == uninitialized */
-};
-
+typedef struct _PangoFT2Family PangoFT2Family;
struct _PangoFT2FontMap
{
@@ -67,7 +51,10 @@ struct _PangoFT2FontMap
FT_Library library;
- GHashTable *fontset_hash; /* Maps PangoFontDescription -> PangoXftFontSet */
+ /* We have one map from PangoFontDescription -> PangoXftPatternSet
+ * per language tag.
+ */
+ GList *fontset_hash_list;
GHashTable *coverage_hash; /* Maps font file name -> PangoCoverage */
GHashTable *fonts; /* Maps XftPattern -> PangoFT2Font */
@@ -80,6 +67,8 @@ struct _PangoFT2FontMap
double dpi_x;
double dpi_y;
+ guint closed : 1;
+
/* Function to call on prepared patterns to do final
* config tweaking.
*/
@@ -88,157 +77,37 @@ struct _PangoFT2FontMap
GDestroyNotify substitute_destroy;
};
-struct _PangoFT2PatternSet
-{
- int n_patterns;
- FcPattern **patterns;
-};
-
-#define PANGO_FT2_TYPE_FAMILY (pango_ft2_family_get_type ())
-#define PANGO_FT2_FAMILY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_FT2_TYPE_FAMILY, PangoFT2Family))
-#define PANGO_FT2_IS_FAMILY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_FT2_TYPE_FAMILY))
+/************************************************************
+ * Code shared with PangoXft *
+ ************************************************************/
-#define PANGO_FT2_TYPE_FACE (pango_ft2_face_get_type ())
-#define PANGO_FT2_FACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_FT2_TYPE_FACE, PangoFT2Face))
-#define PANGO_FT2_IS_FACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_FT2_TYPE_FACE))
+#define PangoFcFamily PangoFT2Family
+#define _PangoFcFamily _PangoFT2Family
+#define PangoFcFontMap PangoFT2FontMap
+#define PangoFcFont PangoFT2Font
-GType pango_ft2_family_get_type (void);
-GType pango_ft2_face_get_type (void);
+#define PANGO_FC_FONT_MAP PANGO_FT2_FONT_MAP
-static void pango_ft2_font_map_init (PangoFT2FontMap *fontmap);
-static void pango_ft2_font_map_class_init (PangoFontMapClass *class);
-static void pango_ft2_font_map_finalize (GObject *object);
-static PangoFont * pango_ft2_font_map_load_font (PangoFontMap *fontmap,
- PangoContext *context,
- const PangoFontDescription *description);
-static PangoFontset *pango_ft2_font_map_load_fontset (PangoFontMap *fontmap,
- PangoContext *context,
- const PangoFontDescription *desc,
- PangoLanguage *language);
-static void pango_ft2_font_set_free (PangoFT2PatternSet *font_set);
-static void pango_ft2_font_map_list_families (PangoFontMap *fontmap,
- PangoFontFamily ***families,
- int *n_families);
-static void pango_ft2_font_map_cache_remove (PangoFontMap *fontmap,
- PangoFT2Font *ft2font);
-static void pango_ft2_font_map_cache_clear (PangoFT2FontMap *ft2fontmap);
+#define pango_fc_font_map_get_type pango_ft2_font_map_get_type
+#define _pango_fc_font_map_add _pango_ft2_font_map_add
+#define _pango_fc_font_map_remove _pango_ft2_font_map_remove
+#define _pango_fc_font_map_cache_add _pango_ft2_font_map_cache_add
+#define _pango_fc_font_map_cache_remove _pango_ft2_font_map_cache_remove
+#define _pango_fc_font_map_get_coverage _pango_ft2_font_map_get_coverage
+#define _pango_fc_font_map_set_coverage _pango_ft2_font_map_set_coverage
+#define _pango_fc_font_desc_from_pattern _pango_ft2_font_desc_from_pattern
+#define _pango_fc_font_new _pango_ft2_font_new
+#define PANGO_FC_NAME "PangoFT2"
+#include "pangofc-fontmap.cI"
-static PangoFontClass *parent_class; /* Parent class structure for PangoFT2FontMap */
+/*************************************************************
+ * FreeType specific code *
+ *************************************************************/
static PangoFT2FontMap *pango_ft2_global_fontmap = NULL;
-GType
-pango_ft2_font_map_get_type (void)
-{
- static GType object_type = 0;
-
- if (!object_type)
- {
- static const GTypeInfo object_info =
- {
- sizeof (PangoFontMapClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) pango_ft2_font_map_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (PangoFT2FontMap),
- 0, /* n_preallocs */
- (GInstanceInitFunc) pango_ft2_font_map_init,
- };
-
- object_type = g_type_register_static (PANGO_TYPE_FONT_MAP,
- "PangoFT2FontMap",
- &object_info, 0);
- }
-
- return object_type;
-}
-
-static void
-pango_ft2_font_set_free (PangoFT2PatternSet *font_set)
-{
- int i;
-
- for (i = 0; i < font_set->n_patterns; i++)
- FcPatternDestroy (font_set->patterns[i]);
-
- g_free (font_set);
-}
-
-static guint
-pango_ft2_pattern_hash (FcPattern *pattern)
-{
- FcChar8 *str;
- int i;
- double d;
- guint hash = 0;
-
- if (FcPatternGetString (pattern, FC_FILE, 0, &str) == FcResultMatch)
- hash = g_str_hash ((char *) str);
-
- if (FcPatternGetInteger (pattern, FC_INDEX, 0, &i) == FcResultMatch)
- hash ^= i;
-
- if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &d) == FcResultMatch)
- hash ^= (guint) (d*1000.0);
-
- return hash;
-}
-
-static gboolean
-pango_ft2_pattern_equal (FcPattern *pattern1,
- FcPattern *pattern2)
-{
- return FcPatternEqual (pattern1, pattern2);
-}
-
-static void
-pango_ft2_init_fontset_hash (PangoFT2FontMap *ft2fontmap)
-{
- if (ft2fontmap->fontset_hash)
- g_hash_table_destroy (ft2fontmap->fontset_hash);
-
- 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);
-}
-
-static void
-pango_ft2_font_map_init (PangoFT2FontMap *ft2fontmap)
-{
- ft2fontmap->n_families = -1;
-
- ft2fontmap->fonts =
- g_hash_table_new ((GHashFunc)pango_ft2_pattern_hash,
- (GEqualFunc)pango_ft2_pattern_equal);
-
- pango_ft2_init_fontset_hash (ft2fontmap);
-
- 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 ();
-}
-
-static void
-pango_ft2_font_map_class_init (PangoFontMapClass *class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
-
- parent_class = g_type_class_peek_parent (class);
-
- object_class->finalize = pango_ft2_font_map_finalize;
- class->load_font = pango_ft2_font_map_load_font;
- class->load_fontset = pango_ft2_font_map_load_fontset;
- class->list_families = pango_ft2_font_map_list_families;
-}
-
/**
* pango_ft2_font_map_new:
*
@@ -285,6 +154,22 @@ pango_ft2_font_map_new (void)
}
/**
+ * pango_ft2_font_map_substitute_changed:
+ * @fontmap: a #PangoFT2Fontmap
+ *
+ * Call this function any time the results of the
+ * default substitution function set with
+ * pango_ft2_font_map_set_default_substitute() change.
+ * That is, if your subsitution function will return different
+ * results for the same input pattern, you must call this function.
+ **/
+void
+pango_ft2_font_map_substitute_changed (PangoFT2FontMap *fontmap)
+{
+ pango_fc_clear_fontset_hash_list (fontmap);
+}
+
+/**
* pango_ft2_font_map_set_resolution:
* @fontmap: a #PangoFT2Fontmap
* @dpi_x: dots per inch in the X direction
@@ -306,53 +191,6 @@ pango_ft2_font_map_set_resolution (PangoFT2FontMap *fontmap,
}
/**
- * pango_ft2_font_map_set_default_substitute:
- * @fontmap: a #PangoFT2Fontmap
- * @func: function to call to to do final config tweaking
- * on #FcPattern objects.
- * @data: data to pass to @func
- * @notify: function to call when @data is no longer used.
- *
- * Sets a function that will be called to do final configuration
- * substitution on a #FcPattern before it is used to load
- * the font. This function can be used to do things like set
- * hinting and antiasing options.
- **/
-void
-pango_ft2_font_map_set_default_substitute (PangoFT2FontMap *fontmap,
- PangoFT2SubstituteFunc func,
- gpointer data,
- GDestroyNotify notify)
-{
- g_return_if_fail (PANGO_FT2_IS_FONT_MAP (fontmap));
-
- if (fontmap->substitute_destroy)
- fontmap->substitute_destroy (fontmap->substitute_data);
-
- fontmap->substitute_func = func;
- fontmap->substitute_data = data;
- fontmap->substitute_destroy = notify;
-
- pango_ft2_font_map_substitute_changed (fontmap);
-}
-
-/**
- * pango_ft2_font_map_substitute_changed:
- * @fontmap: a #PangoFT2Fontmap
- *
- * Call this function any time the results of the
- * default substitution function set with
- * pango_ft2_font_map_set_default_substitute() change.
- * That is, if your subsitution function will return different
- * results for the same input pattern, you must call this function.
- **/
-void
-pango_ft2_font_map_substitute_changed (PangoFT2FontMap *fontmap)
-{
- pango_ft2_init_fontset_hash (fontmap);
-}
-
-/**
* pango_ft2_font_map_create_context:
* @fontmap: a #PangoFT2Fontmap
*
@@ -374,26 +212,6 @@ pango_ft2_font_map_create_context (PangoFT2FontMap *fontmap)
}
/**
- * pango_ft2_font_map_for_display:
- *
- * Returns a #PangoFT2FontMap. This font map is cached and should
- * not be freed. If the font map is no longer needed, it can
- * be released with pango_ft2_shutdown_display().
- *
- * Returns: a #PangoFT2FontMap.
- **/
-PangoFontMap *
-pango_ft2_font_map_for_display (void)
-{
- if (pango_ft2_global_fontmap != NULL)
- return PANGO_FONT_MAP (pango_ft2_global_fontmap);
-
- pango_ft2_global_fontmap = (PangoFT2FontMap *)pango_ft2_font_map_new ();
-
- return PANGO_FONT_MAP (pango_ft2_global_fontmap);
-}
-
-/**
* pango_ft2_get_context:
* @dpi_x: the horizontal dpi of the target device
* @dpi_y: the vertical dpi of the target device
@@ -419,6 +237,26 @@ pango_ft2_get_context (double dpi_x, double dpi_y)
}
/**
+ * pango_ft2_font_map_for_display:
+ *
+ * Returns a #PangoFT2FontMap. This font map is cached and should
+ * not be freed. If the font map is no longer needed, it can
+ * be released with pango_ft2_shutdown_display().
+ *
+ * Returns: a #PangoFT2FontMap.
+ **/
+PangoFontMap *
+pango_ft2_font_map_for_display (void)
+{
+ if (pango_ft2_global_fontmap != NULL)
+ return PANGO_FONT_MAP (pango_ft2_global_fontmap);
+
+ pango_ft2_global_fontmap = (PangoFT2FontMap *)pango_ft2_font_map_new ();
+
+ return PANGO_FONT_MAP (pango_ft2_global_fontmap);
+}
+
+/**
* pango_ft2_shutdown_display:
*
* Free the global fontmap. (See pango_ft2_font_map_for_display())
@@ -428,7 +266,7 @@ pango_ft2_shutdown_display (void)
{
if (pango_ft2_global_fontmap)
{
- pango_ft2_font_map_cache_clear (pango_ft2_global_fontmap);
+ pango_fc_font_map_cache_clear (pango_ft2_global_fontmap);
g_object_unref (G_OBJECT (pango_ft2_global_fontmap));
@@ -436,576 +274,6 @@ pango_ft2_shutdown_display (void)
}
}
-
-static void
-pango_ft2_font_map_finalize (GObject *object)
-{
- PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (object);
-
- g_queue_free (ft2fontmap->freed_fonts);
- g_hash_table_destroy (ft2fontmap->fontset_hash);
- g_hash_table_destroy (ft2fontmap->coverage_hash);
-
- if (ft2fontmap->substitute_destroy)
- ft2fontmap->substitute_destroy (ft2fontmap->substitute_data);
-
- FT_Done_FreeType (ft2fontmap->library);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-/* Add a mapping from xfont->font_pattern to xfont */
-void
-_pango_ft2_font_map_add (PangoFontMap *fontmap,
- PangoFT2Font *ft2font)
-{
- PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *) fontmap;
-
- 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 PangoFT2Family *
-create_family (PangoFT2FontMap *ft2fontmap,
- const char *family_name)
-{
- PangoFT2Family *family = g_object_new (PANGO_FT2_TYPE_FAMILY, NULL);
- family->fontmap = ft2fontmap;
- family->family_name = g_strdup (family_name);
- family->n_faces = -1;
-
- return family;
-}
-
-static gboolean
-is_alias_family (const char *family_name)
-{
- switch (family_name[0])
- {
- case 'm':
- case 'M':
- return (g_ascii_strcasecmp (family_name, "monospace") == 0);
- case 's':
- case 'S':
- return (g_ascii_strcasecmp (family_name, "sans") == 0 ||
- g_ascii_strcasecmp (family_name, "serif") == 0);
- }
-
- return FALSE;
-}
-
-static void
-pango_ft2_font_map_list_families (PangoFontMap *fontmap,
- PangoFontFamily ***families,
- int *n_families)
-{
- PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
- FcFontSet *fontset;
- int i;
- int count;
-
- if (ft2fontmap->n_families < 0)
- {
- FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, NULL);
- FcPattern *pat = FcPatternCreate ();
- fontset = FcFontList (NULL, pat, os);
- FcPatternDestroy (pat);
- FcObjectSetDestroy (os);
-
- ft2fontmap->families = g_new (PangoFT2Family *, fontset->nfont + 3); /* 3 standard aliases */
-
- count = 0;
- for (i = 0; i < fontset->nfont; i++)
- {
- FcChar8 *s;
- FcResult res;
-
- res = FcPatternGetString (fontset->fonts[i], FC_FAMILY, 0, &s);
- g_assert (res == FcResultMatch);
-
- if (!is_alias_family (s))
- ft2fontmap->families[count++] = create_family (ft2fontmap, s);
-
- }
-
- ft2fontmap->families[count++] = create_family (ft2fontmap, "Sans");
- ft2fontmap->families[count++] = create_family (ft2fontmap, "Serif");
- ft2fontmap->families[count++] = create_family (ft2fontmap, "Monospace");
-
- FcFontSetDestroy (fontset);
-
- ft2fontmap->n_families = count;
- }
-
- if (n_families)
- *n_families = ft2fontmap->n_families;
-
- if (families)
- *families = g_memdup (ft2fontmap->families,
- ft2fontmap->n_families * sizeof (PangoFontFamily *));
-}
-
-static int
-pango_ft2_convert_weight (PangoWeight pango_weight)
-{
- int weight;
-
- if (pango_weight < (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_LIGHT) / 2)
- weight = FC_WEIGHT_LIGHT;
- else if (pango_weight < (PANGO_WEIGHT_NORMAL + 600) / 2)
- weight = FC_WEIGHT_MEDIUM;
- else if (pango_weight < (600 + PANGO_WEIGHT_BOLD) / 2)
- weight = FC_WEIGHT_DEMIBOLD;
- else if (pango_weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2)
- weight = FC_WEIGHT_BOLD;
- else
- weight = FC_WEIGHT_BLACK;
-
- return weight;
-}
-
-static int
-pango_ft2_convert_slant (PangoStyle pango_style)
-{
- int slant;
-
- if (pango_style == PANGO_STYLE_ITALIC)
- slant = FC_SLANT_ITALIC;
- else if (pango_style == PANGO_STYLE_OBLIQUE)
- slant = FC_SLANT_OBLIQUE;
- else
- slant = FC_SLANT_ROMAN;
-
- return slant;
-}
-
-
-static FcPattern *
-pango_ft2_make_pattern (const PangoFontDescription *description)
-{
- FcPattern *pattern;
- PangoStyle pango_style;
- int slant;
- int weight;
- char **families;
- int i;
-
- pango_style = pango_font_description_get_style (description);
-
- slant = pango_ft2_convert_slant (pango_style);
- weight = pango_ft2_convert_weight (pango_font_description_get_weight (description));
-
- /* To fool Xft into not munging glyph indices, we open it as glyphs-fontspecific
- * then set the encoding ourself
- */
- pattern = FcPatternBuild (NULL,
- FC_WEIGHT, FcTypeInteger, weight,
- FC_SLANT, FcTypeInteger, slant,
- FC_SIZE, FcTypeDouble, (double)pango_font_description_get_size (description)/PANGO_SCALE,
- NULL);
-
- families = g_strsplit (pango_font_description_get_family (description), ",", -1);
-
- for (i = 0; families[i]; i++)
- FcPatternAddString (pattern, FC_FAMILY, families[i]);
-
- g_strfreev (families);
-
- return pattern;
-}
-
-static PangoFont *
-pango_ft2_font_map_new_font (PangoFontMap *fontmap,
- FcPattern *match)
-{
- PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
- PangoFT2Font *font;
-
- /* Look up cache */
- font = g_hash_table_lookup (ft2fontmap->fonts, match);
-
- if (font)
- {
- g_object_ref (font);
-
- /* Revive font from cache */
- if (font->in_cache)
- pango_ft2_font_map_cache_remove (fontmap, font);
-
- return (PangoFont *)font;
- }
-
- return (PangoFont *)_pango_ft2_font_new (fontmap, FcPatternDuplicate (match));
-}
-
-
-static PangoFont *
-pango_ft2_font_map_load_font (PangoFontMap *fontmap,
- PangoContext *context,
- const PangoFontDescription *description)
-{
- FcPattern *pattern, *match;
- FcResult res;
- PangoFont *font;
-
- pattern = pango_ft2_make_pattern (description);
-
- match = FcFontMatch (0, pattern, &res);
- FcPatternDestroy (pattern);
-
- font = NULL;
-
- if (match)
- {
- font = pango_ft2_font_map_new_font (fontmap, match);
- FcPatternDestroy (match);
- }
-
- return font;
-}
-
-static void
-pango_ft2_default_substitute (PangoFT2FontMap *fontmap,
- FcPattern *pattern)
-{
- FcValue v;
-
- if (fontmap->substitute_func)
- fontmap->substitute_func (pattern, fontmap->substitute_data);
-
- if (FcPatternGet (pattern, FC_DPI, 0, &v) == FcResultNoMatch)
- FcPatternAddDouble (pattern, FC_DPI, fontmap->dpi_y);
-}
-
-static PangoFontset *
-pango_ft2_font_map_load_fontset (PangoFontMap *fontmap,
- PangoContext *context,
- const PangoFontDescription *desc,
- PangoLanguage *language)
-{
- PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
- FcPattern *pattern, *pattern_copy;
- FcPattern *match;
- int i;
- FcChar8 *family, *family_res;
- FcResult res;
- GPtrArray *array;
- int id;
- PangoFT2PatternSet *patterns;
- PangoFontsetSimple *simple;
-
- patterns = g_hash_table_lookup (ft2fontmap->fontset_hash, desc);
-
- if (patterns == NULL)
- {
- pattern = pango_ft2_make_pattern (desc);
-
- if (!FcInit ())
- {
- g_warning ("Cannot initialize fontconfig");
- return NULL;
- }
- FcConfigSubstitute (0, pattern, FcMatchPattern);
- FcDefaultSubstitute (pattern);
- pango_ft2_default_substitute (ft2fontmap, pattern);
-
- pattern_copy = FcPatternDuplicate (pattern);
-
- array = g_ptr_array_new ();
- patterns = g_new (PangoFT2PatternSet, 1);
-
- match = NULL;
- id = 0;
- while (FcPatternGetString (pattern, FC_FAMILY, id++, &family) == FcResultMatch)
- {
- FcPatternDel (pattern_copy, FC_FAMILY);
- FcPatternAddString (pattern_copy, FC_FAMILY, family);
-
- match = FcFontMatch (NULL, pattern_copy, &res);
-
- if (match &&
- FcPatternGetString (match, FC_FAMILY, 0, &family_res) == FcResultMatch &&
- FcStrCmpIgnoreCase (family, family_res) == 0)
- {
- g_ptr_array_add (array, match);
- match = NULL;
- }
- if (match)
- FcPatternDestroy (match);
- }
-
- if (array->len == 0)
- {
- match = FcFontMatch (0, pattern, &res);
- g_ptr_array_add (array, match);
- }
-
- FcPatternDestroy (pattern);
- FcPatternDestroy (pattern_copy);
-
- patterns->n_patterns = array->len;
- patterns->patterns = (FcPattern **)g_ptr_array_free (array, FALSE);
-
- g_hash_table_insert (ft2fontmap->fontset_hash,
- pango_font_description_copy (desc),
- patterns);
- }
-
- simple = pango_fontset_simple_new (language);
-
- for (i = 0; i < patterns->n_patterns; i++)
- pango_fontset_simple_append (simple,
- pango_ft2_font_map_new_font (fontmap, patterns->patterns[i]));
-
- return PANGO_FONTSET (simple);
-}
-
-void
-_pango_ft2_font_map_cache_add (PangoFontMap *fontmap,
- PangoFT2Font *ft2font)
-{
- PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (fontmap);
-
- if (ft2fontmap->freed_fonts->length == MAX_FREED_FONTS)
- {
- PangoFT2Font *old_font = g_queue_pop_tail (ft2fontmap->freed_fonts);
- g_object_unref (G_OBJECT (old_font));
- }
-
- g_object_ref (G_OBJECT (ft2font));
- g_queue_push_head (ft2fontmap->freed_fonts, ft2font);
- ft2font->in_cache = TRUE;
-}
-
-static void
-pango_ft2_font_map_cache_remove (PangoFontMap *fontmap,
- PangoFT2Font *ft2font)
-{
- PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (fontmap);
-
- GList *link = g_list_find (ft2fontmap->freed_fonts->head, ft2font);
- if (link == ft2fontmap->freed_fonts->tail)
- {
- ft2fontmap->freed_fonts->tail = ft2fontmap->freed_fonts->tail->prev;
- if (ft2fontmap->freed_fonts->tail)
- ft2fontmap->freed_fonts->tail->next = NULL;
- }
-
- ft2fontmap->freed_fonts->head = g_list_delete_link (ft2fontmap->freed_fonts->head, link);
- ft2fontmap->freed_fonts->length--;
- ft2font->in_cache = FALSE;
-
- g_object_unref (G_OBJECT (ft2font));
-}
-
-static void
-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);
- ft2fontmap->freed_fonts->head = NULL;
- ft2fontmap->freed_fonts->tail = NULL;
- ft2fontmap->freed_fonts->length = 0;
-}
-
-/*
- * PangoFT2Face
- */
-
-PangoFontDescription *
-_pango_ft2_font_desc_from_pattern (FcPattern *pattern,
- gboolean include_size)
-{
- PangoFontDescription *desc;
- PangoStyle style;
- PangoWeight weight;
- double size;
-
- FcChar8 *s;
- int i;
-
- desc = pango_font_description_new ();
-
- g_assert (FcPatternGetString (pattern, FC_FAMILY, 0, &s) == FcResultMatch);
-
- pango_font_description_set_family (desc, s);
-
- if (FcPatternGetInteger (pattern, FC_SLANT, 0, &i) == FcResultMatch)
- {
- if (i == FC_SLANT_ROMAN)
- style = PANGO_STYLE_NORMAL;
- else if (i == FC_SLANT_OBLIQUE)
- style = PANGO_STYLE_OBLIQUE;
- else
- style = PANGO_STYLE_ITALIC;
- }
- else
- style = PANGO_STYLE_NORMAL;
-
- pango_font_description_set_style (desc, style);
-
- if (FcPatternGetInteger (pattern, FC_WEIGHT, 0, &i) == FcResultMatch)
- {
- if (i < FC_WEIGHT_LIGHT)
- weight = PANGO_WEIGHT_ULTRALIGHT;
- else if (i < (FC_WEIGHT_LIGHT + FC_WEIGHT_MEDIUM) / 2)
- weight = PANGO_WEIGHT_LIGHT;
- else if (i < (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2)
- weight = PANGO_WEIGHT_NORMAL;
- else if (i < (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2)
- weight = 600;
- else if (i < (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2)
- weight = PANGO_WEIGHT_BOLD;
- else
- weight = PANGO_WEIGHT_ULTRABOLD;
- }
- else
- weight = PANGO_WEIGHT_NORMAL;
-
- if (include_size && FcPatternGetDouble (pattern, FC_SIZE, 0, &size) == FcResultMatch)
- pango_font_description_set_size (desc, size * PANGO_SCALE);
-
- 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);
-
- return desc;
-}
-
-
-static PangoFontDescription *
-make_alias_description (PangoFT2Family *ft2family,
- gboolean bold,
- gboolean italic)
-{
- PangoFontDescription *desc = pango_font_description_new ();
-
- pango_font_description_set_family (desc, ft2family->family_name);
- pango_font_description_set_style (desc, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
- pango_font_description_set_variant (desc, PANGO_VARIANT_NORMAL);
- pango_font_description_set_weight (desc, bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
- pango_font_description_set_stretch (desc, PANGO_STRETCH_NORMAL);
-
- return desc;
-}
-
-static PangoFontDescription *
-pango_ft2_face_describe (PangoFontFace *face)
-{
- PangoFT2Face *ft2face = (PangoFT2Face *) face;
- PangoFT2Family *ft2family = ft2face->family;
- PangoFontDescription *desc = NULL;
- FcResult res;
- FcPattern *match_pattern;
- FcPattern *result_pattern;
-
- if (is_alias_family (ft2family->family_name))
- {
- if (strcmp (ft2face->style, "Regular") == 0)
- return make_alias_description (ft2family, FALSE, FALSE);
- else if (strcmp (ft2face->style, "Bold") == 0)
- return make_alias_description (ft2family, TRUE, FALSE);
- else if (strcmp (ft2face->style, "Italic") == 0)
- return make_alias_description (ft2family, FALSE, TRUE);
- else /* Bold Italic */
- return make_alias_description (ft2family, TRUE, TRUE);
- }
-
- match_pattern = FcPatternBuild (NULL,
- FC_FAMILY, FcTypeString, ft2family->family_name,
- FC_STYLE, FcTypeString, ft2face->style,
- NULL);
-
- g_assert (match_pattern);
-
- result_pattern = FcFontMatch (NULL, match_pattern, &res);
- if (result_pattern)
- {
- desc = _pango_ft2_font_desc_from_pattern (result_pattern, FALSE);
- FcPatternDestroy (result_pattern);
- }
-
- FcPatternDestroy (match_pattern);
-
- return desc;
-}
-
-static const char *
-pango_ft2_face_get_face_name (PangoFontFace *face)
-{
- PangoFT2Face *ft2face = PANGO_FT2_FACE (face);
-
- return ft2face->style;
-}
-
-static void
-pango_ft2_face_class_init (PangoFontFaceClass *class)
-{
- class->describe = pango_ft2_face_describe;
- class->get_face_name = pango_ft2_face_get_face_name;
-}
-
-GType
-pango_ft2_face_get_type (void)
-{
- static GType object_type = 0;
-
- if (!object_type)
- {
- static const GTypeInfo object_info =
- {
- sizeof (PangoFontFaceClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) pango_ft2_face_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (PangoFT2Face),
- 0, /* n_preallocs */
- (GInstanceInitFunc) NULL,
- };
-
- object_type = g_type_register_static (PANGO_TYPE_FONT_FACE,
- "PangoFT2Face",
- &object_info, 0);
- }
-
- return object_type;
-}
-
-void
-_pango_ft2_font_map_set_coverage (PangoFontMap *fontmap,
- const char *name,
- PangoCoverage *coverage)
-{
- PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
-
- g_hash_table_insert (ft2fontmap->coverage_hash, g_strdup (name),
- pango_coverage_ref (coverage));
-}
-
-PangoCoverage *
-_pango_ft2_font_map_get_coverage (PangoFontMap *fontmap,
- const char *name)
-{
- PangoFT2FontMap *ft2fontmap = (PangoFT2FontMap *)fontmap;
-
- return g_hash_table_lookup (ft2fontmap->coverage_hash, name);
-}
-
FT_Library
_pango_ft2_font_map_get_library (PangoFontMap *fontmap)
{
@@ -1014,120 +282,24 @@ _pango_ft2_font_map_get_library (PangoFontMap *fontmap)
return ft2fontmap->library;
}
-/*
- * PangoFT2FontFamily
- */
-static PangoFT2Face *
-create_face (PangoFT2Family *ft2family,
- const char *style)
-{
- PangoFT2Face *face = g_object_new (PANGO_FT2_TYPE_FACE, NULL);
- face->style = g_strdup (style);
- face->family = ft2family;
-
- return face;
-}
-
static void
-pango_ft2_family_list_faces (PangoFontFamily *family,
- PangoFontFace ***faces,
- int *n_faces)
-{
- PangoFT2Family *ft2family = PANGO_FT2_FAMILY (family);
-
- if (ft2family->n_faces < 0)
- {
- FcFontSet *fontset;
- FcPattern *pat;
- FcObjectSet *os;
- int i;
-
- if (is_alias_family (ft2family->family_name))
- {
- ft2family->n_faces = 4;
- ft2family->faces = g_new (PangoFT2Face *, ft2family->n_faces);
-
- i = 0;
- ft2family->faces[i++] = create_face (ft2family, "Regular");
- ft2family->faces[i++] = create_face (ft2family, "Bold");
- ft2family->faces[i++] = create_face (ft2family, "Italic");
- ft2family->faces[i++] = create_face (ft2family, "Bold Italic");
- }
- else
- {
- os = FcObjectSetBuild (FC_STYLE, NULL);
- pat = FcPatternBuild (NULL,
- FC_FAMILY, FcTypeString, ft2family->family_name,
- NULL);
-
- fontset = FcFontList (NULL, pat, os);
-
- FcPatternDestroy (pat);
- FcObjectSetDestroy (os);
-
- ft2family->n_faces = fontset->nfont;
- ft2family->faces = g_new (PangoFT2Face *, ft2family->n_faces);
-
- for (i = 0; i < fontset->nfont; i++)
- {
- FcChar8 *s;
- FcResult res;
-
- res = FcPatternGetString (fontset->fonts[i], FC_STYLE, 0, &s);
- g_assert (res == FcResultMatch);
-
- ft2family->faces[i] = create_face (ft2family, s);
- }
-
- FcFontSetDestroy (fontset);
- }
- }
-
- if (n_faces)
- *n_faces = ft2family->n_faces;
-
- if (faces)
- *faces = g_memdup (ft2family->faces, ft2family->n_faces * sizeof (PangoFontFace *));
-}
-
-const char *
-pango_ft2_family_get_name (PangoFontFamily *family)
+pango_fc_do_finalize (PangoFT2FontMap *fontmap)
{
- PangoFT2Family *ft2family = PANGO_FT2_FAMILY (family);
- return ft2family->family_name;
+ FT_Done_FreeType (fontmap->library);
}
static void
-pango_ft2_family_class_init (PangoFontFamilyClass *class)
+pango_fc_default_substitute (PangoFT2FontMap *fontmap,
+ FcPattern *pattern)
{
- class->list_faces = pango_ft2_family_list_faces;
- class->get_name = pango_ft2_family_get_name;
-}
+ FcValue v;
+
+ FcConfigSubstitute (NULL, pattern, FcMatchPattern);
-GType
-pango_ft2_family_get_type (void)
-{
- static GType object_type = 0;
+ if (fontmap->substitute_func)
+ fontmap->substitute_func (pattern, fontmap->substitute_data);
- if (!object_type)
- {
- static const GTypeInfo object_info =
- {
- sizeof (PangoFontFamilyClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) pango_ft2_family_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (PangoFT2Family),
- 0, /* n_preallocs */
- (GInstanceInitFunc) NULL,
- };
-
- object_type = g_type_register_static (PANGO_TYPE_FONT_FAMILY,
- "PangoFT2Family",
- &object_info, 0);
- }
-
- return object_type;
+ FcDefaultSubstitute (pattern);
+ if (FcPatternGet (pattern, FC_DPI, 0, &v) == FcResultNoMatch)
+ FcPatternAddDouble (pattern, FC_DPI, fontmap->dpi_y);
}
diff --git a/pango/pangoft2-private.h b/pango/pangoft2-private.h
index 2fe8f719..d8d20eae 100644
--- a/pango/pangoft2-private.h
+++ b/pango/pangoft2-private.h
@@ -55,8 +55,6 @@
typedef struct _PangoFT2Font PangoFT2Font;
typedef struct _PangoFT2GlyphInfo PangoFT2GlyphInfo;
-typedef struct _PangoFT2Face PangoFT2Face;
-typedef struct _PangoFT2Family PangoFT2Family;
struct _PangoFT2Font
@@ -89,24 +87,11 @@ struct _PangoFT2GlyphInfo
void *cached_glyph;
};
-struct _PangoFT2Face
-{
- PangoFontFace parent_instance;
-
- PangoFT2Family *family;
- char *style;
-};
-
PangoFT2Font * _pango_ft2_font_new (PangoFontMap *font,
FcPattern *pattern);
PangoMap *_pango_ft2_get_shaper_map (PangoLanguage *language);
-void _pango_ft2_font_map_set_coverage (PangoFontMap *fontmap,
- const char *name,
- PangoCoverage *coverage);
PangoCoverage *_pango_ft2_font_map_get_coverage (PangoFontMap *fontmap,
- const char *name);
-void _pango_ft2_face_remove (PangoFT2Face *face,
- PangoFont *font);
+ FcPattern *pattern);
FT_Library _pango_ft2_font_map_get_library (PangoFontMap *fontmap);
void _pango_ft2_font_map_cache_add (PangoFontMap *fontmap,
PangoFT2Font *ft2font);
diff --git a/pango/pangoft2.c b/pango/pangoft2.c
index fce91a5e..0851840c 100644
--- a/pango/pangoft2.c
+++ b/pango/pangoft2.c
@@ -677,46 +677,6 @@ pango_ft2_font_get_metrics (PangoFont *font,
return pango_font_metrics_ref (info->metrics);
}
-static PangoCoverage *
-pango_ft2_calc_coverage (PangoFont *font,
- PangoLanguage *language)
-{
- PangoCoverage *coverage;
- FT_Face face;
-
- coverage = pango_coverage_new ();
- face = pango_ft2_font_get_face (font);
-
-#ifdef HAVE_FT_GET_FIRST_CHAR
- {
- FT_UInt gindex;
- FT_ULong charcode;
-
- charcode = FT_Get_First_Char (face, &gindex);
- while (gindex)
- {
- pango_coverage_set (coverage, charcode, PANGO_COVERAGE_EXACT);
- charcode = FT_Get_Next_Char (face, charcode, &gindex);
- }
- }
-#else
- /* Ugh, this is going to be SLOW */
- {
- gunichar wc;
-
- for (wc = 0; wc < G_MAXUSHORT; wc++)
- {
- FT_UInt glyph = FT_Get_Char_Index (face, wc);
-
- if (glyph && glyph < face->num_glyphs)
- pango_coverage_set (coverage, wc, PANGO_COVERAGE_EXACT);
- }
- }
-#endif
-
- return coverage;
-}
-
static void
pango_ft2_font_dispose (GObject *object)
{
@@ -822,26 +782,8 @@ pango_ft2_font_get_coverage (PangoFont *font,
PangoLanguage *language)
{
PangoFT2Font *ft2font = (PangoFT2Font *)font;
- FcChar8 *filename = NULL;
- FT_Face face;
- PangoCoverage *coverage;
-
- FcPatternGetString (ft2font->font_pattern, FC_FILE, 0, &filename);
-
- coverage = _pango_ft2_font_map_get_coverage (ft2font->fontmap, filename);
-
- if (coverage)
- return pango_coverage_ref (coverage);
- /* 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;
+ return _pango_ft2_font_map_get_coverage (ft2font->fontmap, ft2font->font_pattern);
}
static PangoEngineShape *
diff --git a/pango/pangoxft-font.c b/pango/pangoxft-font.c
index 315e0795..bd388787 100644
--- a/pango/pangoxft-font.c
+++ b/pango/pangoxft-font.c
@@ -551,68 +551,8 @@ pango_xft_font_get_coverage (PangoFont *font,
PangoLanguage *language)
{
PangoXftFont *xfont = (PangoXftFont *)font;
- PangoXftCoverageKey key;
- PangoCoverage *coverage;
- Display *display;
- FcChar32 map[FC_CHARSET_MAP_SIZE];
- FcChar32 ucs4, pos;
- FcCharSet *charset;
- int i;
-
- _pango_xft_font_map_get_info (xfont->fontmap, &display, NULL);
-
- /*
- * Assume that coverage information is identified by
- * a filename/index pair; there shouldn't be any reason
- * this isn't true, but it's not specified anywhere
- */
- if (FcPatternGetString (xfont->font_pattern, FC_FILE, 0, (FcChar8 **) &key.filename) != FcResultMatch)
- return NULL;
-
- if (FcPatternGetInteger (xfont->font_pattern, FC_INDEX, 0, &key.id) != FcResultMatch)
- return NULL;
-
- coverage = _pango_xft_font_map_get_coverage (xfont->fontmap, &key);
-
- if (coverage)
- return pango_coverage_ref (coverage);
-
- /*
- * Pull the coverage out of the pattern, this
- * doesn't require loading the font
- */
- if (FcPatternGetCharSet (xfont->font_pattern, FC_CHARSET, 0, &charset) != FcResultMatch)
- return NULL;
-
- /*
- * Convert an Fc CharSet into a pango coverage structure. Sure
- * would be nice to just use the Fc structure in place...
- */
- coverage = pango_coverage_new ();
- for (ucs4 = FcCharSetFirstPage (charset, map, &pos);
- ucs4 != FC_CHARSET_DONE;
- ucs4 = FcCharSetNextPage (charset, map, &pos))
- {
- for (i = 0; i < FC_CHARSET_MAP_SIZE; i++)
- {
- FcChar32 bits = map[i];
- FcChar32 base = ucs4 + i * 32;
- int b = 0;
- bits = map[i];
- while (bits)
- {
- if (bits & 1)
- pango_coverage_set (coverage, base + b, PANGO_COVERAGE_EXACT);
-
- bits >>= 1;
- b++;
- }
- }
- }
- _pango_xft_font_map_set_coverage (xfont->fontmap, &key, coverage);
-
- return coverage;
+ return _pango_xft_font_map_get_coverage (xfont->fontmap, xfont->font_pattern);
}
static void
diff --git a/pango/pangoxft-fontmap.c b/pango/pangoxft-fontmap.c
index 05804e9e..a49cf797 100644
--- a/pango/pangoxft-fontmap.c
+++ b/pango/pangoxft-fontmap.c
@@ -29,13 +29,8 @@
/* For XExtSetCloseDisplay */
#include <X11/Xlibint.h>
-/* Number of freed fonts */
-#define MAX_FREED_FONTS 128
-
-typedef struct _PangoXftFontMap PangoXftFontMap;
typedef struct _PangoXftFamily PangoXftFamily;
-typedef struct _PangoXftFace PangoXftFace;
-typedef struct _PangoXftPatternSet PangoXftPatternSet;
+typedef struct _PangoXftFontMap PangoXftFontMap;
#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))
@@ -60,6 +55,7 @@ struct _PangoXftFontMap
Display *display;
int screen;
+ guint closed : 1;
/* Function to call on prepared patterns to do final
* config tweaking.
@@ -69,238 +65,34 @@ struct _PangoXftFontMap
GDestroyNotify substitute_destroy;
};
-#define PANGO_XFT_TYPE_FAMILY (pango_xft_family_get_type ())
-#define PANGO_XFT_FAMILY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_XFT_TYPE_FAMILY, PangoXftFamily))
-#define PANGO_XFT_IS_FAMILY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_XFT_TYPE_FAMILY))
-
-struct _PangoXftFamily
-{
- PangoFontFamily parent_instance;
-
- PangoXftFontMap *fontmap;
- char *family_name;
-
- PangoXftFace **faces;
- int n_faces; /* -1 == uninitialized */
-};
-
-struct _PangoXftPatternSet
-{
- int n_patterns;
- FcPattern **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))
-
-struct _PangoXftFace
-{
- PangoFontFace parent_instance;
-
- PangoXftFamily *family;
- char *style;
-};
+/************************************************************
+ * Code shared with PangoFT2 *
+ ************************************************************/
-static GType pango_xft_font_map_get_type (void);
-GType pango_xft_family_get_type (void);
-GType pango_xft_face_get_type (void);
+#define PangoFcFamily PangoXftFamily
+#define _PangoFcFamily _PangoXftFamily
+#define PangoFcFontMap PangoXftFontMap
+#define PangoFcFont PangoXftFont
-static void pango_xft_font_map_init (PangoXftFontMap *fontmap);
-static void pango_xft_font_map_class_init (PangoFontMapClass *class);
-static void pango_xft_font_map_finalize (GObject *object);
-static PangoFont * pango_xft_font_map_load_font (PangoFontMap *fontmap,
- PangoContext *context,
- const PangoFontDescription *description);
-static PangoFontset *pango_xft_font_map_load_fontset (PangoFontMap *fontmap,
- PangoContext *context,
- const PangoFontDescription *desc,
- PangoLanguage *language);
-static void pango_xft_font_map_list_families (PangoFontMap *fontmap,
- PangoFontFamily ***families,
- int *n_families);
+#define PANGO_FC_FONT_MAP PANGO_XFT_FONT_MAP
+#define pango_fc_font_map_get_type pango_xft_font_map_get_type
+#define _pango_fc_font_map_add _pango_xft_font_map_add
+#define _pango_fc_font_map_remove _pango_xft_font_map_remove
+#define _pango_fc_font_map_cache_add _pango_xft_font_map_cache_add
+#define _pango_fc_font_map_cache_remove _pango_xft_font_map_cache_remove
+#define _pango_fc_font_map_get_coverage _pango_xft_font_map_get_coverage
+#define _pango_fc_font_map_set_coverage _pango_xft_font_map_set_coverage
+#define _pango_fc_font_desc_from_pattern _pango_xft_font_desc_from_pattern
+#define _pango_fc_font_new _pango_xft_font_new
-static void pango_xft_font_set_free (PangoXftPatternSet *font_set);
+#define PANGO_FC_NAME "PangoXft"
-static void pango_xft_font_map_cache_clear (PangoXftFontMap *xfontmap);
-static void pango_xft_font_map_cache_remove (PangoFontMap *fontmap,
- PangoXftFont *xfont);
+#include "pangofc-fontmap.cI"
-static PangoFontClass *parent_class; /* Parent class structure for PangoXftFontMap */
-
-static GType
-pango_xft_font_map_get_type (void)
-{
- static GType object_type = 0;
-
- if (!object_type)
- {
- static const GTypeInfo object_info =
- {
- sizeof (PangoFontMapClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) pango_xft_font_map_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (PangoXftFontMap),
- 0, /* n_preallocs */
- (GInstanceInitFunc) pango_xft_font_map_init,
- };
-
- object_type = g_type_register_static (PANGO_TYPE_FONT_MAP,
- "PangoXftFontMap",
- &object_info, 0);
- }
-
- return object_type;
-}
-
-static void
-pango_xft_font_map_init (PangoXftFontMap *xfontmap)
-{
- xfontmap->n_families = -1;
-}
-
-static void
-pango_xft_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_xft_font_map_finalize;
- class->load_font = pango_xft_font_map_load_font;
- class->load_fontset = pango_xft_font_map_load_fontset;
- class->list_families = pango_xft_font_map_list_families;
-}
-
-static GSList *fontmaps = NULL;
-
-guint
-pango_xft_pattern_hash (FcPattern *pattern)
-{
-#if 1
- return FcPatternHash (pattern);
-#else
- /* Hashing only part of the pattern can improve speed a bit.
- */
- char *str;
- int i;
- double d;
- guint hash = 0;
-
- FcPatternGetString (pattern, FC_FILE, 0, (FcChar8 **) &str);
- if (str)
- hash = g_str_hash (str);
-
- if (FcPatternGetInteger (pattern, FC_INDEX, 0, &i) == FcResultMatch)
- hash ^= i;
-
- if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &d) == FcResultMatch)
- hash ^= (guint) (d*1000.0);
-
- return hash;
-#endif
-}
-
-gboolean
-pango_xft_pattern_equal (FcPattern *pattern1,
- FcPattern *pattern2)
-{
- if (pattern1 == pattern2)
- return TRUE;
- else
- return FcPatternEqual (pattern1, pattern2);
-}
-
-static guint
-pango_xft_coverage_key_hash (PangoXftCoverageKey *key)
-{
- return g_str_hash (key->filename) ^ key->id;
-}
-
-static gboolean
-pango_xft_coverage_key_equal (PangoXftCoverageKey *key1,
- PangoXftCoverageKey *key2)
-{
- return key1->id == key2->id && strcmp (key1->filename, key2->filename) == 0;
-}
-
-typedef struct _FontsetHashListNode FontsetHashListNode;
-
-struct _FontsetHashListNode {
- GHashTable *fontset_hash;
- PangoLanguage *language;
-};
-
-/* Get the description => fontset map for a particular
- * language tag.
- */
-static GHashTable *
-pango_xft_get_fontset_hash (PangoXftFontMap *xfontmap,
- PangoLanguage *language)
-{
- /* We treat NULL as a distinct language tag, but
- * we should actually determine the real language
- * tag it corresponds to to avoid duplicate entries
- * in the list.
- */
- GList *tmp_list = xfontmap->fontset_hash_list;
- while (tmp_list)
- {
- FontsetHashListNode *node = tmp_list->data;
- if (node->language == language)
- {
- if (tmp_list != xfontmap->fontset_hash_list)
- {
- /* Put the found node at the beginning
- */
- xfontmap->fontset_hash_list = g_list_remove_link (xfontmap->fontset_hash_list, tmp_list);
- xfontmap->fontset_hash_list->prev = tmp_list;
- tmp_list->next = xfontmap->fontset_hash_list;
- xfontmap->fontset_hash_list = tmp_list;
- }
-
- return node->fontset_hash;
- }
-
- tmp_list = tmp_list->next;
- }
-
- {
- FontsetHashListNode *node = g_new (FontsetHashListNode, 1);
- xfontmap->fontset_hash_list = g_list_prepend (xfontmap->fontset_hash_list, node);
-
- node->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);
- node->language = language;
-
- return node->fontset_hash;
- }
-}
-
-static void
-pango_xft_clear_fontset_hash_list (PangoXftFontMap *xfontmap)
-{
- GList *tmp_list = xfontmap->fontset_hash_list;
- while (tmp_list)
- {
- FontsetHashListNode *node = tmp_list->data;
-
- g_hash_table_destroy (node->fontset_hash);
- g_free (node);
-
- tmp_list = tmp_list->next;
- }
-
- g_list_free (xfontmap->fontset_hash_list);
- xfontmap->fontset_hash_list = NULL;
-}
+/*************************************************************
+ * Xft specific code *
+ *************************************************************/
static PangoFontMap *
pango_xft_find_font_map (Display *display,
@@ -311,11 +103,11 @@ pango_xft_find_font_map (Display *display,
tmp_list = fontmaps;
while (tmp_list)
{
- PangoXftFontMap *xfontmap = tmp_list->data;
+ PangoXftFontMap *xftfontmap = tmp_list->data;
- if (xfontmap->display == display &&
- xfontmap->screen == screen)
- return PANGO_FONT_MAP (xfontmap);
+ if (xftfontmap->display == display &&
+ xftfontmap->screen == screen)
+ return PANGO_FONT_MAP (xftfontmap);
tmp_list = tmp_list->next;
}
@@ -337,11 +129,11 @@ close_display_cb (Display *display,
tmp_list = fontmaps;
while (tmp_list)
{
- PangoXftFontMap *xfontmap = tmp_list->data;
+ PangoXftFontMap *xftfontmap = tmp_list->data;
tmp_list = tmp_list->next;
- if (xfontmap->display == display)
- pango_xft_shutdown_display (display, xfontmap->screen);
+ if (xftfontmap->display == display)
+ pango_xft_shutdown_display (display, xftfontmap->screen);
}
registered_displays = g_slist_remove (registered_displays, display);
@@ -384,7 +176,7 @@ pango_xft_get_font_map (Display *display,
{
static gboolean registered_modules = FALSE;
PangoFontMap *fontmap;
- PangoXftFontMap *xfontmap;
+ PangoXftFontMap *xftfontmap;
g_return_val_if_fail (display != NULL, NULL);
@@ -405,34 +197,25 @@ pango_xft_get_font_map (Display *display,
if (fontmap)
return fontmap;
- xfontmap = (PangoXftFontMap *)g_object_new (PANGO_TYPE_XFT_FONT_MAP, NULL);
+ xftfontmap = (PangoXftFontMap *)g_object_new (PANGO_TYPE_XFT_FONT_MAP, NULL);
- xfontmap->display = display;
- xfontmap->screen = screen;
-
- xfontmap->fonts = g_hash_table_new ((GHashFunc)pango_xft_pattern_hash,
- (GEqualFunc)pango_xft_pattern_equal);
-
- xfontmap->coverage_hash = g_hash_table_new_full ((GHashFunc)pango_xft_coverage_key_hash,
- (GEqualFunc)pango_xft_coverage_key_equal,
- (GDestroyNotify)g_free,
- (GDestroyNotify)pango_coverage_unref);
- xfontmap->freed_fonts = g_queue_new ();
+ xftfontmap->display = display;
+ xftfontmap->screen = screen;
register_display (display);
- fontmaps = g_slist_prepend (fontmaps, xfontmap);
+ fontmaps = g_slist_prepend (fontmaps, xftfontmap);
- return PANGO_FONT_MAP (xfontmap);
+ return PANGO_FONT_MAP (xftfontmap);
}
static void
cleanup_font (gpointer key,
PangoXftFont *xfont,
- PangoXftFontMap *xfontmap)
+ PangoXftFontMap *xftfontmap)
{
if (xfont->xft_font)
- XftFontClose (xfontmap->display, xfont->xft_font);
+ XftFontClose (xftfontmap->display, xfont->xft_font);
xfont->fontmap = NULL;
}
@@ -454,16 +237,17 @@ pango_xft_shutdown_display (Display *display,
fontmap = pango_xft_find_font_map (display, screen);
if (fontmap)
{
- PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
+ PangoXftFontMap *xftfontmap = PANGO_XFT_FONT_MAP (fontmap);
fontmaps = g_slist_remove (fontmaps, fontmap);
- pango_xft_font_map_cache_clear (xfontmap);
+ pango_fc_font_map_cache_clear (xftfontmap);
- g_hash_table_foreach (xfontmap->fonts, (GHFunc)cleanup_font, fontmap);
- g_hash_table_destroy (xfontmap->fonts);
- xfontmap->fonts = NULL;
+ g_hash_table_foreach (xftfontmap->fonts, (GHFunc)cleanup_font, fontmap);
+ g_hash_table_destroy (xftfontmap->fonts);
+ xftfontmap->fonts = NULL;
- xfontmap->display = NULL;
+ xftfontmap->display = NULL;
+ xftfontmap->closed = TRUE;
g_object_unref (G_OBJECT (fontmap));
}
}
@@ -489,16 +273,16 @@ pango_xft_set_default_substitute (Display *display,
gpointer data,
GDestroyNotify notify)
{
- PangoXftFontMap *xfontmap = (PangoXftFontMap *)pango_xft_get_font_map (display, screen);
+ PangoXftFontMap *xftfontmap = (PangoXftFontMap *)pango_xft_get_font_map (display, screen);
- if (xfontmap->substitute_destroy)
- xfontmap->substitute_destroy (xfontmap->substitute_data);
+ if (xftfontmap->substitute_destroy)
+ xftfontmap->substitute_destroy (xftfontmap->substitute_data);
- xfontmap->substitute_func = func;
- xfontmap->substitute_data = data;
- xfontmap->substitute_destroy = notify;
+ xftfontmap->substitute_func = func;
+ xftfontmap->substitute_data = data;
+ xftfontmap->substitute_destroy = notify;
- pango_xft_clear_fontset_hash_list (xfontmap);
+ pango_fc_clear_fontset_hash_list (xftfontmap);
}
/**
@@ -515,9 +299,22 @@ void
pango_xft_substitute_changed (Display *display,
int screen)
{
- PangoXftFontMap *xfontmap = (PangoXftFontMap *)pango_xft_get_font_map (display, screen);
+ PangoXftFontMap *xftfontmap = (PangoXftFontMap *)pango_xft_get_font_map (display, screen);
- pango_xft_clear_fontset_hash_list (xfontmap);
+ pango_fc_clear_fontset_hash_list (xftfontmap);
+}
+
+void
+_pango_xft_font_map_get_info (PangoFontMap *fontmap,
+ Display **display,
+ int *screen)
+{
+ PangoXftFontMap *xftfontmap = PANGO_XFT_FONT_MAP (fontmap);
+
+ if (display)
+ *display = xftfontmap->display;
+ if (screen)
+ *screen = xftfontmap->screen;
}
/**
@@ -545,719 +342,16 @@ pango_xft_get_context (Display *display,
}
static void
-pango_xft_font_map_finalize (GObject *object)
-{
- PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (object);
-
- fontmaps = g_slist_remove (fontmaps, object);
-
- if (xfontmap->substitute_destroy)
- xfontmap->substitute_destroy (xfontmap->substitute_data);
-
- pango_xft_font_map_cache_clear (xfontmap);
- g_queue_free (xfontmap->freed_fonts);
- pango_xft_clear_fontset_hash_list (xfontmap);
- g_hash_table_destroy (xfontmap->coverage_hash);
-
- if (xfontmap->fonts)
- g_hash_table_destroy (xfontmap->fonts);
-
- 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)
-{
- PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
-
- 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->fonts,
- xfont->font_pattern);
-}
-
-static PangoXftFamily *
-create_family (PangoXftFontMap *xfontmap,
- const char *family_name)
-{
- PangoXftFamily *family = g_object_new (PANGO_XFT_TYPE_FAMILY, NULL);
- family->fontmap = xfontmap;
- family->family_name = g_strdup (family_name);
-
- return family;
-}
-
-static gboolean
-is_alias_family (const char *family_name)
-{
- switch (family_name[0])
- {
- case 'm':
- case 'M':
- return (g_ascii_strcasecmp (family_name, "monospace") == 0);
- case 's':
- case 'S':
- return (g_ascii_strcasecmp (family_name, "sans") == 0 ||
- g_ascii_strcasecmp (family_name, "serif") == 0);
- }
-
- return FALSE;
-}
-
-static void
-pango_xft_font_map_list_families (PangoFontMap *fontmap,
- PangoFontFamily ***families,
- int *n_families)
-{
- PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
- FcFontSet *fontset;
- int i;
- int count;
-
- if (!xfontmap->display)
- {
- if (families)
- *families = NULL;
- if (n_families)
- n_families = 0;
-
- return;
- }
-
- if (xfontmap->n_families < 0)
- {
- fontset = XftListFonts (xfontmap->display, xfontmap->screen,
- NULL,
- FC_FAMILY,
- NULL);
-
- xfontmap->families = g_new (PangoXftFamily *, fontset->nfont + 3); /* 3 standard aliases */
-
- count = 0;
- for (i = 0; i < fontset->nfont; i++)
- {
- char *s;
- FcResult res;
-
- res = FcPatternGetString (fontset->fonts[i], FC_FAMILY, 0, (FcChar8 **) &s);
- g_assert (res == FcResultMatch);
-
- if (!is_alias_family (s))
- xfontmap->families[count++] = create_family (xfontmap, s);
- }
-
- FcFontSetDestroy (fontset);
-
- xfontmap->families[count++] = create_family (xfontmap, "Sans");
- xfontmap->families[count++] = create_family (xfontmap, "Serif");
- xfontmap->families[count++] = create_family (xfontmap, "Monospace");
-
- xfontmap->n_families = count;
- }
-
- if (n_families)
- *n_families = xfontmap->n_families;
-
- if (families)
- *families = g_memdup (xfontmap->families, xfontmap->n_families * sizeof (PangoFontFamily *));
-}
-
-static int
-pango_xft_convert_weight (PangoWeight pango_weight)
-{
- int weight;
-
- if (pango_weight < (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_LIGHT) / 2)
- weight = FC_WEIGHT_LIGHT;
- else if (pango_weight < (PANGO_WEIGHT_NORMAL + 600) / 2)
- weight = FC_WEIGHT_MEDIUM;
- else if (pango_weight < (600 + PANGO_WEIGHT_BOLD) / 2)
- weight = FC_WEIGHT_DEMIBOLD;
- else if (pango_weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2)
- weight = FC_WEIGHT_BOLD;
- else
- weight = FC_WEIGHT_BLACK;
-
- return weight;
-}
-
-static int
-pango_xft_convert_slant (PangoStyle pango_style)
-{
- int slant;
-
- if (pango_style == PANGO_STYLE_ITALIC)
- slant = FC_SLANT_ITALIC;
- else if (pango_style == PANGO_STYLE_OBLIQUE)
- slant = FC_SLANT_OBLIQUE;
- else
- slant = FC_SLANT_ROMAN;
-
- return slant;
-}
-
-
-static FcPattern *
-pango_xft_make_pattern (const PangoFontDescription *description)
-{
- FcPattern *pattern;
- PangoStyle pango_style;
- int slant;
- int weight;
- char **families;
- int i;
-
- 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));
-
- pattern = FcPatternBuild (0,
- FC_WEIGHT, FcTypeInteger, weight,
- FC_SLANT, FcTypeInteger, slant,
- FC_SIZE, FcTypeDouble, (double)pango_font_description_get_size (description)/PANGO_SCALE,
- NULL);
-
- families = g_strsplit (pango_font_description_get_family (description), ",", -1);
-
- for (i = 0; families[i]; i++)
- FcPatternAddString (pattern, FC_FAMILY, families[i]);
-
- g_strfreev (families);
-
- return pattern;
-}
-
-static PangoFont *
-pango_xft_font_map_new_font (PangoFontMap *fontmap,
- FcPattern *match)
-{
- PangoXftFontMap *xfontmap = (PangoXftFontMap *)fontmap;
- PangoXftFont *font;
-
- /* Returning NULL here actually violates a contract
- * that loading load_font() will never return NULL.
- * We probably should actually create a dummy
- * font that doesn't draw anything and has empty
- * metrics.
- */
- if (!xfontmap->display)
- return NULL;
-
- /* Look up cache */
- font = g_hash_table_lookup (xfontmap->fonts, match);
-
- if (font)
- {
- g_object_ref (font);
-
- /* Revive font from cache */
- if (font->in_cache)
- pango_xft_font_map_cache_remove (fontmap, font);
-
- return (PangoFont *)font;
- }
-
- FcPatternReference (match);
- return (PangoFont *)_pango_xft_font_new (fontmap, match);
-}
-
-static PangoXftPatternSet *
-pango_xft_font_map_get_patterns (PangoFontMap *fontmap,
- PangoContext *context,
- const PangoFontDescription *desc,
- PangoLanguage *language)
-{
- PangoXftFontMap *xfontmap = (PangoXftFontMap *)fontmap;
- FcPattern *pattern, *font_pattern;
- FcResult res;
- int f;
- PangoXftPatternSet *patterns;
- FcFontSet *font_patterns;
- GHashTable *fontset_hash;
-
- if (!language && context)
- language = pango_context_get_language (context);
-
- fontset_hash = pango_xft_get_fontset_hash (xfontmap, language);
- patterns = g_hash_table_lookup (fontset_hash, desc);
-
- if (patterns == NULL)
- {
- pattern = pango_xft_make_pattern (desc);
- if (language)
- FcPatternAddString (pattern, FC_LANG, (FcChar8 *) pango_language_to_string (language));
-
- FcConfigSubstitute (NULL, pattern, FcMatchPattern);
- if (xfontmap->substitute_func)
- xfontmap->substitute_func (pattern, xfontmap->substitute_data);
- XftDefaultSubstitute (xfontmap->display, xfontmap->screen, pattern);
-
- font_patterns = FcFontSort (NULL, pattern, FcTrue, 0, &res);
-
- if (!font_patterns)
- return NULL;
-
- patterns = g_new (PangoXftPatternSet, 1);
- patterns->patterns = g_new (FcPattern *, font_patterns->nfont);
- patterns->n_patterns = 0;
-
- for (f = 0; f < font_patterns->nfont; f++)
- {
- font_pattern = FcFontRenderPrepare (NULL, pattern,
- font_patterns->fonts[f]);
-
- if (font_pattern)
- patterns->patterns[patterns->n_patterns++] = font_pattern;
- }
-
- FcPatternDestroy (pattern);
-
- FcFontSetSortDestroy (font_patterns);
-
- g_hash_table_insert (fontset_hash,
- pango_font_description_copy (desc),
- patterns);
- }
-
- return patterns;
-}
-
-static PangoFont *
-pango_xft_font_map_load_font (PangoFontMap *fontmap,
- PangoContext *context,
- const PangoFontDescription *description)
-{
- PangoXftPatternSet *patterns = pango_xft_font_map_get_patterns (fontmap, context, description, NULL);
- if (!patterns)
- return NULL;
-
- if (patterns->n_patterns > 0)
- return pango_xft_font_map_new_font (fontmap, patterns->patterns[0]);
-
- return NULL;
-}
-
-static void
-pango_xft_font_set_free (PangoXftPatternSet *font_set)
-{
- int i;
-
- for (i = 0; i < font_set->n_patterns; i++)
- FcPatternDestroy (font_set->patterns[i]);
-
- g_free (font_set);
-}
-
-
-static PangoFontset *
-pango_xft_font_map_load_fontset (PangoFontMap *fontmap,
- PangoContext *context,
- const PangoFontDescription *desc,
- PangoLanguage *language)
-{
- PangoFontsetSimple *simple;
- int i;
- PangoXftPatternSet *patterns = pango_xft_font_map_get_patterns (fontmap, context, desc, language);
- if (!patterns)
- return NULL;
-
- simple = pango_fontset_simple_new (language);
-
- for (i = 0; i < patterns->n_patterns; i++)
- {
- PangoFont *font = pango_xft_font_map_new_font (fontmap, patterns->patterns[i]);
- if (font)
- pango_fontset_simple_append (simple, font);
- }
-
- return PANGO_FONTSET (simple);
-}
-
-
-void
-_pango_xft_font_map_cache_add (PangoFontMap *fontmap,
- PangoXftFont *xfont)
-{
- PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
-
- g_object_ref (G_OBJECT (xfont));
- g_queue_push_head (xfontmap->freed_fonts, xfont);
- xfont->in_cache = TRUE;
-
- if (xfontmap->freed_fonts->length > MAX_FREED_FONTS)
- {
- GObject *old_font = g_queue_pop_tail (xfontmap->freed_fonts);
- g_object_unref (old_font);
- }
-}
-
-static void
-pango_xft_font_map_cache_remove (PangoFontMap *fontmap,
- PangoXftFont *xfont)
-{
- PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
-
- GList *link = g_list_find (xfontmap->freed_fonts->head, xfont);
- if (link == xfontmap->freed_fonts->tail)
- {
- xfontmap->freed_fonts->tail = xfontmap->freed_fonts->tail->prev;
- if (xfontmap->freed_fonts->tail)
- xfontmap->freed_fonts->tail->next = NULL;
- }
-
- xfontmap->freed_fonts->head = g_list_delete_link (xfontmap->freed_fonts->head, link);
- xfontmap->freed_fonts->length--;
- xfont->in_cache = FALSE;
-
- g_object_unref (G_OBJECT (xfont));
-}
-
-static void
-pango_xft_font_map_cache_clear (PangoXftFontMap *xfontmap)
-{
- g_list_foreach (xfontmap->freed_fonts->head, (GFunc)g_object_unref, NULL);
- g_list_free (xfontmap->freed_fonts->head);
- xfontmap->freed_fonts->head = NULL;
- xfontmap->freed_fonts->tail = NULL;
- xfontmap->freed_fonts->length = 0;
-}
-
-void
-_pango_xft_font_map_set_coverage (PangoFontMap *fontmap,
- const PangoXftCoverageKey *key,
- PangoCoverage *coverage)
-{
- PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
- PangoXftCoverageKey *key_dup;
-
- key_dup = g_malloc (sizeof (PangoXftCoverageKey) + strlen (key->filename) + 1);
- key_dup->id = key->id;
- key_dup->filename = (char *) (key_dup + 1);
- strcpy (key_dup->filename, key->filename);
-
- g_hash_table_insert (xfontmap->coverage_hash,
- key_dup, pango_coverage_ref (coverage));
-}
-
-PangoCoverage *
-_pango_xft_font_map_get_coverage (PangoFontMap *fontmap,
- const PangoXftCoverageKey *key)
-{
- PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
-
- return g_hash_table_lookup (xfontmap->coverage_hash, key);
-}
-
-void
-_pango_xft_font_map_get_info (PangoFontMap *fontmap,
- Display **display,
- int *screen)
-{
- PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
-
- if (display)
- *display = xfontmap->display;
- if (screen)
- *screen = xfontmap->screen;
-}
-
-
-/*
- * PangoXftFace
- */
-
-PangoFontDescription *
-_pango_xft_font_desc_from_pattern (FcPattern *pattern, gboolean include_size)
-{
- PangoFontDescription *desc;
- PangoStyle style;
- PangoWeight weight;
- double size;
-
- char *s;
- int i;
-
- desc = pango_font_description_new ();
-
- g_assert (FcPatternGetString (pattern, FC_FAMILY, 0, (FcChar8 **) &s) == FcResultMatch);
-
- pango_font_description_set_family (desc, s);
-
- if (FcPatternGetInteger (pattern, FC_SLANT, 0, &i) == FcResultMatch)
- {
- if (i == FC_SLANT_ROMAN)
- style = PANGO_STYLE_NORMAL;
- else if (i == FC_SLANT_OBLIQUE)
- style = PANGO_STYLE_OBLIQUE;
- else
- style = PANGO_STYLE_ITALIC;
- }
- else
- style = PANGO_STYLE_NORMAL;
-
- pango_font_description_set_style (desc, style);
-
- if (FcPatternGetInteger (pattern, FC_WEIGHT, 0, &i) == FcResultMatch)
- {
- if (i < FC_WEIGHT_LIGHT)
- weight = PANGO_WEIGHT_ULTRALIGHT;
- else if (i < (FC_WEIGHT_LIGHT + FC_WEIGHT_MEDIUM) / 2)
- weight = PANGO_WEIGHT_LIGHT;
- else if (i < (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2)
- weight = PANGO_WEIGHT_NORMAL;
- else if (i < (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2)
- weight = 600;
- else if (i < (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2)
- weight = PANGO_WEIGHT_BOLD;
- else
- weight = PANGO_WEIGHT_ULTRABOLD;
- }
- else
- weight = PANGO_WEIGHT_NORMAL;
-
- if (include_size && FcPatternGetDouble (pattern, FC_SIZE, 0, &size) == FcResultMatch)
- pango_font_description_set_size (desc, size * PANGO_SCALE);
-
- 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);
-
- return desc;
-}
-
-static PangoFontDescription *
-make_alias_description (PangoXftFamily *xfamily,
- gboolean bold,
- gboolean italic)
-{
- PangoFontDescription *desc = pango_font_description_new ();
-
- pango_font_description_set_family (desc, xfamily->family_name);
- pango_font_description_set_style (desc, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL);
- pango_font_description_set_variant (desc, PANGO_VARIANT_NORMAL);
- pango_font_description_set_weight (desc, bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL);
- pango_font_description_set_stretch (desc, PANGO_STRETCH_NORMAL);
-
- return desc;
-}
-
-static PangoFontDescription *
-pango_xft_face_describe (PangoFontFace *face)
-{
- PangoXftFace *xface = PANGO_XFT_FACE (face);
- PangoXftFamily *xfamily = xface->family;
- PangoXftFontMap *xfontmap = xfamily->fontmap;
- PangoFontDescription *desc = NULL;
- FcResult res;
- FcPattern *match_pattern;
- FcPattern *result_pattern;
-
- if (is_alias_family (xfamily->family_name))
- {
- if (strcmp (xface->style, "Regular") == 0)
- return make_alias_description (xfamily, FALSE, FALSE);
- else if (strcmp (xface->style, "Bold") == 0)
- return make_alias_description (xfamily, TRUE, FALSE);
- else if (strcmp (xface->style, "Italic") == 0)
- return make_alias_description (xfamily, FALSE, TRUE);
- else /* Bold Italic */
- return make_alias_description (xfamily, TRUE, TRUE);
- }
-
- match_pattern = FcPatternBuild (NULL,
- FC_FAMILY, FcTypeString, xfamily->family_name,
- FC_STYLE, FcTypeString, xface->style,
- NULL);
-
- g_assert (match_pattern);
-
- result_pattern = XftFontMatch (xfontmap->display, xfontmap->screen, match_pattern, &res);
- if (result_pattern)
- {
- desc = _pango_xft_font_desc_from_pattern (result_pattern, FALSE);
- FcPatternDestroy (result_pattern);
- }
-
- FcPatternDestroy (match_pattern);
-
- return desc;
-}
-
-static const char *
-pango_xft_face_get_face_name (PangoFontFace *face)
-{
- PangoXftFace *xface = PANGO_XFT_FACE (face);
-
- return xface->style;
-}
-
-static void
-pango_xft_face_class_init (PangoFontFaceClass *class)
+pango_fc_do_finalize (PangoXftFontMap *fontmap)
{
- class->describe = pango_xft_face_describe;
- class->get_face_name = pango_xft_face_get_face_name;
-}
-
-GType
-pango_xft_face_get_type (void)
-{
- static GType object_type = 0;
-
- if (!object_type)
- {
- static const GTypeInfo object_info =
- {
- sizeof (PangoFontFaceClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) pango_xft_face_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (PangoXftFace),
- 0, /* n_preallocs */
- (GInstanceInitFunc) NULL,
- };
-
- object_type = g_type_register_static (PANGO_TYPE_FONT_FACE,
- "PangoXftFace",
- &object_info, 0);
- }
-
- return object_type;
-}
-
-/*
- * PangoXFontFamily
- */
-static PangoXftFace *
-create_face (PangoXftFamily *xfamily,
- const char *style)
-{
- PangoXftFace *face = g_object_new (PANGO_XFT_TYPE_FACE, NULL);
- face->style = g_strdup (style);
- face->family = xfamily;
-
- return face;
-}
-
-static void
-pango_xft_family_list_faces (PangoFontFamily *family,
- PangoFontFace ***faces,
- int *n_faces)
-{
- PangoXftFamily *xfamily = PANGO_XFT_FAMILY (family);
- PangoXftFontMap *xfontmap = xfamily->fontmap;
-
- if (xfamily->n_faces < 0)
- {
- FcFontSet *fontset;
- int i;
-
- if (is_alias_family (xfamily->family_name) || !xfontmap->display)
- {
- xfamily->n_faces = 4;
- xfamily->faces = g_new (PangoXftFace *, xfamily->n_faces);
-
- i = 0;
- xfamily->faces[i++] = create_face (xfamily, "Regular");
- xfamily->faces[i++] = create_face (xfamily, "Bold");
- xfamily->faces[i++] = create_face (xfamily, "Italic");
- xfamily->faces[i++] = create_face (xfamily, "Bold Italic");
- }
- else
- {
- fontset = XftListFonts (xfontmap->display, xfontmap->screen,
- FC_FAMILY, FcTypeString, xfamily->family_name,
- NULL,
- FC_STYLE,
- NULL);
-
- xfamily->n_faces = fontset->nfont;
- xfamily->faces = g_new (PangoXftFace *, xfamily->n_faces);
-
- for (i = 0; i < fontset->nfont; i++)
- {
- FcChar8 *s;
- FcResult res;
-
- res = FcPatternGetString (fontset->fonts[i], FC_STYLE, 0, (FcChar8 **) &s);
- if (res != FcResultMatch)
- s = "Regular";
-
- xfamily->faces[i] = create_face (xfamily, s);
- }
-
- FcFontSetDestroy (fontset);
- }
- }
-
- if (n_faces)
- *n_faces = xfamily->n_faces;
-
- if (faces)
- *faces = g_memdup (xfamily->faces, xfamily->n_faces * sizeof (PangoFontFace *));
-}
-
-const char *
-pango_xft_family_get_name (PangoFontFamily *family)
-{
- PangoXftFamily *xfamily = PANGO_XFT_FAMILY (family);
-
- return xfamily->family_name;
}
static void
-pango_xft_family_class_init (PangoFontFamilyClass *class)
+pango_fc_default_substitute (PangoXftFontMap *fontmap,
+ FcPattern *pattern)
{
- class->list_faces = pango_xft_family_list_faces;
- class->get_name = pango_xft_family_get_name;
-}
-
-void
-pango_xft_family_init (PangoXftFamily *xfamily)
-{
- xfamily->n_faces = -1;
-}
-
-GType
-pango_xft_family_get_type (void)
-{
- static GType object_type = 0;
-
- if (!object_type)
- {
- static const GTypeInfo object_info =
- {
- sizeof (PangoFontFamilyClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) pango_xft_family_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (PangoXftFamily),
- 0, /* n_preallocs */
- (GInstanceInitFunc) pango_xft_family_init,
- };
-
- object_type = g_type_register_static (PANGO_TYPE_FONT_FAMILY,
- "PangoXftFamily",
- &object_info, 0);
- }
-
- return object_type;
+ FcConfigSubstitute (NULL, pattern, FcMatchPattern);
+ if (fontmap->substitute_func)
+ fontmap->substitute_func (pattern, fontmap->substitute_data);
+ XftDefaultSubstitute (fontmap->display, fontmap->screen, pattern);
}
diff --git a/pango/pangoxft-private.h b/pango/pangoxft-private.h
index 07dbad44..194c4f2b 100644
--- a/pango/pangoxft-private.h
+++ b/pango/pangoxft-private.h
@@ -28,7 +28,6 @@
G_BEGIN_DECLS
typedef struct _PangoXftFont PangoXftFont;
-typedef struct _PangoXftCoverageKey PangoXftCoverageKey;
struct _PangoXftFont
{
@@ -49,12 +48,6 @@ struct _PangoXftFont
gboolean in_cache;
};
-struct _PangoXftCoverageKey
-{
- char *filename;
- int id; /* needed to handle TTC files with multiple faces */
-};
-
PangoXftFont * _pango_xft_font_new (PangoFontMap *font,
FcPattern *pattern);
void _pango_xft_font_map_cache_add (PangoFontMap *fontmap,
@@ -63,11 +56,8 @@ void _pango_xft_font_map_add (PangoFontMap *fo
PangoXftFont *xfont);
void _pango_xft_font_map_remove (PangoFontMap *fontmap,
PangoXftFont *xfont);
-void _pango_xft_font_map_set_coverage (PangoFontMap *fontmap,
- const PangoXftCoverageKey *key,
- PangoCoverage *coverage);
PangoCoverage *_pango_xft_font_map_get_coverage (PangoFontMap *fontmap,
- const PangoXftCoverageKey *key);
+ FcPattern *pattern);
void _pango_xft_font_map_get_info (PangoFontMap *fontmap,
Display **display,
int *screen);