From e63843d36910308338e442f848c763a02b825933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bert=20M=C3=BCnnich?= Date: Thu, 7 Dec 2017 21:29:41 +0100 Subject: [PATCH] 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. --- window.c | 87 ++++++++++++++++++++++---------------------------------- 1 file changed, 34 insertions(+), 53 deletions(-) diff --git a/window.c b/window.c index b2d72d1..8c233d8 100644 --- a/window.c +++ b/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); } -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; - XftTextExtentsUtf8(e->dpy, fnt, (XftChar8*)text, len, &ext); - return ext.xOff + (with_padding ? 2 * H_TEXT_PAD : 0); -} - -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) -{ - 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)) { + for (t = text; t - text < len; t = next) { + next = utf8_decode(t, &rune, &err); + if (XftCharExists(win->env.dpy, font, rune)) { + f = font; + } else { /* fallback font */ fccharset = FcCharSetCreate(); - FcCharSetAddChar(fccharset, codep); - fallback = XftFontOpen(win->env.dpy, win->env.scr, - FC_CHARSET, FcTypeCharSet, fccharset, - FC_SCALABLE, FcTypeBool, FcTrue, - NULL); + FcCharSetAddChar(fccharset, rune); + f = XftFontOpen(win->env.dpy, win->env.scr, FC_CHARSET, FcTypeCharSet, + fccharset, FC_SCALABLE, FcTypeBool, FcTrue, NULL); FcCharSetDestroy(fccharset); } - newshift = win_textwidth(&win->env, p, (int) (nextp-p), false, (fallback ? fallback : font)); - if (xshift + newshift <= maximum_x) - XftDrawStringUtf8(d, color, (fallback ? fallback : font), x + xshift, y, (XftChar8*)p, (int) (nextp-p)); - xshift += newshift; - if (fallback) { - XftFontClose(win->env.dpy, fallback); - fallback = NULL; + XftTextExtentsUtf8(win->env.dpy, f, (XftChar8*)t, next - t, &ext); + tw += ext.xOff; + if (tw <= w) { + XftDrawStringUtf8(d, color, f, x, y, (XftChar8*)t, next - t); + x += ext.xOff; } + if (f != font) + XftFontClose(win->env.dpy, f); } + return tw; } void win_draw_bar(win_t *win) { - int len, olen, x, y, w, tw, maximum_x; - char rest[3]; - const char *dots = "..."; + int len, x, y, w, tw; win_env_t *e; win_bar_t *l, *r; XftDraw *d; @@ -415,7 +410,7 @@ void win_draw_bar(win_t *win) e = &win->env; 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), DefaultColormap(e->dpy, e->scr)); @@ -426,30 +421,16 @@ void win_draw_bar(win_t *win) XSetBackground(e->dpy, gc, win->bar.bgcol.pixel); 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; - x = win->w - tw + H_TEXT_PAD; + x = win->w - tw - H_TEXT_PAD; 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) { - 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; - win_draw_bar_text(win, d, &win->bar.fgcol, font, x, y, l->buf, len, maximum_x); - if (len != olen) - memcpy(l->buf + len - w, rest, w); - } + x = H_TEXT_PAD; + w -= 2 * H_TEXT_PAD; /* gap between left and right parts */ + win_draw_text(win, d, &win->bar.fgcol, x, y, l->buf, len, w); } XftDrawDestroy(d); }