diff options
-rw-r--r-- | gtk/PlatGTK.cxx | 129 |
1 files changed, 114 insertions, 15 deletions
diff --git a/gtk/PlatGTK.cxx b/gtk/PlatGTK.cxx index df6c65069..e8168557b 100644 --- a/gtk/PlatGTK.cxx +++ b/gtk/PlatGTK.cxx @@ -37,6 +37,8 @@ #if GTK_MAJOR_VERSION >= 2 #define USE_PANGO 1 +#include <iconv.h> +const iconv_t iconvhBad = (iconv_t)(-1); #endif #ifdef _MSC_VER @@ -106,6 +108,7 @@ public: GdkFont *pfont; #ifdef USE_PANGO PangoFontDescription *pfd; + int characterSet; #endif FontHandle(GdkFont *pfont_) { et = singleByte; @@ -113,15 +116,17 @@ public: pfont = pfont_; #ifdef USE_PANGO pfd = 0; + characterSet = -1; #endif ResetWidths(et); } #ifdef USE_PANGO - FontHandle(PangoFontDescription *pfd_) { + FontHandle(PangoFontDescription *pfd_, int characterSet_) { et = singleByte; ascent = 0; pfont = 0; pfd = pfd_; + characterSet = characterSet_; ResetWidths(et); } #endif @@ -496,7 +501,7 @@ FontID FontCached::CreateNewFont(const char *fontName, int characterSet, pango_font_description_set_size(pfd, size * PANGO_SCALE); pango_font_description_set_weight(pfd, bold ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL); pango_font_description_set_style(pfd, italic ? PANGO_STYLE_ITALIC : PANGO_STYLE_NORMAL); - return new FontHandle(pfd); + return new FontHandle(pfd, characterSet); } } #endif @@ -664,6 +669,9 @@ class SurfaceImpl : public Surface { #ifdef USE_PANGO PangoContext *pcontext; PangoLayout *layout; + iconv_t iconvh; + int characterSet; + void SetIconv(int characterSet_); #endif public: SurfaceImpl(); @@ -710,10 +718,71 @@ public: void SetDBCSMode(int codePage); }; +#ifdef USE_PANGO + +static const char *CharacterSetID(int characterSet) { + switch (characterSet) { + case SC_CHARSET_ANSI: + return "ASCII"; + case SC_CHARSET_DEFAULT: + return "LATIN1"; + case SC_CHARSET_BALTIC: + return "BALTIC"; + case SC_CHARSET_CHINESEBIG5: + return "BIG-5"; + case SC_CHARSET_EASTEUROPE: + return "ISO8859-2"; + case SC_CHARSET_GB2312: + return "GB2312"; + case SC_CHARSET_GREEK: + return "ISO8859-7"; + case SC_CHARSET_HANGUL: + return ""; + case SC_CHARSET_MAC: + return "MACINTOSH"; + case SC_CHARSET_OEM: + return "ASCII"; + case SC_CHARSET_RUSSIAN: + return "KOI8-R"; + case SC_CHARSET_SHIFTJIS: + return "SHIFT-JIS"; + case SC_CHARSET_SYMBOL: + return ""; + case SC_CHARSET_TURKISH: + return "ISO8859-9"; + case SC_CHARSET_JOHAB: + return "JOHAB"; + case SC_CHARSET_HEBREW: + return "ISO8859-8"; + case SC_CHARSET_ARABIC: + return "ISO8859-6"; + case SC_CHARSET_VIETNAMESE: + return ""; + case SC_CHARSET_THAI: + return "ISO8859-1"; + default: + return ""; + } +} + +void SurfaceImpl::SetIconv(int characterSet_) { + if (characterSet != characterSet_) { + if (iconvh != iconvhBad) + iconv_close(iconvh); + iconvh = iconvhBad; + characterSet = characterSet_; + const char *source = CharacterSetID(characterSet); + if (*source) { + iconvh = iconv_open("UTF8", source); + } + } +} +#endif + SurfaceImpl::SurfaceImpl() : et(singleByte), drawable(0), gc(0), ppixmap(0), x(0), y(0), inited(false), createdGC(false) #ifdef USE_PANGO -, pcontext(0), layout(0) +, pcontext(0), layout(0), iconvh(iconvhBad), characterSet(-1) #endif { } @@ -723,6 +792,7 @@ SurfaceImpl::~SurfaceImpl() { } void SurfaceImpl::Release() { + et = singleByte; drawable = 0; if (createdGC) { createdGC = false; @@ -739,6 +809,10 @@ void SurfaceImpl::Release() { if (pcontext) g_object_unref(pcontext); pcontext = 0; + if (iconvh != iconvhBad) + iconv_close(iconvh); + iconvh = iconvhBad; + characterSet = -1; #endif x = 0; y = 0; @@ -957,6 +1031,22 @@ static size_t UTF8Len(char ch) { } #ifdef USE_PANGO +static char *UTF8FromIconv(iconv_t iconvh, const char *s, int len) { + if (iconvh != ((iconv_t)(-1))) { + char *utfForm = new char[len*3+1]; + char *pin = const_cast<char *>(s); + size_t inLeft = len; + char *pout = utfForm; + size_t outLeft = len*3+1; + size_t conversions = iconv(iconvh, &pin, &inLeft, &pout, &outLeft); + if (conversions != ((size_t)(-1))) { + *pout = '\0'; + return utfForm; + } + delete []utfForm; + } + return 0; +} static char *UTF8FromLatin1(const char *s, int len) { char *utfForm = new char[len*2+1]; @@ -1032,14 +1122,17 @@ void SurfaceImpl::DrawTextBase(PRectangle rc, Font &font_, int ybase, const char // Convert to utf8 utfForm = UTF8FromDBCS(s, len); } + if (!utfForm) { // DBCS failed so treat as iconv + SetIconv(PFont(font_)->characterSet); + utfForm = UTF8FromIconv(iconvh, s, len); + } if (!utfForm) { // DBCS failed so treat as locale gsize w; // stub utfForm = g_locale_to_utf8(s, len, NULL, &w, NULL); - useGFree = true; + useGFree = static_cast<bool>(utfForm); }; if (!utfForm) { // g_locale_to_utf8 failed so treat as Latin1 utfForm = UTF8FromLatin1(s, len); - useGFree = false; } pango_layout_set_text(layout, utfForm, strlen(utfForm)); } @@ -1172,14 +1265,17 @@ void SurfaceImpl::MeasureWidths(Font &font_, const char *s, int len, int *positi delete []wctext; } if (wclen < 1 ) { - // Either DBCS conversion failed or is 8 bit string so - // try as current locale and if that fails treat as Latin1. - gsize w; // stub - char *utfForm = g_locale_to_utf8(s, len, NULL, &w, NULL); - bool useGFree = true; + // Either Latin1 or DBCS conversion failed so treat as Latin1. + bool useGFree = false; + SetIconv(PFont(font_)->characterSet); + char *utfForm = UTF8FromIconv(iconvh, s, len); + if (!utfForm) { // iconv failed so treat as locale + gsize w; // stub + utfForm = g_locale_to_utf8(s, len, NULL, &w, NULL); + useGFree = static_cast<bool>(utfForm); + } if (!utfForm) { utfForm = UTF8FromLatin1(s, len); - useGFree = false; } pango_layout_set_text(layout, utfForm, strlen(utfForm)); int i = 0; @@ -1268,17 +1364,20 @@ int SurfaceImpl::WidthText(Font &font_, const char *s, int len) { // Convert to utf8 utfForm = UTF8FromDBCS(s, len); } - if (!utfForm) { // DBCS failed so treat as locale + if (!utfForm) { // DBCS failed so treat as iconv + SetIconv(PFont(font_)->characterSet); + utfForm = UTF8FromIconv(iconvh, s, len); + } + if (!utfForm) { // iconv failed so treat as locale gsize w; utfForm = g_locale_to_utf8(s, len, NULL, &w, NULL); - useGFree = true; + useGFree = static_cast<bool>(utfForm); }; if (!utfForm) { // g_locale_to_utf8 failed so treat as Latin1 utfForm = UTF8FromLatin1(s, len); - useGFree = false; } pango_layout_set_text(layout, utfForm, strlen(utfForm)); - // TODO: len = strlen(utfForm) + len = strlen(utfForm) } pango_layout_index_to_pos(layout, len, &pos); int width = PANGO_PIXELS(pos.x); |