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.cc261
1 files changed, 95 insertions, 166 deletions
diff --git a/src/FbTk/Font.cc b/src/FbTk/Font.cc
index 05dae54..365637d 100644
--- a/src/FbTk/Font.cc
+++ b/src/FbTk/Font.cc
@@ -27,6 +27,7 @@
27#include "Font.hh" 27#include "Font.hh"
28#include "FontImp.hh" 28#include "FontImp.hh"
29#include "I18n.hh" 29#include "I18n.hh"
30#include "App.hh"
30 31
31#ifdef HAVE_CONFIG_H 32#ifdef HAVE_CONFIG_H
32#include "config.h" 33#include "config.h"
@@ -67,6 +68,7 @@
67 #include <stdlib.h> 68 #include <stdlib.h>
68#endif 69#endif
69#include <list> 70#include <list>
71#include <map>
70#include <typeinfo> 72#include <typeinfo>
71#include <langinfo.h> 73#include <langinfo.h>
72 74
@@ -148,69 +150,15 @@ char *recode(int cd,
148} 150}
149#endif // HAVE_ICONV 151#endif // HAVE_ICONV
150 152
151int extract_halo_options(const std::string& opts, std::string& color) { 153// use to map <font1>|<font2>|<font3> => <fontthatworks>
152 std::list< std::string > tokens; 154typedef std::map<std::string, std::string> StringMap;
153 size_t sep= opts.find_first_of(':'); 155typedef StringMap::iterator StringMapIt;
156StringMap lookup_map;
154 157
155 if ( sep == std::string::npos ) 158// stores <fontthatworks and the fontimp
156 return 1; 159typedef std::map<std::string, FbTk::FontImp* > FontCache;
157 160typedef FontCache::iterator FontCacheIt;
158 FbTk::StringUtil::stringtok(tokens, opts.substr(sep + 1, opts.length()), ";"); 161FontCache font_cache;
159 tokens.unique();
160 std::list< std::string >::const_iterator token;
161
162 for ( token= tokens.begin(); token != tokens.end(); token++ ) {
163 if ( (*token).find("color=", 0) != std::string::npos ) {
164 size_t s= (*token).find_first_of('=');
165 std::string c= (*token).substr(s + 1, (*token).length());
166 if ( !c.empty() )
167 std::swap(color, c);
168 }
169 }
170
171 return 1;
172}
173
174int extract_shadow_options(const std::string& opts,
175 std::string& color,
176 int& offx, int& offy) {
177
178 std::list< std::string > tokens;
179 size_t sep= opts.find_first_of(':');
180
181 if ( sep == std::string::npos )
182 return 1;
183
184 FbTk::StringUtil::stringtok(tokens, opts.substr(sep + 1, opts.length()), ";");
185 tokens.unique();
186 std::list< std::string >::const_iterator token;
187
188 for ( token= tokens.begin(); token != tokens.end(); token++ ) {
189 if ( (*token).find("color=", 0) != std::string::npos ) {
190 size_t s= (*token).find_first_of('=');
191 std::string c= (*token).substr(s + 1, (*token).length());
192 if ( !c.empty() )
193 std::swap(color, c);
194 }
195 else if ( (*token).find("offsetx=", 0) != std::string::npos ) {
196 size_t s= (*token).find_first_of('=');
197 FbTk_istringstream o((*token).substr(s + 1, (*token).length()).c_str());
198 if ( !o.eof() ) {
199 o >> offx;
200 }
201 }
202 else if ( (*token).find("offsety=", 0) != std::string::npos ) {
203 size_t s= (*token).find_first_of('=');
204 FbTk_istringstream o((*token).substr(s + 1, (*token).length()).c_str());
205 if ( !o.eof() ) {
206 o >> offy;
207 }
208 }
209 }
210
211 return 1;
212
213};
214 162
215}; // end nameless namespace 163}; // end nameless namespace
216 164
@@ -218,8 +166,8 @@ int extract_shadow_options(const std::string& opts,
218 166
219namespace FbTk { 167namespace FbTk {
220 168
221bool Font::m_multibyte = false; 169bool Font::s_multibyte = false;
222bool Font::m_utf8mode = false; 170bool Font::s_utf8mode = false;
223 171
224 172
225void Font::init() { 173void Font::init() {
@@ -229,24 +177,34 @@ void Font::init() {
229 177
230void Font::shutdown() { 178void Font::shutdown() {
231 179
180 FontCacheIt fit;
181 for (fit = font_cache.begin(); fit != font_cache.end(); fit++) {
182 FontImp* font = fit->second;
183 if (font) {
184 FontCacheIt it;
185 for (it = fit; it != font_cache.end(); it++)
186 if (it->second == font)
187 it->second = 0;
188 delete font;
189 }
190 }
232} 191}
233 192
234Font::Font(const char *name, bool antialias): 193Font::Font(const char *name):
235 m_fontimp(0), 194 m_fontimp(0),
236 m_antialias(false), m_rotated(false), 195 m_rotated(false),
237 m_shadow(false), m_shadow_color("#000000"), 196 m_shadow(false), m_shadow_color("black", DefaultScreen(App::instance()->display())),
238 m_shadow_offx(1), m_shadow_offy(1), 197 m_shadow_offx(2), m_shadow_offy(2),
239 m_halo(false), m_halo_color("#ffffff"), 198 m_halo(false), m_halo_color("white", DefaultScreen(App::instance()->display())),
240#ifdef HAVE_ICONV 199#ifdef HAVE_ICONV
241 m_iconv((iconv_t)(-1)) 200 m_iconv((iconv_t)(-1))
242#else 201#else
243 m_iconv(-1) 202 m_iconv(-1)
244#endif // HAVE_ICONV 203#endif // HAVE_ICONV
245{ 204{
246
247 // MB_CUR_MAX returns the size of a char in the current locale 205 // MB_CUR_MAX returns the size of a char in the current locale
248 if (MB_CUR_MAX > 1) // more than one byte, then we're multibyte 206 if (MB_CUR_MAX > 1) // more than one byte, then we're multibyte
249 m_multibyte = true; 207 s_multibyte = true;
250 208
251 // check for utf-8 mode 209 // check for utf-8 mode
252#ifdef CODESET 210#ifdef CODESET
@@ -256,7 +214,7 @@ Font::Font(const char *name, bool antialias):
256#endif // CODESET 214#endif // CODESET
257 215
258 if (locale_codeset && strcmp("UTF-8", locale_codeset) == 0) { 216 if (locale_codeset && strcmp("UTF-8", locale_codeset) == 0) {
259 m_utf8mode = true; 217 s_utf8mode = true;
260 } else if (locale_codeset != 0) { 218 } else if (locale_codeset != 0) {
261 // if locale isn't UTF-8 we try to 219 // if locale isn't UTF-8 we try to
262 // create a iconv pointer so we can 220 // create a iconv pointer so we can
@@ -272,13 +230,13 @@ Font::Font(const char *name, bool antialias):
272 cerr<<"FbTk::Font: code error: from "<<locale_codeset<<" to: UTF-8"<<endl; 230 cerr<<"FbTk::Font: code error: from "<<locale_codeset<<" to: UTF-8"<<endl;
273 // if we failed with iconv then we can't convert 231 // if we failed with iconv then we can't convert
274 // the strings to utf-8, so we disable utf8 mode 232 // the strings to utf-8, so we disable utf8 mode
275 m_utf8mode = false; 233 s_utf8mode = false;
276 } else { 234 } else {
277 // success, we can now enable utf8mode 235 // success, we can now enable utf8mode
278 // and if antialias is on later we can recode 236 // and if antialias is on later we can recode
279 // the non utf-8 string to utf-8 and use utf-8 237 // the non utf-8 string to utf-8 and use utf-8
280 // drawing functions 238 // drawing functions
281 m_utf8mode = true; 239 s_utf8mode = true;
282 } 240 }
283#endif // HAVE_ICONV 241#endif // HAVE_ICONV
284 } 242 }
@@ -287,23 +245,6 @@ Font::Font(const char *name, bool antialias):
287 cerr<<"FbTk::Font m_iconv = "<<(int)m_iconv<<endl; 245 cerr<<"FbTk::Font m_iconv = "<<(int)m_iconv<<endl;
288#endif // DEBUG 246#endif // DEBUG
289 247
290 // create the right font implementation
291 // antialias is prio 1
292#ifdef USE_XFT
293 if (antialias) {
294 m_fontimp.reset(new XftFontImp(0, m_utf8mode));
295 }
296#endif //USE_XFT
297 // if we didn't create a Xft font then create basic font
298 if (m_fontimp.get() == 0) {
299#ifdef USE_XMB
300 if (m_multibyte || m_utf8mode)
301 m_fontimp.reset(new XmbFontImp(0, m_utf8mode));
302 else // basic font implementation
303#endif // USE_XMB
304 m_fontimp.reset(new XFontImp());
305 }
306
307 if (name != 0) { 248 if (name != 0) {
308 load(name); 249 load(name);
309 } 250 }
@@ -317,82 +258,68 @@ Font::~Font() {
317#endif // HAVE_ICONV 258#endif // HAVE_ICONV
318} 259}
319 260
320void Font::setAntialias(bool flag) {
321 bool loaded = m_fontimp->loaded();
322#ifdef USE_XFT
323 if (flag && !isAntialias() && !m_rotated) {
324 m_fontimp.reset(new XftFontImp(m_fontstr.c_str(), m_utf8mode));
325 } else if (!flag && isAntialias())
326#endif // USE_XFT
327 {
328#ifdef USE_XMB
329 if (m_multibyte || m_utf8mode)
330 m_fontimp.reset(new XmbFontImp(m_fontstr.c_str(), m_utf8mode));
331 else
332#endif // USE_XMB
333 m_fontimp.reset(new XFontImp(m_fontstr.c_str()));
334 }
335
336 if (m_fontimp->loaded() != loaded) { // if the new font failed to load, fall back to 'fixed'
337 if (!m_fontimp->load("fixed")) {// if that failes too, output warning
338 _FB_USES_NLS;
339 cerr<<_FBTKTEXT(Error, CantFallbackFont, "Warning: can't load fallback font", "Attempt to load the last-resort default font failed")<<" 'fixed'."<<endl;
340 }
341 }
342
343 m_antialias = flag;
344}
345
346bool Font::load(const std::string &name) { 261bool Font::load(const std::string &name) {
347 262
348 if (name.size() == 0) 263 if (name.size() == 0)
349 return false; 264 return false;
350 // default values for font options 265
351 m_shadow = false; 266 StringMapIt lookup_entry;
352 m_halo = false; 267 FontCacheIt cache_entry;
353 268
354 // everything after ':' is a fontoption 269 // check if one of <font1>|<font2>|<font3> is already there
355 // -> extract 'halo' and 'shadow' and 270 if ((lookup_entry = lookup_map.find(name)) != lookup_map.end() &&
356 // load remaining fname 271 (cache_entry = font_cache.find(lookup_entry->second)) != font_cache.end()) {
357 size_t sep= name.find_first_of(':'); 272 m_fontstr = cache_entry->first;
358 273 m_fontimp = cache_entry->second;
359 if ( sep != std::string::npos ) { 274 return true;
360 275 }
361 std::list< std::string > tokens; 276
362 std::string fname; 277 // split up the namelist
363 278 typedef std::list<std::string> StringList;
364 fname= std::string(name.c_str(), sep); 279 typedef StringList::iterator StringListIt;
365 280 StringList names;
366 FbTk::StringUtil::stringtok(tokens, name.substr(sep + 1), ","); 281 FbTk::StringUtil::stringtok<StringList>(names, name, "|");
367 282
368 tokens.unique(); 283 StringListIt name_it;
369 bool firstone= true; 284 for (name_it = names.begin(); name_it != names.end(); name_it++) {
370 std::list< std::string >::const_iterator token; 285 FbTk::StringUtil::removeTrailingWhitespace(*name_it);
371 286 FbTk::StringUtil::removeFirstWhitespace(*name_it);
372 // check tokens and extract extraoptions for halo and shadow 287
373 for( token= tokens.begin(); token != tokens.end(); token++ ) { 288 if ((cache_entry = font_cache.find(*name_it)) != font_cache.end()) {
374 if ( (*token).find("halo",0) != std::string::npos ) { 289 m_fontstr = cache_entry->first;
375 m_halo= true; 290 m_fontimp = cache_entry->second;
376 extract_halo_options(*token, m_halo_color); 291 lookup_map[name] = m_fontstr;
377 } 292 return true;
378 else if ( (*token).find("shadow", 0) != std::string::npos ) {
379 m_shadow= true;
380 extract_shadow_options(*token, m_shadow_color, m_shadow_offx, m_shadow_offy);
381 }
382 else {
383 if ( !firstone )
384 fname+= ", ";
385 else
386 firstone= false;
387 fname= fname + ":" + *token;
388 }
389 } 293 }
390 294
391 m_fontstr = fname; 295 FontImp* tmp_font(0);
392 } else 296
393 m_fontstr = name; 297#ifdef USE_XFT
298 if ((*name_it)[0] != '-')
299 tmp_font = new XftFontImp(0, s_utf8mode);
300#endif // USE_XFT
301
302 if (!tmp_font) {
303#ifdef USE_XMB
304 if (s_multibyte || s_utf8mode)
305 tmp_font = new XmbFontImp(0, s_utf8mode);
306 else // basic font implementation
307#endif // USE_XMB
308 tmp_font = new XFontImp();
309 }
310
311 if (tmp_font && tmp_font->load((*name_it).c_str())) {
312 lookup_map[name] = (*name_it);
313 m_fontimp = tmp_font;
314 font_cache[(*name_it)] = tmp_font;
315 m_fontstr = name;
316 return true;
317 }
318
319 delete tmp_font;
320 }
394 321
395 return m_fontimp->load(m_fontstr.c_str()); 322 return false;;
396} 323}
397 324
398unsigned int Font::textWidth(const char * const text, unsigned int size) const { 325unsigned int Font::textWidth(const char * const text, unsigned int size) const {
@@ -449,14 +376,14 @@ void Font::drawText(const FbDrawable &w, int screen, GC gc,
449 if (first_run) { 376 if (first_run) {
450 if (m_shadow) { 377 if (m_shadow) {
451 FbTk::GContext shadow_gc(w); 378 FbTk::GContext shadow_gc(w);
452 shadow_gc.setForeground(FbTk::Color(m_shadow_color.c_str(), screen)); 379 shadow_gc.setForeground(m_shadow_color);
453 first_run = false; 380 first_run = false;
454 drawText(w, screen, shadow_gc.gc(), real_text, len, 381 drawText(w, screen, shadow_gc.gc(), real_text, len,
455 x + m_shadow_offx, y + m_shadow_offy, rotate); 382 x + m_shadow_offx, y + m_shadow_offy, rotate);
456 first_run = true; 383 first_run = true;
457 } else if (m_halo) { 384 } else if (m_halo) {
458 FbTk::GContext halo_gc(w); 385 FbTk::GContext halo_gc(w);
459 halo_gc.setForeground(FbTk::Color(m_halo_color.c_str(), screen)); 386 halo_gc.setForeground(m_halo_color);
460 first_run = false; 387 first_run = false;
461 drawText(w, screen, halo_gc.gc(), real_text, len, x + 1, y + 1, rotate); 388 drawText(w, screen, halo_gc.gc(), real_text, len, x + 1, y + 1, rotate);
462 drawText(w, screen, halo_gc.gc(), real_text, len, x - 1, y + 1, rotate); 389 drawText(w, screen, halo_gc.gc(), real_text, len, x - 1, y + 1, rotate);
@@ -473,7 +400,7 @@ void Font::drawText(const FbDrawable &w, int screen, GC gc,
473 // Using dynamic_cast just temporarly until there's a better solution 400 // Using dynamic_cast just temporarly until there's a better solution
474 // to put in FontImp 401 // to put in FontImp
475 try { 402 try {
476 XFontImp *font = dynamic_cast<XFontImp *>(m_fontimp.get()); 403 XFontImp *font = dynamic_cast<XFontImp *>(m_fontimp);
477 font->setRotate(false); // disable rotation temporarly 404 font->setRotate(false); // disable rotation temporarly
478 405
479 font->drawText(w, screen, gc, real_text, len, x, y); 406 font->drawText(w, screen, gc, real_text, len, x, y);
@@ -492,15 +419,16 @@ void Font::drawText(const FbDrawable &w, int screen, GC gc,
492} 419}
493 420
494void Font::rotate(float angle) { 421void Font::rotate(float angle) {
422/* TODO: reimplement rotated text
495#ifdef USE_XFT 423#ifdef USE_XFT
496 // if we are rotated and we are changing to horiz text 424 // if we are rotated and we are changing to horiz text
497 // and we were antialiased before we rotated then change to XftFontImp 425 // and we were antialiased before we rotated then change to XftFontImp
498 if (isRotated() && angle == 0 && isAntialias()) 426 if (isRotated() && angle == 0 && !m_xftfontstr.empty())
499 m_fontimp.reset(new XftFontImp(m_fontstr.c_str(), m_utf8mode)); 427 m_fontimp.reset(new XftFontImp(m_fontstr.c_str(),s_utf8mode));
500#endif // USE_XFT 428#endif // USE_XFT
501 // change to a font imp that handles rotated fonts (i.e just XFontImp at the moment) 429 // change to a font imp that handles rotated fonts (i.e just XFontImp at the moment)
502 // if we're going to rotate this font 430 // if we're going to rotate this font
503 if (angle != 0 && isAntialias() && !isRotated()) { 431 if (angle != 0 && !isRotated()) {
504 m_fontimp.reset(new XFontImp(m_fontstr.c_str())); 432 m_fontimp.reset(new XFontImp(m_fontstr.c_str()));
505 if (!m_fontimp->loaded()) // if it failed to load font, try default font fixed 433 if (!m_fontimp->loaded()) // if it failed to load font, try default font fixed
506 m_fontimp->load("fixed"); 434 m_fontimp->load("fixed");
@@ -511,6 +439,7 @@ void Font::rotate(float angle) {
511 439
512 m_rotated = (angle == 0 ? false : true); 440 m_rotated = (angle == 0 ? false : true);
513 m_angle = angle; 441 m_angle = angle;
442 */
514} 443}
515 444
516 445