diff -abBpur fluxbox/src/FbTk/Font.cc ak-fluxbox/src/FbTk/Font.cc --- fluxbox/src/FbTk/Font.cc 2004-01-15 00:37:12.000000000 +0100 +++ ak-fluxbox/src/FbTk/Font.cc 2004-01-16 00:36:03.615301493 +0100 @@ -22,6 +22,7 @@ //$Id: Font.cc,v 1.6 2003/12/01 19:57:01 fluxgen Exp $ +#include "StringUtil.hh" #include "Font.hh" #include "FontImp.hh" @@ -56,6 +57,7 @@ #include #include #include +#include #include using namespace std; @@ -63,14 +65,92 @@ using namespace std; #include #endif //HAVE_SETLOCALE +#ifdef HAVE_SSTREAM +#include +#define FB_istringstream istringstream +#elif HAVE_STRSTREAM +#include +#define FB_istringstream istrstream +#else +#error "You dont have sstream or strstream headers!" +#endif // HAVE_STRSTREAM + namespace FbTk { +namespace { + +int extract_halo_options(const std::string& opts, std::string& color) { + std::list< std::string > tokens; + size_t sep= opts.find_first_of(':'); + + if ( sep == std::string::npos ) + return 1; + + FbTk::StringUtil::stringtok(tokens, opts.substr(sep + 1, opts.length()), ";"); + tokens.unique(); + std::list< std::string >::const_iterator token; + + for ( token= tokens.begin(); token != tokens.end(); token++ ) { + if ( (*token).find("color=", 0) != std::string::npos ) { + size_t s= (*token).find_first_of('='); + std::string c= (*token).substr(s + 1, (*token).length()); + if ( !c.empty() ) + std::swap(color, c); + } + } + + return 1; +} + +int extract_shadow_options(const std::string& opts, std::string& color, int& offx, int& offy) { + std::list< std::string > tokens; + size_t sep= opts.find_first_of(':'); + + if ( sep == std::string::npos ) + return 1; + + FbTk::StringUtil::stringtok(tokens, opts.substr(sep + 1, opts.length()), ";"); + tokens.unique(); + std::list< std::string >::const_iterator token; + + for ( token= tokens.begin(); token != tokens.end(); token++ ) { + if ( (*token).find("color=", 0) != std::string::npos ) { + size_t s= (*token).find_first_of('='); + std::string c= (*token).substr(s + 1, (*token).length()); + if ( !c.empty() ) + std::swap(color, c); + } + else if ( (*token).find("offsetx=", 0) != std::string::npos ) { + size_t s= (*token).find_first_of('='); + FB_istringstream o((*token).substr(s + 1, (*token).length())); + if ( !o.eof() ) { + o >> offx; + } + } + else if ( (*token).find("offsety=", 0) != std::string::npos ) { + size_t s= (*token).find_first_of('='); + FB_istringstream o((*token).substr(s + 1, (*token).length())); + if ( !o.eof() ) { + o >> offy; + } + } + } + + return 1; + +}; + +}; // end nameless namespace + + bool Font::m_multibyte = false; bool Font::m_utf8mode = false; Font::Font(const char *name, bool antialias): m_fontimp(0), - m_antialias(false), m_rotated(false), m_shadow(false) { + m_antialias(false), m_rotated(false), + m_shadow(false), m_shadow_color("#000000"), m_shadow_offx(1), m_shadow_offy(1), + m_halo(false), m_halo_color("#ffffff") { // MB_CUR_MAX returns the size of a char in the current locale if (MB_CUR_MAX > 1) // more than one byte, then we're multibyte @@ -140,46 +220,49 @@ void Font::setAntialias(bool flag) { bool Font::load(const std::string &name) { if (name.size() == 0) return false; - // copy name so we can manipulate it - std::string new_name = name; m_shadow = false; + m_halo = false; - // find font option "shadow" - size_t start_pos = new_name.find_first_of(':'); - if (start_pos != std::string::npos) { - size_t shadow_pos = new_name.find("shadow", start_pos); - if (shadow_pos != std::string::npos) { - m_shadow = true; - // erase "shadow" since it's not a valid option for the font - new_name.erase(shadow_pos, 6); - - // is the option row empty? - if (new_name.find_first_not_of("\t ,", start_pos + 1) == std::string::npos) - new_name.erase(start_pos); // erase the ':' and the rest of the line - else { - // there might be some options left so we need to remove the "," - // before/after "shadow" option - size_t pos = new_name.find_last_not_of("\t ", shadow_pos); - if (pos != std::string::npos) { - if (new_name[pos] == ',') - new_name.erase(pos, 1); - + // everything after ':' is a fontoption + // -> extract 'halo' and 'shadow' and + // load remaining fname + std::list< std::string > tokens; + size_t sep= name.find_first_of(':'); + std::string fname; + + if ( sep != std::string::npos ) { + fname= std::string(name.c_str(), sep + 1); + FbTk::StringUtil::stringtok(tokens, name.substr(sep + 1, name.length()), ","); } + else + fname= name; - // ok, we removed the "," and "shadow" now we need to determine - // if we need to remove the ":" , so we search for anything except - // \t and space and if we dont find anything the ":" is removed - if (new_name.find_first_not_of("\t ", start_pos + 1) == std::string::npos) - new_name.erase(start_pos, 1); - + tokens.unique(); + bool firstone= true; + std::list< std::string >::const_iterator token; + + // check tokens and extract extraoptions for halo and shadow + for( token= tokens.begin(); token != tokens.end(); token++ ) { + if ( (*token).find("halo",0) != std::string::npos ) { + m_halo= true; + extract_halo_options(*token, m_halo_color); + } + else if ( (*token).find("shadow", 0) != std::string::npos ) { + m_shadow= true; + extract_shadow_options(*token, m_shadow_color, m_shadow_offx, m_shadow_offy); } - + else { + if ( !firstone ) + fname+= ", "; + else + firstone= false; + fname= fname + *token; } } - m_fontstr = name; - return m_fontimp->load(new_name.c_str()); + m_fontstr = fname; + return m_fontimp->load(fname.c_str()); } unsigned int Font::textWidth(const char * const text, unsigned int size) const { @@ -199,20 +282,25 @@ int Font::descent() const { } void Font::drawText(Drawable w, int screen, GC gc, const char *text, size_t len, int x, int y, - bool rotate) const { + bool rotate, bool selfcalled) const { if (text == 0 || len == 0) return; - // so we don't end up in a loop with m_shadow - static bool first_run = true; - - // draw shadow first - if (first_run && m_shadow) { + // draw shadow / halo first + if (!selfcalled) { + if (m_shadow) { FbTk::GContext shadow_gc(w); - shadow_gc.setForeground(FbTk::Color("black", screen)); - first_run = false; // so we don't end up in a loop - drawText(w, screen, shadow_gc.gc(), text, len, x + 1, y + 1); - first_run = true; + shadow_gc.setForeground(FbTk::Color(m_shadow_color.c_str(), screen)); + drawText(w, screen, shadow_gc.gc(), text, len, + x + m_shadow_offx, y + m_shadow_offy, rotate, true); + } else if (m_halo) { + FbTk::GContext halo_gc(w); + halo_gc.setForeground(FbTk::Color(m_halo_color.c_str(), screen)); + drawText(w, screen, halo_gc.gc(), text, len, x + 1, y + 1, rotate, true); + drawText(w, screen, halo_gc.gc(), text, len, x - 1, y + 1, rotate, true); + drawText(w, screen, halo_gc.gc(), text, len, x - 1, y - 1, rotate, true); + drawText(w, screen, halo_gc.gc(), text, len, x + 1, y - 1, rotate, true); + } } if (!rotate && isRotated()) { diff -abBpur fluxbox/src/FbTk/Font.hh ak-fluxbox/src/FbTk/Font.hh --- fluxbox/src/FbTk/Font.hh 2004-01-15 00:37:12.000000000 +0100 +++ ak-fluxbox/src/FbTk/Font.hh 2004-01-15 23:51:33.000000000 +0100 @@ -54,7 +54,8 @@ public: /// @return true if utf-8 mode is enabled, else false static bool utf8() { return m_utf8mode; } void setAntialias(bool flag); - inline void setShadow(bool flag) { m_shadow = flag; } + inline void setShadow(bool flag) { m_shadow = flag; if (m_shadow) setHalo(false); } + inline void setHalo(bool flag) { m_halo = flag; if (m_halo) setShadow(false); } /** @param text text to check size @param size length of text in bytes @@ -80,16 +81,19 @@ public: @param x position @param y position @param rotate if the text should be drawn rotated (if it's rotated before) + @param selfcalled some effects (halo/shadow) need + to call this function multiple times, avoid infinit loop */ void drawText(Drawable w, int screen, GC gc, const char *text, size_t len, - int x, int y, bool rotate=true) const; + int x, int y, bool rotate=true, bool selfcalled= false) const; bool isAntialias() const { return m_antialias; } /// @return true if the font is rotated, else false bool isRotated() const { return m_rotated; } /// @return rotated angle float angle() const { return m_angle; } bool shadow() const { return m_shadow; } + bool halo() const { return m_halo; } private: std::auto_ptr m_fontimp; ///< font implementation @@ -100,6 +104,11 @@ private: bool m_rotated; ///< wheter we're rotated or not float m_angle; ///< rotation angle bool m_shadow; ///< shadow text + std::string m_shadow_color; ///< shadow color + int m_shadow_offx; ///< offset y for shadow + int m_shadow_offy; ///< offset x for shadow + bool m_halo; ///< halo text + std::string m_halo_color; ///< halo color }; } //end namespace FbTk