[morx] Implement InsertionMorphAction
This commit is contained in:
parent
17e627e366
commit
5f03a64a57
@ -317,6 +317,107 @@ class LigatureMorphAction(AATAction):
|
|||||||
xmlWriter.newline()
|
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):
|
class FeatureParams(BaseTable):
|
||||||
|
|
||||||
def compile(self, writer, font):
|
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__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
sys.exit(unittest.main())
|
sys.exit(unittest.main())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user