[morx] Implement InsertionMorphAction

This commit is contained in:
Sascha Brawer 2017-10-31 13:54:30 +01:00
parent 17e627e366
commit 5f03a64a57
2 changed files with 138 additions and 0 deletions

View File

@ -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):

View File

@ -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())