Repository navigation
Reverse right-to-left text in fonts without GSUB, GPOS or morx (#39) - #415
Conversation
| @@ -0,0 +1,31 @@ | |||
| NotoKufiArabic-NoLayout.ttf is derived from NotoKufiArabic-Regular.ttf in this | |||
There was a problem hiding this comment.
Is there a existing font in the code base that can be used to test this behavior?
There was a problem hiding this comment.
Partly. FontkitMarkFallbackTest-Italic.ttf has no GSUB or GPOS, and the change only depends on the direction, so with direction: 'rtl' it covers the order and the marks. It matches hb-shape --direction=rtl --script=hebr:
| Text | fontkit / HarfBuzz |
|---|---|
abx |
x, b, a |
q + U+0323 + U+0307 |
dot above @899,-53, dot below @899,-375, q |
I moved those tests to it in d3f18d9.
Kerning still needs the new font. None of the test fonts without layout tables has a kern table, so nothing else can show that the pairs are now kerned in visual order. That's all NotoKufiArabic-NoLayout.ttf is used for now. If you'd rather not add a font, I can drop that test.
There was a problem hiding this comment.
Thanks. Keep the new font. Please rebase so i can merge
d3f18d9 to
06b11cd
Compare
|
Rebased on master. The only conflict was the changelog, and the tests pass. |
Fixes #39
When a font has no GSUB, GPOS or morx table,
LayoutEnginehas no advanced layout engine, and nothing reverses right-to-left text.OTLayoutEngine.positionandAATLayoutEngine.substituteboth reverse the glyphs fordirection: 'rtl', but without either,layout()returns the glyphs in logical order while the run saysrtl. As a result:kerntable, which runs after that point, kerns logical pairs instead of the pairs that are drawn.UnicodeLayoutEngineoffsets each mark back by its base's advance, which is right for left-to-right text but not once the run is reversed and the mark is drawn before its base.The change:
LayoutEngine.positionreverses the glyphs and positions when there's no engine and the direction isrtl. It does that after the fallback mark positioning, which works in logical order, and before kerning, so kern pairs are visual like in HarfBuzz and in the two engines.UnicodeLayoutEngine.positionGlyphstakes the direction. Forrtlthe marks are offset from the base's origin, as HarfBuzz'sposition_around_basedoes for backward text (no-base.xAdvance, and spacing marks in between add their advance instead of subtracting it). The OpenType path still passes'ltr', so its output doesn't change.With
test/data/NotoSans/NotoKufiArabic-NoLayout.ttf(glyph, x offset, y offset, advance):بتمال(kern lam + alef = -150)لابَ(HarfBuzz splits the -150 as -75 on each glyph, so its advances differ per glyph, but the total is the same; fontkit puts the whole kern on the first glyph as before.)
I also checked the issue's Hebrew against HarfBuzz with Taamey Frank CLM from the test data, with its GSUB, GPOS, GDEF and kern tables removed (not committed).
עבריתandשלום 2024now match HarfBuzz glyph for glyph. With nikud, every mark both engines draw has the same offset. HarfBuzz composes some pairs (shin + shin dot) into precomposed glyphs, which fontkit doesn't do without an engine. That isn't part of this change.Not in this change:
KernProcessoronly kerns adjacent glyphs, so a mark between two kerned letters (اَل) still blocks the pair, as it does in left-to-right text. In the OpenType path the glyphs are already reversed when the fallback mark positioning runs, so right-to-left fonts with GSUB but no GPOS still lose their mark positions: with GPOS removed fromNotoKufiArabic-Regular.ttf, the fatha ofبَstays at 0,0, where HarfBuzz puts it at 796,-234. I can send that separately.Tests:
test/issues.js"#39 - right-to-left text in fonts without GSUB, GPOS or morx". Order, marks andltrstaying in logical order useFontkitMarkFallbackTest-Italic.ttf, which is already in the test data, withdirection: 'rtl'; the values matchhb-shape --direction=rtl --script=hebr. Kerning in visual order usesNotoKufiArabic-NoLayout.ttf, because none of the existing test fonts without layout tables has akerntable. It is a 2 KB subset ofNotoKufiArabic-Regular.ttfwith its GSUB, GPOS and GDEF tables removed and a one-pair kern table added, andNotoKufiArabic-NoLayout.txtnext to it notes the license and the fontTools script that made it. The reverse, mark and kern tests fail before the change.Validation:
npm run format:checkpassesnpm test: 695 passing, 7 pending