Simplify drawing of bar text
Non-fitting text is truncated by simply cutting it off. win_textwidth() has been replaced by a simple macro wrapper around win_draw_text() with a maximum width of zero, which results in a dry-run that still calculates the number of pixels used by the text, much like snprintf(3) with a buffer length of zero.
This commit is contained in:
parent
3c7d6f3528
commit
e63843d369
85
window.c
85
window.c
|
@ -362,50 +362,45 @@ void win_clear(win_t *win)
|
||||||
XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h);
|
XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
int win_textwidth(const win_env_t *e, const char *text, unsigned int len, bool with_padding, XftFont *fnt)
|
#define TEXTWIDTH(win, text, len) \
|
||||||
|
win_draw_text(win, NULL, NULL, 0, 0, text, len, 0)
|
||||||
|
|
||||||
|
int win_draw_text(win_t *win, XftDraw *d, XftColor *color, int x, int y,
|
||||||
|
char *text, int len, int w)
|
||||||
{
|
{
|
||||||
|
int err, tw = 0;
|
||||||
|
char *t, *next;
|
||||||
|
uint32_t rune;
|
||||||
|
XftFont *f;
|
||||||
|
FcCharSet *fccharset;
|
||||||
XGlyphInfo ext;
|
XGlyphInfo ext;
|
||||||
|
|
||||||
XftTextExtentsUtf8(e->dpy, fnt, (XftChar8*)text, len, &ext);
|
for (t = text; t - text < len; t = next) {
|
||||||
return ext.xOff + (with_padding ? 2 * H_TEXT_PAD : 0);
|
next = utf8_decode(t, &rune, &err);
|
||||||
}
|
if (XftCharExists(win->env.dpy, font, rune)) {
|
||||||
|
f = font;
|
||||||
void win_draw_bar_text(win_t *win, XftDraw *d, XftColor *color, XftFont *font, int x, int y, char *text, int maxlen, int maximum_x)
|
} else { /* fallback font */
|
||||||
{
|
|
||||||
size_t len = 0;
|
|
||||||
int err, xshift = 0, newshift;
|
|
||||||
uint32_t codep;
|
|
||||||
char *p, *nextp;
|
|
||||||
FcCharSet* fccharset;
|
|
||||||
XftFont* fallback = NULL;
|
|
||||||
|
|
||||||
for (p = text; *p && (len < maxlen); p = nextp, len++) {
|
|
||||||
nextp = utf8_decode(p, &codep, &err);
|
|
||||||
if (!XftCharExists(win->env.dpy, font, codep)) {
|
|
||||||
fccharset = FcCharSetCreate();
|
fccharset = FcCharSetCreate();
|
||||||
FcCharSetAddChar(fccharset, codep);
|
FcCharSetAddChar(fccharset, rune);
|
||||||
fallback = XftFontOpen(win->env.dpy, win->env.scr,
|
f = XftFontOpen(win->env.dpy, win->env.scr, FC_CHARSET, FcTypeCharSet,
|
||||||
FC_CHARSET, FcTypeCharSet, fccharset,
|
fccharset, FC_SCALABLE, FcTypeBool, FcTrue, NULL);
|
||||||
FC_SCALABLE, FcTypeBool, FcTrue,
|
|
||||||
NULL);
|
|
||||||
FcCharSetDestroy(fccharset);
|
FcCharSetDestroy(fccharset);
|
||||||
}
|
}
|
||||||
newshift = win_textwidth(&win->env, p, (int) (nextp-p), false, (fallback ? fallback : font));
|
XftTextExtentsUtf8(win->env.dpy, f, (XftChar8*)t, next - t, &ext);
|
||||||
if (xshift + newshift <= maximum_x)
|
tw += ext.xOff;
|
||||||
XftDrawStringUtf8(d, color, (fallback ? fallback : font), x + xshift, y, (XftChar8*)p, (int) (nextp-p));
|
if (tw <= w) {
|
||||||
xshift += newshift;
|
XftDrawStringUtf8(d, color, f, x, y, (XftChar8*)t, next - t);
|
||||||
if (fallback) {
|
x += ext.xOff;
|
||||||
XftFontClose(win->env.dpy, fallback);
|
|
||||||
fallback = NULL;
|
|
||||||
}
|
}
|
||||||
|
if (f != font)
|
||||||
|
XftFontClose(win->env.dpy, f);
|
||||||
}
|
}
|
||||||
|
return tw;
|
||||||
}
|
}
|
||||||
|
|
||||||
void win_draw_bar(win_t *win)
|
void win_draw_bar(win_t *win)
|
||||||
{
|
{
|
||||||
int len, olen, x, y, w, tw, maximum_x;
|
int len, x, y, w, tw;
|
||||||
char rest[3];
|
|
||||||
const char *dots = "...";
|
|
||||||
win_env_t *e;
|
win_env_t *e;
|
||||||
win_bar_t *l, *r;
|
win_bar_t *l, *r;
|
||||||
XftDraw *d;
|
XftDraw *d;
|
||||||
|
@ -415,7 +410,7 @@ void win_draw_bar(win_t *win)
|
||||||
|
|
||||||
e = &win->env;
|
e = &win->env;
|
||||||
y = win->h + font->ascent + V_TEXT_PAD;
|
y = win->h + font->ascent + V_TEXT_PAD;
|
||||||
w = win->w;
|
w = win->w - 2*H_TEXT_PAD;
|
||||||
d = XftDrawCreate(e->dpy, win->buf.pm, DefaultVisual(e->dpy, e->scr),
|
d = XftDrawCreate(e->dpy, win->buf.pm, DefaultVisual(e->dpy, e->scr),
|
||||||
DefaultColormap(e->dpy, e->scr));
|
DefaultColormap(e->dpy, e->scr));
|
||||||
|
|
||||||
|
@ -426,30 +421,16 @@ void win_draw_bar(win_t *win)
|
||||||
XSetBackground(e->dpy, gc, win->bar.bgcol.pixel);
|
XSetBackground(e->dpy, gc, win->bar.bgcol.pixel);
|
||||||
|
|
||||||
if ((len = strlen(r->buf)) > 0) {
|
if ((len = strlen(r->buf)) > 0) {
|
||||||
if ((tw = win_textwidth(e, r->buf, len, true, font)) > w)
|
if ((tw = TEXTWIDTH(win, r->buf, len)) > w)
|
||||||
return;
|
return;
|
||||||
x = win->w - tw + H_TEXT_PAD;
|
x = win->w - tw - H_TEXT_PAD;
|
||||||
w -= tw;
|
w -= tw;
|
||||||
XftDrawStringUtf8(d, &win->bar.fgcol, font, x, y, (XftChar8*)r->buf, len);
|
win_draw_text(win, d, &win->bar.fgcol, x, y, r->buf, len, tw);
|
||||||
}
|
}
|
||||||
if ((len = strlen(l->buf)) > 0) {
|
if ((len = strlen(l->buf)) > 0) {
|
||||||
olen = len;
|
|
||||||
while (len > 0 && (tw = win_textwidth(e, l->buf, len, true, font)) > w)
|
|
||||||
len--;
|
|
||||||
if (len > 0) {
|
|
||||||
maximum_x = w;
|
|
||||||
if (len != olen) {
|
|
||||||
w = strlen(dots);
|
|
||||||
if (len <= w)
|
|
||||||
return;
|
|
||||||
memcpy(rest, l->buf + len - w, w);
|
|
||||||
memcpy(l->buf + len - w, dots, w);
|
|
||||||
}
|
|
||||||
x = H_TEXT_PAD;
|
x = H_TEXT_PAD;
|
||||||
win_draw_bar_text(win, d, &win->bar.fgcol, font, x, y, l->buf, len, maximum_x);
|
w -= 2 * H_TEXT_PAD; /* gap between left and right parts */
|
||||||
if (len != olen)
|
win_draw_text(win, d, &win->bar.fgcol, x, y, l->buf, len, w);
|
||||||
memcpy(l->buf + len - w, rest, w);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
XftDrawDestroy(d);
|
XftDrawDestroy(d);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue