FreeType monospace font emboldening

Motivation

2015-02-14 This week a discussion came up on the fontconfig mailing list (not for the first time) about emboldening (bold face synthesis) of monospace fonts.

The problem with it is that FreeType (at least up until 2.5.5) adds a little extra advance width to emboldened glyphs, which helps make them look natural but is less than optimal in a monospace context, as text editors often default to bold-face for syntax highlighting of keywords, and lines that contain such highlighted keywords don't align with the rest of the file.

For illustration, this is a screenshot of 24px Lucida Console in pango-view:

For comparison, the emboldened variant of the same font:

Note the greater advance width of the emboldened variant.

A possible solution

2015-02-14 As pointed out on the mailing list, the well-known Infinality patchset for FreeType 2.4.12 (updated versions may be available, check in the Infinality Forum) contains a fix that applies the original advance width to emboldened glyphs. This is part of the INFINALITY_FT_USE_VARIOUS_TWEAKS feature. Here is the documentation from infinality_settings.sh:

##################################################################
# INFINALITY_FT_USE_VARIOUS_TWEAKS
#
# - Force autohint when no TT instructions present.
# - Artificially embolden horizontally only.
# - When artificially emboldening, maintain the glyph width.
# - Embolden light and thin-stemmed glyphs automatically.
# - Don't sharpen italics. 
#
# Some fonts look bad when stem aligned at certain ppems, no matter
# what. I've put exceptions in to deal with these, included in
# these tweaks.  Georgia and Lucida Grande are examples.
#
#
# Possible values:
# true             - enable tweaks
# false            - do not enable tweaks (do Freetype default)
#
#
# Default if no ENV_VARS present:     false
# Recommended:                        true

export INFINALITY_FT_USE_VARIOUS_TWEAKS=true

As can be seen, the feature enables a number of changes that affect bold face synthesis. These do cause emboldened glyphs to look a little sharper on screen, although only the advance width fix is interesting in this context.

With the Infinality patch applied to FreeType 2.4.12, the example from above looks like this:

Note that it uses the exact same advance width as the regular face:

For comparison again, the standard emboldened variant of the font:

Unfortunately, the change affects all fonts, not just monospace ones. Here is a sample of Corsiva Bold 24px:

Note that the glyphs partially overlap. With standard FreeType 2.4.12 and 2.5.5, it looks like this:

So the goal would be to extract Infinality's fix but apply it only to monospace fonts.

The relevant portion of Infinality's patch seems to be the following section:

diff --git a/src/base/ftsynth.c b/src/base/ftsynth.c
index 241d37f..3d5a593 100644
--- a/src/base/ftsynth.c
+++ b/src/base/ftsynth.c
@@ -141,6 +173,9 @@
 
     slot->metrics.width       += xstr;
     slot->metrics.height      += ystr;
+#ifdef FT_CONFIG_OPTION_INFINALITY_PATCHSET
+    if ( !use_various_tweaks )
+#endif
     slot->metrics.horiAdvance += xstr;
     slot->metrics.vertAdvance += ystr;

It appears that only this check needs to be changed a little. Below is a suggested patch (Download) that I tested with FreeType 2.5.5:

Index: freetype-2.5.5/src/base/ftsynth.c
===================================================================
--- freetype-2.5.5.orig/src/base/ftsynth.c	2014-11-26 18:45:48.000000000 +0100
+++ freetype-2.5.5/src/base/ftsynth.c	2015-02-14 11:46:28.929503116 +0100
@@ -150,7 +150,10 @@
 
     slot->metrics.width        += xstr;
     slot->metrics.height       += ystr;
-    slot->metrics.horiAdvance  += xstr;
+    /* for mono-width fonts (like Andale, Courier, etc.) we need */
+    /* to keep the original advance width                        */
+    if ( !FT_IS_FIXED_WIDTH( face ) )
+      slot->metrics.horiAdvance  += xstr;
     slot->metrics.vertAdvance  += ystr;
     slot->metrics.horiBearingY += ystr;
 
Index: freetype-2.5.5/include/ftsynth.h
===================================================================
--- freetype-2.5.5.orig/include/ftsynth.h	2014-12-02 13:11:52.000000000 +0100
+++ freetype-2.5.5/include/ftsynth.h	2015-02-14 13:12:50.014546469 +0100
@@ -62,8 +62,10 @@
   /* a wrapper for @FT_Outline_Embolden and @FT_Bitmap_Embolden.           */
   /*                                                                       */
   /* For emboldened outlines the height, width, and advance metrics are    */
-  /* increased by the strength of the emboldening.  You can also call      */
-  /* @FT_Outline_Get_CBox to get precise values.                           */
+  /* increased by the strength of the emboldening.  (An exception to this  */
+  /* are mono-width fonts, where the horizontal advance metrics are left   */
+  /* unchanged.)  You can also call @FT_Outline_Get_CBox to get precise    */
+  /* values.                                                               */
   FT_EXPORT( void )
   FT_GlyphSlot_Embolden( FT_GlyphSlot  slot );

(The wording of the comment in ftsynth.c is taken from a similar situation in src/autofit/afloader.c.)

As far as I have been able to test, this applies Infinality's fix to monospace fonts, but keeps the original FreeType appearance of other fonts.


Last change 2015-02-14