How HarfBuzz Handles Complex Ligatures in Chromium

This article provides a technical breakdown of how the HarfBuzz text shaping engine, integrated within the Chromium web browser, processes and renders complex ligatures for Arabic, Indic, and Thai scripts. While simple scripts like Latin generally map one Unicode character directly to one visual glyph, complex scripts require dynamic character reordering, contextual shape shifting, and intricate ligature fusion. HarfBuzz achieves this in Chromium by parsing Unicode text strings, categorizing character clusters through script-specific state machines, and executing rules defined within a font's OpenType tables to output precisely positioned glyphs for the browser to draw.

The Role of HarfBuzz in Chromium

Inside Chromium's Blink rendering engine, text layout is handled by LayoutNG, which passes runs of Unicode text and font data to HarfBuzz. HarfBuzz does not draw text; instead, it converts a sequence of Unicode code points into a sequence of glyph indices with exact X and Y coordinates.

To form ligatures and position characters, HarfBuzz relies heavily on two OpenType font tables:

  • GSUB (Glyph Substitution): Contains rules for replacing one or more glyphs with another glyph (forming ligatures or contextual shapes).
  • GPOS (Glyph Positioning): Contains rules for fine-tuning the exact placement of glyphs, such as attaching vowel marks and tone diacritics to base characters.

Arabic Script: Cursive Joining and Mandatory Ligatures

Arabic is a right-to-left (RTL) cursive script where letters change shape depending on their position within a word. It also utilizes mandatory ligatures and stacked diacritics (harakat). HarfBuzz handles Arabic through the following steps:

  1. Joining Analysis: HarfBuzz analyzes the Unicode string to determine how each character connects to its neighbors. It assigns each character a state: isolated (isol), initial (init), medial (medi), or final (fina).
  2. Contextual Substitution: HarfBuzz queries the font's GSUB table using these state tags, swapping the default Unicode characters for their positional glyph variants so the letters visually connect.
  3. Ligature Formation: HarfBuzz applies the rlig (Required Ligatures) and liga (Standard Ligatures) OpenType features. For example, when the Arabic letter Lam is followed by Alef, HarfBuzz uses rlig to fuse the two separate characters into the mandatory Lam-Alef ligature glyph.
  4. Diacritic Placement: Short vowels and pronunciation marks are placed using the GPOS table. HarfBuzz uses the mark (Mark-to-Base) feature to anchor a diacritic to a base letter or ligature, and the mkmk (Mark-to-Mark) feature to stack multiple diacritics without collision.

Indic Scripts: Syllabification, Reordering, and Conjuncts

Indic scripts (such as Devanagari, Bengali, and Tamil) are abugidas where consonants carry an inherent vowel, and consonant clusters merge into complex ligatures called conjuncts. Furthermore, the logical order in which characters are typed often differs from the visual order in which they are displayed. HarfBuzz uses a dedicated Indic shaper state machine to manage this:

  1. Syllable Identification: HarfBuzz scans the text and groups characters into orthographic syllables using regular-expression-like state machines based on Unicode Indic categories. All shaping happens strictly within the boundaries of these syllables.
  2. Pre-Shaping Reordering: In many Indic scripts, a short 'i' vowel (matra) is typed after a consonant cluster, but visually renders before it. HarfBuzz reorders the glyph buffer in memory, moving pre-base matras to the front of the syllable. Similarly, a Ra followed by a Halant (virama) at the start of a cluster is flagged as a Repha and moved to the end of the syllable to be drawn above the final ligature.
  3. Conjunct Ligature Formation: When consonants are joined by a Halant (which suppresses the inherent vowel), HarfBuzz executes a strict sequence of GSUB features to form ligatures:
    • half: Converts consonants into their "half-forms" before the main base consonant.
    • akhn: Forms Akhand ligatures, which are mandatory, unbreakable consonant fusions (such as Kssa in Devanagari).
    • cjct and pres: Fuses the remaining half-forms and base consonants into a single complex conjunct glyph.
  4. Matra and Mark Attachment: Finally, HarfBuzz uses GPOS lookups (abvm for above-base marks, blwm for below-base marks) to attach vowel signs and nasalization marks to the newly formed conjunct ligature.

Thai Script: Decomposition and Vertical Stacking

Thai does not use spaces between words and features a complex system of vowels and tone marks that stack vertically above and below the base consonant. While Thai does not fuse consonants into conjuncts like Indic scripts, it relies on HarfBuzz for contextual ligature substitution and decomposition to prevent visual overlapping.

  1. Sara Am Decomposition: The Thai vowel Sara Am (ำ) is logically a single Unicode character, but visually consists of a circle (Nikhahit) above the consonant and a Sara Aa beside it. If a word also has a tone mark, the tone mark must sit above the Nikhahit, not the Sara Aa. HarfBuzz automatically decomposes the single Sara Am character into its two constituent parts, reorders the buffer so the tone mark sits right after the Nikhahit, and shapes them correctly.
  2. Collision Avoidance via Substitution: Certain Thai consonants (like Po Pla ป and Fo Fan ฟ) have tall ascenders that collide with upper vowels and tone marks. HarfBuzz triggers contextual substitution (ccmp and liga) in the GSUB table to replace standard tone marks with shorter, shifted variants, or substitutes the consonant itself with a short-tailed glyph variant when followed by a below-base vowel.
  3. Vertical Stacking: HarfBuzz applies GPOS mark and mkmk features to stack upper vowels and tone marks cleanly above the base consonant, dynamically adjusting their height based on the presence of other marks in the same syllable cluster.

Final Output to Chromium

Once HarfBuzz completes the script-specific shaping pipeline, it returns a finalized hb_buffer_t data structure to Chromium. This buffer contains the final ligature glyph IDs and their exact two-dimensional positioning offsets. Chromium then hands this data to the Skia graphics library, which rasterizes the complex script accurately onto the user's screen.