[hackers] [dwm][PATCH] drw: use cap height for optical text centering

From: aartoni <aartoni_AT_artixlinux.org>
Date: Tue, 19 May 2026 13:56:39 +0200

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..2fbdbab 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 = xfont->ascent > xfont->descent ? 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
Received on Tue May 19 2026 - 13:56:39 CEST

This archive was generated by hypermail 2.3.0 : Tue May 19 2026 - 14:00:41 CEST