Skip to content

Instantly share code, notes, and snippets.

@evocateur
Created March 15, 2009 00:15
Show Gist options
  • Save evocateur/79238 to your computer and use it in GitHub Desktop.
Save evocateur/79238 to your computer and use it in GitHub Desktop.
Fix Consolas's line-height on OS X
#!/bin/bash
#
# Requires ftxdumperfuser from http://developer.apple.com/textfonts/download/
#
# Usage: fixconsolas [files ...]
# When called with no arguments, it attempts to operate on every TrueType
# file in the current directory.
#
# References:
# http://bandes-storch.net/blog/2008/12/21/consolas-controlled/#comment-2042
# http://lists.macromates.com/textmate/2009-March/028282.html
# test for ftxdumperfuser in PATH
ftxdumperfuser &>/dev/null
if [ $? -eq 127 ]; then
echo "The ftxdumperfuser utility was not found!"
echo "Please download and install to continue:"
echo " http://developer.apple.com/textfonts/download/"
exit $?
fi
# protect against spaces in filenames
# hat tip Alexey Blinov
# and http://tldp.org/LDP/abs/html/internalvariables.html#IFSH
IFS=$'\n'
if [ $# -eq 0 ]; then
# when no arguments passed,
# set positional parameters
# to ttf in current directory
set -- $(ls *.[Tt][Tt][Ff])
fi
unset IFS # reset to default
E_NOARGS=85
if [ -z "$1" ]; then
echo "Error: No TrueType font files found!"
echo "Usage: `basename $0` [Consolas.ttf]"
exit $E_NOARGS
fi
ASC="1884" # ascender
DSC="514" # descender, already negative in file
GAP="0" # lineGap
D='[0-9]\{1,\}' # BRE equivalent of PCRE \d+
# iterate through positional parameters
for font
do
# error-checking, what a concept
if [ ! -e "$font" ]; then
echo "$font does not exist."
continue
fi
# dump hhea table
ftxdumperfuser -t hhea "$font" | \
# replace desired values
sed \
-e "/ascender=/s/$D/$ASC/" \
-e "/descender=/s/$D/$DSC/" \
-e "/lineGap=/s/$D/$GAP/" | \
# fuse hhea table back into font
ftxdumperfuser -F -t hhea "$font"
echo "Fixed $font"
done
exit $?
@alpaker
Copy link

alpaker commented Nov 4, 2013

If the names of any of the font files contain spaces, set -- $(ls *.[Tt][Tt][Ff]) won't correctly assign them to positional parameters. You should either weak quote the command substitution or just use globbing directly: set -- *.[Tt][Tt][Ff].

@dev97
Copy link

dev97 commented Apr 30, 2014

Consolas has problems with the line height not just under OSX but on Linux as well. Most programs are computing line height just by summing Freetype's ascender and descender and don't have problems with the line height. But some meticulous programs like rxvt-unicode are also checking the height metric which includes the line gap and have unnaturally big line spacing.

Your script does not work under Linux since it's using proprietary Apple utility, therefore I had to create Linux version of your script which is doing basically the same. I think it's the right place to share it.

NB: I had problem only with the gap (ascender and descender was just fine). Furthermore, with your ascender and descender parameters font is not displayed properly under Linux. Therefore I left those field commented out.

#! /usr/bin/perl

use strict;
use warnings;

use Font::TTF::Font;

die "Usage: $0 font.ttf...\n" unless @ARGV;

foreach my $filename (@ARGV) {
  (my $backup = $filename) =~ s/\.[^.]+$/.bak/
    or die "$0: $filename does not have an extension\n";

  my $f = Font::TTF::Font->open($filename)
    or die "$0: unable to read $filename\n";

  $f->{hhea}->read;
  # $f->{hhea}{Ascender} = 1884;
  # $f->{hhea}{Descender} = 514;
  $f->{hhea}{LineGap} = 0;

  rename $filename, $backup
    or die "$0: can't rename $filename to $backup ($!)\n";

  $f->out($filename)
    or die "$0: can't write $filename\n";
}

@bassu
Copy link

bassu commented Jan 26, 2015

Seems like the latest ftxdumperfuser has bugs.

ftxdumperfuser -t hhea -A f CONSOLAI.TTF

Caught exception inside main(), 'tReturnValue == NULL'
    'Error -88 (tReturnValue == NULL) in file /Volumes/Mahu/Apple/FOLK/FontTools/trunk/ftxdumperfuser/Sources/main.cp, line 1288',
    Source code file '/Volumes/Mahu/Apple/FOLK/FontTools/trunk/ftxdumperfuser/Sources/main.cp', line 1288
    Font '<unknown font>'
    Font file '<unknown container>'

@bassu
Copy link

bassu commented Jan 26, 2015

But luckily the Perl script by @dev97 worked. Had to install Font::TTF module of course and then restart the iTerm after that.

@jrnewell
Copy link

jrnewell commented Mar 31, 2018

In case anyone wants a python solution, this worked for me

import os
import sys

from fontTools import ttLib

def run(argv):
    if len(argv) != 2:
        print("USAGE: %s <font-file>" % argv[0])
        sys.exit(1)

    fontpath = argv[1]
    tt = ttLib.TTFont(fontpath)
    tt['hhea'].lineGap = 0
    tt['hhea'].ascent = 1884
    tt['hhea'].descent = -514
    tt.save(get_nolinegap_filepath(fontpath))

def get_nolinegap_filepath(fontpath):
    fontpath_list = os.path.split(fontpath)
    font_dirname = fontpath_list[0]
    font_basename = fontpath_list[1]
    basepath_list = font_basename.split(".")
    outfile_basename = basepath_list[0] + "-nolinegap." + basepath_list[1]
    return os.path.join(font_dirname, outfile_basename)

if __name__ == '__main__':
    run(sys.argv)

Save as file and install dependency:

pip install fonttools

Will save the output <font-file>-nolinegap.ttf

@erikarvstedt
Copy link

In case anyone wants a python solution...

Awesome, that fixed consolas for me in Emacs/X11, where the glyphs appeared shifted upwards, touching the top of the mode line.
I prefer the following parameters, which fix the shift and only slightly increase the line height:

shift_down = 100
extra_ascent = 100
tt['hhea'].ascent += shift_down + extra_ascent
tt['hhea'].descent += shift_down
# tt['hhea'].lineGap in unchanged

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment