summaryrefslogtreecommitdiff
path: root/pango
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
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')
-rw-r--r--pango/Makefile.am41
-rw-r--r--pango/pangoxft-font.c474
-rw-r--r--pango/pangoxft-fontmap.c499
-rw-r--r--pango/pangoxft-private.h63
-rw-r--r--pango/pangoxft.h61
5 files changed, 1122 insertions, 16 deletions
diff --git a/pango/Makefile.am b/pango/Makefile.am
index 4df0d880..7ffb4114 100644
--- a/pango/Makefile.am
+++ b/pango/Makefile.am
@@ -8,9 +8,19 @@ endif
INCLUDES = \
-DSYSCONFDIR=\"$(sysconfdir)\" \
-DLIBDIR=\"$(libdir)\" \
+ $(X_CFLAGS) \
-I$(top_srcdir)
-lib_LTLIBRARIES = libpango.la libpangox.la
+if HAVE_XFT
+XFT_HFILES=pangoxft.h
+XFT_BUILD_LIBS=libpangoxft.la
+else
+XFT_HFILES=
+XFT_BUILD_LIBS=
+endif
+
+lib_LTLIBRARIES = libpango.la libpangox.la $(XFT_BUILD_LIBS)
+
bin_PROGRAMS = pango-querymodules
libpango_la_SOURCES = \
@@ -53,7 +63,14 @@ libpango_la_LIBADD = mini-fribidi/libmini-fribidi.la
endif
libpangox_la_LDFLAGS = -release $(VERSION)
-libpangox_la_LIBADD = $(INCLUDED_MODULES)
+libpangox_la_LIBADD = $(INCLUDED_MODULES) $(X_LIBS)
+
+libpangoxft_la_SOURCES = \
+ pangoxft-font.c \
+ pangoxft-fontmap.c
+
+libpangoxft_la_LIBADD = $(INCLUDED_MODULES) $(XFT_LIBS)
+libpangoxft_la_LDFLAGS = -release $(VERSION)
pangoincludedir=$(includedir)/pango-1.0/pango
@@ -73,14 +90,19 @@ pangoinclude_HEADERS = \
pango-tabs.h \
pango-types.h \
pango-utils.h \
- pangox.h
+ pangox.h \
+ $(XFT_HFILES)
#
# As a temporary hack, we pull in libpangox here so that we can link
#
pango_querymodules_SOURCES = \
querymodules.c
+if HAVE_XFT
+pango_querymodules_LDADD = libpangox.la libpangoxft.la libpango.la $(GLIB_LIBS) $(FRIBIDI_LIBS) $(XFT_LIBS)
+else
pango_querymodules_LDADD = libpangox.la libpango.la $(GLIB_LIBS) $(FRIBIDI_LIBS) $(X_LIBS)
+endif
EXTRA_DIST = \
module-defs.c.win32 \
@@ -105,16 +127,3 @@ EXTRA_DIST = \
pangoft2.rc.in \
pangowin32.rc \
pangowin32.rc.in
-
-
-makefile.mingw: $(top_builddir)/config.status $(top_srcdir)/pango/makefile.mingw.in
- cd $(top_builddir) && CONFIG_FILES=pango/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-pango2.rc: $(top_builddir)/config.status $(top_srcdir)/pango/pango.rc.in
- cd $(top_builddir) && CONFIG_FILES=pango/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-pangoft2.rc: $(top_builddir)/config.status $(top_srcdir)/pango/pangoft2.rc.in
- cd $(top_builddir) && CONFIG_FILES=pango/$@ CONFIG_HEADERS= $(SHELL) ./config.status
-
-pangowin32.rc: $(top_builddir)/config.status $(top_srcdir)/pango/pangowin32.rc.in
- cd $(top_builddir) && CONFIG_FILES=pango/$@ CONFIG_HEADERS= $(SHELL) ./config.status
diff --git a/pango/pangoxft-font.c b/pango/pangoxft-font.c
new file mode 100644
index 00000000..66a3d356
--- /dev/null
+++ b/pango/pangoxft-font.c
@@ -0,0 +1,474 @@
+/* Pango
+ * pangoxft-font.c: Routines for handling X fonts
+ *
+ * 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 "pangoxft-private.h"
+#include "X11/Xft/XftFreetype.h"
+#include "modules.h"
+
+#define PANGO_TYPE_XFT_FONT (pango_xft_font_get_type ())
+#define PANGO_XFT_FONT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_XFT_FONT, PangoXftFont))
+#define PANGO_XFT_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_XFT_FONT, PangoXftFontClass))
+#define PANGO_XFT_IS_FONT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_XFT_FONT))
+#define PANGO_XFT_IS_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_XFT_FONT))
+#define PANGO_XFT_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_XFT_FONT, PangoXftFontClass))
+
+#define PANGO_XFT_UNKNOWN_FLAG 0x10000000
+
+typedef struct _PangoXftFontClass PangoXftFontClass;
+
+struct _PangoXftFontClass
+{
+ PangoFontClass parent_class;
+};
+
+static PangoFontClass *parent_class; /* Parent class structure for PangoXftFont */
+
+static void pango_xft_font_class_init (PangoXftFontClass *class);
+static void pango_xft_font_init (PangoXftFont *xfont);
+static void pango_xft_font_shutdown (GObject *object);
+static void pango_xft_font_finalize (GObject *object);
+
+static PangoFontDescription *pango_xft_font_describe (PangoFont *font);
+static PangoCoverage * pango_xft_font_get_coverage (PangoFont *font,
+ const char *lang);
+static PangoEngineShape * pango_xft_font_find_shaper (PangoFont *font,
+ const char *lang,
+ guint32 ch);
+static void pango_xft_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect);
+static void pango_xft_font_get_metrics (PangoFont *font,
+ const gchar *lang,
+ PangoFontMetrics *metrics);
+
+
+static GType
+pango_xft_font_get_type (void)
+{
+ static GType object_type = 0;
+
+ if (!object_type)
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (PangoXftFontClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) pango_xft_font_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (PangoXftFont),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) pango_xft_font_init,
+ };
+
+ object_type = g_type_register_static (PANGO_TYPE_FONT,
+ "PangoXftFont",
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+static void
+pango_xft_font_init (PangoXftFont *xfont)
+{
+ xfont->in_cache = FALSE;
+}
+
+static void
+pango_xft_font_class_init (PangoXftFontClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ PangoFontClass *font_class = PANGO_FONT_CLASS (class);
+
+ parent_class = g_type_class_peek_parent (class);
+
+ object_class->finalize = pango_xft_font_finalize;
+ object_class->shutdown = pango_xft_font_shutdown;
+
+ font_class->describe = pango_xft_font_describe;
+ font_class->get_coverage = pango_xft_font_get_coverage;
+ font_class->find_shaper = pango_xft_font_find_shaper;
+ font_class->get_glyph_extents = pango_xft_font_get_glyph_extents;
+ font_class->get_metrics = pango_xft_font_get_metrics;
+}
+
+PangoXftFont *
+_pango_xft_font_new (PangoFontMap *fontmap,
+ const PangoFontDescription *description,
+ XftFont *xft_font)
+{
+ PangoXftFont *xfont;
+
+ g_return_val_if_fail (fontmap != NULL, NULL);
+ g_return_val_if_fail (description != NULL, NULL);
+ g_return_val_if_fail (xft_font != NULL, NULL);
+
+ xfont = (PangoXftFont *)g_object_new (PANGO_TYPE_XFT_FONT, NULL);
+
+ xfont->fontmap = fontmap;
+
+ g_object_ref (G_OBJECT (fontmap));
+ xfont->description = pango_font_description_copy (description);
+ xfont->xft_font = xft_font;
+
+ _pango_xft_font_map_add (xfont->fontmap, xfont);
+
+ return xfont;
+}
+
+static PangoFont *
+get_mini_font (PangoFont *font)
+{
+ PangoXftFont *xfont = (PangoXftFont *)font;
+
+ if (!xfont->mini_font)
+ {
+ Display *display;
+ PangoFontDescription desc;
+ int i;
+ int width = 0, height = 0;
+ XGlyphInfo extents;
+ XftFont *mini_xft;
+
+ _pango_xft_font_map_get_info (xfont->fontmap, &display, NULL);
+
+ desc.family_name = "monospace";
+ desc.style = PANGO_STYLE_NORMAL;
+ desc.variant = PANGO_VARIANT_NORMAL;
+ desc.weight = PANGO_WEIGHT_NORMAL;
+
+ desc.size = 0.5 * xfont->description->size;
+
+ xfont->mini_font = pango_font_map_load_font (xfont->fontmap, &desc);
+ mini_xft = ((PangoXftFont *)xfont->mini_font)->xft_font;
+
+ for (i = 0 ; i < 16 ; i++)
+ {
+ char c = i < 10 ? '0' + i : 'A' + i - 10;
+
+ XftTextExtents8 (display, mini_xft, &c, 1, &extents);
+
+ width = MAX (width, extents.width);
+ height = MAX (height, extents.height);
+ }
+
+ xfont->mini_width = width;
+ xfont->mini_height = height;
+ xfont->mini_pad = MAX (height / 10, 1);
+ }
+
+ return xfont->mini_font;
+}
+
+static void
+draw_box (XftDraw *draw,
+ XftColor *color,
+ PangoXftFont *xfont,
+ gint x,
+ gint y,
+ gint width,
+ gint height)
+{
+ XftDrawRect (draw, color,
+ x, y, width, xfont->mini_pad);
+ XftDrawRect (draw, color,
+ x, y + xfont->mini_pad, xfont->mini_pad, height - xfont->mini_pad * 2);
+ XftDrawRect (draw, color,
+ x + width - xfont->mini_pad, y + xfont->mini_pad, xfont->mini_pad, height - xfont->mini_pad * 2);
+ XftDrawRect (draw, color,
+ x, y + height - xfont->mini_pad, width, xfont->mini_pad);
+}
+
+void
+pango_xft_render (XftDraw *draw,
+ XftColor *color,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y)
+{
+ PangoXftFont *xfont = PANGO_XFT_FONT (font);
+ Display *display;
+ int i;
+ int x_off = 0;
+
+ g_return_if_fail (draw != NULL);
+ g_return_if_fail (color != NULL);
+ g_return_if_fail (font != NULL);
+ g_return_if_fail (glyphs != NULL);
+
+ /* Slow initial implementation. For speed, it should really
+ * collect the characters into runs, and draw multiple
+ * characters with each XftDrawString32 call.
+ */
+
+ _pango_xft_font_map_get_info (xfont->fontmap, &display, NULL);
+
+ for (i=0; i<glyphs->num_glyphs; i++)
+ {
+ PangoGlyph glyph = glyphs->glyphs[i].glyph;
+
+ if (glyph)
+ {
+ if (glyph & PANGO_XFT_UNKNOWN_FLAG)
+ {
+ char buf[5];
+ int ys[3];
+ int xs[3];
+ int j, k;
+
+ PangoFont *mini_font = get_mini_font (font);
+ XftFont *mini_xft = ((PangoXftFont *)mini_font)->xft_font;
+
+ glyph &= ~PANGO_XFT_UNKNOWN_FLAG;
+
+ ys[0] = y + PANGO_PIXELS (glyphs->glyphs[i].geometry.y_offset) - xfont->xft_font->ascent + (xfont->xft_font->ascent + xfont->xft_font->descent - xfont->mini_height * 2 - xfont->mini_pad * 5) / 2;
+ ys[1] = ys[0] + 2 * xfont->mini_pad + xfont->mini_height;
+ ys[2] = ys[1] + xfont->mini_height + xfont->mini_pad;
+
+ xs[0] = x + PANGO_PIXELS (x_off + glyphs->glyphs[i].geometry.x_offset);
+ xs[1] = xs[0] + 2 * xfont->mini_pad;
+ xs[2] = xs[1] + xfont->mini_width + xfont->mini_pad;
+
+ draw_box (draw, color, xfont,
+ xs[0], ys[0],
+ xfont->mini_width * 2 + xfont->mini_pad * 5,
+ xfont->mini_height * 2 + xfont->mini_pad * 5);
+
+ g_snprintf (buf, sizeof(buf), "%04X", glyph);
+
+ for (j = 0; j < 2; j++)
+ for (k = 0; k < 2; k++)
+ XftDrawString8 (draw, color, mini_xft,
+ xs[k+1], ys[j+1],
+ &buf[2*j + k], 1);
+ }
+ else
+ XftDrawString32 (draw, color, xfont->xft_font,
+ x + PANGO_PIXELS (x_off + glyphs->glyphs[i].geometry.x_offset),
+ y + PANGO_PIXELS (glyphs->glyphs[i].geometry.y_offset),
+ &glyph, 1);
+ }
+
+ x_off += glyphs->glyphs[i].geometry.width;
+ }
+}
+
+static void
+pango_xft_font_get_metrics (PangoFont *font,
+ const gchar *lang,
+ PangoFontMetrics *metrics)
+{
+ PangoXftFont *xfont = (PangoXftFont *)font;
+
+ metrics->ascent = PANGO_SCALE * xfont->xft_font->ascent;
+ metrics->descent = PANGO_SCALE * xfont->xft_font->descent;
+
+ return;
+}
+
+static void
+pango_xft_font_shutdown (GObject *object)
+{
+ PangoXftFont *xfont = PANGO_XFT_FONT (object);
+
+ /* If the font is not already in the freed-fonts cache, add it,
+ * if it is already there, do nothing and the font will be
+ * freed.
+ */
+ if (!xfont->in_cache && xfont->fontmap)
+ _pango_xft_font_map_cache_add (xfont->fontmap, xfont);
+
+ G_OBJECT_CLASS (parent_class)->shutdown (object);
+}
+
+static void
+pango_xft_font_finalize (GObject *object)
+{
+ PangoXftFont *xfont = (PangoXftFont *)object;
+
+ _pango_xft_font_map_remove (xfont->fontmap, xfont);
+
+ if (xfont->mini_font)
+ g_object_unref (xfont->mini_font);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static PangoFontDescription *
+pango_xft_font_describe (PangoFont *font)
+{
+ PangoXftFont *xfont = (PangoXftFont *)font;
+
+ return pango_font_description_copy (xfont->description);
+}
+
+static PangoCoverage *
+pango_xft_font_get_coverage (PangoFont *font,
+ const char *lang)
+{
+ PangoXftFont *xfont = (PangoXftFont *)font;
+ PangoCoverage *coverage;
+ Display *display;
+ int i;
+
+ _pango_xft_font_map_get_info (xfont->fontmap, &display, NULL);
+
+ coverage = _pango_xft_font_map_get_coverage (xfont->fontmap,
+ xfont->description->family_name);
+
+ if (coverage)
+ return pango_coverage_ref (coverage);
+
+ /* Ugh, this is going to be SLOW */
+
+ coverage = pango_coverage_new ();
+ for (i = 0; i < G_MAXUSHORT; i++)
+ {
+ if (XftGlyphExists (display, xfont->xft_font, i))
+ pango_coverage_set (coverage, i, PANGO_COVERAGE_EXACT);
+ }
+
+ _pango_xft_font_map_set_coverage (xfont->fontmap, xfont->description->family_name, coverage);
+
+ return coverage;
+}
+
+static void
+pango_xft_font_get_glyph_extents (PangoFont *font,
+ PangoGlyph glyph,
+ PangoRectangle *ink_rect,
+ PangoRectangle *logical_rect)
+{
+ PangoXftFont *xfont = (PangoXftFont *)font;
+ XGlyphInfo extents;
+ Display *display;
+
+ _pango_xft_font_map_get_info (xfont->fontmap, &display, NULL);
+
+ if (glyph == (PangoGlyph)-1)
+ glyph = 0;
+
+ if (glyph & PANGO_XFT_UNKNOWN_FLAG)
+ {
+ get_mini_font (font);
+
+ if (ink_rect)
+ {
+ ink_rect->x = 0;
+ ink_rect->y = PANGO_SCALE * (- xfont->xft_font->ascent + (xfont->xft_font->ascent + xfont->xft_font->descent - xfont->mini_height * 2 - xfont->mini_pad * 5) / 2);
+ ink_rect->width = PANGO_SCALE * (xfont->mini_width * 2 + xfont->mini_pad * 5);
+ ink_rect->height = PANGO_SCALE * (xfont->mini_height * 2 + xfont->mini_pad * 5);
+ }
+
+ if (logical_rect)
+ {
+ logical_rect->x = 0;
+ logical_rect->y = - PANGO_SCALE * xfont->xft_font->ascent;
+ logical_rect->width = PANGO_SCALE * (xfont->mini_width * 2 + xfont->mini_pad * 6);
+ logical_rect->height = (xfont->xft_font->ascent + xfont->xft_font->descent) * PANGO_SCALE;
+ }
+ }
+ else
+ {
+ XftTextExtents32 (display, xfont->xft_font, &glyph, 1, &extents);
+
+ if (ink_rect)
+ {
+ ink_rect->x = extents.x * PANGO_SCALE;
+ ink_rect->y = extents.y * PANGO_SCALE;
+ ink_rect->width = extents.width * PANGO_SCALE;
+ ink_rect->height = extents.height * PANGO_SCALE;
+ }
+
+ if (logical_rect)
+ {
+ logical_rect->x = 0;
+ logical_rect->y = - xfont->xft_font->ascent * PANGO_SCALE;
+ logical_rect->width = extents.xOff * PANGO_SCALE;
+ logical_rect->height = (xfont->xft_font->ascent + xfont->xft_font->descent) * PANGO_SCALE;
+ }
+ }
+}
+
+static PangoMap *
+pango_xft_get_shaper_map (const char *lang)
+{
+ static guint engine_type_id = 0;
+ static guint render_type_id = 0;
+
+ if (engine_type_id == 0)
+ {
+ engine_type_id = g_quark_from_static_string (PANGO_ENGINE_TYPE_SHAPE);
+ render_type_id = g_quark_from_static_string (PANGO_RENDER_TYPE_XFT);
+ }
+
+ return pango_find_map (lang, engine_type_id, render_type_id);
+}
+
+static PangoEngineShape *
+pango_xft_font_find_shaper (PangoFont *font,
+ const gchar *lang,
+ guint32 ch)
+{
+ PangoMap *shape_map = NULL;
+
+ shape_map = pango_xft_get_shaper_map (lang);
+ return (PangoEngineShape *)pango_map_get_engine (shape_map, ch);
+}
+
+XftFont *
+pango_xft_font_get_font (PangoFont *font)
+{
+ PangoXftFont *xfont;
+
+ g_return_val_if_fail (PANGO_XFT_IS_FONT (font), NULL);
+
+ xfont = PANGO_XFT_FONT (font);
+
+ return xfont->xft_font;
+}
+
+Display *
+pango_xft_font_get_display (PangoFont *font)
+{
+ PangoXftFont *xfont;
+ Display *display;
+
+ g_return_val_if_fail (PANGO_XFT_IS_FONT (font), NULL);
+
+ xfont = PANGO_XFT_FONT (font);
+ _pango_xft_font_map_get_info (xfont->fontmap, &display, NULL);
+
+ return display;
+}
+
+PangoGlyph
+pango_xft_font_get_unknown_glyph (PangoFont *font,
+ gunichar wc)
+{
+ g_return_val_if_fail (PANGO_XFT_IS_FONT (font), -1);
+
+ return wc | PANGO_XFT_UNKNOWN_FLAG;
+}
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;
+}
diff --git a/pango/pangoxft-private.h b/pango/pangoxft-private.h
new file mode 100644
index 00000000..7cf7dc2e
--- /dev/null
+++ b/pango/pangoxft-private.h
@@ -0,0 +1,63 @@
+/* Pango
+ * pangox-private.h:
+ *
+ * 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 <pangoxft.h>
+
+#ifndef __PANGOXFT_PRIVATE_H__
+#define __PANGOXFT_PRIVATE_H__
+
+typedef struct _PangoXftFont PangoXftFont;
+
+struct _PangoXftFont
+{
+ PangoFont parent_instance;
+
+ XftFont *xft_font;
+ PangoFont *mini_font;
+ PangoFontMap *fontmap;
+ PangoFontDescription *description;
+
+ guint16 mini_width;
+ guint16 mini_height;
+ guint16 mini_pad;
+
+ gboolean in_cache;
+};
+
+PangoXftFont * _pango_xft_font_new (PangoFontMap *font,
+ const PangoFontDescription *description,
+ XftFont *xft_font);
+void _pango_xft_font_map_cache_add (PangoFontMap *fontmap,
+ PangoXftFont *xfont);
+void _pango_xft_font_map_add (PangoFontMap *fontmap,
+ PangoXftFont *xfont);
+void _pango_xft_font_map_remove (PangoFontMap *fontmap,
+ PangoXftFont *xfont);
+void _pango_xft_font_map_set_coverage (PangoFontMap *fontmap,
+ const char *name,
+ PangoCoverage *coverage);
+PangoCoverage *_pango_xft_font_map_get_coverage (PangoFontMap *fontmap,
+ const char *name);
+void _pango_xft_font_map_get_info (PangoFontMap *fontmap,
+ Display **display,
+ int *screen);
+
+#endif /* __PANGOXFT_PRIVATE_H__ */
diff --git a/pango/pangoxft.h b/pango/pangoxft.h
new file mode 100644
index 00000000..b7636ee4
--- /dev/null
+++ b/pango/pangoxft.h
@@ -0,0 +1,61 @@
+/* Pango
+ * pangox.h:
+ *
+ * Copyright (C) 1999 Red Hat Software
+ * Copyright (C) 2000 SuSE Linux Ltd
+ *
+ * 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.
+ */
+
+#ifndef __PANGOXFT_H__
+#define __PANGOXFT_H__
+
+#include <pango/pango.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <X11/Xlib.h>
+#include <X11/Xft/Xft.h>
+
+#define PANGO_RENDER_TYPE_XFT "PangoRenderXft"
+
+/* Calls for applications
+ */
+PangoContext * pango_xft_get_context (Display *display,
+ int screen);
+void pango_xft_render (XftDraw *draw,
+ XftColor *color,
+ PangoFont *font,
+ PangoGlyphString *glyphs,
+ gint x,
+ gint y);
+
+/* For shape engines
+ */
+
+XftFont * pango_xft_font_get_font (PangoFont *font);
+Display * pango_xft_font_get_display (PangoFont *font);
+PangoGlyph pango_xft_font_get_unknown_glyph (PangoFont *font,
+ gunichar wc);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __PANGOXFT_H__ */