aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNRK <nrk@disroot.org>2022-03-24 00:37:55 +0600
committerHiltjo Posthuma <hiltjo@codemadness.org>2022-03-25 22:49:07 +0100
commit22511c41d55a38a770541ae617a09383d5e6ad1c (patch)
tree2239b8590d3bff0212ccf56e6f3c9fdcefcce5fe
parent77526f756e23e362081ac807521f901f2e5cd5e6 (diff)
drw_text: improve performance when there's no match
this was the last piece of the puzzle, the case where we can't find any font to draw the codepoint. in such cases, we use XftFontMatch() which is INSANELY slow. but that's not the real problem. the real problem was we were continuously trying to match the same thing over and over again. this patch introduces a small cache, which keeps track a couple codepoints for which we know we won't find any matches. with this, i can dump lots of emojies into dmenu where some of them don't have any matching font, and still not have dmenu lag insanely or FREEZE completely when scrolling up and down. this also improves startup time, which will of course depend on the system and all installed fonts; but on my system and test case i see the following startup time drop: before -> after 60ms -> 34ms
-rw-r--r--drw.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/drw.c b/drw.c
index 7d985b1..a50c9ee 100644
--- a/drw.c
+++ b/drw.c
@@ -251,7 +251,7 @@ drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int
251int 251int
252drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert) 252drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert)
253{ 253{
254 int ty, ellipsis_x = 0; 254 int i, ty, ellipsis_x = 0;
255 unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, ellipsis_width; 255 unsigned int tmpw, ew, ellipsis_w = 0, ellipsis_len, ellipsis_width;
256 XftDraw *d = NULL; 256 XftDraw *d = NULL;
257 Fnt *usedfont, *curfont, *nextfont; 257 Fnt *usedfont, *curfont, *nextfont;
@@ -263,6 +263,9 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
263 FcPattern *match; 263 FcPattern *match;
264 XftResult result; 264 XftResult result;
265 int charexists = 0, overflow = 0; 265 int charexists = 0, overflow = 0;
266 /* keep track of a couple codepoints for which we have no match. */
267 enum { nomatches_len = 64 };
268 static struct { long codepoint[nomatches_len]; unsigned int idx; } nomatches;
266 269
267 if (!drw || (render && !drw->scheme) || !text || !drw->fonts) 270 if (!drw || (render && !drw->scheme) || !text || !drw->fonts)
268 return 0; 271 return 0;
@@ -346,6 +349,12 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
346 * character must be drawn. */ 349 * character must be drawn. */
347 charexists = 1; 350 charexists = 1;
348 351
352 for (i = 0; i < nomatches_len; ++i) {
353 /* avoid calling XftFontMatch if we know we won't find a match */
354 if (utf8codepoint == nomatches.codepoint[i])
355 goto no_match;
356 }
357
349 fccharset = FcCharSetCreate(); 358 fccharset = FcCharSetCreate();
350 FcCharSetAddChar(fccharset, utf8codepoint); 359 FcCharSetAddChar(fccharset, utf8codepoint);
351 360
@@ -374,6 +383,8 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
374 curfont->next = usedfont; 383 curfont->next = usedfont;
375 } else { 384 } else {
376 xfont_free(usedfont); 385 xfont_free(usedfont);
386 nomatches.codepoint[++nomatches.idx % nomatches_len] = utf8codepoint;
387no_match:
377 usedfont = drw->fonts; 388 usedfont = drw->fonts;
378 } 389 }
379 } 390 }