Skip to content

Instantly share code, notes, and snippets.

@CrendKing
Last active October 11, 2024 11:02
Show Gist options
  • Save CrendKing/c162f5a16507d2163d58ee0cf542e695 to your computer and use it in GitHub Desktop.
Save CrendKing/c162f5a16507d2163d58ee0cf542e695 to your computer and use it in GitHub Desktop.
browser-font-fallback.md

This document records my conclusions of experimenting Firefox 68 and Chromium 74 font fallback mechanism on Windows, as dated of the writing time.

Definition of font fallback

Both Firefox and Chromium allow users to configure the desired fonts used for displaying HTML in various languages. The HTML language is specified in the <html lang={lang}> tag. For instance, a Chinese webpage could be written as <html lang="zh"> or more specifically <html lang="zh-CN">. English webpage is <html lang="en"> or simplify lefting out the lang tag (although strongly discouraged by the W3C standard). The per-script font setting in Chromium is unlocked with the Advanced Font Settings extension.

When the webpage specify the font list to be used for certain element in CSS, the browsers will first search its font cache for the target font in declared order. font-family: font-a, font-b will result in font-a to be used if it is installed in the system, or font-b otherwise.

There are 2 cases where the configured fonts to be used.

  1. The font-family is not a concrete font name, but rather a generic family such as sans-serif. In this case, the corresponding font in browser settings is used.
  2. All the fonts in the font-family are missing in the system, or no font-family is given at all. In this case, the standard font family of the browser is used. In Firefox, the standard family is the "Proportional" family for the current html language. In Chromium, it is the "Standard font".

Unfortunately, not every font contains all the required glyphs to display the text. For example, Latin-based fonts do not contain CJK glyphs. If the webpage failed to specify the correct language tag (or missing the tag), the browsers need a mechanism to use fonts from other scripts to fill in the missing glyphs. This mechanism is called font fallback.

Windows font linking

Windows has its own font linking mechanism to resolve missing glyphs in native application. This is a not well documented feature, provided by the traditional GDI architecture as well as the new DirectWrite system. The mechanism works automatically inside the APIs and requires little attention from application developers.

Windows font linking does not provide any user facing configuration interface. All configuration are stored under registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontLink\SystemLink. This document will not include the detail of the registry structure.

Both Firefox and Chromium do NOT use the Windows font linking mechanism. Rather, they have implemented their own different logics to accomplish the task.

Firefox font fallback

Firefox has different algorithm for CJK glyphs and non-CJK glyphs:

non-CJK

non-CJK algorithm is very simple: try all the configured fonts of the given html language. These include both config font.name.{generic}.{language} and the list of config font.name-list.{generic}.{language}.

CJK

CJK is by nature complicated due to the shear number of glyphs, encodings and language variations. Firefox uses a dynamic search algorithm to resolve the glyphs.

  1. Use the configured fonts for the given html language.
  2. Use the configured Japanese (ja) fonts.
  3. Use the configured Korean (ko) fonts.
  4. Use the configured Simplified Chinese (zh-CN) fonts.
  5. Use the configured Traditional Chinese (Hong Kong) (zh-HK) fonts.
  6. Use the configured Traditional Chinese (Taiwan) (zh-TW) fonts.

The algorithm is currently implemented in GetLangPrefs(). In both CJK and non-CJK cases, there is a limit of how many fonts to be searched (32). The script search order is hard coded and thus can't be user configured at the moment.

The advantage of Firefox's fallback algorithm is that, thanks to its dynamic nature, more fonts are searched thus minimizing the chance of user encountering missing glyphs. Additionally, by understanding the search order, users can manipulate the configuration to choose desired fonts for missing glyphs.

The disadvantage is inconsistency: because the search list is hard coded, fonts from certain languages are prioritized for all webpages. For instance, Japanese optimized fonts might be used in tag-missing Korean webpages. Also, since more fonts are tried, the performance might deteriorate.

Chromium font fallback

Unlike Firefox, Chromium chooses a more static approach to search fonts. Instead of dividing CJK cases and going through font list, Chromium hard codes several "core" fonts for each script. Chromium assumes these fonts should always be available, thus only search these fonts. The mapping of script to font can be found in InitializeScriptFontMap(). This mapping cannot be user configured at the moment.

The advantage of this algorithm is simplicity, consistency and performance, at the cost of flexibility and configurability.

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