From 94f39b93e929db7881070f4b5e1f5dc3c106e3fb Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Sun, 3 Aug 2003 02:35:20 +0000 Subject: Make pangoxft depend on pangoft2. Sat Aug 2 14:33:28 2003 Owen Taylor * pango/Makefile.am (libpangoxft_1_0_la_LIBADD): Make pangoxft depend on pangoft2. * pango/pangofc-fontmap.[ch]: Make pangofc-fontmap.cI into a real base class. * pango/pangofc-font.[ch]: Move some of the pangoxft/ pangoft2 implementation here. * pango/pangoft2.c pango/pangoft2-fontmap.c pango/pangoft2-private.h pango/pangoxft-font.c pango/pangoxft2-fontmap.c pango/pangoxft-private.h: Adapt to the new scheme * modules/*/Makefile.am Modules/*/*/*-fc.c: Don't build separate FT2 and Xft shapers, just build one Fc shaper. * docs/pango-sections.txt docs/pango-docs.sgml docs/tmpl/pangofc-font{,map}.sgml: Basic docs for the new stuff. * configure.in: Up pango_module_version to 1.4.0. --- pango/Makefile.am | 24 +- pango/modules.h | 3 +- pango/pangofc-font.c | 320 ++++++++++++- pango/pangofc-font.h | 66 ++- pango/pangofc-fontmap.c | 386 +++++++++++----- pango/pangofc-fontmap.cI | 1138 ---------------------------------------------- pango/pangofc-fontmap.h | 106 +++++ pango/pangofc-private.h | 39 ++ pango/pangoft2-fontmap.c | 166 +++---- pango/pangoft2-private.h | 18 +- pango/pangoft2.c | 221 +-------- pango/pangoft2.h | 2 + pango/pangoxft-font.c | 285 ++---------- pango/pangoxft-fontmap.c | 181 ++++---- pango/pangoxft-private.h | 27 +- pango/pangoxft.h | 2 + 16 files changed, 1050 insertions(+), 1934 deletions(-) delete mode 100644 pango/pangofc-fontmap.cI create mode 100644 pango/pangofc-fontmap.h create mode 100644 pango/pangofc-private.h (limited to 'pango') diff --git a/pango/Makefile.am b/pango/Makefile.am index ac541e05..a7de4dba 100644 --- a/pango/Makefile.am +++ b/pango/Makefile.am @@ -67,7 +67,6 @@ libpango_1_0_la_SOURCES = \ pango-markup.c \ pango-tabs.c \ pango-utils.c \ - pangofc-font.c \ reorder-items.c \ shape.c \ pango-enum-types.c @@ -90,7 +89,8 @@ pango_headers = \ pango-tabs.h \ pango-types.h \ pango-utils.h \ - pangofc-font.h + pangofc-font.h \ + pangofc-fontmap.h pangoinclude_HEADERS = \ $(pango_headers) \ @@ -152,14 +152,13 @@ lib_LTLIBRARIES += libpangoxft-1.0.la endif libpangoxft_1_0_la_LDFLAGS = -version-info $(LT_VERSION_INFO) -libpangoxft_1_0_la_LIBADD = opentype/libpango-ot.la libpango-$(PANGO_API_VERSION).la $(INCLUDED_XFT_MODULES) $(XFT_LIBS) +libpangoxft_1_0_la_LIBADD = libpangoft2-$(PANGO_API_VERSION).la libpango-$(PANGO_API_VERSION).la $(INCLUDED_XFT_MODULES) $(XFT_LIBS) libpangoxft_1_0_la_DEPENDENCIES = libpango-$(PANGO_API_VERSION).la $(INCLUDED_XFT_MODULES) libpangoxft_1_0_la_SOURCES = \ pangoxft-font.c \ pangoxft-fontmap.c \ - pangoxft-private.h \ - module-defs-xft.c + pangoxft-private.h # ------------------- libpangoft2 ------------------- @@ -174,11 +173,14 @@ libpangoft2_1_0_la_LIBADD = opentype/libpango-ot.la libpango-$(PANGO_API_VERSION libpangoft2_1_0_la_DEPENDENCIES = libpango-$(PANGO_API_VERSION).la $(INCLUDED_FT2_MODULES) libpangoft2_1_0_la_SOURCES = \ + pangofc-font.c \ + pangofc-fontmap.c \ + pangofc-private.h \ pangoft2.h \ pangoft2.c \ pangoft2-private.h \ pangoft2-fontmap.c \ - module-defs-ft2.c + module-defs-fc.c if OS_WIN32 libpangoft2_1_0_la_LDFLAGS += -export-symbols pangoft2.def @@ -292,10 +294,9 @@ pango_querymodules_LDADD += libpango-$(PANGO_API_VERSION).la $(GLIB_LIBS) EXTRA_DIST = \ pango-enum-types.h \ - module-defs-ft2.c.win32 \ + module-defs-fc.c.win32 \ module-defs-win32.c.win32 \ module-defs.h \ - pangofc-fontmap.cI \ pango.def \ pangowin32.def \ pangoft2.def \ @@ -322,9 +323,7 @@ module-defs.h: $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status pango/$@ module-defs-x.c: $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status pango/$@ -module-defs-xft.c: $(top_builddir)/config.status - cd $(top_builddir) && $(SHELL) ./config.status pango/$@ -module-defs-ft2.c: $(top_builddir)/config.status +module-defs-fc.c: $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status pango/$@ module-defs-win32.c: $(top_builddir)/config.status cd $(top_builddir) && $(SHELL) ./config.status pango/$@ @@ -336,8 +335,7 @@ CLEANFILES = \ s-enum-types-c \ module-defs.h \ module-defs-x.c \ - module-defs-xft.c \ - module-defs-ft2.c \ + module-defs-fc.c \ module-defs-win32.c diff --git a/pango/modules.h b/pango/modules.h index 56707b06..c8f306df 100644 --- a/pango/modules.h +++ b/pango/modules.h @@ -26,8 +26,7 @@ #define __MODULES_H__ extern PangoIncludedModule _pango_included_x_modules[]; -extern PangoIncludedModule _pango_included_xft_modules[]; -extern PangoIncludedModule _pango_included_ft2_modules[]; +extern PangoIncludedModule _pango_included_fc_modules[]; extern PangoIncludedModule _pango_included_win32_modules[]; #endif /* __MODULES_H__ */ diff --git a/pango/pangofc-font.c b/pango/pangofc-font.c index aadb2e08..bf218f73 100644 --- a/pango/pangofc-font.c +++ b/pango/pangofc-font.c @@ -20,6 +20,48 @@ */ #include "pangofc-font.h" +#include "pangofc-fontmap.h" +#include "pangofc-private.h" +#include "pango-layout.h" +#include "pango-modules.h" +#include "pango-utils.h" + +#define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6)) +#define PANGO_PIXELS_26_6(d) \ + (((d) >= 0) ? \ + ((d) + PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6 : \ + ((d) - PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6) +#define PANGO_UNITS_26_6(d) (PANGO_SCALE_26_6 * (d)) + +typedef struct _PangoFcMetricsInfo PangoFcMetricsInfo; + +struct _PangoFcMetricsInfo +{ + const char *sample_str; + PangoFontMetrics *metrics; +}; + +enum { + PROP_0, + PROP_PATTERN +}; + +static void pango_fc_font_class_init (PangoFcFontClass *class); +static void pango_fc_font_finalize (GObject *object); +static void pango_fc_font_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec); +static PangoEngineShape * pango_fc_font_find_shaper (PangoFont *font, + PangoLanguage *language, + guint32 ch); +static PangoCoverage * pango_fc_font_get_coverage (PangoFont *font, + PangoLanguage *language); +static PangoFontMetrics * pango_fc_font_get_metrics (PangoFont *font, + PangoLanguage *language); +static PangoFontDescription *pango_fc_font_describe (PangoFont *font); + +static GObjectClass *parent_class; GType pango_fc_font_get_type (void) @@ -33,7 +75,7 @@ pango_fc_font_get_type (void) sizeof (PangoFcFontClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, - NULL, /* class_init */ + (GClassInitFunc) pango_fc_font_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (PangoFcFont), @@ -43,12 +85,245 @@ pango_fc_font_get_type (void) object_type = g_type_register_static (PANGO_TYPE_FONT, "PangoFcFont", - &object_info, 0); + &object_info, + G_TYPE_FLAG_ABSTRACT); } return object_type; } +static void +pango_fc_font_class_init (PangoFcFontClass *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_fc_font_finalize; + object_class->set_property = pango_fc_font_set_property; + font_class->describe = pango_fc_font_describe; + font_class->find_shaper = pango_fc_font_find_shaper; + font_class->get_coverage = pango_fc_font_get_coverage; + font_class->get_metrics = pango_fc_font_get_metrics; + + g_object_class_install_property (object_class, PROP_PATTERN, + g_param_spec_pointer ("pattern", + "Pattern", + "The fontconfig pattern for this font", + G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); +} + +static void +free_metrics_info (PangoFcMetricsInfo *info) +{ + pango_font_metrics_unref (info->metrics); + g_free (info); +} + +static void +pango_fc_font_finalize (GObject *object) +{ + PangoFcFont *fcfont = PANGO_FC_FONT (object); + + g_slist_foreach (fcfont->metrics_by_lang, (GFunc)free_metrics_info, NULL); + g_slist_free (fcfont->metrics_by_lang); + + if (fcfont->fontmap) + _pango_fc_font_map_remove (PANGO_FC_FONT_MAP (fcfont->fontmap), fcfont); + + FcPatternDestroy (fcfont->font_pattern); + pango_font_description_free (fcfont->description); + + parent_class->finalize (object); +} + +static void +pango_fc_font_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) + { + case PROP_PATTERN: + { + PangoFcFont *fcfont = PANGO_FC_FONT (object); + FcPattern *pattern = g_value_get_pointer (value); + + g_return_if_fail (pattern != NULL); + g_return_if_fail (fcfont->font_pattern == NULL); + + FcPatternReference (pattern); + fcfont->font_pattern = pattern; + fcfont->description = pango_fc_font_description_from_pattern (pattern, TRUE); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static PangoFontDescription * +pango_fc_font_describe (PangoFont *font) +{ + PangoFcFont *fcfont = (PangoFcFont *)font; + + return pango_font_description_copy (fcfont->description); +} + +static PangoMap * +pango_fc_get_shaper_map (PangoLanguage *language) +{ + 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_FC); + } + + return pango_find_map (language, engine_type_id, render_type_id); +} + +static PangoEngineShape * +pango_fc_font_find_shaper (PangoFont *font, + PangoLanguage *language, + guint32 ch) +{ + PangoMap *shaper_map = NULL; + + shaper_map = pango_fc_get_shaper_map (language); + return (PangoEngineShape *)pango_map_get_engine (shaper_map, ch); +} + +static PangoCoverage * +pango_fc_font_get_coverage (PangoFont *font, + PangoLanguage *language) +{ + PangoFcFont *fcfont = (PangoFcFont *)font; + + return _pango_fc_font_map_get_coverage (PANGO_FC_FONT_MAP (fcfont->fontmap), + fcfont->font_pattern); +} + +/* For Xft, it would be slightly more efficient to simply to + * call Xft, and also more robust against changes in Xft. + * But for now, we simply use the same code for all backends. + * + * The code in this function is partly based on code from Xft, + * Copyright 2000 Keith Packard + */ +static void +get_face_metrics (PangoFcFont *fcfont, + PangoFontMetrics *metrics) +{ + FT_Face face = pango_fc_font_lock_face (fcfont); + FcMatrix *fc_matrix; + FT_Matrix ft_matrix; + gboolean have_transform = FALSE; + + if (FcPatternGetMatrix (fcfont->font_pattern, + FC_MATRIX, 0, &fc_matrix) == FcResultMatch) + { + ft_matrix.xx = 0x10000L * fc_matrix->xx; + ft_matrix.yy = 0x10000L * fc_matrix->yy; + ft_matrix.xy = 0x10000L * fc_matrix->xy; + ft_matrix.yx = 0x10000L * fc_matrix->yx; + + have_transform = (ft_matrix.xx != 0x10000 || ft_matrix.xy != 0 || + ft_matrix.yx != 0 || ft_matrix.yy != 0x10000); + } + + if (have_transform) + { + FT_Vector vector; + + vector.x = 0; + vector.y = face->size->metrics.descender; + FT_Vector_Transform (&vector, &ft_matrix); + metrics->descent = PANGO_UNITS_26_6 (vector.y); + + vector.x = 0; + vector.y = face->size->metrics.ascender; + FT_Vector_Transform (&vector, &ft_matrix); + metrics->ascent = PANGO_UNITS_26_6 (vector.y); + } + else + { + metrics->descent = PANGO_UNITS_26_6 (face->size->metrics.descender); + metrics->ascent = PANGO_UNITS_26_6 (face->size->metrics.ascender); + } + + pango_fc_font_unlock_face (fcfont); +} + + +static PangoFontMetrics * +pango_fc_font_get_metrics (PangoFont *font, + PangoLanguage *language) +{ + PangoFcFont *fcfont = PANGO_FC_FONT (font); + PangoFcMetricsInfo *info = NULL; /* Quiet gcc */ + GSList *tmp_list; + + const char *sample_str = pango_language_get_sample_string (language); + + tmp_list = fcfont->metrics_by_lang; + while (tmp_list) + { + info = tmp_list->data; + + if (info->sample_str == sample_str) /* We _don't_ need strcmp */ + break; + + tmp_list = tmp_list->next; + } + + if (!tmp_list) + { + PangoLayout *layout; + PangoRectangle extents; + PangoContext *context; + + info = g_new0 (PangoFcMetricsInfo, 1); + fcfont->metrics_by_lang = g_slist_prepend (fcfont->metrics_by_lang, + info); + + if (fcfont->fontmap) + { + info->sample_str = sample_str; + info->metrics = pango_font_metrics_new (); + + get_face_metrics (fcfont, info->metrics); + + context = pango_fc_font_map_create_context (PANGO_FC_FONT_MAP (fcfont->fontmap)); + pango_context_set_language (context, language); + + layout = pango_layout_new (context); + pango_layout_set_font_description (layout, fcfont->description); + + pango_layout_set_text (layout, sample_str, -1); + pango_layout_get_extents (layout, NULL, &extents); + + info->metrics->approximate_char_width = + extents.width / g_utf8_strlen (sample_str, -1); + + pango_layout_set_text (layout, "0123456789", -1); + pango_layout_get_extents (layout, NULL, &extents); + + info->metrics->approximate_digit_width = extents.width / 10; + + g_object_unref (layout); + g_object_unref (context); + } + } + + return pango_font_metrics_ref (info->metrics); +} + /** * pango_fc_font_lock_face: * @font: a #PangoFcFont. @@ -151,6 +426,15 @@ pango_fc_font_get_unknown_glyph (PangoFcFont *font, return PANGO_FC_FONT_GET_CLASS (font)->get_unknown_glyph (font, wc); } +void +_pango_fc_font_shutdown (PangoFcFont *font) +{ + g_return_if_fail (PANGO_IS_FC_FONT (font)); + + if (PANGO_FC_FONT_GET_CLASS (font)->shutdown) + PANGO_FC_FONT_GET_CLASS (font)->shutdown (font); +} + /** * pango_fc_font_kern_glyphs * @font: a #PangoFcFont @@ -165,5 +449,35 @@ void pango_fc_font_kern_glyphs (PangoFcFont *font, PangoGlyphString *glyphs) { - PANGO_FC_FONT_GET_CLASS (font)->kern_glyphs (font, glyphs); + FT_Face face; + FT_Error error; + FT_Vector kerning; + int i; + + g_return_if_fail (PANGO_IS_FC_FONT (font)); + g_return_if_fail (glyphs != NULL); + + face = pango_fc_font_lock_face (font); + if (!face) + return; + + if (!FT_HAS_KERNING (face)) + { + pango_fc_font_unlock_face (font); + return; + } + + for (i = 1; i < glyphs->num_glyphs; ++i) + { + error = FT_Get_Kerning (face, + glyphs->glyphs[i-1].glyph, + glyphs->glyphs[i].glyph, + ft_kerning_default, + &kerning); + + if (error == FT_Err_Ok) + glyphs->glyphs[i-1].geometry.width += PANGO_UNITS_26_6 (kerning.x); + } + + pango_fc_font_unlock_face (font); } diff --git a/pango/pangofc-font.h b/pango/pangofc-font.h index 6e666542..315abd2e 100644 --- a/pango/pangofc-font.h +++ b/pango/pangofc-font.h @@ -1,5 +1,5 @@ /* Pango - * pangofc-font.h: Shared interfaces for fontconfig-based backends + * pangofc-font.h: Base fontmap type for fontconfig-based backends * * Copyright (C) 2003 Red Hat Software * @@ -23,11 +23,11 @@ #define __PANGO_FC_FONT_H__ #include +#include #include +#include #include -#if defined(PANGO_ENABLE_ENGINE) || defined(PANGO_ENABLE_BACKEND) - G_BEGIN_DECLS #define PANGO_TYPE_FC_FONT (pango_fc_font_get_type ()) @@ -37,19 +37,68 @@ G_BEGIN_DECLS typedef struct _PangoFcFont PangoFcFont; typedef struct _PangoFcFontClass PangoFcFontClass; +#if defined(PANGO_ENABLE_ENGINE) || defined(PANGO_ENABLE_BACKEND) + +/** + * PANGO_RENDER_TYPE_FC: + * + * A string constant used to identify shape engines that work + * with the fontconfig based backends. See the @engine_type field + * of #PangoEngineInfo. + **/ +#define PANGO_RENDER_TYPE_FC "PangoRenderFc" + #ifdef PANGO_ENABLE_BACKEND #define PANGO_FC_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FC_FONT, PangoFcFontClass)) #define PANGO_IS_FC_FONT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FC_FONT)) #define PANGO_FC_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FC_FONT, PangoFcFontClass)) +/** + * PangoFcFont: + * + * #PangoFcFontMap is a base class for font implementations + * using the FontConfig and FreeType libraries and is used in + * conjunction with #PangoFcFontMap. When deriving from this + * class, you need to implement all of its virtual functions + * other than shutdown() along with the get_glyph_extents() + * virtual function from #PangoFont. + **/ struct _PangoFcFont { PangoFont parent_instance; + + FcPattern *font_pattern; /* fully resolved pattern */ + PangoFontMap *fontmap; /* associated map */ + PangoFontDescription *description; + + GSList *metrics_by_lang; }; +/** + * PangoFcFontClass: + * @lock_face: Returns the FT_Face of the font and increases + * the reference count for the face by one. + * @unlock_face: Decreases the reference count for the + * FT_Face of the font by one. When the count is zero, + * the #PangoFcFont subclass is allowed to free the + * FT_Face. + * @has_char: Return %TRUE if the the font contains a glyph + * corresponding to the specified character. + * @get_glyph: Gets the glyph that corresponds to the given + * Unicode character. + * @get_unknown_glyph: Gets the glyph that should be used to + * display an unknown-glyph indication for the specified + * unicode character. + * @shutdown: Performs any font-specific shutdown code that + * needs to be done when pango_fc_font_map_shutdown is called. + * May be %NULL. + * + * Class structure for #PangoFcFont. + **/ struct _PangoFcFontClass { + /*< private >*/ PangoFontClass parent_class; /*< public >*/ @@ -61,8 +110,7 @@ struct _PangoFcFontClass gunichar wc); PangoGlyph (*get_unknown_glyph) (PangoFcFont *font, gunichar wc); - void (*kern_glyphs) (PangoFcFont *font, - PangoGlyphString *glyphs); + void (*shutdown) (PangoFcFont *font); /*< private >*/ /* Padding for future expansion */ @@ -74,8 +122,6 @@ struct _PangoFcFontClass #endif /* PANGO_ENABLE_BACKEND */ -GType pango_fc_font_get_type (void); - FT_Face pango_fc_font_lock_face (PangoFcFont *font); void pango_fc_font_unlock_face (PangoFcFont *font); gboolean pango_fc_font_has_char (PangoFcFont *font, @@ -87,8 +133,10 @@ PangoGlyph pango_fc_font_get_unknown_glyph (PangoFcFont *font, void pango_fc_font_kern_glyphs (PangoFcFont *font, PangoGlyphString *glyphs); -G_END_DECLS - #endif /* PANGO_ENABLE_ENGINE || PANGO_ENABLE_BACKEND */ +GType pango_fc_font_get_type (void); + +G_END_DECLS + #endif /* __PANGO_FC_FONT_H__ */ diff --git a/pango/pangofc-fontmap.c b/pango/pangofc-fontmap.c index 28d5fa20..7607d39a 100644 --- a/pango/pangofc-fontmap.c +++ b/pango/pangofc-fontmap.c @@ -1,7 +1,7 @@ /* Pango - * pangofc-fontmap.cI: Common font handling between Xft and FT2 + * pangofc-fontmap.c: Base fontmap type for fontconfig-based backends * - * Copyright (C) 2000,2001,2002 Red Hat, Inc. + * Copyright (C) 2000-2003 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 @@ -19,16 +19,20 @@ * 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. - */ - /* Size of fontset cache */ #define FONTSET_CACHE_SIZE 16 -typedef struct _PangoFcCoverageKey PangoFcCoverageKey; +#include "pango-context.h" +#include "pangofc-fontmap.h" +#include "pangofc-private.h" +#include "modules.h" + +/* Currently broken */ +#undef INSTANCE_PRIVATE_DATA_WORKS + +typedef struct _PangoFcCoverageKey PangoFcCoverageKey; typedef struct _PangoFcFace PangoFcFace; +typedef struct _PangoFcFamily PangoFcFamily; typedef struct _PangoFcPatternSet PangoFcPatternSet; #define PANGO_FC_TYPE_FAMILY (pango_fc_family_get_type ()) @@ -39,6 +43,29 @@ typedef struct _PangoFcPatternSet PangoFcPatternSet; #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 _PangoFcFontMapPrivate +{ + /* We have one map from PangoFontDescription -> PangoXftPatternSet + * per language tag. + */ + GList *fontset_hash_list; + /* pattern_hash is used to make sure we only store one copy of + * each identical pattern. (Speeds up lookup). + */ + GHashTable *pattern_hash; + GHashTable *coverage_hash; /* Maps font file name/id -> PangoCoverage */ + + GHashTable *fonts; /* Maps XftPattern -> PangoXftFont */ + + GQueue *fontset_cache; /* Recently used fontsets */ + + /* List of all families availible */ + PangoFcFamily **families; + int n_families; /* -1 == uninitialized */ + + guint closed : 1; +}; + struct _PangoFcCoverageKey { char *filename; @@ -72,8 +99,7 @@ struct _PangoFcPatternSet GList *cache_link; }; -GType pango_fc_font_map_get_type (void); -static GType pango_fc_family_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); @@ -93,11 +119,6 @@ static void pango_fc_font_map_list_families (PangoFontMap static void pango_fc_pattern_set_free (PangoFcPatternSet *patterns); -static void pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap); -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); @@ -105,7 +126,7 @@ 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 */ +static PangoFontClass *parent_class; GType pango_fc_font_map_get_type (void) @@ -116,7 +137,7 @@ pango_fc_font_map_get_type (void) { static const GTypeInfo object_info = { - sizeof (PangoFontMapClass), + sizeof (PangoFcFontMapClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) pango_fc_font_map_class_init, @@ -128,7 +149,7 @@ pango_fc_font_map_get_type (void) }; object_type = g_type_register_static (PANGO_TYPE_FONT_MAP, - PANGO_FC_NAME "FontMap", + "PangoFcFontMap", &object_info, 0); } @@ -138,15 +159,37 @@ pango_fc_font_map_get_type (void) static void pango_fc_font_map_init (PangoFcFontMap *fcfontmap) { - fcfontmap->n_families = -1; - - fcfontmap->fonts = g_hash_table_new ((GHashFunc)g_direct_hash, NULL); - 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->fontset_cache = g_queue_new (); + static gboolean registered_modules = FALSE; + PangoFcFontMapPrivate *priv = fcfontmap->priv; + +#if INSTANCE_PRIVATE_DATA_WORKS + priv = fcfontmap->priv = G_TYPE_INSTANCE_GET_PRIVATE (fcfontmap, + PANGO_TYPE_FC_FONT_MAP, + PangoFcFontMapPrivate); +#else + priv = fcfontmap->priv = g_new0 (PangoFcFontMapPrivate, 1); +#endif + + if (!registered_modules) + { + int i; + + registered_modules = TRUE; + + for (i = 0; _pango_included_fc_modules[i].list; i++) + pango_module_register (&_pango_included_fc_modules[i]); + } + + priv->n_families = -1; + + priv->fonts = g_hash_table_new ((GHashFunc)g_direct_hash, NULL); + priv->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); + priv->fontset_cache = g_queue_new (); } + static void pango_fc_font_map_class_init (PangoFontMapClass *class) { @@ -158,9 +201,11 @@ pango_fc_font_map_class_init (PangoFontMapClass *class) 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; +#ifdef INSTANCE_PRIVATE_DATA_WORKS + g_type_class_add_private (object_class, sizeof (PangoFontMapClass)); +#endif +} static guint pango_fc_pattern_hash (FcPattern *pattern) @@ -224,27 +269,29 @@ struct _FontsetHashListNode { */ static GHashTable * pango_fc_get_fontset_hash (PangoFcFontMap *fcfontmap, - PangoLanguage *language) + PangoLanguage *language) { + PangoFcFontMapPrivate *priv = fcfontmap->priv; + /* 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; + GList *tmp_list = priv->fontset_hash_list; while (tmp_list) { FontsetHashListNode *node = tmp_list->data; if (node->language == language) { - if (tmp_list != fcfontmap->fontset_hash_list) + if (tmp_list != priv->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; + priv->fontset_hash_list = g_list_remove_link (priv->fontset_hash_list, tmp_list); + priv->fontset_hash_list->prev = tmp_list; + tmp_list->next = priv->fontset_hash_list; + priv->fontset_hash_list = tmp_list; } return node->fontset_hash; @@ -255,7 +302,7 @@ pango_fc_get_fontset_hash (PangoFcFontMap *fcfontmap, { FontsetHashListNode *node = g_new (FontsetHashListNode, 1); - fcfontmap->fontset_hash_list = g_list_prepend (fcfontmap->fontset_hash_list, node); + priv->fontset_hash_list = g_list_prepend (priv->fontset_hash_list, node); node->fontset_hash = g_hash_table_new_full ((GHashFunc)pango_font_description_hash, @@ -271,9 +318,10 @@ pango_fc_get_fontset_hash (PangoFcFontMap *fcfontmap, static void pango_fc_clear_pattern_hashes (PangoFcFontMap *fcfontmap) { + PangoFcFontMapPrivate *priv = fcfontmap->priv; GList *tmp_list; - tmp_list = fcfontmap->fontset_hash_list; + tmp_list = priv->fontset_hash_list; while (tmp_list) { FontsetHashListNode *node = tmp_list->data; @@ -284,57 +332,60 @@ pango_fc_clear_pattern_hashes (PangoFcFontMap *fcfontmap) tmp_list = tmp_list->next; } - g_list_free (fcfontmap->fontset_hash_list); - fcfontmap->fontset_hash_list = NULL; + g_list_free (priv->fontset_hash_list); + priv->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); + PangoFcFontMapPrivate *priv = fcfontmap->priv; pango_fc_font_map_cache_clear (fcfontmap); - g_queue_free (fcfontmap->fontset_cache); - g_hash_table_destroy (fcfontmap->coverage_hash); + g_queue_free (priv->fontset_cache); + g_hash_table_destroy (priv->coverage_hash); - if (fcfontmap->fonts) - g_hash_table_destroy (fcfontmap->fonts); + if (priv->fonts) + g_hash_table_destroy (priv->fonts); - if (fcfontmap->pattern_hash) - g_hash_table_destroy (fcfontmap->pattern_hash); - - pango_fc_do_finalize (fcfontmap); + if (priv->pattern_hash) + g_hash_table_destroy (priv->pattern_hash); + +#ifndef INSTANCE_PRIVATE_DATA_WORKS + g_free (priv); +#endif 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) +static void +pango_fc_font_map_add (PangoFcFontMap *fcfontmap, + PangoFcFont *fcfont) { - PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap); + PangoFcFontMapPrivate *priv = fcfontmap->priv; - g_hash_table_insert (fcfontmap->fonts, - xfont->font_pattern, - xfont); + g_assert (fcfont->fontmap == NULL); + + fcfont->fontmap = g_object_ref (fcfontmap); + g_hash_table_insert (priv->fonts, + fcfont->font_pattern, + fcfont); } /* Remove mapping from xfont->font_pattern to xfont */ void -_pango_fc_font_map_remove (PangoFontMap *fontmap, - PangoFcFont *xfont) +_pango_fc_font_map_remove (PangoFcFontMap *fcfontmap, + PangoFcFont *fcfont) { - PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap); - - g_hash_table_remove (fcfontmap->fonts, - xfont->font_pattern); + PangoFcFontMapPrivate *priv = fcfontmap->priv; + + g_hash_table_remove (priv->fonts, + fcfont->font_pattern); + fcfont->fontmap = NULL; + g_object_unref (fcfontmap); } static PangoFcFamily * @@ -366,16 +417,17 @@ is_alias_family (const char *family_name) } static void -pango_fc_font_map_list_families (PangoFontMap *fontmap, - PangoFontFamily ***families, - int *n_families) +pango_fc_font_map_list_families (PangoFontMap *fontmap, + PangoFontFamily ***families, + int *n_families) { PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap); + PangoFcFontMapPrivate *priv = fcfontmap->priv; FcFontSet *fontset; int i; int count; - if (fcfontmap->closed) + if (priv->closed) { if (families) *families = NULL; @@ -385,7 +437,7 @@ pango_fc_font_map_list_families (PangoFontMap *fontmap, return; } - if (fcfontmap->n_families < 0) + if (priv->n_families < 0) { FcObjectSet *os = FcObjectSetBuild (FC_FAMILY, NULL); FcPattern *pat = FcPatternCreate (); @@ -395,7 +447,7 @@ pango_fc_font_map_list_families (PangoFontMap *fontmap, FcPatternDestroy (pat); FcObjectSetDestroy (os); - fcfontmap->families = g_new (PangoFcFamily *, fontset->nfont + 3); /* 3 standard aliases */ + priv->families = g_new (PangoFcFamily *, fontset->nfont + 3); /* 3 standard aliases */ count = 0; for (i = 0; i < fontset->nfont; i++) @@ -407,23 +459,23 @@ pango_fc_font_map_list_families (PangoFontMap *fontmap, g_assert (res == FcResultMatch); if (!is_alias_family (s)) - fcfontmap->families[count++] = create_family (fcfontmap, s); + priv->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"); + priv->families[count++] = create_family (fcfontmap, "Sans"); + priv->families[count++] = create_family (fcfontmap, "Serif"); + priv->families[count++] = create_family (fcfontmap, "Monospace"); - fcfontmap->n_families = count; + priv->n_families = count; } if (n_families) - *n_families = fcfontmap->n_families; + *n_families = priv->n_families; if (families) - *families = g_memdup (fcfontmap->families, fcfontmap->n_families * sizeof (PangoFontFamily *)); + *families = g_memdup (priv->families, priv->n_families * sizeof (PangoFontFamily *)); } static int @@ -494,10 +546,11 @@ pango_fc_make_pattern (const PangoFontDescription *description) static PangoFont * pango_fc_font_map_new_font (PangoFontMap *fontmap, - FcPattern *match) + FcPattern *match) { PangoFcFontMap *fcfontmap = (PangoFcFontMap *)fontmap; - PangoFcFont *font; + PangoFcFontMapPrivate *priv = fcfontmap->priv; + PangoFcFont *fcfont; /* Returning NULL here actually violates a contract * that loading load_font() will never return NULL. @@ -505,32 +558,36 @@ pango_fc_font_map_new_font (PangoFontMap *fontmap, * font that doesn't draw anything and has empty * metrics. */ - if (fcfontmap->closed) + if (priv->closed) return NULL; /* Look up cache */ - font = g_hash_table_lookup (fcfontmap->fonts, match); + fcfont = g_hash_table_lookup (priv->fonts, match); - if (font) - return g_object_ref (font); + if (fcfont) + return g_object_ref (fcfont); + + fcfont = PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->new_font (fcfontmap, match); + + pango_fc_font_map_add (fcfontmap, fcfont); - FcPatternReference (match); - return (PangoFont *)_pango_fc_font_new (fontmap, match); + return (PangoFont *)fcfont; } static FcPattern * uniquify_pattern (PangoFcFontMap *fcfontmap, FcPattern *pattern) { + PangoFcFontMapPrivate *priv = fcfontmap->priv; FcPattern *old_pattern; - if (!fcfontmap->pattern_hash) - fcfontmap->pattern_hash = + if (!priv->pattern_hash) + priv->pattern_hash = g_hash_table_new_full ((GHashFunc)pango_fc_pattern_hash, (GEqualFunc)pango_fc_pattern_equal, (GDestroyNotify)FcPatternDestroy, NULL); - old_pattern = g_hash_table_lookup (fcfontmap->pattern_hash, pattern); + old_pattern = g_hash_table_lookup (priv->pattern_hash, pattern); if (old_pattern) { FcPatternDestroy (pattern); @@ -540,11 +597,19 @@ uniquify_pattern (PangoFcFontMap *fcfontmap, else { FcPatternReference (pattern); - g_hash_table_insert (fcfontmap->pattern_hash, pattern, pattern); + g_hash_table_insert (priv->pattern_hash, pattern, pattern); return pattern; } } +static void +pango_fc_default_substitute (PangoFcFontMap *fontmap, + FcPattern *pattern) +{ + if (PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->default_substitute) + PANGO_FC_FONT_MAP_GET_CLASS (fontmap)->default_substitute (fontmap, pattern); +} + static PangoFcPatternSet * pango_fc_font_map_get_patterns (PangoFontMap *fontmap, PangoContext *context, @@ -659,7 +724,8 @@ static void pango_fc_font_map_cache_fontset (PangoFcFontMap *fcfontmap, PangoFcPatternSet *patterns) { - GQueue *cache = fcfontmap->fontset_cache; + PangoFcFontMapPrivate *priv = fcfontmap->priv; + GQueue *cache = priv->fontset_cache; if (patterns->cache_link) { @@ -695,9 +761,11 @@ pango_fc_font_map_load_fontset (PangoFontMap *fontmap, const PangoFontDescription *desc, PangoLanguage *language) { - int i; PangoFcPatternSet *patterns = pango_fc_font_map_get_patterns (fontmap, context, desc, language); PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap); + PangoFcFontMapPrivate *priv = fcfontmap->priv; + int i; + if (!patterns) return NULL; @@ -721,7 +789,7 @@ pango_fc_font_map_load_fontset (PangoFontMap *fontmap, g_object_ref (patterns->fontset); if (!patterns->cache_link || - patterns->cache_link != fcfontmap->fontset_cache->head) + patterns->cache_link != priv->fontset_cache->head) pango_fc_font_map_cache_fontset (fcfontmap, patterns); return patterns->fontset; @@ -734,9 +802,10 @@ uncache_patterns (PangoFcPatternSet *patterns) } static void -pango_fc_font_map_clear_fontset_cache (PangoFcFontMap *fcfontmap) +pango_fc_font_map_clear_fontset_cache (PangoFcFontMap *fcfontmap) { - GQueue *cache = fcfontmap->fontset_cache; + PangoFcFontMapPrivate *priv = fcfontmap->priv; + GQueue *cache = priv->fontset_cache; g_list_foreach (cache->head, (GFunc)uncache_patterns, NULL); g_list_free (cache->head); @@ -745,7 +814,20 @@ pango_fc_font_map_clear_fontset_cache (PangoFcFontMap *fcfontmap) cache->length = 0; } -static void +/** + * pango_fc_font_map_cache_clear: + * @fcfontmap: a #PangoFcFontmap + * + * Clear all cached information and fontsets for this font map; + * this should be called whenever there is a change in the + * output of the default_substitute() virtual function. + * + * This function is intended to be used only by backend implementations + * deriving from #PangoFcFontmap. + * + * Since: 1.4 + **/ +void pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap) { /* Clear the fontset cache first, since any entries @@ -760,6 +842,7 @@ pango_fc_font_map_set_coverage (PangoFcFontMap *fcfontmap, PangoFcCoverageKey *key, PangoCoverage *coverage) { + PangoFcFontMapPrivate *priv = fcfontmap->priv; PangoFcCoverageKey *key_dup; key_dup = g_malloc (sizeof (PangoFcCoverageKey) + strlen (key->filename) + 1); @@ -767,15 +850,15 @@ pango_fc_font_map_set_coverage (PangoFcFontMap *fcfontmap, key_dup->filename = (char *) (key_dup + 1); strcpy (key_dup->filename, key->filename); - g_hash_table_insert (fcfontmap->coverage_hash, + g_hash_table_insert (priv->coverage_hash, key_dup, pango_coverage_ref (coverage)); } PangoCoverage * -_pango_fc_font_map_get_coverage (PangoFontMap *fontmap, - FcPattern *pattern) +_pango_fc_font_map_get_coverage (PangoFcFontMap *fcfontmap, + FcPattern *pattern) { - PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap); + PangoFcFontMapPrivate *priv = fcfontmap->priv; PangoFcCoverageKey key; PangoCoverage *coverage; FcChar32 map[FC_CHARSET_MAP_SIZE]; @@ -794,7 +877,7 @@ _pango_fc_font_map_get_coverage (PangoFontMap *fontmap, if (FcPatternGetInteger (pattern, FC_INDEX, 0, &key.id) != FcResultMatch) return NULL; - coverage = g_hash_table_lookup (fcfontmap->coverage_hash, &key); + coverage = g_hash_table_lookup (priv->coverage_hash, &key); if (coverage) return pango_coverage_ref (coverage); @@ -848,12 +931,83 @@ _pango_fc_font_map_get_coverage (PangoFontMap *fontmap, return coverage; } -/* - * PangoFcFace - */ +/** + * pango_fc_font_map_create_context: + * @fcfontmap: a #PangoFcFontMap + * + * Creates a new context for this fontmap. This function is intended + * only for backend implementations deriving from #PangoFcFontmap; + * it is possible that a backend will store additional information + * needed for correct operation on the #PangoContext after calling + * this function. + * + * Return value: a new #PangoContext + * + * Since: 1.4 + **/ +PangoContext * +pango_fc_font_map_create_context (PangoFcFontMap *fcfontmap) +{ + PangoContext *context = pango_context_new (); + pango_context_set_font_map (context, PANGO_FONT_MAP (fcfontmap)); + return context; +} + +static void +cleanup_font (gpointer key, + PangoFcFont *fcfont) +{ + _pango_fc_font_shutdown (fcfont); + + g_object_unref (fcfont->fontmap); + fcfont->fontmap = NULL; +} + +/** + * pango_fc_font_map_shutdown: + * @fcfontmap: a #PangoFcFontmap + * + * Clears all cached information for the fontmap and marks + * all fonts open for the fontmap as dead. (See the shutdown() + * virtual function of PangoFcFont.) This function might be used + * by a backend when the underlying windowing system for the font + * map exits. This function is only intended to be called from + * only for backend implementations deriving from #PangoFcFontmap. + * + * Since: 1.4 + **/ +void +pango_fc_font_map_shutdown (PangoFcFontMap *fcfontmap) +{ + PangoFcFontMapPrivate *priv = fcfontmap->priv; + + pango_fc_font_map_cache_clear (fcfontmap); + + g_hash_table_foreach (priv->fonts, (GHFunc)cleanup_font, NULL); + g_hash_table_destroy (priv->fonts); + priv->fonts = NULL; + priv->closed = TRUE; +} + +/** + * pango_fc_font_description_from_pattern: + * @pattern: a #FcPattern + * @include_size: if %TRUE, the pattern will include the size from + * the @pattern; otherwise the resulting pattern will be unsized. + * + * Creates a #PangoFontDescription that matches the specified + * Fontconfig pattern as closely as possible. Many possible Fontconfig + * pattern values, such as %FC_RASTERIZER or %FC_DPI, don't make sense in + * the context of #PangoFontDescription, so will be ignored. + * + * Return value: a new #PangoFontDescription. Free with + * pango_font_description_free(). + * + * Since: 1.4 + **/ PangoFontDescription * -_pango_fc_font_desc_from_pattern (FcPattern *pattern, gboolean include_size) +pango_fc_font_description_from_pattern (FcPattern *pattern, gboolean include_size) { PangoFontDescription *desc; PangoStyle style; @@ -912,6 +1066,10 @@ _pango_fc_font_desc_from_pattern (FcPattern *pattern, gboolean include_size) return desc; } +/* + * PangoFcFace + */ + static PangoFontDescription * make_alias_description (PangoFcFamily *fcfamily, gboolean bold, @@ -943,8 +1101,8 @@ pango_fc_face_describe (PangoFontFace *face) 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, 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); @@ -960,7 +1118,7 @@ pango_fc_face_describe (PangoFontFace *face) result_pattern = FcFontMatch (NULL, match_pattern, &res); if (result_pattern) { - desc = _pango_fc_font_desc_from_pattern (result_pattern, FALSE); + desc = pango_fc_font_description_from_pattern (result_pattern, FALSE); FcPatternDestroy (result_pattern); } @@ -1005,8 +1163,9 @@ pango_fc_face_get_type (void) }; object_type = g_type_register_static (PANGO_TYPE_FONT_FACE, - PANGO_FC_NAME "Face", - &object_info, 0); + "PangoFcFace", + &object_info, + G_TYPE_FLAG_ABSTRACT); } return object_type; @@ -1033,13 +1192,14 @@ pango_fc_family_list_faces (PangoFontFamily *family, { PangoFcFamily *fcfamily = PANGO_FC_FAMILY (family); PangoFcFontMap *fcfontmap = fcfamily->fontmap; - + PangoFcFontMapPrivate *priv = fcfontmap->priv; + if (fcfamily->n_faces < 0) { FcFontSet *fontset; int i; - if (is_alias_family (fcfamily->family_name) || fcfontmap->closed) + if (is_alias_family (fcfamily->family_name) || priv->closed) { fcfamily->n_faces = 4; fcfamily->faces = g_new (PangoFcFace *, fcfamily->n_faces); @@ -1130,7 +1290,7 @@ pango_fc_family_get_type (void) }; object_type = g_type_register_static (PANGO_TYPE_FONT_FAMILY, - PANGO_FC_NAME "Family", + "PangoFcFamily", &object_info, 0); } diff --git a/pango/pangofc-fontmap.cI b/pango/pangofc-fontmap.cI deleted file mode 100644 index 28d5fa20..00000000 --- a/pango/pangofc-fontmap.cI +++ /dev/null @@ -1,1138 +0,0 @@ -/* 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. - */ - -/* Size of fontset cache */ -#define FONTSET_CACHE_SIZE 16 - -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; - PangoFontset *fontset; - GList *cache_link; -}; - -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_pattern_set_free (PangoFcPatternSet *patterns); - -static void pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap); -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)g_direct_hash, NULL); - 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->fontset_cache = 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_pattern_set_free); - node->language = language; - - return node->fontset_hash; - } -} - -static void -pango_fc_clear_pattern_hashes (PangoFcFontMap *fcfontmap) -{ - GList *tmp_list; - - 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->fontset_cache); - g_hash_table_destroy (fcfontmap->coverage_hash); - - if (fcfontmap->fonts) - g_hash_table_destroy (fcfontmap->fonts); - - if (fcfontmap->pattern_hash) - g_hash_table_destroy (fcfontmap->pattern_hash); - - 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) - return g_object_ref (font); - - FcPatternReference (match); - return (PangoFont *)_pango_fc_font_new (fontmap, match); -} - -static FcPattern * -uniquify_pattern (PangoFcFontMap *fcfontmap, - FcPattern *pattern) -{ - FcPattern *old_pattern; - - if (!fcfontmap->pattern_hash) - fcfontmap->pattern_hash = - g_hash_table_new_full ((GHashFunc)pango_fc_pattern_hash, - (GEqualFunc)pango_fc_pattern_equal, - (GDestroyNotify)FcPatternDestroy, NULL); - - old_pattern = g_hash_table_lookup (fcfontmap->pattern_hash, pattern); - if (old_pattern) - { - FcPatternDestroy (pattern); - FcPatternReference (old_pattern); - return old_pattern; - } - else - { - FcPatternReference (pattern); - g_hash_table_insert (fcfontmap->pattern_hash, pattern, pattern); - return pattern; - } -} - -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) - { - g_printerr ("No fonts found; this probably means that the fontconfig\n" - "library is not correctly configured. You may need to\n" - "edit the fonts.conf configuration file. More information\n" - "about fontconfig can be found in the fontconfig(3) manual\n" - "page and on http://fontconfig.org\n"); - - /* There is no point in proceeding; we'll just get a segfault later - * on, and a bunch more possibly confusing error messages in between. - */ - - /* return NULL; */ - exit (1); - } - - patterns = g_new (PangoFcPatternSet, 1); - patterns->patterns = g_new (FcPattern *, font_patterns->nfont); - patterns->n_patterns = 0; - patterns->fontset = NULL; - patterns->cache_link = NULL; - - for (f = 0; f < font_patterns->nfont; f++) - { - font_pattern = FcFontRenderPrepare (NULL, pattern, - font_patterns->fonts[f]); -#ifdef FC_PATTERN - /* The FC_PATTERN element, which points back to our the original patterm - * defeats our hash tables. - */ - FcPatternDel (font_pattern, FC_PATTERN); -#endif /* FC_PATTERN */ - - if (font_pattern) - patterns->patterns[patterns->n_patterns++] = uniquify_pattern (fcfontmap, 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_pattern_set_free (PangoFcPatternSet *patterns) -{ - int i; - - if (patterns->fontset) - g_object_remove_weak_pointer (G_OBJECT (patterns->fontset), - (gpointer *)&patterns->fontset); - - for (i = 0; i < patterns->n_patterns; i++) - FcPatternDestroy (patterns->patterns[i]); - - g_free (patterns->patterns); - g_free (patterns); -} - -static void -pango_fc_font_map_cache_fontset (PangoFcFontMap *fcfontmap, - PangoFcPatternSet *patterns) -{ - GQueue *cache = fcfontmap->fontset_cache; - - if (patterns->cache_link) - { - /* Already in cache, move to head - */ - if (patterns->cache_link == cache->tail) - cache->tail = patterns->cache_link->prev; - - cache->head = g_list_remove_link (cache->head, patterns->cache_link); - cache->length--; - } - else - { - /* Add to cache initially - */ - if (cache->length == FONTSET_CACHE_SIZE) - { - PangoFcPatternSet *tmp_patterns = g_queue_pop_tail (cache); - tmp_patterns->cache_link = NULL; - g_object_unref (tmp_patterns->fontset); - } - - g_object_ref (patterns->fontset); - patterns->cache_link = g_list_prepend (NULL, patterns); - } - - g_queue_push_head_link (cache, patterns->cache_link); -} - -static PangoFontset * -pango_fc_font_map_load_fontset (PangoFontMap *fontmap, - PangoContext *context, - const PangoFontDescription *desc, - PangoLanguage *language) -{ - int i; - PangoFcPatternSet *patterns = pango_fc_font_map_get_patterns (fontmap, context, desc, language); - PangoFcFontMap *fcfontmap = PANGO_FC_FONT_MAP (fontmap); - if (!patterns) - return NULL; - - if (!patterns->fontset) - { - PangoFontsetSimple *simple; - 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); - } - - patterns->fontset = PANGO_FONTSET (simple); - g_object_add_weak_pointer (G_OBJECT (patterns->fontset), - (gpointer *)&patterns->fontset); - } - else - g_object_ref (patterns->fontset); - - if (!patterns->cache_link || - patterns->cache_link != fcfontmap->fontset_cache->head) - pango_fc_font_map_cache_fontset (fcfontmap, patterns); - - return patterns->fontset; -} - -static void -uncache_patterns (PangoFcPatternSet *patterns) -{ - g_object_unref (patterns->fontset); -} - -static void -pango_fc_font_map_clear_fontset_cache (PangoFcFontMap *fcfontmap) -{ - GQueue *cache = fcfontmap->fontset_cache; - - g_list_foreach (cache->head, (GFunc)uncache_patterns, NULL); - g_list_free (cache->head); - cache->head = NULL; - cache->tail = NULL; - cache->length = 0; -} - -static void -pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap) -{ - /* Clear the fontset cache first, since any entries - * in the fontset_cache must also be in the pattern cache. - */ - pango_fc_font_map_clear_fontset_cache (fcfontmap); - pango_fc_clear_pattern_hashes (fcfontmap); -} - -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++; - } - } - } - - /* Awful hack so Hangul Tone marks get rendered with the same - * font and in the same run as other Hangul characters. If a font - * covers the first composed Hangul glyph, then it is declared to cover - * the Hangul tone marks. This hack probably needs to be formalized - * by choosing fonts for scripts rather than individual code points. - */ - if (pango_coverage_get (coverage, 0xac00) == PANGO_COVERAGE_EXACT) - { - pango_coverage_set (coverage, 0x302e, PANGO_COVERAGE_EXACT); - pango_coverage_set (coverage, 0x302f, PANGO_COVERAGE_EXACT); - } - - 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.h b/pango/pangofc-fontmap.h new file mode 100644 index 00000000..9d02dee9 --- /dev/null +++ b/pango/pangofc-fontmap.h @@ -0,0 +1,106 @@ +/* Pango + * pangofc-fontmap.h: Base fontmap type for fontconfig-based backends + * + * Copyright (C) 2003 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. + */ + +#ifndef __PANGO_FC_FONT_MAP_H__ +#define __PANGO_FC_FONT_MAP_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define PANGO_TYPE_FC_FONT_MAP (pango_fc_font_map_get_type ()) +#define PANGO_FC_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FC_FONT_MAP, PangoFcFontMap)) +#define PANGO_IS_FC_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_FC_FONT_MAP)) + +typedef struct _PangoFcFontMap PangoFcFontMap; +typedef struct _PangoFcFontMapClass PangoFcFontMapClass; +typedef struct _PangoFcFontMapPrivate PangoFcFontMapPrivate; + +#ifdef PANGO_ENABLE_BACKEND + +#define PANGO_FC_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_FC_FONT_MAP, PangoFcFontMapClass)) +#define PANGO_IS_FC_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_FC_FONT_MAP)) +#define PANGO_FC_FONT_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FC_FONT_MAP, PangoFcFontMapClass)) + +/** + * PangoFcFontMap: + * + * #PangoFcFontMap is a base class for font map implementations + * using the FontConfig and FreeType libraries. To create a new + * backend using Fontconfig and FreeType, you derive from this class + * and implement a new_font() virtual function that creates an + * instance deriving from #PangoFcFont. + **/ +struct _PangoFcFontMap +{ + PangoFontMap parent_instance; + + PangoFcFontMapPrivate *priv; +}; + +/** + * PangoFcFontMapClass: + * @default_substitute: Substitutes in default values for + * unspecified fields in a #FcPattern. This will be called + * prior to creating a font for the pattern. May be %NULL. + * @new_font: Creates a new #PangoFcFont for the specified + * pattern of the appropriate type for this font map. The + * @pattern argument must be passed to the "pattern" property + * of #PangoFcFont when you call g_object_new() + * + * Class structure for #PangoFcFontMap. + **/ +struct _PangoFcFontMapClass +{ + /*< private >*/ + PangoFontMapClass parent_class; + + /*< public >*/ + void (*default_substitute) (PangoFcFontMap *fontmap, + FcPattern *pattern); + PangoFcFont *(*new_font) (PangoFcFontMap *fontmap, + FcPattern *pattern); + + /*< private >*/ + + /* Padding for future expansion */ + void (*_pango_reserved1) (void); + void (*_pango_reserved2) (void); + void (*_pango_reserved3) (void); + void (*_pango_reserved4) (void); +}; + +PangoContext * pango_fc_font_map_create_context (PangoFcFontMap *fcfontmap); +void pango_fc_font_map_cache_clear (PangoFcFontMap *fcfontmap); +void pango_fc_font_map_shutdown (PangoFcFontMap *fcfontmap); + +#endif + +GType pango_fc_font_map_get_type (void); + +PangoFontDescription *pango_fc_font_description_from_pattern (FcPattern *pattern, + gboolean include_size); + +G_END_DECLS + +#endif /* __PANGO_FC_FONT_MAP_H__ */ diff --git a/pango/pangofc-private.h b/pango/pangofc-private.h new file mode 100644 index 00000000..9ef285af --- /dev/null +++ b/pango/pangofc-private.h @@ -0,0 +1,39 @@ +/* Pango + * pangofc-private.h: Private routines and declarations for generic + * fontconfig operation + * + * Copyright (C) 2003 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. + */ + +#ifndef __PANGOFC_PRIVATE_H__ +#define __PANGOFC_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +void _pango_fc_font_shutdown (PangoFcFont *fcfont); + +void _pango_fc_font_map_remove (PangoFcFontMap *fcfontmap, + PangoFcFont *fcfont); +PangoCoverage *_pango_fc_font_map_get_coverage (PangoFcFontMap *fcfontmap, + FcPattern *pattern); + +G_END_DECLS + +#endif /* __PANGOFC_PRIVATE_H__ */ diff --git a/pango/pangoft2-fontmap.c b/pango/pangoft2-fontmap.c index 9feea38f..1abc5a0d 100644 --- a/pango/pangoft2-fontmap.c +++ b/pango/pangoft2-fontmap.c @@ -33,10 +33,9 @@ #include -#include "pango-fontmap.h" #include "pango-utils.h" #include "pangoft2-private.h" -#include "modules.h" +#include "pangofc-fontmap.h" #ifdef G_OS_WIN32 #define STRICT @@ -44,36 +43,17 @@ #endif typedef struct _PangoFT2Family PangoFT2Family; +typedef struct _PangoFT2FontMapClass PangoFT2FontMapClass; struct _PangoFT2FontMap { - PangoFontMap parent_instance; + PangoFcFontMap parent_instance; FT_Library library; - /* We have one map from PangoFontDescription -> PangoXftPatternSet - * per language tag. - */ - GList *fontset_hash_list; - /* pattern_hash is used to make sure we only store one copy of - * each identical pattern. (Speeds up lookup). - */ - GHashTable *pattern_hash; - GHashTable *coverage_hash; /* Maps font file name -> PangoCoverage */ - - GHashTable *fonts; /* Maps XftPattern -> PangoFT2Font */ - - GQueue *fontset_cache; /* Recently used fontsets */ - - /* List of all families availible */ - PangoFT2Family **families; - int n_families; /* -1 == uninitialized */ - double dpi_x; double dpi_y; - guint closed : 1; - /* Function to call on prepared patterns to do final * config tweaking. */ @@ -82,34 +62,75 @@ struct _PangoFT2FontMap GDestroyNotify substitute_destroy; }; -/************************************************************ - * Code shared with PangoXft * - ************************************************************/ +struct _PangoFT2FontMapClass +{ + PangoFcFontMapClass parent_class; +}; + +static void pango_ft2_font_map_class_init (PangoFT2FontMapClass *class); +static void pango_ft2_font_map_finalize (GObject *object); +static void pango_ft2_font_map_default_substitute (PangoFcFontMap *fcfontmap, + FcPattern *pattern); +static PangoFcFont * pango_ft2_font_map_new_font (PangoFcFontMap *fcfontmap, + FcPattern *pattern); -#define PangoFcFamily PangoFT2Family -#define _PangoFcFamily _PangoFT2Family -#define PangoFcFontMap PangoFT2FontMap -#define PangoFcFont PangoFT2Font +static PangoFT2FontMap *pango_ft2_global_fontmap = NULL; -#define PANGO_FC_FONT_MAP PANGO_FT2_FONT_MAP +static GObjectClass *parent_class; -#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_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 +GType +pango_ft2_font_map_get_type (void) +{ + static GType object_type = 0; -#define PANGO_FC_NAME "PangoFT2" + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (PangoFT2FontMapClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) pango_ft2_font_map_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PangoFT2FontMap), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + object_type = g_type_register_static (PANGO_TYPE_FC_FONT_MAP, + "PangoFT2FontMap", + &object_info, 0); + } + + return object_type; +} -#include "pangofc-fontmap.cI" +static void +pango_ft2_font_map_class_init (PangoFT2FontMapClass *class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (class); + PangoFcFontMapClass *fcfontmap_class = PANGO_FC_FONT_MAP_CLASS (class); + + parent_class = g_type_class_peek_parent (class); -/************************************************************* - * FreeType specific code * - *************************************************************/ + gobject_class->finalize = pango_ft2_font_map_finalize; + fcfontmap_class->default_substitute = pango_ft2_font_map_default_substitute; + fcfontmap_class->new_font = pango_ft2_font_map_new_font; +} -static PangoFT2FontMap *pango_ft2_global_fontmap = NULL; +static void +pango_ft2_font_map_finalize (GObject *object) +{ + PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (object); + + if (ft2fontmap->substitute_destroy) + ft2fontmap->substitute_destroy (ft2fontmap->substitute_data); + + FT_Done_FreeType (ft2fontmap->library); + + parent_class->finalize (object); +} /** * pango_ft2_font_map_new: @@ -128,23 +149,12 @@ static PangoFT2FontMap *pango_ft2_global_fontmap = NULL; PangoFontMap * pango_ft2_font_map_new (void) { - static gboolean registered_modules = FALSE; PangoFT2FontMap *ft2fontmap; FT_Error error; - if (!registered_modules) - { - int i; - - registered_modules = TRUE; - - /* Make sure that the type system is initialized */ - g_type_init (); + /* Make sure that the type system is initialized */ + g_type_init (); - for (i = 0; _pango_included_ft2_modules[i].list; i++) - pango_module_register (&_pango_included_ft2_modules[i]); - } - ft2fontmap = g_object_new (PANGO_TYPE_FT2_FONT_MAP, NULL); error = FT_Init_FreeType (&ft2fontmap->library); @@ -186,7 +196,7 @@ pango_ft2_font_map_set_default_substitute (PangoFT2FontMap *fontmap, fontmap->substitute_data = data; fontmap->substitute_destroy = notify; - pango_fc_font_map_cache_clear (fontmap); + pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (fontmap)); } /** @@ -204,7 +214,7 @@ pango_ft2_font_map_set_default_substitute (PangoFT2FontMap *fontmap, void pango_ft2_font_map_substitute_changed (PangoFT2FontMap *fontmap) { - pango_fc_font_map_cache_clear (fontmap); + pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (fontmap)); } /** @@ -241,14 +251,9 @@ pango_ft2_font_map_set_resolution (PangoFT2FontMap *fontmap, PangoContext * pango_ft2_font_map_create_context (PangoFT2FontMap *fontmap) { - PangoContext *context; - g_return_val_if_fail (PANGO_FT2_IS_FONT_MAP (fontmap), NULL); - context = pango_context_new (); - pango_context_set_font_map (context, PANGO_FONT_MAP (fontmap)); - - return context; + return pango_fc_font_map_create_context (PANGO_FC_FONT_MAP (fontmap)); } /** @@ -306,7 +311,7 @@ pango_ft2_shutdown_display (void) { if (pango_ft2_global_fontmap) { - pango_fc_font_map_cache_clear (pango_ft2_global_fontmap); + pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (pango_ft2_global_fontmap)); g_object_unref (pango_ft2_global_fontmap); @@ -323,26 +328,25 @@ _pango_ft2_font_map_get_library (PangoFontMap *fontmap) } static void -pango_fc_do_finalize (PangoFT2FontMap *fontmap) -{ - if (fontmap->substitute_destroy) - fontmap->substitute_destroy (fontmap->substitute_data); - - FT_Done_FreeType (fontmap->library); -} - -static void -pango_fc_default_substitute (PangoFT2FontMap *fontmap, - FcPattern *pattern) +pango_ft2_font_map_default_substitute (PangoFcFontMap *fcfontmap, + FcPattern *pattern) { + PangoFT2FontMap *ft2fontmap = PANGO_FT2_FONT_MAP (fcfontmap); FcValue v; - + FcConfigSubstitute (NULL, pattern, FcMatchPattern); - if (fontmap->substitute_func) - fontmap->substitute_func (pattern, fontmap->substitute_data); + if (ft2fontmap->substitute_func) + ft2fontmap->substitute_func (pattern, ft2fontmap->substitute_data); FcDefaultSubstitute (pattern); if (FcPatternGet (pattern, FC_DPI, 0, &v) == FcResultNoMatch) - FcPatternAddDouble (pattern, FC_DPI, fontmap->dpi_y); + FcPatternAddDouble (pattern, FC_DPI, ft2fontmap->dpi_y); +} + +static PangoFcFont * +pango_ft2_font_map_new_font (PangoFcFontMap *fcfontmap, + FcPattern *pattern) +{ + return (PangoFcFont *)_pango_ft2_font_new (PANGO_FT2_FONT_MAP (fcfontmap), pattern); } diff --git a/pango/pangoft2-private.h b/pango/pangoft2-private.h index 71746f02..1f086832 100644 --- a/pango/pangoft2-private.h +++ b/pango/pangoft2-private.h @@ -23,7 +23,6 @@ #ifndef __PANGOFT2_PRIVATE_H__ #define __PANGOFT2_PRIVATE_H__ -#include "pango-modules.h" #include "pangoft2.h" #include @@ -61,15 +60,11 @@ struct _PangoFT2Font { PangoFcFont font; - FcPattern *font_pattern; FT_Face face; int load_flags; int size; - PangoFontMap *fontmap; - PangoFontDescription *description; - GSList *metrics_by_lang; GHashTable *glyph_info; @@ -83,19 +78,10 @@ struct _PangoFT2GlyphInfo void *cached_glyph; }; -PangoFT2Font * _pango_ft2_font_new (PangoFontMap *font, - FcPattern *pattern); -PangoMap *_pango_ft2_get_shaper_map (PangoLanguage *language); -PangoCoverage *_pango_ft2_font_map_get_coverage (PangoFontMap *fontmap, - FcPattern *pattern); +PangoFT2Font * _pango_ft2_font_new (PangoFT2FontMap *ft2fontmap, + FcPattern *pattern); FT_Library _pango_ft2_font_map_get_library (PangoFontMap *fontmap); -void _pango_ft2_font_map_add (PangoFontMap *fontmap, - PangoFT2Font *ft2font); -void _pango_ft2_font_map_remove (PangoFontMap *fontmap, - PangoFT2Font *ft2font); const char *_pango_ft2_ft_strerror (FT_Error error); -PangoFontDescription *_pango_ft2_font_desc_from_pattern (FcPattern *pattern, - gboolean include_size); void *pango_ft2_font_get_cache_glyph_data (PangoFont *font, int glyph_index); diff --git a/pango/pangoft2.c b/pango/pangoft2.c index 517e952b..6c42b3c4 100644 --- a/pango/pangoft2.c +++ b/pango/pangoft2.c @@ -30,9 +30,9 @@ #include -#include "pango-utils.h" #include "pangoft2.h" #include "pangoft2-private.h" +#include "pangofc-fontmap.h" /* for compatibility with older freetype versions */ #ifndef FT_LOAD_TARGET_MONO @@ -47,19 +47,12 @@ #define PANGO_FT2_FONT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_FT2_FONT, PangoFT2FontClass)) typedef struct _PangoFT2FontClass PangoFT2FontClass; -typedef struct _PangoFT2MetricsInfo PangoFT2MetricsInfo; struct _PangoFT2FontClass { PangoFcFontClass parent_class; }; -struct _PangoFT2MetricsInfo -{ - const char *sample_str; - PangoFontMetrics *metrics; -}; - typedef struct { FT_Bitmap bitmap; @@ -73,21 +66,11 @@ static void pango_ft2_font_class_init (PangoFT2FontClass *class); static void pango_ft2_font_init (PangoFT2Font *ft2font); static void pango_ft2_font_finalize (GObject *object); -static PangoFontDescription * pango_ft2_font_describe (PangoFont *font); - -static PangoEngineShape * pango_ft2_font_find_shaper (PangoFont *font, - PangoLanguage *language, - guint32 ch); - static void pango_ft2_font_get_glyph_extents (PangoFont *font, PangoGlyph glyph, PangoRectangle *ink_rect, PangoRectangle *logical_rect); -static PangoFontMetrics * pango_ft2_font_get_metrics (PangoFont *font, - PangoLanguage *language); - - static FT_Face pango_ft2_font_real_lock_face (PangoFcFont *font); static void pango_ft2_font_real_unlock_face (PangoFcFont *font); static gboolean pango_ft2_font_real_has_char (PangoFcFont *font, @@ -96,8 +79,6 @@ static guint pango_ft2_font_real_get_glyph (PangoFcFont *font, gunichar wc); static PangoGlyph pango_ft2_font_real_get_unknown_glyph (PangoFcFont *font, gunichar wc); -static void pango_ft2_font_real_kern_glyphs (PangoFcFont *font, - PangoGlyphString *glyphs); static GType pango_ft2_font_get_type (void); @@ -111,29 +92,23 @@ static void pango_ft2_get_item_properties (PangoItem *item, PangoFT2Font * -_pango_ft2_font_new (PangoFontMap *fontmap, - FcPattern *pattern) +_pango_ft2_font_new (PangoFT2FontMap *ft2fontmap, + FcPattern *pattern) { + PangoFontMap *fontmap = PANGO_FONT_MAP (ft2fontmap); PangoFT2Font *ft2font; double d; g_return_val_if_fail (fontmap != NULL, NULL); g_return_val_if_fail (pattern != NULL, NULL); - ft2font = (PangoFT2Font *)g_object_new (PANGO_TYPE_FT2_FONT, NULL); - - ft2font->fontmap = fontmap; - ft2font->font_pattern = pattern; - - g_object_ref (fontmap); - ft2font->description = _pango_ft2_font_desc_from_pattern (pattern, TRUE); - ft2font->face = NULL; + ft2font = (PangoFT2Font *)g_object_new (PANGO_TYPE_FT2_FONT, + "pattern", pattern, + NULL); if (FcPatternGetDouble (pattern, FC_PIXEL_SIZE, 0, &d) == FcResultMatch) ft2font->size = d*PANGO_SCALE; - _pango_ft2_font_map_add (ft2font->fontmap, ft2font); - return ft2font; } @@ -156,6 +131,7 @@ static void load_fallback_face (PangoFT2Font *ft2font, const char *original_file) { + PangoFcFont *fcfont = PANGO_FC_FONT (ft2font); FcPattern *sans; FcPattern *matched; FcResult result; @@ -166,7 +142,7 @@ load_fallback_face (PangoFT2Font *ft2font, sans = FcPatternBuild (NULL, FC_FAMILY, FcTypeString, "sans", - FC_SIZE, FcTypeDouble, (double)pango_font_description_get_size (ft2font->description)/PANGO_SCALE, + FC_SIZE, FcTypeDouble, (double)pango_font_description_get_size (fcfont->description)/PANGO_SCALE, NULL); matched = FcFontMatch (0, sans, &result); @@ -177,20 +153,20 @@ load_fallback_face (PangoFT2Font *ft2font, if (FcPatternGetInteger (matched, FC_INDEX, 0, &id) != FcResultMatch) goto bail1; - error = FT_New_Face (_pango_ft2_font_map_get_library (ft2font->fontmap), + error = FT_New_Face (_pango_ft2_font_map_get_library (fcfont->fontmap), (char *) filename2, id, &ft2font->face); if (error) { bail1: - name = pango_font_description_to_string (ft2font->description); + name = pango_font_description_to_string (fcfont->description); g_warning ("Unable to open font file %s for font %s, exiting\n", filename2, name); exit (1); } else { - name = pango_font_description_to_string (ft2font->description); + name = pango_font_description_to_string (fcfont->description); g_warning ("Unable to open font file %s for font %s, falling back to %s\n", original_file, name, filename2); g_free (name); } @@ -220,13 +196,14 @@ FT_Face pango_ft2_font_get_face (PangoFont *font) { PangoFT2Font *ft2font = (PangoFT2Font *)font; + PangoFcFont *fcfont = (PangoFcFont *)font; FT_Error error; FcPattern *pattern; FcChar8 *filename; FcBool antialias, hinting, autohint; int id; - pattern = ft2font->font_pattern; + pattern = fcfont->font_pattern; if (!ft2font->face) { @@ -264,7 +241,7 @@ pango_ft2_font_get_face (PangoFont *font) if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch) goto bail0; - error = FT_New_Face (_pango_ft2_font_map_get_library (ft2font->fontmap), + error = FT_New_Face (_pango_ft2_font_map_get_library (fcfont->fontmap), (char *) filename, id, &ft2font->face); if (error != FT_Err_Ok) { @@ -331,8 +308,6 @@ pango_ft2_font_init (PangoFT2Font *ft2font) ft2font->size = 0; - ft2font->metrics_by_lang = NULL; - ft2font->glyph_info = g_hash_table_new (NULL, NULL); } @@ -347,18 +322,13 @@ pango_ft2_font_class_init (PangoFT2FontClass *class) object_class->finalize = pango_ft2_font_finalize; - font_class->describe = pango_ft2_font_describe; - font_class->get_coverage = pango_ft2_font_get_coverage; - font_class->find_shaper = pango_ft2_font_find_shaper; font_class->get_glyph_extents = pango_ft2_font_get_glyph_extents; - font_class->get_metrics = pango_ft2_font_get_metrics; fc_font_class->lock_face = pango_ft2_font_real_lock_face; fc_font_class->unlock_face = pango_ft2_font_real_unlock_face; fc_font_class->has_char = pango_ft2_font_real_has_char; fc_font_class->get_glyph = pango_ft2_font_real_get_glyph; fc_font_class->get_unknown_glyph = pango_ft2_font_real_get_unknown_glyph; - fc_font_class->kern_glyphs = pango_ft2_font_real_kern_glyphs; } static void @@ -669,71 +639,6 @@ pango_ft2_font_get_kerning (PangoFont *font, return PANGO_UNITS_26_6 (kerning.x); } -static PangoFontMetrics * -pango_ft2_font_get_metrics (PangoFont *font, - PangoLanguage *language) -{ - PangoFT2Font *ft2font = PANGO_FT2_FONT (font); - PangoFT2MetricsInfo *info = NULL; /* Quiet gcc */ - GSList *tmp_list; - - const char *sample_str = pango_language_get_sample_string (language); - - tmp_list = ft2font->metrics_by_lang; - while (tmp_list) - { - info = tmp_list->data; - - if (info->sample_str == sample_str) /* We _don't_ need strcmp */ - break; - - tmp_list = tmp_list->next; - } - - if (!tmp_list) - { - PangoContext *context; - PangoLayout *layout; - PangoRectangle extents; - FT_Face face = pango_ft2_font_get_face (font); - - info = g_new (PangoFT2MetricsInfo, 1); - info->sample_str = sample_str; - info->metrics = pango_font_metrics_new (); - - info->metrics->ascent = PANGO_UNITS_26_6 (face->size->metrics.ascender); - info->metrics->descent = PANGO_UNITS_26_6 (- face->size->metrics.descender); - info->metrics->approximate_char_width = - info->metrics->approximate_digit_width = - PANGO_UNITS_26_6 (face->size->metrics.max_advance); - - ft2font->metrics_by_lang = g_slist_prepend (ft2font->metrics_by_lang, info); - - context = pango_context_new (); - pango_context_set_font_map (context, ft2font->fontmap); - pango_context_set_language (context, language); - - layout = pango_layout_new (context); - pango_layout_set_font_description (layout, ft2font->description); - - pango_layout_set_text (layout, sample_str, -1); - pango_layout_get_extents (layout, NULL, &extents); - - info->metrics->approximate_char_width = - extents.width / g_utf8_strlen (sample_str, -1); - - pango_layout_set_text (layout, "0123456789", -1); - pango_layout_get_extents (layout, NULL, &extents); - - info->metrics->approximate_digit_width = extents.width / 10; - - g_object_unref (layout); - g_object_unref (context); - } - - return pango_font_metrics_ref (info->metrics); -} - static FT_Face pango_ft2_font_real_lock_face (PangoFcFont *font) { @@ -779,40 +684,6 @@ pango_ft2_font_real_get_unknown_glyph (PangoFcFont *font, return 0; } -static void -pango_ft2_font_real_kern_glyphs (PangoFcFont *font, - PangoGlyphString *glyphs) -{ - FT_Face face; - FT_Error error; - FT_Vector kerning; - int i; - - face = pango_fc_font_lock_face (font); - if (!face) - return; - - if (!FT_HAS_KERNING (face)) - { - pango_fc_font_unlock_face (font); - return; - } - - for (i = 1; i < glyphs->num_glyphs; ++i) - { - error = FT_Get_Kerning (face, - glyphs->glyphs[i-1].glyph, - glyphs->glyphs[i].glyph, - ft_kerning_default, - &kerning); - - if (error == FT_Err_Ok) - glyphs->glyphs[i-1].geometry.width += PANGO_UNITS_26_6 (kerning.x); - } - - pango_fc_font_unlock_face (font); -} - static gboolean pango_ft2_free_glyph_info_callback (gpointer key, gpointer value, gpointer data) { @@ -826,34 +697,17 @@ pango_ft2_free_glyph_info_callback (gpointer key, gpointer value, gpointer data) return TRUE; } -static void -free_metrics_info (PangoFT2MetricsInfo *info) -{ - pango_font_metrics_unref (info->metrics); - g_free (info); -} - static void pango_ft2_font_finalize (GObject *object) { PangoFT2Font *ft2font = (PangoFT2Font *)object; - _pango_ft2_font_map_remove (ft2font->fontmap, ft2font); - if (ft2font->face) { FT_Done_Face (ft2font->face); ft2font->face = NULL; } - pango_font_description_free (ft2font->description); - FcPatternDestroy (ft2font->font_pattern); - - g_object_unref (ft2font->fontmap); - - g_slist_foreach (ft2font->metrics_by_lang, (GFunc)free_metrics_info, NULL); - g_slist_free (ft2font->metrics_by_lang); - g_hash_table_foreach_remove (ft2font->glyph_info, pango_ft2_free_glyph_info_callback, object); g_hash_table_destroy (ft2font->glyph_info); @@ -861,60 +715,19 @@ pango_ft2_font_finalize (GObject *object) G_OBJECT_CLASS (parent_class)->finalize (object); } -static PangoFontDescription * -pango_ft2_font_describe (PangoFont *font) -{ - PangoFT2Font *ft2font; - PangoFontDescription *desc; - - ft2font = PANGO_FT2_FONT (font); - - desc = pango_font_description_copy (ft2font->description); - - return desc; -} - -PangoMap * -pango_ft2_get_shaper_map (PangoLanguage *language) -{ - 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_FT2); - } - - return pango_find_map (language, engine_type_id, render_type_id); -} - /** * pango_ft2_font_get_coverage: * @font: a #PangoFT2Font. * @language: a language tag. * @returns: a #PangoCoverage. * - * Should not be called directly, use pango_font_get_coverage() instead. + * Gets the #PangoCoverage for a #PangoFT2Font. Use pango_font_get_coverage() instead. **/ PangoCoverage * pango_ft2_font_get_coverage (PangoFont *font, PangoLanguage *language) { - PangoFT2Font *ft2font = (PangoFT2Font *)font; - - return _pango_ft2_font_map_get_coverage (ft2font->fontmap, ft2font->font_pattern); -} - -static PangoEngineShape * -pango_ft2_font_find_shaper (PangoFont *font, - PangoLanguage *language, - guint32 ch) -{ - PangoMap *shape_map = NULL; - - shape_map = pango_ft2_get_shaper_map (language); - return (PangoEngineShape *)pango_map_get_engine (shape_map, ch); + return pango_font_get_coverage (font, language); } /* Utility functions */ diff --git a/pango/pangoft2.h b/pango/pangoft2.h index 2bb7db8d..da5cf3fb 100644 --- a/pango/pangoft2.h +++ b/pango/pangoft2.h @@ -30,7 +30,9 @@ G_BEGIN_DECLS +#ifndef PANGO_DISABLE_DEPRECATED #define PANGO_RENDER_TYPE_FT2 "PangoRenderFT2" +#endif #define PANGO_TYPE_FT2_FONT_MAP (pango_ft2_font_map_get_type ()) #define PANGO_FT2_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_FT2_FONT_MAP, PangoFT2FontMap)) diff --git a/pango/pangoxft-font.c b/pango/pangoxft-font.c index 1c11fb0b..968192b2 100644 --- a/pango/pangoxft-font.c +++ b/pango/pangoxft-font.c @@ -23,10 +23,8 @@ #include +#include "pangofc-fontmap.h" #include "pangoxft-private.h" -#include "pango-layout.h" -#include "pango-modules.h" -#include "pango-utils.h" #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)) @@ -35,45 +33,22 @@ #define PANGO_XFT_UNKNOWN_FLAG 0x10000000 -#define PANGO_SCALE_26_6 (PANGO_SCALE / (1<<6)) -#define PANGO_PIXELS_26_6(d) \ - (((d) >= 0) ? \ - ((d) + PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6 : \ - ((d) - PANGO_SCALE_26_6 / 2) / PANGO_SCALE_26_6) -#define PANGO_UNITS_26_6(d) (PANGO_SCALE_26_6 * (d)) - typedef struct _PangoXftFontClass PangoXftFontClass; -typedef struct _PangoXftMetricsInfo PangoXftMetricsInfo; struct _PangoXftFontClass { PangoFcFontClass parent_class; }; -struct _PangoXftMetricsInfo -{ - const char *sample_str; - PangoFontMetrics *metrics; -}; - 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_finalize (GObject *object); -static PangoFontDescription *pango_xft_font_describe (PangoFont *font); -static PangoCoverage * pango_xft_font_get_coverage (PangoFont *font, - PangoLanguage *language); -static PangoEngineShape * pango_xft_font_find_shaper (PangoFont *font, - PangoLanguage *language, - guint32 ch); static void pango_xft_font_get_glyph_extents (PangoFont *font, PangoGlyph glyph, PangoRectangle *ink_rect, PangoRectangle *logical_rect); -static PangoFontMetrics * pango_xft_font_get_metrics (PangoFont *font, - PangoLanguage *language); static FT_Face pango_xft_font_real_lock_face (PangoFcFont *font); static void pango_xft_font_real_unlock_face (PangoFcFont *font); @@ -83,8 +58,7 @@ static guint pango_xft_font_real_get_glyph (PangoFcFont *font, gunichar wc); static PangoGlyph pango_xft_font_real_get_unknown_glyph (PangoFcFont *font, gunichar wc); -static void pango_xft_font_real_kern_glyphs (PangoFcFont *font, - PangoGlyphString *glyphs); +static void pango_xft_font_real_shutdown (PangoFcFont *font); static XftFont *xft_font_get_font (PangoFont *font); @@ -105,7 +79,7 @@ pango_xft_font_get_type (void) NULL, /* class_data */ sizeof (PangoXftFont), 0, /* n_preallocs */ - (GInstanceInitFunc) pango_xft_font_init, + (GInstanceInitFunc) NULL, }; object_type = g_type_register_static (PANGO_TYPE_FC_FONT, @@ -116,12 +90,6 @@ pango_xft_font_get_type (void) return object_type; } -static void -pango_xft_font_init (PangoXftFont *xfont) -{ - xfont->metrics_by_lang = NULL; -} - static void pango_xft_font_class_init (PangoXftFontClass *class) { @@ -133,40 +101,32 @@ pango_xft_font_class_init (PangoXftFontClass *class) object_class->finalize = pango_xft_font_finalize; - 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; fc_font_class->lock_face = pango_xft_font_real_lock_face; fc_font_class->unlock_face = pango_xft_font_real_unlock_face; fc_font_class->has_char = pango_xft_font_real_has_char; fc_font_class->get_glyph = pango_xft_font_real_get_glyph; fc_font_class->get_unknown_glyph = pango_xft_font_real_get_unknown_glyph; - fc_font_class->kern_glyphs = pango_xft_font_real_kern_glyphs; + fc_font_class->shutdown = pango_xft_font_real_shutdown; } PangoXftFont * -_pango_xft_font_new (PangoFontMap *fontmap, - FcPattern *pattern) +_pango_xft_font_new (PangoXftFontMap *xftfontmap, + FcPattern *pattern) { + PangoFontMap *fontmap = PANGO_FONT_MAP (xftfontmap); PangoXftFont *xfont; g_return_val_if_fail (fontmap != NULL, NULL); g_return_val_if_fail (pattern != NULL, NULL); - xfont = (PangoXftFont *)g_object_new (PANGO_TYPE_XFT_FONT, NULL); - - xfont->fontmap = fontmap; - xfont->font_pattern = pattern; + xfont = (PangoXftFont *)g_object_new (PANGO_TYPE_XFT_FONT, + "pattern", pattern, + NULL); - g_object_ref (fontmap); - xfont->description = _pango_xft_font_desc_from_pattern (pattern, TRUE); xfont->xft_font = NULL; - _pango_xft_font_map_add (xfont->fontmap, xfont); - return xfont; } @@ -174,8 +134,9 @@ static PangoFont * get_mini_font (PangoFont *font) { PangoXftFont *xfont = (PangoXftFont *)font; + PangoFcFont *fcfont = (PangoFcFont *)font; - g_assert (xfont->fontmap); + g_assert (fcfont->fontmap); if (!xfont->mini_font) { @@ -186,13 +147,13 @@ get_mini_font (PangoFont *font) XGlyphInfo extents; XftFont *mini_xft; - _pango_xft_font_map_get_info (xfont->fontmap, &display, NULL); + _pango_xft_font_map_get_info (fcfont->fontmap, &display, NULL); pango_font_description_set_family_static (desc, "monospace"); pango_font_description_set_size (desc, - 0.5 * pango_font_description_get_size (xfont->description)); + 0.5 * pango_font_description_get_size (fcfont->description)); - xfont->mini_font = pango_font_map_load_font (xfont->fontmap, NULL, desc); + xfont->mini_font = pango_font_map_load_font (fcfont->fontmap, NULL, desc); pango_font_description_free (desc); mini_xft = xft_font_get_font (xfont->mini_font); @@ -281,6 +242,7 @@ pango_xft_real_render (Display *display, gint y) { PangoXftFont *xfont = PANGO_XFT_FONT (font); + PangoFcFont *fcfont = PANGO_FC_FONT (font); XftFont *xft_font = xft_font_get_font (font); int i; int x_off = 0; @@ -289,7 +251,7 @@ pango_xft_real_render (Display *display, XftCharSpec chars[4]; /* for unknown */ int n_xft_glyph = 0; - if (!xfont->fontmap) /* Display closed */ + if (!fcfont->fontmap) /* Display closed */ return; #define FLUSH_GLYPHS() G_STMT_START { \ @@ -305,7 +267,7 @@ pango_xft_real_render (Display *display, } G_STMT_END if (!display) - _pango_xft_font_map_get_info (xfont->fontmap, &display, NULL); + _pango_xft_font_map_get_info (fcfont->fontmap, &display, NULL); for (i=0; inum_glyphs; i++) { @@ -444,133 +406,26 @@ pango_xft_picture_render (Display *display, pango_xft_real_render (display, src_picture, dest_picture, NULL, NULL, font, glyphs, x, y); } -static PangoFontMetrics * -pango_xft_font_get_metrics (PangoFont *font, - PangoLanguage *language) -{ - PangoXftFont *xfont = PANGO_XFT_FONT (font); - PangoXftMetricsInfo *info = NULL; /* Quiet gcc */ - GSList *tmp_list; - - const char *sample_str = pango_language_get_sample_string (language); - - tmp_list = xfont->metrics_by_lang; - while (tmp_list) - { - info = tmp_list->data; - - if (info->sample_str == sample_str) /* We _don't_ need strcmp */ - break; - - tmp_list = tmp_list->next; - } - - if (!tmp_list) - { - PangoLayout *layout; - PangoRectangle extents; - PangoContext *context; - XftFont *xft_font; - Display *display; - int screen; - - info = g_new0 (PangoXftMetricsInfo, 1); - xfont->metrics_by_lang = g_slist_prepend (xfont->metrics_by_lang, - info); - - - if (xfont->fontmap) - { - xft_font = xft_font_get_font (font); - - _pango_xft_font_map_get_info (xfont->fontmap, &display, &screen); - context = pango_xft_get_context (display, screen); - - info->sample_str = sample_str; - info->metrics = pango_font_metrics_new (); - - info->metrics->ascent = PANGO_SCALE * xft_font->ascent; - info->metrics->descent = PANGO_SCALE * xft_font->descent; - info->metrics->approximate_char_width = - info->metrics->approximate_digit_width = - PANGO_SCALE * xft_font->max_advance_width; - - pango_context_set_language (context, language); - layout = pango_layout_new (context); - pango_layout_set_font_description (layout, xfont->description); - - pango_layout_set_text (layout, sample_str, -1); - pango_layout_get_extents (layout, NULL, &extents); - - info->metrics->approximate_char_width = - extents.width / g_utf8_strlen (sample_str, -1); - - pango_layout_set_text (layout, "0123456789", -1); - pango_layout_get_extents (layout, NULL, &extents); - - info->metrics->approximate_digit_width = extents.width / 10; - - g_object_unref (layout); - g_object_unref (context); - } - } - - return pango_font_metrics_ref (info->metrics); -} - -static void -free_metrics_info (PangoXftMetricsInfo *info) -{ - pango_font_metrics_unref (info->metrics); - g_free (info); -} - static void pango_xft_font_finalize (GObject *object) { PangoXftFont *xfont = (PangoXftFont *)object; - - if (xfont->fontmap) - _pango_xft_font_map_remove (xfont->fontmap, xfont); + PangoFcFont *fcfont = (PangoFcFont *)object; if (xfont->mini_font) g_object_unref (xfont->mini_font); - pango_font_description_free (xfont->description); - - g_slist_foreach (xfont->metrics_by_lang, (GFunc)free_metrics_info, NULL); - g_slist_free (xfont->metrics_by_lang); - if (xfont->xft_font) { Display *display; - _pango_xft_font_map_get_info (xfont->fontmap, &display, NULL); + _pango_xft_font_map_get_info (fcfont->fontmap, &display, NULL); XftFontClose (display, xfont->xft_font); } - FcPatternDestroy (xfont->font_pattern); - 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, - PangoLanguage *language) -{ - PangoXftFont *xfont = (PangoXftFont *)font; - - return _pango_xft_font_map_get_coverage (xfont->fontmap, xfont->font_pattern); -} - static void pango_xft_font_get_glyph_extents (PangoFont *font, PangoGlyph glyph, @@ -579,13 +434,14 @@ pango_xft_font_get_glyph_extents (PangoFont *font, { PangoXftFont *xfont = (PangoXftFont *)font; XftFont *xft_font = xft_font_get_font (font); + PangoFcFont *fcfont = PANGO_FC_FONT (font); XGlyphInfo extents; Display *display; - if (!xfont->fontmap) /* Display closed */ + if (!fcfont->fontmap) /* Display closed */ goto fallback; - _pango_xft_font_map_get_info (xfont->fontmap, &display, NULL); + _pango_xft_font_map_get_info (fcfont->fontmap, &display, NULL); if (glyph == (PangoGlyph)-1) glyph = 0; @@ -652,59 +508,19 @@ pango_xft_font_get_glyph_extents (PangoFont *font, } } -static PangoMap * -pango_xft_get_shaper_map (PangoLanguage *language) -{ - 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 (language, engine_type_id, render_type_id); -} - -static PangoEngineShape * -pango_xft_font_find_shaper (PangoFont *font, - PangoLanguage *language, - guint32 ch) -{ - PangoMap *shape_map = NULL; - - shape_map = pango_xft_get_shaper_map (language); - return (PangoEngineShape *)pango_map_get_engine (shape_map, ch); -} - -static gboolean -set_unicode_charmap (FT_Face face) -{ - int charmap; - - for (charmap = 0; charmap < face->num_charmaps; charmap++) - if (face->charmaps[charmap]->encoding == ft_encoding_unicode) - { - FT_Error error = FT_Set_Charmap(face, face->charmaps[charmap]); - return error == FT_Err_Ok; - } - - return FALSE; -} - static void load_fallback_font (PangoXftFont *xfont) { + PangoFcFont *fcfont = PANGO_FC_FONT (xfont); Display *display; int screen; XftFont *xft_font; - _pango_xft_font_map_get_info (xfont->fontmap, &display, &screen); + _pango_xft_font_map_get_info (fcfont->fontmap, &display, &screen); xft_font = XftFontOpen (display, screen, FC_FAMILY, FcTypeString, "sans", - FC_SIZE, FcTypeDouble, (double)pango_font_description_get_size (xfont->description)/PANGO_SCALE, + FC_SIZE, FcTypeDouble, (double)pango_font_description_get_size (fcfont->description)/PANGO_SCALE, NULL); if (!xft_font) @@ -720,19 +536,21 @@ static XftFont * xft_font_get_font (PangoFont *font) { PangoXftFont *xfont; + PangoFcFont *fcfont; Display *display; int screen; xfont = (PangoXftFont *)font; + fcfont = (PangoFcFont *)font; if (xfont->xft_font == NULL) { - _pango_xft_font_map_get_info (xfont->fontmap, &display, &screen); + _pango_xft_font_map_get_info (fcfont->fontmap, &display, &screen); - xfont->xft_font = XftFontOpenPattern (display, FcPatternDuplicate (xfont->font_pattern)); + xfont->xft_font = XftFontOpenPattern (display, FcPatternDuplicate (fcfont->font_pattern)); if (!xfont->xft_font) { - gchar *name = pango_font_description_to_string (xfont->description); + gchar *name = pango_font_description_to_string (fcfont->description); g_warning ("Cannot open font file for font %s", name); g_free (name); @@ -785,37 +603,18 @@ pango_xft_font_real_get_unknown_glyph (PangoFcFont *font, } static void -pango_xft_font_real_kern_glyphs (PangoFcFont *font, - PangoGlyphString *glyphs) +pango_xft_font_real_shutdown (PangoFcFont *fcfont) { - FT_Face face; - FT_Error error; - FT_Vector kerning; - int i; - - face = pango_fc_font_lock_face (font); - if (!face) - return; - - if (!FT_HAS_KERNING (face)) - { - pango_fc_font_unlock_face (font); - return; - } + PangoXftFont *xfont = PANGO_XFT_FONT (fcfont); - for (i = 1; i < glyphs->num_glyphs; ++i) + if (xfont->xft_font) { - error = FT_Get_Kerning (face, - glyphs->glyphs[i-1].glyph, - glyphs->glyphs[i].glyph, - ft_kerning_default, - &kerning); - - if (error == FT_Err_Ok) - glyphs->glyphs[i-1].geometry.width += PANGO_UNITS_26_6 (kerning.x); + Display *display; + + _pango_xft_font_map_get_info (fcfont->fontmap, &display, NULL); + XftFontClose (display, xfont->xft_font); + xfont->xft_font = NULL; } - - pango_fc_font_unlock_face (font); } /** @@ -845,13 +644,13 @@ pango_xft_font_get_font (PangoFont *font) Display * pango_xft_font_get_display (PangoFont *font) { - PangoXftFont *xfont; + PangoFcFont *fcfont; 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); + fcfont = PANGO_FC_FONT (font); + _pango_xft_font_map_get_info (fcfont->fontmap, &display, NULL); return display; } diff --git a/pango/pangoxft-fontmap.c b/pango/pangoxft-fontmap.c index 9d800d10..ca362cb2 100644 --- a/pango/pangoxft-fontmap.c +++ b/pango/pangoxft-fontmap.c @@ -1,7 +1,7 @@ /* Pango * pangoxft-fontmap.c: Xft font handling * - * Copyright (C) 2000 Red Hat Software + * Copyright (C) 2000-2003 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 @@ -22,16 +22,15 @@ #include #include -#include "pango-fontmap.h" +#include "pangofc-fontmap.h" #include "pangoxft.h" #include "pangoxft-private.h" -#include "modules.h" /* For XExtSetCloseDisplay */ #include typedef struct _PangoXftFamily PangoXftFamily; -typedef struct _PangoXftFontMap PangoXftFontMap; +typedef struct _PangoXftFontMapClass PangoXftFontMapClass; #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)) @@ -39,29 +38,10 @@ typedef struct _PangoXftFontMap PangoXftFontMap; struct _PangoXftFontMap { - PangoFontMap parent_instance; - - /* We have one map from PangoFontDescription -> PangoXftPatternSet - * per language tag. - */ - GList *fontset_hash_list; - /* pattern_hash is used to make sure we only store one copy of - * each identical pattern. (Speeds up lookup). - */ - GHashTable *pattern_hash; - GHashTable *coverage_hash; /* Maps font file name/id -> PangoCoverage */ - - GHashTable *fonts; /* Maps XftPattern -> PangoXftFont */ - - GQueue *fontset_cache; /* Recently used fontsets */ - - /* List of all families availible */ - PangoXftFamily **families; - int n_families; /* -1 == uninitialized */ + PangoFcFontMap parent_instance; Display *display; int screen; - guint closed : 1; /* Function to call on prepared patterns to do final * config tweaking. @@ -71,32 +51,76 @@ struct _PangoXftFontMap GDestroyNotify substitute_destroy; }; -/************************************************************ - * Code shared with PangoFT2 * - ************************************************************/ +struct _PangoXftFontMapClass +{ + PangoFcFontMapClass parent_class; +}; + +static void pango_xft_font_map_class_init (PangoXftFontMapClass *class); +static void pango_xft_font_map_default_substitute (PangoFcFontMap *fcfontmap, + FcPattern *pattern); +static PangoFcFont * pango_xft_font_map_new_font (PangoFcFontMap *fcfontmap, + FcPattern *pattern); +static void pango_xft_font_map_finalize (GObject *object); + +static GObjectClass *parent_class; + +static GSList *fontmaps = NULL; + +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) NULL, + }; + + object_type = g_type_register_static (PANGO_TYPE_FC_FONT_MAP, + "PangoXftFontMap", + &object_info, 0); + } + + return object_type; +} + +static void +pango_xft_font_map_class_init (PangoXftFontMapClass *class) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (class); + PangoFcFontMapClass *fcfontmap_class = PANGO_FC_FONT_MAP_CLASS (class); -#define PangoFcFamily PangoXftFamily -#define _PangoFcFamily _PangoXftFamily -#define PangoFcFontMap PangoXftFontMap -#define PangoFcFont PangoXftFont + parent_class = g_type_class_peek_parent (class); -#define PANGO_FC_FONT_MAP PANGO_XFT_FONT_MAP + gobject_class->finalize = pango_xft_font_map_finalize; + fcfontmap_class->default_substitute = pango_xft_font_map_default_substitute; + fcfontmap_class->new_font = pango_xft_font_map_new_font; +} -#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_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_map_finalize (GObject *object) +{ + PangoXftFontMap *xftfontmap = PANGO_XFT_FONT_MAP (object); + + fontmaps = g_slist_remove (fontmaps, object); -#define PANGO_FC_NAME "PangoXft" + if (xftfontmap->substitute_destroy) + xftfontmap->substitute_destroy (xftfontmap->substitute_data); -#include "pangofc-fontmap.cI" + parent_class->finalize (object); +} -/************************************************************* - * Xft specific code * - *************************************************************/ static PangoFontMap * pango_xft_find_font_map (Display *display, @@ -180,29 +204,18 @@ PangoFontMap * pango_xft_get_font_map (Display *display, int screen) { - static gboolean registered_modules = FALSE; PangoFontMap *fontmap; PangoXftFontMap *xftfontmap; g_return_val_if_fail (display != NULL, NULL); - if (!registered_modules) - { - int i; - - registered_modules = TRUE; - - /* Make sure that the type system is initialized */ - g_type_init (); - - for (i = 0; _pango_included_xft_modules[i].list; i++) - pango_module_register (&_pango_included_xft_modules[i]); - } - fontmap = pango_xft_find_font_map (display, screen); if (fontmap) return fontmap; + /* Make sure that the type system is initialized */ + g_type_init (); + xftfontmap = (PangoXftFontMap *)g_object_new (PANGO_TYPE_XFT_FONT_MAP, NULL); xftfontmap->display = display; @@ -215,17 +228,6 @@ pango_xft_get_font_map (Display *display, return PANGO_FONT_MAP (xftfontmap); } -static void -cleanup_font (gpointer key, - PangoXftFont *xfont, - PangoXftFontMap *xftfontmap) -{ - if (xfont->xft_font) - XftFontClose (xftfontmap->display, xfont->xft_font); - - xfont->fontmap = NULL; -} - /** * pango_xft_shutdown_display: * @display: an X display @@ -246,16 +248,11 @@ pango_xft_shutdown_display (Display *display, if (fontmap) { PangoXftFontMap *xftfontmap = PANGO_XFT_FONT_MAP (fontmap); - + fontmaps = g_slist_remove (fontmaps, fontmap); - pango_fc_font_map_cache_clear (xftfontmap); - - g_hash_table_foreach (xftfontmap->fonts, (GHFunc)cleanup_font, fontmap); - g_hash_table_destroy (xftfontmap->fonts); - xftfontmap->fonts = NULL; + pango_fc_font_map_shutdown (PANGO_FC_FONT_MAP (fontmap)); xftfontmap->display = NULL; - xftfontmap->closed = TRUE; g_object_unref (fontmap); } } @@ -292,7 +289,7 @@ pango_xft_set_default_substitute (Display *display, xftfontmap->substitute_data = data; xftfontmap->substitute_destroy = notify; - pango_fc_font_map_cache_clear (xftfontmap); + pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (xftfontmap)); } /** @@ -314,7 +311,7 @@ pango_xft_substitute_changed (Display *display, { PangoXftFontMap *xftfontmap = (PangoXftFontMap *)pango_xft_get_font_map (display, screen); - pango_fc_font_map_cache_clear (xftfontmap); + pango_fc_font_map_cache_clear (PANGO_FC_FONT_MAP (xftfontmap)); } void @@ -344,29 +341,29 @@ PangoContext * pango_xft_get_context (Display *display, int screen) { - PangoContext *result; + PangoFontMap *fontmap; g_return_val_if_fail (display != NULL, NULL); - result = pango_context_new (); - pango_context_set_font_map (result, pango_xft_get_font_map (display, screen)); - - return result; + fontmap = pango_xft_get_font_map (display, screen); + return pango_fc_font_map_create_context (PANGO_FC_FONT_MAP (fontmap)); } static void -pango_fc_do_finalize (PangoXftFontMap *fontmap) +pango_xft_font_map_default_substitute (PangoFcFontMap *fcfontmap, + FcPattern *pattern) { - if (fontmap->substitute_destroy) - fontmap->substitute_destroy (fontmap->substitute_data); + PangoXftFontMap *xftfontmap = PANGO_XFT_FONT_MAP (fcfontmap); + + FcConfigSubstitute (NULL, pattern, FcMatchPattern); + if (xftfontmap->substitute_func) + xftfontmap->substitute_func (pattern, xftfontmap->substitute_data); + XftDefaultSubstitute (xftfontmap->display, xftfontmap->screen, pattern); } -static void -pango_fc_default_substitute (PangoXftFontMap *fontmap, +static PangoFcFont * +pango_xft_font_map_new_font (PangoFcFontMap *fcfontmap, FcPattern *pattern) { - FcConfigSubstitute (NULL, pattern, FcMatchPattern); - if (fontmap->substitute_func) - fontmap->substitute_func (pattern, fontmap->substitute_data); - XftDefaultSubstitute (fontmap->display, fontmap->screen, pattern); + return (PangoFcFont *)_pango_xft_font_new (PANGO_XFT_FONT_MAP (fcfontmap), pattern); } diff --git a/pango/pangoxft-private.h b/pango/pangoxft-private.h index 0d42ae16..0ffdf6e5 100644 --- a/pango/pangoxft-private.h +++ b/pango/pangoxft-private.h @@ -27,39 +27,26 @@ G_BEGIN_DECLS -typedef struct _PangoXftFont PangoXftFont; +typedef struct _PangoXftFont PangoXftFont; +typedef struct _PangoXftFontMap PangoXftFontMap; struct _PangoXftFont { PangoFcFont parent_instance; - FcPattern *font_pattern; /* fully resolved pattern */ XftFont *xft_font; /* created on demand */ PangoFont *mini_font; /* font used to display missing glyphs */ - PangoFontMap *fontmap; /* associated map */ - PangoFontDescription *description; - - GSList *metrics_by_lang; guint16 mini_width; /* metrics for missing glyph drawing */ guint16 mini_height; guint16 mini_pad; }; -PangoXftFont * _pango_xft_font_new (PangoFontMap *font, - FcPattern *pattern); -void _pango_xft_font_map_add (PangoFontMap *fontmap, - PangoXftFont *xfont); -void _pango_xft_font_map_remove (PangoFontMap *fontmap, - PangoXftFont *xfont); -PangoCoverage *_pango_xft_font_map_get_coverage (PangoFontMap *fontmap, - FcPattern *pattern); -void _pango_xft_font_map_get_info (PangoFontMap *fontmap, - Display **display, - int *screen); - -PangoFontDescription * _pango_xft_font_desc_from_pattern (FcPattern *pattern, - gboolean include_size); +PangoXftFont *_pango_xft_font_new (PangoXftFontMap *xftfontmap, + FcPattern *pattern); +void _pango_xft_font_map_get_info (PangoFontMap *fontmap, + Display **display, + int *screen); G_END_DECLS diff --git a/pango/pangoxft.h b/pango/pangoxft.h index bb5ce511..3f6ecfd5 100644 --- a/pango/pangoxft.h +++ b/pango/pangoxft.h @@ -38,7 +38,9 @@ G_BEGIN_DECLS #error "must have Xft version 2 or newer" #endif +#ifndef PANGO_DISABLE_DEPRECATED #define PANGO_RENDER_TYPE_XFT "PangoRenderXft" +#endif typedef void (*PangoXftSubstituteFunc) (FcPattern *pattern, gpointer data); -- cgit v1.2.1