summaryrefslogtreecommitdiff
path: root/src/FbTk/Font.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/FbTk/Font.cc')
-rw-r--r--src/FbTk/Font.cc139
1 files changed, 123 insertions, 16 deletions
diff --git a/src/FbTk/Font.cc b/src/FbTk/Font.cc
index 453a195..75d89f1 100644
--- a/src/FbTk/Font.cc
+++ b/src/FbTk/Font.cc
@@ -1,5 +1,5 @@
1// Font.cc 1// Font.cc
2// Copyright (c) 2002 Henrik Kinnunen (fluxgen@linuxmail.org) 2// Copyright (c) 2002-2004 Henrik Kinnunen (fluxgen@linuxmail.org)
3// 3//
4// Permission is hereby granted, free of charge, to any person obtaining a 4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"), 5// copy of this software and associated documentation files (the "Software"),
@@ -19,7 +19,7 @@
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE. 20// DEALINGS IN THE SOFTWARE.
21 21
22//$Id: Font.cc,v 1.7 2004/06/07 11:46:05 rathnor Exp $ 22//$Id: Font.cc,v 1.8 2004/08/10 11:21:50 fluxgen Exp $
23 23
24 24
25#include "Font.hh" 25#include "Font.hh"
@@ -44,7 +44,6 @@
44#include "XFontImp.hh" 44#include "XFontImp.hh"
45 45
46#include "GContext.hh" 46#include "GContext.hh"
47
48//use gnu extensions 47//use gnu extensions
49#ifndef _GNU_SOURCE 48#ifndef _GNU_SOURCE
50#define _GNU_SOURCE 49#define _GNU_SOURCE
@@ -58,12 +57,59 @@
58#include <cstring> 57#include <cstring>
59#include <cstdlib> 58#include <cstdlib>
60#include <typeinfo> 59#include <typeinfo>
60
61#include <cstdlib>
62
61using namespace std; 63using namespace std;
62 64
63#ifdef HAVE_SETLOCALE 65#ifdef HAVE_SETLOCALE
64#include <locale.h> 66#include <locale.h>
65#endif //HAVE_SETLOCALE 67#endif //HAVE_SETLOCALE
66 68
69/**
70 Recodes the text from one encoding to another
71 assuming cd is correct
72 @param cd the iconv type
73 @param msg text to be converted
74 @param len number of chars to convert
75 @return the recoded string, or 0 on failure
76*/
77static char* recode(iconv_t cd,
78 const char *msg, size_t size) {
79
80 // If empty message, yes this can happen, return
81 if(strlen(msg) == 0)
82 return 0;
83
84
85 size_t inbytesleft = strlen(msg);
86 size_t outbytesleft = 4*inbytesleft;
87 char *new_msg = new char[outbytesleft];
88 char *new_msg_ptr = new_msg;
89 char *msg_ptr = strdup(msg);
90
91 if (iconv(cd, &msg_ptr, &inbytesleft, &new_msg, &outbytesleft) == -1) {
92 // iconv can fail for three reasons
93 // 1) Invalid multibyte sequence is encountered in the input
94 // 2) An incomplete multibyte sequence
95 // 3) The output buffer has no more room for the next converted character.
96 // So we the delete new message and return original message
97 delete new_msg;
98 free(msg_ptr);
99 return 0;
100 }
101 free(msg_ptr);
102
103 *new_msg_ptr = '\0';
104
105 if(inbytesleft != 0) {
106 delete new_msg;
107 return 0;
108 }
109
110 return new_msg;
111}
112
67namespace FbTk { 113namespace FbTk {
68 114
69bool Font::m_multibyte = false; 115bool Font::m_multibyte = false;
@@ -71,21 +117,53 @@ bool Font::m_utf8mode = false;
71 117
72Font::Font(const char *name, bool antialias): 118Font::Font(const char *name, bool antialias):
73 m_fontimp(0), 119 m_fontimp(0),
74 m_antialias(false), m_rotated(false), m_shadow(false) { 120 m_antialias(false), m_rotated(false), m_shadow(false),
75 121 m_iconv((iconv_t)-1) {
122
76 // MB_CUR_MAX returns the size of a char in the current locale 123 // MB_CUR_MAX returns the size of a char in the current locale
77 if (MB_CUR_MAX > 1) // more than one byte, then we're multibyte 124 if (MB_CUR_MAX > 1) // more than one byte, then we're multibyte
78 m_multibyte = true; 125 m_multibyte = true;
79 126
80 char *s; // temporary string for enviroment variable 127 char *envstr; // temporary string for enviroment variable
81 // check for utf-8 mode 128 // check for utf-8 mode
82 if (((s = getenv("LC_ALL")) && *s) || 129 if (((envstr = getenv("LC_ALL")) && *envstr) ||
83 ((s = getenv("LC_CTYPE")) && *s) || 130 ((envstr = getenv("LC_CTYPE")) && *envstr) ||
84 ((s = getenv("LANG")) && *s)) { 131 ((envstr = getenv("LANG")) && *envstr)) {
85 if (strstr(s, "UTF-8")) 132 if (strstr(envstr, "UTF-8"))
86 m_utf8mode = true; 133 m_utf8mode = true;
134 m_locale = envstr;
135 int index = m_locale.find(".");
136 if (index != 0)
137 m_locale = m_locale.substr(index + 1);
138 else
139 m_locale = "UTF-8";
140 }
141 // if locale isn't UTF-8 we try to
142 // create a iconv pointer so we can
143 // convert non utf-8 strings to utf-8
144 if (m_locale != "UTF-8") {
145#ifdef DEBUG
146 cerr<<"FbTk::Font: m_locale = "<<m_locale<<endl;
147#endif // DEBUG
148 m_iconv = iconv_open(m_locale.c_str(), "UTF-8");
149 if(m_iconv == (iconv_t)(-1)) {
150 cerr<<"FbTk::Font: code error: from "<<m_locale<<" to: UTF-8"<<endl;
151 // if we failed with iconv then we can't convert
152 // the strings to utf-8, so we disable utf8 mode
153 m_utf8mode = false;
154 } else {
155 // success, we can now enable utf8mode
156 // and if antialias is on later we can recode
157 // the non utf-8 string to utf-8 and use utf-8
158 // drawing functions
159 m_utf8mode = true;
160 }
87 } 161 }
88 162
163#ifdef DEBUG
164 cerr<<"FbTk::Font m_iconv = "<<(int)m_iconv<<endl;
165#endif // DEBUG
166
89 // create the right font implementation 167 // create the right font implementation
90 // antialias is prio 1 168 // antialias is prio 1
91#ifdef USE_XFT 169#ifdef USE_XFT
@@ -103,7 +181,7 @@ Font::Font(const char *name, bool antialias):
103#endif // USE_XMB 181#endif // USE_XMB
104 m_fontimp.reset(new XFontImp()); 182 m_fontimp.reset(new XFontImp());
105 } 183 }
106 184
107 if (name != 0) { 185 if (name != 0) {
108 load(name); 186 load(name);
109 } 187 }
@@ -111,7 +189,8 @@ Font::Font(const char *name, bool antialias):
111} 189}
112 190
113Font::~Font() { 191Font::~Font() {
114 192 if (m_iconv != (iconv_t)(-1))
193 iconv_close(m_iconv);
115} 194}
116 195
117void Font::setAntialias(bool flag) { 196void Font::setAntialias(bool flag) {
@@ -186,6 +265,16 @@ bool Font::load(const std::string &name) {
186} 265}
187 266
188unsigned int Font::textWidth(const char * const text, unsigned int size) const { 267unsigned int Font::textWidth(const char * const text, unsigned int size) const {
268 if (isAntialias() && m_iconv != (iconv_t)(-1)) {
269 char* rtext = recode(m_iconv, text, size);
270 if (rtext != 0)
271 size = strlen(rtext);
272 unsigned int r = m_fontimp->textWidth(rtext ? rtext : text, size);
273 if (rtext != 0)
274 delete rtext;
275 return r;
276 }
277
189 return m_fontimp->textWidth(text, size); 278 return m_fontimp->textWidth(text, size);
190} 279}
191 280
@@ -200,21 +289,35 @@ int Font::ascent() const {
200int Font::descent() const { 289int Font::descent() const {
201 return m_fontimp->descent(); 290 return m_fontimp->descent();
202} 291}
292
203void Font::drawText(Drawable w, int screen, GC gc, 293void Font::drawText(Drawable w, int screen, GC gc,
204 const char *text, size_t len, int x, int y, 294 const char *text, size_t len, int x, int y,
205 bool rotate) const { 295 bool rotate) const {
206 if (text == 0 || len == 0) 296 if (text == 0 || len == 0)
207 return; 297 return;
208 298
299 char* rtext = 0;
300
209 // so we don't end up in a loop with m_shadow 301 // so we don't end up in a loop with m_shadow
210 static bool first_run = true; 302 static bool first_run = true;
211 303
304 if (isAntialias() && m_iconv != (iconv_t)(-1) && first_run) {
305 rtext = recode(m_iconv, text, len);
306 if (rtext != 0) {
307 len = strlen(rtext);
308 // ok, we can't use utf8 mode since the string is invalid
309 }
310 }
311
312
313 const char *real_text = rtext ? rtext : text;
314
212 // draw shadow first 315 // draw shadow first
213 if (first_run && m_shadow) { 316 if (first_run && m_shadow) {
214 FbTk::GContext shadow_gc(w); 317 FbTk::GContext shadow_gc(w);
215 shadow_gc.setForeground(FbTk::Color("black", screen)); 318 shadow_gc.setForeground(FbTk::Color("black", screen));
216 first_run = false; // so we don't end up in a loop 319 first_run = false; // so we don't end up in a loop
217 drawText(w, screen, shadow_gc.gc(), text, len, x + 1, y + 1); 320 drawText(w, screen, shadow_gc.gc(), real_text, len, x + 1, y + 1);
218 first_run = true; 321 first_run = true;
219 } 322 }
220 323
@@ -228,16 +331,18 @@ void Font::drawText(Drawable w, int screen, GC gc,
228 XFontImp *font = dynamic_cast<XFontImp *>(m_fontimp.get()); 331 XFontImp *font = dynamic_cast<XFontImp *>(m_fontimp.get());
229 font->setRotate(false); // disable rotation temporarly 332 font->setRotate(false); // disable rotation temporarly
230 333
231 font->drawText(w, screen, gc, text, len, x, y); 334 font->drawText(w, screen, gc, real_text, len, x, y);
232 font->setRotate(true); // enable rotation 335 font->setRotate(true); // enable rotation
233 } catch (std::bad_cast &bc) { 336 } catch (std::bad_cast &bc) {
234 // draw normal... 337 // draw normal...
235 m_fontimp->drawText(w, screen, gc, text, len, x, y); 338 m_fontimp->drawText(w, screen, gc, real_text, len, x, y);
236 } 339 }
237 340
238 } else 341 } else
239 m_fontimp->drawText(w, screen, gc, text, len, x, y); 342 m_fontimp->drawText(w, screen, gc, real_text, len, x, y);
240 343
344 if (rtext != 0)
345 delete rtext;
241 346
242} 347}
243 348
@@ -263,4 +368,6 @@ void Font::rotate(float angle) {
263 m_angle = angle; 368 m_angle = angle;
264} 369}
265 370
371
266}; 372};
373