# Universal Shaping Engine script shaping in OpenType # This document details the default shaping procedure needed to display text runs in scripts supported by the Universal Shaping Engine (USE) model. **Contents** - [General information](#general-information) - [Terminology](#terminology) - [Glyph classification](#glyph-classification) - [The USE shaping model](#the-use-shaping-model) - [Stage 1: Split vowel decomposition](#stage-1-split-vowel-decomposition) - [Stage 2: Cluster identification](#stage-2-cluster-identification) - [Stage 3: Basic cluster formation](#stage-3-basic-cluster-formation) - [Stage 3, step 1: Applying the basic pre-processing features from GSUB](#stage-3-step-1-applying-the-basic-pre-processing-features-from-gsub) - [Stage 3, step 2: Applying the basic reordering features from GSUB](#stage-3-step-2-applying-the-basic-reordering-features-from-gsub) - [Stage 3, step 3: Applying the basic orthographic features from GSUB](#stage-3-step-3-applying-the-basic-orthographic-features-from-gsub) - [Stage 4: Glyph reordering](#stage-4-glyph-reordering) - [Stage 4, step 1: Applying the reordering features from GSUB](#stage-4-step-1-applying-the-reordering-features-from-gsub) - [Stage 4, step 2: Performing property-based reordering moves](#stage-4-step-2-performing-property-based-reordering-moves) - [Stage 5: Final feature application](#stage-5-final-feature-application) - [Stage 5, step 1: Applying the final topographic features from GSUB](#stage-5-step-1-applying-the-final-topographic-features-from-gsub) - [Stage 5, step 2: Applying the final typographic-presentation features from GSUB](#stage-5-step-2-applying-the-final-typographic-presentation-features-from-gsub) - [Stage 5, step 3: Applying the final positioning features from GPOS](#stage-5-step-3-applying-the-final-positioning-features-from-gpos) ## General information ## The Universal Shaping Engine (USE) model is used for complex scripts that are not already supported by a dedicated OpenType shaping model. "Complex" scripts, in OpenType shaping terminology, are scripts that require some combination of glyph reordering, contextual joining behavior, or the substitution of context-dependent forms for linguistic or orthographic correctness. The scripts covered by this model include Javanese, Balinese, Buginese, Batak, Chakma, Lepcha, Modi, Phags-pa, Tagalog, Siddham, Sundanese, Tai Le, Tai Tham, Tai Viet, and many others. In many ways, the USE model is a generalization of the [Indic2](opentype-shaping-indic-general.md) OpenType shaping model, with adjustments made to correct shortfalls encountered when using the Indic2 shaping model, as well as additional changes designed to broaden the number of scripts that can be supported. For example, the USE model includes a step applying contextual joining-behavior features as is performed in the Arabic-like shaping model. > Note: The term _Indic3_ is sometimes used in comparison to Indic2 > (or the corresponding increment of the script tags for existing > OpenType shaping models, such as `` in comparison to > ``). > > This terminology either indicates that a shaping engine has > implemented support for one or more of the Indic2 scripts within the > USE model or it is merely a conversational convention to discuss > support for the Indic2-model scripts in USE. > > At the present time, there is no formal definition for an Indic3 > model, and there are not registered OpenType script tags for > `` or any other third generation of the scripts handled by the > Indic2 model. USE was introduced after the release of version 8.0 of the Unicode specification. The intent is for USE to support complex scripts added to future Unicode releases in addition to those already supported. ## Terminology ## The USE shaping model uses a standard set of terms for the features of supported scripts. These terms are similar to the standard terms used for Indic scripts, but with several key distinctions. A **cluster** is the fundamental unit used in shaping; it consists of a sequence of Unicode codepoints that will be processed as an atomic unit. An individual syllable typically corresponds to a single cluster, but any particular cluster might involve multiple syllables or a sequence that does not match the syllable-formation rules of the script. A **base** character in the USE model may be a consonant, an independent vowel, a number, or any of several additional character classes. A cluster's base consonant is generally rendered in its full form (although it may form ligatures), while other consonants in the cluster frequently take on secondary forms. Different GSUB substitutions may apply to a script's **pre-base** and **post-base** consonants. Some of these substitutions create **above-base** or **below-base** forms. The **Reph** form of the consonant "Ra" is an example. A **vowel** character in the USE model is a dependent vowel or any of several additional marks with similar behavior. This class is similar to the "matra" class used in Indic shaping. **Halant** is the standard term for a "vowel-killer" sign. ## Glyph classification ## The USE shaping model classifies characters based on a specific set of properties defined for each codepoint in the Unicode Character Database (UCD), augmented with a small set of pre-defined property overrides. The UCD properties used for USE character classification are: Unicode General Category (UGC) Unicode Indic Syllabic Category (UISC) Unicode Indic Positional Category (UIPC) In addition, the Unicode Character Decomposition Mapping (UCDM) is used for all split vowels. ### USE overrides ### Although, in general, the USE shaping model relies on the UGC, UISC, and UIPC properties, the USE model makes a small set of standardized overrides to the properties of certain specific characters. The following table lists the complete set of USE overrides. Shaping engines should implement the override properties in order to guarantee correct results. > Note: A _null_ in the following table indicates that the > corresponding Unicode property is not overridden for the codepoint > featured in that row. :::{table} Property overrides for USE shaping | Codepoint | Unicode UISC | USE override UISC | Unicode UIPC | USE override UIPC | Glyph | |:----------|:---------------------------|:------------------|:-------------|:------------------|:----------------------------------------| | `U+AA29` | Vowel_Dependent | Bindu | _null_ | _null_ | ꨩ Cham Vowel Sign Aa | | `U+0F71` | Vowel_Dependent | Nukta | _null_ | _null_ | ཱ Tibetan Vowel Sign Aa | | `U+A982` | Consonant_Succeeding_Repha | Tone_Mark | _null_ | _null_ | ꦂ Javanese Sign Layar | | `U+0F7F` | Visarga | Consonant_Dead | _null_ | _null_ | ཿ Tibetan Sign Rnam Bcad | | `U+11134` | Pure_Killer | Gemination_Mark | _null_ | _null_ | 𑄴 Chakma Maayyaa | | `U+0F74` | _null_ | _null_ | Bottom | Top | ུ Tibetan Vowel Sign U | | `U+AA35` | _null_ | _null_ | Bottom | Top | ꨵ Cham Consonant Sign | | `U+1A18` | _null_ | _null_ | Bottom | Top | ᨘ Buginese Vowel Sign U | | `U+0F72` | _null_ | _null_ | Top | Bottom | ི Tibetan Vowel Sign I | | `U+0F7A` | _null_ | _null_ | Top | Bottom | ེ Tibetan Vowel Sign E | | `U+0F7B` | _null_ | _null_ | Top | Bottom | ཻ Tibetan Vowel Sign Ee | | `U+0F7C` | _null_ | _null_ | Top | Bottom | ོ Tibetan Vowel Sign O | | `U+0F7D` | _null_ | _null_ | Top | Bottom | ཽ Tibetan Vowel Sign Oo | | `U+0F80` | _null_ | _null_ | Top | Bottom | ྀ Tibetan Vowel Sign Reversed Ii | | `U+11127` | _null_ | _null_ | Top | Bottom | 𑄧 Chakma Vowel Sign A | | `U+11128` | _null_ | _null_ | Top | Bottom | 𑄨 Chakma Vowel Sign I | | `U+11129` | _null_ | _null_ | Top | Bottom | 𑄩 Chakma Vowel Sign Ii | | `U+1112D` | _null_ | _null_ | Top | Bottom | 𑄭 Chakma Vowel Sign Ai | | `U+11130` | _null_ | _null_ | Top | Bottom | 𑄰 Chakma Vowel Sign Oi | | | | | | | | ::: ### USE classification table ### The following table lists the classes utilized in the USE shaping model, along with a definition for each class. The class definitions refer to the UGC, UISC, and UIPC categories in the Unicode standard, or to specific Unicode codepoints. The symbols given in the "Symbol" column for each class may be used to express cluster-matching rules or other algorithms. Vowels and modifiers may be further subclassified as described in the [USE subclasses table](#use-subclasses-table) below. :::{table} Class definitions for USE shaping | USE classification | Symbol | Definition | |:--------------------------|:-------|:--------------------------------------------------------------------------------------------------------------| | BASE | `B` | UISC = Number _or_ (UISC = Avagraha & UGC = Lo) _or_ (UISC = Bindu & UGC = Lo) _or_ UISC = Consonant _or_ (UISC = Consonant_Final & UGC = Lo) _or_ UISC = Consonant_Head_Letter _or_ (UISC = Consonant_Medial & UGC = Lo) _or_ (UISC = Consonant_Subjoined & UGC = Lo) _or_ UISC = Tone_Letter _or_ (UISC = Vowel & UGC = Lo) _or_ UISC = Vowel_Independent _or_ (UISC = Vowel_Dependent & UGC = Lo) | | Combining grapheme joiner | `CGJ` | `U+034F` | | CONS_MOD | `CM` | UISC = Nukta _or_ Gemination_Mark _or_ Consonant_Killer | | CONS_WITH_STACKER | `CS` | UISC = Consonant_With_Stacker | | CONS_FINAL | `F` | (UISC = Consonant_Final & UGC != Lo) _or_ UISC = Consonant_Succeeding_Repha | | CONS_FINAL_MOD | `FM` | UISC = Syllable_Modifier | | BASE_OTHER | `GB` | UISC = Consonant_Placeholder _or_ `U+2015`, `U+2022`, `U+25FB`–`U+25FE` | | HALANT | `H` | UISC = Virama _or_ Invisible_Stacker | | HALANT_NUM | `HN` | UISC = Number_Joiner | | BASE_IND | `IND` | (UISC = Consonant_Dead _or_ Modifying_Letter) _or_ (UGC = Po != `U+104E`, `U+2022`) _or_ `U+002D` | | CONS_MED | `M` | UISC = Consonant_Medial & UGC != Lo | | BASE_NUM | `N` | UISC = Brahmi_Joining_Number | | OTHER | `O` | Any other SCRIPT_COMMON characters; White space characters, UGC=Zs | | REPHA | `R` | UISC = Consonant_Preceding_Repha _or_ Consonant_Prefixed | | Reserved character | `Rsv` | Any character not currently assigned or otherwise reserved in Unicode | | SYM | `S` | UGC = Sc _or_ (UGC = So & != `U+25CC`) | | SYM_MOD | `SM` | `U+1B6B`, `U+1B6C`, `U+1B6D`, `U+1B6E`, `U+1B6F`, `U+1B70`, `U+1B71`, `U+1B72`, `U+1B73` | | CONS_SUB | `SUB` | UISC = Consonant_Subjoined & UGC != Lo | | VOWEL | `V` | (UISC = Vowel & UGC != Lo) _or_ (UISC = Vowel_Dependent & UGC != Lo) _or_ UISC = Pure_Killer | | VOWEL_MOD | `VM` | (UISC = Bindu & UGC != Lo) _or_ UISC = Tone_Mark _or_ Cantillation_Mark _or_ Register_Shifter _or_ Visarga | | VARIATION_SELECTOR | `VS` | `U+FE00`‒`U+FE0F` | | Word joiner | `WJ` | `U+2060` | | Zero width joiner | `ZWJ` | UISC = Joiner | | Zero width nonjoiner | `ZWNJ` | UISC = Non_Joiner | | | | | ::: ### USE subclasses table ### Vowels and modifiers may be further subclassified based on their position relative to base characters. The subclasses incorporated in the USE shaping model are defined in the table below. Split-vowel subclasses are not assigned a symbol because each split vowel must be decomposed into its components. :::{table} Subclasses for USE shaping | USE classification | Symbol | Definition | |:-----------------------|:--------|:------------------------------------------------------------------------| | CONS_MOD_ABOVE | `CMAbv` | USE=CM & UIPC = Top | | CONS_MOD_BELOW | `CMBlw` | USE=CM & UIPC = Bottom | | CONS_FINAL_ABOVE | `FAbv` | USE=F & UIPC = Top | | CONS_FINAL_BELOW | `FBlw` | USE=F & UIPC = Bottom | | CONS_FINAL_POST | `FPst` | USE=F & UIPC = Right | | CONS_MED_ABOVE | `MAbv` | USE=M & UIPC = Top | | CONS_MED_BELOW | `MBlw` | USE=M & UIPC = Bottom | | CONS_MED_PRE | `MPre` | USE=M & UIPC = Left | | CONS_MED_POST | `MPst` | USE=M & UIPC = Right | | SYM_MOD_ABOVE | `SMAbv` | `U+1B6B`,`U+1B6D`,`U+1B6E`,`U+1B6F`,`U+1B70`,`U+1B71`,`U+1B72`,`U+1B73` | | SYM_MOD_BELOW | `SMBlw` | `U+1B6C` | | VOWEL_ABOVE | `VAbv` | USE=V & UIPC = Top | | VOWEL_ABOVE_BELOW | _null_ | USE=V & UIPC = Top_And_Bottom | | VOWEL_ABOVE_BELOW_POST | _null_ | USE=V & UIPC = Top_And_Bottom_And_Right | | VOWEL_ABOVE_POST | _null_ | USE=V & UIPC = Top_And_Right | | VOWEL_BELOW | `VBlw` | USE=V & UIPC = Bottom _or_ Overstruck | | VOWEL_BELOW_POST | _null_ | USE=V & UIPC = Bottom_And_Right | | VOWEL_PRE | `VPre` | USE=V & UIPC = Left | | VOWEL_PRE_ABOVE | _null_ | USE=V & UIPC = Top_And_Left | | VOWEL_PRE_ABOVE_POST | _null_ | USE=V & UIPC = Top_And_Left_And_Right | | VOWEL_PRE_POST | _null_ | USE=V & UIPC = Left_And_Right | | VOWEL_POST | `VPst` | USE=V & UIPC = Right | | VOWEL_MOD_ABOVE | `VMAbv` | USE=VM & UIPC = Top | | VOWEL_MOD_BELOW | `VMBlw` | USE=VM & UIPC = Bottom _or_ Overstruck | | VOWEL_MOD_PRE | `VMPre` | USE=VM & UIPC = Left | | VOWEL_MOD_POST | `VMPst` | USE=VM & UIPC = Right | | | | | ::: ## The USE shaping model ## The USE shaping model consists of five top-level stages. 1. Decomposition of split vowels 2. Identifying clusters 3. Applying basic cluster formation features 4. Glyph reordering 5. Applying final features All scripts supported by the USE model will be processed in this same pattern. However, not every script requires that actions be taken in every operation. The first two stages take place for the entire text run being shaped. Subsequently, stages 3, 4, and 5 are each conducted in order on a per-cluster basis, until every cluster in the run has been processed. The substitution features from GSUB and the positioning features from GPOS are applied to the text run in predefined features groups. Which features are applied at each step in the process are described below. ### Stage 1: Split vowel decomposition ### Most split vowels have a canonical decomposition defined in the Unicode specification. The USE shaping model requires that all such split vowels be decomposed into their components before any further processing is performed. For these vowels, the canonical decomposition must be performed prior to cluster identification. Because this decomposition is a character-level operation, the shaping engine may choose to perform it earlier, such as during an initial Unicode-normalization stage. For any split vowels that do not have a canonical decomposition, the active font should provide a decomposition via the `ccmp` substitution feature in GSUB. The cluster-identification rules detailed in stage two are based on the canonical decompositions, and do not take non-canonical GSUB decomposition into account. ### Stage 2. Cluster identification ### A cluster in the USE model is defined according to a generalized, visual pattern that is common to all supported scripts. Consequently, the cluster-identification expressions used do not enforce linguistic or orthographic correctness. An independent cluster will consist of a standalone codepoint that does not require further shaping, optionally followed by a variation selector. Independent clusters will match the expression: ```markdown (IND | O | Rsv | WJ) VS? ``` A standard cluster features a required base character and may include many optional elements. Standard clusters will match the expression: ```markdown ( R | CS )? ( B | GB ) VS? CMAbv* CMBlw* ( ((H B) | SUB) VS? CMAbv* CMBlw* )* MPre? MAbv? MBlw? MPst? VPre* VAbv* VBlw* VPst* VMPre* VMAbv* VMBlw* VMPst* FAbv* FBlw* FPst* FM? ``` A halant-terminated cluster occurs when any character other than a `B` follows a `H`. Halant-terminated clusters will match the expression: ```markdown ( R | CS )? (B | GB) VS? CMAbv* CMBlw* ( ((H B) | SUB) VS? CMAbv* CMBlw*)* H ``` A number-joiner–terminated cluster will match the expression: ```markdown N VS? (HN N VS?)* HN ``` A numeral cluster will match the expression: ```markdown N VS? (HN N VS?)* ``` A symbol cluster will match the expression: ```markdown (S | GB) VS? SMAbv* SMBlw* ``` > Note: Practically speaking, shaping engines are highly unlikely to > encounter more than a small number of sequential vowel or modifiers > in any real-world clusters. Thus, implementations may choose to > limit occurrences by limiting some of the above expressions to a > finite length, such as `VPre{0,4}` rather than `VPre*`. The expressions above use state-machine syntax from the Ragel state-machine compiler. The operators represent: ```markdown a* = zero or more copies of a b+ = one or more copies of b c? = optional instance of c d{n} = exactly n copies of d d{,n} = zero to n copies of d d{n,} = n or more copies of d d{n,m} = n to m copies of d !e = not e ^f = character-level not f g.h = concatenation of g and h i|j = i or j ( ) = grouping of expression elements ``` Sequences not matching any of the above expressions should be regarded as broken. The shaping engine may make a best-effort attempt to shape the broken sequence, but making guarantees about the correctness or appearance of the final result is out of scope for this document. After the clusters have been identified, each of the subsequent shaping stages occurs on a per-cluster basis. ### Stage 3: Basic cluster formation ### The basic cluster formation stage is used to apply fundamental substitutions necessary for script and language correctness. #### Stage 3, step 1: Applying the basic pre-processing features from GSUB #### The basic pre-processing step applies mandatory substitution features using the rules in the font's GSUB table. In preparation for this stage, glyph sequences should be tagged for possible application of GSUB features. The order in which these features are applied is not canonical; they should be applied in the order in which they appear in the GSUB table in the font. locl ccmp nukt akhn The `locl` feature replaces default glyphs with any language-specific variants, based on examining the language setting of the text run. > Note: Strictly speaking, the use of localized-form substitutions is > not part of the shaping process, but of the localization process, > and could take place at an earlier point while handling the text > run. However, shaping engines are expected to complete the > application of the `locl` feature before applying the subsequent > GSUB substitutions in the following steps. The `ccmp` feature allows a font to substitute mark-and-base sequences with a pre-composed glyph including the mark and the base, or to substitute a single glyph into an equivalent decomposed sequence of glyphs. If present, these composition and decomposition substitutions must be performed before applying any other GSUB lookups, because those lookups may be written to match only the `ccmp`-substituted glyphs. > Note: The `ccmp` feature may perform decompositions of split vowels > that do not have a canonical decomposition defined in Unicode. Split > vowels that do have a canonical decomposition were decomposed in > stage one. The `nukt` feature replaces "_Consonant_,Nukta" sequences with a precomposed nukta-variant of the consonant glyph. The `akhn` feature replaces specific sequences with required ligatures. These sequences can occur anywhere in a cluster. Akhand characters have orthographic status equivalent to full consonants in some languages, and fonts may have later substitution rules designed to match them in subsequences. Therefore, this feature must be applied before all other many-to-one substitutions. #### Stage 3, step 2: Applying the basic reordering features from GSUB #### The basic reordering step applies mandatory substitution features from GSUB that affect reordering elements. For these features, the glyph substitutions themselves are applied at this step. However, the actual reordering of the glyphs does not take place until stage 4, step 1. The order in which these substitutions must be performed is fixed for all USE scripts: rphf pref ##### Stage 3, step 2.1: rphf ##### The `rphf` feature replaces cluster-initial "Ra,Halant" sequences with the "Reph" glyph. > Note: although the glyph substitution is performed in this step, the > corresponding glyph reordering move is not performed until a later > stage. ##### Stage 3, step 2.2: pref ##### The `pref` feature replaces pre-base-consonant glyphs with any special forms. > Note: although the glyph substitution is performed in this step, the > corresponding glyph reordering move is not performed until a later > stage. #### Stage 3, step 3: Applying the basic orthographic features from GSUB #### The basic orthographic step applies substitution features using the rules in the font's GSUB table. In preparation for this stage, glyph sequences should be tagged for possible application of GSUB features. The order in which these features are applied is not canonical; they should be applied in the order in which they appear in the GSUB table in the font. rkrf abvf blwf half pstf vatu cjct The `rkrf` feature replaces "_Consonant_,Halant,Ra" sequences with the "Rakaar"-ligature form of the consonant glyph. The `abvf` feature replaces above-base-consonant glyphs with any special forms. The `blwf` feature replaces below-base-consonant glyphs with any special forms. The `half` feature replaces "_Consonant_,Halant" sequences before the base consonant with "half forms" of the consonant glyphs. The `pstf` feature replaces post-base-consonant glyphs with any special forms. The `vatu` feature replaces certain sequences with "Vattu variant" forms. The `cjct` feature replaces sequences of adjacent consonants with conjunct ligatures. These sequences must match "_Consonant_,Halant,_Consonant_". ### Stage 4: Glyph reordering ### The glyph-reordering stage moves dependent vowels, diacritics, and other mark glyphs in relation to the base consonant. All reordering is performed in this stage, which is broken into two distinct steps: 1. Applying the reordering features from GSUB 2. Performing property-based reordering moves #### Stage 4, step 1: Applying the reordering features from GSUB #### In this step, the reordering moves corresponding to the glyph-reordering features in GSUB are performed. Any glyph substitutions that apply to characters involved in these reordering moves were performed in stage 3, step 2. Therefore, this step only requires moving glyphs to their final positions. The order in which these substitutions must be performed is fixed for all USE scripts: rphf pref ##### Stage 4, step 1.1: rphf ##### In stage 3, step 2, the `rphf` feature replaced cluster-initial "Ra,Halant" sequences with the "Reph" glyph. The "Reph" glyph is now reordered to its final position. The algorithm to determine the final position of the "Reph" glyph is: - Move the "Reph" right one position at a time. - If the character immediately following the new position is an explicit "Halant", stop. - If the character immediately before the new position is a full base (`B`) character, stop. - If the end of the cluster is reached, stop. ##### Stage 4, step 1.2: pref ##### In stage 3, step 2, the `pref` feature replaced pre-base-consonant glyphs with special forms. The pre-base-consonant glyph is now reordered to its final position. The algorithm to determine the final position of the pre-base-reordering consonant is: - Move the pre-base-reordering consonant left one position at a time. - If the pre-base reordering consonant is to the left of the first spacing glyph after an explicit "Halant", stop. - When the pre-base reordering consonant is to the left of the first spacing glyph in the cluster, stop. - If the beginning of the cluster is reached, stop. > Note: Each cluster may have only one pre-base-reordering consonant > glyph. > > Note: scripts that use pre-base medial consonants may also make use > of the `pref` feature reordering. #### Stage 4, step 2: Performing property-based reordering moves #### In this step, any characters that match one of the USE reordering classifications should be reordered into their final position. > Note: this classification-based reordering step ensures that > reordering characters not addressed by the active font's GSUB > features are ordered correctly. The character classes reordered in this step are: ```markdown `R` = `REPHA` `VPre` = `VOWEL_PRE` `VMPre` = `VOWEL_MOD_PRE` ``` Pre-base `REPHA` glyphs that occur before a full base are reordered using the "Reph" reordering algorithm described in [Stage 4, step 1.1](#stage-4-step-11-rphf), just as if the `rphf` feature had been applied to the glyph. Pre-base `VOWEL_PRE` vowel glyphs, including both stand-alone `VOWEL_PRE` vowels and `VOWEL_PRE` components of split vowels, are reordered to - before the base glyph - before any other pre-base glyphs that were reordered in earlier steps Pre-base `VOWEL_MOD_PRE` vowel-modifier glyphs are reordered to - before the base glyph - before any pre-base `VOWEL_PRE` vowel glyphs - before any other pre-base glyphs that were reordered in earlier steps ### Stage 5: Final feature application ### The final stage involves applying topographic joining features for connected scripts, applying typographic-presentation features from GSUB, and applying positioning features from GPOS. #### Stage 5, step 1: Applying the final topographic features from GSUB #### For connected scripts, this step applies the substitutions to select the correct topographic form for each glyph, based on its position in the syllable. Whether or not each codepoint joins on the left or the right side is determined by the `Unicode Joining Type` (UJT) property defined in UCD for each codepoint. > Note: USE does not support positional typographic features for any > non-connected scripts. isol init medi fina #### Stage 5, step 2: Applying the final typographic-presentation features from GSUB #### The final typographic-presentation step applies mandatory substitution features using the rules in the font's GSUB table. In preparation for this stage, glyph sequences should be tagged for possible application of GSUB features. The order in which these features are applied is not canonical; they should be applied in the order in which they appear in the GSUB table in the font. abvs blws calt clig haln liga pres psts rclt rlig vert vrt2 The `abvs` feature replaces above-base-consonant glyphs with special presentation forms. This usually includes contextual variants of above-base marks or contextually appropriate mark-and-base ligatures. The `blws` feature replaces below-base-consonant glyphs with special presentation forms. This usually includes replacing consonants that are adjacent to special consonant forms with contextual ligatures. The `calt` feature substitutes glyphs with contextual alternate forms. In contrast to `rclt`, the `calt` feature performs substitutions that are not mandatory for orthographic correctness. However, unlike `rclt`, the substitutions made by `calt` can be disabled by application-level user interfaces. The `clig` feature substitutes optional ligatures that are on by default, but which are activated only in certain contexts. Substitutions made by clig may be disabled by application-level user interfaces. The `haln` feature replaces syllable-final "_Consonant_,Halant" pairs with special presentation forms. This can include stylistic variants of the consonant where placing the "Halant" mark on its own is typographically problematic. The `liga` feature substitutes standard, optional ligatures that are on by default. Substitutions made by `liga` may be disabled by application-level user interfaces. The `pres` feature replaces pre-base-consonant glyphs with special presentations forms. This can include consonant conjuncts, half-form consonants, and stylistic variants of left-side dependent vowels (matras). The `psts` feature replaces post-base-consonant glyphs with special presentation forms. This usually includes replacing right-side dependent vowels (matras) with stylistic variants or replacing post-base-consonant/matra pairs with contextual ligatures. The `rclt` feature substitutes glyphs with contextual alternate forms. The `rclt` feature should be used to perform such substitutions that are required by the orthography of the active script and language. Substitutions made by `rclt` cannot be disabled by application-level user interfaces. The `rlig` feature substitutes glyph sequences with mandatory ligatures. Substitutions made by `rlig` cannot be disabled by application-level user interfaces. #### Stage 5, step 3: Applying the final positioning features from GPOS #### curs dist kern mark abvm blwm mkmk The `curs` feature perform cursive positioning in connected scripts or cursive styles. Each cursive glyph has an entry point and exit point; the `curs` feature positions glyphs so that the entry point of the current glyph meets the exit point of the preceding glyph. The `dist` feature adjusts the horizontal positioning of glyphs. Unlike `kern`, adjustments made with `dist` do not require the application or the user to enable any software _kerning_ features, if such features are optional. The `kern` adjusts glyph spacing between pairs of adjacent glyphs. The `mark` feature positions marks with respect to base glyphs. The `abvm` feature positions above-base marks for attachment to base characters. This includes above-base dependent vowels (matras), diacritical marks, syllable modifiers, and above-base consonant forms. The `blwm` feature positions below-base marks for attachment to base characters. This includes below-base dependent vowels (matras), diacritical marks, syllable modifiers, and below-base consonant forms. The `mkmk` feature positions marks with respect to preceding marks, providing proper positioning for sequences of marks that attach to the same base glyph.