aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk/Font.cc
diff options
context:
space:
mode:
authormathias <mathias>2005-06-03 07:25:48 (GMT)
committermathias <mathias>2005-06-03 07:25:48 (GMT)
commitef76b45ab1857af1b12f0c336bfb8c0f19140aeb (patch)
treee380d87f9e4c5e1b27f7aeb8d3aa8acbe0e09d2c /src/FbTk/Font.cc
parent9c27e2e7993c9ccd604f77219a1f07c1be22e75a (diff)
downloadfluxbox_pavel-ef76b45ab1857af1b12f0c336bfb8c0f19140aeb.zip
fluxbox_pavel-ef76b45ab1857af1b12f0c336bfb8c0f19140aeb.tar.bz2
- Usage of xft-fonts is prefered, except a font-description starts with '-'
- Removed "antialias"-option completly, to enable/disable "antialias" use either <fontname>:antialias=<bool> in the style or use Xft.antialias: <bool> in your .Xdefaults - Added new styleresources: *.font.effect: <halo|shadow> *.font.shadow.x : <int> - shadow x offset *.font.shadow.y : <int> - shadow y offset *.font.shadow.color : <color> - color of shadow *.font.halo.color : <color> - color of halo - Removed 'shadow' and 'halo' options from fontdefinitions: !! Style authors have to update their styles !! - Simplified XmbFontImp to not try all possible fonts to match locale - Style authors may specify multiple fonts: <font1>|<font2>|<font3> if loading of font1 fails, fluxbox probes <font2>, etc. The last font is "fixed". Hints for style authors: - if xft tries to load a font it will _ALWAYS_ return a valid font, it doesnt have to look like the one you want to have, read more about it: http://fontconfig.org/fontconfig-user.html - export XFT_DEBUG=1 before running fluxbox helps to see which fonts are picked. eg: *.font: Verdana,Arial-12:antialias=true|-artwiz-snap-*- if fluxbox is compiled with xft this will NEVER try to load "-artwiz-snap-*-" since xft gives for sure a font, most likely Verdana or Arial but noone knows. So, if fluxbox has no xft support the first fontpattern fails and fluxbox tries the next one, which might be successful. if everything fails, it will use "fixed" - Added caching of fonts, fonts are only loaded once. - Fixed #1090902 (slow utf8 start)
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