joining
Mojo module đźˇ
joining
Arabic joining: which contextual form – isolated, initial, medial or final – each letter of a run takes from the letters beside it. An Arabic font ships four glyphs for a dual-joining letter and states the choice between them as GSUB isol/init/medi/fina features; this module decides which of the four each character is eligible for, so ttf.mojo can enable that one feature on that one glyph.
The algorithm is the Unicode Standard’s (chapter 9, “Arabic Cursive
Joining”), over the Joining_Type property ArabicShaping.txt
defines:
- D dual-joining – joins on both sides (most letters: beh, seen, meem)
- R right-joining – joins only to the preceding letter (alef, dal, waw)
- L left-joining – joins only to the following letter; no Arabic letter is L, and it is here for completeness
- C join-causing – joins on both sides and takes no form of its own (tatweel U+0640, ZWJ U+200D)
- U non-joining – breaks a join (ZWNJ U+200C, digits, punctuation, every character outside the covered blocks)
- T transparent – skipped when looking for a neighbor, so a vowel mark between two letters does not break their join (the harakat, and every other combining mark)
Ranges covered, from ArabicShaping.txt plus its stated default (a
character it does not list is T when its General_Category is Mn, Me or
Cf, and U otherwise):
- U+0600..U+06FF Arabic
- U+0750..U+077F Arabic Supplement
- U+0870..U+089F Arabic Extended-B
- U+08A0..U+08FF Arabic Extended-A
- U+200D ZERO WIDTH JOINER (C) and U+FEFF ZERO WIDTH NO-BREAK SPACE (T); U+200C ZERO WIDTH NON-JOINER is U, which is the default and needs no entry
Everything else is non-joining. That leaves out the other cursive
scripts ArabicShaping.txt also covers – Syriac, N’Ko, Mandaic,
Manichaean, Mongolian, Adlam – whose letters classify as U here and
so stay in their isolated forms, and the Arabic presentation-form
blocks (U+FB50..U+FDFF, U+FE70..U+FEFF), whose characters are
non-joining: they encode a form directly rather than taking one from
context.