Re: [hackers] [dmenu|libsl][PATCH] optimize drw_text() for large stringsa

From: Stein Gunnar Bakkeby <bakkeby_AT_gmail.com>
Date: Tue, 22 Mar 2022 09:36:30 +0100

>
> But I still see the
> prompt getting incorrectly cut off and the ellipsis still don't get
> rendered in case of font change.


I see, you mean in the edge case that there is a font change, but there is
not enough space to add a single utf8 character for that font.

You can just move the ellipsis rendering if statement outside of the if
(utf8strlen) { block.


On Tue, Mar 22, 2022 at 6:54 AM NRK <nrk_AT_disroot.org> wrote:

> On Mon, Mar 21, 2022 at 10:35:21PM +0100, Stein Gunnar Bakkeby wrote:
> > you make some interesting points. I am curious as to what your queueing
> > approach would look like.
> >
> > I played around some more simplifying the ellipsis drawing and removing
> buf
> > as you suggested.
> > This would solve all of the aforementioned problems as far as I can tell,
> > but it can result in a partly drawn
> > emoji for example when the ellipsis cuts it off (which I think is a fair
> > tradeoff).
>
> Hi,
>
> Tried out your last patch, it's simpler indeed. But I still see the
> prompt getting incorrectly cut off and the ellipsis still don't get
> rendered in case of font change.
>
> The queue patch solves the above problems, but as I've said it's quite
> messy. I was planning to move everything over to the queue so that we
> won't need to special case anything during string drawing.
>
> But after looking at your current patch, I've scraped that idea. It's
> simpler to just draw on top of the problem cases, overwriting them
> instead.
>
> The following diff fixes pretty much every problem for me. The
> performance is better and I don't notice any problems with truncating.
> Let me know if there's still some edge case unhandled.
>
> - NRK
>
> diff --git a/drw.c b/drw.c
> index 4cdbcbe..8595a69 100644
> --- a/drw.c
> +++ b/drw.c
> _AT__AT_ -251,12 +251,10 @@ drw_rect(Drw *drw, int x, int y, unsigned int w,
> unsigned int h, int filled, int
> int
> drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned
> int lpad, const char *text, int invert)
> {
> - char buf[1024];
> - int ty;
> - unsigned int ew;
> + int ty, ellipsis_x = 0;
> + unsigned int tmpw, ew, ellipsis_w, ellipsis_len;
> XftDraw *d = NULL;
> Fnt *usedfont, *curfont, *nextfont;
> - size_t i, len;
> int utf8strlen, utf8charlen, render = x || y || w || h;
> long utf8codepoint = 0;
> const char *utf8str;
> _AT__AT_ -264,7 +262,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w,
> unsigned int h, unsigned int lp
> FcPattern *fcpattern;
> FcPattern *match;
> XftResult result;
> - int charexists = 0;
> + int charexists = 0, overflow = 0;
>
> if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
> return 0;
> _AT__AT_ -282,8 +280,9 @@ drw_text(Drw *drw, int x, int y, unsigned int w,
> unsigned int h, unsigned int lp
> }
>
> usedfont = drw->fonts;
> + drw_font_getexts(usedfont, "...", 3, &ellipsis_w, NULL);
> while (1) {
> - utf8strlen = 0;
> + ew = ellipsis_len = utf8strlen = 0;
> utf8str = text;
> nextfont = NULL;
> while (*text) {
> _AT__AT_ -291,9 +290,19 @@ drw_text(Drw *drw, int x, int y, unsigned int w,
> unsigned int h, unsigned int lp
> for (curfont = drw->fonts; curfont; curfont =
> curfont->next) {
> charexists = charexists ||
> XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
> if (charexists) {
> - if (curfont == usedfont) {
> + drw_font_getexts(curfont, text,
> utf8charlen, &tmpw, NULL);
> + if (ew + ellipsis_w <= w) {
> + ellipsis_x = x + ew;
> + ellipsis_len = utf8strlen;
> + }
> +
> + if (ew > w) {
> + overflow = 1;
> + utf8strlen = ellipsis_len;
> + } else if (curfont == usedfont) {
> utf8strlen += utf8charlen;
> text += utf8charlen;
> + ew += tmpw;
> } else {
> nextfont = curfont;
> }
> _AT__AT_ -301,36 +310,25 @@ drw_text(Drw *drw, int x, int y, unsigned int w,
> unsigned int h, unsigned int lp
> }
> }
>
> - if (!charexists || nextfont)
> + if (overflow || !charexists || nextfont)
> break;
> else
> charexists = 0;
> }
>
> if (utf8strlen) {
> - drw_font_getexts(usedfont, utf8str, utf8strlen,
> &ew, NULL);
> - /* shorten text if necessary */
> - for (len = MIN(utf8strlen, sizeof(buf) - 1); len
> && ew > w; len--)
> - drw_font_getexts(usedfont, utf8str, len,
> &ew, NULL);
> -
> - if (len) {
> - memcpy(buf, utf8str, len);
> - buf[len] = '\0';
> - if (len < utf8strlen)
> - for (i = len; i && i > len - 3;
> buf[--i] = '.')
> - ; /* NOP */
> -
> - if (render) {
> - ty = y + (h - usedfont->h) / 2 +
> usedfont->xfont->ascent;
> - XftDrawStringUtf8(d,
> &drw->scheme[invert ? ColBg : ColFg],
> - usedfont->xfont,
> x, ty, (XftChar8 *)buf, len);
> - }
> - x += ew;
> - w -= ew;
> + if (render) {
> + ty = y + (h - usedfont->h) / 2 +
> usedfont->xfont->ascent;
> + XftDrawStringUtf8(d, &drw->scheme[invert ?
> ColBg : ColFg],
> + usedfont->xfont, x, ty,
> (XftChar8 *)utf8str, utf8strlen);
> }
> + x += ew;
> + w -= ew;
> }
> + if (render && overflow)
> + drw_text(drw, ellipsis_x, y, ellipsis_w, h, 0,
> "...", invert);
>
> - if (!*text) {
> + if (overflow || !*text) {
> break;
> } else if (nextfont) {
> charexists = 0;
>
>
>
Received on Tue Mar 22 2022 - 09:36:30 CET

This archive was generated by hypermail 2.3.0 : Tue Mar 22 2022 - 13:36:38 CET