nsxive63843d
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.
+34 −53
1 file changed
- M window.c +34 −53
| @@ -362,50 +362,45 @@ void win_clear(win_t *win) | |||
| 362 | 362 | XFillRectangle(e->dpy, win->buf.pm, gc, 0, 0, win->buf.w, win->buf.h); | |
| 363 | 363 | } | |
| 364 | 364 | ||
| 365 | − | int win_textwidth(const win_env_t *e, const char *text, unsigned int len, bool with_padding, XftFont *fnt) | |
| 365 | + | #define TEXTWIDTH(win, text, len) \ | |
| 366 | + | win_draw_text(win, NULL, NULL, 0, 0, text, len, 0) | |
| 367 | + | ||
| 368 | + | int win_draw_text(win_t *win, XftDraw *d, XftColor *color, int x, int y, | |
| 369 | + | char *text, int len, int w) | |
| 366 | 370 | { | |
| 371 | + | int err, tw = 0; | |
| 372 | + | char *t, *next; | |
| 373 | + | uint32_t rune; | |
| 374 | + | XftFont *f; | |
| 375 | + | FcCharSet *fccharset; | |
| 367 | 376 | XGlyphInfo ext; | |
| 368 | 377 | ||
| 369 | − | XftTextExtentsUtf8(e->dpy, fnt, (XftChar8*)text, len, &ext); | |
| 370 | − | return ext.xOff + (with_padding ? 2 * H_TEXT_PAD : 0); | |
| 371 | − | } | |
| 372 | − | ||
| 373 | − | 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) | |
| 374 | − | { | |
| 375 | − | size_t len = 0; | |
| 376 | − | int err, xshift = 0, newshift; | |
| 377 | − | uint32_t codep; | |
| 378 | − | char *p, *nextp; | |
| 379 | − | FcCharSet* fccharset; | |
| 380 | − | XftFont* fallback = NULL; | |
| 381 | − | ||
| 382 | − | for (p = text; *p && (len < maxlen); p = nextp, len++) { | |
| 383 | − | nextp = utf8_decode(p, &codep, &err); | |
| 384 | − | if (!XftCharExists(win->env.dpy, font, codep)) { | |
| 378 | + | for (t = text; t - text < len; t = next) { | |
| 379 | + | next = utf8_decode(t, &rune, &err); | |
| 380 | + | if (XftCharExists(win->env.dpy, font, rune)) { | |
| 381 | + | f = font; | |
| 382 | + | } else { /* fallback font */ | |
| 385 | 383 | fccharset = FcCharSetCreate(); | |
| 386 | − | FcCharSetAddChar(fccharset, codep); | |
| 387 | − | fallback = XftFontOpen(win->env.dpy, win->env.scr, | |
| 388 | − | FC_CHARSET, FcTypeCharSet, fccharset, | |
| 389 | − | FC_SCALABLE, FcTypeBool, FcTrue, | |
| 390 | − | NULL); | |
| 384 | + | FcCharSetAddChar(fccharset, rune); | |
| 385 | + | f = XftFontOpen(win->env.dpy, win->env.scr, FC_CHARSET, FcTypeCharSet, | |
| 386 | + | fccharset, FC_SCALABLE, FcTypeBool, FcTrue, NULL); | |
| 391 | 387 | FcCharSetDestroy(fccharset); | |
| 392 | 388 | } | |
| 393 | − | newshift = win_textwidth(&win->env, p, (int) (nextp-p), false, (fallback ? fallback : font)); | |
| 394 | − | if (xshift + newshift <= maximum_x) | |
| 395 | − | XftDrawStringUtf8(d, color, (fallback ? fallback : font), x + xshift, y, (XftChar8*)p, (int) (nextp-p)); | |
| 396 | − | xshift += newshift; | |
| 397 | − | if (fallback) { | |
| 398 | − | XftFontClose(win->env.dpy, fallback); | |
| 399 | − | fallback = NULL; | |
| 389 | + | XftTextExtentsUtf8(win->env.dpy, f, (XftChar8*)t, next - t, &ext); | |
| 390 | + | tw += ext.xOff; | |
| 391 | + | if (tw <= w) { | |
| 392 | + | XftDrawStringUtf8(d, color, f, x, y, (XftChar8*)t, next - t); | |
| 393 | + | x += ext.xOff; | |
| 400 | 394 | } | |
| 395 | + | if (f != font) | |
| 396 | + | XftFontClose(win->env.dpy, f); | |
| 401 | 397 | } | |
| 398 | + | return tw; | |
| 402 | 399 | } | |
| 403 | 400 | ||
| 404 | 401 | void win_draw_bar(win_t *win) | |
| 405 | 402 | { | |
| 406 | − | int len, olen, x, y, w, tw, maximum_x; | |
| 407 | − | char rest[3]; | |
| 408 | − | const char *dots = "..."; | |
| 403 | + | int len, x, y, w, tw; | |
| 409 | 404 | win_env_t *e; | |
| 410 | 405 | win_bar_t *l, *r; | |
| 411 | 406 | XftDraw *d; | |
| @@ -415,7 +410,7 @@ void win_draw_bar(win_t *win) | |||
| 415 | 410 | ||
| 416 | 411 | e = &win->env; | |
| 417 | 412 | y = win->h + font->ascent + V_TEXT_PAD; | |
| 418 | − | w = win->w; | |
| 413 | + | w = win->w - 2*H_TEXT_PAD; | |
| 419 | 414 | d = XftDrawCreate(e->dpy, win->buf.pm, DefaultVisual(e->dpy, e->scr), | |
| 420 | 415 | DefaultColormap(e->dpy, e->scr)); | |
| 421 | 416 | ||
| @@ -426,30 +421,16 @@ void win_draw_bar(win_t *win) | |||
| 426 | 421 | XSetBackground(e->dpy, gc, win->bar.bgcol.pixel); | |
| 427 | 422 | ||
| 428 | 423 | if ((len = strlen(r->buf)) > 0) { | |
| 429 | − | if ((tw = win_textwidth(e, r->buf, len, true, font)) > w) | |
| 424 | + | if ((tw = TEXTWIDTH(win, r->buf, len)) > w) | |
| 430 | 425 | return; | |
| 431 | − | x = win->w - tw + H_TEXT_PAD; | |
| 426 | + | x = win->w - tw - H_TEXT_PAD; | |
| 432 | 427 | w -= tw; | |
| 433 | − | XftDrawStringUtf8(d, &win->bar.fgcol, font, x, y, (XftChar8*)r->buf, len); | |
| 428 | + | win_draw_text(win, d, &win->bar.fgcol, x, y, r->buf, len, tw); | |
| 434 | 429 | } | |
| 435 | 430 | if ((len = strlen(l->buf)) > 0) { | |
| 436 | − | olen = len; | |
| 437 | − | while (len > 0 && (tw = win_textwidth(e, l->buf, len, true, font)) > w) | |
| 438 | − | len--; | |
| 439 | − | if (len > 0) { | |
| 440 | − | maximum_x = w; | |
| 441 | − | if (len != olen) { | |
| 442 | − | w = strlen(dots); | |
| 443 | − | if (len <= w) | |
| 444 | − | return; | |
| 445 | − | memcpy(rest, l->buf + len - w, w); | |
| 446 | − | memcpy(l->buf + len - w, dots, w); | |
| 447 | − | } | |
| 448 | − | x = H_TEXT_PAD; | |
| 449 | − | win_draw_bar_text(win, d, &win->bar.fgcol, font, x, y, l->buf, len, maximum_x); | |
| 450 | − | if (len != olen) | |
| 451 | − | memcpy(l->buf + len - w, rest, w); | |
| 452 | − | } | |
| 431 | + | x = H_TEXT_PAD; | |
| 432 | + | w -= 2 * H_TEXT_PAD; /* gap between left and right parts */ | |
| 433 | + | win_draw_text(win, d, &win->bar.fgcol, x, y, l->buf, len, w); | |
| 453 | 434 | } | |
| 454 | 435 | XftDrawDestroy(d); | |
| 455 | 436 | } | |