Another Linux Font Rendering Annoyance Solved: Georgia

One of my longest-running annoyances with font rendering under Linux has been that of the Georgia font; it is a modern favourite for rendering serif text as its bolder weight and well-designed hinting. Unfortunately, Georgia has never rendered as well for me under Linux as it did in Windows; I finally put 2 and 2 together and realised why this is the case, and came up with a simple solution to fix my complaint.

Background

As explained in a previous post, I’m using Freetype-2.2.1 and Cairo-1.2.4 compiled with the FIR filter patches to get deliciously smooth fonts (especially at larger font sizes), while using Freetype’s Byte-Code Interpreter for fonts below a certain size (usually around 14 pixels and below) to keep them as crisp and legible as possible—BCI-rendered fonts tend to be narrower whereas FIR-smoothed fonts tend to be wider, and BCI-rendered fonts seldom (if ever) have problems with character kerning, whereas such issues are commonplace with the FIR filter, especially at smaller font sizes.

If you aren’t already doing this, I highly recommend it. Adding the following to your ~/.fonts.conf file:

 <match target="font" >
  <test compare="more" name="pixelsize" qual="all" >
   <double>9</double>
  </test>
  <test compare="less" name="pixelsize" qual="all" >
   <double>13</double>
  </test>
  <edit mode="assign" name="autohint" >
   <bool>false</bool>
  </edit>
 </match>

… Will do the trick. Be sure to have Freetype compiled with the BCI enabled, and both Freetype and Cairo patched and recompiled with the FIR filter patches, or this will look like butt.

The Problem

The issue is highly technical and has everything to do with hinting—which means how fonts “snap” to a grid of pixels to render crisply. The BCI forces fonts to certain integer sizes that are known to render the fonts well on the screen. The FIR filter is less aggressive in enforcing these sizes and tries to accommodate decimal font sizes. This is where the problem comes in: fonts that don’t snap well to the grid render with unsightly artifacts, and Georgia appears to be one of the worst offenders in this regard. Consider the following example:

Georgia rendered at sizes between 14.25 – 15 pixels

This is a screenshot of a Georgia test sheet I created to illustrate the problem. The font sizes shown, from top to bottom, are 14.25, 14.5, 14.75, and 15 pixels, all rendered through Firefox via HTML. Note how the text is rendered differently on all four examples: The first and fourth examples have all of the serifs intact, whereas the second example has a few poorly rendered characters (”h” and “n” on the lower-right), the third having the same problems in addition to the mid-right serif on the “m”. While it seems like a trivial complaint, such omissions can ruin the flow of the font and cause poor kerning between certain characters (like the “na” combiation in lines 2-3).

My solution is simple: Snap Georgia to integer sizes, the same way the BCI does, in the more fragile font heights—again, by editing ~/.fonts.conf:

 <match target="font" >
  <test name="family" qual="any" >
   <string>Georgia</string>
  </test>
  <test compare="less" name="pixelsize" qual="all" >
   <double>14.5</double>
  </test>
  <test compare="more_eq" name="pixelsize" qual="all" >
   <double>13.5</double>
  </test>
  <edit mode="assign" name="pixelsize" >
   <double>14</double>
  </edit>
 </match>

 <match target="font" >
  <test name="family" qual="any" >
   <string>Georgia</string>
  </test>
  <test compare="less" name="pixelsize" qual="all" >
   <double>15.5</double>
  </test>
  <test compare="more_eq" name="pixelsize" qual="all" >
   <double>14.5</double>
  </test>
  <edit mode="assign" name="pixelsize" >
   <double>15</double>
  </edit>
 </match>

Then save and restart Firefox. This is the result:

Georgia at same four sizes, but snapped to nearest pixel.

As you can see, the first line (which is 14.25 pixels) is snapped down to 14, the rest are above the threshold to the next size up and render at 15 pixels. We can tell this is the case because not only are there no problems with “missing” serifs, but also because unlike the first example, the last three lines are of identical length.

I handle Georgia in the same way from 10-16 pixels, so if you want to implement it in the same way you’ll have to fill in the extra gaps in my example above (as I only posted enough to cover what to do between 13.5 and 15.499 pixels).

One last suggestion: If you’ve edited your ~/.fonts.conf file manually at all, you want to protect your changes from accidental erasure. I don’t know about Gnome, but KDE’s Control Centre has a mighty annoying habit of completely rewriting your font configuration file for the slightest change. My suggestion: Get fonts the way you want them, then from a console, run:

chmod 444 ~/.fonts.conf

… To prevent yourself (and others) from accidentally overwriting your font configuration. Remember to make the file writable again before you edit it to make a change. It’s probably also a good idea to make a backup of the file when you get things working the way you want them, as you don’t want to have to figure all those details out again from scratch if you lose the file in six months.

Hope this helps all you font-rendering pedants like me out there!

Leave a Reply