aboutsummaryrefslogtreecommitdiffstats
path: root/e-util
diff options
context:
space:
mode:
authorLauris Kaplinski <lauris@src.gnome.org>2000-09-09 06:32:24 +0800
committerLauris Kaplinski <lauris@src.gnome.org>2000-09-09 06:32:24 +0800
commit1768e0e4fde11a6dfdf2336536edce3c954f4474 (patch)
tree8d778c052a38846c98e1def4e10438a459c2debf /e-util
parent16e05ea9a531460f45404773e0cb1f0a8aafb10f (diff)
downloadgsoc2013-evolution-1768e0e4fde11a6dfdf2336536edce3c954f4474.tar.gz
gsoc2013-evolution-1768e0e4fde11a6dfdf2336536edce3c954f4474.tar.zst
gsoc2013-evolution-1768e0e4fde11a6dfdf2336536edce3c954f4474.zip
Some UTF-8 fixes and experimental 16-bit unicode font support
svn path=/trunk/; revision=5279
Diffstat (limited to 'e-util')
-rw-r--r--e-util/ChangeLog4
-rw-r--r--e-util/e-font.c210
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);