Test Report for Rendering Engine “fontkit

Overview

This report was generated on November 23, 2023 by running Unicode’s test suite for text rendering engines with fontkit 2.0.2, NPM 10.2.0 and Node 21.1.0. Some tests have failed. For details, see CFF-3, GSUB-3, GVAR-9, MORX-3, MORX-5, MORX-10, MORX-11, MORX-17, MORX-19, MORX-20, MORX-24, MORX-29, MORX-30, MORX-31, MORX-32, MORX-33, MORX-34, MORX-35, MORX-36, MORX-38, MORX-40, MORX-41, SFNT-1, SHLANA-1, SHLANA-2, SHLANA-3, SHLANA-4, SHLANA-5, SHLANA-6, SHLANA-7, SHLANA-8, SHLANA-9, and SHLANA-10.

AVAR–1: Weight Flattening

The font for this test case is a variation font with a single axis. While the ‘gvar’ table does a regular interpolation without any special quirks, the font’s ‘avar’ table defines a mapping that modifies the variation axis.
A correct implementation should produce the test glyph in its maximally thin shape at axis value 100. The resulting glyph should become bolder until 250, then stay at the exact same weight until 650, then become bolder up to the maximum at 900.
100 150 200 250 300 350 400 450 500 550 600 650 700 750 800 850 900
Curve
Expected
Observed
Conformance

CFF–1: Hexing the Last Byte

The font for this test case is FDArray Test 257, a test font by Adobe. The font has been engineered by Ken Lunde to use a CFF font dictionary array for mapping Unicode codepoints to glyphs. If your implementation is correct, each rendered glyph should show a hexadecimal number with the least significant byte of the Unicode codepoint being rendered. For a more detailed explanation of this test, please refer to Adobe’s description.
A
U+0041
U+211D
U+24EA
U+2460
U+2461
仿
U+4EFF
U+FF21
𐄳
U+10133
𝓐
U+1D4D0
🌺
U+1F33A
🌻
U+1F33B
💧
U+1F4A7
🥝
U+1F95D
Expected
Observed
Conformance

CFF–2: Hexing the Second Last Byte

The font for this test case is Adobe’s FDArray Test 65535, which complements test case CFF-1. If your implementation is correct, each rendered glyph should show a hexadecimal number with the second least significant byte of the Unicode codepoint being rendered. For a more detailed explanation of this test, please refer to Adobe’s description.
A
U+0041
U+211D
U+24EA
U+2460
U+2461
仿
U+4EFF
U+FF21
𐄳
U+10133
𝓐
U+1D4D0
🌺
U+1F33A
🌻
U+1F33B
💧
U+1F4A7
🥝
U+1F95D
Expected
Observed
Conformance

CFF–3: Endchar With Five Arguments

In the font for this test case, the glyphs Agrave and Udieresis pass five arguments to the endchar command. For a description of this particular variant of the endchar operator, see Adobe PostScript Technical Note #5177, Appendix C, at the bottom of page 35. See also OpenType.js bug 117 and fontkit bug 322.
If the implementation under test works correctly, you should see the glyphs À and Ü.
Expected
Observed
Conformance

CFF2–1: Variations

The font for this test case is a subset of Adobe’s Variable Font Prototype, a variable font in the Compact Font Format (CFF) Version 2. If your implementation is correct, the dollar sign should change its weight in the rendering below. For most weights, the dollar glyph should be fully stroked. But for the boldest weights, you should see a glyph variant where the stroke is only partial.
100 200 300 400 500 600 700 800 900
Expected
Observed
Conformance

CMAP–1: Ideographic Variation Sequences

The Unicode Ideographic Variation Database defines glyph variants for Han ideographs. For example, Unicode supports two slightly different variants when rendering U+82A6 in Japanese; the font for this test case contains a type 14 ‘cmap’ table that implements them. With a conforming implementation, you should see four glyphs below. In the third glyph (U+82A6 U+E0101), the top stroke below the radical should be attached and slanting up. But in the first, second, and fourth glyph, that stroke should be detached and horizontal. If all four glyphs look the same, or if you see any black boxes in the renderings, it’s a sign that your implementation is broken.
82A6
82A6
E0100
82A6
E0101
82A6
E0102
Expected
Observed
Conformance

CMAP–2: Unicode Variation Selectors

Unicode defines Standardized Variants of certain characters, including some Mathematical Symbols. The font for this test case contains a type 14 ‘cmap’ table that implements both the regular symbol ≩ U+2269 GREATER-THAN BUT NOT EQUAL TO, and its variant U+2269 U+FE00 GREATER-THAN BUT NOT EQUAL TO WITH VERTICAL STROKE. With a correct implementation, the two glyphs should look different. If the two glyphs look the same, or if you see any black boxes in the renderings, it’s a sign that your implementation is broken.
2269
2269
FE00
Expected
Observed
Conformance

CMAP–3: MacOS Turkish Encoding

The font for this test case contains a ‘cmap’ table of format 0, platform 1, encoding 0, language 18. Platform 1 means the classic Macintosh up to MacOS 9; the combination of encoding 0 and language 18 indicates the MacOS Turkish character encoding. (The QuickDraw graphics system of the classic Macintosh had used code 17 for the Turkish language; as described by section ”The ‘cmap’ table and language codes” in the Apple TrueType specification, Macintosh language codes in the ‘cmap’ table are 1 higher than the QuickDraw language code). Although Apple has deprecated the Macintosh encodings in favor of Unicode in 2002, present-day renderers may still encounter such fonts. For example, users sometimes want to open electronic documents that were created a long time ago, and certain file formats contain embedded fonts.
A correct implementation should be able to render Turkish text with this test font, using Unicode’s conversion table. If you see boxes, missing characters, or glyphs from a different (fallback) font in the rendering below, it’s a sign that your implementation cannot handle legacy fonts that were built for MacOS.
Expected
Observed
Conformance

CMAP–4: Many-to-one range mappings

The font for this test case contains a format 13 ‘cmap’ table that defines many-to-one range mapping for Latin, Cherokee, Cuneiform, and Chess Symbols. The font is a subset of the Last Resort Font.
U
U+0055

U+13EF
𒀼
U+1203C
🨀
U+1FA00
Expected
Observed
Conformance

CVAR–1: Sharing Points

The font for this test case uses shared point numbers in its ‘cvar’ table. Some versions of the FreeType rasterizer had a bug which made the glyphs look as if the font had a reverse-contrast design; see FontTools bug 1113 and FreeType bug 52532.
Note: The OpenType specification explicitly requires that weight values can be interpreted in direct comparison to values for usWeightClass in the ‘OS/2’ table, or the CSS font-weight property. Our test font uses a numeric range from 28 to 194. Therefore, applications will typically display the rendered letters in a much thinner weight than the font designer probably expected. However, the font’s weight axis is still within the permitted bounds (from 1 to 1000), so this font is technically valid. In any case, an implementation should not distort the glyphs to appear in reverse contrast.
28 94 194
Expected
Observed
Conformance

CVAR–2: Not Sharing Points

Other than CVAR–1, the font for this test case does not use shared point numbers in its ‘cvar’ table.
28 94 194
Expected
Observed
Conformance

GLYF–1: Composite Glyphs

The font for this test case has a ‘glyf’ table whose entry for U+0123 LATIN SMALL LETTER G WITH CEDILLA is a composite glyph. It has two components: one for the base glyph, and another one for the accent. A correct implementation must place the accent on top of the g.
Expected
Observed
Conformance

GPOS–1: Pair Adjustment Positioning

The font for this test case contains a ‘GPOS’ table whose ‘kern’ feature enables a lookup of type 2 for Pair Adjustment Positioning. The lookup contains two subtables:
If you see touching or overlapping glyph pairs in the rendering, it’s a sign that your implementation fails to handle ‘GPOS’ tables with type 2 lookups for Pair Adjustment Positioning.
Expected
Observed
Conformance

GPOS–2: Coverage in Pair Adjustment Positioning

This test case exercises the handling of the Coverage field in Pair Adjustment Positioning subtables. The font contains a ‘GPOS’ table whose ‘kern’ feature enables a single lookup of type 2. This lookup contains three PairPos format 1 subtables. All three subtables specify ◯ U+25EF LARGE CIRCLE as their Coverage, but no other glyphs.
If your implementation is correct, the two symbols ◯ and ☼ should exactly overlap when drawn next to each other. If you see two separate symbols in the rightmost column below, your text rendering engine fails to correctly handle Coverage inside GPOS pair adjustment positioning subtables.
◯☼
Expected
Observed
Conformance

GPOS–3: Mark-to-Base Attachment for Ethiopic Diacritics

The font for this test case defines a Mark Positioning feature in its Glyph Positioning table. The feature uses a MarkToBase Attachment Positioning Subtable for placing Ethiopic diacritics on top of a base glyph. If your text rendering engine is correct, the dots (which indicate “long vowel”, “long consonant”, and “long consonant plus long vowel”) should be placed on top of the base glyph (the syllable “la”). If the dots appear to the right of the base glyph, or if they are missing entirely, it’s a sign that your text rendering system is broken.
U+1308
U+1308
U+135E
U+1308
U+135F
U+1308
U+135D
Expected
Observed
Conformance

GPOS–4: Mark-to-Mark Attachment for Stacked Accents

The font for this test case uses a MarkToMark Attachment Positioning Subtable for stacking accents. If your text rendering engine is correct, the accents should be positioned on top each other. If the accents appear to the right of the base glyph, or if they are missing entirely, it’s a sign that your text rendering system is broken.
Expected
Observed
Conformance

GPOS–5: Glyph Positioning for Variable Fonts

The font for this test case uses a Glyph positioning table with font variations. If your text rendering engine is correct, the Sukun mark should be centered on the dots of the Shin letter, no matter the weight. If the placement is off for some weights, your text rendering system fails to handle Item Variation Stores inside GPOS tables.
100 300 500 700 900
Expected
Observed
Conformance

GSUB–1: Space Isn’t Nothing

The font for this test case has a contextual alternates feature in its GSUB table that substitutes a by a.alt if followed by a space. Some versions of Adobe InDesign had a bug where space was treated like an empty substitution context. If your implementation is correct, you should see two different glyphs in the rendering: the first letter should have an overbar, the second letter should not.
Expected
Observed
Conformance

GSUB–2: Chaining Contextual Substitution for Ethiopic Numerals

The font for this test case supports the “joining style” of Ethiopic numerals. It contains distinct glyphs for the the initial, medial, and final form of every digit, plus an isolated form which gets used when a digit stands alone. In its Glyph Substitution table, the test font uses a Glyph Composition/Decomposition feature to select the correct shape depending on its context. To achieve this effect, the feature invokes lookups for Chaining Contextual Substitution. In the test rendering, you should see continuous strokes; only the the first and the last digit of each number should have side strokes. If you can see small side strokes also at interior digits, it’s a sign that your text rendering engine is broken.
20 3 40 5 23 45 100 2300 2323 2345 4523
Expected
Observed
Conformance

GSUB-3: Substituting a Billion Laughs

The font for this test case is an OpenType version of the Billion laughs attack. Its GSUB table contains a sequence of nine identical lookups. Each lookup replaces the glyph o by the string olololololololololo, provided that the o is surrounded (both preceded and followed) by an l. The first lookup thus expands one single laugh (lol) into ten. The second lookup gives 100 laughs; the third 1000; the fourth 10,000; the fifth 100,000; and so forth. After executing the ninth lookup, the final result would be a billion laughs, but this takes a very long time (and large amounts of memory) to compute. If your implementation is immune to this attack, it should neither crash nor hang when rendering lol with this font. Instead, your implementation should stop executing once its internal buffer has reached a size limit. See also fontkit bug 221.
Expected Shouldn’t crash
Conformance

GVAR–1: Sharing All Points

The font for this test case uses shared point numbers in its ‘gvar’ table. In its shared points set, the font sets the number of points to zero. A correct implementation should interpret such an empty set as a compact encoding of “all points.” If the glyphs in the rendering below have all the same weight, of if some glyphs are missing entirely, it’s a sign that your implementation is broken.
300 350 400 450 500 550 600 650 700
Expected
Observed
Conformance

GVAR–2: Sharing Enumerated Points

Like in test case GVAR–1, the font for this test uses shared point numbers in its ‘gvar’ table. However, this font does not simply state an empty set for indicating that “all points” should be affected by the variation record. Instead, it gives an explicit enumeration of point numbers in its shared points set. A correct implementation should render the glyphs in the exact same way as in GVAR–1, although the font uses a less compact encoding.
300 350 400 450 500 550 600 650 700
Expected
Observed
Conformance

GVAR–3: Sharing No Points

Other than the fonts for test cases GVAR–1 and GVAR–2, the font for this test does not use any shared point numbers in its ‘gvar’ table. A correct implementation should still render the glyphs in the exact same way, no matter what encoding has been used.
300 350 400 450 500 550 600 650 700
Expected
Observed
Conformance

GVAR–4: Crawling Lizard

The font for this test case is Zycon, designed in 1993, by David Berlow at Font Bureau Inc. The font was developed for illustrating the capabilities of TrueType GX. The glyph ids and the font have been updated to OpenType 1.8. The new version supports a small number of Emoji such as 🦎 U+1F98E LIZARD. If your implementation is correct, the lizard should crawl. Variation axis M₁ moves its legs while axis T₁ bobs the head.
–1.0
+0.0
–0.8
+0.1
–0.6
+0.2
–0.4
+0.3
–0.2
+0.4
±0.0
+0.5
+0.2
+0.6
+0.4
+0.7
+0.6
+0.8
+0.8
+0.9
+1.0
+1.0
Expected
Observed
Conformance

GVAR–5: Lunar Phases

The font for this test case is the same Zycon as in GVAR–4. If your implementation is correct, 🌝 U+1F31D FULL MOON WITH FACE should wax and wane in sync with to variation axis M₁.
–1.0 –0.8 –0.6 –0.4 –0.2 ±0.0 +0.2 +0.4 +0.6 +0.8 +1.0
Expected
Observed
Conformance

GVAR–6: Timid Turtle

The font for this test case is again the same Zycon as in GVAR–4. Here, axis T₁ controls the timidity of 🐢 U+1F422 TURTLE. If your implementation is correct, the turtle should fully stick its head, legs and tail out of the shell at T₁ = 0.0. As the axis value goes up, the turtle should become increasingly timid. At T₁ = 1.0, it should be fully hidden inside the shell.
0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0
Expected
Observed
Conformance

GVAR–7: Stemming Digits

With one particular OpenType implementation, the font for this test case triggered an etched look where the glyphs were distorted. If your implementation is correct, you see normal-looking glyphs whose weight is smoothly increasing. All the “I” letters should have visible stems, and there should not be anything unusual about the “O” letters either.
150 200 250 300 350 400 450
Expected
Observed
Conformance

GVAR–8: Inferring Variation Deltas for Unreferenced Points

The font for this test case has a single glyph (‘H’) which displays examples of a boundary IUP issue which was treated differently in existing implementations. The top of the top serifs and bottom of the bottom serifs all have multiple points at the same Y location in the default. If you examine the bottom left serif, you will see points 149 through 157 all share the same Y coordinate of 0. When moving from the default 0.0 to –1.0 in the Hooves axis, point 153 moves by (0,50). This now leaves 6 untouched points that need to be interpolated. The handling of these intermediate points (150–152 and 154–156) was different between Apple’s, FreeType’s and Monotype’s implementations.
±0.0 –0.2 –0.4 –0.6 –0.8 –1.0
Expected
Observed
Conformance

GVAR–9: IUP, again

The font for this test case has one axis, TEST, that runs from –1.0 to 1.0 with default 0.0. It has one glyph, A, which contains 4 square contours, all identical apart from their x position. The top edge of each contour contains 5 points, with 3 extra points spaced evenly between the top-left and top-right points. It has one gvar variation tuple, value 1 on axis TEST. This tuple only moves points that lie on the top of each contour. Note that in each contour moved by the gvar tuple, there are TWO runs of interpolated points. Thus: contour #0 has points 0–6; contour #1 has points 7–13; contour #2 has points 14–20; contour #3 has points 21–27.
If your implementation is correct, you should see four square contours for values of TEST ≤ 0. As the value increases towards +1.0, the first, third and fourth contour should look increasingly distorted.
An early version of Apple’s CoreText library had a bug which prevented the third contour from getting interpolated at TEST = +0.944444; see Radar bug 31935412. An early version of FreeType had a different problem; see FreeType bug 50832. For fontkit, see fontkit bug 182. Finally, see also the OpenType-Layout mailing list archives of November 2018.
–1.0 –0.5 ±0.0 +0.5 +0.6 +0.7 +0.8 +0.9 +0.944444 +1.0
Expected
Observed
Conformance

HVAR–1: No Advance Width Mapping

The font for this test case contains a Horizontal Metrics Variation Table whose offsetToAdvanceWidthMapping field is zero. The font, which was kindly contributed by Adobe Systems, had triggered a bug in an unreleased version of the FreeType library; see FreeType bug 50170. If your implementation is correct, the advance width should grow as the weight increases. In particular, the letters A and B should not overlap, not even in the boldest weights. If you see any overlapping glyphs, your implementation fails to compute advance widths for fonts whose HVAR table contains no advance width mapping.
0 200 400 600 800 1000
Expected
Observed
Conformance

HVAR–2: Last entry

The font for this test case contains an HVAR table with fewer entries than glyphs in the font. According to the OpenType HVAR specification, “if a given glyph ID is greater than mapCount – 1, then the last entry is used.” If your implementation is correct, the two glyphs should not crisscross. If they overlap, your implementation is faulty. See also FreeType bug 50678.
0 200 400 600 800 1000
Expected
Observed
Conformance

KERN–1

The font for this test case contains a ‘kern’ table of format 0, which in turns contains a single format 0 subtable. Without kerning, the glyphs for T, u and the dotless ı will look like normal letters. However, if your implementation correctly applies the font’s kerning data, the shapes will join to form a geometric pattern. If you can still discern the original letters ıTuTuTı in the rendering, it’s a sign that your implementation fails to correctly handle kerning. See also HarfBuzz bug 1255.
Expected
Observed
Conformance

KERN–2

Although kerning is typically reducing space between letter pairs, it’s entirely valid for a font to increase it. This test verifies that an implementation can handle such kerning tables. If your implementation works correctly, you should see four groups separated by whitespace.
Expected
Observed
Conformance

MORX–1: Non-Contextual Glyph Substitution

The font for this test case contains an AAT Extended Glyph Metamorphosis Table with a single Non-Contextual Glyph Substitution Subtable, replacing the glyphs A and C by alternate forms. If your renderer supports Apple Advanced Typography, the letters A and C should be white on black whereas the letter B should appear inside a stroked circle.
Expected
Observed
Conformance

MORX–2: Rearrangement

The font for this test case contains an AAT Extended Glyph Metamorphosis Table with a single Rearrangement Subtable. Its finite-state table contains one single state, but a set of interesting transitions.
If your renderer supports Apple Advanced Typography, the text should get rearranged as expected.
0: No Change 1: Ax ⇒ xA
Expected
Observed
Conformance
 
2: xD ⇒ Dx 3: AxD ⇒ DxA
Expected
Observed
Conformance
 
4: ABx ⇒ xAB 5: ABx ⇒ xBA
Expected
Observed
Conformance
 
6: xCD ⇒ CDx 7: xCD ⇒ DCx
Expected
Observed
Conformance
 
8: AxCD ⇒ CDxA 9: AxCD ⇒ DCxA
Expected
Observed
Conformance
 
10: ABxD ⇒ DxAB 11: ABxD ⇒ DxBA
Expected
Observed
Conformance
 
12: ABxCD ⇒ CDxAB 13: ABxCD ⇒ CDxBA
Expected
Observed
Conformance
 
14: ABxCD ⇒ DCxAB 15: ABxCD ⇒ DCxBA
Expected
Observed
Conformance

MORX–3: Rearrangment without Marking

In the font for this test case, the transitions for glyphs ⓿ to ⓯ execute the corresponding rearrangement actions. However, the font’s state machine is unusual because it does not contain any transitions for changing the marked glyph range. Therefore, the rearrangements get invoked without a marked range. If your rendering engine is correctly implemented, it should leave the input sequence unchanged.
Expected
Observed
Conformance
 
Expected
Observed
Conformance
 
Expected
Observed
Conformance
 
Expected
Observed
Conformance

MORX–4: Empty Rearrangement

The font for this test case contains an AAT Extended Glyph Metamorphosis Table with a single Rearrangement Subtable. Its finite-state table contains one single state and the following transitions:
The test strings are crafted to trigger rearrangements on sequences whose variable-length part is empty (x = ε). If your rendering engine implements Apple Advanced Typography, the output should should match the expectations. See also Apple Radar bug 36384131.
0: No change 1: Aε ⇒ εA 2: εA ⇒ Aε 3: AεD ⇒ DεA
Expected
Observed
Conformance
 
4: ABε ⇒ εAB 5: ABε ⇒ εBA 6: εAB ⇒ ABε 7: εAB ⇒ BAε
Expected
Observed
Conformance
 
8: AεCD ⇒ CDεA 9: AεCD ⇒ DCεA 10: ABεD ⇒ DεAB 11: ABεD ⇒ DεBA
Expected
Observed
Conformance
 
12: ABεCD ⇒ CDεAB 13: ABεCD ⇒ CDεBA 14: ABεCD ⇒ DCεAB 15: ABεCD ⇒ DCεBA
Expected
Observed
Conformance

MORX–5: Rearrangement underflow

The font for this test case is the same as in MORX-4. The test strings are crafted to trigger rearrangements on sequences that are shorter than the operands of the executed action. For example, rearrangement action 3 swaps the first and last glyph of the marked sequence; so we test what happens when the marked sequence contains just one glyph. If your rendering engine is correctly implemented, it should not perform rearrangements when there are not enough arguments. See also fontkit bug 143.
3: AxD ⇒ DxA
only 1 of 2+ glyphs
4: ABx ⇒ xAB
only 1 of 2+ glyphs
5: ABx ⇒ xBA
only 1 of 2+ glyphs
6: xCD ⇒ CDx
only 1 of 2+ glyphs
Expected
Observed
Conformance
 
7: xCD ⇒ DCx
only 1 of 2+ glyphs
8: AxCD ⇒ CDxA
only 1 of 3+ glyphs
8: AxCD ⇒ CDxA
only 2 of 3+ glyphs
9: AxCD ⇒ DCxA
only 1 of 3+ glyph
Expected
Observed
Conformance
 
9: AxCD ⇒ DCxA
only 2 of 3+ glyphs
10: ABxD ⇒ DxAB
only 1 of 3+ glyph
10: ABxD ⇒ DxAB
only 2 of 3+ glyphs
11: ABxD ⇒ DxBA
only 1 of 3+ glyphs
Expected
Observed
Conformance
 
11: ABxD ⇒ DxBA
only 2 of 3+ glyphs
12: ABxCD ⇒ CDxAB
only 1 of 4+ glyphs
12: ABxCD ⇒ CDxAB
only 2 of 4+ glyphs
12: ABxCD ⇒ CDxAB
only 3 of 4+ glyphs
Expected
Observed
Conformance
 
13: ABxCD ⇒ CDxBA
only 1 of 4+ glyphs
13: ABxCD ⇒ CDxBA
only 2 of 4+ glyphs
13: ABxCD ⇒ CDxBA
only 3 of 4+ glyphs
14: ABxCD ⇒ DCxAB
only 1 of 4+ glyphs
Expected
Observed
Conformance
 
14: ABxCD ⇒ DCxAB
only 2 of 4+ glyphs
14: ABxCD ⇒ DCxAB
only 3 of 4+ glyphs
15: ABxCD ⇒ DCxBA
only 1 of 4+ glyphs
15: ABxCD ⇒ DCxBA
only 2 of 4+ glyphs
Expected
Observed
Conformance
 
15: ABxCD ⇒ DCxBA
only 3 of 4+ glyphs
Expected
Observed
Conformance

MORX–6: Re-Re-Re-Rearrangements

The font for this test case is the same as in MORX-4. When rendering the test string OOOABCDEFGOOO3141, the following should happen:
If your implementation supports Apple Advanced Typography, the text should get rearranged as expected. If the resulting string is ordered as ABCDEFG, your implementation does not implement AAT at all. If the result is ordered as GBCDEFA, your implementation incorrectly clears the marked glyph sequence after executing actions.
Expected
Observed
Conformance

MORX–7: Unstarted Rearrangement

The font for this test case is the same as in MORX–2. When rendering the string OBCD1, we set the end of the marked glyph sequence to B; then we change it to C; finally, to D. However, we never set the start of the marked glyph sequence. If your rendering engine is correctly implemented, it should implicitly start the marked glyph range at the beginning of the string, and move the O after the D when executing the rearrangement for 1.
Expected
Observed
Conformance

MORX–8: Rearrangement State Machine

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Rearrangement Subtable. Its finite-state machine contains three states (0, 1, 2) and the following transitions:
If your rendering system correctly implements Apple Advanced Typography, the string “0ABC” should get rendered in the original ordering, whereas “1ABC” and “2ABC” should get re-arranged in a state-dependent way.
See also libraqm bug 95 and HarfBuzz bug 1190.
Expected
Observed
Conformance

MORX–9: “Out of Bounds” Rearrangement

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Rearrangement Subtable. Its finite-state machine contains one single state with the following transitions:
If your rendering system correctly implements Apple Advanced Typography, it should swap the first two letters in ABXAB.
Expected
Observed
Conformance

MORX–10: “End of Text” Rearrangement

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Rearrangement Subtable. Its finite-state machine contains one single state with the following transitions:
If your rendering system correctly implements Apple Advanced Typography, it should swap the last two letters in ABABAB when taking the final end-of-text transition. See also fontkit bug 144.
Expected
Observed
Conformance

MORX–11: “End of Text” Rearrangement with MarkLast Flag

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Rearrangement Subtable. Its finite-state machine contains one single state with the following transitions:
The input string for this test case is BABBAABX. If your rendering system correctly implements Apple Advanced Typography, the finite-state machine should have marked the last A (the third-last glyph in the input string) before taking the final end-of-text transition. When processing end-of-text, your implementation should first extend the marked glyph sequence to the trailing ABX, and then perform a rearrangement for moving X to the front of the marked sequence. See also fontkit bug 145.
Expected
Observed
Conformance

MORX–12: Rearrangement with DontAdvance Flag

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Rearrangement Subtable. Its finite-state machine contains two states (0 and 1) with the following transitions:
The input string for this test case is XABCX followed by ➊, ➋, or ➌. If your rendering system correctly implements Apple Advanced Typography, the finite-state machine should follow the DontAdvance transitions to state 1 and produce the expected outputs.
XABCX➊ XABCX➋ XABCX➌
Expected
Observed
Conformance

MORX-13: Rearrangement with DontAdvance and MarkLast

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Rearrangement Subtable. Its finite-state machine contains two states (0 and 1) with the following transitions:
The input string for this test case is ABCDE. If your rendering system correctly implements Apple Advanced Typography, the finite-state machine should extend the marked glyph range to include E when the state changes from 0 to 1, even though the current position is not advancing. As a result, the final string after rearrangement should be BCDEA. If your implementation produces BCDAE or another order, it fails to handle state transitions that carry both the DontAdvance and MarkLast flags.
Expected
Observed
Conformance

MORX-14: Rearrangement Loop

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Rearrangement Subtable. Its finite-state machine contains two states (0 and 1) with the following transitions:
If your rendering system correctly implements Apple Advanced Typography, the finite-state machine should loop multiple times through state 1, repeatedly rearranging the marked glyphs in every iteration.
ABCDE ABBBCCCDDDBCDCE
Expected Shouldn’t crash or hang
Observed
Conformance

MORX-16: Rearrangement with DontAdvance and MarkFirst

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Rearrangement Subtable. Its finite-state machine contains two states (0 and 1) with the following transitions:
The input string for this test case is ABCDE. If your rendering system correctly implements Apple Advanced Typography, the A glyph should be rearranged to the end of the rendered string, resulting in BCDEA.
ABCDE
Expected
Observed
Conformance

MORX-17: Rearrangement with DontAdvance at End of Text

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Rearrangement Subtable. Its finite-state machine contains a single state with the following transitions:
The input string for this test case is AB. If your rendering system correctly implements Apple Advanced Typography, the A glyph should be rearranged to the end of the rendered string when your implementation executes the rearrangement for the End-of-text transition. Despite the presence of the DontAdvance flag, the result should be BA. See also fontkit bug 147.
AB
Expected
Observed
Conformance

MORX-18: Contextual Glyph Substitution

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Contextual Glyph Substitution Subtable. Its finite-state machine contains a single state with the following transitions:
The glyph substitution table has two entries. Index 0 replaces letters A to E by circled black-on-white forms; index 1 replaces A to E by circled white-on-black forms.
If your rendering system correctly implements Apple Advanced Typography, the renderings should look as expected.
Expected
Observed
Conformance

MORX-19: Contextual Glyph Substitution without Marking

The font for this test case is the same as with MORX–18. In this test, we do not render the B letter, so there are no marked glyphs. If your rendering system correctly implements Apple Advanced Typography, it should implicitly mark the first letter of the rendered string, so the output should look as expected. See also Fontkit bug 150.
Expected
Observed
Conformance

MORX-20: Contextual Glyph Substitution at End of Text

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Contextual Glyph Substitution Subtable. Its finite-state machine contains a single state with the following transitions:
The glyph substitution table has two entries. Index 0 replaces letters A to E by circled black-on-white forms; index 1 replaces A to E by circled white-on-black forms.
If your rendering system correctly implements Apple Advanced Typography, the renderings should look as expected. See also Fontkit bug 151.
ABCDE ABC ABE AE EE A E
Expected
Observed
Conformance

MORX-21: Contextual Glyph Substitution with SetMark

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Contextual Glyph Substitution Subtable. Its finite-state machine contains a single state with the following transitions:
The input string for this test is ABCDE. If your rendering system correctly implements Apple Advanced Typography, it should do the following when processing the transition for D: first, it should replace the marked glyph B by a circled form. Second, it should reset the marked glyph index to D. Therefore, only the B letter should be encircled in the rendered result. If the D is encircled, your implementation should be fixed to reset the marked glyph index after performing the replacement.
ABCDE
Expected
Observed
Conformance

MORX-22: Contextual Glyph Substitution with MarkIndex and CurrentIndex

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Contextual Glyph Substitution Subtable. Its finite-state machine contains two states (0 and 1) with the following transitions:
The input string for this test is A. If your rendering system implements Apple Advanced Typography, both MarkIndex and CurrentIndex will affect the same glyph. If your implementation is correct, it should first execute the glyph substitution for MarkIndex to replace A by B. Then, it should execute the glyph substitution for CurrentIndex, which replaces B (the result of the previous substitution) by C. Therefore, the final result should be C.
A
Expected
Observed
Conformance

MORX-23: Contextual Glyph Substitution with CurrentIndex and DontAdvance

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Contextual Glyph Substitution Subtable. Its finite-state machine contains one state. For glyphs glyphs A, B, C, and D, the machine executes the per-glyph substitution #0 on CurrentIndex on a transition that is also marked with the DontAdvance flag. The glyph substitution replaces A by B, B by C, C by D, and D by E.
The input string for this test is ABCDE. If your rendering system correctly implements Apple Advanced Typography, the finite-state machine should loop for each glyph in state 0 until it gets rewritten to E. The final result should be EEEEE.
ABCDE
Expected
Observed
Conformance

MORX-24: Contextual Glyph Subsitution Forever

The font for this test case attempts to run a denial-of-service attack on the rendering engine under test. The font’s finite-state transducer substitutes glyph A by B, B by C, C by D, D by E, and E by A. These transitions are all marked with the DontAdvance flag, so the machine never makes progress.
If your rendering system is immune to this attack, it will detect getting stuck (for example, by imposing an upper limit on the number of transitions taken by the finite-state machine), and give up quickly. See fontkit bug 175.
Expected Shouldn’t crash
Conformance

MORX-25: State Machine for Contextual Glyph Substitution

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Contextual Glyph Substitution Subtable. Its finite-state machine contains two states (0 and 1). In state 0, glyph A moves to state 1 with a transition carrying the SetMark flag; other glyphs have no effect. In state 1, glyphs B, C, D, E replace both the current and the marked glyph by an encircled form; other glyphs have no effect.
ABCDE EBCDA CBABC ABC CBA AB BA A B
Expected
Observed
Conformance

MORX-26: Another State Machine for Contextual Glyph Substitution

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Contextual Glyph Substitution Subtable. Its finite-state machine contains two states (0 and 1). In state 0, glyph A moves to state 1; glyphs B, C, D, E get replaced by an encircled form. In state 1, no substitution happens. If your implementation is correct, the input string AB should not get any substitutions, but a stand-alone B should get rendered inside a circle.
AB B
Expected
Observed
Conformance

MORX-27: Ligature Substitution

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Ligature Subtable to sustitute the strings AEB, AEC and AED by ligatures.
AEB AEC AED
Expected
Observed
Conformance

MORX-28: Ligature Substitution with Unmarked Glyphs

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Ligature Subtable to substitute AED by a ligature. The glyphs x and y do not change the current state of the finite-state machine, and their transitions also do not carry the SetMark flag. If your implementation is correct, it should form the ligature in spite of the presence of x and y.
AED AxED AEyD AxEyD AxxxEyyyyD
Expected
Observed
Conformance

MORX-29: Insertion

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Glyph Insertion Subtable. The glyph M has the SetMark bit set. The glyph A inserts the string INS before the last marked glyph because its MarkedInsertBefore bit is set; whereas B inserts the same after the marked sequence because its MarkedInsertBefore bit is clear. Glyphs C and D perform the same insertion before/after the current glyph. The glyphs P, Q, R, X, Y,Z perform no actions.
MarkedInsert = “INS”; MarkedInsertBefore = True
Expected
Observed
Conformance
MarkedInsert = “INS”; MarkedInsertBefore = False
Observed
Conformance
CurrentInsert = “INS”; CurrentInsertBefore = True
Expected
Observed
Conformance
CurrentInsert = “INS”; CurrentInsertBefore = False
Expected
Observed
Conformance

MORX-30: Multiple Insertions Without Resetting Mark

The font for this test case is the same as in MORX-29; we test the behavior when multiple insertions get performed without re-setting the mark. See also fontkit bug 172.
Expected
Observed
Conformance
 
Expected
Observed
Conformance
 
Expected
Observed
Conformance
 
Expected
Observed
Conformance

MORX-31: Insertion With SetMark On Same Transition

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Glyph Insertion Subtable. Its finite-state machine contains the following transitions:
See also Apple Radar bug 44861764. Contextual and insertion subtables should mark the first glyph (according to process order) before doing anything else.
  XXAYYAZZ XXAYYBZZ
Expected
Observed
Conformance
 
  XXBYYAZZ XXBYYBZZ
Expected
Observed
Conformance
 
  MPQRAXYZA MPQRAXYZB
Expected
Observed
Conformance
 
  MPQRBXYZA MPQRBXYZB
Expected
Observed
Conformance

MORX-32: Insertion At Mark Without SetMark

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Glyph Insertion Subtable. Its finite-state machine contains the following transitions:
The test cases check what happens when inserting glyphs without setting the mark. We expect that implementations match the buggy behavior of Apple’s CoreText, since the existing fonts have been developed for that platform. See also HarfBuzz bug 1195.
  A XAY B XBY
Expected
Observed
Conformance

MORX-33: Twice the Fun

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Glyph Insertion Subtable. When consuming glyph ‘h’ in state 0, its finite-state machine transitions to state 1. When consuming glyph ‘a’ in state 1, its finite-state machine transitions back to state 0 while also inserting the string “ha”. If your implementation is correct, every ha in the input should get rendered twice.
See also Apple Radar bug 44902550.
  ha haha ah
Expected
Observed
Conformance

MORX-34: Inserting a Billion Laughs

The font for this test case is an AAT version of the Billion laughs attack. It contains an AAT Extended Glyph Metamorphosis Table with nine identical Glyph Insertion Subtables whose embedded finite-state machine inserts the string hahahahahahahahahaha for every a in the input string. If the input is “ha” (one single laugh), the first subtable rewrites it to 10 laughs. The second subtable rewrites 10 to 100 laughs; the third goes from 100 to 1000; the fourth from 1000 to 10,000. After executing the ninth subtable, the final result will be a billion laughs, but this will take a very long time (and large amounts of memory) to compute. Your implementation should neither crash nor hang under attack. See also fontkit bug 174.
Expected Shouldn’t crash
Conformance

MORX-35: Insertion with DontAdvance

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Glyph Insertion Subtable. Its finite-state machine contains two states (0 and 1) with the following transitions:
See also HarfBuzz bug 1224.
A XAY
Expected
Observed
Conformance

MORX-36: Insertion forever

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Glyph Insertion Subtable. Its finite-state machine contains three states (0, 1 and 2) with the following transitions:
The input string for this test case is A. Your implementation should not hang (run without time limit) nor crash while rendering this input, even though the font is trying to trick the rendering engine into an infinite loop.
Expected Shouldn’t crash
Conformance

MORX-37: Processing in Layout/Physical Order

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Contextual Glyph Substitution Subtable. Bits 28 and 30 of that subtable’s Coverage Flags request processing in Layout (= physical) order, which is always left-to-right. The subtable’s finite-state machine contains two states (0 and 1) with the following transitions:
Thus, if the tested rendering engine first processes A or א, the result will be displayed in circled letters. If the tested rendering engine first processes B or ב, the result will be displayed in normal letters. If your rendering is correctly implemented, the observed output should look as expected.
AB BA אב בא
Expected
Observed
Conformance

MORX-38: Processing in Logical Order

The font for this test case is similar to MORX-37, but bits 28 and 30 of the subtable’s Coverage Flags request processing in Logical Order.
AB BA אב בא
Expected
Observed
Conformance

MORX-39: Processing in Reverse Layout/Physical Order

The font for this test case is similar to MORX-37, but bits 28 and 30 of the subtable’s Coverage Flags request processing in Reverse Layout/Physical Order.
AB BA אב בא
Expected
Observed
Conformance

MORX-40: Processing in Reverse Logical Order

The font for this test case is similar to MORX-37, but bits 28 and 30 of the subtable’s Coverage Flags request processing in Reverse Logical Order.
AB BA אב בא
Expected
Observed
Conformance

MORX-41: Ligature Substitution Under-/Overflow

The font for this test case has an AAT Extended Glyph Metamorphosis Table with a single Ligature Subtable whose finite-state machine has one single state. For glyphs a and b, the transition marks the current glyph. For glyph c, the transition also marks the current glyph, and then it executes an action to substitue the marked glyphs by a ligature. When rendering the strings ac and bc, the implementation finds two glyphs on its glyph stack, which should get replaced by the corresponding ligature. When rendering the string cc, the implementation is asked to pop two glyphs from a stack that contains just one. When rendering abcc, the stack will contain three glyphs when handling the first c.
ac bc cc abcc
Expected No crash No crash
Observed
Conformance

SFNT–1: OpenType with PostScript Outlines

The font for this test case, contributed by Simon Cozens, contains glyphs outlines in both CFF and glyf format. Because the Offset Table uses an sfntVersion of 0x4F54544F (‘OTTO’), your rendering engine should take the glyph outlines from the CFF table. If you see CFF below the characters A and B, your rendering engine makes correct use of the sfntVersion field. See also fontkit bug 214 and OpenType.js bug 419.
Expected
Observed
Conformance

SFNT–2: OpenType with TrueType Outlines

The font for this test case, contributed by Simon Cozens, contains glyphs outlines in both CFF and glyf format. Because the Offset Table uses an sfntVersion of 0x00010000, your rendering engine should take the glyph outlines from the glyf table. If you see glyf below the characters A and B, your rendering engine makes correct use of the sfntVersion field.
Expected
Observed
Conformance

SHARAN–1: Nasta‘līq

The font for this test case supports the Nasta‘līq script with letterforms for the Urdu language. Other than Naskh, Nasta‘līq requires that letters get arranged both in the horizontal and in the vertical direction. For text rendering systems, this is difficult to implement. If your implementation is correct, you should see the sample Urdu words arranged along a slightly diagonal baseline.
Language Unicode Font Typeface Calligraphy Nasta‘līq
Expected
Observed
Conformance

SHBALI–1: Balinese

A correct implementation should call the Universal Shaping Engine when rendering Balinese text. The test cases are taken from Noto bug #572, HarfBuzz bug #180, and HarfBuzz bug #387.
Expected
Observed
Conformance

SHBALI–2: More Balinese

A correct implementation should call the Universal Shaping Engine when rendering Balinese text. The test cases are again taken from Noto bug #572.
Expected
Observed
Conformance

SHBALI–3: Balinese Musical Diacritics

A correct implementation should be able to render Balinese diacritical marks for musical symbols.
1B6B 1B6C 1B6D 1B6E 1B6F 1B70 1B71 1B72 1B73
Expected
Observed
Conformance

SHKNDA–1: Kannada

A correct implementation should call the Kannada Shaping Engine when rendering Kannada text. The test cases are taken from Noto bug #759.
Expected
Observed
Conformance
 
Expected
Observed
Conformance

SHKNDA–2: Kannada

A correct implementation should call the Kannada Shaping Engine when rendering Kannada text. The test cases are taken from Noto bugs 760, 770, and 793. Some of these test cases have also been reported to Unicode, for example in text rendering bugs 18, 21 and 22.
Expected
Observed
Conformance
 
Expected
Observed
Conformance

SHKNDA–3: Kannada

Some versions of Apple’s CoreText library had a bug which caused incorrect renderings of certain Kannada text. In Apple’s “Radar” system, this has been reported as bugs 29311179, 30862517, and 30948070. See also here and here.
Expected
Observed
Conformance
 
Expected
Observed
Conformance
 
Expected
Observed
Conformance
 
Expected
Observed
Conformance

SHLANA–1: Tai Tham Vowel Combinations

The font for this test case supports the Tai Tham script, also known as Lanna. The font and test cases have been kindly contributed by Richard Wordingham. See also Richard Wordingham’s browser test page for Tai Tham rendering which gives more background.
These vowel combinations are taken from Revised proposal for encoding the Lanna script in the BMP of the UCS, ISO/IEC JTC1/SC2/WG2/N3207R, L2/07-007R (Everson, Hosken & Constable). Changes have been rung on the initial consonants to check for silly omissions. A hyphen in the pronunciation indicates a syllable-final consonant that would be specifed by a subscript consonant or following orthographic syllable.

/ko-/
‘then, and’
/kɔː/

/tɕaʔ/
‘to prevaricate’
/tuaʔ/
‘lotus’
/bua/

/kua-/
‘to request’
/kʰɔː/

/kɔː-/
‘to split up’
/ŋaʔ/
‘crow’
/kaː/
Expected
Observed
Conformance
 
‘to paint’
/taː/
‘to sprinkle’
/ham/
‘word’
/kam/
‘to pretend’
/tʰiʔ/
‘boil’ (noun)
/fiː/
‘moist’
/tɕɯʔ/
‘hand’
/mɯː/
‘monk’
/tʰuʔ/
‘snake’
/ŋuː/
‘to kick’
/keʔ/
Expected
Observed
Conformance
 
‘danger’
/pʰeː/
‘to limp along’
/kʰɛʔ/
‘corner’
/tɕɛː/
‘mud’
/pɤʔ/

/nɤː/

/kɯaʔ/

/kɯa/
‘we’
/hau/
‘drunk’
/mau/

/ko:/
Expected
Observed
Conformance
 
(a type of sound)
/pʰiaʔ/
‘flower’
/pia/

/kia-/
‘mucus’
/mɯaʔ/
‘salt’
/kɯa/
‘to practice’
/soʔ/
‘big’
/moː/
‘to gouge out’
/sɔʔ/
‘victory’
/tɕai/
‘in’
/nai/
Expected
Observed
Conformance
 
‘to expose’
/kʰai/
‘Thailand’
/tai/

Khün /kɤʔ/

Khün /kɤː/

Khün /ko-/

/saŋ/
‘whole’
/taŋ/
‘edge’
/him/

/kiŋ/

/kam/
 
Expected
Observed
Conformance
 

/kam/
‘mountain’
/dɔːi/
Expected
Observed
Conformance

SHLANA–2: Tai Tham Sequences from L2/07-007R

These Tai Tham sequences are taken from Revised proposal for encoding the Lanna script in the BMP of the UCS, ISO/IEC JTC1/SC2/WG2/N3207R, L2/07-007R (Everson, Hosken & Constable). The font has been kindly contributed by Richard Wordingham. See also Richard Wordingham’s browser test page for Tai Tham rendering which gives more background and contains notes describing each test case.
‘thrice’
/saːm tiː/
‘different in my view’
/taːŋ taːŋ/
‘path’
/tʰănon/
‘belongings’
/kʰau kʰɔːŋ/
‘elephant’
/tɕaːŋ/
‘to flee’
/niː/
‘to blockade’
/kʰwɛːn/
‘head’
/hua/
‘like this’
/daŋ niː/
‘stone’
/hin/
Expected
Observed
Conformance
 
‘to follow’
/taːm/
‘sickness’
/păɲaːt/
‘to change’
/pian/
‘even though’
/mɛːn waː/
‘to butt in’
/swɛː/
‘to embroider’
/sɛːw/
‘broom, whisk’
/ɲuː/
‘to have’
/miː/
‘pig’
/muː/
‘bear’ (n.)
/miː/
Expected
Observed
Conformance
 

‘husband’
/pʰua/
‘to cast’
(in metal)
/lɔː/

‘to come’
/maː/

‘to hit’
/hai/

‘city’
/wiaŋ/
‘to carry
by the handles’
/haːm/

‘black’
/dam/

‘dog’
/maː/
‘to prostrate
oneself’
/kʰaːp/

‘indefatigable’
/pʰam/
Expected
Observed
Conformance
 
‘garland’;
‘Mekong’
/kʰɔːŋ/

‘ascetic’
/sălom/

‘to embrace’
/săluam/

‘to eat’
/mam/

‘mine’ (n.)
/mɯaŋ/

‘to despise’
/ɲɯaŋ/

‘many’
/laːi/
Expected
Observed
Conformance

SHLANA–3: Tai Tham Words from L2/07-007R

Like in SHLANA-1 and SHLANA-2, the following Tai Tham words have been taken from Revised proposal for encoding the Lanna script in the BMP of the UCS, ISO/IEC JTC1/SC2/WG2/N3207R, L2/07-007R (Everson, Hosken & Constable). However, unlike above, L2/07-007R does not indicate a particular sequence of Unicode codepoints for these words. As before, the test font has been contributed by Richard Wordingham, whose browser test page for Tai Tham rendering gives more background for each test case.
‘golf’
/kɔp/
‘golf’
/kɔp/
‘golf’
/kɔp/
‘graph’
/kaːp/
‘toffee’ ‘pregnant’
/kap pʰa?/
‘shape’
/san tʰaːn/
‘government’
/rat tʰa baːn/
‘government’
/rat tʰa baːn/
‘omniscience’
/sap paʔ/
Expected
Observed
Conformance
 
‘mango’
/ʔam paʔ/
Rajabhat’
/la:t tɕa pʰat/
‘disciple’
"banop burus"
Expected
Observed
Conformance

SHLANA–4: Tai Tham Sign Mai Lang Kai

The Tai Tham codepoint U+1A58 TAI THAM SIGN MAI LANG KAI is challenging due to its wide range of behaviours. It can behave as a spacing final character (as in modern Tai Khün fonts) to a repha-like character, the old-fashioned behaviour seen in Tai Khün, Thailand and Laos. The MFL dictionary shows an intermediate behaviour, where marks above the following base consonant cause it to be positioned within the previous syllable. This is the style employed by the test font, which has been contributed by Richard Wordingham and whose browser test page for Tai Tham rendering gives more background.

‘all’
/taŋ laːi/
Nominative of
Pali ‹saṅgha›
‹saṅgho›

‘ray’
/raŋ siː/
Expected
Observed
Conformance

SHLANA–5: Tai Tham Ligature Naa

Again, the test font and the test cases have been contributed by Richard Wordingham whose browser test page for Tai Tham rendering discusses each case.

‘to lead’
/nam/

‘heart’, ‘mind’
/maʔ no:/
‘to sew
a long stitch’
/nau/

‘leader’
/na:i/

Nan
/na:n/

‘Indra’
/ʔin ta:/

‘danger’
/ʔon tʰaʔ la:i/

‘water’
/nam/
‘to falsely
accuse’
/nwaːp/

‘to foretell’
/tam nwaːi/
Expected
Observed
Conformance
 
‘to foretell’
/tam nwaːi/
‘rice field’
/naː/
‘face’
/naː/
Expected
Observed
Conformance

SHLANA–6: English Loanwords in Tai Tham

These examples are taken from ภาษาเมืองล้านนา, ISBN 974-85472-0-5, pages 151 to 156. Some of these renderings are unusual compared with the native tradition, and are included for that reason. The position of RA HAAM is particularly noteworthy. The pronuciations given are guesswork where Siamese practice and Lanna script orthography conflict. Like above, the test font and the test cases have been contributed by Richard Wordingham whose browser test page for Tai Tham rendering discusses each case.
‘gas’
/kɛs/
‘tractor’
/tʰɛːk tʰɤː/
‘note’
/noːt/
‘protein’
/pʰoː tiːn/
‘fuse’
/fiu/
‘postage stamp’
/sa tɛːm/
‘to serve’
/sɤːp/
Expected
Observed
Conformance

SHLANA–7: Tai Lü

The following Tai Lü words are taken from Veomany Khotsimeuang, A Lost Tradition: The Lue of Sipsongpanna and the Written Language Reform, Hours Thesis in Asian Studies (Chinese), Australian National University, 2001; chapter “Graphic Blends”, section “Complex Orthographic Rules” (available online). The test font and the encoded test strings have been contributed by Richard Wordingham whose browser test page for Tai Tham rendering gives more background.
‘all’
/taŋ laːi/
‘spell’ (magic)
/kʰan tʰaː/
‘okay’
/kɔː diː/
‘to not come’
/bau maː/
‘to not come’
/bau ma:/
‘to not have’
/bau da:i/
‘How big an area?’
/tsak va:/
‘deceased’
/se: lɛu/
‘Really, is that true?’
/tɛː nɔː/
‘to look this way’
/lɛ maː/
Expected
Observed
Conformance
 
‘hair’
/keː saː/
‘to come and go’
/pai maː/
‘if’
/seː vaː/
‘time’
/veː laː/
‘physical body’
/tʰaː tuʔ/
‘in conclusion’
/tsălɛː/
‘because’
/pɔi vaː/
‘world’
/suŋ saːn/
Expected
Observed
Conformance

SHLANA–8: More Tai Lü

The following Tai Lü words are taken from from the MA thesis Development of Tai Lue Scripts and Orthography by Apiradee Techasiriwan (อภิรดี เตชะศิริวรรณ), which is available online. The pronunciations given are Tai Lü. As with the other Lanna tests, the font and the encoded strings have been contributed by Richard Wordingham whose browser test page for Tai Tham rendering gives more background.
‘father’
/pɔː/
‘content’, ‘well’
/săbaːi/
‘city’
/weŋ/
‘person’
/kun/
‘Sipsongpanna’
/sip.sɔːŋ.pan.naː/
‘to go to the location’
/pai paːi/
Kengtung
/tseŋ tuŋ/
‘matter’
/wat tʰu/
‘matter’
/wat tʰu/
‘one’
/deu/
Expected
Observed
Conformance
 
‘debt’
/niː/
‘auspicious occasion’
/hɤːk/
‘to learn’
/heːn/
Expected
Observed
Conformance

SHLANA–9: And Not

The word typically meaning ‘and ... not’ or ‘and ... then’ may be written with a chained syllable, and this may present challenges to renderers. The form of the letter representing /b/ in a chained syllable presented an encoding challenge. N3207R proposed using the sequence ‹SAKOT, BA› for it, and using ‹SAKOT, HIGH PA› for the subscript form corresponding to both BA (common) and HIGH PA (extremely rare) in its rôle as a final (Thai sakot) consonant. During the ISO process, a new character was introduced instead for the special form, SIGN BA, and it is widely assumed that ‹SAKOT, BA› represents the usual subscript form corresponding to BA, both as a sakot consonant and in the Pali /mp/ and /pp/ intervocalic clusters.
When syllables are chained, shared vowel symbols are not repeated. This leads to ambiguity as to which symbol is dropped. All the spellings in the table below represent the same careful pronuciation in Northern Thai, namely /kɔː bɔː/. The Tai Lü forms are written with different marks and pronounced with different vowels, but use the same two consonant forms in the stack.
As with the other Lanna tests, the font and the encoded strings have been contributed by Richard Wordingham whose browser test page for Tai Tham rendering gives more background.
1A23 1A74 1A37
1A74 1A75
1A23 1A74
1A37 1A74
1A23 1A5D
1A74 1A75
1A23 1A74
1A5D 1A75
1A23 1A5D
1A74
1A23 1A74 1A5D
Expected
Observed
Conformance

SHLANA–10: Potential Surprises

These words have caused rendering problems with existing shaping engines such as HarfBuzz bug 364 or Microsoft Typography bug 181. As with the other Lanna tests, the font and the encoded strings have been contributed by Richard Wordingham whose browser test page for Tai Tham rendering gives more background.
‘very much’
/lɛː/
‘to take’
/ʔau/
‘very hot’
/ʔau/
‘listen to me’
/duː haː/
‘March’
/dɯan pʰon laʔ kun/
‘Pabol’ (sic)
/paː boːn/
‘little’
/nɔːi/
Nonsense word
/pʰiʔ luʔ pʰiʔ luʔ/
‘big’
/luaŋ/
‘iron’
/lwaː/
Expected
Observed
Conformance
 
a type of sound
/pʰiaʔ/
‘to prosper’
/kaːn kuŋ/
a satang coin
/ʔat/
‘rank’
/sak/
‘rank’
/sak/
‘giant fennel’
/ma haː hiŋ/
‘giant fennel’
/ma haː hiŋ/
‘science’
/saːt/
‘science’
/saːt/
‘image’
/huːp/
Expected
Observed
Conformance
 
‘relatives’
/piː nɔːŋ/
‘mouth’
/paːk/
‘child’ (progeny)
/luːk/
‘flower’
/dɔːk/
‘flower’
/dɔːk/
‘group’
/puak/
‘wasp’, ‘hornet’
/tɛːn tɔː/
‘wasp’, ‘hornet’
/tɔː tɛːn/
‘wasp’, ‘hornet’
/tɔː tɛːn/
‘street’
/sănon/
Expected
Observed
Conformance
 
‘scripture’
/kam piː/
‘nirvana’
/nip paːn/
‘saintly’
/tʰam miʔ kaʔ/
‘stupa’ (?)
/sătʰup/
‘special’
/wiʔ seːt/
‘slave’
/kʰaː/
‘religion’
/saː saʔ naː/
‘religion’
/saː saʔ naː/
‘javelin’
/sănau/
‘javelin’
/sănau/
Expected
Observed
Conformance
 
‘to beat
to death’
/tiː taːi/
‘Grub’s up!’
/mam mam/
‘trickery’
/leːs/
Pali ‹Anāthapiṇḍikassa› (no meaning)
/dam dam/
din-dins
/mam mam/
(no meaning)
/dam dam/
Expected
Observed
Conformance