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/TextButton.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/TextButton.cc')
-rw-r--r-- | src/FbTk/TextButton.cc | 78 |
1 files changed, 52 insertions, 26 deletions
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 | ||
27 | namespace FbTk { | 28 | namespace FbTk { |
28 | 29 | ||
@@ -62,16 +63,18 @@ void TextButton::setJustify(FbTk::Justify just) { | |||
62 | } | 63 | } |
63 | 64 | ||
64 | bool TextButton::setOrientation(FbTk::Orientation orient) { | 65 | bool 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 |
114 | void TextButton::clear() { | 117 | void TextButton::clear() { |
115 | TextButton::clearArea(0, 0, | 118 | TextButton::clearArea(0, 0, width(), height()); |
116 | width(), height()); | ||
117 | } | 119 | } |
118 | 120 | ||
119 | void TextButton::clearArea(int x, int y, | 121 | void TextButton::clearArea(int x, int y, |
@@ -135,34 +137,58 @@ void TextButton::renderForeground(FbWindow &win, FbDrawable &drawable) { | |||
135 | } | 137 | } |
136 | 138 | ||
137 | void TextButton::drawText(int x_offset, int y_offset, FbDrawable *drawable) { | 139 | void 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 | ||
184 | void TextButton::exposeEvent(XExposeEvent &event) { | 210 | void TextButton::exposeEvent(XExposeEvent &event) { |