diff options
Diffstat (limited to 'e-util')
-rw-r--r-- | e-util/ChangeLog | 4 | ||||
-rw-r--r-- | e-util/e-font.c | 210 |
2 files changed, 155 insertions, 59 deletions
diff --git a/e-util/ChangeLog b/e-util/ChangeLog index 2c1e3a902a..19aca4a76f 100644 --- a/e-util/ChangeLog +++ b/e-util/ChangeLog @@ -1,3 +1,7 @@ +2000-09-08 Lauris Kaplinski <lauris@helixcode.com> + + * e-font.c: Use experimental 16-bit font stuff for EFonts + 2000-09-08 Dan Winship <danw@helixcode.com> * e-popup-menu.h: remove consts from the EPopupMenu structure: the diff --git a/e-util/e-font.c b/e-util/e-font.c index cfee9f0923..15fa868254 100644 --- a/e-util/e-font.c +++ b/e-util/e-font.c @@ -16,58 +16,169 @@ #include <unicode.h> #include "e-font.h" +#define FONT_TESTING + struct _EFont { - GdkFont font; + gint refcount; + GdkFont *font; + gboolean bytes; + unicode_iconv_t to; + unicode_iconv_t from; }; EFont * e_font_from_gdk_name (const gchar *name) { - GdkFont *font; + EFont * font; + GdkFont *gdkfont; - font = gdk_fontset_load (name); + gdkfont = gdk_fontset_load (name); + font = e_font_from_gdk_font (gdkfont); + gdk_font_unref (gdkfont); - return (EFont *) font; + return font; } EFont * -e_font_from_gdk_font (GdkFont *font) +e_font_from_gdk_font (GdkFont *gdkfont) { - gdk_font_ref (font); + EFont *font; + XFontStruct *xfs; + Atom font_atom, atom; + Bool status; + + gdk_font_ref (gdkfont); + + /* Try to find iso-10646-1 encoded font with same name */ + + font_atom = gdk_atom_intern ("FONT", FALSE); + if (gdkfont->type == GDK_FONT_FONTSET) { + XFontStruct **font_structs; + gint num_fonts; + gchar **font_names; + num_fonts = XFontsOfFontSet (GDK_FONT_XFONT (gdkfont), + &font_structs, + &font_names); + status = XGetFontProperty (font_structs[0], + font_atom, + &atom); + } else { + status = XGetFontProperty (GDK_FONT_XFONT (gdkfont), + font_atom, + &atom); + } + if (status) { + gchar *name, *p; + gchar *newname; + GdkFont *newfont; + gint i; + + name = gdk_atom_name (atom); + newname = alloca (strlen (name) + 12); + strcpy (newname, name); + p = newname; + for (i = 0; i < 13; i++) { + /* Skip hyphen */ + while (*p && (*p != '-')) p++; + if (*p) p++; + } + g_snprintf (p, 12, "ISO10646-1"); + newfont = gdk_font_load (newname); + if (newfont) { + gdk_font_unref (gdkfont); + gdkfont = newfont; + } + g_free (name); + } + + font = g_new (EFont, 1); + + xfs = GDK_FONT_XFONT (gdkfont); + + font->refcount = 1; + font->font = gdkfont; + font->bytes = ((xfs->min_byte1 != 0) || (xfs->max_byte1 != 0)) ? 2 : 1; + font->to = e_uiconv_to_gdk_font (font->font); + font->from = e_uiconv_from_gdk_font (font->font); + + return font; - return (EFont *) font; } void e_font_ref (EFont *font) { - gdk_font_ref (&font->font); + font->refcount++; } void e_font_unref (EFont *font) { - gdk_font_unref (&font->font); + font->refcount--; + + if (font->refcount < 1) { + gdk_font_unref (font->font); + g_free (font); + } } gint e_font_ascent (EFont * font) { - return font->font.ascent; + return font->font->ascent; } gint e_font_descent (EFont * font) { - return font->font.descent; + return font->font->descent; +} + +static gint +e_font_to_native (EFont *font, gchar *native, gchar *utf, gint bytes) +{ + char *ib, *ob; + size_t ibl, obl; + + ib = utf; + ibl = bytes; + ob = native; + obl = bytes * 4; + + while (ibl > 0) { + unicode_iconv (font->to, (const char **) &ib, &ibl, &ob, &obl); + if (ibl > 0) { + gint len; + if ((*ib & 0x80) == 0x00) len = 1; + else if ((*ib &0xe0) == 0xc0) len = 2; + else if ((*ib &0xf0) == 0xe0) len = 3; + else if ((*ib &0xf80) == 0xf0) len = 4; + else { + g_warning ("Invalid UTF-8 sequence"); + return ob - native; + } + ib += len; + ibl = bytes - (ib - utf); + if (ibl > bytes) ibl = 0; + if (font->bytes == 1) { + *ob++ = '_'; + obl--; + } else { + *((guint16 *) ob) = '_'; + ob += 2; + obl -= 2; + } + } + } + + return ob - native; } void e_font_draw_utf8_text (GdkDrawable *drawable, EFont *font, EFontStyle style, GdkGC *gc, gint x, gint y, gchar *text, gint numbytes) { - guchar *iso; - gchar *p; - gint uni, len; + gchar *native; + gint native_bytes; g_return_if_fail (drawable != NULL); g_return_if_fail (font != NULL); @@ -76,57 +187,55 @@ e_font_draw_utf8_text (GdkDrawable *drawable, EFont *font, EFontStyle style, Gdk if (numbytes < 1) return; - iso = alloca (numbytes); + native = alloca (numbytes * 4); - for (len = 0, p = text; p != NULL && p < (text + numbytes); len++, p = unicode_next_utf8 (p)) { - unicode_get_utf8 (p, &uni); - if ((uni < ' ') || (uni > 255)) uni = ' '; - iso[len] = uni; - } + native_bytes = e_font_to_native (font, native, text, numbytes); - gdk_draw_text (drawable, &font->font, gc, x, y, iso, len); + gdk_draw_text (drawable, font->font, gc, x, y, native, native_bytes); if (style & E_FONT_BOLD) - gdk_draw_text (drawable, &font->font, gc, x + 1, y, iso, len); + gdk_draw_text (drawable, font->font, gc, x + 1, y, native, native_bytes); } gint e_font_utf8_text_width (EFont *font, EFontStyle style, char *text, int numbytes) { - guchar *iso; - gchar *p; - gint uni, len; + gchar *native; + gint native_bytes; + gint width; g_return_val_if_fail (font != NULL, 0); g_return_val_if_fail (text != NULL, 0); - iso = alloca (numbytes); + if (numbytes < 1) return 0; - for (len = 0, p = text; p != NULL && p < (text + numbytes); len++, p = unicode_next_utf8 (p)) { - unicode_get_utf8 (p, &uni); - if ((uni < ' ') || (uni > 255)) uni = ' '; - iso[len] = uni; - } + native = alloca (numbytes * 4); - return gdk_text_width (&font->font, iso, len); + native_bytes = e_font_to_native (font, native, text, numbytes); + + width = gdk_text_width (font->font, native, native_bytes); + + return width; } gint e_font_utf8_char_width (EFont *font, EFontStyle style, char *text) { - unicode_char_t uni; - guchar iso; + gint len; g_return_val_if_fail (font != NULL, 0); g_return_val_if_fail (text != NULL, 0); - if (!unicode_get_utf8 (text, &uni)) return 0; - - if ((uni < ' ') || (uni > 255)) uni = ' '; - - iso = uni; + if ((*text & 0x80) == 0x00) len = 1; + else if ((*text &0xe0) == 0xc0) len = 2; + else if ((*text &0xf0) == 0xe0) len = 3; + else if ((*text &0xf80) == 0xf0) len = 4; + else { + g_warning ("Invalid UTF-8 sequence"); + return 0; + } - return gdk_text_width (&font->font, &iso, 1); + return e_font_utf8_text_width (font, style, text, len); } static const gchar * @@ -151,7 +260,8 @@ translate_encoding (const gchar *encoding) g_hash_table_insert (eh, "iso8859-13", "iso-8859-13"); g_hash_table_insert (eh, "iso8859-14", "iso-8859-14"); g_hash_table_insert (eh, "iso8859-15", "iso-8859-15"); - g_hash_table_insert (eh, "iso10646-1", "UCS2"); + g_hash_table_insert (eh, "iso10646-1", "UTF-16"); + g_hash_table_insert (eh, "koi8-r", "koi8-r"); } strncpy (e, encoding, 64); @@ -200,27 +310,9 @@ e_gdk_font_encoding (GdkFont *font) if (*p) p++; } -#if 0 - p = strchr (name, '-'); /* Foundry */ - p = strchr (p + 1, '-'); /* Family */ - p = strchr (p + 1, '-'); /* Weight */ - p = strchr (p + 1, '-'); /* Slant */ - p = strchr (p + 1, '-'); /* Set Width */ - p = strchr (p + 1, '-'); /* Add Style */ - p = strchr (p + 1, '-'); /* Pixel Size */ - p = strchr (p + 1, '-'); /* Point Size */ - p = strchr (p + 1, '-'); /* Resolution X */ - p = strchr (p + 1, '-'); /* Resolution Y */ - p = strchr (p + 1, '-'); /* Spacing */ - p = strchr (p + 1, '-'); /* Average Width */ - p = strchr (p + 1, '-'); /* Charset */ - - encoding = translate_encoding (p + 1); -#else if (!*p) return NULL; encoding = translate_encoding (p); -#endif g_free (name); |