aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMathias Gumz <akira at fluxbox dot org>2012-10-02 12:24:47 (GMT)
committerMathias Gumz <akira at fluxbox dot org>2012-10-03 08:27:16 (GMT)
commit7b6ab828c7e5453a2720462156d165707935c9ef (patch)
tree3b641791b20b1994935e149fd7461decb11bef8c /src
parent032a23d1e790c5224194562a837cc80fc157ce9b (diff)
downloadfluxbox-7b6ab828c7e5453a2720462156d165707935c9ef.zip
fluxbox-7b6ab828c7e5453a2720462156d165707935c9ef.tar.bz2
Improved vertical alignment of text in FbTk::TextButton
The old formula for vertical align text inside FbTk::TextButton ('height/2 + font_ascent/2 - 1') produced not always good looking results, escpecially when different fonts are involved (eg, ClockTool and WorkspaceName have different fonts and font-sizes). '(height - font_ascent) / 2 - 1' produces better results. Additional changes: * added ASCII-Art to document the involved entities when calculating the baseline * rewritten tests/testFont.cc to accept multiples texts and multiple fonts * removed some internal parts of FbTk::Font from the public interface
Diffstat (limited to 'src')
-rw-r--r--src/FbTk/Font.cc75
-rw-r--r--src/FbTk/Font.hh17
-rw-r--r--src/FbTk/TextButton.cc78
-rw-r--r--src/FbTk/TextButton.hh4
-rw-r--r--src/Toolbar.cc2
-rw-r--r--src/tests/testFont.cc212
6 files changed, 215 insertions, 173 deletions
diff --git a/src/FbTk/Font.cc b/src/FbTk/Font.cc
index 37621a8..544ddc2 100644
--- a/src/FbTk/Font.cc
+++ b/src/FbTk/Font.cc
@@ -66,6 +66,7 @@
66#include <map> 66#include <map>
67#include <typeinfo> 67#include <typeinfo>
68#include <langinfo.h> 68#include <langinfo.h>
69#include <cstdio>
69 70
70#include <errno.h> 71#include <errno.h>
71 72
@@ -83,12 +84,10 @@ namespace {
83// use to map <font1>|<font2>|<font3> => <fontthatworks> 84// use to map <font1>|<font2>|<font3> => <fontthatworks>
84typedef map<string, string> StringMap; 85typedef map<string, string> StringMap;
85typedef StringMap::iterator StringMapIt; 86typedef StringMap::iterator StringMapIt;
86StringMap lookup_map;
87 87
88// stores <fontthatworks and the fontimp 88// stores <fontthatworks and the fontimp
89typedef map<string, FbTk::FontImp* > FontCache; 89typedef map<string, FbTk::FontImp* > FontCache;
90typedef FontCache::iterator FontCacheIt; 90typedef FontCache::iterator FontCacheIt;
91FontCache font_cache;
92 91
93 92
94void resetEffects(FbTk::Font& font) { 93void resetEffects(FbTk::Font& font) {
@@ -100,24 +99,30 @@ void resetEffects(FbTk::Font& font) {
100 font.setShadowOffX(2); 99 font.setShadowOffX(2);
101} 100}
102 101
102
103StringMap s_lookup_map;
104FontCache s_font_cache;
105bool s_multibyte = false; // if the fontimp should be a multibyte font
106bool s_utf8mode = false; // should the font use utf8 font imp
107
108
103} // end nameless namespace 109} // end nameless namespace
104 110
105 111
106 112
107namespace FbTk { 113namespace FbTk {
108 114
109bool Font::s_multibyte = false; 115const char Font::DEFAULT_FONT[] = "__DEFAULT__";
110bool Font::s_utf8mode = false;
111 116
112 117
113void Font::shutdown() { 118void Font::shutdown() {
114 119
115 FontCacheIt fit; 120 FontCacheIt fit;
116 for (fit = font_cache.begin(); fit != font_cache.end(); fit++) { 121 for (fit = s_font_cache.begin(); fit != s_font_cache.end(); ++fit) {
117 FontImp* font = fit->second; 122 FontImp* font = fit->second;
118 if (font) { 123 if (font) {
119 FontCacheIt it; 124 FontCacheIt it;
120 for (it = fit; it != font_cache.end(); ++it) 125 for (it = fit; it != s_font_cache.end(); ++it)
121 if (it->second == font) 126 if (it->second == font)
122 it->second = 0; 127 it->second = 0;
123 delete font; 128 delete font;
@@ -125,6 +130,15 @@ void Font::shutdown() {
125 } 130 }
126} 131}
127 132
133bool Font::multibyte() {
134 return s_multibyte;
135}
136
137bool Font::utf8() {
138 return s_utf8mode;
139}
140
141
128Font::Font(const char *name): 142Font::Font(const char *name):
129 m_fontimp(0), 143 m_fontimp(0),
130 m_shadow(false), m_shadow_color("black", DefaultScreen(App::instance()->display())), 144 m_shadow(false), m_shadow_color("black", DefaultScreen(App::instance()->display())),
@@ -135,13 +149,15 @@ Font::Font(const char *name):
135 if (MB_CUR_MAX > 1) // more than one byte, then we're multibyte 149 if (MB_CUR_MAX > 1) // more than one byte, then we're multibyte
136 s_multibyte = true; 150 s_multibyte = true;
137 151
138 // check for utf-8 mode 152
139#if defined(CODESET) && !defined(_WIN32)
140 char *locale_codeset = nl_langinfo(CODESET);
141#else // openbsd doesnt have this (yet?)
142 char *locale_codeset = 0; 153 char *locale_codeset = 0;
143#endif // defined(CODESET) && !defined(_WIN32)
144 154
155 // openbsd doesnt have this (yet?)
156#if defined(CODESET) && !defined(_WIN32)
157 locale_codeset = nl_langinfo(CODESET);
158#endif
159
160 // check for utf-8 mode
145 if (locale_codeset && strcmp("UTF-8", locale_codeset) == 0) { 161 if (locale_codeset && strcmp("UTF-8", locale_codeset) == 0) {
146 s_utf8mode = true; 162 s_utf8mode = true;
147 } else if (locale_codeset != 0) { 163 } else if (locale_codeset != 0) {
@@ -159,15 +175,15 @@ Font::~Font() {
159 175
160bool Font::load(const string &name) { 176bool Font::load(const string &name) {
161 177
162 if (name.size() == 0) 178 if (name.empty())
163 return false; 179 return false;
164 180
165 StringMapIt lookup_entry; 181 StringMapIt lookup_entry;
166 FontCacheIt cache_entry; 182 FontCacheIt cache_entry;
167 183
168 // check if one of <font1>|<font2>|<font3> is already there 184 // check if one of <font1>|<font2>|<font3> is already there
169 if ((lookup_entry = lookup_map.find(name)) != lookup_map.end() && 185 if ((lookup_entry = s_lookup_map.find(name)) != s_lookup_map.end() &&
170 (cache_entry = font_cache.find(lookup_entry->second)) != font_cache.end()) { 186 (cache_entry = s_font_cache.find(lookup_entry->second)) != s_font_cache.end()) {
171 m_fontstr = cache_entry->first; 187 m_fontstr = cache_entry->first;
172 m_fontimp = cache_entry->second; 188 m_fontimp = cache_entry->second;
173 resetEffects(*this); 189 resetEffects(*this);
@@ -185,10 +201,10 @@ bool Font::load(const string &name) {
185 FbTk::StringUtil::removeTrailingWhitespace(*name_it); 201 FbTk::StringUtil::removeTrailingWhitespace(*name_it);
186 FbTk::StringUtil::removeFirstWhitespace(*name_it); 202 FbTk::StringUtil::removeFirstWhitespace(*name_it);
187 203
188 if ((cache_entry = font_cache.find(*name_it)) != font_cache.end()) { 204 if ((cache_entry = s_font_cache.find(*name_it)) != s_font_cache.end()) {
189 m_fontstr = cache_entry->first; 205 m_fontstr = cache_entry->first;
190 m_fontimp = cache_entry->second; 206 m_fontimp = cache_entry->second;
191 lookup_map[name] = m_fontstr; 207 s_lookup_map[name] = m_fontstr;
192 resetEffects(*this); 208 resetEffects(*this);
193 return true; 209 return true;
194 } 210 }
@@ -210,32 +226,33 @@ bool Font::load(const string &name) {
210#ifdef USE_XFT 226#ifdef USE_XFT
211 if ((*name_it)[0] != '-') { 227 if ((*name_it)[0] != '-') {
212 228
213 if (*name_it == "__DEFAULT__") 229 if (*name_it == Font::DEFAULT_FONT)
214 realname = "monospace"; 230 realname = "monospace";
215 231
216 tmp_font = new XftFontImp(0, s_utf8mode); 232 tmp_font = new XftFontImp(0, utf8());
217 } 233 }
218#endif // USE_XFT 234#endif // USE_XFT
219 235
220 if (!tmp_font) { 236 if (!tmp_font) {
221 if (*name_it == "__DEFAULT__") 237 if (*name_it == Font::DEFAULT_FONT)
222 realname = "fixed"; 238 realname = "fixed";
223 239
224#ifdef USE_XMB 240#ifdef USE_XMB
225 241
226 if (s_multibyte || s_utf8mode) { 242 if (multibyte() || utf8()) {
227 tmp_font = new XmbFontImp(0, s_utf8mode); 243 tmp_font = new XmbFontImp(0, utf8());
228 } else // basic font implementation 244 }
229#endif // USE_XMB 245#endif // USE_XMB
230 { 246 }
231 tmp_font = new XFontImp(); 247
232 } 248 if (!tmp_font) {
249 tmp_font = new XFontImp();
233 } 250 }
234 251
235 if (tmp_font && tmp_font->load(realname.c_str())) { 252 if (tmp_font && tmp_font->load(realname.c_str())) {
236 lookup_map[name] = (*name_it); 253 s_lookup_map[name] = (*name_it);
237 m_fontimp = tmp_font; 254 m_fontimp = tmp_font;
238 font_cache[(*name_it)] = tmp_font; 255 s_font_cache[(*name_it)] = tmp_font;
239 m_fontstr = name; 256 m_fontstr = name;
240 resetEffects(*this); 257 resetEffects(*this);
241 return true; 258 return true;
@@ -251,6 +268,10 @@ unsigned int Font::textWidth(const char* text, unsigned int size) const {
251 return m_fontimp->textWidth(text, size); 268 return m_fontimp->textWidth(text, size);
252} 269}
253 270
271unsigned int Font::textWidth(const BiDiString &text) const {
272 return textWidth(text.visual().c_str(), text.visual().size());
273}
274
254unsigned int Font::height() const { 275unsigned int Font::height() const {
255 return m_fontimp->height(); 276 return m_fontimp->height();
256} 277}
diff --git a/src/FbTk/Font.hh b/src/FbTk/Font.hh
index fb399d9..6ea2571 100644
--- a/src/FbTk/Font.hh
+++ b/src/FbTk/Font.hh
@@ -43,17 +43,19 @@ class FbDrawable;
43class Font { 43class Font {
44public: 44public:
45 45
46 static const char DEFAULT_FONT[];
47
48
46 /// called at FbTk::App destruction time, cleans up cache 49 /// called at FbTk::App destruction time, cleans up cache
47 static void shutdown(); 50 static void shutdown();
48 51
49 /// @return true if multibyte is enabled, else false 52 /// @return true if multibyte is enabled, else false
50 static bool multibyte() { return s_multibyte; } 53 static bool multibyte();
51 /// @return true if utf-8 mode is enabled, else false 54 /// @return true if utf-8 mode is enabled, else false
52 static bool utf8() { return s_utf8mode; } 55 static bool utf8();
53
54 56
55 57
56 explicit Font(const char *name = "__DEFAULT__"); 58 explicit Font(const char* name = DEFAULT_FONT);
57 virtual ~Font(); 59 virtual ~Font();
58 /** 60 /**
59 Load a font 61 Load a font
@@ -76,9 +78,7 @@ public:
76 @return size of text in pixels 78 @return size of text in pixels
77 */ 79 */
78 unsigned int textWidth(const char* text, unsigned int size) const; 80 unsigned int textWidth(const char* text, unsigned int size) const;
79 unsigned int textWidth(const BiDiString &text) const { 81 unsigned int textWidth(const BiDiString &text) const;
80 return textWidth(text.visual().c_str(), text.visual().size());
81 }
82 82
83 unsigned int height() const; 83 unsigned int height() const;
84 int ascent() const; 84 int ascent() const;
@@ -119,9 +119,6 @@ private:
119 FbTk::FontImp* m_fontimp; ///< font implementation 119 FbTk::FontImp* m_fontimp; ///< font implementation
120 std::string m_fontstr; ///< font name 120 std::string m_fontstr; ///< font name
121 121
122 static bool s_multibyte; ///< if the fontimp should be a multibyte font
123 static bool s_utf8mode; ///< should the font use utf8 font imp
124
125 int m_angle; ///< rotation angle 122 int m_angle; ///< rotation angle
126 bool m_shadow; ///< shadow text 123 bool m_shadow; ///< shadow text
127 Color m_shadow_color; ///< shadow color 124 Color m_shadow_color; ///< shadow color
diff --git a/src/FbTk/TextButton.cc b/src/FbTk/TextButton.cc
index c31e3d6..33a2b44 100644
--- a/src/FbTk/TextButton.cc
+++ b/src/FbTk/TextButton.cc
@@ -23,6 +23,7 @@
23#include "TextUtils.hh" 23#include "TextUtils.hh"
24#include "Font.hh" 24#include "Font.hh"
25#include "GContext.hh" 25#include "GContext.hh"
26#include <cstdio>
26 27
27namespace FbTk { 28namespace FbTk {
28 29
@@ -62,16 +63,18 @@ void TextButton::setJustify(FbTk::Justify just) {
62} 63}
63 64
64bool TextButton::setOrientation(FbTk::Orientation orient) { 65bool TextButton::setOrientation(FbTk::Orientation orient) {
66
65 if (orient == m_orientation 67 if (orient == m_orientation
66 || !m_font->validOrientation(orient)) 68 || !m_font->validOrientation(orient))
67 return false; 69 return false;
70
68 invalidateBackground(); 71 invalidateBackground();
69 72
70 if (((m_orientation == FbTk::ROT0 || m_orientation == FbTk::ROT180) && 73 if (((m_orientation == FbTk::ROT0 || m_orientation == FbTk::ROT180) &&
71 (orient == FbTk::ROT90 || orient == FbTk::ROT270)) || 74 (orient == FbTk::ROT90 || orient == FbTk::ROT270)) ||
72 ((m_orientation == FbTk::ROT90 || m_orientation == FbTk::ROT270) && 75 ((m_orientation == FbTk::ROT90 || m_orientation == FbTk::ROT270) &&
73 (orient == FbTk::ROT0 || orient == FbTk::ROT180))) { 76 (orient == FbTk::ROT0 || orient == FbTk::ROT180))) {
74 // flip width and height 77
75 m_orientation = orient; 78 m_orientation = orient;
76 resize(height(), width()); 79 resize(height(), width());
77 } else { 80 } else {
@@ -112,8 +115,7 @@ void TextButton::setTextPadding(unsigned int padding) {
112 115
113/// clear window and redraw text 116/// clear window and redraw text
114void TextButton::clear() { 117void TextButton::clear() {
115 TextButton::clearArea(0, 0, 118 TextButton::clearArea(0, 0, width(), height());
116 width(), height());
117} 119}
118 120
119void TextButton::clearArea(int x, int y, 121void TextButton::clearArea(int x, int y,
@@ -135,34 +137,58 @@ void TextButton::renderForeground(FbWindow &win, FbDrawable &drawable) {
135} 137}
136 138
137void TextButton::drawText(int x_offset, int y_offset, FbDrawable *drawable) { 139void TextButton::drawText(int x_offset, int y_offset, FbDrawable *drawable) {
140
141 if (drawable == 0)
142 drawable = this;
143
138 const FbString& visual = text().visual(); 144 const FbString& visual = text().visual();
139 unsigned int textlen = visual.size(); 145 unsigned int textlen = visual.size();
140 unsigned int textw = width(); 146 unsigned int button_width = width();
141 unsigned int texth = height(); 147 unsigned int button_height = height();
142 translateSize(m_orientation, textw, texth); 148
149 translateSize(m_orientation, button_width, button_height);
143 150
144 int align_x = FbTk::doAlignment(textw - x_offset - m_left_padding - m_right_padding, 151 // horizontal alignment, cut off text if needed
152 int align_x = FbTk::doAlignment(button_width - x_offset - m_left_padding - m_right_padding,
145 bevel(), justify(), font(), 153 bevel(), justify(), font(),
146 visual.data(), visual.size(), 154 visual.data(), visual.size(),
147 textlen); // return new text len 155 textlen); // return new text len
148 156
149 // center text by default 157 //
150 int center_pos = texth/2 + font().ascent()/2 - 1; 158 // we center the text vertically. to do this we have to nudge the
151 159 // baseline a little bit down so the "middle" of the glyph is placed
152 int textx = align_x + x_offset + m_left_padding; 160 // on the middle of the button. we "assume", that ascent/2 is roughly
153 int texty = center_pos + y_offset; 161 // the middle of the glyph. example:
154 162 //
155 if (drawable == 0) 163 // +== ascent <--------->== +=====================
156 drawable = this; 164 // | | | |
165 // | | ggggg | | ascent <--------->
166 // | | g gg | | | |
167 // | baseline < glyph | | | ggggg |
168 // | | g | -- middle of button -- | | g gg |
169 // | descent < ggggg | | baseline < glyph |
170 // | height |_________| | | g |
171 // | | descent < ggggg |
172 // | | height |_________|
173 // | |
174 // +======================= +=====================
175 //
176 // ascent = 4
177 // button_height = 11
178 // baseline = (11 + 4) / 2 - 1 = 6
179 //
180
181 int baseline_x = align_x + x_offset + m_left_padding;
182 int baseline_y = ((button_height + font().ascent()) / 2) - 1 + y_offset;
183
184 // TODO: remove debug output fprintf(stderr, "%d | %d %d %d\n", height(), font().height(), font().ascent(), font().descent());
157 185
158 // give it ROT0 style coords 186 // give it ROT0 style coords
159 translateCoords(m_orientation, textx, texty, textw, texth); 187 translateCoords(m_orientation, baseline_x, baseline_y, button_width, button_height);
160 188
161 font().drawText(*drawable, 189 font().drawText(*drawable, screenNumber(), gc(),
162 screenNumber(), 190 visual.c_str(), textlen,
163 gc(), // graphic context 191 baseline_x, baseline_y, m_orientation);
164 visual.c_str(), textlen, // string and string size
165 textx, texty, m_orientation); // position
166} 192}
167 193
168 194
@@ -170,15 +196,15 @@ bool TextButton::textExceeds(int x_offset) {
170 196
171 const FbString& visual = text().visual(); 197 const FbString& visual = text().visual();
172 unsigned int textlen = visual.size(); 198 unsigned int textlen = visual.size();
173 unsigned int textw = width(); 199 unsigned int button_width = width();
174 unsigned int texth = height(); 200 unsigned int button_height = height();
175 translateSize(m_orientation, textw, texth); 201 translateSize(m_orientation, button_width, button_height);
176 202
177 FbTk::doAlignment(textw - x_offset - m_left_padding - m_right_padding, 203 FbTk::doAlignment(button_width - x_offset - m_left_padding - m_right_padding,
178 bevel(), justify(), font(), visual.data(), visual.size(), 204 bevel(), justify(), font(), visual.data(), visual.size(),
179 textlen); // return new text len 205 textlen); // return new text len
180 206
181 return visual.size()>textlen; 207 return visual.size() > textlen;
182} 208}
183 209
184void TextButton::exposeEvent(XExposeEvent &event) { 210void TextButton::exposeEvent(XExposeEvent &event) {
diff --git a/src/FbTk/TextButton.hh b/src/FbTk/TextButton.hh
index a1c8b0e..eb0beca 100644
--- a/src/FbTk/TextButton.hh
+++ b/src/FbTk/TextButton.hh
@@ -56,7 +56,8 @@ public:
56 56
57 void exposeEvent(XExposeEvent &event); 57 void exposeEvent(XExposeEvent &event);
58 58
59 void renderForeground(FbDrawable &drawable); 59 //void renderForeground(FbDrawable &drawable);
60 void renderForeground(FbWindow &win, FbDrawable &drawable);
60 61
61 FbTk::Justify justify() const { return m_justify; } 62 FbTk::Justify justify() const { return m_justify; }
62 const BiDiString &text() const { return m_text; } 63 const BiDiString &text() const { return m_text; }
@@ -65,7 +66,6 @@ public:
65 unsigned int textWidth() const; 66 unsigned int textWidth() const;
66 int bevel() const { return m_bevel; } 67 int bevel() const { return m_bevel; }
67 68
68 void renderForeground(FbWindow &win, FbDrawable &drawable);
69 69
70protected: 70protected:
71 virtual void drawText(int x_offset, int y_offset, FbDrawable *drawable_override); 71 virtual void drawText(int x_offset, int y_offset, FbDrawable *drawable_override);
diff --git a/src/Toolbar.cc b/src/Toolbar.cc
index 1c22440..f46b9e9 100644
--- a/src/Toolbar.cc
+++ b/src/Toolbar.cc
@@ -170,14 +170,12 @@ Toolbar::Frame::Frame(FbTk::EventHandler &evh, int screen_num):
170{ 170{
171 171
172 FbTk::EventManager &evm = *FbTk::EventManager::instance(); 172 FbTk::EventManager &evm = *FbTk::EventManager::instance();
173 // add windows to eventmanager
174 evm.add(evh, window); 173 evm.add(evh, window);
175 174
176} 175}
177 176
178Toolbar::Frame::~Frame() { 177Toolbar::Frame::~Frame() {
179 FbTk::EventManager &evm = *FbTk::EventManager::instance(); 178 FbTk::EventManager &evm = *FbTk::EventManager::instance();
180 // remove windows from eventmanager
181 evm.remove(window); 179 evm.remove(window);
182} 180}
183 181
diff --git a/src/tests/testFont.cc b/src/tests/testFont.cc
index 1ba63f7..3fdc0a6 100644
--- a/src/tests/testFont.cc
+++ b/src/tests/testFont.cc
@@ -19,13 +19,16 @@
19// DEALINGS IN THE SOFTWARE. 19// DEALINGS IN THE SOFTWARE.
20 20
21#include "FbTk/App.hh" 21#include "FbTk/App.hh"
22#include "FbTk/FbString.hh"
22#include "FbTk/FbWindow.hh" 23#include "FbTk/FbWindow.hh"
23#include "FbTk/Font.hh" 24#include "FbTk/Font.hh"
25#include "FbTk/TextButton.hh"
24#include "FbTk/EventHandler.hh" 26#include "FbTk/EventHandler.hh"
25#include "FbTk/EventManager.hh" 27#include "FbTk/EventManager.hh"
26#include "FbTk/GContext.hh" 28#include "FbTk/GContext.hh"
27#include "FbTk/Color.hh" 29#include "FbTk/Color.hh"
28#include "FbTk/FbString.hh" 30#include "FbTk/FbString.hh"
31#include "FbTk/StringUtil.hh"
29 32
30#include <X11/Xutil.h> 33#include <X11/Xutil.h>
31#include <X11/keysym.h> 34#include <X11/keysym.h>
@@ -34,124 +37,103 @@
34#include <cstring> 37#include <cstring>
35#include <cstdlib> 38#include <cstdlib>
36#include <iostream> 39#include <iostream>
40#include <vector>
37using namespace std; 41using namespace std;
38 42
39class App:public FbTk::App, public FbTk::EventHandler { 43
44class App:public FbTk::App, public FbTk::FbWindow, public FbTk::EventHandler {
40public: 45public:
41 App(const char *displayname, const string &foreground, const string background): 46 App(const char *displayname, const string& foreground, const string& background):
42 FbTk::App(displayname), 47 FbTk::App(displayname),
43 m_win(DefaultScreen(display()), 48 FbTk::FbWindow(DefaultScreen(this->FbTk::App::display()), 0, 0, 640, 480, KeyPressMask|ExposureMask|StructureNotifyMask),
44 0, 0, 640, 480, KeyPressMask | ExposureMask) { 49 m_gc(drawable()),
45 m_background = background; 50 m_foreground(foreground.c_str(), screenNumber()),
46 m_foreground = foreground; 51 m_background(background.c_str(), screenNumber()) {
47 m_orient = FbTk::ROT0; 52
48 m_win.show(); 53 m_gc.setLineAttributes(1, FbTk::GContext::JOINMITER, FbTk::GContext::LINESOLID, FbTk::GContext::CAPNOTLAST);
49 m_win.setBackgroundColor(FbTk::Color(background.c_str(), m_win.screenNumber())); 54 m_gc.setForeground(m_foreground);
50 FbTk::EventManager::instance()->add(*this, m_win); 55 m_gc.setBackground(m_background);
51 } 56 setBackgroundColor(m_background);
52 ~App() { 57
58 FbTk::EventManager::instance()->add(*this, *this);
53 } 59 }
60
61 ~App() { }
62
54 void keyPressEvent(XKeyEvent &ke) { 63 void keyPressEvent(XKeyEvent &ke) {
55 KeySym ks; 64 KeySym ks;
56 char keychar[1]; 65 char keychar[1];
57 XLookupString(&ke, keychar, 1, &ks, 0); 66 XLookupString(&ke, keychar, 1, &ks, 0);
58 if (ks == XK_Escape) 67 if (ks == XK_Escape) {
59 end(); 68 end();
60 /* 69 }
61 else { // toggle antialias
62 m_font.setAntialias(!m_font.isAntialias());
63 cerr<<boolalpha;
64 cerr<<"antialias: "<<m_font.isAntialias()<<endl;
65 redraw();
66 } */
67 } 70 }
68 71
72 virtual void handleEvent(XEvent& event) {
73 if (event.type == ConfigureNotify) {
74 resize(event.xconfigure.width, event.xconfigure.height);
75 }
76 }
77
78
69 void exposeEvent(XExposeEvent &event) { 79 void exposeEvent(XExposeEvent &event) {
70 redraw(); 80 redraw();
71 } 81 }
72 82
73 void redraw() { 83 void redraw() {
74 size_t text_w = m_font.textWidth(m_text.c_str(), m_text.size()); 84 size_t i;
75 int mult = 1; 85 for (i = 0; i < m_buttons.size(); ++i) {
76 if (m_orient == FbTk::ROT180) 86 FbTk::TextButton* b = m_buttons[i];
77 mult = -1; 87 b->clear();
78 size_t text_h = m_font.height(); 88 b->drawLine(m_gc.gc(), 0, b->height() / 2, b->width(), b->height() / 2);
79 int x = 640/2 - mult* text_w/2;
80 int y = 480/2 - mult*text_h/2;
81 m_win.clear();
82 FbTk::GContext wingc(m_win.drawable());
83
84 int bx1 = 0;
85 int by1 = 0;
86 int bx2 = text_w;
87 int by2 = 0;
88
89 switch (m_orient) {
90 case FbTk::ROT90:
91 by2 = bx2;
92 bx2 = 0;
93 break;
94 case FbTk::ROT180:
95 bx2 = -bx2;
96 break;
97 case FbTk::ROT270:
98 by2 = -bx2;
99 bx2 = 0;
100 break;
101 default:
102 break;
103 } 89 }
90 this->clear();
91 }
104 92
105/* 93 void resize(unsigned int width, unsigned int height) {
106 m_win.drawLine(wingc.gc(), 94 FbTk::FbWindow::resize(width, height);
107 x, y + m_font.descent(), 95 unsigned w = width / m_buttons.size();
108 x + text_w, y + m_font.descent()); 96 size_t i;
109 m_win.drawLine(wingc.gc(), 97 for (i = 0; i < m_buttons.size(); ++i) {
110 x, y - text_h, 98 m_buttons[i]->moveResize(i * w, 0, w, height);
111 x + text_w, y - text_h); 99 }
112*/ 100 redraw();
113 // draw the baseline in red
114 wingc.setForeground(FbTk::Color("red", m_win.screenNumber()));
115 m_win.drawLine(wingc.gc(),
116 x + bx1, y + by1, x + bx2, y+by2);
117 wingc.setForeground(FbTk::Color(m_foreground.c_str(), m_win.screenNumber()));
118 cerr<<"text size "<<text_w<<"x"<<text_h<<endl;
119 m_font.drawText(m_win,
120 0, wingc.gc(),
121 m_text.c_str(), m_text.size(),
122 x, y, m_orient);
123
124 } 101 }
125 102
126 FbTk::Font &font() { return m_font; } 103 void addText(const FbTk::BiDiString& text, FbTk::Font& font, const FbTk::Orientation orient) {
127 void setText(const std::string& text, const FbTk::Orientation orient) { m_text = text; m_orient = orient; } 104
105 FbTk::FbWindow* win = this;
106 FbTk::TextButton* button = new FbTk::TextButton(*win, font, text);
107
108 button->setGC(m_gc.gc());
109 button->setOrientation(orient);
110 button->setBackgroundColor(m_background);
111 button->show();
112
113 m_buttons.push_back(button);
114 }
128 115
129private: 116private:
130 string m_foreground, m_background; 117 vector<FbTk::TextButton*> m_buttons;
131 FbTk::FbWindow m_win; 118 FbTk::GContext m_gc;
132 FbTk::Font m_font; 119 FbTk::Color m_foreground;
133 FbTk::Orientation m_orient; 120 FbTk::Color m_background;
134 string m_text;
135}; 121};
136 122
123
124
137int main(int argc, char **argv) { 125int main(int argc, char **argv) {
138 //bool antialias = false; 126
127 vector<string> texts_and_fonts;
139 FbTk::Orientation orient = FbTk::ROT0; 128 FbTk::Orientation orient = FbTk::ROT0;
140 bool xft = false;
141 string fontname("");
142 string displayname(""); 129 string displayname("");
143 string background("black"); 130 string background("white");
144 string foreground("white"); 131 string foreground("black");
145 string text("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.-_¯åäöÅÄÖ^~+=`\"!#¤%&/()=¡@£$½¥{[]}¶½§±"); 132
146 for (int a=1; a<argc; ++a) { 133 int a;
147 if (strcmp("-font", argv[a])==0 && a + 1 < argc) { 134 for (a = 1; a < argc; ++a) {
148 fontname = argv[++a]; 135 if (strcmp("-display", argv[a]) == 0 && a + 1 < argc) {
149 } else if (strcmp("-xft", argv[a])==0) {
150 xft = true;
151 } else if (strcmp("-display", argv[a]) == 0 && a + 1 < argc) {
152 displayname = argv[++a]; 136 displayname = argv[++a];
153 } else if (strcmp("-text", argv[a]) == 0 && a + 1 < argc) {
154 text = argv[++a];
155 } else if (strcmp("-orient", argv[a]) == 0) { 137 } else if (strcmp("-orient", argv[a]) == 0) {
156 orient = (FbTk::Orientation) (atoi(argv[++a]) % 4); 138 orient = (FbTk::Orientation) (atoi(argv[++a]) % 4);
157 } else if (strcmp("-bg", argv[a]) == 0 && a + 1 < argc) { 139 } else if (strcmp("-bg", argv[a]) == 0 && a + 1 < argc) {
@@ -159,35 +141,53 @@ int main(int argc, char **argv) {
159 } else if (strcmp("-fg", argv[a]) == 0 && a + 1 < argc) { 141 } else if (strcmp("-fg", argv[a]) == 0 && a + 1 < argc) {
160 foreground = argv[++a]; 142 foreground = argv[++a];
161 } else if (strcmp("-h", argv[a]) == 0) { 143 } else if (strcmp("-h", argv[a]) == 0) {
162 cerr<<"Arguments: "<<endl; 144 cerr<<"Arguments: \"text|fontname\" [\"text|fontname2\"]"<<endl;
163 cerr<<"-font <fontname>"<<endl;
164 // cerr<<"-antialias"<<endl;
165 cerr<<"-display <display>"<<endl; 145 cerr<<"-display <display>"<<endl;
166 cerr<<"-text <text>"<<endl;
167 cerr<<"-orient"<<endl; 146 cerr<<"-orient"<<endl;
168 cerr<<"-fg <foreground color>"<<endl; 147 cerr<<"-fg <foreground color>"<<endl;
169 cerr<<"-bg <background color>"<<endl; 148 cerr<<"-bg <background color>"<<endl;
170 cerr<<"-h"<<endl; 149 cerr<<"-h"<<endl;
171 exit(0); 150 exit(0);
151 } else {
152 texts_and_fonts.push_back(argv[a]);
172 } 153 }
173
174 } 154 }
175
176 155
177 App app(displayname.c_str(), foreground, background); 156 if (texts_and_fonts.empty()) {
178 //app.font().setAntialias(antialias); 157 texts_and_fonts.push_back("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.-_¯åäöÅÄÖ^~+=`\"!#¤%&/()=¡@£$½¥{[]}¶½§±|default");
179 if (!app.font().load(fontname.c_str()))
180 cerr<<"Failed to load: "<<fontname<<endl;
181 if (orient && !app.font().validOrientation(orient)) {
182 cerr<<"Orientation not valid ("<<orient<<")"<<endl;
183 orient = FbTk::ROT0;
184 } 158 }
185 // utf-8 it
186 159
187 cerr<<"Setting text: "<<text<<endl; 160 App app(displayname.c_str(), foreground, background);
188 app.setText(FbTk::FbStringUtil::XStrToFb(text), orient); 161 app.show();
162
163 for (a = 0; a < texts_and_fonts.size(); ++a) {
164
165 vector<string> tf;
166 FbTk::StringUtil::stringtok(tf, texts_and_fonts[a], "|");
167 if (tf.size() < 2) {
168 tf.push_back("default");
169 }
170
171 FbTk::Font* f = new FbTk::Font(0);
172 if (f->load(tf[1])) {
173
174 if (orient && !f->validOrientation(orient)) {
175 cerr<<"Orientation not valid ("<<orient<<")"<<endl;
176 orient = FbTk::ROT0;
177 }
189 178
179 app.addText(FbTk::FbStringUtil::XStrToFb(tf[0]), *f, orient);
180
181 } else {
182 cerr<<"Failed to load: "<<tf[1]<<endl;
183 delete f;
184 }
185 }
186
187 app.resize(app.width(), app.height());
190 app.redraw(); 188 app.redraw();
191 app.eventLoop(); 189 app.eventLoop();
192 190
191 return 0;
193} 192}
193