sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

st-fontmetrics-0.9.3.diff (4173B)


      1 From d0d9715e5197a5b8af810508f48db001f54817c3 Mon Sep 17 00:00:00 2001
      2 From: Paul Storkman <storkman@storkman.nl>
      3 Date: Tue, 4 Nov 2025 17:41:50 +0100
      4 Subject: [PATCH] Use vertical font metrics from the "OS/2" table, if possible.
      5 
      6 ---
      7  config.def.h | 10 +++++++
      8  x.c          | 73 +++++++++++++++++++++++++++++++++++++++++++++++-----
      9  2 files changed, 77 insertions(+), 6 deletions(-)
     10 
     11 diff --git a/config.def.h b/config.def.h
     12 index 2cd740a..e959638 100644
     13 --- a/config.def.h
     14 +++ b/config.def.h
     15 @@ -8,6 +8,16 @@
     16  static char *font = "Liberation Mono:pixelsize=12:antialias=true:autohint=true";
     17  static int borderpx = 2;
     18  
     19 +/* "OS/2" OpenType tables give more accurate typographic metrics for some fonts,
     20 + * which may or may not improve rendering of box-drawing elements.
     21 + */
     22 +static int ignoreOS2metrics = 0;
     23 +
     24 +/* Multiplier applied to the distance between baselines.
     25 + * Increasing this value can misalign block or line-drawing characters.
     26 + */
     27 +static float linespacing = 1.0;
     28 +
     29  /*
     30   * What program is execed by st depends of these precedence rules:
     31   * 1: program passed with -e
     32 diff --git a/x.c b/x.c
     33 index d73152b..ae07d57 100644
     34 --- a/x.c
     35 +++ b/x.c
     36 @@ -15,6 +15,8 @@
     37  #include <X11/Xft/Xft.h>
     38  #include <X11/XKBlib.h>
     39  
     40 +#include <freetype/tttables.h>
     41 +
     42  char *argv0;
     43  #include "arg.h"
     44  #include "st.h"
     45 @@ -123,6 +125,10 @@ typedef struct {
     46  	int width;
     47  	int ascent;
     48  	int descent;
     49 +	int strike_y;
     50 +	int strike_h;
     51 +	int underline_y;
     52 +	int underline_h;
     53  	int badslant;
     54  	int badweight;
     55  	short lbearing;
     56 @@ -969,14 +975,67 @@ xloadfont(Font *f, FcPattern *pattern)
     57  	f->set = NULL;
     58  	f->pattern = configured;
     59  
     60 -	f->ascent = f->match->ascent;
     61 -	f->descent = f->match->descent;
     62 +	f->ascent = f->match->ascent * linespacing;
     63 +	f->descent = f->match->descent * linespacing;
     64  	f->lbearing = 0;
     65  	f->rbearing = f->match->max_advance_width;
     66  
     67  	f->height = f->ascent + f->descent;
     68  	f->width = DIVCEIL(extents.xOff, strlen(ascii_printable));
     69  
     70 +	f->strike_y = -2 * f->match->ascent / 3;
     71 +	f->strike_h = 1;
     72 +	f->underline_y = 1;
     73 +	f->underline_h = 1;
     74 +
     75 +	/* Extract proper typographic metrics if available. */
     76 +	do {
     77 +		TT_OS2 *os2;
     78 +		TT_Postscript *post;
     79 +		FT_Face face;
     80 +		double px, uppx, asc, desc, lgap;
     81 +		if (ignoreOS2metrics)
     82 +			break;
     83 +		if (FcPatternGetDouble(f->match->pattern,
     84 +				FC_PIXEL_SIZE, 0, &px) != FcResultMatch)
     85 +			break;
     86 +
     87 +		face = XftLockFace(f->match);
     88 +		/* Rerturn value may be NULL. This is not documented. */
     89 +		if (!face)
     90 +			break;
     91 +		os2 = FT_Get_Sfnt_Table(face, FT_SFNT_OS2);
     92 +		if (!os2) {
     93 +			XftUnlockFace(f->match);
     94 +			break;
     95 +		}
     96 +		uppx = face->units_per_EM / px;
     97 +		asc = os2->sTypoAscender / uppx;
     98 +		desc = os2->sTypoDescender / uppx;
     99 +		lgap = os2->sTypoLineGap / uppx;
    100 +		lgap = (asc + desc + lgap) * linespacing - asc - desc;
    101 +		post = FT_Get_Sfnt_Table(face, FT_SFNT_POST);
    102 +		if (!post) {
    103 +			f->strike_y = -2 * asc / 3;
    104 +		} else {
    105 +			f->strike_y = -os2->yStrikeoutPosition / uppx;
    106 +			f->strike_h = os2->yStrikeoutSize / uppx;
    107 +			if (f->strike_h == 0)
    108 +				f->strike_h = 1;
    109 +			f->underline_y = post->underlinePosition / uppx;
    110 +			f->underline_h = post->underlineThickness / uppx;
    111 +			if (f->underline_y == 0)
    112 +				f->underline_y = 1;
    113 +			if (f->underline_h == 0)
    114 +				f->underline_h = f->strike_h;
    115 +		}
    116 +		XftUnlockFace(f->match);
    117 +
    118 +		f->ascent = asc + lgap/2;
    119 +		f->descent = -desc + lgap/2 + asc - f->ascent;
    120 +		f->height = f->ascent + f->descent;
    121 +	} while (0);
    122 +
    123  	return 0;
    124  }
    125  
    126 @@ -1496,13 +1555,15 @@ xdrawglyphfontspecs(const XftGlyphFontSpec *specs, Glyph base, int len, int x, i
    127  
    128  	/* Render underline and strikethrough. */
    129  	if (base.mode & ATTR_UNDERLINE) {
    130 -		XftDrawRect(xw.draw, fg, winx, winy + dc.font.ascent * chscale + 1,
    131 -				width, 1);
    132 +		XftDrawRect(xw.draw, fg, winx,
    133 +				winy + (dc.font.ascent + dc.font.underline_y) * chscale,
    134 +				width, dc.font.underline_h);
    135  	}
    136  
    137  	if (base.mode & ATTR_STRUCK) {
    138 -		XftDrawRect(xw.draw, fg, winx, winy + 2 * dc.font.ascent * chscale / 3,
    139 -				width, 1);
    140 +		XftDrawRect(xw.draw, fg, winx,
    141 +				winy + (dc.font.ascent + dc.font.strike_y) * chscale - dc.font.strike_h/2,
    142 +				width, dc.font.strike_h);
    143  	}
    144  
    145  	/* Reset clip to none. */
    146 -- 
    147 2.49.1
    148