diff options
Diffstat (limited to 'pango/pangoxft-fontmap.c')
-rw-r--r-- | pango/pangoxft-fontmap.c | 481 |
1 files changed, 317 insertions, 164 deletions
diff --git a/pango/pangoxft-fontmap.c b/pango/pangoxft-fontmap.c index c9f044a6..a63f969a 100644 --- a/pango/pangoxft-fontmap.c +++ b/pango/pangoxft-fontmap.c @@ -26,18 +26,16 @@ #include "X11/Xft/XftFreetype.h" -#define PANGO_TYPE_XFT_FONT_MAP (pango_xft_font_map_get_type ()) -#define PANGO_XFT_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_XFT_FONT_MAP, PangoXftFontMap)) -#define PANGO_XFT_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PANGO_TYPE_XFT_FONT_MAP, PangoXftFontMapClass)) -#define PANGO_XFT_IS_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_XFT_FONT_MAP)) -#define PANGO_XFT_IS_FONT_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PANGO_TYPE_XFT_FONT_MAP)) -#define PANGO_XFT_FONT_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PANGO_TYPE_XFT_FONT_MAP, PangoXftFontMapClass)) - /* Number of freed fonts */ #define MAX_FREED_FONTS 16 typedef struct _PangoXftFontMap PangoXftFontMap; -typedef struct _PangoXftFontMapClass PangoXftFontMapClass; +typedef struct _PangoXftFamily PangoXftFamily; +typedef struct _PangoXftFace PangoXftFace; + +#define PANGO_TYPE_XFT_FONT_MAP (pango_xft_font_map_get_type ()) +#define PANGO_XFT_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_TYPE_XFT_FONT_MAP, PangoXftFontMap)) +#define PANGO_XFT_IS_FONT_MAP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_TYPE_XFT_FONT_MAP)) struct _PangoXftFontMap { @@ -47,29 +45,52 @@ struct _PangoXftFontMap GHashTable *coverage_hash; GQueue *freed_fonts; + PangoXftFamily **families; + int n_families; /* -1 == uninitialized */ + Display *display; int screen; }; -struct _PangoXftFontMapClass +#define PANGO_XFT_TYPE_FAMILY (pango_xft_family_get_type ()) +#define PANGO_XFT_FAMILY(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_XFT_TYPE_FAMILY, PangoXftFamily)) +#define PANGO_XFT_IS_FAMILY(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_XFT_TYPE_FAMILY)) + +struct _PangoXftFamily +{ + PangoFontFamily parent_instance; + + PangoXftFontMap *fontmap; + char *family_name; + + PangoXftFace **faces; + int n_faces; /* -1 == uninitialized */ +}; + +#define PANGO_XFT_TYPE_FACE (pango_xft_face_get_type ()) +#define PANGO_XFT_FACE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), PANGO_XFT_TYPE_FACE, PangoXftFace)) +#define PANGO_XFT_IS_FACE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), PANGO_XFT_TYPE_FACE)) + +struct _PangoXftFace { - PangoFontMapClass parent_class; + PangoFontFace parent_instance; + + PangoXftFamily *family; + char *style; }; static GType pango_xft_font_map_get_type (void); -static void pango_xft_font_map_init (PangoXftFontMap *fontmap); -static void pango_xft_font_map_class_init (PangoXftFontMapClass *class); +GType pango_xft_family_get_type (void); +GType pango_xft_face_get_type (void); +static void pango_xft_font_map_init (PangoXftFontMap *fontmap); +static void pango_xft_font_map_class_init (PangoFontMapClass *class); static void pango_xft_font_map_finalize (GObject *object); static PangoFont *pango_xft_font_map_load_font (PangoFontMap *fontmap, - const PangoFontDescription *description); -static void pango_xft_font_map_list_fonts (PangoFontMap *fontmap, - const gchar *family, - PangoFontDescription ***descs, - int *n_descs); + const PangoFontDescription *description); static void pango_xft_font_map_list_families (PangoFontMap *fontmap, - gchar ***families, - int *n_families); + PangoFontFamily ***families, + int *n_families); static void pango_xft_font_map_cache_clear (PangoXftFontMap *xfontmap); static void pango_xft_font_map_cache_remove (PangoFontMap *fontmap, @@ -86,7 +107,7 @@ pango_xft_font_map_get_type (void) { static const GTypeInfo object_info = { - sizeof (PangoXftFontMapClass), + sizeof (PangoFontMapClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) pango_xft_font_map_class_init, @@ -108,41 +129,23 @@ pango_xft_font_map_get_type (void) static void pango_xft_font_map_init (PangoXftFontMap *xfontmap) { + xfontmap->n_families = -1; } static void -pango_xft_font_map_class_init (PangoXftFontMapClass *class) +pango_xft_font_map_class_init (PangoFontMapClass *class) { GObjectClass *object_class = G_OBJECT_CLASS (class); - PangoFontMapClass *font_map_class = PANGO_FONT_MAP_CLASS (class); parent_class = g_type_class_peek_parent (class); object_class->finalize = pango_xft_font_map_finalize; - font_map_class->load_font = pango_xft_font_map_load_font; - font_map_class->list_fonts = pango_xft_font_map_list_fonts; - font_map_class->list_families = pango_xft_font_map_list_families; + class->load_font = pango_xft_font_map_load_font; + class->list_families = pango_xft_font_map_list_families; } static GSList *fontmaps = NULL; -static guint -font_description_hash (const PangoFontDescription *desc) -{ - guint hash = 0; - - if (desc->family_name) - hash = g_str_hash (desc->family_name); - - hash ^= desc->size; - hash ^= desc->style << 16; - hash ^= desc->variant << 18; - hash ^= desc->weight << 16; - hash ^= desc->stretch << 26; - - return hash; -} - static PangoFontMap * pango_xft_get_font_map (Display *display, int screen) @@ -169,7 +172,7 @@ pango_xft_get_font_map (Display *display, xfontmap->display = display; xfontmap->screen = screen; - xfontmap->font_hash = g_hash_table_new ((GHashFunc)font_description_hash, + xfontmap->font_hash = g_hash_table_new ((GHashFunc)pango_font_description_hash, (GEqualFunc)pango_font_description_equal); xfontmap->coverage_hash = g_hash_table_new (g_str_hash, g_str_equal); xfontmap->freed_fonts = g_queue_new (); @@ -246,124 +249,26 @@ _pango_xft_font_map_remove (PangoFontMap *fontmap, g_hash_table_remove (xfontmap->font_hash, xfont->description); } -static PangoFontDescription * -font_desc_from_pattern (XftPattern *pattern) -{ - PangoFontDescription *desc; - char *s; - int i; - - desc = g_new (PangoFontDescription, 1); - - g_assert (XftPatternGetString (pattern, XFT_FAMILY, 0, &s) == XftResultMatch); - - desc->family_name = g_strdup (s); - - if (XftPatternGetInteger (pattern, XFT_SLANT, 0, &i) == XftResultMatch) - { - if (i == XFT_SLANT_ROMAN) - desc->style = PANGO_STYLE_NORMAL; - else if (i == XFT_SLANT_OBLIQUE) - desc->style = PANGO_STYLE_OBLIQUE; - else - desc->style = PANGO_STYLE_ITALIC; - } - else - desc->style = PANGO_STYLE_NORMAL; - - if (XftPatternGetInteger (pattern, XFT_WEIGHT, 0, &i) == XftResultMatch) - { - if (i < XFT_WEIGHT_LIGHT) - desc->weight = PANGO_WEIGHT_ULTRALIGHT; - else if (i < (XFT_WEIGHT_LIGHT + XFT_WEIGHT_MEDIUM) / 2) - desc->weight = PANGO_WEIGHT_LIGHT; - else if (i < (XFT_WEIGHT_MEDIUM + XFT_WEIGHT_DEMIBOLD) / 2) - desc->weight = PANGO_WEIGHT_NORMAL; - else if (i < (XFT_WEIGHT_DEMIBOLD + XFT_WEIGHT_BOLD) / 2) - desc->weight = 600; - else if (i < (XFT_WEIGHT_BOLD + XFT_WEIGHT_BLACK) / 2) - desc->weight = PANGO_WEIGHT_BOLD; - else - desc->weight = PANGO_WEIGHT_ULTRABOLD; - } - - desc->variant = PANGO_VARIANT_NORMAL; - desc->stretch = PANGO_STRETCH_NORMAL; - desc->size = -1; - - return desc; -} - - -static void -pango_xft_font_map_list_fonts (PangoFontMap *fontmap, - const gchar *family, - PangoFontDescription ***descs, - int *n_descs) -{ - PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap); - XftFontSet *fontset; - - if (family) - fontset = XftListFonts (xfontmap->display, xfontmap->screen, - XFT_ENCODING, XftTypeString, "iso10646-1", - XFT_FAMILY, XftTypeString, family, - XFT_CORE, XftTypeBool, False, - NULL, - XFT_FAMILY, - XFT_STYLE, - XFT_WEIGHT, - XFT_SLANT, - NULL); - else - fontset = XftListFonts (xfontmap->display, xfontmap->screen, - XFT_ENCODING, XftTypeString, "iso10646-1", - XFT_CORE, XftTypeBool, False, - NULL, - XFT_FAMILY, - XFT_STYLE, - XFT_WEIGHT, - XFT_SLANT, - NULL); - - if (n_descs) - *n_descs = fontset->nfont; - - if (descs) - { - gint i; - - *descs = g_new (PangoFontDescription *, fontset->nfont); - - for (i = 0; i < fontset->nfont; i++) - (*descs)[i] = font_desc_from_pattern (fontset->fonts[i]); - } - - XftFontSetDestroy (fontset); -} - static void pango_xft_font_map_list_families (PangoFontMap *fontmap, - gchar ***families, + PangoFontFamily ***families, int *n_families) { PangoXftFontMap *xfontmap = PANGO_XFT_FONT_MAP (fontmap); XftFontSet *fontset; int i; - fontset = XftListFonts (xfontmap->display, xfontmap->screen, - XFT_CORE, XftTypeBool, False, - XFT_ENCODING, XftTypeString, "iso10646-1", - NULL, - XFT_FAMILY, - NULL); - - if (n_families) - *n_families = fontset->nfont; - - if (families) + if (xfontmap->n_families < 0) { - *families = g_new (gchar *, fontset->nfont); + fontset = XftListFonts (xfontmap->display, xfontmap->screen, + XFT_CORE, XftTypeBool, False, + XFT_ENCODING, XftTypeString, "iso10646-1", + NULL, + XFT_FAMILY, + NULL); + + xfontmap->n_families = fontset->nfont; + xfontmap->families = g_new (PangoXftFamily *, xfontmap->n_families); for (i = 0; i < fontset->nfont; i++) { @@ -372,12 +277,20 @@ pango_xft_font_map_list_families (PangoFontMap *fontmap, res = XftPatternGetString (fontset->fonts[i], XFT_FAMILY, 0, &s); g_assert (res == XftResultMatch); - - (*families)[i] = g_strdup (s); + + xfontmap->families[i] = g_object_new (PANGO_XFT_TYPE_FAMILY, NULL); + xfontmap->families[i]->family_name = g_strdup (s); + xfontmap->families[i]->fontmap = xfontmap; } - } - XftFontSetDestroy (fontset); + XftFontSetDestroy (fontset); + } + + if (n_families) + *n_families = xfontmap->n_families; + + if (families) + *families = g_memdup (xfontmap->families, xfontmap->n_families * sizeof (PangoFontFamily *)); } static PangoFont * @@ -386,7 +299,9 @@ pango_xft_font_map_load_font (PangoFontMap *fontmap, { PangoXftFontMap *xfontmap = (PangoXftFontMap *)fontmap; PangoXftFont *font; + PangoStyle pango_style; int slant; + PangoWeight pango_weight; int weight; XftFont *xft_font; @@ -400,20 +315,24 @@ pango_xft_font_map_load_font (PangoFontMap *fontmap, return (PangoFont *)g_object_ref (G_OBJECT (font)); } - if (description->style == PANGO_STYLE_ITALIC) + pango_style = pango_font_description_get_style (description); + + if (pango_style == PANGO_STYLE_ITALIC) slant = XFT_SLANT_ITALIC; - else if (description->style == PANGO_STYLE_OBLIQUE) + else if (pango_style == PANGO_STYLE_OBLIQUE) slant = XFT_SLANT_OBLIQUE; else slant = XFT_SLANT_ROMAN; - if (description->weight < (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_LIGHT) / 2) + pango_weight = pango_font_description_get_weight (description); + + if (pango_weight < (PANGO_WEIGHT_NORMAL + PANGO_WEIGHT_LIGHT) / 2) weight = XFT_WEIGHT_LIGHT; - else if (description->weight < (PANGO_WEIGHT_NORMAL + 600) / 2) + else if (pango_weight < (PANGO_WEIGHT_NORMAL + 600) / 2) weight = XFT_WEIGHT_MEDIUM; - else if (description->weight < (600 + PANGO_WEIGHT_BOLD) / 2) + else if (pango_weight < (600 + PANGO_WEIGHT_BOLD) / 2) weight = XFT_WEIGHT_DEMIBOLD; - else if (description->weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2) + else if (pango_weight < (PANGO_WEIGHT_BOLD + PANGO_WEIGHT_ULTRABOLD) / 2) weight = XFT_WEIGHT_BOLD; else weight = XFT_WEIGHT_BLACK; @@ -424,10 +343,10 @@ pango_xft_font_map_load_font (PangoFontMap *fontmap, xft_font = XftFontOpen (xfontmap->display, xfontmap->screen, XFT_ENCODING, XftTypeString, "glyphs-fontspecific", XFT_CORE, XftTypeBool, False, - XFT_FAMILY, XftTypeString, description->family_name, + XFT_FAMILY, XftTypeString, pango_font_description_get_family (description), XFT_WEIGHT, XftTypeInteger, weight, XFT_SLANT, XftTypeInteger, slant, - XFT_SIZE, XftTypeDouble, (double)description->size/PANGO_SCALE, + XFT_SIZE, XftTypeDouble, (double)pango_font_description_get_size (description)/PANGO_SCALE, NULL); if (xft_font) @@ -547,3 +466,237 @@ _pango_xft_font_map_get_info (PangoFontMap *fontmap, *screen = xfontmap->screen; } + + +/* + * PangoXftFace + */ + +static PangoFontDescription * +font_desc_from_pattern (XftPattern *pattern) +{ + PangoFontDescription *desc; + PangoStyle style; + PangoWeight weight; + + char *s; + int i; + + desc = pango_font_description_new (); + + g_assert (XftPatternGetString (pattern, XFT_FAMILY, 0, &s) == XftResultMatch); + + pango_font_description_set_family (desc, s); + + if (XftPatternGetInteger (pattern, XFT_SLANT, 0, &i) == XftResultMatch) + { + if (i == XFT_SLANT_ROMAN) + style = PANGO_STYLE_NORMAL; + else if (i == XFT_SLANT_OBLIQUE) + style = PANGO_STYLE_OBLIQUE; + else + style = PANGO_STYLE_ITALIC; + } + else + style = PANGO_STYLE_NORMAL; + + pango_font_description_set_style (desc, style); + + if (XftPatternGetInteger (pattern, XFT_WEIGHT, 0, &i) == XftResultMatch) + { + if (i < XFT_WEIGHT_LIGHT) + weight = PANGO_WEIGHT_ULTRALIGHT; + else if (i < (XFT_WEIGHT_LIGHT + XFT_WEIGHT_MEDIUM) / 2) + weight = PANGO_WEIGHT_LIGHT; + else if (i < (XFT_WEIGHT_MEDIUM + XFT_WEIGHT_DEMIBOLD) / 2) + weight = PANGO_WEIGHT_NORMAL; + else if (i < (XFT_WEIGHT_DEMIBOLD + XFT_WEIGHT_BOLD) / 2) + weight = 600; + else if (i < (XFT_WEIGHT_BOLD + XFT_WEIGHT_BLACK) / 2) + weight = PANGO_WEIGHT_BOLD; + else + weight = PANGO_WEIGHT_ULTRABOLD; + } + else + weight = PANGO_WEIGHT_NORMAL; + + pango_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 * +pango_xft_face_describe (PangoFontFace *face) +{ + PangoXftFace *xface = PANGO_XFT_FACE (face); + PangoXftFamily *xfamily = xface->family; + PangoXftFontMap *xfontmap = xfamily->fontmap; + PangoFontDescription *desc = NULL; + XftResult res; + XftPattern *match_pattern; + XftPattern *result_pattern; + + match_pattern = XftPatternBuild (NULL, + XFT_ENCODING, XftTypeString, "iso10646-1", + XFT_FAMILY, XftTypeString, xfamily->family_name, + XFT_CORE, XftTypeBool, False, + XFT_STYLE, XftTypeString, xface->style, + NULL); + g_assert (match_pattern); + + result_pattern = XftFontMatch (xfontmap->display, xfontmap->screen, match_pattern, &res); + if (result_pattern) + { + desc = font_desc_from_pattern (result_pattern); + XftPatternDestroy (result_pattern); + } + + XftPatternDestroy (match_pattern); + + return desc; +} + +static const char * +pango_xft_face_get_face_name (PangoFontFace *face) +{ + PangoXftFace *xface = PANGO_XFT_FACE (face); + + return xface->style; +} + +static void +pango_xft_face_class_init (PangoFontFaceClass *class) +{ + class->describe = pango_xft_face_describe; + class->get_face_name = pango_xft_face_get_face_name; +} + +GType +pango_xft_face_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (PangoFontFaceClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) pango_xft_face_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PangoXftFace), + 0, /* n_preallocs */ + (GInstanceInitFunc) NULL, + }; + + object_type = g_type_register_static (PANGO_TYPE_FONT_FACE, + "PangoXftFace", + &object_info, 0); + } + + return object_type; +} + +/* + * PangoXFontFamily + */ +static void +pango_xft_family_list_faces (PangoFontFamily *family, + PangoFontFace ***faces, + int *n_faces) +{ + PangoXftFamily *xfamily = PANGO_XFT_FAMILY (family); + PangoXftFontMap *xfontmap = xfamily->fontmap; + + if (xfamily->n_faces < 0) + { + XftFontSet *fontset; + int i; + + fontset = XftListFonts (xfontmap->display, xfontmap->screen, + XFT_ENCODING, XftTypeString, "iso10646-1", + XFT_FAMILY, XftTypeString, xfamily->family_name, + XFT_CORE, XftTypeBool, False, + NULL, + XFT_STYLE, + NULL); + + xfamily->n_faces = fontset->nfont; + xfamily->faces = g_new (PangoXftFace *, xfamily->n_faces); + + for (i = 0; i < fontset->nfont; i++) + { + char *s; + XftResult res; + + res = XftPatternGetString (fontset->fonts[i], XFT_STYLE, 0, &s); + g_assert (res == XftResultMatch); + + xfamily->faces[i] = g_object_new (PANGO_XFT_TYPE_FACE, NULL); + xfamily->faces[i]->style = g_strdup (s); + xfamily->faces[i]->family = xfamily; + } + + XftFontSetDestroy (fontset); + } + + if (n_faces) + *n_faces = xfamily->n_faces; + + if (faces) + *faces = g_memdup (xfamily->faces, xfamily->n_faces * sizeof (PangoFontFace *)); +} + +const char * +pango_xft_family_get_name (PangoFontFamily *family) +{ + PangoXftFamily *xfamily = PANGO_XFT_FAMILY (family); + + return xfamily->family_name; +} + +static void +pango_xft_family_class_init (PangoFontFamilyClass *class) +{ + class->list_faces = pango_xft_family_list_faces; + class->get_name = pango_xft_family_get_name; +} + +void +pango_xft_family_init (PangoXftFamily *xfamily) +{ + xfamily->n_faces = -1; +} + +GType +pango_xft_family_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + static const GTypeInfo object_info = + { + sizeof (PangoFontFamilyClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) pango_xft_family_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (PangoXftFamily), + 0, /* n_preallocs */ + (GInstanceInitFunc) pango_xft_family_init, + }; + + object_type = g_type_register_static (PANGO_TYPE_FONT_FAMILY, + "PangoXftFamily", + &object_info, 0); + } + + return object_type; +} |