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

From: Storkman <storkman_AT_storkman.nl>
Date: Tue, 19 May 2026 18:18:07 +0200

On Tue, May 19, 2026 at 04:35:48PM +0200, Alessio Artoni wrote:
> 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

I was slightly confusing this with st, which just packs lines on top of
each other, and centering anything isn't a concern. (or is it?)

For dwm, the drawing area always has height (ascent + descent + 2).
Is there a guarantee that descent + cap_height == ascent for every font?

In fact, for Fira Code, if we have ascent=1800, descent=600, and cap=1377,
that would put the baseline at 1888.5, with descent up to 2488.5.
That's 88.5 under the box.
Should the bar height then be calculated as (ascent + descent + cap/2)?

> 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.

I just find it difficult to accept that correct code should have a step
like "measure the outline of letter H in particular, and use it as a constant",
but it's probably the simplest way, in terms of LoC.

You could potentially read sCapHeight from the 'OS/2' table through FreeType.
(See: https://st.suckless.org/patches/fontmetrics/st-fontmetrics-0.9.3.diff)

> + font->cap = MAX(xfont->ascent - xfont->descent, 0);
I'd just get rid of this entirely. Unless, like I said, there's some reason
why cap_height must equal (ascent - descent) I'm not getting.

Then...
> - ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
> + ty = y + (h + usedfont->cap) / 2;
Instead:

        if (usedfont->cap)
                ty = y + (h + usedfont->cap) / 2;
        else
                ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;

Even though it is algebraically equivalent, it takes an amount of thinking
to prove that (h + c) / 2 = (h - H) / 2 + A where c = A - D, etc. etc.
But that's a matter of taste.

-- 
Storkman
Received on Tue May 19 2026 - 18:18:07 CEST

This archive was generated by hypermail 2.3.0 : Tue May 19 2026 - 18:24:37 CEST