summaryrefslogtreecommitdiff
path: root/pango/pangoxft-fontmap.c
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2000-12-15 01:10:13 +0000
committerOwen Taylor <otaylor@src.gnome.org>2000-12-15 01:10:13 +0000
commitf2bb9b92d5cebe5594e73e2eeea8a1a606da9005 (patch)
tree0eb5ddbd7f3c77b799603fcc21e444f6d9941d6c /pango/pangoxft-fontmap.c
parent016c4d7047fd3ac2f76667f4ffe3b3a22ad0b902 (diff)
downloadpango-f2bb9b92d5cebe5594e73e2eeea8a1a606da9005.tar.gz
Fix macro breakage.
Thu Dec 14 19:00:46 2000 Owen Taylor <otaylor@redhat.com> * modules/indic/pango-indic-script.h: Fix macro breakage. * modules/basic/tables-big.i: Remove extra copy of basic_ranges. * modules/thai/thai.c: Fix various warnings. * configure.in Makefile.am pangoxft.pc.in pango-config.in modules/basic/Makefile.am modules/basic/basic-xft.c pango/Makefile.am pango/pangoxft-font.[ch] pango/pangoxft-fontmap.c pango/pangoxft.h pango/pangoxft-private.h: Initial support for rendering via Xft and the Xrender extension.
Diffstat (limited to 'pango/pangoxft-fontmap.c')
-rw-r--r--pango/pangoxft-fontmap.c499
1 files changed, 499 insertions, 0 deletions
diff --git a/pango/pangoxft-fontmap.c b/pango/pangoxft-fontmap.c
new file mode 100644
index 00000000..03695f1b
--- /dev/null
+++ b/pango/pangoxft-fontmap.c
@@ -0,0 +1,499 @@
+/* Pango
+ * pangoxft-fontmap.h: Font handling
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * 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.
+ */
+
+#include "pango-fontmap.h"
+#include "pangoxft.h"
+#include "pangoxft-private.h"
+
+#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))
+#define PANGO_XFT_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_XFT_FONT_MAP, PangoXftFontMapClass))
+#define PANGO_XFT_IS_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_XFT_FONT_MAP))
+#define PANGO_XFT_IS_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_XFT_FONT_MAP))
+#define PANGO_XFT_FONT_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_XFT_FONT_MAP, PangoXftFontMapClass))
+
+/* Number of freed fonts */
+#define MAX_FREED_FONTS 16
+
+typedef struct _PangoXftFontMap PangoXftFontMap;
+typedef struct _PangoXftFontMapClass PangoXftFontMapClass;
+
+struct _PangoXftFontMap
+{
+ PangoFontMap parent_instance;
+
+ GHashTable *font_hash;
+ GHashTable *coverage_hash;
+ GQueue *freed_fonts;
+
+ Display *display;
+ int screen;
+};
+
+struct _PangoXftFontMapClass
+{
+ PangoFontMapClass parent_class;
+};
+
+static GType pango_xft_font_map_get_type (void);
+static void pango_xft_font_map_init (PangoXftFontMap *fontmap);
+static void pango_xft_font_map_class_init (PangoXftFontMapClass *class);
+
+static void pango_xft_font_map_finalize (GObject *object);
+static PangoFont *pango_xft_font_map_load_font (PangoFontMap *fontmap,
+ const PangoFontDescription *description);
+static void pango_xft_font_map_list_fonts (PangoFontMap *fontmap,
+ const gchar *family,
+ PangoFontDescription ***descs,
+ int *n_descs);
+static void pango_xft_font_map_list_families (PangoFontMap *fontmap,
+ gchar ***families,
+ int *n_families);
+
+static void pango_xft_font_map_cache_clear (PangoXftFontMap *xfontmap);
+static void pango_xft_font_map_cache_remove (PangoFontMap *fontmap,
+ PangoXftFont *xfont);
+
+static 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 (PangoXftFontMapClass),
+ (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)
+{
+}
+
+static void
+pango_xft_font_map_class_init (PangoXftFontMapClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontMapClass *font_map_class = PANGO_FONT_MAP_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class->finalize = pango_xft_font_map_finalize;
+ font_map_class->load_font = pango_xft_font_map_load_font;
+ font_map_class->list_fonts = pango_xft_font_map_list_fonts;
+ font_map_class->list_families = pango_xft_font_map_list_families;
+}
+
+static GSList *fontmaps = NULL;
+
+static guint
+font_description_hash (const PangoFontDescription *desc)
+{
+ guint hash = 0;
+
+ if (desc->family_name)
+ hash = g_str_hash (desc->family_name);
+
+ hash ^= desc->size;
+ hash ^= desc->style << 16;
+ hash ^= desc->variant << 18;
+ hash ^= desc->weight << 16;
+ hash ^= desc->stretch << 26;
+
+ return hash;
+}
+
+static PangoFontMap *
+pango_xft_get_font_map (Display *display,
+ int screen)
+{
+ PangoXftFontMap *xfontmap;
+ GSList *tmp_list = fontmaps;
+
+ g_return_val_if_fail (display != NULL, NULL);
+
+ /* Make sure that the type system is initialized */
+ g_type_init();
+
+ while (tmp_list)
+ {
+ xfontmap = tmp_list->data;
+
+ if (xfontmap->display == display &&
+ xfontmap->screen == screen)
+ return PANGO_FONT_MAP (xfontmap);
+ }
+
+ xfontmap = (PangoXftFontMap *)g_object_new (PANGO_TYPE_XFT_FONT_MAP, NULL);
+
+ xfontmap->display = display;
+ xfontmap->screen = screen;
+
+ xfontmap->font_hash = g_hash_table_new ((GHashFunc)font_description_hash,
+ (GEqualFunc)pango_font_description_equal);
+ xfontmap->coverage_hash = g_hash_table_new (g_str_hash, g_str_equal);
+ xfontmap->freed_fonts = g_queue_new ();
+
+ fontmaps = g_slist_prepend (fontmaps, xfontmap);
+
+ return PANGO_FONT_MAP (xfontmap);
+}
+
+PangoContext *
+pango_xft_get_context (Display *display,
+ int screen)
+{
+ PangoContext *result;
+
+ g_return_val_if_fail (display != NULL, NULL);
+
+ result = pango_context_new ();
+ pango_context_add_font_map (result, pango_xft_get_font_map (display, screen));
+
+ return result;
+}
+
+static void
+coverage_foreach (gpointer key, gpointer value, gpointer data)
+{
+ PangoCoverage *coverage = value;
+
+ g_free (key);
+ pango_coverage_unref (coverage);
+}
+
+static void
+pango_xft_font_map_finalize (GObject *object)
+{
+ PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (object);
+
+ fontmaps = g_slist_remove (fontmaps, object);
+
+ g_queue_free (xfontmap->freed_fonts);
+ g_hash_table_destroy (xfontmap->font_hash);
+
+ g_hash_table_foreach (xfontmap->coverage_hash, coverage_foreach, NULL);
+ g_hash_table_destroy (xfontmap->coverage_hash);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+void
+_pango_xft_font_map_add (PangoFontMap *fontmap,
+ PangoXftFont *xfont)
+{
+ PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
+
+ g_hash_table_insert (xfontmap->font_hash, xfont->description, xfont);
+}
+
+void
+_pango_xft_font_map_remove (PangoFontMap *fontmap,
+ PangoXftFont *xfont)
+{
+ PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
+
+ g_hash_table_remove (xfontmap->font_hash, xfont->description);
+}
+
+static PangoFontDescription *
+font_desc_from_pattern (XftPattern *pattern)
+{
+ PangoFontDescription *desc;
+ char *s;
+ int i;
+
+ desc = g_new (PangoFontDescription, 1);
+
+ g_assert (XftPatternGetString (pattern, XFT_FAMILY, 0, &s) == XftResultMatch);
+
+ desc->family_name = g_strdup (s);
+
+ if (XftPatternGetInteger (pattern, XFT_SLANT, 0, &i) == XftResultMatch)
+ {
+ if (i == XFT_SLANT_ROMAN)
+ desc->style = PANGO_STYLE_NORMAL;
+ else if (i == XFT_SLANT_OBLIQUE)
+ desc->style = PANGO_STYLE_OBLIQUE;
+ else
+ desc->style = PANGO_STYLE_ITALIC;
+ }
+ else
+ desc->style = PANGO_STYLE_NORMAL;
+
+ if (XftPatternGetInteger (pattern, XFT_WEIGHT, 0, &i) == XftResultMatch)
+ {
+ if (i < XFT_WEIGHT_LIGHT)
+ desc->weight = PANGO_WEIGHT_ULTRALIGHT;
+ else if (i < (XFT_WEIGHT_LIGHT + XFT_WEIGHT_MEDIUM) / 2)
+ desc->weight = PANGO_WEIGHT_LIGHT;
+ else if (i < (XFT_WEIGHT_MEDIUM + XFT_WEIGHT_DEMIBOLD) / 2)
+ desc->weight = PANGO_WEIGHT_NORMAL;
+ else if (i < (XFT_WEIGHT_DEMIBOLD + XFT_WEIGHT_BOLD) / 2)
+ desc->weight = 600;
+ else if (i < (XFT_WEIGHT_BOLD + XFT_WEIGHT_BLACK) / 2)
+ desc->weight = PANGO_WEIGHT_BOLD;
+ else
+ desc->weight = PANGO_WEIGHT_ULTRABOLD;
+ }
+
+ desc->variant = PANGO_VARIANT_NORMAL;
+ desc->stretch = PANGO_STRETCH_NORMAL;
+ desc->size = -1;
+
+ return desc;
+}
+
+
+static void
+pango_xft_font_map_list_fonts (PangoFontMap *fontmap,
+ const gchar *family,
+ PangoFontDescription ***descs,
+ int *n_descs)
+{
+ PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
+ XftFontSet *fontset;
+
+ if (family)
+ fontset = XftListFonts (xfontmap->display, xfontmap->screen,
+ XFT_ENCODING, XftTypeString, "iso10646-1",
+ XFT_FAMILY, XftTypeString, family,
+ NULL,
+ XFT_FAMILY,
+ XFT_STYLE,
+ XFT_WEIGHT,
+ XFT_SLANT,
+ NULL);
+ else
+ fontset = XftListFonts (xfontmap->display, xfontmap->screen,
+ XFT_ENCODING, XftTypeString, "iso10646-1",
+ NULL,
+ XFT_FAMILY,
+ XFT_STYLE,
+ XFT_WEIGHT,
+ XFT_SLANT,
+ NULL);
+
+ if (n_descs)
+ *n_descs = fontset->nfont;
+
+ if (descs)
+ {
+ gint i;
+
+ *descs = g_new (PangoFontDescription *, fontset->nfont);
+
+ for (i = 0; i < fontset->nfont; i++)
+ (*descs)[i] = font_desc_from_pattern (fontset->fonts[i]);
+ }
+
+ XftFontSetDestroy (fontset);
+}
+
+static void
+pango_xft_font_map_list_families (PangoFontMap *fontmap,
+ gchar ***families,
+ int *n_families)
+{
+ PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
+ XftFontSet *fontset;
+ int i;
+
+ fontset = XftListFonts (xfontmap->display, xfontmap->screen,
+ XFT_ENCODING, XftTypeString, "iso10646-1",
+ NULL,
+ XFT_FAMILY,
+ NULL);
+
+ if (n_families)
+ *n_families = fontset->nfont;
+
+ if (families)
+ {
+ *families = g_new (gchar *, fontset->nfont);
+
+ for (i = 0; i < fontset->nfont; i++)
+ {
+ char *s;
+ XftResult res;
+
+ res = XftPatternGetString (fontset->fonts[i], XFT_FAMILY, 0, &s);
+ g_assert (res == XftResultMatch);
+
+ (*families)[i] = g_strdup (s);
+ }
+ }
+
+ XftFontSetDestroy (fontset);
+}
+
+static PangoFont *
+pango_xft_font_map_load_font (PangoFontMap *fontmap,
+ const PangoFontDescription *description)
+{
+ PangoXftFontMap *xfontmap = (PangoXftFontMap *)fontmap;
+ PangoXftFont *font;
+ int slant;
+ int weight;
+ XftFont *xft_font;
+
+ font = g_hash_table_lookup (xfontmap->font_hash, description);
+
+ if (font)
+ {
+ if (font->in_cache)
+ pango_xft_font_map_cache_remove (fontmap, font);
+
+ return (PangoFont *)g_object_ref (G_OBJECT (font));
+ }
+
+ if (description->style == PANGO_STYLE_ITALIC)
+ slant = XFT_SLANT_ITALIC;
+ else if (description->style == PANGO_STYLE_OBLIQUE)
+ slant = XFT_SLANT_OBLIQUE;
+ else
+ slant = XFT_SLANT_ROMAN;
+
+ if (description->weight < (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_LIGHT) / 2)
+ weight = XFT_WEIGHT_LIGHT;
+ else if (description->weight < (PANGO_WEIGHT_NORMAL + 600) / 2)
+ weight = XFT_WEIGHT_MEDIUM;
+ else if (description->weight < (600 + PANGO_WEIGHT_BOLD) / 2)
+ weight = XFT_WEIGHT_DEMIBOLD;
+ else if (description->weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2)
+ weight = XFT_WEIGHT_BOLD;
+ else
+ weight = XFT_WEIGHT_BLACK;
+
+ xft_font = XftFontOpen (xfontmap->display, xfontmap->screen,
+ XFT_FAMILY, XftTypeString, description->family_name,
+ XFT_WEIGHT, XftTypeInteger, weight,
+ XFT_SLANT, XftTypeInteger, slant,
+ XFT_SIZE, XftTypeDouble, (double)description->size/PANGO_SCALE,
+ NULL);
+
+ if (xft_font)
+ font = _pango_xft_font_new (fontmap, description, xft_font);
+ else
+ return NULL;
+
+ return (PangoFont *)font;
+}
+
+void
+_pango_xft_font_map_cache_add (PangoFontMap *fontmap,
+ PangoXftFont *xfont)
+{
+ PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
+
+ if (xfontmap->freed_fonts->length == MAX_FREED_FONTS)
+ {
+ GObject *old_font = g_queue_pop_tail (xfontmap->freed_fonts);
+ g_object_unref (old_font);
+ }
+
+ g_object_ref (G_OBJECT (xfont));
+ g_queue_push_head (xfontmap->freed_fonts, xfont);
+ xfont->in_cache = TRUE;
+}
+
+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 char *name,
+ PangoCoverage *coverage)
+{
+ PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
+
+ g_hash_table_insert (xfontmap->coverage_hash, g_strdup (name),
+ pango_coverage_ref (coverage));
+}
+
+PangoCoverage *
+_pango_xft_font_map_get_coverage (PangoFontMap *fontmap,
+ const char *name)
+{
+ PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap);
+
+ return g_hash_table_lookup (xfontmap->coverage_hash, name);
+}
+
+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;
+}