diff options
Diffstat (limited to 'gdk/gdkfont.c')
-rw-r--r-- | gdk/gdkfont.c | 107 |
1 files changed, 99 insertions, 8 deletions
diff --git a/gdk/gdkfont.c b/gdk/gdkfont.c index d1f779a064..096cf8a537 100644 --- a/gdk/gdkfont.c +++ b/gdk/gdkfont.c @@ -29,6 +29,63 @@ #include "gdk.h" #include "gdkprivate.h" +static GHashTable *font_name_hash = NULL; +static GHashTable *fontset_name_hash = NULL; + +static void +gdk_font_hash_insert (GdkFontType type, GdkFont *font, const gchar *font_name) +{ + GdkFontPrivate *private = (GdkFontPrivate *)font; + GHashTable **hashp = (type == GDK_FONT_FONT) ? + &font_name_hash : &fontset_name_hash; + + if (!*hashp) + *hashp = g_hash_table_new (g_str_hash, g_str_equal); + + private->names = g_slist_prepend (private->names, g_strdup (font_name)); + g_hash_table_insert (*hashp, private->names->data, font); +} + +static void +gdk_font_hash_remove (GdkFontType type, GdkFont *font) +{ + GdkFontPrivate *private = (GdkFontPrivate *)font; + GSList *tmp_list; + GHashTable *hash = (type == GDK_FONT_FONT) ? + font_name_hash : fontset_name_hash; + + tmp_list = private->names; + while (tmp_list) + { + g_hash_table_remove (hash, tmp_list->data); + g_free (tmp_list->data); + + tmp_list = tmp_list->next; + } + + g_slist_free (private->names); + private->names = NULL; +} + +static GdkFont * +gdk_font_hash_lookup (GdkFontType type, const gchar *font_name) +{ + GdkFont *result; + GHashTable *hash = (type == GDK_FONT_FONT) ? + font_name_hash : fontset_name_hash; + + if (!hash) + return NULL; + else + { + result = g_hash_table_lookup (hash, font_name); + if (result) + gdk_font_ref (result); + + return result; + } +} + GdkFont* gdk_font_load (const gchar *font_name) { @@ -38,6 +95,10 @@ gdk_font_load (const gchar *font_name) g_return_val_if_fail (font_name != NULL, NULL); + font = gdk_font_hash_lookup (GDK_FONT_FONT, font_name); + if (font) + return font; + xfont = XLoadQueryFont (gdk_display, font_name); if (xfont == NULL) return NULL; @@ -57,7 +118,8 @@ gdk_font_load (const gchar *font_name) private->xdisplay = gdk_display; private->xfont = xfont; private->ref_count = 1; - + private->names = NULL; + font = (GdkFont*) private; font->type = GDK_FONT_FONT; font->ascent = xfont->ascent; @@ -66,6 +128,8 @@ gdk_font_load (const gchar *font_name) gdk_xid_table_insert (&xfont->fid, font); } + gdk_font_hash_insert (GDK_FONT_FONT, font, font_name); + return font; } @@ -79,6 +143,10 @@ gdk_fontset_load (gchar *fontset_name) gchar **missing_charset_list; gchar *def_string; + font = gdk_font_hash_lookup (GDK_FONT_FONTSET, fontset_name); + if (font) + return font; + private = g_new (GdkFontPrivate, 1); font = (GdkFont*) private; @@ -121,8 +189,12 @@ gdk_fontset_load (gchar *fontset_name) font->ascent = MAX (font->ascent, font_structs[i]->ascent); font->descent = MAX (font->descent, font_structs[i]->descent); } + + private->names = NULL; + gdk_font_hash_insert (GDK_FONT_FONTSET, font, fontset_name); + + return font; } - return font; } GdkFont* @@ -141,14 +213,16 @@ void gdk_font_unref (GdkFont *font) { GdkFontPrivate *private; + private = (GdkFontPrivate*) font; g_return_if_fail (font != NULL); - - private = (GdkFontPrivate*) font; + g_return_if_fail (private->ref_count > 0); private->ref_count -= 1; if (private->ref_count == 0) { + gdk_font_hash_remove (font->type, font); + switch (font->type) { case GDK_FONT_FONT: @@ -205,8 +279,12 @@ gdk_font_equal (const GdkFont *fonta, } else if (fonta->type == GDK_FONT_FONTSET && fontb->type == GDK_FONT_FONTSET) { - /* how to compare two fontsets ?? by basename or XFontSet ?? */ - return (((XFontSet) privatea->xfont) == ((XFontSet) privateb->xfont)); + gchar *namea, *nameb; + + namea = XBaseFontNameListOfFontSet((XFontSet) privatea->xfont); + nameb = XBaseFontNameListOfFontSet((XFontSet) privateb->xfont); + + return (strcmp(namea, nameb) == 0); } else /* fontset != font */ @@ -578,7 +656,20 @@ gdk_text_extents_wc (GdkFont *font, } case GDK_FONT_FONTSET: fontset = (XFontSet) private->xfont; - XwcTextExtents (fontset, text, text_length, &ink, &logical); + + if (sizeof(GdkWChar) == sizeof(wchar_t)) + XwcTextExtents (fontset, (wchar_t *)text, text_length, &ink, &logical); + else + { + wchar_t *text_wchar; + gint i; + + text_wchar = g_new (wchar_t, text_length); + for (i = 0; i < text_length; i++) + text_wchar[i] = text[i]; + XwcTextExtents (fontset, text_wchar, text_length, &ink, &logical); + g_free (text_wchar); + } if (lbearing) *lbearing = ink.x; if (rbearing) @@ -652,7 +743,7 @@ gdk_text_measure (GdkFont *font, case GDK_FONT_FONTSET: fontset = (XFontSet) private->xfont; XmbTextExtents (fontset, text, text_length, &ink, &log); - width = log.width; + width = ink.x + ink.width; break; default: width = 0; |