[morx] Implement InsertionMorphAction
This commit is contained in:
parent
17e627e366
commit
5f03a64a57
@ -317,6 +317,107 @@ class LigatureMorphAction(AATAction):
|
||||
xmlWriter.newline()
|
||||
|
||||
|
||||
class InsertionMorphAction(AATAction):
|
||||
staticSize = 8
|
||||
|
||||
_FLAGS = ["SetMark", "DontAdvance",
|
||||
"CurrentIsKashidaLike", "MarkedIsKashidaLike",
|
||||
"CurrentInsertBefore", "MarkedInsertBefore"]
|
||||
|
||||
def __init__(self):
|
||||
self.NewState = 0
|
||||
for flag in self._FLAGS:
|
||||
setattr(self, flag, False)
|
||||
self.ReservedFlags = 0
|
||||
self.CurrentInsertionAction, self.MarkedInsertionAction = [], []
|
||||
|
||||
def compile(self, writer, font, actionIndex):
|
||||
assert actionIndex is not None
|
||||
writer.writeUShort(self.NewState)
|
||||
flags = self.ReservedFlags
|
||||
if self.SetMark: flags |= 0x8000
|
||||
if self.DontAdvance: flags |= 0x4000
|
||||
if self.CurrentIsKashidaLike: flags |= 0x2000
|
||||
if self.MarkedIsKashidaLike: flags |= 0x1000
|
||||
if self.CurrentInsertBefore: flags |= 0x0800
|
||||
if self.MarkedInsertBefore: flags |= 0x0400
|
||||
flags |= len(self.CurrentInsertionAction) << 5
|
||||
flags |= len(self.MarkedInsertionAction)
|
||||
writer.writeUShort(flags)
|
||||
if len(self.CurrentInsertionAction) > 0:
|
||||
currentIndex = actionIndex[
|
||||
tuple(self.CurrentInsertionAction)]
|
||||
else:
|
||||
currentIndex = 0xFFFF
|
||||
writer.writeUShort(currentIndex)
|
||||
if len(self.MarkedInsertionAction) > 0:
|
||||
markedIndex = actionIndex[
|
||||
tuple(self.MarkedInsertionAction)]
|
||||
else:
|
||||
markedIndex = 0xFFFF
|
||||
writer.writeUShort(markedIndex)
|
||||
|
||||
def decompile(self, reader, font, actionReader):
|
||||
assert actionReader is not None
|
||||
self.NewState = reader.readUShort()
|
||||
flags = reader.readUShort()
|
||||
self.SetMark = bool(flags & 0x8000)
|
||||
self.DontAdvance = bool(flags & 0x4000)
|
||||
self.CurrentIsKashidaLike = bool(flags & 0x2000)
|
||||
self.MarkedIsKashidaLike = bool(flags & 0x1000)
|
||||
self.CurrentInsertBefore = bool(flags & 0x0800)
|
||||
self.MarkedInsertBefore = bool(flags & 0x0400)
|
||||
self.CurrentInsertionAction = self._decompileInsertionAction(
|
||||
actionReader, font,
|
||||
index=reader.readUShort(),
|
||||
count=((flags & 0x03E0) >> 5))
|
||||
self.MarkedInsertionAction = self._decompileInsertionAction(
|
||||
actionReader, font,
|
||||
index=reader.readUShort(),
|
||||
count=(flags & 0x001F))
|
||||
|
||||
def _decompileInsertionAction(self, actionReader, font, index, count):
|
||||
if index == 0xFFFF or count == 0:
|
||||
return []
|
||||
reader = actionReader.getSubReader(
|
||||
actionReader.pos + index * 2)
|
||||
return [font.getGlyphName(glyphID)
|
||||
for glyphID in reader.readUShortArray(count)]
|
||||
|
||||
def toXML(self, xmlWriter, font, attrs, name):
|
||||
xmlWriter.begintag(name, **attrs)
|
||||
xmlWriter.newline()
|
||||
xmlWriter.simpletag("NewState", value=self.NewState)
|
||||
xmlWriter.newline()
|
||||
self._writeFlagsToXML(xmlWriter)
|
||||
for g in self.CurrentInsertionAction:
|
||||
xmlWriter.simpletag("CurrentInsertionAction", glyph=g)
|
||||
xmlWriter.newline()
|
||||
for g in self.MarkedInsertionAction:
|
||||
xmlWriter.simpletag("MarkedInsertionAction", glyph=g)
|
||||
xmlWriter.newline()
|
||||
xmlWriter.endtag(name)
|
||||
xmlWriter.newline()
|
||||
|
||||
def fromXML(self, name, attrs, content, font):
|
||||
self.__init__()
|
||||
content = [t for t in content if isinstance(t, tuple)]
|
||||
for eltName, eltAttrs, eltContent in content:
|
||||
if eltName == "NewState":
|
||||
self.NewState = safeEval(eltAttrs["value"])
|
||||
elif eltName == "Flags":
|
||||
for flag in eltAttrs["value"].split(","):
|
||||
self._setFlag(flag.strip())
|
||||
elif eltName == "CurrentInsertionAction":
|
||||
self.CurrentInsertionAction.append(
|
||||
eltAttrs["glyph"])
|
||||
elif eltName == "MarkedInsertionAction":
|
||||
self.MarkedInsertionAction.append(
|
||||
eltAttrs["glyph"])
|
||||
else:
|
||||
assert False, eltName
|
||||
|
||||
|
||||
class FeatureParams(BaseTable):
|
||||
|
||||
def compile(self, writer, font):
|
||||
|
@ -448,6 +448,43 @@ class LigatureMorphActionTest(unittest.TestCase):
|
||||
])
|
||||
|
||||
|
||||
class InsertionMorphActionTest(unittest.TestCase):
|
||||
MORPH_ACTION_XML = [
|
||||
'<Transition Test="Foo">',
|
||||
' <NewState value="4660"/>', # 0x1234 = 4660
|
||||
' <Flags value="SetMark,DontAdvance,CurrentIsKashidaLike,'
|
||||
'MarkedIsKashidaLike,CurrentInsertBefore,MarkedInsertBefore"/>',
|
||||
' <CurrentInsertionAction glyph="B"/>',
|
||||
' <CurrentInsertionAction glyph="C"/>',
|
||||
' <MarkedInsertionAction glyph="B"/>',
|
||||
' <MarkedInsertionAction glyph="A"/>',
|
||||
' <MarkedInsertionAction glyph="D"/>',
|
||||
'</Transition>'
|
||||
]
|
||||
|
||||
def setUp(self):
|
||||
self.font = FakeFont(['.notdef', 'A', 'B', 'C', 'D'])
|
||||
self.maxDiff = None
|
||||
|
||||
def testDecompileToXML(self):
|
||||
a = otTables.InsertionMorphAction()
|
||||
actionReader = OTTableReader(
|
||||
deHexStr("DEAD BEEF 0002 0001 0004 0002 0003 DEAD BEEF"))
|
||||
a.decompile(OTTableReader(deHexStr("1234 FC43 0005 0002")),
|
||||
self.font, actionReader)
|
||||
toXML = lambda w, f: a.toXML(w, f, {"Test": "Foo"}, "Transition")
|
||||
self.assertEqual(getXML(toXML, self.font), self.MORPH_ACTION_XML)
|
||||
|
||||
def testCompileFromXML(self):
|
||||
a = otTables.InsertionMorphAction()
|
||||
for name, attrs, content in parseXML(self.MORPH_ACTION_XML):
|
||||
a.fromXML(name, attrs, content, self.font)
|
||||
writer = OTTableWriter()
|
||||
a.compile(writer, self.font,
|
||||
actionIndex={('B', 'C'): 9, ('B', 'A', 'D'): 7})
|
||||
self.assertEqual(hexStr(writer.getAllData()), "1234fc4300090007")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
sys.exit(unittest.main())
|
||||
|
Loading…
x
Reference in New Issue
Block a user