From 4dace0d93eee428ca92069efd462de3450e955b5 Mon Sep 17 00:00:00 2001
From: aartoni <aartoni_AT_artixlinux.org>
Date: Tue, 19 May 2026 13:55:40 +0200
Subject: [dwm][PATCH] drw: use cap height for optical text centering
The current formula centers the font em box (ascent + descent)
within the drawing area. This assumes visible ink is symmetric
inside that box. Fonts whose ascent includes significant internal
leading above the cap line (e.g. Fira Code: ascent 894, capHeight
1377, upm 1950) cause text to ride above optical center.
Read the cap height by measuring a capital H via XftTextExtents8,
which is already linked. Center the cap height span instead of the
em box. For fonts where the measurement fails (ext.y <= 0), fall
back to 2*ascent - h, which is algebraically equivalent to the old
formula and produces pixel-identical output.
No new dependencies. No change for fonts with symmetric metrics.
---
drw.c | 7 ++++++-
drw.h | 1 +
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/drw.c b/drw.c
index 9fdd1a4..f94c2e6 100644
--- a/drw.c
+++ b/drw.c
_AT_@ -94,6 +94,7 @@ xfont_create(Drw *drw, const char *fontname, FcPattern
*fontpattern)
Fnt *font;
XftFont *xfont = NULL;
FcPattern *pattern = NULL;
+ XGlyphInfo ext;
if (fontname) {
/* Using the pattern found at font->xfont->pattern does not yield the
_AT_@ -123,6 +124,10 @@ xfont_create(Drw *drw, const char *fontname,
FcPattern *fontpattern)
font->xfont = xfont;
font->pattern = pattern;
font->h = xfont->ascent + xfont->descent;
+ font->cap = MAX(xfont->ascent - xfont->descent, 0);
+ XftTextExtents8(drw->dpy, xfont, (FcChar8 *)"H", 1, &ext);
+ if (ext.y > 0)
+ font->cap = ext.y;
font->dpy = drw->dpy;
return font;
_AT_@ -330,7 +335,7 @@ drw_text(Drw *drw, int x, int y, unsigned int w,
unsigned int h, unsigned int lp
if (utf8strlen) {
if (render) {
- ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
+ ty = y + (h + usedfont->cap) / 2;
XftDrawStringUtf8(d, &drw->scheme[invert ? ColBg : ColFg],
usedfont->xfont, x, ty, (XftChar8 *)utf8str,
utf8strlen);
}
diff --git a/drw.h b/drw.h
index bda06f9..eea46ce 100644
--- a/drw.h
+++ b/drw.h
_AT_@ -6,6 +6,7 @@ typedef struct {
typedef struct Fnt {
Display *dpy;
+ unsigned int cap;
unsigned int h;
XftFont *xfont;
FcPattern *pattern;
--
2.54.0
Definitely better now. Thanks!
--
aartoni
Received on Tue May 19 2026 - 16:35:48 CEST