URI:
       [st][patches][fontmetrics] Add new patch - sites - public wiki contents of suckless.org
  HTML git clone git://git.suckless.org/sites
   DIR Log
   DIR Files
   DIR Refs
       ---
   DIR commit 0c6a1c7823c6ff0b616142bc58719f19013e97b1
   DIR parent d893c7ab3871c86248f97d8bb4b8ae3c42a5fa2f
  HTML Author: Paul Storkman <storkman@storkman.nl>
       Date:   Wed, 21 Jan 2026 13:50:02 +0100
       
       [st][patches][fontmetrics] Add new patch
       
       An alternative way to retrieve vertical font metrics.
       
       Diffstat:
         A st.suckless.org/patches/fontmetric… |      26 ++++++++++++++++++++++++++
         A st.suckless.org/patches/fontmetric… |     148 +++++++++++++++++++++++++++++++
       
       2 files changed, 174 insertions(+), 0 deletions(-)
       ---
   DIR diff --git a/st.suckless.org/patches/fontmetrics/index.md b/st.suckless.org/patches/fontmetrics/index.md
       @@ -0,0 +1,26 @@
       +fontmetrics
       +===========
       +
       +Description
       +-----------
       +This patch uses the font metrics provided in a TrueType font's `OS/2` table
       +(see [Microsoft](https://learn.microsoft.com/en-us/typography/opentype/spec/os2)
       +or [Apple](https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6OS2.html) documentation),
       +if available, to determine the character cell height and underline/strike-through thickness and position.
       +This may or may not make the font rendering, particularly block and box-drawing elements, better or worse.
       +
       +`st` normally uses the descent and ascent heights provided by FreeType,
       +which seems to derive them from `hhea` table values.
       +
       +There is no standard for how monotype font files are supposed to communicate correct metrics to terminal emulators,
       +and actual usage is inconsistent between fonts.
       +
       +Download
       +--------
       +
       +- [st-fontmetrics-0.9.3.diff](st-fontmetrics-0.9.3.diff) (0.9.3)
       +
       +Authors
       +-------
       +
       +- Paul Storkman - <storkman@storkman.nl>
   DIR diff --git a/st.suckless.org/patches/fontmetrics/st-fontmetrics-0.9.3.diff b/st.suckless.org/patches/fontmetrics/st-fontmetrics-0.9.3.diff
       @@ -0,0 +1,148 @@
       +From d0d9715e5197a5b8af810508f48db001f54817c3 Mon Sep 17 00:00:00 2001
       +From: Paul Storkman <storkman@storkman.nl>
       +Date: Tue, 4 Nov 2025 17:41:50 +0100
       +Subject: [PATCH] Use vertical font metrics from the "OS/2" table, if possible.
       +
       +---
       + config.def.h | 10 +++++++
       + x.c          | 73 +++++++++++++++++++++++++++++++++++++++++++++++-----
       + 2 files changed, 77 insertions(+), 6 deletions(-)
       +
       +diff --git a/config.def.h b/config.def.h
       +index 2cd740a..e959638 100644
       +--- a/config.def.h
       ++++ b/config.def.h
       +@@ -8,6 +8,16 @@
       + static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true";
       + static int borderpx = 2;
       + 
       ++/* "OS/2" OpenType tables give more accurate typographic metrics for some fonts,
       ++ * which may or may not improve rendering of box-drawing elements.
       ++ */
       ++static int ignoreOS2metrics = 0;
       ++
       ++/* Multiplier applied to the distance between baselines.
       ++ * Increasing this value can misalign block or line-drawing characters.
       ++ */
       ++static float linespacing = 1.0;
       ++
       + /*
       +  * What program is execed by st depends of these precedence rules:
       +  * 1: program passed with -e
       +diff --git a/x.c b/x.c
       +index d73152b..ae07d57 100644
       +--- a/x.c
       ++++ b/x.c
       +@@ -15,6 +15,8 @@
       + #include <X11/Xft/Xft.h>
       + #include <X11/XKBlib.h>
       + 
       ++#include <freetype/tttables.h>
       ++
       + char *argv0;
       + #include "arg.h"
       + #include "st.h"
       +@@ -123,6 +125,10 @@ typedef struct {
       +         int width;
       +         int ascent;
       +         int descent;
       ++        int strike_y;
       ++        int strike_h;
       ++        int underline_y;
       ++        int underline_h;
       +         int badslant;
       +         int badweight;
       +         short lbearing;
       +@@ -969,14 +975,67 @@ xloadfont(Font *f, FcPattern *pattern)
       +         f->set = NULL;
       +         f->pattern = configured;
       + 
       +-        f->ascent = f->match->ascent;
       +-        f->descent = f->match->descent;
       ++        f->ascent = f->match->ascent * linespacing;
       ++        f->descent = f->match->descent * linespacing;
       +         f->lbearing = 0;
       +         f->rbearing = f->match->max_advance_width;
       + 
       +         f->height = f->ascent + f->descent;
       +         f->width = DIVCEIL(extents.xOff, strlen(ascii_printable));
       + 
       ++        f->strike_y = -2 * f->match->ascent / 3;
       ++        f->strike_h = 1;
       ++        f->underline_y = 1;
       ++        f->underline_h = 1;
       ++
       ++        /* Extract proper typographic metrics if available. */
       ++        do {
       ++                TT_OS2 *os2;
       ++                TT_Postscript *post;
       ++                FT_Face face;
       ++                double px, uppx, asc, desc, lgap;
       ++                if (ignoreOS2metrics)
       ++                        break;
       ++                if (FcPatternGetDouble(f->match->pattern,
       ++                                FC_PIXEL_SIZE, 0, &px) != FcResultMatch)
       ++                        break;
       ++
       ++                face = XftLockFace(f->match);
       ++                /* Rerturn value may be NULL. This is not documented. */
       ++                if (!face)
       ++                        break;
       ++                os2 = FT_Get_Sfnt_Table(face, FT_SFNT_OS2);
       ++                if (!os2) {
       ++                        XftUnlockFace(f->match);
       ++                        break;
       ++                }
       ++                uppx = face->units_per_EM / px;
       ++                asc = os2->sTypoAscender / uppx;
       ++                desc = os2->sTypoDescender / uppx;
       ++                lgap = os2->sTypoLineGap / uppx;
       ++                lgap = (asc + desc + lgap) * linespacing - asc - desc;
       ++                post = FT_Get_Sfnt_Table(face, FT_SFNT_POST);
       ++                if (!post) {
       ++                        f->strike_y = -2 * asc / 3;
       ++                } else {
       ++                        f->strike_y = -os2->yStrikeoutPosition / uppx;
       ++                        f->strike_h = os2->yStrikeoutSize / uppx;
       ++                        if (f->strike_h == 0)
       ++                                f->strike_h = 1;
       ++                        f->underline_y = post->underlinePosition / uppx;
       ++                        f->underline_h = post->underlineThickness / uppx;
       ++                        if (f->underline_y == 0)
       ++                                f->underline_y = 1;
       ++                        if (f->underline_h == 0)
       ++                                f->underline_h = f->strike_h;
       ++                }
       ++                XftUnlockFace(f->match);
       ++
       ++                f->ascent = asc + lgap/2;
       ++                f->descent = -desc + lgap/2 + asc - f->ascent;
       ++                f->height = f->ascent + f->descent;
       ++        } while (0);
       ++
       +         return 0;
       + }
       + 
       +@@ -1496,13 +1555,15 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
       + 
       +         /* Render underline and strikethrough. */
       +         if (base.mode & ATTR_UNDERLINE) {
       +-                XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1,
       +-                                width, 1);
       ++                XftDrawRect(xw.draw, fg, winx,
       ++                                winy + (dc.font.ascent + dc.font.underline_y) * chscale,
       ++                                width, dc.font.underline_h);
       +         }
       + 
       +         if (base.mode & ATTR_STRUCK) {
       +-                XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3,
       +-                                width, 1);
       ++                XftDrawRect(xw.draw, fg, winx,
       ++                                winy + (dc.font.ascent + dc.font.strike_y) * chscale - dc.font.strike_h/2,
       ++                                width, dc.font.strike_h);
       +         }
       + 
       +         /* Reset clip to none. */
       +-- 
       +2.49.1
       +