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:
- 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). - Contextual Substitution: HarfBuzz queries the
font's
GSUBtable using these state tags, swapping the default Unicode characters for their positional glyph variants so the letters visually connect. - Ligature Formation: HarfBuzz applies the
rlig(Required Ligatures) andliga(Standard Ligatures) OpenType features. For example, when the Arabic letter Lam is followed by Alef, HarfBuzz usesrligto fuse the two separate characters into the mandatory Lam-Alef ligature glyph. - Diacritic Placement: Short vowels and pronunciation
marks are placed using the
GPOStable. HarfBuzz uses themark(Mark-to-Base) feature to anchor a diacritic to a base letter or ligature, and themkmk(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:
- 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.
- 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.
- Conjunct Ligature Formation: When consonants are
joined by a Halant (which suppresses the inherent vowel), HarfBuzz
executes a strict sequence of
GSUBfeatures 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).cjctandpres: Fuses the remaining half-forms and base consonants into a single complex conjunct glyph.
- Matra and Mark Attachment: Finally, HarfBuzz uses
GPOSlookups (abvmfor above-base marks,blwmfor 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.
- 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.
- 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 (
ccmpandliga) in theGSUBtable 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. - Vertical Stacking: HarfBuzz applies
GPOSmarkandmkmkfeatures 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.