diff options
author | Mathias Gumz <akira at fluxbox dot org> | 2013-06-18 15:43:28 (GMT) |
---|---|---|
committer | Mathias Gumz <akira at fluxbox dot org> | 2013-06-18 15:43:28 (GMT) |
commit | 118ea25f9d581de6fc2c57dde7b8737cbba6faf4 (patch) | |
tree | c1ade88f6cc1de44c3eab0d7190a57d80e44a236 /src/FbTk/XftFontImp.cc | |
parent | 1f24e6decdc1b34b46565f4e9b76a4b6fa91a063 (diff) | |
download | fluxbox-118ea25f9d581de6fc2c57dde7b8737cbba6faf4.zip fluxbox-118ea25f9d581de6fc2c57dde7b8737cbba6faf4.tar.bz2 |
Speedup overlong text detection
Detecting very long window titles is done via FbTk::TextUtils::doAlignment().
Instead of removing one char from the title at a time to see if it fits into a
given 'max_width', we now use a binary-search like approach to get faster to
the right value. This massively improves the speed for windows with
(arbitrary) long window titles (see bug #1090, javascript
document.title = new Array(4999).join(".");
leads to massive waiting for fluxbox to detect that this window has a very
long title).
In addition to that Xft returns 'wrapped' shorts ('integer overflows') for
long texts: XGlpyhInfo.xOff is declared as signed short, it's able to hold
~32k pixels. A monospace font with font-size 10 produces an integer
overflow after 3276 chars / glyphs, thus rendering the check
if (text_width < max_width) { /* ... */ }
pointless and leading rendering the whole title. By calculating some kind of
upper limit for a pseudo-wide glyph ("WW") and strictly cutting off the input
string at that limit prevents this issue.
Diffstat (limited to 'src/FbTk/XftFontImp.cc')
-rw-r--r-- | src/FbTk/XftFontImp.cc | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/src/FbTk/XftFontImp.cc b/src/FbTk/XftFontImp.cc index 15c8212..9e57349 100644 --- a/src/FbTk/XftFontImp.cc +++ b/src/FbTk/XftFontImp.cc | |||
@@ -23,7 +23,9 @@ | |||
23 | #include "App.hh" | 23 | #include "App.hh" |
24 | #include "FbDrawable.hh" | 24 | #include "FbDrawable.hh" |
25 | 25 | ||
26 | #include <math.h> | 26 | #include <cmath> |
27 | #include <cstdio> | ||
28 | #include <algorithm> | ||
27 | 29 | ||
28 | #ifdef HAVE_CONFIG_H | 30 | #ifdef HAVE_CONFIG_H |
29 | #include "config.h" | 31 | #include "config.h" |
@@ -32,7 +34,7 @@ | |||
32 | namespace FbTk { | 34 | namespace FbTk { |
33 | 35 | ||
34 | XftFontImp::XftFontImp(const char *name, bool utf8): | 36 | XftFontImp::XftFontImp(const char *name, bool utf8): |
35 | m_utf8mode(utf8), m_name("") { | 37 | m_utf8mode(utf8), m_name(""), m_maxlength(0x8000) { |
36 | 38 | ||
37 | for (int r = ROT0; r <= ROT270; r++) { | 39 | for (int r = ROT0; r <= ROT270; r++) { |
38 | m_xftfonts[r] = 0; | 40 | m_xftfonts[r] = 0; |
@@ -74,6 +76,15 @@ bool XftFontImp::load(const std::string &name) { | |||
74 | m_xftfonts_loaded[ROT0] = true; | 76 | m_xftfonts_loaded[ROT0] = true; |
75 | m_name = name; | 77 | m_name = name; |
76 | 78 | ||
79 | // XGlyphInfo (used by XftFontImp::textWidth() / XftTextExtents8() etc) | ||
80 | // holds only type 'short' or 'unsigned short'. any text bigger than that | ||
81 | // yields either some negative or some 'wrapped' values ('integer | ||
82 | // overflow'). to prevent something like this we detect the maximium | ||
83 | // number of glyphs by calculating the amount of 'WW' (pretending a 'wide' | ||
84 | // glyph) fitting into 32k pixels | ||
85 | unsigned int tw = textWidth("WW", 2); | ||
86 | m_maxlength = 0x8000 / tw; | ||
87 | |||
77 | return true; | 88 | return true; |
78 | } | 89 | } |
79 | 90 | ||
@@ -160,6 +171,8 @@ unsigned int XftFontImp::textWidth(const char* text, unsigned int len) const { | |||
160 | 171 | ||
161 | XftFont *font = m_xftfonts[ROT0]; | 172 | XftFont *font = m_xftfonts[ROT0]; |
162 | 173 | ||
174 | len = std::min(len, m_maxlength); | ||
175 | |||
163 | 176 | ||
164 | #ifdef HAVE_XFT_UTF8_STRING | 177 | #ifdef HAVE_XFT_UTF8_STRING |
165 | if (m_utf8mode) { | 178 | if (m_utf8mode) { |