1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
from .BaseShaper import BaseShaper
from youseedee import ucd_data
jts = {"U": 0, "L": 1, "R": 2, "D": 3, "ALAPH": 4, "DALATH_RISH": 5}
state_table = [
# jt_U, jt_L, jt_R, jt_D, jg_ALAPH, jg_DALATH_RISH */
# State 0: prev was U, not willing to join.
[
("none", "none", 0),
("none", "isol", 2),
("none", "isol", 1),
("none", "isol", 2),
("none", "isol", 1),
("none", "isol", 6),
],
# State 1: prev was R or ISOL/ALAPH, not willing to join.
[
("none", "none", 0),
("none", "isol", 2),
("none", "isol", 1),
("none", "isol", 2),
("none", "fin2", 5),
("none", "isol", 6),
],
# State 2: prev was D/L in ISOL form, willing to join.
[
("none", "none", 0),
("none", "isol", 2),
("init", "fina", 1),
("init", "fina", 3),
("init", "fina", 4),
("init", "fina", 6),
],
# State 3: prev was D in FINA form, willing to join.
[
("none", "none", 0),
("none", "isol", 2),
("medi", "fina", 1),
("medi", "fina", 3),
("medi", "fina", 4),
("medi", "fina", 6),
],
# State 4: prev was FINA ALAPH, not willing to join.
[
("none", "none", 0),
("none", "isol", 2),
("med2", "isol", 1),
("med2", "isol", 2),
("med2", "fin2", 5),
("med2", "isol", 6),
],
# State 5: prev was FIN2/FIN3 ALAPH, not willing to join.
[
("none", "none", 0),
("none", "isol", 2),
("isol", "isol", 1),
("isol", "isol", 2),
("isol", "fin2", 5),
("isol", "isol", 6),
],
# State 6: prev was DALATH/RISH, not willing to join.
[
("none", "none", 0),
("none", "isol", 2),
("none", "isol", 1),
("none", "isol", 2),
("none", "fin3", 5),
("none", "isol", 6),
],
]
arabic_features = ["isol", "fina", "fin2", "fin3", "medi", "med2", "init"]
class ArabicShaper(BaseShaper):
def collect_features(self, shaper):
# shaper.add_features("stch")
shaper.add_features("ccmp", "locl")
shaper.add_pause()
shaper.add_features(*arabic_features)
shaper.add_pause()
shaper.add_features("rlig", "rclt", "calt")
shaper.add_pause()
shaper.add_features("mset")
def substitute_default(self):
super().substitute_default()
state = 0
prev_item = None
for item in self.buffer.items:
item.arabic_joining = "NONE"
ucd = ucd_data(item.codepoint)
joining = ucd.get("Joining_Type")
if not joining:
if ucd.get("General_Category") in ["Mn", "Cf", "Em"]:
joining = "T"
else:
joining = "U"
if joining == "T":
continue
if joining == "C":
joining = "D" # Mongolian
if ucd.get("Joining_Group") == "ALAPH":
joining = "ALAPH"
if ucd.get("Joining_Group") == "DALATH RISH":
joining = "DALATH_RISH"
prev, this, state = state_table[state][jts[joining]]
if prev_item:
prev_item.arabic_joining = prev
item.arabic_joining = this
prev_item = item
if self.buffer.script == "Mongolian":
self.mongolian_variation_selectors()
self.plan.msg(
"Assigned Arabic joining", self.buffer, serialize_options=["arabic_joining"]
)
for f in arabic_features:
if f not in self.plan.fontfeatures.features:
continue
for item in self.buffer.items:
item.feature_masks[f] = item.arabic_joining != f
def mongolian_variation_selectors(self):
for ix, item in enumerate(self.buffer.items):
if 0x180B <= item.codepoint <= 0x180D and ix > 0:
item.arabic_joining = self.buffer.items[ix - 1].arabic_joining
|