diff options
author | Mathias Gumz <akira at fluxbox dot org> | 2012-10-02 12:24:47 (GMT) |
---|---|---|
committer | Mathias Gumz <akira at fluxbox dot org> | 2012-10-03 08:27:16 (GMT) |
commit | 7b6ab828c7e5453a2720462156d165707935c9ef (patch) | |
tree | 3b641791b20b1994935e149fd7461decb11bef8c /src/FbTk/Font.cc | |
parent | 032a23d1e790c5224194562a837cc80fc157ce9b (diff) | |
download | fluxbox-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/FbTk/Font.cc')
-rw-r--r-- | src/FbTk/Font.cc | 75 |
1 files changed, 48 insertions, 27 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> |
84 | typedef map<string, string> StringMap; | 85 | typedef map<string, string> StringMap; |
85 | typedef StringMap::iterator StringMapIt; | 86 | typedef StringMap::iterator StringMapIt; |
86 | StringMap lookup_map; | ||
87 | 87 | ||
88 | // stores <fontthatworks and the fontimp | 88 | // stores <fontthatworks and the fontimp |
89 | typedef map<string, FbTk::FontImp* > FontCache; | 89 | typedef map<string, FbTk::FontImp* > FontCache; |
90 | typedef FontCache::iterator FontCacheIt; | 90 | typedef FontCache::iterator FontCacheIt; |
91 | FontCache font_cache; | ||
92 | 91 | ||
93 | 92 | ||
94 | void resetEffects(FbTk::Font& font) { | 93 | void 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 | |||
103 | StringMap s_lookup_map; | ||
104 | FontCache s_font_cache; | ||
105 | bool s_multibyte = false; // if the fontimp should be a multibyte font | ||
106 | bool 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 | ||
107 | namespace FbTk { | 113 | namespace FbTk { |
108 | 114 | ||
109 | bool Font::s_multibyte = false; | 115 | const char Font::DEFAULT_FONT[] = "__DEFAULT__"; |
110 | bool Font::s_utf8mode = false; | ||
111 | 116 | ||
112 | 117 | ||
113 | void Font::shutdown() { | 118 | void 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 | ||
133 | bool Font::multibyte() { | ||
134 | return s_multibyte; | ||
135 | } | ||
136 | |||
137 | bool Font::utf8() { | ||
138 | return s_utf8mode; | ||
139 | } | ||
140 | |||
141 | |||
128 | Font::Font(const char *name): | 142 | Font::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 | ||
160 | bool Font::load(const string &name) { | 176 | bool 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 | ||
271 | unsigned int Font::textWidth(const BiDiString &text) const { | ||
272 | return textWidth(text.visual().c_str(), text.visual().size()); | ||
273 | } | ||
274 | |||
254 | unsigned int Font::height() const { | 275 | unsigned int Font::height() const { |
255 | return m_fontimp->height(); | 276 | return m_fontimp->height(); |
256 | } | 277 | } |