def test_buildPairPosClassesSubtable(self): d20 = builder.buildValue({"XPlacement": -20}) d50 = builder.buildValue({"XPlacement": -50}) d0 = builder.buildValue({}) d8020 = builder.buildValue({"XPlacement": -80, "YPlacement": -20}) subtable = builder.buildPairPosClassesSubtable( { (tuple("A"), tuple(["zero"])): (d0, d50), (tuple("A"), tuple(["one", "two"])): (None, d20), (tuple(["B", "C"]), tuple(["zero"])): (d8020, d50), }, self.GLYPHMAP, ) assert getXML(subtable.toXML) == [ '<PairPos Format="2">', " <Coverage>", ' <Glyph value="A"/>', ' <Glyph value="B"/>', ' <Glyph value="C"/>', " </Coverage>", ' <ValueFormat1 value="3"/>', ' <ValueFormat2 value="1"/>', " <ClassDef1>", ' <ClassDef glyph="A" class="1"/>', " </ClassDef1>", " <ClassDef2>", ' <ClassDef glyph="one" class="1"/>', ' <ClassDef glyph="two" class="1"/>', ' <ClassDef glyph="zero" class="2"/>', " </ClassDef2>", " <!-- Class1Count=2 -->", " <!-- Class2Count=3 -->", ' <Class1Record index="0">', ' <Class2Record index="0">', " </Class2Record>", ' <Class2Record index="1">', " </Class2Record>", ' <Class2Record index="2">', ' <Value1 XPlacement="-80" YPlacement="-20"/>', ' <Value2 XPlacement="-50"/>', " </Class2Record>", " </Class1Record>", ' <Class1Record index="1">', ' <Class2Record index="0">', " </Class2Record>", ' <Class2Record index="1">', ' <Value2 XPlacement="-20"/>', " </Class2Record>", ' <Class2Record index="2">', " <Value1/>", ' <Value2 XPlacement="-50"/>', " </Class2Record>", " </Class1Record>", "</PairPos>", ]
def test_getSinglePosValueKey(self): device = builder.buildDevice({10: 1, 11: 3}) a1 = builder.buildValue({"XPlacement": 500, "XPlaDevice": device}) a2 = builder.buildValue({"XPlacement": 500, "XPlaDevice": device}) b = builder.buildValue({"XPlacement": 500}) keyA1 = builder._getSinglePosValueKey(a1) keyA2 = builder._getSinglePosValueKey(a1) keyB = builder._getSinglePosValueKey(b) assert keyA1 == keyA2 assert hash(keyA1) == hash(keyA2) assert keyA1 != keyB assert hash(keyA1) != hash(keyB)
def test_getSinglePosValueKey(self): device = builder.buildDevice({10:1, 11:3}) a1 = builder.buildValue({"XPlacement": 500, "XPlaDevice": device}) a2 = builder.buildValue({"XPlacement": 500, "XPlaDevice": device}) b = builder.buildValue({"XPlacement": 500}) keyA1 = builder._getSinglePosValueKey(a1) keyA2 = builder._getSinglePosValueKey(a1) keyB = builder._getSinglePosValueKey(b) self.assertEqual(keyA1, keyA2) self.assertEqual(hash(keyA1), hash(keyA2)) self.assertNotEqual(keyA1, keyB) self.assertNotEqual(hash(keyA1), hash(keyB))
def test_getSinglePosValueKey(self): device = builder.buildDevice([(10, 1), (11, 3)]) a1 = builder.buildValue({"XPlacement": 500, "XPlaDevice": device}) a2 = builder.buildValue({"XPlacement": 500, "XPlaDevice": device}) b = builder.buildValue({"XPlacement": 500}) keyA1 = builder._getSinglePosValueKey(a1) keyA2 = builder._getSinglePosValueKey(a1) keyB = builder._getSinglePosValueKey(b) self.assertEqual(keyA1, keyA2) self.assertEqual(hash(keyA1), hash(keyA2)) self.assertNotEqual(keyA1, keyB) self.assertNotEqual(hash(keyA1), hash(keyB))
def test_buildPairPosClassesSubtable(self): d20 = builder.buildValue({"XPlacement": -20}) d50 = builder.buildValue({"XPlacement": -50}) d0 = builder.buildValue({}) d8020 = builder.buildValue({"XPlacement": -80, "YPlacement": -20}) subtable = builder.buildPairPosClassesSubtable( { (frozenset("A"), frozenset(["zero"])): (d0, d50), (frozenset("A"), frozenset(["one", "two"])): (None, d20), (frozenset(["B", "C"]), frozenset(["zero"])): (d8020, d50), }, self.GLYPHMAP) self.maxDiff = None self.assertEqual( getXML(subtable.toXML), '<PairPos Format="2">' ' <Coverage>' ' <Glyph value="A"/>' ' <Glyph value="B"/>' ' <Glyph value="C"/>' ' </Coverage>' ' <ValueFormat1 value="3"/>' ' <ValueFormat2 value="1"/>' ' <ClassDef1>' ' <ClassDef glyph="A" class="1"/>' ' </ClassDef1>' ' <ClassDef2>' ' <ClassDef glyph="one" class="1"/>' ' <ClassDef glyph="two" class="1"/>' ' <ClassDef glyph="zero" class="2"/>' ' </ClassDef2>' ' <!-- Class1Count=2 -->' ' <!-- Class2Count=3 -->' ' <Class1Record index="0">' ' <Class2Record index="0">' ' </Class2Record>' ' <Class2Record index="1">' ' </Class2Record>' ' <Class2Record index="2">' ' <Value1 XPlacement="-80" YPlacement="-20"/>' ' <Value2 XPlacement="-50"/>' ' </Class2Record>' ' </Class1Record>' ' <Class1Record index="1">' ' <Class2Record index="0">' ' </Class2Record>' ' <Class2Record index="1">' ' <Value2 XPlacement="-20"/>' ' </Class2Record>' ' <Class2Record index="2">' ' <Value1/>' ' <Value2 XPlacement="-50"/>' ' </Class2Record>' ' </Class1Record>' '</PairPos>')
def test_buildPairPosClassesSubtable(self): d20 = builder.buildValue({"XPlacement": -20}) d50 = builder.buildValue({"XPlacement": -50}) d0 = builder.buildValue({}) d8020 = builder.buildValue({"XPlacement": -80, "YPlacement": -20}) subtable = builder.buildPairPosClassesSubtable({ (tuple("A",), tuple(["zero"])): (d0, d50), (tuple("A",), tuple(["one", "two"])): (None, d20), (tuple(["B", "C"]), tuple(["zero"])): (d8020, d50), }, self.GLYPHMAP) self.maxDiff = None self.assertEqual(getXML(subtable.toXML), '<PairPos Format="2">' ' <Coverage>' ' <Glyph value="A"/>' ' <Glyph value="B"/>' ' <Glyph value="C"/>' ' </Coverage>' ' <ValueFormat1 value="3"/>' ' <ValueFormat2 value="1"/>' ' <ClassDef1>' ' <ClassDef glyph="A" class="1"/>' ' </ClassDef1>' ' <ClassDef2>' ' <ClassDef glyph="one" class="1"/>' ' <ClassDef glyph="two" class="1"/>' ' <ClassDef glyph="zero" class="2"/>' ' </ClassDef2>' ' <!-- Class1Count=2 -->' ' <!-- Class2Count=3 -->' ' <Class1Record index="0">' ' <Class2Record index="0">' ' </Class2Record>' ' <Class2Record index="1">' ' </Class2Record>' ' <Class2Record index="2">' ' <Value1 XPlacement="-80" YPlacement="-20"/>' ' <Value2 XPlacement="-50"/>' ' </Class2Record>' ' </Class1Record>' ' <Class1Record index="1">' ' <Class2Record index="0">' ' </Class2Record>' ' <Class2Record index="1">' ' <Value2 XPlacement="-20"/>' ' </Class2Record>' ' <Class2Record index="2">' ' <Value1/>' ' <Value2 XPlacement="-50"/>' ' </Class2Record>' ' </Class1Record>' '</PairPos>')
def test_buildSinglePosSubtable_format1(self): subtable = builder.buildSinglePosSubtable({ "one": builder.buildValue({"XPlacement": 777}), "two": builder.buildValue({"XPlacement": 777}), }, self.GLYPHMAP) self.assertEqual(getXML(subtable.toXML), '<SinglePos Format="1">' ' <Coverage>' ' <Glyph value="one"/>' ' <Glyph value="two"/>' ' </Coverage>' ' <ValueFormat value="1"/>' ' <Value XPlacement="777"/>' '</SinglePos>')
def test_buildSinglePosSubtable_format2(self): subtable = builder.buildSinglePosSubtable({ "one": builder.buildValue({"XPlacement": 777}), "two": builder.buildValue({"YPlacement": -888}), }, self.GLYPHMAP) self.assertEqual(getXML(subtable.toXML), '<SinglePos Format="2">' ' <Coverage>' ' <Glyph value="one"/>' ' <Glyph value="two"/>' ' </Coverage>' ' <ValueFormat value="3"/>' ' <!-- ValueCount=2 -->' ' <Value index="0" XPlacement="777"/>' ' <Value index="1" YPlacement="-888"/>' '</SinglePos>')
def test_buildPairPosGlyphsSubtable(self): d20 = builder.buildValue({"XPlacement": -20}) d50 = builder.buildValue({"XPlacement": -50}) d0 = builder.buildValue({}) d8020 = builder.buildValue({"XPlacement": -80, "YPlacement": -20}) subtable = builder.buildPairPosGlyphsSubtable( { ("A", "zero"): (d0, d50), ("A", "one"): (None, d20), ("B", "five"): (d8020, d50), }, self.GLYPHMAP, ) assert getXML(subtable.toXML) == [ '<PairPos Format="1">', " <Coverage>", ' <Glyph value="A"/>', ' <Glyph value="B"/>', " </Coverage>", ' <ValueFormat1 value="3"/>', ' <ValueFormat2 value="1"/>', " <!-- PairSetCount=2 -->", ' <PairSet index="0">', " <!-- PairValueCount=2 -->", ' <PairValueRecord index="0">', ' <SecondGlyph value="zero"/>', ' <Value2 XPlacement="-50"/>', " </PairValueRecord>", ' <PairValueRecord index="1">', ' <SecondGlyph value="one"/>', ' <Value2 XPlacement="-20"/>', " </PairValueRecord>", " </PairSet>", ' <PairSet index="1">', " <!-- PairValueCount=1 -->", ' <PairValueRecord index="0">', ' <SecondGlyph value="five"/>', ' <Value1 XPlacement="-80" YPlacement="-20"/>', ' <Value2 XPlacement="-50"/>', " </PairValueRecord>", " </PairSet>", "</PairPos>", ]
def test_buildPairPosGlyphs(self): d50 = builder.buildValue({"XPlacement": -50}) d8020 = builder.buildValue({"XPlacement": -80, "YPlacement": -20}) subtables = builder.buildPairPosGlyphs( { ("A", "zero"): (None, d50), ("A", "one"): (d8020, d50), }, self.GLYPHMAP) self.maxDiff = None self.assertEqual( ''.join([getXML(t.toXML) for t in subtables]), '<PairPos Format="1">' ' <Coverage>' ' <Glyph value="A"/>' ' </Coverage>' ' <ValueFormat1 value="0"/>' ' <ValueFormat2 value="1"/>' ' <!-- PairSetCount=1 -->' ' <PairSet index="0">' ' <!-- PairValueCount=1 -->' ' <PairValueRecord index="0">' ' <SecondGlyph value="zero"/>' ' <Value2 XPlacement="-50"/>' ' </PairValueRecord>' ' </PairSet>' '</PairPos>' '<PairPos Format="1">' ' <Coverage>' ' <Glyph value="A"/>' ' </Coverage>' ' <ValueFormat1 value="3"/>' ' <ValueFormat2 value="1"/>' ' <!-- PairSetCount=1 -->' ' <PairSet index="0">' ' <!-- PairValueCount=1 -->' ' <PairValueRecord index="0">' ' <SecondGlyph value="one"/>' ' <Value1 XPlacement="-80" YPlacement="-20"/>' ' <Value2 XPlacement="-50"/>' ' </PairValueRecord>' ' </PairSet>' '</PairPos>')
def test_buildSinglePos_ValueFormat0(self): subtables = builder.buildSinglePos({"zero": builder.buildValue({})}, self.GLYPHMAP) assert sum([getXML(t.toXML) for t in subtables], []) == [ '<SinglePos Format="1">', " <Coverage>", ' <Glyph value="zero"/>', " </Coverage>", ' <ValueFormat value="0"/>', "</SinglePos>", ]
def test_buildSinglePos_ValueFormat0(self): subtables = builder.buildSinglePos({ "zero": builder.buildValue({}) }, self.GLYPHMAP) self.assertEqual(''.join([getXML(t.toXML) for t in subtables]), '<SinglePos Format="1">' ' <Coverage>' ' <Glyph value="zero"/>' ' </Coverage>' ' <ValueFormat value="0"/>' '</SinglePos>')
def test_buildPairPosGlyphs(self): d50 = builder.buildValue({"XPlacement": -50}) d8020 = builder.buildValue({"XPlacement": -80, "YPlacement": -20}) subtables = builder.buildPairPosGlyphs( { ("A", "zero"): (None, d50), ("A", "one"): (d8020, d50) }, self.GLYPHMAP) assert sum([getXML(t.toXML) for t in subtables], []) == [ '<PairPos Format="1">', " <Coverage>", ' <Glyph value="A"/>', " </Coverage>", ' <ValueFormat1 value="0"/>', ' <ValueFormat2 value="1"/>', " <!-- PairSetCount=1 -->", ' <PairSet index="0">', " <!-- PairValueCount=1 -->", ' <PairValueRecord index="0">', ' <SecondGlyph value="zero"/>', ' <Value2 XPlacement="-50"/>', " </PairValueRecord>", " </PairSet>", "</PairPos>", '<PairPos Format="1">', " <Coverage>", ' <Glyph value="A"/>', " </Coverage>", ' <ValueFormat1 value="3"/>', ' <ValueFormat2 value="1"/>', " <!-- PairSetCount=1 -->", ' <PairSet index="0">', " <!-- PairValueCount=1 -->", ' <PairValueRecord index="0">', ' <SecondGlyph value="one"/>', ' <Value1 XPlacement="-80" YPlacement="-20"/>', ' <Value2 XPlacement="-50"/>', " </PairValueRecord>", " </PairSet>", "</PairPos>", ]
def test_buildPairPosGlyphs(self): d50 = builder.buildValue({"XPlacement": -50}) d8020 = builder.buildValue({"XPlacement": -80, "YPlacement": -20}) subtables = builder.buildPairPosGlyphs({ ("A", "zero"): (None, d50), ("A", "one"): (d8020, d50), }, self.GLYPHMAP) self.maxDiff = None self.assertEqual(''.join([getXML(t.toXML) for t in subtables]), '<PairPos Format="1">' ' <Coverage>' ' <Glyph value="A"/>' ' </Coverage>' ' <ValueFormat1 value="0"/>' ' <ValueFormat2 value="1"/>' ' <!-- PairSetCount=1 -->' ' <PairSet index="0">' ' <!-- PairValueCount=1 -->' ' <PairValueRecord index="0">' ' <SecondGlyph value="zero"/>' ' <Value2 XPlacement="-50"/>' ' </PairValueRecord>' ' </PairSet>' '</PairPos>' '<PairPos Format="1">' ' <Coverage>' ' <Glyph value="A"/>' ' </Coverage>' ' <ValueFormat1 value="3"/>' ' <ValueFormat2 value="1"/>' ' <!-- PairSetCount=1 -->' ' <PairSet index="0">' ' <!-- PairValueCount=1 -->' ' <PairValueRecord index="0">' ' <SecondGlyph value="one"/>' ' <Value1 XPlacement="-80" YPlacement="-20"/>' ' <Value2 XPlacement="-50"/>' ' </PairValueRecord>' ' </PairSet>' '</PairPos>')
def __init__(self, font: Font, glyph_sets: 'GlyphSets') -> None: glyph_sets.assert_glyphs_are_disjoint() self.left, self.right, self.middle, self.space, self.na_left, self.na_right = ( tuple(font.glyph_names(sorted(glyphs.glyph_id_set))) for glyphs in (glyph_sets.left, glyph_sets.right, glyph_sets.middle, glyph_sets.space, glyph_sets.na_left, glyph_sets.na_right)) em = font.fullwidth_advance # When `em` is an odd number, ceil the advance. To do this, use # floor to compute the adjustment of the advance and the offset. # e.g., "ZCOOL QingKe HuangYou". half_em = math.floor(em / 2) assert half_em > 0 quad_em = math.floor(half_em / 2) if font.is_vertical: self.left_value = buildValue({"YAdvance": -half_em}) self.right_value = buildValue({ "YPlacement": half_em, "YAdvance": -half_em }) self.middle_value = buildValue({ "YPlacement": quad_em, "YAdvance": -half_em }) else: self.left_value = buildValue({"XAdvance": -half_em}) self.right_value = buildValue({ "XPlacement": -half_em, "XAdvance": -half_em }) self.middle_value = buildValue({ "XPlacement": -quad_em, "XAdvance": -half_em })
def makeOpenTypeValueRecord(v): """ast.ValueRecord --> (otBase.ValueRecord, int ValueFormat)""" if v is None: return None, 0 vr = {} for astName, (otName, isDevice) in _VALUEREC_ATTRS.items(): val = getattr(v, astName, None) if val: vr[otName] = otl.buildDevice(dict(val)) if isDevice else val valRec = otl.buildValue(vr) return valRec, valRec.getFormat()
def test_buildPairPosGlyphsSubtable(self): d20 = builder.buildValue({"XPlacement": -20}) d50 = builder.buildValue({"XPlacement": -50}) d0 = builder.buildValue({}) d8020 = builder.buildValue({"XPlacement": -80, "YPlacement": -20}) subtable = builder.buildPairPosGlyphsSubtable({ ("A", "zero"): (d0, d50), ("A", "one"): (None, d20), ("B", "five"): (d8020, d50), }, self.GLYPHMAP) self.assertEqual(getXML(subtable.toXML), '<PairPos Format="1">' ' <Coverage>' ' <Glyph value="A"/>' ' <Glyph value="B"/>' ' </Coverage>' ' <ValueFormat1 value="3"/>' ' <ValueFormat2 value="1"/>' ' <!-- PairSetCount=2 -->' ' <PairSet index="0">' ' <!-- PairValueCount=2 -->' ' <PairValueRecord index="0">' ' <SecondGlyph value="zero"/>' ' <Value2 XPlacement="-50"/>' ' </PairValueRecord>' ' <PairValueRecord index="1">' ' <SecondGlyph value="one"/>' ' <Value2 XPlacement="-20"/>' ' </PairValueRecord>' ' </PairSet>' ' <PairSet index="1">' ' <!-- PairValueCount=1 -->' ' <PairValueRecord index="0">' ' <SecondGlyph value="five"/>' ' <Value1 XPlacement="-80" YPlacement="-20"/>' ' <Value2 XPlacement="-50"/>' ' </PairValueRecord>' ' </PairSet>' '</PairPos>')
def test_buildSinglePos(self): subtables = builder.buildSinglePos( { "one": builder.buildValue({"XPlacement": 500}), "two": builder.buildValue({"XPlacement": 500}), "three": builder.buildValue({"XPlacement": 200}), "four": builder.buildValue({"XPlacement": 400}), "five": builder.buildValue({"XPlacement": 500}), "six": builder.buildValue({"YPlacement": -6}), }, self.GLYPHMAP) self.assertEqual( ''.join([getXML(t.toXML) for t in subtables]), '<SinglePos Format="1">' ' <Coverage>' ' <Glyph value="one"/>' ' <Glyph value="two"/>' ' <Glyph value="five"/>' ' </Coverage>' ' <ValueFormat value="1"/>' ' <Value XPlacement="500"/>' '</SinglePos>' '<SinglePos Format="2">' ' <Coverage>' ' <Glyph value="three"/>' ' <Glyph value="four"/>' ' </Coverage>' ' <ValueFormat value="1"/>' ' <!-- ValueCount=2 -->' ' <Value index="0" XPlacement="200"/>' ' <Value index="1" XPlacement="400"/>' '</SinglePos>' '<SinglePos Format="1">' ' <Coverage>' ' <Glyph value="six"/>' ' </Coverage>' ' <ValueFormat value="2"/>' ' <Value YPlacement="-6"/>' '</SinglePos>')
def test_buildSinglePos(self): subtables = builder.buildSinglePos( { "one": builder.buildValue({"XPlacement": 500}), "two": builder.buildValue({"XPlacement": 500}), "three": builder.buildValue({"XPlacement": 200}), "four": builder.buildValue({"XPlacement": 400}), "five": builder.buildValue({"XPlacement": 500}), "six": builder.buildValue({"YPlacement": -6}), }, self.GLYPHMAP, ) assert sum([getXML(t.toXML) for t in subtables], []) == [ '<SinglePos Format="2">', " <Coverage>", ' <Glyph value="one"/>', ' <Glyph value="two"/>', ' <Glyph value="three"/>', ' <Glyph value="four"/>', ' <Glyph value="five"/>', " </Coverage>", ' <ValueFormat value="1"/>', " <!-- ValueCount=5 -->", ' <Value index="0" XPlacement="500"/>', ' <Value index="1" XPlacement="500"/>', ' <Value index="2" XPlacement="200"/>', ' <Value index="3" XPlacement="400"/>', ' <Value index="4" XPlacement="500"/>', "</SinglePos>", '<SinglePos Format="1">', " <Coverage>", ' <Glyph value="six"/>', " </Coverage>", ' <ValueFormat value="2"/>', ' <Value YPlacement="-6"/>', "</SinglePos>", ]
def test_buildSinglePos(self): subtables = builder.buildSinglePos({ "one": builder.buildValue({"XPlacement": 500}), "two": builder.buildValue({"XPlacement": 500}), "three": builder.buildValue({"XPlacement": 200}), "four": builder.buildValue({"XPlacement": 400}), "five": builder.buildValue({"XPlacement": 500}), "six": builder.buildValue({"YPlacement": -6}), }, self.GLYPHMAP) self.assertEqual(''.join([getXML(t.toXML) for t in subtables]), '<SinglePos Format="1">' ' <Coverage>' ' <Glyph value="one"/>' ' <Glyph value="two"/>' ' <Glyph value="five"/>' ' </Coverage>' ' <ValueFormat value="1"/>' ' <Value XPlacement="500"/>' '</SinglePos>' '<SinglePos Format="2">' ' <Coverage>' ' <Glyph value="three"/>' ' <Glyph value="four"/>' ' </Coverage>' ' <ValueFormat value="1"/>' ' <!-- ValueCount=2 -->' ' <Value index="0" XPlacement="200"/>' ' <Value index="1" XPlacement="400"/>' '</SinglePos>' '<SinglePos Format="1">' ' <Coverage>' ' <Glyph value="six"/>' ' </Coverage>' ' <ValueFormat value="2"/>' ' <Value YPlacement="-6"/>' '</SinglePos>')
def test_buildValue(self): value = builder.buildValue({"XPlacement": 7, "YPlacement": 23}) func = lambda writer, font: value.toXML(writer, font, valueName="Val") self.assertEqual(getXML(func), '<Val XPlacement="7" YPlacement="23"/>')
def test_buildValue(self): value = builder.buildValue({"XPlacement": 7, "YPlacement": 23}) func = lambda writer, font: value.toXML(writer, font, valueName="Val") assert getXML(func) == ['<Val XPlacement="7" YPlacement="23"/>']