Forum How do I...?

Font fallback doesn't happen for generic fonts if specifying individual styles/weights

jez
Is there a way to redefine the generic fonts such that I can specify to render `font-weight: bold;` with the Semibold style, while still inheriting all the fallback fonts for various unicode characters not present in that font?

I want to Redefine the generic font families in a document. Specifically, I want to specify that the meaning of
font-family: serif;
font-weight: bold;

is typeset using the Semibold style of the font family, not the Bold style. If I just do
@font-face {
  font-family: serif;
  src: local("Crimson Pro");
}

to redefine the generic fallback font using the `local()` functional expression, it picks the Bold style of the font for `font-weight: bold;` text, as evidenced by `pdffonts` (from the Poppler package):
❯ pdffonts example.pdf
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
PXAAAA+CrimsonPro-Regular            Type 1C           MacRoman         yes yes no      11  0
PXAAAB+ArialUnicodeMS                TrueType          WinAnsi          yes yes yes     12  0
PXAAAC+CrimsonPro-Bold               Type 1C           MacRoman         yes yes no      13  0
PXAAAD+CrimsonPro-Italic             Type 1C           MacRoman         yes yes no      14  0
PXAAAE+CrimsonPro-BoldItalic         Type 1C           MacRoman         yes yes no      15  0

I can get it to pick the Semibold styles if I specify the `@font-face` stanzas like this, with the `url()` functional expression (instead of `local()`) and paths to the individual styles I want to use:
@font-face {
  font-family: serif;
  font-style: normal;
  font-weight: normal;
  src: url("CrimsonPro-Regular.otf");
}
@font-face {
  font-family: serif;
  font-style: normal;
  font-weight: bold;
  src: url("CrimsonPro-SemiBold.otf");
}
@font-face {
  font-family: serif;
  font-style: italic;
  font-weight: normal;
  src: url("CrimsonPro-Italic.otf");
}
@font-face {
  font-family: serif;
  font-style: italic;
  font-weight: bold;
  src: url("CrimsonPro-SemiBoldItalic.otf");
}

and now the SemiBold styles are chosen:
❯ pdffonts example.pdf
name                                 type              encoding         emb sub uni object ID
------------------------------------ ----------------- ---------------- --- --- --- ---------
PXAAAA+CrimsonPro-Regular            Type 1C           MacRoman         yes yes no      11  0
PXAAAB+PrinceFallback                TrueType          WinAnsi          yes yes yes     12  0
PXAAAC+CrimsonPro-SemiBold           Type 1C           MacRoman         yes yes no      13  0
PXAAAD+CrimsonPro-Italic             Type 1C           MacRoman         yes yes no      14  0
PXAAAE+CrimsonPro-SemiBoldItalic     Type 1C           MacRoman         yes yes no      15  0

But this makes certain unicode characters fail to render:
❯ prince-books example.html && open example.pdf
prince: page 1: warning: no font for Arrows character U+21A9, fallback to U+2BD1 ⯑
prince: page 1: warning: no font for Arrows character U+21A9, fallback to U+2BD1 ⯑
prince: page 1: warning: no font for Arrows character U+21A9, fallback to U+2BD1 ⯑
prince: page 1: warning: no font for Arrows character U+21A9, fallback to U+2BD1 ⯑


So it seems that redefining the generic fonts and their weights/styles means that I don't benefit from all the fallback `@font-face` declarations in the `fonts.css` file included in the Prince for Books distribution.

  1. example.html1.2 kB
    HTML
  2. example.pdf25.0 kB
    PDF, using semibold but missing glyphs
  3. fallback-font-example.zip228.2 kB
    HTML and font files
wezm
I think the issue is that there is no font available from the default font stack with a glyph for U+21A9. If all the @font-face rules are removed from your example.html I still see the "no font for Arrows character U+21A9" warning. I've also confirmed that CrimsonPro does not have a glyph for U+21A9. To fix this you'll need to add a font with that glyph to the serif font stack.

One option is "Arial Unicode MS" as you identified. Another option that might be better because it's a serif font, and freely available is TeX Gyre Pagella.

To achieve what you originally described (render serif with Crimson Pro Semibold), falling back to Tex Gyre Pagella you could do as shown in the attached files.

  1. example.html1.0 kB
    Example document without missing glyph
  2. example.pdf50.1 kB
    Output from Prince for example.html