How XeTeX Selects Bold Fonts

Share on:

I’ve been using the Linux Libertine fonts with XeTeX for several months now, and while they look beautiful, they for some reason tend to trigger odd quirks about just about every aspect of the typesetting system. One that I’ve been dealing with: the font comes in regular, semibold, and bold weights, but by default XeTeX will use the semibold rather than the bold variant. This is apparently a known issue.

It’s easy enough to fix this by simply specifying the exact bold font to use, say through the fontspec package:

\setmainfont[BoldFont=* Bold]{Linux Libertine O}
But why does XeTeX select the semibold variant by default? I found the answer by looking through the source code of XeTeX, which contains the following code in the file XeTeXFontMgr.cpp:
if (reqBold) {
    // try for more boldness, with the same width and slant
    Font* bestMatch = font;
    if (font->weight < parent->maxWeight) {
        // try to increase weight by 1/2 x (max - min), rounding up
        bestMatch = bestMatchFromFamily(parent,
                font->weight + (parent->maxWeight - parent->minWeight) / 2 + 1,
                font->width, font->slant);
The background information is that each font in a family is assigned a "weight number," which determines how bold the font is. So based on the second-to-last line of code above, XeTeX's algorithm for selecting the bold font is as follows:
  1. Determine the weight of the regular font, and the maximum and minimum weights of the family.
  2. Compute a new bold weight, equal to the regular font's weight plus half the difference between the family's maximum and minimum weights (plus a small number to favor rounding up).
  3. Find the font closest in weight to that computed bold weight.
For Linux Libertine, the regular font has weight 400, the semibold 600, and the bold 700. So the computation would go as follows:
  1. Regular weight = 400; maximum weight = 700; minimum weight = 400.
  2. New bold weight = 400 + (700 – 400) / 2 + 1 = 551
  3. Closest font is semibold, at 600
This algorithm strikes me as a bit odd, since it would result in selecting a more bold font if there is a lighter-than-regular font in the family. In any event, this seems to be how it works.