aboutsummaryrefslogtreecommitdiff
path: root/src/FbTk
diff options
context:
space:
mode:
Diffstat (limited to 'src/FbTk')
-rw-r--r--src/FbTk/Font.cc185
-rw-r--r--src/FbTk/Font.hh11
2 files changed, 153 insertions, 43 deletions
diff --git a/src/FbTk/Font.cc b/src/FbTk/Font.cc
index 75d89f1..709c8e4 100644
--- a/src/FbTk/Font.cc
+++ b/src/FbTk/Font.cc
@@ -19,9 +19,10 @@
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.8 2004/08/10 11:21:50 fluxgen Exp $ 22//$Id: Font.cc,v 1.9 2004/08/10 18:08:37 fluxgen Exp $
23 23
24 24
25#include "StringUtil.hh"
25#include "Font.hh" 26#include "Font.hh"
26#include "FontImp.hh" 27#include "FontImp.hh"
27#include "I18n.hh" 28#include "I18n.hh"
@@ -56,12 +57,27 @@
56#include <iostream> 57#include <iostream>
57#include <cstring> 58#include <cstring>
58#include <cstdlib> 59#include <cstdlib>
60#include <list>
59#include <typeinfo> 61#include <typeinfo>
60 62
63
64#ifdef HAVE_SSTREAM
65#include <sstream>
66#define FB_istringstream istringstream
67#elif HAVE_STRSTREAM
68#include <strstream>
69#define FB_istringstream istrstream
70#else
71#error "You dont have sstream or strstream headers!"
72#endif // HAVE_STRSTREAM
73
61#include <cstdlib> 74#include <cstdlib>
62 75
63using namespace std; 76using namespace std;
64 77
78
79namespace {
80
65#ifdef HAVE_SETLOCALE 81#ifdef HAVE_SETLOCALE
66#include <locale.h> 82#include <locale.h>
67#endif //HAVE_SETLOCALE 83#endif //HAVE_SETLOCALE
@@ -74,7 +90,7 @@ using namespace std;
74 @param len number of chars to convert 90 @param len number of chars to convert
75 @return the recoded string, or 0 on failure 91 @return the recoded string, or 0 on failure
76*/ 92*/
77static char* recode(iconv_t cd, 93char* recode(iconv_t cd,
78 const char *msg, size_t size) { 94 const char *msg, size_t size) {
79 95
80 // If empty message, yes this can happen, return 96 // If empty message, yes this can happen, return
@@ -110,6 +126,75 @@ static char* recode(iconv_t cd,
110 return new_msg; 126 return new_msg;
111} 127}
112 128
129
130int extract_halo_options(const std::string& opts, std::string& color) {
131 std::list< std::string > tokens;
132 size_t sep= opts.find_first_of(':');
133
134 if ( sep == std::string::npos )
135 return 1;
136
137 FbTk::StringUtil::stringtok(tokens, opts.substr(sep + 1, opts.length()), ";");
138 tokens.unique();
139 std::list< std::string >::const_iterator token;
140
141 for ( token= tokens.begin(); token != tokens.end(); token++ ) {
142 if ( (*token).find("color=", 0) != std::string::npos ) {
143 size_t s= (*token).find_first_of('=');
144 std::string c= (*token).substr(s + 1, (*token).length());
145 if ( !c.empty() )
146 std::swap(color, c);
147 }
148 }
149
150 return 1;
151}
152
153int extract_shadow_options(const std::string& opts,
154 std::string& color,
155 int& offx, int& offy) {
156
157 std::list< std::string > tokens;
158 size_t sep= opts.find_first_of(':');
159
160 if ( sep == std::string::npos )
161 return 1;
162
163 FbTk::StringUtil::stringtok(tokens, opts.substr(sep + 1, opts.length()), ";");
164 tokens.unique();
165 std::list< std::string >::const_iterator token;
166
167 for ( token= tokens.begin(); token != tokens.end(); token++ ) {
168 if ( (*token).find("color=", 0) != std::string::npos ) {
169 size_t s= (*token).find_first_of('=');
170 std::string c= (*token).substr(s + 1, (*token).length());
171 if ( !c.empty() )
172 std::swap(color, c);
173 }
174 else if ( (*token).find("offsetx=", 0) != std::string::npos ) {
175 size_t s= (*token).find_first_of('=');
176 FB_istringstream o((*token).substr(s + 1, (*token).length()));
177 if ( !o.eof() ) {
178 o >> offx;
179 }
180 }
181 else if ( (*token).find("offsety=", 0) != std::string::npos ) {
182 size_t s= (*token).find_first_of('=');
183 FB_istringstream o((*token).substr(s + 1, (*token).length()));
184 if ( !o.eof() ) {
185 o >> offy;
186 }
187 }
188 }
189
190 return 1;
191
192};
193
194}; // end nameless namespace
195
196
197
113namespace FbTk { 198namespace FbTk {
114 199
115bool Font::m_multibyte = false; 200bool Font::m_multibyte = false;
@@ -117,7 +202,10 @@ bool Font::m_utf8mode = false;
117 202
118Font::Font(const char *name, bool antialias): 203Font::Font(const char *name, bool antialias):
119 m_fontimp(0), 204 m_fontimp(0),
120 m_antialias(false), m_rotated(false), m_shadow(false), 205 m_antialias(false), m_rotated(false),
206 m_shadow(false), m_shadow_color("#000000"),
207 m_shadow_offx(1), m_shadow_offy(1),
208 m_halo(false), m_halo_color("#ffffff"),
121 m_iconv((iconv_t)-1) { 209 m_iconv((iconv_t)-1) {
122 210
123 // MB_CUR_MAX returns the size of a char in the current locale 211 // MB_CUR_MAX returns the size of a char in the current locale
@@ -222,46 +310,49 @@ void Font::setAntialias(bool flag) {
222bool Font::load(const std::string &name) { 310bool Font::load(const std::string &name) {
223 if (name.size() == 0) 311 if (name.size() == 0)
224 return false; 312 return false;
225 // copy name so we can manipulate it
226 std::string new_name = name;
227 313
228 m_shadow = false; 314 m_shadow = false;
229 315 m_halo = false;
230 // find font option "shadow" 316
231 size_t start_pos = new_name.find_first_of(':'); 317 // everything after ':' is a fontoption
232 if (start_pos != std::string::npos) { 318 // -> extract 'halo' and 'shadow' and
233 size_t shadow_pos = new_name.find("shadow", start_pos); 319 // load remaining fname
234 if (shadow_pos != std::string::npos) { 320 std::list< std::string > tokens;
235 m_shadow = true; 321 size_t sep= name.find_first_of(':');
236 // erase "shadow" since it's not a valid option for the font 322 std::string fname;
237 new_name.erase(shadow_pos, 6); 323
238 324 if ( sep != std::string::npos ) {
239 // is the option row empty? 325 fname= std::string(name.c_str(), sep + 1);
240 if (new_name.find_first_not_of("\t ,", start_pos + 1) == std::string::npos) 326 FbTk::StringUtil::stringtok(tokens, name.substr(sep + 1, name.length()), ",");
241 new_name.erase(start_pos); // erase the ':' and the rest of the line
242 else {
243 // there might be some options left so we need to remove the ","
244 // before/after "shadow" option
245 size_t pos = new_name.find_last_not_of("\t ", shadow_pos);
246 if (pos != std::string::npos) {
247 if (new_name[pos] == ',')
248 new_name.erase(pos, 1);
249
250 } 327 }
251 328 else
252 // ok, we removed the "," and "shadow" now we need to determine 329 fname= name;
253 // if we need to remove the ":" , so we search for anything except 330
254 // \t and space and if we dont find anything the ":" is removed 331 tokens.unique();
255 if (new_name.find_first_not_of("\t ", start_pos + 1) == std::string::npos) 332 bool firstone= true;
256 new_name.erase(start_pos, 1); 333 std::list< std::string >::const_iterator token;
257 334
335 // check tokens and extract extraoptions for halo and shadow
336 for( token= tokens.begin(); token != tokens.end(); token++ ) {
337 if ( (*token).find("halo",0) != std::string::npos ) {
338 m_halo= true;
339 extract_halo_options(*token, m_halo_color);
340 }
341 else if ( (*token).find("shadow", 0) != std::string::npos ) {
342 m_shadow= true;
343 extract_shadow_options(*token, m_shadow_color, m_shadow_offx, m_shadow_offy);
258 } 344 }
259 345 else {
346 if ( !firstone )
347 fname+= ", ";
348 else
349 firstone= false;
350 fname= fname + *token;
260 } 351 }
261 } 352 }
262 353
263 m_fontstr = name; 354 m_fontstr = fname;
264 return m_fontimp->load(new_name.c_str()); 355 return m_fontimp->load(fname.c_str());
265} 356}
266 357
267unsigned int Font::textWidth(const char * const text, unsigned int size) const { 358unsigned int Font::textWidth(const char * const text, unsigned int size) const {
@@ -312,13 +403,25 @@ void Font::drawText(Drawable w, int screen, GC gc,
312 403
313 const char *real_text = rtext ? rtext : text; 404 const char *real_text = rtext ? rtext : text;
314 405
315 // draw shadow first 406 // draw "effects" first
316 if (first_run && m_shadow) { 407 if (first_run) {
408 if (m_shadow) {
317 FbTk::GContext shadow_gc(w); 409 FbTk::GContext shadow_gc(w);
318 shadow_gc.setForeground(FbTk::Color("black", screen)); 410 shadow_gc.setForeground(FbTk::Color(m_shadow_color.c_str(), screen));
319 first_run = false; // so we don't end up in a loop 411 first_run = false;
320 drawText(w, screen, shadow_gc.gc(), real_text, len, x + 1, y + 1); 412 drawText(w, screen, shadow_gc.gc(), real_text, len,
413 x + m_shadow_offx, y + m_shadow_offy, rotate);
321 first_run = true; 414 first_run = true;
415 } else if (m_halo) {
416 FbTk::GContext halo_gc(w);
417 halo_gc.setForeground(FbTk::Color(m_halo_color.c_str(), screen));
418 first_run = false;
419 drawText(w, screen, halo_gc.gc(), real_text, len, x + 1, y + 1, rotate);
420 drawText(w, screen, halo_gc.gc(), real_text, len, x - 1, y + 1, rotate);
421 drawText(w, screen, halo_gc.gc(), real_text, len, x - 1, y - 1, rotate);
422 drawText(w, screen, halo_gc.gc(), real_text, len, x + 1, y - 1, rotate);
423 first_run = true;
424 }
322 } 425 }
323 426
324 if (!rotate && isRotated()) { 427 if (!rotate && isRotated()) {
diff --git a/src/FbTk/Font.hh b/src/FbTk/Font.hh
index fded0c4..1ac2fe0 100644
--- a/src/FbTk/Font.hh
+++ b/src/FbTk/Font.hh
@@ -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.hh,v 1.8 2004/08/10 11:22:10 fluxgen Exp $ 22//$Id: Font.hh,v 1.9 2004/08/10 18:08:37 fluxgen Exp $
23 23
24#ifndef FBTK_FONT_HH 24#ifndef FBTK_FONT_HH
25#define FBTK_FONT_HH 25#define FBTK_FONT_HH
@@ -56,7 +56,8 @@ public:
56 /// @return true if utf-8 mode is enabled, else false 56 /// @return true if utf-8 mode is enabled, else false
57 static bool utf8() { return m_utf8mode; } 57 static bool utf8() { return m_utf8mode; }
58 void setAntialias(bool flag); 58 void setAntialias(bool flag);
59 inline void setShadow(bool flag) { m_shadow = flag; } 59 inline void setShadow(bool flag) { m_shadow = flag; if (m_shadow) setHalo(false); }
60 inline void setHalo(bool flag) { m_halo = flag; if (m_halo) setShadow(false); }
60 /** 61 /**
61 @param text text to check size 62 @param text text to check size
62 @param size length of text in bytes 63 @param size length of text in bytes
@@ -92,6 +93,7 @@ public:
92 /// @return rotated angle 93 /// @return rotated angle
93 float angle() const { return m_angle; } 94 float angle() const { return m_angle; }
94 bool shadow() const { return m_shadow; } 95 bool shadow() const { return m_shadow; }
96 bool halo() const { return m_halo; }
95private: 97private:
96 98
97 std::auto_ptr<FontImp> m_fontimp; ///< font implementation 99 std::auto_ptr<FontImp> m_fontimp; ///< font implementation
@@ -102,6 +104,11 @@ private:
102 bool m_rotated; ///< wheter we're rotated or not 104 bool m_rotated; ///< wheter we're rotated or not
103 float m_angle; ///< rotation angle 105 float m_angle; ///< rotation angle
104 bool m_shadow; ///< shadow text 106 bool m_shadow; ///< shadow text
107 std::string m_shadow_color; ///< shadow color
108 int m_shadow_offx; ///< offset y for shadow
109 int m_shadow_offy; ///< offset x for shadow
110 bool m_halo; ///< halo text
111 std::string m_halo_color; ///< halo color
105 std::string m_locale; ///< system encoding 112 std::string m_locale; ///< system encoding
106 iconv_t m_iconv; 113 iconv_t m_iconv;
107}; 114};