introduce drw_fontset_getwidth_clamp()
authorNRK <nrk@disroot.org>
Wed, 23 Mar 2022 20:00:00 +0000 (02:00 +0600)
committerHiltjo Posthuma <hiltjo@codemadness.org>
Fri, 25 Mar 2022 21:49:07 +0000 (22:49 +0100)
getting the width of a string is an O(n) operation, and in many cases
users only care about getting the width upto a certain number.

instead of calling drw_fontset_getwidth() and *then* clamping the
result, this patch introduces drw_fontset_getwidth_clamp() function,
similar to strnlen(), which will stop once we reach n.

the `invert` parameter was overloaded internally to preserve the API,
however library users should be calling drw_fontset_getwidth_clamp() and
not depend upon internal behavior of drw_text().

drw.c
drw.h

diff --git a/drw.c b/drw.c
index e65d069090edec3546f6c2ee9a8f5f7dc2e396e2..7d985b188407c3e86a5c227530c5dad2fb4f300c 100644 (file)
--- a/drw.c
+++ b/drw.c
@@ -268,7 +268,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
                return 0;
 
        if (!render) {
-               w = ~w;
+               w = invert ? invert : ~invert;
        } else {
                XSetForeground(drw->dpy, drw->gc, drw->scheme[invert ? ColFg : ColBg].pixel);
                XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
@@ -300,7 +300,13 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
 
                                        if (ew + tmpw > w) {
                                                overflow = 1;
-                                               utf8strlen = ellipsis_len;
+                                               /* called from drw_fontset_getwidth_clamp():
+                                                * it wants the width AFTER the overflow
+                                                */
+                                               if (!render)
+                                                       x += tmpw;
+                                               else
+                                                       utf8strlen = ellipsis_len;
                                        } else if (curfont == usedfont) {
                                                utf8strlen += utf8charlen;
                                                text += utf8charlen;
@@ -397,6 +403,15 @@ drw_fontset_getwidth(Drw *drw, const char *text)
        return drw_text(drw, 0, 0, 0, 0, 0, text, 0);
 }
 
+unsigned int
+drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n)
+{
+       unsigned int tmp = 0;
+       if (drw && drw->fonts && text && n)
+               tmp = drw_text(drw, 0, 0, 0, 0, 0, text, n);
+       return MIN(n, tmp);
+}
+
 void
 drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h)
 {
diff --git a/drw.h b/drw.h
index 4c67419a98dd6d87e0b15e6f14094f24aa44c143..fd7631b2ba4a3b3b3734345afae2b80078a8e980 100644 (file)
--- a/drw.h
+++ b/drw.h
@@ -35,6 +35,7 @@ void drw_free(Drw *drw);
 Fnt *drw_fontset_create(Drw* drw, const char *fonts[], size_t fontcount);
 void drw_fontset_free(Fnt* set);
 unsigned int drw_fontset_getwidth(Drw *drw, const char *text);
+unsigned int drw_fontset_getwidth_clamp(Drw *drw, const char *text, unsigned int n);
 void drw_font_getexts(Fnt *font, const char *text, unsigned int len, unsigned int *w, unsigned int *h);
 
 /* Colorscheme abstraction */